mirror of
https://github.com/KarolS/millfork.git
synced 2024-11-18 22:07:07 +00:00
Improve error reporting
This commit is contained in:
parent
960cee5124
commit
1e9be50ccb
@ -61,11 +61,8 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
|
||||
val pos = stmt.position
|
||||
// generic warnings:
|
||||
stmt match {
|
||||
case ExpressionStatement(expr@FunctionCallExpression("strzlen" | "putstrz", List(TextLiteralExpression(ch)))) =>
|
||||
ch.last match {
|
||||
case LiteralExpression(0, _) => //ok
|
||||
case _ => ctx.log.warn("Passing a non-null-terminated string to a function that expects a null-terminated string.", stmt.position)
|
||||
}
|
||||
case ExpressionStatement(expr@FunctionCallExpression("strzlen" | "putstrz" | "strzcmp" | "strzcopy", params)) =>
|
||||
for (param <- params) checkIfNullTerminated(stmt, param)
|
||||
case ExpressionStatement(VariableExpression(v)) =>
|
||||
val volatile = ctx.env.maybeGet[ThingInMemory](v).fold(false)(_.isVolatile)
|
||||
if (!volatile) ctx.log.warn("Pointless expression.", stmt.position)
|
||||
@ -133,6 +130,17 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
|
||||
}
|
||||
}
|
||||
|
||||
private def checkIfNullTerminated(stmt: ExecutableStatement, param: Expression): Unit = {
|
||||
param match {
|
||||
case TextLiteralExpression(ch) =>
|
||||
ch.last match {
|
||||
case LiteralExpression(0, _) => //ok
|
||||
case _ => ctx.log.warn("Passing a non-null-terminated string to a function that expects a null-terminated string.", stmt.position)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
def search(expr: Expression, cv: VV): VV = {
|
||||
expr match {
|
||||
case FunctionCallExpression(op, List(VariableExpression(v), arg)) if op.endsWith("=") && op != "<=" && op != ">=" =>
|
||||
|
@ -613,7 +613,7 @@ object BuiltIns {
|
||||
AssemblyLine.variable(ctx, CMP, rva, 0))
|
||||
case _ =>
|
||||
// TODO comparing expressions
|
||||
ctx.log.error("Too complex expressions in comparison", lhs.position)
|
||||
ctx.log.error("Too complex expressions in comparison", lhs.position.orElse(rhs.position))
|
||||
(Nil, Nil, Nil, Nil)
|
||||
}
|
||||
val lType = MosExpressionCompiler.getExpressionType(ctx, lhs)
|
||||
|
23
src/main/scala/millfork/env/Environment.scala
vendored
23
src/main/scala/millfork/env/Environment.scala
vendored
@ -798,7 +798,26 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
case e: ExecutableStatement => Some(e)
|
||||
case _ => None
|
||||
}
|
||||
val needsExtraRTS = !stmt.isMacro && !stmt.assembly && (statements.isEmpty || !statements.last.isInstanceOf[ReturnStatement])
|
||||
val paramForAutomaticReturn: List[Option[Expression]] = if (stmt.isMacro || stmt.assembly) {
|
||||
Nil
|
||||
} else if (statements.isEmpty) {
|
||||
List(None)
|
||||
} else {
|
||||
statements.last match {
|
||||
case _: ReturnStatement => Nil
|
||||
case WhileStatement(VariableExpression(tr), _, _, _) =>
|
||||
if (resultType.size > 0 && env.getBooleanConstant(tr).contains(true)) {
|
||||
List(Some(LiteralExpression(0, 1))) // TODO: what if the loop is breakable?
|
||||
} else List(None)
|
||||
case DoWhileStatement(_, _, VariableExpression(tr), _) =>
|
||||
if (resultType.size > 0 && env.getBooleanConstant(tr).contains(true)) {
|
||||
List(Some(LiteralExpression(0, 1))) // TODO: what if the loop is breakable?
|
||||
} else List(None)
|
||||
case _ =>
|
||||
// None so the compiler warns
|
||||
List(None)
|
||||
}
|
||||
}
|
||||
if (stmt.isMacro) {
|
||||
if (stmt.bank.isDefined) {
|
||||
log.error("Macro functions cannot be in a defined segment", stmt.position)
|
||||
@ -823,7 +842,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
env,
|
||||
stackVariablesSize,
|
||||
stmt.address.map(a => this.eval(a).getOrElse(errorConstant(s"Address of `${stmt.name}` is not a constant"))),
|
||||
executableStatements ++ (if (needsExtraRTS) List(ReturnStatement(None).pos(executableStatements.lastOption.fold(stmt.position)(_.position))) else Nil),
|
||||
executableStatements ++ paramForAutomaticReturn.map(param => ReturnStatement(param).pos(executableStatements.lastOption.fold(stmt.position)(_.position))),
|
||||
interrupt = stmt.interrupt,
|
||||
kernalInterrupt = stmt.kernalInterrupt,
|
||||
reentrant = stmt.reentrant,
|
||||
|
Loading…
Reference in New Issue
Block a user