diff --git a/bootstrap/isbpl.js b/bootstrap/isbpl.js index cdd5c99..d018adc 100644 --- a/bootstrap/isbpl.js +++ b/bootstrap/isbpl.js @@ -1,6 +1,204 @@ #!/bin/node -const fs = require('fs') -const process = require('process') +const fs = require('fs'); +const process = require('process'); + +const stack = []; +const vars = [{}]; +const keywords = [ + "native", + "func", + "if", + "def", + "stop", +]; +let insns; +let die = 0; + +const natives = { + "alen": function () { + stack.push(stack.pop().length); + }, + "aget": function () { + let idx = stack.pop(); + let array = stack.pop(); + stack.push(array[idx]); + }, + "aput": function () { + let val = stack.pop(); + let idx = stack.pop(); + let array = stack.pop(); + array[idx] = val; + }, + "anew": function () { + let length = stack.pop(); + let val = stack.pop(); + stack.push(Array.apply(val, Array(length)); + }, + "_char": function () { + stack.push(String.fromCharCode(stack.pop())); + }, + "_int": function () { + stack.push(Number(stack.pop())); + }, + "_file": function () { + stack.push(String(stack.pop())); + }, + "_float": function () { + stack.push(Number(stack.pop())); + }, + "_long": function () { + stack.push(Number(stack.pop())); + }, + "_double": function () { + stack.push(Number(stack.pop())); + }, + "ischar": function () { + let x = stack.pop(); + stack.push(x instanceof String && x.length == 1) + }, + "isint": function () { + let x = stack.pop(); + stack.push(x instanceof Number) + }, + "isfloat": function () { + let x = stack.pop(); + stack.push(x instanceof Number) + }, + "islong": function () { + let x = stack.pop(); + stack.push(x instanceof Number) + }, + "isdouble": function () { + let x = stack.pop(); + stack.push(x instanceof Number) + }, + "putchar": function () { + if(x instanceof String && x.length == 1) + process.stdout.write(x); + else + process.stdout.write(Number(x)) + process.stdout.flush(); + }, + "read": function () { + let filename = stack.pop(); + stack.push(fs.readFileSync(filename, "iso-8859-1")); + }, + "write": function () { + let content = stack.pop(); + let filename = stack.pop(); + fs.writeFileSync(filename, content, { encoding: "iso-8859-1" }); + }, + "flength": function () { + let filename = stack.pop(); + stack.push(fs.statSync(filename).size); + }, + "mktype": function () { + }, + "type": function () { + }, + "call": function () { + resolve(stack.pop(), 0); + }, + "typename": function () { + } +} + +function beginBlock(i) { + if(insns[i++] !== "{") { + console.err("Exoected { at " + insns[i] + " at beginning of block!") + process.exit(1); + } + const finsns = []; + let n = 1; + while(n > 0) { + finsns.push(insns[i]); + if(insns[i] === "{") n++; + if(insns[i] === "}") n--; + i++; + } + finsns.pop(); + return [ + function call () { + for(let j = 0; j < finsns.length; ) { + j = resolve(finsns[j], j); + if(die > 0) { + die--; + return; + } + } + }, + i + ] +} + +function handleKeyword(id, i) { + if(id === "def") { + i++; + vars.peek()[insns[i]] = 0 + vars.peek()["=" + insns[i]] = function set() { + vars.peek()[insns[i]] = stack.pop(); + }; + } + if(id === "native") { + i++; + vars.peek()[insns[i]] = natives[insns[i]]; + } + if(id === "if") { + i++; + const block = beginBlock(); + if(stack.pop()) { + block[0](); + } + i = block[1]; + } + if(id === "func") { + i++; + const block = beginBlock(i); + vars.peek()[insns[i]] = block[0]; + i = block[1]; + } + if(id === "while") { + i++; + const n = i; + // This is needed to set the insn pointer to the right location after the block + let block; + while((function check() { + while(insns[i] !== "{") { + i = resolve(insns[i], i); + } + i--; + return stack.pop() + })()) { + block = block || beginBlock(i); + block[0](); + i = n; + } + block = block || beginBlock(i); + i = block[1]; + } + if(id === "stop") { + die = stack.pop() + } + return i + 1; +} + +function resolve(id, i) { + if(keywords.contains(keywords)) { + return handleKeyword(id, i); + } + let toRun = vars.peek()[id] || vars[0][id]; + if(!toRun) { + console.err("Could not find keyword " + id + "!"); + process.exit(1); + } + else { + toRun(); + } + return ++i; +} +for(let i = 0; i < isns.length; ) { + i = resolve(insns[i]); +} diff --git a/isbpl.isbpl b/isbpl.isbpl index fdf2b7c..b2de30a 100644 --- a/isbpl.isbpl +++ b/isbpl.isbpl @@ -1,7 +1,7 @@ - -"" =insns +def insns func main { # entry point returning int + def insns filename =args # put arg array into args var args 0 aget =filename @@ -12,6 +12,12 @@ func main { # entry point returning int } func compile { + def file + def content + def i + def ln + def j + def c =file # read & split content @@ -49,6 +55,11 @@ func compile { } func mkcode { + def allowfunc + def content + def definefunc + def level + def i =allowfunc =content diff --git a/std.isbpl b/std.isbpl index 931f054..562ffee 100644 --- a/std.isbpl +++ b/std.isbpl @@ -1,18 +1,18 @@ -native func alen -native func aget -native func aput -native func anew -native func _array +native alen +native aget +native aput +native anew +native _array func __array { "NotImplemented" "Not implemented" throw } -native func _char -native func _int -native func _file -native func _float -native func _long -native func _double +native _char +native _int +native _file +native _float +native _long +native _double func __char { _char @@ -23,53 +23,52 @@ func __int { func __file { _file } -native func __float +native __float func __long { _long } -native func __double +native __double -native func ischar -native func isint -native func isfloat -native func islong -native func isdouble +native ischar +native isint +native isfloat +native islong +native isdouble -native func stop -native func include -native func putchar -native func read -native func flength -native func write -native func type -native func mktype +native include +native putchar +native read +native flength +native write +native type +native mktype # call a dynamically computed function -native func call -native func typename -native func istype -native func settype -native func throw +native call +native typename +native istype +native settype # try and catch are keywords, not functions +native throw # storelength -native func stlen +native stlen -native func eq -native func gt -native func lt -native func not -native func or -native func and -native func + -native func - -native func / -native func * -native func ** -native func % -native func ^ +native eq +native gt +native lt +native not +native or +native and +native + +native - +native / +native * +native ** +native % +native ^ -native func dup -native func pop -native func swap +native dup +native pop +native swap "char" mktype =TYPE_CHAR "int" mktype =TYPE_INT