benchmarking; changed arg length from 3 to 2
This commit is contained in:
parent
35d2b96651
commit
8a956debc6
|
@ -0,0 +1,9 @@
|
|||
local function fib(n)
|
||||
if n < 2 then
|
||||
return 1
|
||||
else
|
||||
return fib(n-1) + fib(n-2)
|
||||
end
|
||||
end
|
||||
|
||||
print(fib(37))
|
|
@ -3,5 +3,4 @@ var fib = funct(n)
|
|||
else ^result = fib(n-1) + fib(n-2)
|
||||
;
|
||||
|
||||
print fib(25);
|
||||
|
||||
print fib(37);
|
|
@ -0,0 +1,7 @@
|
|||
def fib(n):
|
||||
if n < 2:
|
||||
return 1
|
||||
else:
|
||||
return fib(n-1) + fib(n-2)
|
||||
|
||||
print(fib(37))
|
35
chunk.nim
35
chunk.nim
|
@ -23,7 +23,10 @@ type
|
|||
lines*: seq[int]
|
||||
name*: string # name of the module/chunk/files
|
||||
|
||||
Triple* = array[3, uint8]
|
||||
DoubleUint8* = array[2, uint8]
|
||||
|
||||
const argSize* = 2
|
||||
const argMax*: int = 256*256
|
||||
|
||||
proc initChunk*(name: string): Chunk =
|
||||
Chunk(code: @[], name: name, lines: @[], constants: @[])
|
||||
|
@ -36,7 +39,7 @@ proc writeChunk*(ch: var Chunk, code: OpCode, line: int) =
|
|||
ch.code.add(code.uint8)
|
||||
ch.lines.add(line)
|
||||
|
||||
proc writeChunk*(ch: var Chunk, code: Triple, line: int) =
|
||||
proc writeChunk*(ch: var Chunk, code: DoubleUint8, line: int) =
|
||||
for c in code:
|
||||
ch.code.add(c)
|
||||
ch.lines.add(line)
|
||||
|
@ -44,16 +47,11 @@ proc writeChunk*(ch: var Chunk, code: Triple, line: int) =
|
|||
proc len*(ch: Chunk): int =
|
||||
ch.code.len
|
||||
|
||||
proc toTriple*(integer: int): Triple =
|
||||
var integer = integer
|
||||
result[0] = integer.uint8
|
||||
integer = integer div 256
|
||||
result[1] = integer.uint8
|
||||
integer = integer div 256
|
||||
result[2] = integer.uint8
|
||||
proc toDU8*(integ: int): DoubleUint8 =
|
||||
cast[ptr array[2, uint8]](integ.unsafeAddr)[]
|
||||
|
||||
proc toInt*(triple: Triple): int =
|
||||
triple[0].int + triple[1].int * 256 + triple[2].int * 256 * 256
|
||||
proc toInt*(du8: DoubleUint8): int =
|
||||
cast[uint16](du8).int
|
||||
|
||||
proc addConstant*(ch: var Chunk, constant: KonValue): int =
|
||||
ch.constants.add(constant)
|
||||
|
@ -62,7 +60,7 @@ proc addConstant*(ch: var Chunk, constant: KonValue): int =
|
|||
proc writeConstant*(ch: var Chunk, constant: KonValue, line: int): int =
|
||||
result = ch.addConstant(constant)
|
||||
ch.writeChunk(opConstant, line)
|
||||
ch.writeChunk(result.toTriple, line)
|
||||
ch.writeChunk(result.toDU8, line)
|
||||
|
||||
const simpleInstructions = {
|
||||
opReturn,
|
||||
|
@ -83,7 +81,6 @@ const argInstructions = {
|
|||
opJumpIfFalse, opJump, opLoop, opJumpIfFalsePop,
|
||||
}
|
||||
|
||||
const tripleMax*: int = 16777215
|
||||
|
||||
proc disassembleChunk*(ch: Chunk) =
|
||||
echo &"== Chunk {ch.name} begin =="
|
||||
|
@ -93,7 +90,7 @@ proc disassembleChunk*(ch: Chunk) =
|
|||
while c < ch.code.len:
|
||||
template instruction: uint8 = ch.code[c]
|
||||
template line: int = ch.lines[c]
|
||||
template triple: Triple = [ch.code[c+1], ch.code[c+2], ch.code[c+3]]
|
||||
template double: DoubleUint8 = [ch.code[c+1], ch.code[c+2]]
|
||||
let cFmt = &"{c:04}"
|
||||
let lineFmt = if lastLine == line: " | " else: &"{line:04}"
|
||||
try:
|
||||
|
@ -102,13 +99,13 @@ proc disassembleChunk*(ch: Chunk) =
|
|||
of simpleInstructions:
|
||||
write stdout, ")\n"
|
||||
of argInstructions:
|
||||
write stdout, &" {triple[0].toHex(2)} {triple[1].toHex(2)} {triple[2].toHex(2)})\n"
|
||||
c += 3
|
||||
write stdout, &" {double[0].toHex(2)} {double[1].toHex(2)})\n"
|
||||
c += 2
|
||||
of constantInstructions:
|
||||
let i = triple.toInt
|
||||
write stdout, &" {triple[0].toHex(2)} {triple[1].toHex(2)} {triple[2].toHex(2)})\n"
|
||||
let i = double.toInt
|
||||
write stdout, &" {double[0].toHex(2)} {double[1].toHex(2)})\n"
|
||||
echo &" points to constant {ch.constants[i]} (i: {i})"
|
||||
c += 3
|
||||
c += 2
|
||||
except:
|
||||
echo &"[{cFmt}] {lineFmt} Unknown opcode {instruction}"
|
||||
c.inc
|
||||
|
|
31
compiler.nim
31
compiler.nim
|
@ -131,7 +131,7 @@ proc synchronize(comp: Compiler) =
|
|||
return
|
||||
comp.advance()
|
||||
|
||||
proc writeChunk(comp: Compiler, dStackIndex: int, ch: OpCode | Triple) =
|
||||
proc writeChunk(comp: Compiler, dStackIndex: int, ch: OpCode | DoubleUint8) =
|
||||
comp.stackIndex += dStackIndex
|
||||
when debugCompiler:
|
||||
debugEcho &"new stackindex: {comp.stackIndex}, delta: {dStackIndex} due to {ch.repr}"
|
||||
|
@ -140,12 +140,12 @@ proc writeChunk(comp: Compiler, dStackIndex: int, ch: OpCode | Triple) =
|
|||
proc writeConstant(comp: Compiler, constant: KonValue) =
|
||||
comp.stackIndex.inc
|
||||
let index = comp.chunk.writeConstant(constant, comp.previous.line)
|
||||
if index >= tripleMax:
|
||||
if index >= argMax:
|
||||
comp.error("Too many constants in one chunk.")
|
||||
|
||||
|
||||
proc addLocal(comp: Compiler, name: string, delta: int) =
|
||||
if comp.locals.len >= tripleMax:
|
||||
if comp.locals.len >= argMax:
|
||||
comp.error("Too many local variables in function.")
|
||||
|
||||
# if delta is 0 or negative, it means that it is already on the stack when addLocal is called
|
||||
|
@ -194,29 +194,28 @@ proc emitJump(comp: Compiler, delta: int, op: OpCode): int =
|
|||
# delta -> 0 if the jump does not pop
|
||||
# delta -> -1 if the jump pops the condition from the stack
|
||||
comp.writeChunk(delta, op)
|
||||
comp.writeChunk(0, 0xffffff.toTriple)
|
||||
comp.chunk.len - 3
|
||||
comp.writeChunk(0, 0xffffff.toDU8)
|
||||
comp.chunk.len - argSize
|
||||
|
||||
proc patchJump(comp: Compiler, offset: int) =
|
||||
let jump = (comp.chunk.len - offset - 3)
|
||||
let jump = (comp.chunk.len - offset - argSize)
|
||||
|
||||
if (jump > tripleMax):
|
||||
if (jump > argMax):
|
||||
comp.error("Too much code to jump over.")
|
||||
|
||||
let jumpt = jump.toTriple
|
||||
let jumpt = jump.toDU8
|
||||
|
||||
comp.chunk.code[offset] = jumpt[0]
|
||||
comp.chunk.code[offset + 1] = jumpt[1]
|
||||
comp.chunk.code[offset + 2] = jumpt[2]
|
||||
|
||||
proc emitLoop(comp: Compiler, loopstart: int, delta: int, op: OpCode) =
|
||||
comp.writeChunk(delta, op)
|
||||
|
||||
let offset = comp.chunk.len - loopstart + 3
|
||||
if offset > tripleMax:
|
||||
let offset = comp.chunk.len - loopstart + argSize
|
||||
if offset > argMax:
|
||||
comp.error("Loop body too large.")
|
||||
|
||||
comp.writeChunk(0, offset.toTriple)
|
||||
comp.writeChunk(0, offset.toDU8)
|
||||
|
||||
# SCOPE HELPERS
|
||||
proc beginScope(comp: Compiler, function: bool = false) =
|
||||
|
@ -413,7 +412,7 @@ proc variable(comp: Compiler) =
|
|||
# get (global/local)
|
||||
comp.writeChunk(1, getOp)
|
||||
|
||||
comp.writeChunk(0, arg.toTriple)
|
||||
comp.writeChunk(0, arg.toDU8)
|
||||
|
||||
tkIdentifier.genRule(variable, nop, pcNone)
|
||||
|
||||
|
@ -443,7 +442,7 @@ proc parseCall(comp: Compiler) =
|
|||
|
||||
# emit call
|
||||
comp.writeChunk(-argcount, opCall)
|
||||
comp.writeChunk(0, argcount.toTriple)
|
||||
comp.writeChunk(0, argcount.toDU8)
|
||||
|
||||
|
||||
tkLeftParen.genRule(grouping, parseCall, pcCall)
|
||||
|
@ -583,7 +582,7 @@ proc parseWhile(comp: Compiler) =
|
|||
# stack size inside code that is conditional must be 0!
|
||||
|
||||
# body
|
||||
comp.writeChunk(-1, opPop) # pop the old result
|
||||
comp.writeChunk(-1, opPop) # pop the old return value
|
||||
comp.expression()
|
||||
# net stack change: 1 + -1 = 0
|
||||
|
||||
|
@ -706,7 +705,7 @@ proc defineVariable(comp: Compiler, index: int) =
|
|||
comp.markInitialized()
|
||||
else:
|
||||
comp.writeChunk(-1, opDefineGlobal)
|
||||
comp.writeChunk(0, index.toTriple)
|
||||
comp.writeChunk(0, index.toDU8)
|
||||
|
||||
proc varStatement(comp: Compiler) =
|
||||
let globalIndex = comp.parseVariable("Expect variable name.")
|
||||
|
|
|
@ -8,8 +8,8 @@ const debugVM* = false
|
|||
const debugScanner* = false
|
||||
const debugCompiler* = false
|
||||
const debugDumpChunk* = false
|
||||
const assertionsVM* = true # sanity checks in the VM, such as the stack being empty at the end
|
||||
const assertionsCompiler* = true # sanity checks in the compiler
|
||||
const assertionsVM* = false # sanity checks in the VM, such as the stack being empty at the end
|
||||
const assertionsCompiler* = false # sanity checks in the compiler
|
||||
|
||||
# choose a line editor for the repl
|
||||
const lineEditor = leRdstdin
|
||||
|
|
24
vm.nim
24
vm.nim
|
@ -55,11 +55,11 @@ proc advance(vm: VM): uint8 =
|
|||
vm.line = vm.chunk.lines[vm.ii-1]
|
||||
vm.chunk.code[vm.ii-1]
|
||||
|
||||
proc readTriple(vm: VM): int =
|
||||
[vm.advance, vm.advance, vm.advance].toInt
|
||||
proc readDU8(vm: VM): int =
|
||||
[vm.advance, vm.advance].toInt
|
||||
|
||||
proc readConstant(vm: VM): KonValue =
|
||||
let index = vm.readTriple()
|
||||
let index = vm.readDU8()
|
||||
vm.chunk.constants[index]
|
||||
|
||||
proc binary(op: OpCode, left: KonValue, right: KonValue): KonValue =
|
||||
|
@ -94,7 +94,7 @@ proc run*(vm: VM): InterpretResult =
|
|||
msg &= &"{e} "
|
||||
msg &= "]"
|
||||
echo msg
|
||||
|
||||
{.computedgoto.} # See https://nim-lang.org/docs/manual.html#pragmas-computedgoto-pragma
|
||||
case ins:
|
||||
of opConstant:
|
||||
let val: KonValue = vm.readConstant()
|
||||
|
@ -103,7 +103,7 @@ proc run*(vm: VM): InterpretResult =
|
|||
let val = vm.pop.negate
|
||||
if not vm.pushSafe(val):
|
||||
break
|
||||
of {opAdd, opSubtract, opMultiply, opDivide}:
|
||||
of opAdd, opSubtract, opMultiply, opDivide:
|
||||
let right = vm.pop()
|
||||
let left = vm.pop()
|
||||
if not vm.pushSafe(binary(ins, left, right)):
|
||||
|
@ -156,24 +156,24 @@ proc run*(vm: VM): InterpretResult =
|
|||
of opPop:
|
||||
discard vm.pop()
|
||||
of opGetLocal:
|
||||
let slot = vm.readTriple()
|
||||
let slot = vm.readDU8()
|
||||
vm.push(vm.stack[slot + frameBottom])
|
||||
of opSetLocal:
|
||||
let slot = vm.readTriple()
|
||||
let slot = vm.readDU8()
|
||||
vm.stack[slot + frameBottom] = vm.peek()
|
||||
of opJumpIfFalse:
|
||||
let offset = vm.readTriple()
|
||||
let offset = vm.readDU8()
|
||||
if vm.peek.isFalsey:
|
||||
vm.ii += offset
|
||||
of opJumpIfFalsePop:
|
||||
let offset = vm.readTriple()
|
||||
let offset = vm.readDU8()
|
||||
if vm.pop.isFalsey:
|
||||
vm.ii += offset
|
||||
of opJump:
|
||||
let offset = vm.readTriple()
|
||||
let offset = vm.readDU8()
|
||||
vm.ii += offset
|
||||
of opLoop:
|
||||
let offset = vm.readTriple()
|
||||
let offset = vm.readDU8()
|
||||
vm.ii -= offset
|
||||
of opCall:
|
||||
# create the call env
|
||||
|
@ -181,7 +181,7 @@ proc run*(vm: VM): InterpretResult =
|
|||
# ... <funct obj> <arg1> <arg2> <arg3>
|
||||
# opCall converts it to this
|
||||
# ... <ret val> <arg1> <arg2> <arg3>
|
||||
let argcount = vm.readTriple()
|
||||
let argcount = vm.readDU8()
|
||||
let funct = vm.stack[vm.stack.high - argcount]
|
||||
if funct.konType != ktFunct:
|
||||
vm.runtimeError("Attempt to call a non-funct (a defunct?).") # here is a bad defunct joke
|
||||
|
|
Loading…
Reference in New Issue