wacc_37/src/main/wacc/ast.scala
2025-02-06 20:26:15 +00:00

233 lines
10 KiB
Scala

package wacc
import parsley.Parsley
import parsley.generic.ErrorBridge
import parsley.ap._
import parsley.position._
import parsley.syntax.zipped._
import cats.data.NonEmptyList
object ast {
// Expressions
sealed trait Expr extends RValue {
val pos: Position
}
sealed trait Expr1 extends Expr
sealed trait Expr2 extends Expr1
sealed trait Expr3 extends Expr2
sealed trait Expr4 extends Expr3
sealed trait Expr5 extends Expr4
sealed trait Expr6 extends Expr5
// Atoms
case class IntLiter(v: Int)(val pos: Position) extends Expr6
object IntLiter extends ParserBridgePos1[Int, IntLiter]
case class BoolLiter(v: Boolean)(val pos: Position) extends Expr6
object BoolLiter extends ParserBridgePos1[Boolean, BoolLiter]
case class CharLiter(v: Char)(val pos: Position) extends Expr6
object CharLiter extends ParserBridgePos1[Char, CharLiter]
case class StrLiter(v: String)(val pos: Position) extends Expr6
object StrLiter extends ParserBridgePos1[String, StrLiter]
case class PairLiter()(val pos: Position) extends Expr6
object PairLiter extends ParserBridgePos0[PairLiter]
case class Ident(v: String, var uid: Int = -1)(val pos: Position) extends Expr6 with LValue
object Ident extends ParserBridgePos1[String, Ident] {
def apply(v: String)(pos: Position): Ident = new Ident(v)(pos)
}
case class ArrayElem(name: Ident, indices: NonEmptyList[Expr])(val pos: Position)
extends Expr6
with LValue
object ArrayElem extends ParserBridgePos1[NonEmptyList[Expr], Ident => ArrayElem] {
def apply(a: NonEmptyList[Expr])(pos: Position): Ident => ArrayElem =
name => ArrayElem(name, a)(pos)
}
case class Parens(expr: Expr)(val pos: Position) extends Expr6
object Parens extends ParserBridgePos1[Expr, Parens]
// Unary operators
sealed trait UnaryOp extends Expr {
val x: Expr
}
case class Negate(x: Expr6)(val pos: Position) extends Expr6 with UnaryOp
object Negate extends ParserBridgePos1[Expr6, Negate]
case class Not(x: Expr6)(val pos: Position) extends Expr6 with UnaryOp
object Not extends ParserBridgePos1[Expr6, Not]
case class Len(x: Expr6)(val pos: Position) extends Expr6 with UnaryOp
object Len extends ParserBridgePos1[Expr6, Len]
case class Ord(x: Expr6)(val pos: Position) extends Expr6 with UnaryOp
object Ord extends ParserBridgePos1[Expr6, Ord]
case class Chr(x: Expr6)(val pos: Position) extends Expr6 with UnaryOp
object Chr extends ParserBridgePos1[Expr6, Chr]
// Binary operators
sealed trait BinaryOp extends Expr {
val x: Expr
val y: Expr
}
case class Add(x: Expr4, y: Expr5)(val pos: Position) extends Expr4 with BinaryOp
object Add extends ParserBridgePos2[Expr4, Expr5, Add]
case class Sub(x: Expr4, y: Expr5)(val pos: Position) extends Expr4 with BinaryOp
object Sub extends ParserBridgePos2[Expr4, Expr5, Sub]
case class Mul(x: Expr5, y: Expr6)(val pos: Position) extends Expr5 with BinaryOp
object Mul extends ParserBridgePos2[Expr5, Expr6, Mul]
case class Div(x: Expr5, y: Expr6)(val pos: Position) extends Expr5 with BinaryOp
object Div extends ParserBridgePos2[Expr5, Expr6, Div]
case class Mod(x: Expr5, y: Expr6)(val pos: Position) extends Expr5 with BinaryOp
object Mod extends ParserBridgePos2[Expr5, Expr6, Mod]
case class Greater(x: Expr4, y: Expr4)(val pos: Position) extends Expr3 with BinaryOp
object Greater extends ParserBridgePos2[Expr4, Expr4, Greater]
case class GreaterEq(x: Expr4, y: Expr4)(val pos: Position) extends Expr3 with BinaryOp
object GreaterEq extends ParserBridgePos2[Expr4, Expr4, GreaterEq]
case class Less(x: Expr4, y: Expr4)(val pos: Position) extends Expr3 with BinaryOp
object Less extends ParserBridgePos2[Expr4, Expr4, Less]
case class LessEq(x: Expr4, y: Expr4)(val pos: Position) extends Expr3 with BinaryOp
object LessEq extends ParserBridgePos2[Expr4, Expr4, LessEq]
case class Eq(x: Expr3, y: Expr3)(val pos: Position) extends Expr2 with BinaryOp
object Eq extends ParserBridgePos2[Expr3, Expr3, Eq]
case class Neq(x: Expr3, y: Expr3)(val pos: Position) extends Expr2 with BinaryOp
object Neq extends ParserBridgePos2[Expr3, Expr3, Neq]
case class And(x: Expr2, y: Expr1)(val pos: Position) extends Expr1 with BinaryOp
object And extends ParserBridgePos2[Expr2, Expr1, And]
case class Or(x: Expr1, y: Expr)(val pos: Position) extends Expr with BinaryOp
object Or extends ParserBridgePos2[Expr1, Expr, Or]
// Types
sealed trait Type
sealed trait BaseType extends Type with PairElemType
case class IntType()(val pos: Position) extends BaseType
object IntType extends ParserBridgePos0[IntType]
case class BoolType()(val pos: Position) extends BaseType
object BoolType extends ParserBridgePos0[BoolType]
case class CharType()(val pos: Position) extends BaseType
object CharType extends ParserBridgePos0[CharType]
case class StringType()(val pos: Position) extends BaseType
object StringType extends ParserBridgePos0[StringType]
case class ArrayType(elemType: Type, dimensions: Int)(val pos: Position)
extends Type
with PairElemType
object ArrayType extends ParserBridgePos1[Int, Type => ArrayType] {
def apply(a: Int)(pos: Position): Type => ArrayType = elemType => ArrayType(elemType, a)(pos)
}
case class PairType(fst: PairElemType, snd: PairElemType)(val pos: Position) extends Type
object PairType extends ParserBridgePos2[PairElemType, PairElemType, PairType]
sealed trait PairElemType
case class UntypedPairType()(val pos: Position) extends PairElemType
object UntypedPairType extends ParserBridgePos0[UntypedPairType]
// waccadoodledo
case class Program(funcs: List[FuncDecl], main: NonEmptyList[Stmt])(val pos: Position)
object Program extends ParserBridgePos2[List[FuncDecl], NonEmptyList[Stmt], Program]
// Function Definitions
case class FuncDecl(
returnType: Type,
name: Ident,
params: List[Param],
body: NonEmptyList[Stmt]
)(val pos: Position)
object FuncDecl
extends ParserBridgePos2[
List[Param],
NonEmptyList[Stmt],
((Type, Ident)) => FuncDecl
] {
def apply(params: List[Param], body: NonEmptyList[Stmt])(
pos: Position
): ((Type, Ident)) => FuncDecl =
(returnType, name) => FuncDecl(returnType, name, params, body)(pos)
}
case class Param(paramType: Type, name: Ident)(val pos: Position)
object Param extends ParserBridgePos2[Type, Ident, Param]
// Statements
sealed trait Stmt
case class Skip()(val pos: Position) extends Stmt
object Skip extends ParserBridgePos0[Skip]
case class VarDecl(varType: Type, name: Ident, value: RValue)(val pos: Position) extends Stmt
object VarDecl extends ParserBridgePos3[Type, Ident, RValue, VarDecl]
case class Assign(lhs: LValue, value: RValue)(val pos: Position) extends Stmt
object Assign extends ParserBridgePos2[LValue, RValue, Assign]
case class Read(lhs: LValue)(val pos: Position) extends Stmt
object Read extends ParserBridgePos1[LValue, Read]
case class Free(expr: Expr)(val pos: Position) extends Stmt
object Free extends ParserBridgePos1[Expr, Free]
case class Return(expr: Expr)(val pos: Position) extends Stmt
object Return extends ParserBridgePos1[Expr, Return]
case class Exit(expr: Expr)(val pos: Position) extends Stmt
object Exit extends ParserBridgePos1[Expr, Exit]
case class Print(expr: Expr, newline: Boolean)(val pos: Position) extends Stmt
object Print extends ParserBridgePos2[Expr, Boolean, Print]
case class If(cond: Expr, thenStmt: NonEmptyList[Stmt], elseStmt: NonEmptyList[Stmt])(
val pos: Position
) extends Stmt
object If extends ParserBridgePos3[Expr, NonEmptyList[Stmt], NonEmptyList[Stmt], If]
case class While(cond: Expr, body: NonEmptyList[Stmt])(val pos: Position) extends Stmt
object While extends ParserBridgePos2[Expr, NonEmptyList[Stmt], While]
case class Block(stmt: NonEmptyList[Stmt])(val pos: Position) extends Stmt
object Block extends ParserBridgePos1[NonEmptyList[Stmt], Block]
sealed trait LValue {
val pos: Position
}
sealed trait RValue
case class ArrayLiter(elems: List[Expr])(val pos: Position) extends RValue
object ArrayLiter extends ParserBridgePos1[List[Expr], ArrayLiter]
case class NewPair(fst: Expr, snd: Expr)(val pos: Position) extends RValue
object NewPair extends ParserBridgePos2[Expr, Expr, NewPair]
case class Call(name: Ident, args: List[Expr])(val pos: Position) extends RValue
object Call extends ParserBridgePos2[Ident, List[Expr], Call]
sealed trait PairElem extends LValue with RValue
case class Fst(elem: LValue)(val pos: Position) extends PairElem
object Fst extends ParserBridgePos1[LValue, Fst]
case class Snd(elem: LValue)(val pos: Position) extends PairElem
object Snd extends ParserBridgePos1[LValue, Snd]
// Parser bridges
case class Position(line: Int, column: Int, offset: Int)
trait ParserSingletonBridgePos[+A] extends ErrorBridge {
protected def con(pos: (Int, Int), offset: Int): A
infix def from(op: Parsley[?]): Parsley[A] = error((pos, offset).zipped(con) <~ op)
final def <#(op: Parsley[?]): Parsley[A] = this from op
}
trait ParserBridgePos0[+A] extends ParserSingletonBridgePos[A] {
def apply()(pos: Position): A
override final def con(pos: (Int, Int), offset: Int): A =
apply()(Position(pos._1, pos._2, offset))
}
trait ParserBridgePos1[-A, +B] extends ParserSingletonBridgePos[A => B] {
def apply(a: A)(pos: Position): B
def apply(a: Parsley[A]): Parsley[B] = error(ap1((pos, offset).zipped(con), a))
override final def con(pos: (Int, Int), offset: Int): A => B =
this.apply(_)(Position(pos._1, pos._2, offset))
}
trait ParserBridgePos2[-A, -B, +C] extends ParserSingletonBridgePos[(A, B) => C] {
def apply(a: A, b: B)(pos: Position): C
def apply(a: Parsley[A], b: => Parsley[B]): Parsley[C] = error(
ap2((pos, offset).zipped(con), a, b)
)
override final def con(pos: (Int, Int), offset: Int): (A, B) => C =
apply(_, _)(Position(pos._1, pos._2, offset))
}
trait ParserBridgePos3[-A, -B, -C, +D] extends ParserSingletonBridgePos[(A, B, C) => D] {
def apply(a: A, b: B, c: C)(pos: Position): D
def apply(a: Parsley[A], b: => Parsley[B], c: => Parsley[C]): Parsley[D] = error(
ap3((pos, offset).zipped(con), a, b, c)
)
override final def con(pos: (Int, Int), offset: Int): (A, B, C) => D =
apply(_, _, _)(Position(pos._1, pos._2, offset))
}
}