-> method call
This commit is contained in:
parent
5f3f61af2d
commit
ece31b11e0
|
@ -9,7 +9,7 @@ type
|
|||
opClosure, # closures
|
||||
opPop, opPopSA, opPopA # pop
|
||||
opNegate, opNot # unary
|
||||
opSwap, # stack manipulation
|
||||
opSwap, opDup, # stack manipulation
|
||||
opAdd, opSubtract, opMultiply, opDivide, # math
|
||||
opEqual, opGreater, opLess, # comparison
|
||||
opTrue, opFalse, opNil, # literal
|
||||
|
@ -92,7 +92,7 @@ proc writeConstant*(ch: var Chunk, constant: NdValue, line: int): int =
|
|||
const simpleInstructions = {
|
||||
opReturn,
|
||||
opPop,
|
||||
opSwap,
|
||||
opSwap, opDup,
|
||||
opNegate, opNot,
|
||||
opAdd, opSubtract, opMultiply, opDivide,
|
||||
opEqual, opGreater, opLess,
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
{.used.}
|
||||
|
||||
import strformat
|
||||
import bitops
|
||||
|
||||
import ../scanner
|
||||
import ../chunk
|
||||
import ../types/value
|
||||
import ../config
|
||||
|
||||
import types
|
||||
|
@ -67,6 +69,32 @@ proc parsePipeCall(comp: Compiler) =
|
|||
|
||||
tkDoublecolon.genRule(nop, parsePipeCall, pcAmpersand)
|
||||
|
||||
proc parseArrowCall(comp: Compiler) =
|
||||
# -> syntactic sugar for table "methods"
|
||||
|
||||
# when called, the stack contains the table
|
||||
# the table should be duplicated first
|
||||
comp.writeChunk(1, opDup)
|
||||
# then the index should be read
|
||||
comp.consume(tkIdentifier, "Identifier (index) expected after '->'.")
|
||||
let index = comp.previous.text.fromNimString()
|
||||
comp.writeConstant(index)
|
||||
comp.writeChunk(-1, opGetIndex)
|
||||
# the stack's state now is table, method
|
||||
# invert to get the right alignment for further function call
|
||||
comp.writeChunk(0, opSwap)
|
||||
# now the same code as :: applies
|
||||
var argcount = 1
|
||||
# args optional
|
||||
if comp.match(tkLeftParen):
|
||||
argcount = 1 + comp.parseArgs()
|
||||
|
||||
comp.writeChunk(-argcount, opCall)
|
||||
comp.writeChunk(0, argcount.uint8)
|
||||
|
||||
|
||||
tkArrow.genRule(nop, parseArrowCall, pcIndex)
|
||||
|
||||
proc parseFunct(comp: Compiler) =
|
||||
|
||||
# jump over
|
||||
|
|
|
@ -11,7 +11,8 @@ type
|
|||
|
||||
TokenType* = enum
|
||||
tkNone, # the default tokentype, if encountered anywhere, erroring out is the best course of action
|
||||
tkLeftParen, tkRightParen, tkLeftBrace, tkRightBrace, tkComma, tkDot, tkColon, tkDoublecolon,
|
||||
tkLeftParen, tkRightParen, tkLeftBrace, tkRightBrace, tkComma, tkDot,
|
||||
tkColon, tkDoublecolon, tkArrow,
|
||||
tkMinus, tkPlus, tkSemicolon, tkSlash, tkStar, tkBang, tkBangEqual,
|
||||
tkGreater, tkGreaterEqual, tkLess, tkLessEqual, tkEqual, tkEqualEqual,
|
||||
tkStartList, tkStartTable, tkLeftBracket, tkRightBracket,
|
||||
|
@ -127,7 +128,7 @@ const keywords = {
|
|||
}.toTable
|
||||
|
||||
proc canStartIdent(chr: char): bool =
|
||||
chr in Letters or chr in {'_', ':'}
|
||||
chr in Letters or chr in {'_'}
|
||||
|
||||
proc canContIdent(chr: char): bool =
|
||||
canStartIdent(chr) or chr in Digits
|
||||
|
@ -175,7 +176,11 @@ proc scanToken*(scanner: Scanner): Token =
|
|||
of ';': return scanner.makeToken(tkSemicolon)
|
||||
of ',': return scanner.makeToken(tkComma)
|
||||
of '.': return scanner.makeToken(tkDot)
|
||||
of '-': return scanner.makeToken(tkMinus)
|
||||
of '-':
|
||||
if scanner.match('>'):
|
||||
return scanner.makeToken(tkArrow)
|
||||
else:
|
||||
return scanner.makeToken(tkMinus)
|
||||
of '+': return scanner.makeToken(tkPlus)
|
||||
of '/': return scanner.makeToken(tkSlash)
|
||||
of '*': return scanner.makeToken(tkStar)
|
||||
|
@ -197,13 +202,13 @@ proc scanToken*(scanner: Scanner): Token =
|
|||
if scanner.match('['): return scanner.makeToken(tkStartList)
|
||||
elif scanner.match('{'): return scanner.makeToken(tkStartTable)
|
||||
else: return scanner.scanLabel()
|
||||
of ':':
|
||||
if scanner.match(':'): return scanner.makeToken(tkDoublecolon)
|
||||
elif scanner.peek().canContIdent(): return scanner.scanIdentifier()
|
||||
else: return scanner.makeToken(tkColon)
|
||||
else:
|
||||
if c == ':' and scanner.match(':'):
|
||||
return scanner.makeToken(tkDoublecolon)
|
||||
if c.canStartIdent():
|
||||
# : can start ident, but if on its own it's probably syntactic sugar for tables
|
||||
if c == ':' and not scanner.peek().canContIdent():
|
||||
return scanner.makeToken(tkColon)
|
||||
# ':' can start ident, but is not handled here
|
||||
return scanner.scanIdentifier()
|
||||
else:
|
||||
return scanner.errorToken("Unexpected character.")
|
||||
|
|
|
@ -188,6 +188,8 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
stack.popn(amt)
|
||||
of opSwap:
|
||||
stack.swap()
|
||||
of opDup:
|
||||
stack.push(stack.peek())
|
||||
of opConstant:
|
||||
let val: NdValue = ip.readConstant(chunk)
|
||||
stack.add(val)
|
||||
|
|
|
@ -40,4 +40,44 @@ nested["lvl1"]["lvl2"]["lvl3"] = -5.4;
|
|||
nested .lvl1 .lvl2 .lvl3 :: print;
|
||||
//expect:-5.4
|
||||
|
||||
// creating tables with : and no [] idents
|
||||
// creating tables with : and no [] idents
|
||||
|
||||
var mix = @{
|
||||
ident = 5,
|
||||
ident2: 6,
|
||||
[3] = 7,
|
||||
["ident4"]: 8,
|
||||
};
|
||||
|
||||
print(mix.ident, mix["ident2"], mix[3], mix.ident4);
|
||||
//expect:5.0 6.0 7.0 8.0
|
||||
|
||||
// -> method call syntax
|
||||
|
||||
var class = @{
|
||||
method = funct(self) print ("i was called")
|
||||
};
|
||||
|
||||
// no args needed then no parentheses needed
|
||||
class->method;
|
||||
//expect:i was called
|
||||
|
||||
var multiplier = @{
|
||||
multiple = 5,
|
||||
do = funct(self, arg) :result = self.multiple * arg,
|
||||
};
|
||||
|
||||
multiplier->do(7) :: print;
|
||||
//expect:35.0
|
||||
|
||||
// -> method call syntax with :: - check for precedence
|
||||
|
||||
var returner = @{
|
||||
method = funct(self) :result = funct(n) :result = n * 2
|
||||
};
|
||||
|
||||
1.7 :: returner->method :: print;
|
||||
//expect:3.4
|
||||
|
||||
print("finish");
|
||||
//expect:finish
|
Loading…
Reference in New Issue