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 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)(pos: Position) extends Expr6 object IntLiter extends ParserBridgePos1[Int, IntLiter] case class BoolLiter(v: Boolean)(pos: Position) extends Expr6 object BoolLiter extends ParserBridgePos1[Boolean, BoolLiter] case class CharLiter(v: Char)(pos: Position) extends Expr6 object CharLiter extends ParserBridgePos1[Char, CharLiter] case class StrLiter(v: String)(pos: Position) extends Expr6 object StrLiter extends ParserBridgePos1[String, StrLiter] case class PairLiter()(pos: Position) extends Expr6 object PairLiter extends ParserBridgePos0[PairLiter] case class Ident(v: String, var uid: Int = -1)(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])(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)(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)(pos: Position) extends Expr6 with UnaryOp object Negate extends ParserBridgePos1[Expr6, Negate] case class Not(x: Expr6)(pos: Position) extends Expr6 with UnaryOp object Not extends ParserBridgePos1[Expr6, Not] case class Len(x: Expr6)(pos: Position) extends Expr6 with UnaryOp object Len extends ParserBridgePos1[Expr6, Len] case class Ord(x: Expr6)(pos: Position) extends Expr6 with UnaryOp object Ord extends ParserBridgePos1[Expr6, Ord] case class Chr(x: Expr6)(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)(pos: Position) extends Expr4 with BinaryOp object Add extends ParserBridgePos2[Expr4, Expr5, Add] case class Sub(x: Expr4, y: Expr5)(pos: Position) extends Expr4 with BinaryOp object Sub extends ParserBridgePos2[Expr4, Expr5, Sub] case class Mul(x: Expr5, y: Expr6)(pos: Position) extends Expr5 with BinaryOp object Mul extends ParserBridgePos2[Expr5, Expr6, Mul] case class Div(x: Expr5, y: Expr6)(pos: Position) extends Expr5 with BinaryOp object Div extends ParserBridgePos2[Expr5, Expr6, Div] case class Mod(x: Expr5, y: Expr6)(pos: Position) extends Expr5 with BinaryOp object Mod extends ParserBridgePos2[Expr5, Expr6, Mod] case class Greater(x: Expr4, y: Expr4)(pos: Position) extends Expr3 with BinaryOp object Greater extends ParserBridgePos2[Expr4, Expr4, Greater] case class GreaterEq(x: Expr4, y: Expr4)(pos: Position) extends Expr3 with BinaryOp object GreaterEq extends ParserBridgePos2[Expr4, Expr4, GreaterEq] case class Less(x: Expr4, y: Expr4)(pos: Position) extends Expr3 with BinaryOp object Less extends ParserBridgePos2[Expr4, Expr4, Less] case class LessEq(x: Expr4, y: Expr4)(pos: Position) extends Expr3 with BinaryOp object LessEq extends ParserBridgePos2[Expr4, Expr4, LessEq] case class Eq(x: Expr3, y: Expr3)(pos: Position) extends Expr2 with BinaryOp object Eq extends ParserBridgePos2[Expr3, Expr3, Eq] case class Neq(x: Expr3, y: Expr3)(pos: Position) extends Expr2 with BinaryOp object Neq extends ParserBridgePos2[Expr3, Expr3, Neq] case class And(x: Expr2, y: Expr1)(pos: Position) extends Expr1 with BinaryOp object And extends ParserBridgePos2[Expr2, Expr1, And] case class Or(x: Expr1, y: Expr)(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()(pos: Position) extends BaseType object IntType extends ParserBridgePos0[IntType] case class BoolType()(pos: Position) extends BaseType object BoolType extends ParserBridgePos0[BoolType] case class CharType()(pos: Position) extends BaseType object CharType extends ParserBridgePos0[CharType] case class StringType()(pos: Position) extends BaseType object StringType extends ParserBridgePos0[StringType] case class ArrayType(elemType: Type, dimensions: Int)(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)(pos: Position) extends Type object PairType extends ParserBridgePos2[PairElemType, PairElemType, PairType] sealed trait PairElemType case class UntypedPairType()(pos: Position) extends PairElemType object UntypedPairType extends ParserBridgePos0[UntypedPairType] // waccadoodledo case class Program(funcs: List[FuncDecl], main: NonEmptyList[Stmt])(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] )(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)(pos: Position) object Param extends ParserBridgePos2[Type, Ident, Param] // Statements sealed trait Stmt case class Skip()(pos: Position) extends Stmt object Skip extends ParserBridgePos0[Skip] case class VarDecl(varType: Type, name: Ident, value: RValue)(pos: Position) extends Stmt object VarDecl extends ParserBridgePos3[Type, Ident, RValue, VarDecl] case class Assign(lhs: LValue, value: RValue)(pos: Position) extends Stmt object Assign extends ParserBridgePos2[LValue, RValue, Assign] case class Read(lhs: LValue)(pos: Position) extends Stmt object Read extends ParserBridgePos1[LValue, Read] case class Free(expr: Expr)(pos: Position) extends Stmt object Free extends ParserBridgePos1[Expr, Free] case class Return(expr: Expr)(pos: Position) extends Stmt object Return extends ParserBridgePos1[Expr, Return] case class Exit(expr: Expr)(pos: Position) extends Stmt object Exit extends ParserBridgePos1[Expr, Exit] case class Print(expr: Expr, newline: Boolean)(pos: Position) extends Stmt object Print extends ParserBridgePos2[Expr, Boolean, Print] case class If(cond: Expr, thenStmt: NonEmptyList[Stmt], elseStmt: NonEmptyList[Stmt])( pos: Position ) extends Stmt object If extends ParserBridgePos3[Expr, NonEmptyList[Stmt], NonEmptyList[Stmt], If] case class While(cond: Expr, body: NonEmptyList[Stmt])(pos: Position) extends Stmt object While extends ParserBridgePos2[Expr, NonEmptyList[Stmt], While] case class Block(stmt: NonEmptyList[Stmt])(pos: Position) extends Stmt object Block extends ParserBridgePos1[NonEmptyList[Stmt], Block] sealed trait LValue sealed trait RValue case class ArrayLiter(elems: List[Expr])(pos: Position) extends RValue object ArrayLiter extends ParserBridgePos1[List[Expr], ArrayLiter] case class NewPair(fst: Expr, snd: Expr)(pos: Position) extends RValue object NewPair extends ParserBridgePos2[Expr, Expr, NewPair] case class Call(name: Ident, args: List[Expr])(pos: Position) extends RValue object Call extends ParserBridgePos2[Ident, List[Expr], Call] sealed trait PairElem extends LValue with RValue case class Fst(elem: LValue)(pos: Position) extends PairElem object Fst extends ParserBridgePos1[LValue, Fst] case class Snd(elem: LValue)(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)) } }