Updated compiler error messages and Generic type object, minor name changes

This commit is contained in:
Mattia Giambirtone 2022-10-11 09:56:55 +02:00
parent 9ef80535f3
commit c168d1584b
1 changed files with 43 additions and 44 deletions

View File

@ -69,7 +69,7 @@ type
of Reference, Pointer:
value: Type
of Generic:
node: IdentExpr
cond: Expression
else:
discard
@ -207,8 +207,9 @@ proc declaration(self: Compiler, node: Declaration)
proc peek(self: Compiler, distance: int = 0): ASTNode
proc identifier(self: Compiler, node: IdentExpr)
proc varDecl(self: Compiler, node: VarDecl)
proc inferType(self: Compiler, node: LiteralExpr): Type
proc inferType(self: Compiler, node: Expression): Type
proc matchImpl(self: Compiler, name: string, kind: Type): Name
proc infer(self: Compiler, node: LiteralExpr): Type
proc infer(self: Compiler, node: Expression): Type
proc findByName(self: Compiler, name: string): seq[Name]
proc findByType(self: Compiler, name: string, kind: Type, depth: int = -1): seq[Name]
proc compareTypes(self: Compiler, a, b: Type): bool
@ -618,7 +619,7 @@ proc toIntrinsic(name: string): Type =
return nil
proc inferType(self: Compiler, node: LiteralExpr): Type =
proc infer(self: Compiler, node: LiteralExpr): Type =
## Infers the type of a given literal expression
if node.isNil():
return nil
@ -660,10 +661,8 @@ proc inferType(self: Compiler, node: LiteralExpr): Type =
else:
discard # TODO
proc matchImpl(self: Compiler, name: string, kind: Type): Name
proc inferType(self: Compiler, node: Expression): Type =
proc infer(self: Compiler, node: Expression): Type =
## Infers the type of a given expression and
## returns it
if node.isNil():
@ -678,22 +677,22 @@ proc inferType(self: Compiler, node: Expression): Type =
result = node.name.lexeme.toIntrinsic()
of unaryExpr:
let node = UnaryExpr(node)
return self.matchImpl(node.operator.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: @[("", self.inferType(node.a))])).valueType.returnType
return self.matchImpl(node.operator.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: @[("", self.infer(node.a))])).valueType.returnType
of binaryExpr:
let node = BinaryExpr(node)
return self.matchImpl(node.operator.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: @[("", self.inferType(node.a)), ("", self.inferType(node.b))])).valueType.returnType
return self.matchImpl(node.operator.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: @[("", self.infer(node.a)), ("", self.infer(node.b))])).valueType.returnType
of {intExpr, hexExpr, binExpr, octExpr,
strExpr, falseExpr, trueExpr, infExpr,
nanExpr, floatExpr, nilExpr
}:
return self.inferType(LiteralExpr(node))
return self.infer(LiteralExpr(node))
of lambdaExpr:
var node = LambdaExpr(node)
result = Type(kind: Function, returnType: nil, args: @[], isLambda: true)
if not node.returnType.isNil():
result.returnType = self.inferType(node.returnType)
result.returnType = self.infer(node.returnType)
for argument in node.arguments:
result.args.add((argument.name.token.lexeme, self.inferType(argument.valueType)))
result.args.add((argument.name.token.lexeme, self.infer(argument.valueType)))
of callExpr:
var node = CallExpr(node)
case node.callee.kind:
@ -704,27 +703,27 @@ proc inferType(self: Compiler, node: Expression): Type =
else:
result = nil
of lambdaExpr:
result = self.inferType(LambdaExpr(node.callee).returnType)
result = self.infer(LambdaExpr(node.callee).returnType)
of callExpr:
result = self.inferType(CallExpr(node.callee))
result = self.infer(CallExpr(node.callee))
if not result.isNil():
result = result.returnType
else:
discard # Unreachable
of varExpr:
result = self.inferType(Var(node).value)
result = self.infer(Var(node).value)
result.mutable = true
of refExpr:
result = Type(kind: Reference, value: self.inferType(Ref(node).value))
result = Type(kind: Reference, value: self.infer(Ref(node).value))
of ptrExpr:
result = Type(kind: Pointer, value: self.inferType(Ptr(node).value))
result = Type(kind: Pointer, value: self.infer(Ptr(node).value))
of groupingExpr:
result = self.inferType(GroupingExpr(node).expression)
result = self.infer(GroupingExpr(node).expression)
else:
discard # Unreachable
proc inferType(self: Compiler, node: Declaration, strictMutable: bool = true): Type =
proc infer(self: Compiler, node: Declaration, strictMutable: bool = true): Type =
## Infers the type of a given declaration
## and returns it
if node.isNil():
@ -741,7 +740,7 @@ proc inferType(self: Compiler, node: Declaration, strictMutable: bool = true): T
if not resolved.isNil():
return resolved.valueType
else:
return self.inferType(node.value, strictMutable)
return self.infer(node.value, strictMutable)
else:
return # Unreachable
@ -774,7 +773,7 @@ proc typeToStr(self: Compiler, typ: Type): string =
if not typ.returnType.isNil():
result &= &": {self.typeToStr(typ.returnType)}"
of Generic:
result = typ.node.name.lexeme
result = &"T: {typ.cond}"
else:
discard
@ -816,7 +815,7 @@ proc matchImpl(self: Compiler, name: string, kind: Type): Name =
var msg = &"cannot find a suitable implementation for '{name}'"
let names = self.findByName(name)
if names.len() > 0:
msg &= &", found {len(names)} candidate"
msg &= &", found {len(names)} potential candidate"
if names.len() > 1:
msg &= "s"
msg &= ": "
@ -838,7 +837,7 @@ proc matchImpl(self: Compiler, name: string, kind: Type): Name =
elif impl.len() > 1:
var msg = &"multiple matching implementations of '{name}' found:\n"
for fn in reversed(impl):
msg &= &"- '{fn.name.token.lexeme}' in '{fn.owner}' at line {fn.line} of type {self.typeToStr(fn.valueType)}\n"
msg &= &"- '{fn.name.token.lexeme}' in module '{fn.owner}' at line {fn.line} of type {self.typeToStr(fn.valueType)}\n"
self.error(msg)
return impl[0]
@ -847,7 +846,7 @@ proc check(self: Compiler, term: Expression, kind: Type) =
## Checks the type of term against a known type.
## Raises an error if appropriate and returns
## otherwise
let k = self.inferType(term)
let k = self.infer(term)
if k.isNil():
if term.kind == identExpr:
self.error(&"reference to undeclared name '{term.token.lexeme}'", term)
@ -1154,7 +1153,7 @@ proc declareName(self: Compiler, node: Declaration, mutable: bool = false) =
isPrivate: node.isPrivate,
owner: self.currentModule,
isConst: node.isConst,
valueType: self.inferType(node.value),
valueType: self.infer(node.value),
codePos: self.chunk.code.len(),
isLet: node.isLet,
line: node.token.line,
@ -1172,7 +1171,7 @@ proc declareName(self: Compiler, node: Declaration, mutable: bool = false) =
isConst: false,
owner: self.currentModule,
line: node.token.line,
valueType: Type(kind: Generic, mutable: false, node: gen.name),
valueType: Type(kind: Generic, mutable: false, cond: gen.cond),
name: gen.name))
self.names.add(Name(depth: self.scopeDepth,
isPrivate: node.isPrivate,
@ -1180,7 +1179,7 @@ proc declareName(self: Compiler, node: Declaration, mutable: bool = false) =
owner: self.currentModule,
valueType: Type(kind: Function,
name: node.name.token.lexeme,
returnType: self.inferType(node.returnType),
returnType: self.infer(node.returnType),
args: @[],
fun: node,
children: @[]),
@ -1211,7 +1210,7 @@ proc declareName(self: Compiler, node: Declaration, mutable: bool = false) =
belongsTo: fn
)
self.names.add(name)
name.valueType = self.inferType(argument.valueType)
name.valueType = self.infer(argument.valueType)
# If it's still nil, it's an error!
if name.valueType.isNil():
self.error(&"cannot determine the type of argument '{argument.name.token.lexeme}'", argument.name)
@ -1291,7 +1290,7 @@ proc fixGenericFunc(self: Compiler, name: Name, args: seq[Expression]): Name =
var typ: Type
for i in 0..args.high():
if fn.valueType.args[i].kind.kind == Generic:
typ = self.inferType(args[i])
typ = self.infer(args[i])
fn.valueType.args[i].kind = typ
self.resolve(fn.valueType.args[i].name).valueType = typ
if fn.valueType.args[i].kind.isNil():
@ -1381,7 +1380,7 @@ proc literal(self: Compiler, node: ASTNode) =
self.emitConstant(LiteralExpr(node), Type(kind: String))
of intExpr:
let y = IntExpr(node)
let kind = self.inferType(y)
let kind = self.infer(y)
if kind.kind in [Int64, Int32, Int16, Int8]:
var x: int
try:
@ -1407,7 +1406,7 @@ proc literal(self: Compiler, node: ASTNode) =
stop: y.token.pos.start + len($x))
)
)
self.emitConstant(node, self.inferType(y))
self.emitConstant(node, self.infer(y))
of binExpr:
var x: int
var y = BinExpr(node)
@ -1420,7 +1419,7 @@ proc literal(self: Compiler, node: ASTNode) =
stop: y.token.pos.start + len($x))
)
)
self.emitConstant(node, self.inferType(y))
self.emitConstant(node, self.infer(y))
of octExpr:
var x: int
var y = OctExpr(node)
@ -1433,7 +1432,7 @@ proc literal(self: Compiler, node: ASTNode) =
stop: y.token.pos.start + len($x))
)
)
self.emitConstant(node, self.inferType(y))
self.emitConstant(node, self.infer(y))
of floatExpr:
var x: float
var y = FloatExpr(node)
@ -1441,7 +1440,7 @@ proc literal(self: Compiler, node: ASTNode) =
discard parseFloat(y.literal.lexeme, x)
except ValueError:
self.error("floating point value out of range")
self.emitConstant(y, self.inferType(y))
self.emitConstant(y, self.infer(y))
of awaitExpr:
var y = AwaitExpr(node)
self.expression(y.expression)
@ -1463,15 +1462,15 @@ proc callBinaryOp(self: Compiler, fn: Name, op: BinaryExpr) =
proc unary(self: Compiler, node: UnaryExpr) =
## Compiles unary expressions such as decimal
## and bitwise negation
let valueType = self.inferType(node.a)
let valueType = self.infer(node.a)
let funct = self.matchImpl(node.token.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: @[("", valueType)]))
self.callUnaryOp(funct, node)
proc binary(self: Compiler, node: BinaryExpr) =
## Compiles all binary expressions
let typeOfA = self.inferType(node.a)
let typeOfB = self.inferType(node.b)
let typeOfA = self.infer(node.a)
let typeOfB = self.infer(node.b)
let funct = self.matchImpl(node.token.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: @[("", typeOfA), ("", typeOfB)]))
self.callBinaryOp(funct, node)
@ -1484,7 +1483,7 @@ proc identifier(self: Compiler, node: IdentExpr) =
elif s.isConst:
# Constants are always emitted as Load* instructions
# no matter the scope depth
self.emitConstant(node, self.inferType(node))
self.emitConstant(node, self.infer(node))
else:
if s.valueType.kind == Function and s.isFunDecl:
# Functions have no runtime
@ -1556,7 +1555,7 @@ proc assignment(self: Compiler, node: ASTNode) =
self.emitBytes(self.getClosurePos(r).toTriple(), node.token.line)
of setItemExpr:
let node = SetItemExpr(node)
let typ = self.inferType(node)
let typ = self.infer(node)
if typ.isNil():
self.error(&"cannot determine the type of '{node.name.token.lexeme}'")
# TODO
@ -1611,7 +1610,7 @@ proc callExpr(self: Compiler, node: CallExpr): Name {.discardable.} =
self.error(&"cannot make sure that call is side-effect free")
# TODO: Keyword arguments
for i, argument in node.arguments.positionals:
kind = self.inferType(argument)
kind = self.infer(argument)
if kind.isNil():
if argument.kind == identExpr:
self.error(&"reference to undeclared name '{IdentExpr(argument).name.lexeme}'")
@ -1646,7 +1645,7 @@ proc callExpr(self: Compiler, node: CallExpr): Name {.discardable.} =
discard # TODO: Lambdas
# TODO: Calling lambdas on-the-fly (i.e. on the same line)
else:
let typ = self.inferType(node)
let typ = self.infer(node)
if typ.isNil():
self.error(&"expression has no type")
else:
@ -1799,7 +1798,7 @@ proc statement(self: Compiler, node: Statement) =
case node.kind:
of exprStmt:
let expression = ExprStmt(node).expression
let kind = self.inferType(expression)
let kind = self.infer(expression)
self.expression(expression)
if kind.isNil():
# The expression has no type and produces no value,
@ -1880,8 +1879,8 @@ proc statement(self: Compiler, node: Statement) =
proc varDecl(self: Compiler, node: VarDecl) =
## Compiles variable declarations
let expected = self.inferType(node.valueType)
let actual = self.inferType(node.value)
let expected = self.infer(node.valueType)
let actual = self.infer(node.value)
if expected.isNil() and actual.isNil():
if node.value.kind == identExpr or node.value.kind == callExpr and CallExpr(node.value).callee.kind == identExpr:
var name = node.value.token.lexeme