From dbeae16dc4086490613201cc654309f46092629a Mon Sep 17 00:00:00 2001 From: Mattia Giambirtone Date: Tue, 24 May 2022 10:23:34 +0200 Subject: [PATCH] Various fixes to matchImpl. Variables can now shadow functions, but not other variables --- src/frontend/compiler.nim | 32 ++++++++++++++++++++++---------- src/tests.pn | 7 +++++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index 4b5c846..c0cfd74 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -574,7 +574,9 @@ proc inferType(self: Compiler, node: Expression): Type = if name != nil: return name.valueType else: - return node.name.lexeme.toIntrinsic() + result = node.name.lexeme.toIntrinsic() + if result != nil: + result.node = node of unaryExpr: return self.inferType(UnaryExpr(node).a) of binaryExpr: @@ -608,14 +610,14 @@ proc typeToStr(self: Compiler, typ: Type): string = of funDecl: var node = FunDecl(typ.node) for i, argument in node.arguments: - result &= &"{argument.name.token.lexeme}: {self.typeToStr(self.inferType(argument.name))}" + result &= &"{argument.name.token.lexeme}: {self.typeToStr(self.inferType(argument.valueType))}" if i < node.arguments.len() - 1: result &= ", " result &= ")" of lambdaExpr: var node = LambdaExpr(typ.node) for i, argument in node.arguments: - result &= &"{argument.name.token.lexeme}: {argument.valueType}" + result &= &"{argument.name.token.lexeme}: {self.typeToStr(self.inferType(argument.name))}" if i < node.arguments.len() - 1: result &= ", " result &= ")" @@ -735,16 +737,25 @@ proc matchImpl(self: Compiler, name: string, kind: Type): Name = ## Tries to find a matching function implementation ## compatible with the given type and returns its ## name object - let impl = self.findByType(name, kind) if impl.len() == 0: var msg = &"cannot find a suitable implementation for '{name}'" let names = self.findByName(name) if names.len() > 0: - msg &= &", found {len(names)} candidates:" + msg &= &", found {len(names)} candidate" + if names.len() > 1: + msg &= "s" + msg &= ": " for name in names: - echo name[] - msg &= &"- '{name.name.token.lexeme}' of type {self.typeToStr(name.valueType)}\n" + msg &= &"\n - '{name.name.token.lexeme}' of type '{self.typeToStr(name.valueType)}'" + if name.valueType.kind != Function: + msg &= ", not a callable" + elif kind.args.len() != name.valueType.args.len(): + msg &= &", wrong number of arguments ({name.valueType.args.len()} expected, got {kind.args.len()})\n" + else: + for i, arg in kind.args: + if not self.compareTypes(arg, name.valueType.args[i]): + msg &= &", first mismatch at position {i + 1}: expected argument of type '{self.typeToStr(name.valueType.args[i])}', got '{self.typeToStr(arg)}' instead" self.error(msg) elif impl.len() > 1: var msg = &"multiple matching implementations of '{name}' found:\n" @@ -752,6 +763,7 @@ proc matchImpl(self: Compiler, name: string, kind: Type): Name = var node = FunDecl(fn.valueType.node) msg &= &"- '{node.name.token.lexeme}' at line {node.token.line} of type {self.typeToStr(fn.valueType)}\n" self.error(msg) + return impl[0] proc callUnaryOp(self: Compiler, fn: Name, op: UnaryExpr) = @@ -839,7 +851,7 @@ proc declareName(self: Compiler, node: Declaration) = # slap myself 100 times with a sign saying "I'm dumb". Mark my words self.error("cannot declare more than 16777216 variables at a time") for name in self.findByName(node.name.token.lexeme): - if name.name.token.lexeme == node.name.token.lexeme: + if name.name.token.lexeme == node.name.token.lexeme and name.depth == self.scopeDepth and name.valueType.node.kind == varDecl: self.error(&"attempt to redeclare '{node.name.token.lexeme}', which was previously defined in '{name.owner}' at line {name.valueType.node.token.line}") self.names.add(Name(depth: self.scopeDepth, name: node.name, @@ -1276,11 +1288,11 @@ proc statement(self: Compiler, node: Statement) = proc varDecl(self: Compiler, node: VarDecl) = ## Compiles variable declarations - let kind = self.toIntrinsic(node.valueType) + 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}'") - elif typ != kind and kind != nil: + 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)}'") self.expression(node.value) self.declareName(node) diff --git a/src/tests.pn b/src/tests.pn index 0ea5253..07d7f74 100644 --- a/src/tests.pn +++ b/src/tests.pn @@ -2,4 +2,11 @@ operator `+`(a: int): int { return a; } +operator `+`(a: int32): int32 { + return a; +} + +var `+`: int = 1; # hehehehe + +1; # Works: defined for int64 ++1'u8; # Nope!