This commit is contained in:
Daniella / Tove 2022-02-23 17:20:09 +01:00
commit a133ab8c55
4 changed files with 264 additions and 52 deletions

View file

@ -2,3 +2,7 @@
Improved Stack-Based Programming Language
Incomplete, not currently compilable!
JS Bootstrap is very, very, very DIRTY! Do not use it to run anything but
the compiler until the compiler is fully finished and can compile itself!!!
A pre-compiled compiler will be added as bootstrap as soon as possible.

View file

@ -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]);
}

View file

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

View file

@ -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,59 +23,58 @@ 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
# "call a dynamically computed function" pop
# "Please keep in mind that this will throw a native error if" pop
# "called incorrectly - this means wrong layer parameter will" pop
# "instantly crash the program." pop
native func _layer_call
native _layer_call
func call {
0 _layer_call
}
native func typename
native func istype
native func settype
native func throw
native include
native putchar
native read
native flength
native write
native type
native mktype
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