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) trait ParserSingletonBridgePos[+A] extends ErrorBridge { protected def con(pos: (Int, Int)): A infix def from(op: Parsley[?]): Parsley[A] = error(pos.map(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)): A = apply()(Position(pos._1, pos._2)) } 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.map(con), a)) override final def con(pos: (Int, Int)): A => B = this.apply(_)(Position(pos._1, pos._2)) } 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.map(con), a, b) ) override final def con(pos: (Int, Int)): (A, B) => C = apply(_, _)(Position(pos._1, pos._2)) } 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.map(con), a, b, c) ) override final def con(pos: (Int, Int)): (A, B, C) => D = apply(_, _, _)(Position(pos._1, pos._2)) } }