mirror of https://github.com/japl-lang/japl.git
Added a beta implementation for arrow functions
This commit is contained in:
parent
56938897d6
commit
2e60ab9fb6
|
@ -925,7 +925,7 @@ proc parseFunction(self: Compiler, funType: FunctionType) =
|
|||
## keyword ones as well
|
||||
var self = initCompiler(funType, self, self.parser, self.file)
|
||||
self.beginScope()
|
||||
self.parser.consume(LP, "Expecting '(' after function name")
|
||||
self.parser.consume(LP, "Expecting '('")
|
||||
if self.parser.hadError:
|
||||
return
|
||||
var paramNames: seq[string] = @[]
|
||||
|
@ -970,13 +970,22 @@ proc parseFunction(self: Compiler, funType: FunctionType) =
|
|||
self.emitBytes(self.makeLongConstant(fun))
|
||||
|
||||
|
||||
proc funDeclaration(self: Compiler) =
|
||||
|
||||
proc parseLambda(self: Compiler, canAssign: bool) =
|
||||
## Parses lambda expressions of the form => (params) {code}
|
||||
self.parseFunction(FunctionType.LAMBDA)
|
||||
|
||||
|
||||
proc funDeclaration(self: Compiler, named: bool = true) =
|
||||
## Parses function declarations and declares
|
||||
## them in the current scope
|
||||
var funName = self.parseVariable("expecting function name")
|
||||
self.markInitialized()
|
||||
self.parseFunction(FunctionType.FUNC)
|
||||
self.defineVariable(funName)
|
||||
if named:
|
||||
var funName = self.parseVariable("expecting function name")
|
||||
self.markInitialized()
|
||||
self.parseFunction(FunctionType.FUNC)
|
||||
self.defineVariable(funName)
|
||||
else:
|
||||
self.parseFunction(FunctionType.LAMBDA)
|
||||
|
||||
|
||||
proc argumentList(self: Compiler): uint8 =
|
||||
|
@ -1153,7 +1162,8 @@ var rules: array[TokenType, ParseRule] = [
|
|||
makeRule(nil, binary, Precedence.Term), # BOR
|
||||
makeRule(unary, nil, Precedence.None), # TILDE
|
||||
makeRule(nil, binary, Precedence.Is), # IS
|
||||
makeRule(nil, binary, Precedence.As) # AS
|
||||
makeRule(nil, binary, Precedence.As), # AS
|
||||
makeRule(parseLambda, nil, Precedence.None) # LAMBDA
|
||||
|
||||
]
|
||||
|
||||
|
@ -1229,9 +1239,15 @@ proc initCompiler*(context: FunctionType, enclosing: Compiler = nil, parser: Par
|
|||
result.parser.file = file
|
||||
result.locals.add(Local(depth: 0, name: Token(kind: EOF, lexeme: "")))
|
||||
inc(result.localCount)
|
||||
result.function = result.markObject(newFunction(chunk=newChunk()))
|
||||
if context != SCRIPT: # If we're compiling a function, we give it its name
|
||||
result.function.name = asStr(enclosing.parser.previous().lexeme)
|
||||
case context:
|
||||
of FunctionType.Func:
|
||||
result.function = result.markObject(newFunction(enclosing.parser.previous().lexeme, newChunk()))
|
||||
of FunctionType.Lambda:
|
||||
result.function = result.markObject(newLambda(newChunk()))
|
||||
else: # Script
|
||||
result.function = result.markObject(newFunction("", newChunk()))
|
||||
result.function.name = nil
|
||||
|
||||
|
||||
# This way the compiler can be executed on its own
|
||||
# without the VM
|
||||
|
|
|
@ -218,6 +218,8 @@ proc scanToken(self: Lexer) =
|
|||
self.parseComment()
|
||||
elif single == '=' and self.match('='):
|
||||
self.tokens.add(self.createToken(TokenType.DEQ))
|
||||
elif single == '=' and self.match('>'):
|
||||
self.tokens.add(self.createToken(TokenType.LAMBDA))
|
||||
elif single == '>' and self.match('='):
|
||||
self.tokens.add(self.createToken(TokenType.GE))
|
||||
elif single == '>' and self.match('>'):
|
||||
|
|
|
@ -29,7 +29,7 @@ type
|
|||
WHILE, DEL, BREAK, EOF,
|
||||
COLON, CONTINUE, CARET,
|
||||
SHL, SHR, NAN, INF, BAND,
|
||||
BOR, TILDE, IS, AS
|
||||
BOR, TILDE, IS, AS, LAMBDA
|
||||
Token* = ref object
|
||||
kind*: TokenType
|
||||
lexeme*: string
|
||||
|
|
|
@ -12,7 +12,7 @@ type
|
|||
## the top-level code, this tiny
|
||||
## enum is used to tell the two
|
||||
## contexts apart when compiling
|
||||
Func, Script
|
||||
Func, Script, Lambda
|
||||
|
||||
Function* = object of Obj
|
||||
## A function object
|
||||
|
@ -40,13 +40,27 @@ proc newFunction*(name: string = "", chunk: Chunk, arity: int = 0): ptr Function
|
|||
result.isHashable = false
|
||||
|
||||
|
||||
proc newLambda*(chunk: Chunk, arity: int = 0): ptr Function =
|
||||
## Allocates a new lambda object (anonymous function) with the given
|
||||
## bytecode chunk and arity
|
||||
# TODO: Add lambdas
|
||||
# TODO: Add support for optional parameters
|
||||
result = allocateObj(Function, ObjectType.Function)
|
||||
result.name = "<lambda function>".asStr()
|
||||
result.arity = arity
|
||||
result.chunk = chunk
|
||||
result.isHashable = false
|
||||
|
||||
|
||||
proc typeName*(self: ptr Function): string =
|
||||
result = "function"
|
||||
|
||||
|
||||
proc stringify*(self: ptr Function): string =
|
||||
if self.name != nil:
|
||||
if self.name != nil and self.name.toStr() != "<lambda function>":
|
||||
result = "<function '" & self.name.toStr() & "'>"
|
||||
elif self.name.toStr() == "<lambda function>":
|
||||
return self.name.toStr()
|
||||
else:
|
||||
result = "<code object>"
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import baseObject
|
|||
import numbers
|
||||
import ../memory
|
||||
import strutils
|
||||
import strformat
|
||||
|
||||
|
||||
type
|
||||
|
|
Loading…
Reference in New Issue