94 lines
2.9 KiB
Scala
94 lines
2.9 KiB
Scala
package wacc
|
|
|
|
import wacc.ast.Position
|
|
import wacc.types._
|
|
|
|
/** Error types for semantic errors
|
|
*/
|
|
enum Error {
|
|
case DuplicateDeclaration(ident: ast.Ident)
|
|
case UndeclaredVariable(ident: ast.Ident)
|
|
case UndefinedFunction(ident: ast.Ident)
|
|
|
|
case FunctionParamsMismatch(ident: ast.Ident, expected: Int, got: Int, funcType: FuncType)
|
|
case SemanticError(pos: Position, msg: String)
|
|
case TypeMismatch(pos: Position, expected: SemType, got: SemType, msg: String)
|
|
case InternalError(pos: Position, msg: String)
|
|
}
|
|
|
|
/** Function to handle printing the details of a given semantic error
|
|
*
|
|
* @param error
|
|
* Error object
|
|
* @param errorContent
|
|
* Contents of the file to generate code snippets
|
|
*/
|
|
def printError(error: Error)(using errorContent: String): Unit = {
|
|
println("Semantic error:")
|
|
error match {
|
|
case Error.DuplicateDeclaration(ident) =>
|
|
printPosition(ident.pos)
|
|
println(s"Duplicate declaration of identifier ${ident.v}")
|
|
highlight(ident.pos, ident.v.length)
|
|
case Error.UndeclaredVariable(ident) =>
|
|
printPosition(ident.pos)
|
|
println(s"Undeclared variable ${ident.v}")
|
|
highlight(ident.pos, ident.v.length)
|
|
case Error.UndefinedFunction(ident) =>
|
|
printPosition(ident.pos)
|
|
println(s"Undefined function ${ident.v}")
|
|
highlight(ident.pos, ident.v.length)
|
|
case Error.FunctionParamsMismatch(id, expected, got, funcType) =>
|
|
printPosition(id.pos)
|
|
println(s"Function expects $expected parameters, got $got")
|
|
println(
|
|
s"(function ${id.v} has type (${funcType.params.mkString(", ")}) -> ${funcType.returnType})"
|
|
)
|
|
highlight(id.pos, 1)
|
|
case Error.TypeMismatch(pos, expected, got, msg) =>
|
|
printPosition(pos)
|
|
println(s"Type mismatch: $msg\nExpected: $expected\nGot: $got")
|
|
highlight(pos, 1)
|
|
case Error.SemanticError(pos, msg) =>
|
|
printPosition(pos)
|
|
println(msg)
|
|
highlight(pos, 1)
|
|
case wacc.Error.InternalError(pos, msg) =>
|
|
printPosition(pos)
|
|
println(s"Internal error: $msg")
|
|
highlight(pos, 1)
|
|
}
|
|
|
|
}
|
|
|
|
/** Function to highlight a section of code for an error message
|
|
*
|
|
* @param pos
|
|
* Position of the error
|
|
* @param size
|
|
* Size(in chars) of section to highlight
|
|
* @param errorContent
|
|
* Contents of the file to generate code snippets
|
|
*/
|
|
def highlight(pos: Position, size: Int)(using errorContent: String): Unit = {
|
|
val lines = errorContent.split("\n")
|
|
|
|
val preLine = if (pos.line > 1) lines(pos.line - 2) else ""
|
|
val midLine = lines(pos.line - 1)
|
|
val postLine = if (pos.line < lines.size) lines(pos.line) else ""
|
|
val linePointer = " " * (pos.column + 2) + ("^" * (size)) + "\n"
|
|
|
|
println(
|
|
s" >$preLine\n >$midLine\n$linePointer >$postLine"
|
|
)
|
|
}
|
|
|
|
/** Function to print the position of an error
|
|
*
|
|
* @param pos
|
|
* Position of the error
|
|
*/
|
|
def printPosition(pos: Position): Unit = {
|
|
println(s"(line ${pos.line}, column ${pos.column}):")
|
|
}
|