diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index 24813d0..96a6709 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -16,8 +16,8 @@ import meta/ast import meta/errors import ../config import ../util/multibyte -import lexer -import parser +import lexer as l +import parser as p import tables import strformat @@ -448,6 +448,9 @@ proc compareTypes(self: Compiler, a, b: Type): bool = # since peon doesn't have return type # inference return true + elif a.kind == Generic or b.kind == Generic: + # Matching generic argument types + return true elif a.kind != b.kind: # Next, we see the type discriminant: # If they're different, then they can't @@ -801,7 +804,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}' at line {fn.line} of type {self.typeToStr(fn.valueType)}\n" + msg &= &"- '{fn.name.token.lexeme}' at line {fn.line} of type {self.typeToStr(fn.valueType)}\n" self.error(msg) return impl[0] @@ -815,8 +818,9 @@ proc emitFunction(self: Compiler, name: Name) = proc handleBuiltinFunction(self: Compiler, fn: Name, args: seq[Expression]) = ## Emits single instructions for builtin functions ## such as addition or subtraction - for argument in args: - self.expression(argument) + if fn.builtinOp notin ["GenericLogicalOr", "GenericLogicalAnd"]: + for argument in args: + self.expression(argument) case fn.builtinOp: of "AddInt64": self.emitByte(AddInt64) @@ -898,6 +902,21 @@ proc handleBuiltinFunction(self: Compiler, fn: Name, args: seq[Expression]) = self.emitByte(DivFloat32) of "MulFloat32": self.emitByte(MulFloat32) + of "GenericLogicalOr": + self.expression(args[0]) + let jump = self.emitJump(JumpIfTrue) + self.expression(args[1]) + self.patchJump(jump) + of "GenericLogicalAnd": + self.expression(args[0]) + var jump: int + if self.enableOptimizations: + jump = self.emitJump(JumpIfFalseOrPop) + else: + jump = self.emitJump(JumpIfFalse) + self.emitByte(Pop) + self.expression(args[1]) + self.patchJump(jump) else: discard # Unreachable @@ -930,7 +949,6 @@ proc generateCall(self: Compiler, fn: Name, args: seq[Expression]) = proc generateObjCall(self: Compiler, args: seq[Expression]) = ## Small wrapper that abstracts emitting a call instruction ## for a given function already loaded on the operand stack - self.emitByte(PushC) # Pops the function off the operand stack onto the call stack self.emitByte(LoadReturnAddress) let pos = self.chunk.code.len() @@ -976,30 +994,6 @@ proc binary(self: Compiler, node: BinaryExpr) = let funct = self.matchImpl(node.token.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: @[("", typeOfA), ("", typeOfB)])) self.callBinaryOp(funct, node) - # TODO: Get rid of old code - #[ - case node.operator.kind: - of NoMatch: - # a and b - self.expression(node.a) - var jump: int - if self.enableOptimizations: - jump = self.emitJump(JumpIfFalseOrPop) - else: - jump = self.emitJump(JumpIfFalse) - self.emitByte(Pop) - self.expression(node.b) - self.patchJump(jump) - of EndOfFile: - # a or b - self.expression(node.a) - let jump = self.emitJump(JumpIfTrue) - self.expression(node.b) - self.patchJump(jump) - else: - self.error(&"invalid AST node of kind {node.kind} at binary(): {node} (This is an internal error and most likely a bug!)") - ]# - proc declareName(self: Compiler, node: Declaration, mutable: bool = false) = ## Statically declares a name into the current scope. @@ -1007,7 +1001,7 @@ proc declareName(self: Compiler, node: Declaration, mutable: bool = false) = ## list of identifiers so that further calls to resolve() ## correctly return them. There is no code to actually ## declare a variable at runtime: the value is already - ## there on the stack + ## on the stack case node.kind: of NodeKind.varDecl: var node = VarDecl(node) @@ -1542,9 +1536,11 @@ proc importStmt(self: Compiler, node: ImportStmt) = ## Imports a module at compile time if self.scopeDepth > 0: self.error("import statements are only allowed at the top level") + var lexer = newLexer() + var parser = newParser() var compiler = newCompiler() # TODO: Find module - var result = compiler.compile(newParser().parse(newLexer().lex("", node.moduleName.name.lexeme), node.moduleName.name.lexeme), node.moduleName.name.lexeme) + var result = compiler.compile(parser.parse(lexer.lex("", node.moduleName.name.lexeme), node.moduleName.name.lexeme), node.moduleName.name.lexeme) proc statement(self: Compiler, node: Statement) = diff --git a/src/frontend/parser.nim b/src/frontend/parser.nim index e46003f..87c4689 100644 --- a/src/frontend/parser.nim +++ b/src/frontend/parser.nim @@ -403,29 +403,14 @@ proc call(self: Parser): Expression = result = self.makeCall(result) elif self.match(Dot): self.expect(Identifier, "expecting attribute name after '.'") - result = newGetItemExpr(result, newIdentExpr(self.peek(-1)), - self.peek(-1)) - elif self.match(LeftBracket): - # Slicing such as a[1:2], which is then - # translated to `[]`(a, 1, 2) - let tok = self.peek(-1) - var ends: seq[Expression] = @[] - while not self.check(RightBracket) and not self.done(): - if self.check(":"): - ends.add(newNilExpr(Token(lexeme: "nil"))) - discard self.step() - else: - ends.add(self.expression()) - discard self.match(":") - self.expect(RightBracket, "expecting ']'") - result = newSliceExpr(result, ends, tok) + result = newGetItemExpr(result, newIdentExpr(self.peek(-1)), self.peek(-1)) else: break ## Operator parsing handlers proc unary(self: Parser): Expression = - if self.peek().lexeme in self.operators.tokens: + if self.peek().kind == Symbol and self.peek().lexeme in self.operators.tokens: result = newUnaryExpr(self.step(), self.unary()) else: result = self.call() @@ -435,7 +420,7 @@ proc parsePow(self: Parser): Expression = result = self.unary() var operator: Token var right: Expression - while self.operators.getPrecedence(self.peek().lexeme) == Power: + while self.peek().kind == Symbol and self.operators.getPrecedence(self.peek().lexeme) == Power: operator = self.step() right = self.unary() result = newBinaryExpr(result, operator, right) @@ -445,7 +430,7 @@ proc parseMul(self: Parser): Expression = result = self.parsePow() var operator: Token var right: Expression - while self.operators.getPrecedence(self.peek().lexeme) == Multiplication: + while self.peek().kind == Symbol and self.operators.getPrecedence(self.peek().lexeme) == Multiplication: operator = self.step() right = self.parsePow() result = newBinaryExpr(result, operator, right) @@ -455,7 +440,7 @@ proc parseAdd(self: Parser): Expression = result = self.parseMul() var operator: Token var right: Expression - while self.operators.getPrecedence(self.peek().lexeme) == Addition: + while self.peek().kind == Symbol and self.operators.getPrecedence(self.peek().lexeme) == Addition: operator = self.step() right = self.parseMul() result = newBinaryExpr(result, operator, right) @@ -465,7 +450,7 @@ proc parseCmp(self: Parser): Expression = result = self.parseAdd() var operator: Token var right: Expression - while self.operators.getPrecedence(self.peek().lexeme) == Compare: + while self.peek().kind == Symbol and self.operators.getPrecedence(self.peek().lexeme) == Compare: operator = self.step() right = self.parseAdd() result = newBinaryExpr(result, operator, right) @@ -475,7 +460,7 @@ proc parseAnd(self: Parser): Expression = result = self.parseCmp() var operator: Token var right: Expression - while self.operators.getPrecedence(self.peek().lexeme) == Precedence.And: + while self.peek().kind == Symbol and self.operators.getPrecedence(self.peek().lexeme) == Precedence.And: operator = self.step() right = self.parseCmp() result = newBinaryExpr(result, operator, right) @@ -485,7 +470,7 @@ proc parseOr(self: Parser): Expression = result = self.parseAnd() var operator: Token var right: Expression - while self.operators.getPrecedence(self.peek().lexeme) == Precedence.Or: + while self.peek().kind == Symbol and self.operators.getPrecedence(self.peek().lexeme) == Precedence.Or: operator = self.step() right = self.parseAnd() result = newBinaryExpr(result, operator, right) @@ -493,7 +478,7 @@ proc parseOr(self: Parser): Expression = proc parseAssign(self: Parser): Expression = result = self.parseOr() - if self.operators.getPrecedence(self.peek().lexeme) == Assign: + if self.peek().kind == Symbol and self.operators.getPrecedence(self.peek().lexeme) == Assign: let tok = self.step() var value = self.expression() case result.kind: @@ -509,7 +494,7 @@ proc parseArrow(self: Parser): Expression = result = self.parseAssign() var operator: Token var right: Expression - while self.operators.getPrecedence(self.peek().lexeme) == Precedence.Or: + while self.peek().kind == Symbol and self.operators.getPrecedence(self.peek().lexeme) == Precedence.Or: operator = self.step() right = self.parseAssign() result = newBinaryExpr(result, operator, right)