diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index f3d1f1a..af594a6 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -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