using System; using System.Collections.Generic; using System.Linq; namespace ABT { //public enum StmtKind { // GOTO, // LABELED, // CONT, // BREAK, // EXPR, // COMPOUND, // RETURN, // WHILE, // DO, // FOR, // SWITCH, // CASE, // DEFAULT, // IF, // IF_ELSE //} public abstract partial class Stmt { public Env Env { get; } public abstract void Accept(StmtVisitor visitor); public virtual bool IsJump { get => false; } } /// /// Goto Statement /// public sealed partial class GotoStmt : Stmt { public GotoStmt(String label) { this.Label = label; } public String Label { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => true; } /// /// Labeled Statement /// public sealed partial class LabeledStmt : Stmt { public LabeledStmt(String label, Stmt stmt) { this.Label = label; this.Stmt = stmt; } public String Label { get; } public Stmt Stmt { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => Stmt.IsJump; } /// /// Continue Statement /// public sealed partial class ContStmt : Stmt { public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => true; } /// /// Break Statement /// public sealed partial class BreakStmt : Stmt { public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => true; } /// /// Expression Statement /// public sealed partial class ExprStmt : Stmt { public ExprStmt(Option exprOpt) { this.ExprOpt = exprOpt; } public Option ExprOpt { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => false; } public sealed partial class CompoundStmt : Stmt { public CompoundStmt(List> declns, List> stmts) { this.Declns = declns; this.Stmts = stmts; } public List> Declns { get; } public List> Stmts { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => Declns.Count == 0 && Stmts.Count >= 1 && Stmts.First().Item2.IsJump; } public sealed partial class ReturnStmt : Stmt { public ReturnStmt(Option exprOpt) { this.ExprOpt = exprOpt; } public Option ExprOpt { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } } /// /// While Statement /// /// while (Cond) { /// Body /// } /// /// Cond must be of scalar Type /// // +--> start: continue: // | test Cond // | jz finish --+ // | Body | // +------- jmp start | // finish: <-------+ // public sealed partial class WhileStmt : Stmt { public WhileStmt(Expr cond, Stmt body) { if (!cond.Type.IsScalar) { throw new InvalidProgramException().Attach(cond); } this.Cond = cond; this.Body = body; } public Expr Cond { get; } public Stmt Body { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } } /// /// Do-while Stmt /// /// do { /// Body /// } while (Cond); /// /// Cond must be of scalar Type /// // +--> start: // | Body // | continue: // | test Cond // +------- jnz start // finish: public sealed partial class DoWhileStmt : Stmt { public DoWhileStmt(Stmt body, Expr cond) { this.Body = body; this.Cond = cond; } public Stmt Body { get; } public Expr Cond { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => Body.IsJump; } /// /// for (Init; Cond; Loop) { /// Body /// } /// /// Cond must be scalar /// // // Init // +--> start: // | test Cond // | jz finish --+ // | Body | // | continue: | // | Loop | // +------- jmp start | // finish: <-------+ // public sealed partial class ForStmt : Stmt { public ForStmt(Option init, Option cond, Option loop, Stmt body) { this.Init = init; this.Cond = cond; this.Loop = loop; this.Body = body; } public Option Init { get; } public Option Cond { get; } public Option Loop { get; } public Stmt Body { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } } /// /// Switch Statement /// // // cmp Cond, value1 // je case1 // cmp Cond, value2 // je case2 // ... // cmp Cond, value_n // je case_n // jmp default # if no default, then default = finish // // case1: // stmt // case2: // stmt // ... // case_n: // stmt // finish: public sealed partial class SwitchStmt : Stmt { public SwitchStmt(Expr expr, Stmt stmt) { this.Expr = expr; this.Stmt = stmt; } public Expr Expr { get; } public Stmt Stmt { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } } /// /// Case Statement /// public sealed partial class CaseStmt : Stmt { public CaseStmt(Int32 value, Stmt stmt) { this.Value = value; this.Stmt = stmt; } public Int32 Value { get; } public Stmt Stmt { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => Stmt.IsJump; } public sealed partial class DefaultStmt : Stmt { public DefaultStmt(Stmt stmt) { this.Stmt = stmt; } public Stmt Stmt { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } public override bool IsJump => Stmt.IsJump; } /// /// If Statement: if (Cond) stmt; /// If Cond is non-zero, stmt is executed. /// /// Cond must be arithmetic or pointer Type. /// // test Cond // +------- jz finish // | Body // +--> finish: public sealed partial class IfStmt : Stmt { public IfStmt(Expr cond, Stmt stmt) { this.Cond = cond; this.Stmt = stmt; } public Expr Cond { get; } public Stmt Stmt { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } } /// /// If-else Statement /// if (Cond) { /// true_stmt /// } else { /// false_stmt /// } /// /// // test Cond // +------- jz false // | true_stmt // | jmp finish --+ // +--> false: | // false_stmt | // finish: <--------+ // public sealed partial class IfElseStmt : Stmt { public IfElseStmt(Expr cond, Stmt trueStmt, Stmt falseStmt) { this.Cond = cond; this.TrueStmt = trueStmt; this.FalseStmt = falseStmt; } public Expr Cond { get; } public Stmt TrueStmt { get; } public Stmt FalseStmt { get; } public override void Accept(StmtVisitor visitor) { visitor.Visit(this); } } }