move arity checking to its own op
This commit is contained in:
parent
dd81e1151b
commit
215d1539de
|
@ -5,7 +5,7 @@ import value
|
|||
|
||||
type
|
||||
OpCode* = enum
|
||||
opReturn, opCall, # functions
|
||||
opReturn, opCall, opCheckArity # functions
|
||||
opPop, opPopSA, opPopA # pop
|
||||
opPrint, # print
|
||||
opNegate, opNot # unary
|
||||
|
@ -87,6 +87,7 @@ const constantInstructions = {
|
|||
const shortArgInstructions = {
|
||||
opPopSA,
|
||||
opCall,
|
||||
opCheckArity,
|
||||
}
|
||||
const argInstructions = {
|
||||
opPopA,
|
||||
|
|
|
@ -633,6 +633,9 @@ proc parseFunct(comp: Compiler) =
|
|||
if params.len > shortArgMax:
|
||||
comp.error("Too many parameters.")
|
||||
|
||||
comp.writeChunk(0, opCheckArity) # runtime arity check
|
||||
comp.writeChunk(0, params.len.uint8)
|
||||
|
||||
for i in countup(1, params.len):
|
||||
comp.stackIndex = i
|
||||
comp.addLocal(params[i-1], 0)
|
||||
|
@ -645,7 +648,7 @@ proc parseFunct(comp: Compiler) =
|
|||
dec comp.stackIndex # the previous end scope did not put anything on the stack, it is jumped over
|
||||
|
||||
# get konvalue functions:
|
||||
let konFunct = newKonFunction(functII, params.len.uint8)
|
||||
let konFunct = newNdFunction(functII)
|
||||
|
||||
# end of function declaration:
|
||||
comp.patchJump(jumpOverBody)
|
||||
|
|
|
@ -19,7 +19,7 @@ const lineEditor = leRdstdin
|
|||
when lineEditor == leRdstdin:
|
||||
import rdstdin
|
||||
|
||||
proc konLineEditor*: string =
|
||||
proc ndLineEditor*: string =
|
||||
proc ctrlc =
|
||||
raise newException(ReadlineInterruptedException, "Ctrl+C/D pressed.")
|
||||
when lineEditor == leBasic:
|
||||
|
|
2
main.nim
2
main.nim
|
@ -21,7 +21,7 @@ proc interpret(name: string, source: string): Result =
|
|||
proc repl =
|
||||
while true:
|
||||
try:
|
||||
let line = konLineEditor()
|
||||
let line = ndLineEditor()
|
||||
if line.len > 0:
|
||||
discard interpret("repl", line)
|
||||
except ReadlineInterruptedException:
|
||||
|
|
14
value.nim
14
value.nim
|
@ -20,8 +20,7 @@ type
|
|||
of ndString:
|
||||
stringValue*: string
|
||||
of ndFunct:
|
||||
sdfga*: string # WHY IS THIS STRING WHEN HERE EVEN THO USELESS SPEEDING THE BENCHMARK UP
|
||||
arity*: uint8 # number of arguments
|
||||
placeholder*: string
|
||||
entryII*: int # entry instruction index
|
||||
of errorTypes:
|
||||
message*: string
|
||||
|
@ -72,7 +71,6 @@ proc equal*(val, right: NdValue): bool =
|
|||
val.stringValue == right.stringValue
|
||||
of ndFunct:
|
||||
val.entryII == right.entryII
|
||||
# same entry II/module but diff arity is a bug
|
||||
of errorTypes:
|
||||
false # error comparison is undefined
|
||||
|
||||
|
@ -87,13 +85,13 @@ proc toNdValue*(val: bool): NdValue =
|
|||
proc toNdValue*(val: string): NdValue =
|
||||
NdValue(ndType: ndString, stringValue: val)
|
||||
|
||||
proc newKonFunction*(ii: int, arity: uint8): NdValue =
|
||||
NdValue(ndType: ndFunct, entryII: ii, arity: arity)
|
||||
proc newNdFunction*(ii: int): NdValue =
|
||||
NdValue(ndType: ndFunct, entryII: ii)
|
||||
|
||||
proc toNdValue*: NdValue =
|
||||
NdValue(ndType: ndNil)
|
||||
|
||||
proc konError*(msg: string): NdValue =
|
||||
proc ndError*(msg: string): NdValue =
|
||||
NdValue(ndType: ndError, message: msg)
|
||||
|
||||
# NatReturn misc
|
||||
|
@ -147,10 +145,10 @@ proc `<`*(val: NdValue, right: NdValue): NdValue =
|
|||
if val.ndType == ndFloat and right.ndType == ndFloat:
|
||||
return toNdValue(val.floatValue < right.floatValue)
|
||||
else:
|
||||
return konError(&"Attempt to compare types {val.ndType} and {right.ndType}.")
|
||||
return ndError(&"Attempt to compare types {val.ndType} and {right.ndType}.")
|
||||
|
||||
proc `>`*(val: NdValue, right: NdValue): NdValue =
|
||||
if val.ndType == ndFloat and right.ndType == ndFloat:
|
||||
return toNdValue(val.floatValue > right.floatValue)
|
||||
else:
|
||||
return konError(&"Attempt to compare types {val.ndType} and {right.ndType}.")
|
||||
return ndError(&"Attempt to compare types {val.ndType} and {right.ndType}.")
|
16
vm.nim
16
vm.nim
|
@ -62,10 +62,6 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
result = ip[].int
|
||||
ip = ip.padd(1)
|
||||
|
||||
proc readUI8Noconv(): uint8 =
|
||||
result = ip[]
|
||||
ip = ip.padd(1)
|
||||
|
||||
proc readDU8(): int =
|
||||
result = ip.DU8ptrToInt
|
||||
ip = ip.padd(argSize)
|
||||
|
@ -204,21 +200,23 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
of opLoop:
|
||||
let offset = readDU8()
|
||||
ip = ip.psub(offset)
|
||||
of opCheckArity:
|
||||
let arity = readUI8()
|
||||
let argcount = stack.high() - frameBottom
|
||||
if arity != argcount:
|
||||
runtimeError(&"Wrong number of arguments, expected {arity}, got {argcount}.")
|
||||
break
|
||||
of opCall:
|
||||
# create the call env
|
||||
# current stack before opCall:
|
||||
# ... <funct obj> <arg1> <arg2> <arg3>
|
||||
# opCall converts it to this
|
||||
# ... <ret val> <arg1> <arg2> <arg3>
|
||||
let argcountUint8 = readUI8Noconv()
|
||||
let argcount = argcountUint8.int
|
||||
let argcount = readUI8()
|
||||
let funct = stack[stack.high - argcount]
|
||||
if funct.ndType != ndFunct:
|
||||
runtimeError("Attempt to call a non-funct (a defunct?).") # here is a bad defunct joke
|
||||
break
|
||||
if funct.arity != argcountUint8:
|
||||
runtimeError(&"Wrong number of arguments, expected {funct.arity}, got {argcount}.")
|
||||
break
|
||||
|
||||
stack[stack.high - argcount] = toNdValue() # replace the function with nil: this is the return value slot
|
||||
|
||||
|
|
Loading…
Reference in New Issue