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 ../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) =

View File

@ -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)