Updated compiler error messages and Generic type object, minor name changes
This commit is contained in:
parent
9ef80535f3
commit
c168d1584b
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue