package wacc import cats.data.NonEmptyList object microWacc { import wacc.types._ sealed trait CallTarget(val retTy: SemType) sealed trait Expr(val ty: SemType) sealed trait LValue extends Expr // 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 NullLiter()(ty: SemType) extends Expr(ty) case class Ident(name: String, uid: Int)(identTy: SemType) extends Expr(identTy) with CallTarget(identTy) with LValue case class ArrayElem(value: LValue, 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 } object BinaryOperator { def fromAst(op: ast.BinaryOp): BinaryOperator = op match { case _: ast.Add => Add case _: ast.Sub => Sub case _: ast.Mul => Mul case _: ast.Div => Div case _: ast.Mod => Mod case _: ast.Greater => Greater case _: ast.GreaterEq => GreaterEq case _: ast.Less => Less case _: ast.LessEq => LessEq case _: ast.Eq => Eq case _: ast.Neq => Neq case _: ast.And => And case _: ast.Or => Or } } // Statements sealed trait Stmt object Builtin { case object ReadInt extends CallTarget(KnownType.Int) case object ReadChar extends CallTarget(KnownType.Char) case object Print extends CallTarget(?) case object Println extends CallTarget(?) case object Exit extends CallTarget(?) case object Free extends CallTarget(?) } 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 with Expr(target.retTy) 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]) }