Various fixes to matchImpl. Variables can now shadow functions, but not other variables
This commit is contained in:
parent
15f412bcac
commit
dbeae16dc4
|
@ -574,7 +574,9 @@ proc inferType(self: Compiler, node: Expression): Type =
|
||||||
if name != nil:
|
if name != nil:
|
||||||
return name.valueType
|
return name.valueType
|
||||||
else:
|
else:
|
||||||
return node.name.lexeme.toIntrinsic()
|
result = node.name.lexeme.toIntrinsic()
|
||||||
|
if result != nil:
|
||||||
|
result.node = node
|
||||||
of unaryExpr:
|
of unaryExpr:
|
||||||
return self.inferType(UnaryExpr(node).a)
|
return self.inferType(UnaryExpr(node).a)
|
||||||
of binaryExpr:
|
of binaryExpr:
|
||||||
|
@ -608,14 +610,14 @@ proc typeToStr(self: Compiler, typ: Type): string =
|
||||||
of funDecl:
|
of funDecl:
|
||||||
var node = FunDecl(typ.node)
|
var node = FunDecl(typ.node)
|
||||||
for i, argument in node.arguments:
|
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:
|
if i < node.arguments.len() - 1:
|
||||||
result &= ", "
|
result &= ", "
|
||||||
result &= ")"
|
result &= ")"
|
||||||
of lambdaExpr:
|
of lambdaExpr:
|
||||||
var node = LambdaExpr(typ.node)
|
var node = LambdaExpr(typ.node)
|
||||||
for i, argument in node.arguments:
|
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:
|
if i < node.arguments.len() - 1:
|
||||||
result &= ", "
|
result &= ", "
|
||||||
result &= ")"
|
result &= ")"
|
||||||
|
@ -735,16 +737,25 @@ proc matchImpl(self: Compiler, name: string, kind: Type): Name =
|
||||||
## Tries to find a matching function implementation
|
## Tries to find a matching function implementation
|
||||||
## compatible with the given type and returns its
|
## compatible with the given type and returns its
|
||||||
## name object
|
## name object
|
||||||
|
|
||||||
let impl = self.findByType(name, kind)
|
let impl = self.findByType(name, kind)
|
||||||
if impl.len() == 0:
|
if impl.len() == 0:
|
||||||
var msg = &"cannot find a suitable implementation for '{name}'"
|
var msg = &"cannot find a suitable implementation for '{name}'"
|
||||||
let names = self.findByName(name)
|
let names = self.findByName(name)
|
||||||
if names.len() > 0:
|
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:
|
for name in names:
|
||||||
echo name[]
|
msg &= &"\n - '{name.name.token.lexeme}' of type '{self.typeToStr(name.valueType)}'"
|
||||||
msg &= &"- '{name.name.token.lexeme}' of type {self.typeToStr(name.valueType)}\n"
|
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)
|
self.error(msg)
|
||||||
elif impl.len() > 1:
|
elif impl.len() > 1:
|
||||||
var msg = &"multiple matching implementations of '{name}' found:\n"
|
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)
|
var node = FunDecl(fn.valueType.node)
|
||||||
msg &= &"- '{node.name.token.lexeme}' at line {node.token.line} of type {self.typeToStr(fn.valueType)}\n"
|
msg &= &"- '{node.name.token.lexeme}' at line {node.token.line} of type {self.typeToStr(fn.valueType)}\n"
|
||||||
self.error(msg)
|
self.error(msg)
|
||||||
|
return impl[0]
|
||||||
|
|
||||||
|
|
||||||
proc callUnaryOp(self: Compiler, fn: Name, op: UnaryExpr) =
|
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
|
# 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")
|
self.error("cannot declare more than 16777216 variables at a time")
|
||||||
for name in self.findByName(node.name.token.lexeme):
|
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.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,
|
self.names.add(Name(depth: self.scopeDepth,
|
||||||
name: node.name,
|
name: node.name,
|
||||||
|
@ -1276,11 +1288,11 @@ proc statement(self: Compiler, node: Statement) =
|
||||||
|
|
||||||
proc varDecl(self: Compiler, node: VarDecl) =
|
proc varDecl(self: Compiler, node: VarDecl) =
|
||||||
## Compiles variable declarations
|
## Compiles variable declarations
|
||||||
let kind = self.toIntrinsic(node.valueType)
|
let kind = self.inferType(node.valueType)
|
||||||
let typ = self.inferType(node.value)
|
let typ = self.inferType(node.value)
|
||||||
if kind == nil and typ == nil:
|
if kind == nil and typ == nil:
|
||||||
self.error(&"cannot determine the type of '{node.name.token.lexeme}'")
|
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.error(&"expected value of type '{self.typeToStr(kind)}', but '{node.name.token.lexeme}' is of type '{self.typeToStr(typ)}'")
|
||||||
self.expression(node.value)
|
self.expression(node.value)
|
||||||
self.declareName(node)
|
self.declareName(node)
|
||||||
|
|
|
@ -2,4 +2,11 @@ operator `+`(a: int): int {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator `+`(a: int32): int32 {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
var `+`: int = 1; # hehehehe
|
||||||
|
|
||||||
+1; # Works: defined for int64
|
+1; # Works: defined for int64
|
||||||
|
+1'u8; # Nope!
|
||||||
|
|
Loading…
Reference in New Issue