More work on pragmas, returning functions now works
This commit is contained in:
parent
dac0cca1bc
commit
11b15abc01
|
@ -27,7 +27,7 @@ when len(PEON_COMMIT_HASH) != 40:
|
|||
const PEON_BRANCH* = "master"
|
||||
when len(PEON_BRANCH) > 255:
|
||||
{.fatal: "The git branch name's length must be less than or equal to 255 characters".}
|
||||
const DEBUG_TRACE_VM* = false # Traces VM execution
|
||||
const DEBUG_TRACE_VM* = true # Traces VM execution
|
||||
const DEBUG_TRACE_GC* = false # Traces the garbage collector (TODO)
|
||||
const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation
|
||||
const DEBUG_TRACE_COMPILER* = false # Traces the compiler
|
||||
|
|
|
@ -796,10 +796,10 @@ proc matchImpl(self: Compiler, name: string, kind: Type): Name =
|
|||
return impl[0]
|
||||
|
||||
|
||||
proc emitFunction(self: Compiler, node: Name) =
|
||||
proc emitFunction(self: Compiler, name: Name) =
|
||||
## Wrapper to emit LoadFunction instructions
|
||||
self.emitByte(LoadFunction)
|
||||
self.emitBytes((node.codePos + 4).toTriple())
|
||||
self.emitBytes((name.codePos + 4).toTriple())
|
||||
|
||||
|
||||
proc generateCall(self: Compiler, fn: Name, args: seq[Expression]) =
|
||||
|
@ -994,6 +994,9 @@ proc identifier(self: Compiler, node: IdentExpr) =
|
|||
# no matter the scope depth
|
||||
self.emitConstant(node, self.inferType(node))
|
||||
else:
|
||||
if s.valueType.kind == Function:
|
||||
self.emitByte(LoadFunction)
|
||||
self.emitBytes(s.codePos.toTriple())
|
||||
self.detectClosureVariable(s)
|
||||
if not s.isClosedOver:
|
||||
# Static name resolution, loads value at index in the stack. Very fast. Much wow.
|
||||
|
@ -1006,6 +1009,8 @@ proc identifier(self: Compiler, node: IdentExpr) =
|
|||
# not much slower than indexing our stack (since they're both dynamic arrays at runtime anyway)
|
||||
self.emitByte(LoadClosure)
|
||||
self.emitBytes(self.closedOver.high().toTriple())
|
||||
if s.valueType.kind == Function:
|
||||
self.emitByte(PopC)
|
||||
|
||||
|
||||
proc assignment(self: Compiler, node: ASTNode) =
|
||||
|
@ -1164,7 +1169,41 @@ proc whileStmt(self: Compiler, node: WhileStmt) =
|
|||
self.emitLoop(start)
|
||||
|
||||
|
||||
proc callExpr(self: Compiler, node: CallExpr) =
|
||||
proc isPure(self: Compiler, node: ASTNode): bool =
|
||||
## Checks if a function has any side effects
|
||||
var pragmas: seq[Pragma]
|
||||
case node.kind:
|
||||
of lambdaExpr:
|
||||
pragmas = LambdaExpr(node).pragmas
|
||||
else:
|
||||
pragmas = Declaration(node).pragmas
|
||||
if pragmas.len() == 0:
|
||||
return false
|
||||
for pragma in pragmas:
|
||||
if pragma.name.name.lexeme == "pure":
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
proc checkCallIsPure(self: Compiler, node: ASTnode): bool =
|
||||
## Checks if a call has any side effects
|
||||
if not self.isPure(node):
|
||||
return true
|
||||
var pragmas: seq[Pragma]
|
||||
case node.kind:
|
||||
of lambdaExpr:
|
||||
pragmas = LambdaExpr(node).pragmas
|
||||
else:
|
||||
pragmas = Declaration(node).pragmas
|
||||
if pragmas.len() == 0:
|
||||
return false
|
||||
for pragma in pragmas:
|
||||
if pragma.name.name.lexeme == "pure":
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
proc callExpr(self: Compiler, node: CallExpr): Name =
|
||||
## Compiles code to call a function
|
||||
var args: seq[tuple[name: string, kind: Type]] = @[]
|
||||
var argExpr: seq[Expression] = @[]
|
||||
|
@ -1186,16 +1225,29 @@ proc callExpr(self: Compiler, node: CallExpr) =
|
|||
case node.callee.kind:
|
||||
of identExpr:
|
||||
funct = self.matchImpl(IdentExpr(node.callee).name.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: args))
|
||||
of NodeKind.callExpr:
|
||||
var node = node.callee
|
||||
while node.kind == callExpr:
|
||||
funct = self.callExpr(CallExpr(node))
|
||||
node = CallExpr(node).callee
|
||||
|
||||
# funct = self.matchImpl(IdentExpr(node.callee).name.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: args))
|
||||
else:
|
||||
discard # TODO: Lambdas
|
||||
self.generateCall(funct, argExpr)
|
||||
if self.scopeDepth > 0 and not self.checkCallIsPure(node.callee):
|
||||
if not self.currentFunction.name.isNil():
|
||||
self.error(&"cannot make sure that calls to '{self.currentFunction.name.token.lexeme}' are side-effect free")
|
||||
else:
|
||||
self.error(&"cannot make sure that call is side-effect free")
|
||||
result = funct
|
||||
|
||||
|
||||
proc expression(self: Compiler, node: Expression) =
|
||||
## Compiles all expressions
|
||||
case node.kind:
|
||||
of NodeKind.callExpr:
|
||||
self.callExpr(CallExpr(node)) # TODO
|
||||
discard self.callExpr(CallExpr(node)) # TODO
|
||||
of getItemExpr:
|
||||
discard # TODO: Get rid of this
|
||||
of pragmaExpr:
|
||||
|
|
|
@ -1047,7 +1047,7 @@ proc statement(self: Parser): Statement =
|
|||
# TODO
|
||||
# from module import a [, b, c as d]
|
||||
discard self.step()
|
||||
result = self.importStmt(fromStmt = true)
|
||||
result = self.importStmt(fromStmt=true)
|
||||
of While:
|
||||
discard self.step()
|
||||
result = self.whileStmt()
|
||||
|
@ -1076,38 +1076,29 @@ proc statement(self: Parser): Statement =
|
|||
result = self.expressionStatement()
|
||||
|
||||
|
||||
proc parsePragma(self: Parser): tuple[global: bool, pragmas: seq[Pragma]] =
|
||||
proc parsePragmas(self: Parser): seq[Pragma] =
|
||||
## Parses pragmas
|
||||
result.global = true
|
||||
var
|
||||
decl: Declaration = nil
|
||||
found = false
|
||||
for node in self.tree:
|
||||
if node.token.line == self.peek(-1).line and node.kind in {NodeKind.varDecl, typeDecl, funDecl, lambdaExpr}:
|
||||
decl = node
|
||||
found = true
|
||||
break
|
||||
if not found:
|
||||
# Dummy declaration
|
||||
result.global = false
|
||||
decl = Declaration(pragmas: @[])
|
||||
var
|
||||
name: IdentExpr
|
||||
args: seq[LiteralExpr]
|
||||
exp: Expression
|
||||
names: seq[string]
|
||||
while not self.match("]") and not self.done():
|
||||
args = @[]
|
||||
self.expect(Identifier, "expecting pragma name")
|
||||
if self.peek(-1).lexeme in names:
|
||||
self.error("duplicate pragmas are not allowed")
|
||||
names.add(self.peek(-1).lexeme)
|
||||
name = newIdentExpr(self.peek(-1))
|
||||
if not self.match(":"):
|
||||
if self.match("]"):
|
||||
decl.pragmas.add(newPragma(name, @[]))
|
||||
result.add(newPragma(name, @[]))
|
||||
break
|
||||
elif self.match("("):
|
||||
while not self.match(")") and not self.done():
|
||||
exp = self.primary()
|
||||
if not exp.isLiteral():
|
||||
self.error("invalid syntax")
|
||||
self.error("pragma arguments can only be literals")
|
||||
args.add(LiteralExpr(exp))
|
||||
if not self.match(","):
|
||||
break
|
||||
|
@ -1115,12 +1106,11 @@ proc parsePragma(self: Parser): tuple[global: bool, pragmas: seq[Pragma]] =
|
|||
else:
|
||||
exp = self.primary()
|
||||
if not exp.isLiteral():
|
||||
self.error("invalid syntax")
|
||||
self.error("pragma arguments can only be literals")
|
||||
args.add(LiteralExpr(exp))
|
||||
if self.match(","):
|
||||
continue
|
||||
decl.pragmas.add(newPragma(name, args))
|
||||
result.pragmas = decl.pragmas
|
||||
result.add(newPragma(name, args))
|
||||
|
||||
|
||||
proc typeDecl(self: Parser): TypeDecl =
|
||||
|
@ -1202,11 +1192,8 @@ proc declaration(self: Parser): Declaration =
|
|||
result = self.funDecl(isOperator=true)
|
||||
of TokenType.Pragma:
|
||||
discard self.step()
|
||||
let temp = self.parsePragma()
|
||||
if not temp.global:
|
||||
for p in temp.pragmas:
|
||||
self.tree.add(p)
|
||||
result = nil
|
||||
for p in self.parsePragmas():
|
||||
self.tree.add(p)
|
||||
of Type:
|
||||
discard self.step()
|
||||
result = self.typeDecl()
|
||||
|
|
Loading…
Reference in New Issue