fix: fix incorrect semantic error logging by refactoring error.scala from frontend
This commit is contained in:
@@ -53,14 +53,15 @@ def frontend(
|
|||||||
|
|
||||||
if (errors.result.isEmpty) IO.pure(Right(typedProg))
|
if (errors.result.isEmpty) IO.pure(Right(typedProg))
|
||||||
else {
|
else {
|
||||||
|
given errorContent: String = contents
|
||||||
val exitCode = errors.result.view.map {
|
val exitCode = errors.result.view.map {
|
||||||
case _: Error.InternalError => 201
|
case _: Error.InternalError => 201
|
||||||
case _ => 200
|
case _ => 200
|
||||||
}.max
|
}.max
|
||||||
|
|
||||||
logger.error(s"Semantic errors:\n${errors.result.mkString("\n")}") *> IO.pure(
|
val formattedErrors = errors.result.map(formatError).mkString("\n")
|
||||||
Left(exitCode)
|
|
||||||
)
|
logger.error(s"Semantic errors:\n$formattedErrors") *> IO.pure(Left(exitCode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package wacc
|
|||||||
|
|
||||||
import wacc.ast.Position
|
import wacc.ast.Position
|
||||||
import wacc.types._
|
import wacc.types._
|
||||||
import java.io.PrintStream
|
|
||||||
|
|
||||||
/** Error types for semantic errors
|
/** Error types for semantic errors
|
||||||
*/
|
*/
|
||||||
@@ -24,71 +23,72 @@ enum Error {
|
|||||||
* @param errorContent
|
* @param errorContent
|
||||||
* Contents of the file to generate code snippets
|
* Contents of the file to generate code snippets
|
||||||
*/
|
*/
|
||||||
def printError(error: Error)(using errorContent: String, stdout: PrintStream): Unit = {
|
def formatError(error: Error)(using errorContent: String): String = {
|
||||||
stdout.println("Semantic error:")
|
val sb = new StringBuilder()
|
||||||
error match {
|
sb.append("Semantic error:\n")
|
||||||
case Error.DuplicateDeclaration(ident) =>
|
|
||||||
printPosition(ident.pos)
|
/** Function to format the position of an error
|
||||||
stdout.println(s"Duplicate declaration of identifier ${ident.v}")
|
*
|
||||||
highlight(ident.pos, ident.v.length)
|
* @param pos
|
||||||
case Error.UndeclaredVariable(ident) =>
|
* Position of the error
|
||||||
printPosition(ident.pos)
|
*/
|
||||||
stdout.println(s"Undeclared variable ${ident.v}")
|
def formatPosition(pos: Position): Unit = {
|
||||||
highlight(ident.pos, ident.v.length)
|
sb.append(s"(line ${pos.line}, column ${pos.column}):\n")
|
||||||
case Error.UndefinedFunction(ident) =>
|
|
||||||
printPosition(ident.pos)
|
|
||||||
stdout.println(s"Undefined function ${ident.v}")
|
|
||||||
highlight(ident.pos, ident.v.length)
|
|
||||||
case Error.FunctionParamsMismatch(id, expected, got, funcType) =>
|
|
||||||
printPosition(id.pos)
|
|
||||||
stdout.println(s"Function expects $expected parameters, got $got")
|
|
||||||
stdout.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)
|
|
||||||
stdout.println(s"Type mismatch: $msg\nExpected: $expected\nGot: $got")
|
|
||||||
highlight(pos, 1)
|
|
||||||
case Error.SemanticError(pos, msg) =>
|
|
||||||
printPosition(pos)
|
|
||||||
stdout.println(msg)
|
|
||||||
highlight(pos, 1)
|
|
||||||
case wacc.Error.InternalError(pos, msg) =>
|
|
||||||
printPosition(pos)
|
|
||||||
stdout.println(s"Internal error: $msg")
|
|
||||||
highlight(pos, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/** Function to highlight a section of code for an error message
|
||||||
|
|
||||||
/** Function to highlight a section of code for an error message
|
|
||||||
*
|
*
|
||||||
* @param pos
|
* @param pos
|
||||||
* Position of the error
|
* Position of the error
|
||||||
* @param size
|
* @param size
|
||||||
* Size(in chars) of section to highlight
|
* 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, stdout: PrintStream): Unit = {
|
def formatHighlight(pos: Position, size: Int): Unit = {
|
||||||
val lines = errorContent.split("\n")
|
val lines = errorContent.split("\n")
|
||||||
|
|
||||||
val preLine = if (pos.line > 1) lines(pos.line - 2) else ""
|
val preLine = if (pos.line > 1) lines(pos.line - 2) else ""
|
||||||
val midLine = lines(pos.line - 1)
|
val midLine = lines(pos.line - 1)
|
||||||
val postLine = if (pos.line < lines.size) lines(pos.line) else ""
|
val postLine = if (pos.line < lines.size) lines(pos.line) else ""
|
||||||
val linePointer = " " * (pos.column + 2) + ("^" * (size)) + "\n"
|
val linePointer = " " * (pos.column + 2) + ("^" * (size)) + "\n"
|
||||||
|
|
||||||
stdout.println(
|
sb.append(
|
||||||
s" >$preLine\n >$midLine\n$linePointer >$postLine"
|
s" >$preLine\n >$midLine\n$linePointer >$postLine\netscape"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error match {
|
||||||
|
case Error.DuplicateDeclaration(ident) =>
|
||||||
|
formatPosition(ident.pos)
|
||||||
|
sb.append(s"Duplicate declaration of identifier ${ident.v}")
|
||||||
|
formatHighlight(ident.pos, ident.v.length)
|
||||||
|
case Error.UndeclaredVariable(ident) =>
|
||||||
|
formatPosition(ident.pos)
|
||||||
|
sb.append(s"Undeclared variable ${ident.v}")
|
||||||
|
formatHighlight(ident.pos, ident.v.length)
|
||||||
|
case Error.UndefinedFunction(ident) =>
|
||||||
|
formatPosition(ident.pos)
|
||||||
|
sb.append(s"Undefined function ${ident.v}")
|
||||||
|
formatHighlight(ident.pos, ident.v.length)
|
||||||
|
case Error.FunctionParamsMismatch(id, expected, got, funcType) =>
|
||||||
|
formatPosition(id.pos)
|
||||||
|
sb.append(s"Function expects $expected parameters, got $got")
|
||||||
|
sb.append(
|
||||||
|
s"(function ${id.v} has type (${funcType.params.mkString(", ")}) -> ${funcType.returnType})"
|
||||||
|
)
|
||||||
|
formatHighlight(id.pos, 1)
|
||||||
|
case Error.TypeMismatch(pos, expected, got, msg) =>
|
||||||
|
formatPosition(pos)
|
||||||
|
sb.append(s"Type mismatch: $msg\nExpected: $expected\nGot: $got")
|
||||||
|
formatHighlight(pos, 1)
|
||||||
|
case Error.SemanticError(pos, msg) =>
|
||||||
|
formatPosition(pos)
|
||||||
|
sb.append(msg)
|
||||||
|
formatHighlight(pos, 1)
|
||||||
|
case wacc.Error.InternalError(pos, msg) =>
|
||||||
|
formatPosition(pos)
|
||||||
|
sb.append(s"Internal error: $msg")
|
||||||
|
formatHighlight(pos, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.toString()
|
||||||
|
|
||||||
/** Function to print the position of an error
|
|
||||||
*
|
|
||||||
* @param pos
|
|
||||||
* Position of the error
|
|
||||||
*/
|
|
||||||
def printPosition(pos: Position)(using stdout: PrintStream): Unit = {
|
|
||||||
stdout.println(s"(line ${pos.line}, column ${pos.column}):")
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user