fix: fix merge breaks, add function names to scope before renaming bodies

This commit is contained in:
Gleb Koval 2025-02-05 20:41:49 +00:00 committed by Barf-Vader
parent ae9625b586
commit 74f62ea933
4 changed files with 35 additions and 34 deletions

View File

@ -34,7 +34,7 @@ def compile(contents: String): Int = {
parser.parse(contents) match { parser.parse(contents) match {
case Success(ast) => case Success(ast) =>
given errors: mutable.Builder[Error, List[Error]] = List.newBuilder given errors: mutable.Builder[Error, List[Error]] = List.newBuilder
val names = renamer.rename(ast) renamer.rename(ast)
// given ctx: types.TypeCheckerCtx[List[Error]] = // given ctx: types.TypeCheckerCtx[List[Error]] =
// types.TypeCheckerCtx(names, errors) // types.TypeCheckerCtx(names, errors)
// types.check(ast) // types.check(ast)

View File

@ -27,10 +27,10 @@ object ast {
case class StrLiter(v: String)(pos: Position) extends Expr6 case class StrLiter(v: String)(pos: Position) extends Expr6
object StrLiter extends ParserBridgePos1[String, StrLiter] object StrLiter extends ParserBridgePos1[String, StrLiter]
case class PairLiter()(pos: Position) extends Expr6 case class PairLiter()(pos: Position) extends Expr6
object PairLiter extends Expr6 with ParserBridgePos0[PairLiter] object PairLiter extends ParserBridgePos0[PairLiter]
case class Ident(v: String, var uid: Int = -1) extends Expr6 with LValue case class Ident(v: String, var uid: Int = -1)(pos: Position) extends Expr6 with LValue
object Ident extends ParserBridgePos1[String, Ident] { object Ident extends ParserBridgePos1[String, Ident] {
def apply(x1: String): Ident = new Ident(x1) def apply(v: String)(pos: Position): Ident = new Ident(v)(pos)
} }
case class ArrayElem(name: Ident, indices: NonEmptyList[Expr])(pos: Position) case class ArrayElem(name: Ident, indices: NonEmptyList[Expr])(pos: Position)
extends Expr6 extends Expr6
@ -46,18 +46,15 @@ object ast {
sealed trait UnaryOp extends Expr { sealed trait UnaryOp extends Expr {
val x: Expr val x: Expr
} }
sealed trait UnaryOp extends Expr { case class Negate(x: Expr6)(pos: Position) extends Expr6 with UnaryOp
val x: Expr
}
case class Negate(x: Expr6)(pos: Position) extends Expr6 with UnaryOp with UnaryOp
object Negate extends ParserBridgePos1[Expr6, Negate] object Negate extends ParserBridgePos1[Expr6, Negate]
case class Not(x: Expr6)(pos: Position) extends Expr6 with UnaryOp with UnaryOp case class Not(x: Expr6)(pos: Position) extends Expr6 with UnaryOp
object Not extends ParserBridgePos1[Expr6, Not] object Not extends ParserBridgePos1[Expr6, Not]
case class Len(x: Expr6)(pos: Position) extends Expr6 with UnaryOp with UnaryOp case class Len(x: Expr6)(pos: Position) extends Expr6 with UnaryOp
object Len extends ParserBridgePos1[Expr6, Len] object Len extends ParserBridgePos1[Expr6, Len]
case class Ord(x: Expr6)(pos: Position) extends Expr6 with UnaryOp with UnaryOp case class Ord(x: Expr6)(pos: Position) extends Expr6 with UnaryOp
object Ord extends ParserBridgePos1[Expr6, Ord] object Ord extends ParserBridgePos1[Expr6, Ord]
case class Chr(x: Expr6)(pos: Position) extends Expr6 with UnaryOp with UnaryOp case class Chr(x: Expr6)(pos: Position) extends Expr6 with UnaryOp
object Chr extends ParserBridgePos1[Expr6, Chr] object Chr extends ParserBridgePos1[Expr6, Chr]
// Binary operators // Binary operators

View File

@ -41,30 +41,34 @@ object renamer {
): Map[Ident, SemType] = ): Map[Ident, SemType] =
given globalNames: mutable.Map[Ident, SemType] = mutable.Map.empty given globalNames: mutable.Map[Ident, SemType] = mutable.Map.empty
given globalNumbering: mutable.Map[String, Int] = mutable.Map.empty given globalNumbering: mutable.Map[String, Int] = mutable.Map.empty
rename(Scope(mutable.Map.empty, Map.empty))(prog) val scope = Scope(mutable.Map.empty, Map.empty)
val Program(funcs, main) = prog
funcs
.map { case FuncDecl(retType, name, params, body) =>
val paramTypes = params.map { param =>
val paramType = SemType(param.paramType)
paramType
}
scope.add(KnownType.Func(SemType(retType), paramTypes), name, IdentType.Func)
(params zip paramTypes, body)
}
.foreach { case (params, body) =>
val functionScope = scope.subscope
params.foreach { case (param, paramType) =>
functionScope.add(paramType, param.name, IdentType.Var)
}
body.toList.foreach(rename(functionScope.subscope)) // body can shadow function params
}
main.toList.foreach(rename(scope))
globalNames.toMap globalNames.toMap
private def rename(scope: Scope)( private def rename(scope: Scope)(
node: Program | FuncDecl | Ident | Stmt | LValue | RValue node: Ident | Stmt | LValue | RValue
)(using )(using
globalNames: mutable.Map[Ident, SemType], globalNames: mutable.Map[Ident, SemType],
globalNumbering: mutable.Map[String, Int], globalNumbering: mutable.Map[String, Int],
errors: mutable.Builder[Error, List[Error]] errors: mutable.Builder[Error, List[Error]]
): Unit = node match { ): Unit = node match {
case Program(funcs, main) => {
funcs.foreach(rename(scope))
main.toList.foreach(rename(scope))
}
case FuncDecl(retType, name, params, body) => {
val functionScope = scope.subscope
val paramTypes = params.map { param =>
val paramType = SemType(param.paramType)
functionScope.add(paramType, param.name, IdentType.Var)
paramType
}
scope.add(KnownType.Func(SemType(retType), paramTypes), name, IdentType.Func)
body.toList.foreach(rename(functionScope))
}
case VarDecl(synType, name, value) => { case VarDecl(synType, name, value) => {
// Order matters here. Variable isn't declared until after the value is evaluated. // Order matters here. Variable isn't declared until after the value is evaluated.
rename(scope)(value) rename(scope)(value)
@ -112,7 +116,7 @@ object renamer {
} }
// Default to variables. Only `call` uses IdentType.Func. // Default to variables. Only `call` uses IdentType.Func.
case id: Ident => renameIdent(scope, id, IdentType.Var) case id: Ident => renameIdent(scope, id, IdentType.Var)
case IntLiter(_) | BoolLiter(_) | CharLiter(_) | StrLiter(_) | PairLiter | Skip => () case IntLiter(_) | BoolLiter(_) | CharLiter(_) | StrLiter(_) | PairLiter() | Skip() => ()
} }
private def renameIdent(scope: Scope, ident: Ident, identType: IdentType)(using private def renameIdent(scope: Scope, ident: Ident, identType: IdentType)(using

View File

@ -17,14 +17,14 @@ object types {
object SemType { object SemType {
def apply(synType: Type | PairElemType): KnownType = synType match { def apply(synType: Type | PairElemType): KnownType = synType match {
case IntType => KnownType.Int case IntType() => KnownType.Int
case BoolType => KnownType.Bool case BoolType() => KnownType.Bool
case CharType => KnownType.Char case CharType() => KnownType.Char
case StringType => KnownType.String case StringType() => KnownType.String
case ArrayType(elemType, dimension) => case ArrayType(elemType, dimension) =>
(0 until dimension).foldLeft(SemType(elemType))((acc, _) => KnownType.Array(acc)) (0 until dimension).foldLeft(SemType(elemType))((acc, _) => KnownType.Array(acc))
case PairType(fst, snd) => KnownType.Pair(SemType(fst), SemType(snd)) case PairType(fst, snd) => KnownType.Pair(SemType(fst), SemType(snd))
case UntypedPairType => KnownType.Pair(?, ?) case UntypedPairType() => KnownType.Pair(?, ?)
} }
} }
} }