From 49ebf2f7d0345d7df41bd7f47295a99fbda3fac4 Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 31 Jan 2025 17:54:30 +0000 Subject: [PATCH 01/11] feat: initial ast implementation --- src/main/wacc/ast.scala | 165 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/main/wacc/ast.scala diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala new file mode 100644 index 0000000..3093fcf --- /dev/null +++ b/src/main/wacc/ast.scala @@ -0,0 +1,165 @@ +package wacc + +import parsley.generic._ + +// TODO - Note that I have opted for object Add extends ParserBridge2[Expr5, Expr6, Add] instead of object Add extends ParserBridge2[Expr5, Expr6, Expr5] +// Reason: Better type safety / pattern matching ? We can change this at any time. +// For consistency in case objects you may see I extended the parser bridge pattern with ".type" +// Personally I am not a fan + +// TODO - Obviously layout issues, could follow Haskell interlude style + +object ast { + + // Expressions + sealed trait Expr + 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 + + case class IntLiter(v: Int) extends Expr6 + object IntLiter extends ParserBridge1[Int, IntLiter] + + case class BoolLiter(v: Boolean) extends Expr6 + object BoolLiter extends ParserBridge1[Boolean, BoolLiter] + + case class CharLiter(v: Char) extends Expr6 + object CharLiter extends ParserBridge1[Char, CharLiter] + + case class StrLiter(v: String) extends Expr6 + object StrLiter extends ParserBridge1[String, StrLiter] + + case object PairLiter extends Expr6 with ParserBridge0[PairLiter.type] + + // TODO: with LValue questionable (see LValue BNF) + case class Ident(v: String) extends Expr6 with LValue + object Ident extends ParserBridge1[String, Ident] + + case class ArrayElem(name: String, indices: List[Expr]) + extends Expr6 + with LValue + object ArrayElem extends ParserBridge2[String, List[Expr], ArrayElem] + + case class UnaryOper(op: UnaryOperator, expr: Expr6) extends Expr6 + object UnaryOper extends ParserBridge2[UnaryOperator, Expr6, UnaryOper] + + // R values + sealed trait RValue + + case class ArrayLiter(elems: List[Expr]) extends Expr6 with RValue + object ArrayLiter extends ParserBridge1[List[Expr], ArrayLiter] + + case class NewPair(fst: Expr, snd: Expr) extends Expr6 with RValue + object NewPair extends ParserBridge2[Expr, Expr, NewPair] + + case class Call(name: String, args: List[Expr]) extends Expr6 with RValue + object Call extends ParserBridge2[String, List[Expr], Call] + + // Operators + sealed trait UnaryOperator + case object Negate extends UnaryOperator with ParserBridge0[Negate.type] + case object Not extends UnaryOperator with ParserBridge0[Not.type] + case object Len extends UnaryOperator with ParserBridge0[Len.type] + case object Ord extends UnaryOperator with ParserBridge0[Ord.type] + case object Chr extends UnaryOperator with ParserBridge0[Chr.type] + + sealed trait BinaryOperator + case class Add(x: Expr5, y: Expr6) extends Expr5 + object Add extends ParserBridge2[Expr5, Expr6, Add] + case class Sub(x: Expr5, y: Expr6) extends Expr5 + object Sub extends ParserBridge2[Expr5, Expr6, Sub] + case class Mul(x: Expr6, y: Expr6) extends Expr6 + object Mul extends ParserBridge2[Expr6, Expr6, Mul] + case class Div(x: Expr6, y: Expr6) extends Expr6 + object Div extends ParserBridge2[Expr6, Expr6, Div] + case class Mod(x: Expr6, y: Expr6) extends Expr6 + object Mod extends ParserBridge2[Expr6, Expr6, Mod] + case class Greater(x: Expr4, y: Expr4) extends Expr3 + object Greater extends ParserBridge2[Expr4, Expr4, Greater] + case class GreaterEq(x: Expr4, y: Expr4) extends Expr3 + object GreaterEq extends ParserBridge2[Expr4, Expr4, GreaterEq] + case class Less(x: Expr4, y: Expr4) extends Expr3 + object Less extends ParserBridge2[Expr4, Expr4, Less] + case class LessEq(x: Expr4, y: Expr4) extends Expr3 + object LessEq extends ParserBridge2[Expr4, Expr4, LessEq] + case class Eq(x: Expr4, y: Expr4) extends Expr3 + object Eq extends ParserBridge2[Expr4, Expr4, Eq] + case class Neq(x: Expr4, y: Expr4) extends Expr3 + object Neq extends ParserBridge2[Expr4, Expr4, Neq] + case class And(x: Expr2, y: Expr2) extends Expr2 + object And extends ParserBridge2[Expr2, Expr2, And] + case class Or(x: Expr1, y: Expr1) extends Expr1 + object Or extends ParserBridge2[Expr1, Expr1, Or] + + // Statements + sealed trait Stmt + case object Skip extends Stmt with ParserBridge0[Skip.type] + case class VarDecl(varType: Type, name: String, expr: Expr) extends Stmt + object VarDecl extends ParserBridge3[Type, String, Expr, VarDecl] + case class Assign(lhs: LValue, expr: Expr) extends Stmt + object Assign extends ParserBridge2[LValue, Expr, Assign] + case class Read(lhs: LValue) extends Stmt + object Read extends ParserBridge1[LValue, Read] + case class Free(expr: Expr) extends Stmt + object Free extends ParserBridge1[Expr, Free] + case class Return(expr: Expr) extends Stmt + object Return extends ParserBridge1[Expr, Return] + case class Exit(expr: Expr) extends Stmt + object Exit extends ParserBridge1[Expr, Exit] + case class Print(expr: Expr, newline: Boolean) extends Stmt + object Print extends ParserBridge2[Expr, Boolean, Print] + case class If(cond: Expr, thenStmt: Stmt, elseStmt: Stmt) extends Stmt + object If extends ParserBridge3[Expr, Stmt, Stmt, If] + case class While(cond: Expr, body: Stmt) extends Stmt + object While extends ParserBridge2[Expr, Stmt, While] + case class SeqStmt(stmt1: Stmt, stmt2: Stmt) extends Stmt + object SeqStmt extends ParserBridge2[Stmt, Stmt, SeqStmt] + + // LValues + sealed trait LValue + + // Pair Elements + sealed trait PairElem extends LValue + case class Fst(elem: LValue) extends PairElem + object Fst extends ParserBridge1[LValue, Fst] + case class Snd(elem: LValue) extends PairElem + object Snd extends ParserBridge1[LValue, Snd] + + // Function Defns + case class FuncDecl( + returnType: Type, + name: String, + params: List[Param], + body: Stmt + ) + object FuncDecl + extends ParserBridge4[Type, String, List[Param], Stmt, FuncDecl] + + case class Param(paramType: Type, name: String) + object Param extends ParserBridge2[Type, String, Param] + + // waccadoodledo + case class Program(funcs: List[FuncDecl], main: Stmt) + object Program extends ParserBridge2[List[FuncDecl], Stmt, Program] + + // Types + sealed trait Type + case object IntType extends Type with ParserBridge0[IntType.type] + case object BoolType extends Type with ParserBridge0[BoolType.type] + case object CharType extends Type with ParserBridge0[CharType.type] + case object StringType extends Type with ParserBridge0[StringType.type] + case class ArrayType(elemType: Type) extends Type + object ArrayType extends ParserBridge1[Type, ArrayType] + case class PairType(fst: PairElemType, snd: PairElemType) extends Type + object PairType extends ParserBridge2[PairElemType, PairElemType, PairType] + + sealed trait PairElemType + case object PairBaseType + extends PairElemType + with ParserBridge0[PairBaseType.type] + case class PairArrayType(baseType: Type) extends PairElemType + object PairArrayType extends ParserBridge1[Type, PairArrayType] +} From c0cf3692fd89cc4532f77cd567c47fe7d7033336 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 31 Jan 2025 19:27:22 +0000 Subject: [PATCH 02/11] fix: unary and binary operators AST - consistent style, precedence and associativity --- src/main/wacc/ast.scala | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index 3093fcf..16d983c 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -43,9 +43,6 @@ object ast { with LValue object ArrayElem extends ParserBridge2[String, List[Expr], ArrayElem] - case class UnaryOper(op: UnaryOperator, expr: Expr6) extends Expr6 - object UnaryOper extends ParserBridge2[UnaryOperator, Expr6, UnaryOper] - // R values sealed trait RValue @@ -58,24 +55,28 @@ object ast { case class Call(name: String, args: List[Expr]) extends Expr6 with RValue object Call extends ParserBridge2[String, List[Expr], Call] - // Operators - sealed trait UnaryOperator - case object Negate extends UnaryOperator with ParserBridge0[Negate.type] - case object Not extends UnaryOperator with ParserBridge0[Not.type] - case object Len extends UnaryOperator with ParserBridge0[Len.type] - case object Ord extends UnaryOperator with ParserBridge0[Ord.type] - case object Chr extends UnaryOperator with ParserBridge0[Chr.type] + // Unary operators + case class Negate(x: Expr6) extends Expr6 + object Negate extends ParserBridge1[Expr6, Negate] + case class Not(x: Expr6) extends Expr6 + object Not extends ParserBridge1[Expr6, Not] + case class Len(x: Expr6) extends Expr6 + object Len extends ParserBridge1[Expr6, Len] + case class Ord(x: Expr6) extends Expr6 + object Ord extends ParserBridge1[Expr6, Ord] + case class Chr(x: Expr6) extends Expr6 + object Chr extends ParserBridge1[Expr6, Chr] - sealed trait BinaryOperator - case class Add(x: Expr5, y: Expr6) extends Expr5 + // Binary operators + case class Add(x: Expr5, y: Expr6) extends Expr4 object Add extends ParserBridge2[Expr5, Expr6, Add] - case class Sub(x: Expr5, y: Expr6) extends Expr5 + case class Sub(x: Expr5, y: Expr6) extends Expr4 object Sub extends ParserBridge2[Expr5, Expr6, Sub] - case class Mul(x: Expr6, y: Expr6) extends Expr6 + case class Mul(x: Expr6, y: Expr6) extends Expr5 object Mul extends ParserBridge2[Expr6, Expr6, Mul] - case class Div(x: Expr6, y: Expr6) extends Expr6 + case class Div(x: Expr6, y: Expr6) extends Expr5 object Div extends ParserBridge2[Expr6, Expr6, Div] - case class Mod(x: Expr6, y: Expr6) extends Expr6 + case class Mod(x: Expr6, y: Expr6) extends Expr5 object Mod extends ParserBridge2[Expr6, Expr6, Mod] case class Greater(x: Expr4, y: Expr4) extends Expr3 object Greater extends ParserBridge2[Expr4, Expr4, Greater] @@ -85,13 +86,13 @@ object ast { object Less extends ParserBridge2[Expr4, Expr4, Less] case class LessEq(x: Expr4, y: Expr4) extends Expr3 object LessEq extends ParserBridge2[Expr4, Expr4, LessEq] - case class Eq(x: Expr4, y: Expr4) extends Expr3 - object Eq extends ParserBridge2[Expr4, Expr4, Eq] - case class Neq(x: Expr4, y: Expr4) extends Expr3 - object Neq extends ParserBridge2[Expr4, Expr4, Neq] - case class And(x: Expr2, y: Expr2) extends Expr2 + case class Eq(x: Expr3, y: Expr3) extends Expr2 + object Eq extends ParserBridge2[Expr3, Expr3, Eq] + case class Neq(x: Expr3, y: Expr3) extends Expr2 + object Neq extends ParserBridge2[Expr3, Expr3, Neq] + case class And(x: Expr2, y: Expr2) extends Expr1 object And extends ParserBridge2[Expr2, Expr2, And] - case class Or(x: Expr1, y: Expr1) extends Expr1 + case class Or(x: Expr1, y: Expr1) extends Expr object Or extends ParserBridge2[Expr1, Expr1, Or] // Statements From 50a07cf5d434a6eebeeb7314976acec57cbd3839 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 31 Jan 2025 19:29:59 +0000 Subject: [PATCH 03/11] feat: add Parens AST node --- src/main/wacc/ast.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index 16d983c..b46c9c5 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -20,6 +20,9 @@ object ast { sealed trait Expr5 extends Expr4 sealed trait Expr6 extends Expr5 + case class Parens(expr: Expr) extends Expr6 + object Parens extends ParserBridge1[Expr, Parens] + case class IntLiter(v: Int) extends Expr6 object IntLiter extends ParserBridge1[Int, IntLiter] From f4d0ef8e706d2dacceef12b43e168ba49b431bdc Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 31 Jan 2025 19:34:13 +0000 Subject: [PATCH 04/11] fix: replace String with Ident where applicable --- src/main/wacc/ast.scala | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index b46c9c5..04d888b 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -37,14 +37,13 @@ object ast { case object PairLiter extends Expr6 with ParserBridge0[PairLiter.type] - // TODO: with LValue questionable (see LValue BNF) case class Ident(v: String) extends Expr6 with LValue object Ident extends ParserBridge1[String, Ident] - case class ArrayElem(name: String, indices: List[Expr]) + case class ArrayElem(name: Ident, indices: List[Expr]) extends Expr6 with LValue - object ArrayElem extends ParserBridge2[String, List[Expr], ArrayElem] + object ArrayElem extends ParserBridge2[Ident, List[Expr], ArrayElem] // R values sealed trait RValue @@ -55,8 +54,8 @@ object ast { case class NewPair(fst: Expr, snd: Expr) extends Expr6 with RValue object NewPair extends ParserBridge2[Expr, Expr, NewPair] - case class Call(name: String, args: List[Expr]) extends Expr6 with RValue - object Call extends ParserBridge2[String, List[Expr], Call] + case class Call(name: Ident, args: List[Expr]) extends Expr6 with RValue + object Call extends ParserBridge2[Ident, List[Expr], Call] // Unary operators case class Negate(x: Expr6) extends Expr6 @@ -101,8 +100,8 @@ object ast { // Statements sealed trait Stmt case object Skip extends Stmt with ParserBridge0[Skip.type] - case class VarDecl(varType: Type, name: String, expr: Expr) extends Stmt - object VarDecl extends ParserBridge3[Type, String, Expr, VarDecl] + case class VarDecl(varType: Type, name: Ident, expr: Expr) extends Stmt + object VarDecl extends ParserBridge3[Type, Ident, Expr, VarDecl] case class Assign(lhs: LValue, expr: Expr) extends Stmt object Assign extends ParserBridge2[LValue, Expr, Assign] case class Read(lhs: LValue) extends Stmt @@ -135,15 +134,15 @@ object ast { // Function Defns case class FuncDecl( returnType: Type, - name: String, + name: Ident, params: List[Param], body: Stmt ) object FuncDecl - extends ParserBridge4[Type, String, List[Param], Stmt, FuncDecl] + extends ParserBridge4[Type, Ident, List[Param], Stmt, FuncDecl] - case class Param(paramType: Type, name: String) - object Param extends ParserBridge2[Type, String, Param] + case class Param(paramType: Type, name: Ident) + object Param extends ParserBridge2[Type, Ident, Param] // waccadoodledo case class Program(funcs: List[FuncDecl], main: Stmt) From 373683b592ce4946193ccdeac4f85446029b6ea0 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 31 Jan 2025 19:42:10 +0000 Subject: [PATCH 05/11] fix: correct usage of RValue (add to Expr, VarDecl, Assign, PairElem) --- src/main/wacc/ast.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index 04d888b..6a86abf 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -12,7 +12,7 @@ import parsley.generic._ object ast { // Expressions - sealed trait Expr + sealed trait Expr extends RValue sealed trait Expr1 extends Expr sealed trait Expr2 extends Expr1 sealed trait Expr3 extends Expr2 @@ -48,13 +48,13 @@ object ast { // R values sealed trait RValue - case class ArrayLiter(elems: List[Expr]) extends Expr6 with RValue + case class ArrayLiter(elems: List[Expr]) extends RValue object ArrayLiter extends ParserBridge1[List[Expr], ArrayLiter] - case class NewPair(fst: Expr, snd: Expr) extends Expr6 with RValue + case class NewPair(fst: Expr, snd: Expr) extends RValue object NewPair extends ParserBridge2[Expr, Expr, NewPair] - case class Call(name: Ident, args: List[Expr]) extends Expr6 with RValue + case class Call(name: Ident, args: List[Expr]) extends RValue object Call extends ParserBridge2[Ident, List[Expr], Call] // Unary operators @@ -100,10 +100,10 @@ object ast { // Statements sealed trait Stmt case object Skip extends Stmt with ParserBridge0[Skip.type] - case class VarDecl(varType: Type, name: Ident, expr: Expr) extends Stmt - object VarDecl extends ParserBridge3[Type, Ident, Expr, VarDecl] - case class Assign(lhs: LValue, expr: Expr) extends Stmt - object Assign extends ParserBridge2[LValue, Expr, Assign] + case class VarDecl(varType: Type, name: Ident, value: RValue) extends Stmt + object VarDecl extends ParserBridge3[Type, Ident, RValue, VarDecl] + case class Assign(lhs: LValue, value: RValue) extends Stmt + object Assign extends ParserBridge2[LValue, RValue, Assign] case class Read(lhs: LValue) extends Stmt object Read extends ParserBridge1[LValue, Read] case class Free(expr: Expr) extends Stmt @@ -125,7 +125,7 @@ object ast { sealed trait LValue // Pair Elements - sealed trait PairElem extends LValue + sealed trait PairElem extends LValue with RValue case class Fst(elem: LValue) extends PairElem object Fst extends ParserBridge1[LValue, Fst] case class Snd(elem: LValue) extends PairElem From 1c0907f61097ee4ec7c412cc1b8a3de5cf339a83 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 31 Jan 2025 19:45:52 +0000 Subject: [PATCH 06/11] fix: add BaseType and correct PairElemType nodes --- src/main/wacc/ast.scala | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index 6a86abf..1e85989 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -150,19 +150,18 @@ object ast { // Types sealed trait Type - case object IntType extends Type with ParserBridge0[IntType.type] - case object BoolType extends Type with ParserBridge0[BoolType.type] - case object CharType extends Type with ParserBridge0[CharType.type] - case object StringType extends Type with ParserBridge0[StringType.type] - case class ArrayType(elemType: Type) extends Type + sealed trait BaseType extends Type with PairElemType + case object IntType extends BaseType with ParserBridge0[IntType.type] + case object BoolType extends BaseType with ParserBridge0[BoolType.type] + case object CharType extends BaseType with ParserBridge0[CharType.type] + case object StringType extends BaseType with ParserBridge0[StringType.type] + case class ArrayType(elemType: Type) extends Type with PairElemType object ArrayType extends ParserBridge1[Type, ArrayType] case class PairType(fst: PairElemType, snd: PairElemType) extends Type object PairType extends ParserBridge2[PairElemType, PairElemType, PairType] sealed trait PairElemType - case object PairBaseType + case object UntypedPairType extends PairElemType - with ParserBridge0[PairBaseType.type] - case class PairArrayType(baseType: Type) extends PairElemType - object PairArrayType extends ParserBridge1[Type, PairArrayType] + with ParserBridge0[UntypedPairType.type] } From 292551aca0b290c7457e4b97723753ad7d0f9e90 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 31 Jan 2025 20:01:44 +0000 Subject: [PATCH 07/11] refactor: format AST to follow BNF order --- src/main/wacc/ast.scala | 110 ++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 65 deletions(-) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index 1e85989..8538e81 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -2,15 +2,7 @@ package wacc import parsley.generic._ -// TODO - Note that I have opted for object Add extends ParserBridge2[Expr5, Expr6, Add] instead of object Add extends ParserBridge2[Expr5, Expr6, Expr5] -// Reason: Better type safety / pattern matching ? We can change this at any time. -// For consistency in case objects you may see I extended the parser bridge pattern with ".type" -// Personally I am not a fan - -// TODO - Obviously layout issues, could follow Haskell interlude style - object ast { - // Expressions sealed trait Expr extends RValue sealed trait Expr1 extends Expr @@ -20,42 +12,24 @@ object ast { sealed trait Expr5 extends Expr4 sealed trait Expr6 extends Expr5 - case class Parens(expr: Expr) extends Expr6 - object Parens extends ParserBridge1[Expr, Parens] - + // Atoms case class IntLiter(v: Int) extends Expr6 object IntLiter extends ParserBridge1[Int, IntLiter] - case class BoolLiter(v: Boolean) extends Expr6 object BoolLiter extends ParserBridge1[Boolean, BoolLiter] - case class CharLiter(v: Char) extends Expr6 object CharLiter extends ParserBridge1[Char, CharLiter] - case class StrLiter(v: String) extends Expr6 object StrLiter extends ParserBridge1[String, StrLiter] - case object PairLiter extends Expr6 with ParserBridge0[PairLiter.type] - case class Ident(v: String) extends Expr6 with LValue object Ident extends ParserBridge1[String, Ident] - case class ArrayElem(name: Ident, indices: List[Expr]) extends Expr6 with LValue object ArrayElem extends ParserBridge2[Ident, List[Expr], ArrayElem] - - // R values - sealed trait RValue - - case class ArrayLiter(elems: List[Expr]) extends RValue - object ArrayLiter extends ParserBridge1[List[Expr], ArrayLiter] - - case class NewPair(fst: Expr, snd: Expr) extends RValue - object NewPair extends ParserBridge2[Expr, Expr, NewPair] - - case class Call(name: Ident, args: List[Expr]) extends RValue - object Call extends ParserBridge2[Ident, List[Expr], Call] + case class Parens(expr: Expr) extends Expr6 + object Parens extends ParserBridge1[Expr, Parens] // Unary operators case class Negate(x: Expr6) extends Expr6 @@ -97,6 +71,40 @@ object ast { case class Or(x: Expr1, y: Expr1) extends Expr object Or extends ParserBridge2[Expr1, Expr1, Or] + // Types + sealed trait Type + sealed trait BaseType extends Type with PairElemType + case object IntType extends BaseType with ParserBridge0[IntType.type] + case object BoolType extends BaseType with ParserBridge0[BoolType.type] + case object CharType extends BaseType with ParserBridge0[CharType.type] + case object StringType extends BaseType with ParserBridge0[StringType.type] + case class ArrayType(elemType: Type) extends Type with PairElemType + object ArrayType extends ParserBridge1[Type, ArrayType] + case class PairType(fst: PairElemType, snd: PairElemType) extends Type + object PairType extends ParserBridge2[PairElemType, PairElemType, PairType] + + sealed trait PairElemType + case object UntypedPairType + extends PairElemType + with ParserBridge0[UntypedPairType.type] + + // waccadoodledo + case class Program(funcs: List[FuncDecl], main: Stmt) + object Program extends ParserBridge2[List[FuncDecl], Stmt, Program] + + // Function Definitions + case class FuncDecl( + returnType: Type, + name: Ident, + params: List[Param], + body: Stmt + ) + object FuncDecl + extends ParserBridge4[Type, Ident, List[Param], Stmt, FuncDecl] + + case class Param(paramType: Type, name: Ident) + object Param extends ParserBridge2[Type, Ident, Param] + // Statements sealed trait Stmt case object Skip extends Stmt with ParserBridge0[Skip.type] @@ -121,47 +129,19 @@ object ast { case class SeqStmt(stmt1: Stmt, stmt2: Stmt) extends Stmt object SeqStmt extends ParserBridge2[Stmt, Stmt, SeqStmt] - // LValues sealed trait LValue - // Pair Elements + sealed trait RValue + case class ArrayLiter(elems: List[Expr]) extends RValue + object ArrayLiter extends ParserBridge1[List[Expr], ArrayLiter] + case class NewPair(fst: Expr, snd: Expr) extends RValue + object NewPair extends ParserBridge2[Expr, Expr, NewPair] + case class Call(name: Ident, args: List[Expr]) extends RValue + object Call extends ParserBridge2[Ident, List[Expr], Call] + sealed trait PairElem extends LValue with RValue case class Fst(elem: LValue) extends PairElem object Fst extends ParserBridge1[LValue, Fst] case class Snd(elem: LValue) extends PairElem object Snd extends ParserBridge1[LValue, Snd] - - // Function Defns - case class FuncDecl( - returnType: Type, - name: Ident, - params: List[Param], - body: Stmt - ) - object FuncDecl - extends ParserBridge4[Type, Ident, List[Param], Stmt, FuncDecl] - - case class Param(paramType: Type, name: Ident) - object Param extends ParserBridge2[Type, Ident, Param] - - // waccadoodledo - case class Program(funcs: List[FuncDecl], main: Stmt) - object Program extends ParserBridge2[List[FuncDecl], Stmt, Program] - - // Types - sealed trait Type - sealed trait BaseType extends Type with PairElemType - case object IntType extends BaseType with ParserBridge0[IntType.type] - case object BoolType extends BaseType with ParserBridge0[BoolType.type] - case object CharType extends BaseType with ParserBridge0[CharType.type] - case object StringType extends BaseType with ParserBridge0[StringType.type] - case class ArrayType(elemType: Type) extends Type with PairElemType - object ArrayType extends ParserBridge1[Type, ArrayType] - case class PairType(fst: PairElemType, snd: PairElemType) extends Type - object PairType extends ParserBridge2[PairElemType, PairElemType, PairType] - - sealed trait PairElemType - case object UntypedPairType - extends PairElemType - with ParserBridge0[UntypedPairType.type] } From af919742a06905383fa0b1860185cbd41a1a3511 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 31 Jan 2025 20:39:45 +0000 Subject: [PATCH 08/11] fix: fully fix binary operators associativity --- src/main/wacc/ast.scala | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index 8538e81..6166d4b 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -44,16 +44,16 @@ object ast { object Chr extends ParserBridge1[Expr6, Chr] // Binary operators - case class Add(x: Expr5, y: Expr6) extends Expr4 - object Add extends ParserBridge2[Expr5, Expr6, Add] - case class Sub(x: Expr5, y: Expr6) extends Expr4 - object Sub extends ParserBridge2[Expr5, Expr6, Sub] - case class Mul(x: Expr6, y: Expr6) extends Expr5 - object Mul extends ParserBridge2[Expr6, Expr6, Mul] - case class Div(x: Expr6, y: Expr6) extends Expr5 - object Div extends ParserBridge2[Expr6, Expr6, Div] - case class Mod(x: Expr6, y: Expr6) extends Expr5 - object Mod extends ParserBridge2[Expr6, Expr6, Mod] + case class Add(x: Expr4, y: Expr5) extends Expr4 + object Add extends ParserBridge2[Expr4, Expr5, Add] + case class Sub(x: Expr4, y: Expr5) extends Expr4 + object Sub extends ParserBridge2[Expr4, Expr5, Sub] + case class Mul(x: Expr5, y: Expr6) extends Expr5 + object Mul extends ParserBridge2[Expr5, Expr6, Mul] + case class Div(x: Expr5, y: Expr6) extends Expr5 + object Div extends ParserBridge2[Expr5, Expr6, Div] + case class Mod(x: Expr5, y: Expr6) extends Expr5 + object Mod extends ParserBridge2[Expr5, Expr6, Mod] case class Greater(x: Expr4, y: Expr4) extends Expr3 object Greater extends ParserBridge2[Expr4, Expr4, Greater] case class GreaterEq(x: Expr4, y: Expr4) extends Expr3 @@ -66,10 +66,10 @@ object ast { object Eq extends ParserBridge2[Expr3, Expr3, Eq] case class Neq(x: Expr3, y: Expr3) extends Expr2 object Neq extends ParserBridge2[Expr3, Expr3, Neq] - case class And(x: Expr2, y: Expr2) extends Expr1 - object And extends ParserBridge2[Expr2, Expr2, And] - case class Or(x: Expr1, y: Expr1) extends Expr - object Or extends ParserBridge2[Expr1, Expr1, Or] + case class And(x: Expr2, y: Expr1) extends Expr1 + object And extends ParserBridge2[Expr2, Expr1, And] + case class Or(x: Expr1, y: Expr) extends Expr + object Or extends ParserBridge2[Expr1, Expr, Or] // Types sealed trait Type From cc97118e76310a3d3cd61f9457da3440c0141a7e Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 31 Jan 2025 21:57:06 +0000 Subject: [PATCH 09/11] fix: add explicit Block statement (required for scoping) --- src/main/wacc/ast.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index 6166d4b..59fb9fa 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -126,6 +126,8 @@ object ast { object If extends ParserBridge3[Expr, Stmt, Stmt, If] case class While(cond: Expr, body: Stmt) extends Stmt object While extends ParserBridge2[Expr, Stmt, While] + case class Block(stmt: Stmt) extends Stmt + object Block extends ParserBridge1[Stmt, Block] case class SeqStmt(stmt1: Stmt, stmt2: Stmt) extends Stmt object SeqStmt extends ParserBridge2[Stmt, Stmt, SeqStmt] From 5361373c017b72fe086b7c673687ba51ab40d536 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Sat, 1 Feb 2025 17:15:14 +0000 Subject: [PATCH 10/11] refactor: non-recursive statements and array types --- src/main/wacc/ast.scala | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index 59fb9fa..4af5b1d 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -78,8 +78,10 @@ object ast { case object BoolType extends BaseType with ParserBridge0[BoolType.type] case object CharType extends BaseType with ParserBridge0[CharType.type] case object StringType extends BaseType with ParserBridge0[StringType.type] - case class ArrayType(elemType: Type) extends Type with PairElemType - object ArrayType extends ParserBridge1[Type, ArrayType] + case class ArrayType(elemType: Type, dimensions: Int) + extends Type + with PairElemType + object ArrayType extends ParserBridge2[Type, Int, ArrayType] case class PairType(fst: PairElemType, snd: PairElemType) extends Type object PairType extends ParserBridge2[PairElemType, PairElemType, PairType] @@ -89,18 +91,18 @@ object ast { with ParserBridge0[UntypedPairType.type] // waccadoodledo - case class Program(funcs: List[FuncDecl], main: Stmt) - object Program extends ParserBridge2[List[FuncDecl], Stmt, Program] + case class Program(funcs: List[FuncDecl], main: List[Stmt]) + object Program extends ParserBridge2[List[FuncDecl], List[Stmt], Program] // Function Definitions case class FuncDecl( returnType: Type, name: Ident, params: List[Param], - body: Stmt + body: List[Stmt] ) object FuncDecl - extends ParserBridge4[Type, Ident, List[Param], Stmt, FuncDecl] + extends ParserBridge4[Type, Ident, List[Param], List[Stmt], FuncDecl] case class Param(paramType: Type, name: Ident) object Param extends ParserBridge2[Type, Ident, Param] @@ -122,14 +124,13 @@ object ast { object Exit extends ParserBridge1[Expr, Exit] case class Print(expr: Expr, newline: Boolean) extends Stmt object Print extends ParserBridge2[Expr, Boolean, Print] - case class If(cond: Expr, thenStmt: Stmt, elseStmt: Stmt) extends Stmt - object If extends ParserBridge3[Expr, Stmt, Stmt, If] - case class While(cond: Expr, body: Stmt) extends Stmt - object While extends ParserBridge2[Expr, Stmt, While] - case class Block(stmt: Stmt) extends Stmt - object Block extends ParserBridge1[Stmt, Block] - case class SeqStmt(stmt1: Stmt, stmt2: Stmt) extends Stmt - object SeqStmt extends ParserBridge2[Stmt, Stmt, SeqStmt] + case class If(cond: Expr, thenStmt: List[Stmt], elseStmt: List[Stmt]) + extends Stmt + object If extends ParserBridge3[Expr, List[Stmt], List[Stmt], If] + case class While(cond: Expr, body: List[Stmt]) extends Stmt + object While extends ParserBridge2[Expr, List[Stmt], While] + case class Block(stmt: List[Stmt]) extends Stmt + object Block extends ParserBridge1[List[Stmt], Block] sealed trait LValue From 1d78072c22478e96447319bca99e71f37ff51351 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Sat, 1 Feb 2025 20:39:56 +0000 Subject: [PATCH 11/11] feat: use NoneEmptyList from cats to enfroce non-empty statements --- project.scala | 1 + src/main/wacc/ast.scala | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/project.scala b/project.scala index 7a42a9c..e6fb151 100644 --- a/project.scala +++ b/project.scala @@ -3,6 +3,7 @@ // dependencies //> using dep com.github.j-mie6::parsley::5.0.0-M10 +//> using dep com.github.j-mie6::parsley-cats::1.3.0 //> using dep com.lihaoyi::os-lib::0.11.3 //> using dep com.github.scopt::scopt::4.1.0 //> using test.dep org.scalatest::scalatest::3.2.19 diff --git a/src/main/wacc/ast.scala b/src/main/wacc/ast.scala index d5c2cca..c6e743e 100644 --- a/src/main/wacc/ast.scala +++ b/src/main/wacc/ast.scala @@ -1,6 +1,7 @@ package wacc import parsley.generic._ +import cats.data.NonEmptyList object ast { // Expressions @@ -24,8 +25,8 @@ object ast { case object PairLiter extends Expr6 with ParserBridge0[PairLiter.type] case class Ident(v: String) extends Expr6 with LValue object Ident extends ParserBridge1[String, Ident] - case class ArrayElem(name: Ident, indices: List[Expr]) extends Expr6 with LValue - object ArrayElem extends ParserBridge2[Ident, List[Expr], ArrayElem] + case class ArrayElem(name: Ident, indices: NonEmptyList[Expr]) extends Expr6 with LValue + object ArrayElem extends ParserBridge2[Ident, NonEmptyList[Expr], ArrayElem] case class Parens(expr: Expr) extends Expr6 object Parens extends ParserBridge1[Expr, Parens] @@ -85,17 +86,17 @@ object ast { case object UntypedPairType extends PairElemType with ParserBridge0[UntypedPairType.type] // waccadoodledo - case class Program(funcs: List[FuncDecl], main: List[Stmt]) - object Program extends ParserBridge2[List[FuncDecl], List[Stmt], Program] + case class Program(funcs: List[FuncDecl], main: NonEmptyList[Stmt]) + object Program extends ParserBridge2[List[FuncDecl], NonEmptyList[Stmt], Program] // Function Definitions case class FuncDecl( returnType: Type, name: Ident, params: List[Param], - body: List[Stmt] + body: NonEmptyList[Stmt] ) - object FuncDecl extends ParserBridge4[Type, Ident, List[Param], List[Stmt], FuncDecl] + object FuncDecl extends ParserBridge4[Type, Ident, List[Param], NonEmptyList[Stmt], FuncDecl] case class Param(paramType: Type, name: Ident) object Param extends ParserBridge2[Type, Ident, Param] @@ -117,12 +118,12 @@ object ast { object Exit extends ParserBridge1[Expr, Exit] case class Print(expr: Expr, newline: Boolean) extends Stmt object Print extends ParserBridge2[Expr, Boolean, Print] - case class If(cond: Expr, thenStmt: List[Stmt], elseStmt: List[Stmt]) extends Stmt - object If extends ParserBridge3[Expr, List[Stmt], List[Stmt], If] - case class While(cond: Expr, body: List[Stmt]) extends Stmt - object While extends ParserBridge2[Expr, List[Stmt], While] - case class Block(stmt: List[Stmt]) extends Stmt - object Block extends ParserBridge1[List[Stmt], Block] + case class If(cond: Expr, thenStmt: NonEmptyList[Stmt], elseStmt: NonEmptyList[Stmt]) extends Stmt + object If extends ParserBridge3[Expr, NonEmptyList[Stmt], NonEmptyList[Stmt], If] + case class While(cond: Expr, body: NonEmptyList[Stmt]) extends Stmt + object While extends ParserBridge2[Expr, NonEmptyList[Stmt], While] + case class Block(stmt: NonEmptyList[Stmt]) extends Stmt + object Block extends ParserBridge1[NonEmptyList[Stmt], Block] sealed trait LValue