Initial work on generics and fixed bugs in the parser with stropped operator names

This commit is contained in:
Mattia Giambirtone 2022-06-14 22:45:32 +02:00
parent 4591e5ca0e
commit e32b8e258f
2 changed files with 38 additions and 57 deletions

View File

@ -16,8 +16,8 @@ import meta/ast
import meta/errors import meta/errors
import ../config import ../config
import ../util/multibyte import ../util/multibyte
import lexer import lexer as l
import parser import parser as p
import tables import tables
import strformat import strformat
@ -448,6 +448,9 @@ proc compareTypes(self: Compiler, a, b: Type): bool =
# since peon doesn't have return type # since peon doesn't have return type
# inference # inference
return true return true
elif a.kind == Generic or b.kind == Generic:
# Matching generic argument types
return true
elif a.kind != b.kind: elif a.kind != b.kind:
# Next, we see the type discriminant: # Next, we see the type discriminant:
# If they're different, then they can't # 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: elif impl.len() > 1:
var msg = &"multiple matching implementations of '{name}' found:\n" var msg = &"multiple matching implementations of '{name}' found:\n"
for fn in reversed(impl): 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) self.error(msg)
return impl[0] return impl[0]
@ -815,8 +818,9 @@ proc emitFunction(self: Compiler, name: Name) =
proc handleBuiltinFunction(self: Compiler, fn: Name, args: seq[Expression]) = proc handleBuiltinFunction(self: Compiler, fn: Name, args: seq[Expression]) =
## Emits single instructions for builtin functions ## Emits single instructions for builtin functions
## such as addition or subtraction ## such as addition or subtraction
for argument in args: if fn.builtinOp notin ["GenericLogicalOr", "GenericLogicalAnd"]:
self.expression(argument) for argument in args:
self.expression(argument)
case fn.builtinOp: case fn.builtinOp:
of "AddInt64": of "AddInt64":
self.emitByte(AddInt64) self.emitByte(AddInt64)
@ -898,6 +902,21 @@ proc handleBuiltinFunction(self: Compiler, fn: Name, args: seq[Expression]) =
self.emitByte(DivFloat32) self.emitByte(DivFloat32)
of "MulFloat32": of "MulFloat32":
self.emitByte(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: else:
discard # Unreachable discard # Unreachable
@ -930,7 +949,6 @@ proc generateCall(self: Compiler, fn: Name, args: seq[Expression]) =
proc generateObjCall(self: Compiler, args: seq[Expression]) = proc generateObjCall(self: Compiler, args: seq[Expression]) =
## Small wrapper that abstracts emitting a call instruction ## Small wrapper that abstracts emitting a call instruction
## for a given function already loaded on the operand stack ## 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(PushC) # Pops the function off the operand stack onto the call stack
self.emitByte(LoadReturnAddress) self.emitByte(LoadReturnAddress)
let pos = self.chunk.code.len() 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)])) let funct = self.matchImpl(node.token.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: @[("", typeOfA), ("", typeOfB)]))
self.callBinaryOp(funct, node) 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) = proc declareName(self: Compiler, node: Declaration, mutable: bool = false) =
## Statically declares a name into the current scope. ## 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() ## list of identifiers so that further calls to resolve()
## correctly return them. There is no code to actually ## correctly return them. There is no code to actually
## declare a variable at runtime: the value is already ## declare a variable at runtime: the value is already
## there on the stack ## on the stack
case node.kind: case node.kind:
of NodeKind.varDecl: of NodeKind.varDecl:
var node = VarDecl(node) var node = VarDecl(node)
@ -1542,9 +1536,11 @@ proc importStmt(self: Compiler, node: ImportStmt) =
## Imports a module at compile time ## Imports a module at compile time
if self.scopeDepth > 0: if self.scopeDepth > 0:
self.error("import statements are only allowed at the top level") self.error("import statements are only allowed at the top level")
var lexer = newLexer()
var parser = newParser()
var compiler = newCompiler() var compiler = newCompiler()
# TODO: Find module # 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) = proc statement(self: Compiler, node: Statement) =

View File

@ -403,29 +403,14 @@ proc call(self: Parser): Expression =
result = self.makeCall(result) result = self.makeCall(result)
elif self.match(Dot): elif self.match(Dot):
self.expect(Identifier, "expecting attribute name after '.'") self.expect(Identifier, "expecting attribute name after '.'")
result = newGetItemExpr(result, newIdentExpr(self.peek(-1)), result = newGetItemExpr(result, newIdentExpr(self.peek(-1)), 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)
else: else:
break break
## Operator parsing handlers ## Operator parsing handlers
proc unary(self: Parser): Expression = 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()) result = newUnaryExpr(self.step(), self.unary())
else: else:
result = self.call() result = self.call()
@ -435,7 +420,7 @@ proc parsePow(self: Parser): Expression =
result = self.unary() result = self.unary()
var operator: Token var operator: Token
var right: Expression 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() operator = self.step()
right = self.unary() right = self.unary()
result = newBinaryExpr(result, operator, right) result = newBinaryExpr(result, operator, right)
@ -445,7 +430,7 @@ proc parseMul(self: Parser): Expression =
result = self.parsePow() result = self.parsePow()
var operator: Token var operator: Token
var right: Expression 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() operator = self.step()
right = self.parsePow() right = self.parsePow()
result = newBinaryExpr(result, operator, right) result = newBinaryExpr(result, operator, right)
@ -455,7 +440,7 @@ proc parseAdd(self: Parser): Expression =
result = self.parseMul() result = self.parseMul()
var operator: Token var operator: Token
var right: Expression 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() operator = self.step()
right = self.parseMul() right = self.parseMul()
result = newBinaryExpr(result, operator, right) result = newBinaryExpr(result, operator, right)
@ -465,7 +450,7 @@ proc parseCmp(self: Parser): Expression =
result = self.parseAdd() result = self.parseAdd()
var operator: Token var operator: Token
var right: Expression 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() operator = self.step()
right = self.parseAdd() right = self.parseAdd()
result = newBinaryExpr(result, operator, right) result = newBinaryExpr(result, operator, right)
@ -475,7 +460,7 @@ proc parseAnd(self: Parser): Expression =
result = self.parseCmp() result = self.parseCmp()
var operator: Token var operator: Token
var right: Expression 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() operator = self.step()
right = self.parseCmp() right = self.parseCmp()
result = newBinaryExpr(result, operator, right) result = newBinaryExpr(result, operator, right)
@ -485,7 +470,7 @@ proc parseOr(self: Parser): Expression =
result = self.parseAnd() result = self.parseAnd()
var operator: Token var operator: Token
var right: Expression 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() operator = self.step()
right = self.parseAnd() right = self.parseAnd()
result = newBinaryExpr(result, operator, right) result = newBinaryExpr(result, operator, right)
@ -493,7 +478,7 @@ proc parseOr(self: Parser): Expression =
proc parseAssign(self: Parser): Expression = proc parseAssign(self: Parser): Expression =
result = self.parseOr() 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() let tok = self.step()
var value = self.expression() var value = self.expression()
case result.kind: case result.kind:
@ -509,7 +494,7 @@ proc parseArrow(self: Parser): Expression =
result = self.parseAssign() result = self.parseAssign()
var operator: Token var operator: Token
var right: Expression 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() operator = self.step()
right = self.parseAssign() right = self.parseAssign()
result = newBinaryExpr(result, operator, right) result = newBinaryExpr(result, operator, right)