move arity checking to its own op

This commit is contained in:
prod2 2022-01-27 05:56:09 +01:00
parent dd81e1151b
commit 215d1539de
6 changed files with 21 additions and 21 deletions

View File

@ -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,

View File

@ -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)

View File

@ -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:

View File

@ -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:

View File

@ -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
View File

@ -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