package wacc import cats.data.NonEmptyList object microWacc { import wacc.types._ sealed trait CallTarget sealed trait Expr(val ty: SemType) sealed trait LValue // Atomic expressions case class IntLiter(v: Int) extends Expr(KnownType.Int) case class BoolLiter(v: Boolean) extends Expr(KnownType.Bool) case class CharLiter(v: Char) extends Expr(KnownType.Char) case class ArrayLiter(elems: List[Expr])(ty: SemType) extends Expr(ty) case class Ident(name: String)(identTy: SemType) extends Expr(identTy) with CallTarget with LValue case class ArrayElem(name: Ident, indices: NonEmptyList[Expr])(ty: SemType) extends Expr(ty) with LValue // Operators case class UnaryOp(x: Expr, op: UnaryOperator)(ty: SemType) extends Expr(ty) enum UnaryOperator { case Negate case Not case Len case Ord case Chr } case class BinaryOp(x: Expr, y: Expr, op: BinaryOperator)(ty: SemType) extends Expr(ty) enum BinaryOperator { case Add case Sub case Mul case Div case Mod case Greater case GreaterEq case Less case LessEq case Eq case Neq case And case Or } // Statements sealed trait Stmt enum Builtin extends CallTarget { case Read case Free case Exit case Print } case class Assign(lhs: LValue, rhs: Expr) extends Stmt case class If(cond: Expr, thenBranch: List[Stmt], elseBranch: List[Stmt]) extends Stmt case class While(cond: Expr, body: List[Stmt]) extends Stmt case class Call(target: CallTarget, args: List[Expr]) extends Stmt case class Return(expr: Expr) extends Stmt // Program case class FuncDecl(name: Ident, params: List[Ident], body: List[Stmt]) case class Program(funcs: List[FuncDecl], stmts: List[Stmt]) }