package wacc import cats.data.Chain object microWacc { import wacc.ast.Position 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, val pos: Position) 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, index: 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 { val pos: Position } case class Builtin(val name: String)(retTy: SemType) extends CallTarget(retTy) { override def toString(): String = name } object Builtin { object Read extends Builtin("read")(?) object Printf extends Builtin("printf")(?) object Exit extends Builtin("exit")(?) object Free extends Builtin("free")(?) object Malloc extends Builtin("malloc")(?) object PrintCharArray extends Builtin("printCharArray")(?) } case class Assign(lhs: LValue, rhs: Expr)(val pos: Position) extends Stmt case class If(cond: Expr, thenBranch: Chain[Stmt], elseBranch: Chain[Stmt])(val pos: Position) extends Stmt case class While(cond: Expr, body: Chain[Stmt])(val pos: Position) extends Stmt case class Call(target: CallTarget, args: List[Expr])(val pos: Position) extends Stmt with Expr(target.retTy) case class Return(expr: Expr)(val pos: Position) extends Stmt // Program case class FuncDecl(name: Ident, params: List[Ident], body: Chain[Stmt])(val pos: Position) case class Program(funcs: Chain[FuncDecl], stmts: Chain[Stmt])(val pos: Position) }