Fixed variable declarations not compiling in some cases

This commit is contained in:
Mattia Giambirtone 2022-05-25 12:15:45 +02:00
parent 990b54fa3e
commit 5bf5c6d3fd
3 changed files with 17 additions and 12 deletions

View File

@ -562,8 +562,8 @@ proc inferType(self: Compiler, node: LiteralExpr): Type =
proc toIntrinsic(self: Compiler, typ: Expression): Type =
## Gets an expression's
## intrinsic type, if possible
## Gets an expression's intrinsic type, if
## possible
if typ == nil:
return nil
case typ.kind:
@ -590,7 +590,7 @@ proc inferType(self: Compiler, node: Expression): Type =
if name != nil:
return name.valueType
else:
result = node.name.lexeme.toIntrinsic()
result = self.toIntrinsic(Expression(node))
if result != nil:
result.node = node
of unaryExpr:
@ -1307,9 +1307,10 @@ proc varDecl(self: Compiler, node: VarDecl) =
let kind = self.inferType(node.valueType)
let typ = self.inferType(node.value)
if kind == nil and typ == nil:
self.error(&"cannot determine the type of '{node.name.token.lexeme}'")
self.error(&"'{node.name.token.lexeme}' has no type")
elif not self.compareTypes(typ, kind):
self.error(&"expected value of type '{self.typeToStr(kind)}', but '{node.name.token.lexeme}' is of type '{self.typeToStr(typ)}'")
if kind != nil:
self.error(&"expected value of type '{self.typeToStr(kind)}', but '{node.name.token.lexeme}' is of type '{self.typeToStr(typ)}'")
self.expression(node.value)
self.declareName(node)
@ -1326,12 +1327,12 @@ proc funDecl(self: Compiler, node: FunDecl) =
# TODO: Forward declarations
if node.body != nil:
if BlockStmt(node.body).code.len() == 0:
self.error("Cannot declare function with empty body")
self.error("cannot declare function with empty body")
let fnType = self.inferType(node)
let impl = self.findByType(node.name.token.lexeme, fnType)
if impl.len() > 1:
# Oh-oh! We found more than one implementation of
# the same function! Error!
# the same function with the same name! Error!
var msg = &"multiple matching implementations of '{node.name.token.lexeme}' found:\n"
for fn in reversed(impl):
var node = FunDecl(fn.valueType.node)

View File

@ -799,6 +799,7 @@ proc varDecl(self: Parser, isLet: bool = false,
let isPrivate = not self.match("*")
self.checkDecl(isPrivate)
var valueType: IdentExpr
var hasInit = false
if self.match(":"):
# We don't enforce it here because
# the compiler may be able to infer
@ -806,6 +807,7 @@ proc varDecl(self: Parser, isLet: bool = false,
self.expect(Identifier, "expecting type name after ':'")
valueType = newIdentExpr(self.peek(-1))
if self.match("="):
hasInit = true
value = self.expression()
if isConst and not value.isConst():
self.error("constant initializer is not a constant")
@ -813,7 +815,7 @@ proc varDecl(self: Parser, isLet: bool = false,
if tok.kind != Var:
self.error(&"{tok.lexeme} declaration requires an initializer")
value = newNilExpr(Token(lexeme: "nil"))
self.expect(Semicolon, &"expecting semicolon after declaration")
self.expect(Semicolon, "expecting semicolon after declaration")
case tok.kind:
of Var:
result = newVarDecl(name, value, isPrivate = isPrivate, token = tok,
@ -826,6 +828,8 @@ proc varDecl(self: Parser, isLet: bool = false,
isLet = isLet, valueType = valueType, pragmas = (@[]))
else:
discard # Unreachable
if not hasInit and VarDecl(result).valueType == nil:
self.error("expecting initializer or type declaration, but neither was found")
proc parseDeclArguments(self: Parser, arguments: var seq[tuple[name: IdentExpr, valueType: Expression, mutable: bool, isRef: bool, isPtr: bool]],

View File

@ -27,10 +27,10 @@ proc fillSymbolTable(tokenizer: Lexer)
proc getLineEditor: LineEditor
# Handy dandy compile-time constants
const debugLexer = false
const debugParser = false
const debugLexer = true
const debugParser = true
const debugCompiler = true
const debugSerializer = false
const debugSerializer = true
const debugRuntime = false
when debugSerializer:
@ -106,7 +106,7 @@ proc repl =
var hashMatches = computeSHA256(input).toHex().toLowerAscii() == serialized.fileHash
styledEcho fgCyan, "Serialization step: "
styledEcho fgBlue, &"\t- File hash: ", fgYellow, serialized.fileHash, fgBlue, " (", if hashMatches: fgGreen else: fgRed, if hashMatches: "OK" else: "Fail", fgBlue, ")"
styledEcho fgBlue, "\t- Peon version: ", fgYellow, &"{serialized.peonVer.major}.{serialized.peonVer.minor}.{serialized.peonVer.patch}", fgBlue, " (commit ", fgYellow, serialized.commitHash[0..8], fgBlue, ") on branch ", fgYellow, serialized.peonBranch
styledEcho fgBlue, "\t- Peon version: ", fgYellow, &"{serialized.version.major}.{serialized.version.minor}.{serialized.version.patch}", fgBlue, " (commit ", fgYellow, serialized.commit[0..8], fgBlue, ") on branch ", fgYellow, serialized.branch
stdout.styledWriteLine(fgBlue, "\t- Compilation date & time: ", fgYellow, fromUnix(serialized.compileDate).format("d/M/yyyy HH:mm:ss"))
stdout.styledWrite(fgBlue, &"\t- Constants segment: ")
if serialized.chunk.consts == compiled.consts: