Initial work on generics and fixed bugs in the parser with stropped operator names
This commit is contained in:
parent
4591e5ca0e
commit
e32b8e258f
|
@ -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) =
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue