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);
}
}
}