Skip to content

Instantly share code, notes, and snippets.

@Maxdamantus
Created July 23, 2011 05:49
Show Gist options
  • Save Maxdamantus/1101078 to your computer and use it in GitHub Desktop.
Save Maxdamantus/1101078 to your computer and use it in GitHub Desktop.
jsdis; Dis Virtual Machine implemented in JavaScript .. moved to https://github.com/Maxdamantus/jsdis
implement AltTest;
include "sys.m";
include "draw.m";
AltTest: module {
init: fn(c: ref Draw->Context, a: list of string);
};
sys: Sys;
init(x: ref Draw->Context, y: list of string){
sys = load Sys Sys->PATH;
# spawn rng(d := chan of int);
# for(;;)
# sys->print("%d\n", <-d);
# sys->print("%d\n", <-d);
# sys->print("%d\n", <-d);
# spawn loop(10000000, a := chan of int);
# spawn loop(1000000, b := chan of int);
# spawn loop(100000, c := chan of int);
# spawn w(a := chan of int);
# spawn w(b := chan of int);
# spawn w(c := chan of int);
a := chan of int;
b := chan of int;
c := chan of int;
d := chan of int;
e := chan of int;
spawn w(a, e);
spawn w(b, e);
<-e; <-e;
sys->print("about to alt\n");
#for(;;)
alt{
<-c =>
sys->print("got c\n");
<-a =>
sys->print("got a\n");
<-b =>
sys->print("got b\n");
}
}
w(g: chan of int, e: chan of int){
if(e != nil)
spawn w(e, nil);
g<- = 42;
}
#se(s: string): int{
# sys->print("%s\n", s);
# return 0;
#}
loop(n: int, c: chan of int){
while(n > 0)
c<- = n--;
}
#rng(c: chan of int){
# c<- = 42;
# c<- = 43;
# for(;;)
# alt{
# c<- = 0 => sys->print("what");
# c<- = 1 => sys->print("what");
# c<- = 2 => sys->print("what");
# c<- = 3 => sys->print("what");
# c<- = 4 => sys->print("what");
# c<- = 5 => sys->print("what");
# c<- = 6 => sys->print("what");
# c<- = 7 => sys->print("what");
# c<- = 8 => sys->print("what");
# c<- = 9 => sys->print("what");
# }
#}
var test = snarf("AltTest.dis");
function showstuff(s){
var r = "", i;
if(typeof s == "object"){
if(s instanceof Array){
for(i = 0; i < s.length; i++)
r += showstuff(s[i]) + ", ";
return "[" + r + "]";
}
for(i in s)
r += i + ": " + showstuff(s[i]) + ", ";
return "{" + r + "}";
}
return s;
}
function replicate(n, f){
var r = [];
while(n-- > 0)
r.push(f());
return r;
}
var dis = function(){
var builtin;
function comp(i, n){
return n == 32? i | 0 :
n < 32? i < 1 << n-1? i : i - (1 << n) :
i < Math.pow(2, n-1)? i : i - Math.pow(2, n);
}
function read(s){
var i = 0;
function byte(){
return s.charCodeAt(i++);
}
function chunk(l){
i += l;
return s.substr(i - l, l);
}
function bigend32(){
return byte() << 24 | byte() << 16 | byte() << 8 | byte();
}
function utf8(){
var x = i;
for(; s.charAt(i) != "\u0000"; i++);
return s.substr(x, i++ - x);
}
// TODO: ieee754
function header(){
var r = {};
r.magic = op();
if(r.magic == 923426)
r.signature = chunk(op());
r.runtime_flag = op();
r.stack_extent = op();
r.code_size = op();
r.data_size = op();
r.type_size = op();
r.link_size = op();
r.entry_pc = op();
r.entry_type = op();
return r;
}
// operand = [] | [immed] | [ind, isfp] | [ind1, ind2, isfp]
// [code, mid_operand, left_operand, right_operand]
function instruction(){
print("ins at " + i);
var opcode = byte(), addrmode = byte(), amm, amsd, r, x;
r = [opcode];
amm = addrmode >> 6;
amsd = [addrmode >> 3 & 7, addrmode & 7];
r.push(
amm == 0? [] :
amm == 1? [op()] :
[op(), !(amm & 1)]);
for(x = 0; x < 2; x++)
r.push(
amsd[x] == 3 || amsd[x] > 5? [] :
amsd[x] == 2? [op()] :
amsd[x] >> 1? [op(), op(), amsd[x] & 1] :
[op(), !!(amsd[x] & 1)]);
return r;
}
function type(){
var num = op(), size = op(), ptrs = op();
return { desc_number: num, size: size, number_ptrs: ptrs,
map: Array.prototype.map.call(chunk(ptrs), function(c){ return c.charCodeAt(0); }) };
}
function datum(){
print("data at " + i.toString(16));
var code = byte(), count, offset, s, t;
count = code & 15? code & 15 : op();
offset = op();
if(code >> 4 == 7)
return { type: 7, data: count };
switch(code >> 4){
case 1:
return { type: "bytes", offset: offset, data: replicate(count, byte) };
case 2:
return { type: "words", offset: offset, data: replicate(count, bigend32) };
case 3:
// should I encode this into JS' UTF-16?
return { type: "string", offset: offset, data: chunk(count) };
case 4:
return { type: "ieee754", offset: offset, data: replicate(count, ieee754) };
case 5:
return { type: "array", offset: offset, data: replicate(count, function(){
return replicate(2, bigend32);
}) };
case 6:
/* wtf */
return { type: "index" };
case 7:
return { type: "pop", offset: offset, count: count };
case 8:
return { type: "longs", offset: offset, data: replicate(count, function(){
return replicate(8, byte);
}) };
}
}
function link(){
return { pc: op(), type: op(), sig: bigend32(), name: utf8() };
}
function moduleimport(){
function functionimport(){
print("functionimport @ " + i.toString(16));
return { sig: bigend32(), name: utf8() };
}
var t = replicate(op(), functionimport);
print("moduleimport() = " + showstuff(t));
return t;
}
function all(){
var code, types, data = [], name, links, imports, head = header(), x;
code = replicate(head.code_size, instruction);
types = replicate(head.type_size, type);
while(byte()){
i--;
data.push(datum());
}
name = utf8();
links = replicate(head.link_size, link);
imports = replicate(op(), moduleimport);
print("read all: " + i.toString(16));
return { name: name, header: head, code: code, types: types, data: data, links: links, imports: imports };
}
function op(){
var b = byte();
if((b & 128) == 0)
return comp(b & 127, 7);
if((b & (128 | 64)) == 128)
return comp((b & 63) << 8 | byte(), 14);
return comp((b & 63) << 24 | byte() << 16 | byte() << 8 | byte(), 30);
}
return all();
}
function quotes(s){
// TODO: ..
return s.toSource();
}
function makemp(data){
var mp = [], ins, x, y, m;
for(x = 0; x < data.length; x++)
switch((ins = data[x]).type){
case "bytes":
case "words":
m = ins.type == "words"? 4 : 1;
for(y = 0; y < ins.data.length; y++)
mp[ins.offset + y*m] = ins.data[y];
break;
case "string":
mp[ins.offset] = ins.data;
break;
case "ieee754":
// TODO: ..
break;
case "array":
for(y = 0; y < ins.data.length; y++)
mp[ins.offset + y*4] = [0, ins.data[1], []];
break;
case "set":
// TODO: ?!#
break;
case "pop":
// TODO: ?!#
break;
case "longs":
// TODO: 0xff << 24 < 0
for(y = 0; y < ins.data.length; y++)
mp[ins.offset + y*8] = [
ins.data[y][4] << 24 | ins.data[y][5] << 16 | ins.data[y][6] << 8 | ins.data[y][7],
ins.data[y][0] << 24 | ins.data[y][1] << 16 | ins.data[y][2] << 8 | ins.data[y][3]];
}
print("mp = " + mp.toSource());
return mp;
}
function insc(s, p, c){
return s.substr(0, p) + String.fromCharCode(c) + s.substr(p + 1);
}
var procs = [];
function start(module){
procs.push(function(){
return module([{ name: "init", sig: 0x4244b354 }])[0]([0,[]]);
});
}
// keep calling this until it returns 0
function run(){
var r, n;
if(procs.length > 0)
if(r = procs[n = Math.random()*procs.length | 0]())
procs[n] = r;
else
rem(procs, n);
return procs.length;
}
function rem(arr, n){
if(n == arr.length - 1)
arr.pop();
else
arr[n] = arr.pop();
}
function runall(){
while(run() > 0);
}
function spawner(fun){
return procs.push(fun) - 1;
}
function crem(arr, n, s){
print("crem(" + s + "); arr.length = " + arr.length + "; n = " + n);
var x;
for(x = 0; x < arr.length; x++)
print("crem: arr[" + x + "][2] = " + arr[x][2]);
if(n == arr.length - 1)
arr.pop();
else{
print("arr[" + n + "] = arr.pop()");
arr[n] = arr.pop();
print("arr[" + n + "][2] = n");
arr[n][2] = n;
}
}
var channelc = 0;
function channel(){
var cid = channelc++;
var receivers = [], senders = [];
function recv(ptr, cont){
var n;
if(senders.length){
ptr[1][ptr[0]] = senders[n = Math.random()*senders.length | 0][0];
print("removing senders[" + n + "]");
procs.push(senders[n][1]);
if(cont)
procs.push(cont);
crem(senders, n, "crem receivers, cid = " + cid);
}else{
print("receivers.push (cid = " + cid + ") = " +
receivers.push(n = [ptr, cont, receivers.length]));
return function(){
crem(receivers, n[2], "crem receivers, cid = " + cid);
};
}
}
function send(val, cont){
var n, ptr;
if(receivers.length){
ptr = receivers[n = Math.random()*receivers.length | 0][0];
print("removing receivers[" + n + "]");
ptr[1][ptr[0]] = val;
procs.push(receivers[n][1]);
if(cont)
procs.push(cont);
crem(receivers, n, "crem receivers, cid = " + cid);
}else{
print("senders.push (cid = " + cid + ") = " +
senders.push(n = [val, cont, senders.length]));
return function(){
crem(senders, n[2], "crem receivers, cid = " + cid);
};
}
}
function recvpoll(){
print("recvpoll() = " + senders.length);
return senders.length;
}
function sendpoll(){
print("sendpoll() = " + receivers.length);
return receivers.length;
}
return [send, recv, sendpoll, recvpoll];
}
function alt(ptr, dst, cont){
var ns = ptr[1][ptr[0]], nr = ptr[1][ptr[0] + 4], aborts = [], ready, x, t, c;
print("alt; ns = " + ns + "; nr = " + nr);
function abortfn(n){
return function(){
print("abort; n = " + n);
abortfnd(n);
dst[1][dst[0]] = n;
procs.push(cont);
};
}
function abortfnd(n){
print("abortfnd(" + n + "); aborts.length = " + aborts.length);
var x;
for(x = aborts.length - 1; x >= 0; x--)
if(x != n){
print("aborts[" + x + "]()");
aborts[x]();
}
}
// hopefully these are actually channels and pointers
for(x = 0; x < ns + nr; x++){
print("alt.for");
t = ptr[1][ptr[0] + 8 + x*8 + 4]; // val pointer
c = ptr[1][ptr[0] + 8 + x*8];
if(c[x < ns? 2 : 3]()){
print("alt.for.if1");
if(aborts){
print("alt.for.if1.if");
abortfnd(-1);
aborts = undefined;
ready = [];
}
ready.push(x);
}else if(aborts){
print("alt.for.if2");
if(x < ns)
aborts.push(c[0](t[1][t[0]], abortfn(x)));
else
aborts.push(c[1](t, abortfn(x)));
}
}
if(ready){
print("** ready");
x = Math.floor(Math.random() * ready.length);
t = ptr[1][ptr[0] + 8 + x*8 + 4];
c = ptr[1][ptr[0] + 8 + x*8];
if(x < ns)
c[0](t[1][t[0]], cont);
else
c[1](t, cont);
dst[1][dst[0]] = x;
}
}
// loader :: (string, [importing]) -> [exporting]
function loader(name, imports){
if(name[0] == "$")
return builtin[name.substr(1)](imports);
// wonder what will go here
}
function exporter(importing, exporting, main){
var r = [], x, y;
for(x = 0; x < importing.length; x++)
for(y = 0; y < exporting.length; y++){
if(importing[x].name == exporting[y].name && importing[x].sig == exporting[y].sig){
print("exporter matched " + importing[x].name);
r[x] = function(pc){
return function(fp, ret){
return main([false, [0, []], pc], ret);
};
}(exporting[y].pc);
break;
}
throw "module has no export (" + importing[x].name + ", " + importing[x].sig.toString(16) + ")";
}
return r;
}
function getargs(fp){
var x = 32;
function get(sz){
return function(){
for(; x % sz; x++);
x += sz;
return fp[1][fp[0] + x - sz];
};
}
return {
word: get(4),
byte: get(1),
dword: get(8),
};
}
function pointer(base, offs){
return {
base: base, offs: offs,
toString: function(){
return base + "[1][" + base + "[0] + " + offs + "]";
},
addrof: function(){
return "[" + offs + " + " + base + "[0], " + base + "[1]]"
}
};
}
// module interface:
// module = ([importing]) -> [exporting]
// importing = { name: string, sig: int }
// exporting = (frame /* fp for the call */, return /* returned after fibre's last ret */) -> exporting
// return = () -> exporting
// the exporting function returns a continuation
// inter-module calls use exporting functions
function compile(source){
function operand(ins, i, addrof){
var n = ins[i + 1], j;
switch(n.length){
case 0:
if(i == 0)
return operand(ins, 2);
throw "expected operand";
case 1:
if(addrof)
throw "address of immediate";
return "" + n[0];
case 2:
j = pointer(n[1]? "fp" : "mp", n[0]);
return addrof? j.addrof() : j.toString();
i = n[1]? "fp" : "mp";
return addrof? "[" + n[0] + " + " + i + "[0], " + i + "[1]]" : i + "[1][" + i + "[0] + " + n[0] + "]";
case 3:
j = pointer(n[2]? "fp" : "mp", n[0]);
j = pointer(j, n[1]);
return addrof? j.addrof() : j.toString();
j = n[2]? "fp" : "mp";
i = j + "[1][" + j + "[0] + " + n[0] + "]";
return addrof? "[" + j + "[0] + " + n[1] + ", " + j + "[1]]" :
i + "[1][" + n[1] + " + " + i + "[0]]";
// return (n[2]? "fp" : "mp") + "[" + n[0] + "][" + n[1] + "]";
}
}
var code = [], x, y, m, ins;
code.push("return function(importing){");
code.push("var mp = [0, newmp()], tmp, tmq, tmr;");
code.push("function main(fps, ret){");
code.push(" var fp = fps[1], pc = fps[2], ic;");
code.push(" for(ic = 0; ic++ < 10000;) switch(pc){");
for(x = 0; x < source.code.length; x++){
code.push(" case " + x + ":");
code.push(" print(\"pc = " + x + "\");");
print("ins = " + showstuff(source.code[x]));
switch((ins = source.code[x])[0]){
case 0x00: // nop
break;
case 0x01: // alt
code.push(" fps[2] = " + (x + 1) + ";");
code.push(" alt(" + operand(ins, 1, true) + ", " + operand(ins, 2, true) + ", function(){");
code.push(" return main(fps, ret);");
code.push(" });");
code.push(" return;");
break;
case 0x03: // goto
code.push(" pc = " + operand(ins, 2, true) + ";");
code.push(" pc = pc[1][pc[0] + " + operand(ins, 1) + "*4];");
code.push(" print(\"mov -> \" + pc);");
code.push(" break;");
break;
case 0x04: // call
code.push(" fps[2] = " + (x + 1) + ";");
code.push(" fps = [fps, fp = " + operand(ins, 1) + ", pc = " + operand(ins, 2) + "];");
code.push(" break;");
break;
case 0x05: // frame
code.push(" " + operand(ins, 2) + " = [0, []];");
break;
case 0x06: // spawn
code.push(" void function(nfps){");
code.push(" spawner(function(){");
code.push(" return main(nfps);");
code.push(" });");
code.push(" }([false, " + operand(ins, 1) + ", " + operand(ins, 2) + "]);");
break;
case 0x08: // load
code.push(" " + operand(ins, 2) + " = loader(" + operand(ins, 1) + ", imports[" + operand(ins, 0) + "]);");
break;
case 0x09: // mcall
code.push(" fps[2] = " + (x + 1) + ";");
code.push(" return function(n, f){");
code.push(" return function(){");
code.push(" return n(f, function(){");
code.push(" return main(fps, ret);");
code.push(" });");
code.push(" };");
code.push(" }(" + operand(ins, 2) + "[" + operand(ins, 0) + "], " + operand(ins, 1) + ");");
break;
case 0x0c: // ret
code.push(" if(!(fps = fps[0]))");
code.push(" return ret;");
code.push(" fp = fps[1];");
code.push(" pc = fps[2];");
code.push(" break;");
break;
case 0x0d: // jmp
code.push(" pc = " + operand(ins, 2) + ";");
code.push(" break;");
break;
case 0x0f: // exit
code.push(" return;");
break;
case 0x11: // newa
code.push(" " + operand(ins, 2) + " = [0, " + operand(ins, 1) + ", []];");
break;
case 0x8e: // consl
case 0x1a: // consb
case 0x1b: // consw
case 0x1c: // consp
case 0x1d: // consf
case 0x1e: // consm
case 0x1f: // consmp
// Should I add a length element?
code.push(" " + operand(ins, 2) + " = [" + operand(ins, 1) + ", " + operand(ins, 2) + "];");
break;
case 0x20: // headb
case 0x21: // headw
case 0x22: // headp
case 0x23: // headf
case 0x24: // headm
case 0x25: // headmp
case 0x8d: // headl
code.push(" " + operand(ins, 2) + " = " + operand(ins, 1) + "[0];");
break;
case 0x26: // tail
code.push(" " + operand(ins, 2) + " = " + operand(ins, 1) + "[1];");
break;
case 0x56: // lenl
code.push(" for(tmp = 0, tmq = " + operand(ins, 1) + "; tmq; tmp++, tmq = tmq[1]);");
code.push(" " + operand(ins, 2) + " = tmp;");
code.push(" tmq = undefined;");
break;
case 0x12: // newcb
case 0x13: // newcw
case 0x14: // newcf
case 0x15: // newcp
case 0x16: // newcm
case 0x17: // newcmp
case 0x8f: // newcl
code.push(" " + operand(ins, 2) + " = channel();");
break;
case 0x18: // send
code.push(" fps[2] = " + (x + 1) + ";");
code.push(" " + operand(ins, 2) + "[0](" + operand(ins, 1) + ", function(){");
code.push(" return main(fps, ret);");
code.push(" });");
code.push(" return;");
break;
case 0x19: // recv
code.push(" fps[2] = " + (x + 1) + ";");
code.push(" " + operand(ins, 1) + "[1](" + operand(ins, 2, true) + ", function(){");
code.push(" return main(fps, ret);");
code.push(" });");
code.push(" return;");
break;
case 0x27: // lea
code.push(" " + operand(ins, 2) + " = " + operand(ins, 1, true) + ";");
break;
// the following seems weird .. documentation suggests
// indw, etc grab the value from the array; behaviour
// suggests it grabs the address, like indx
case 0x28: // indx
case 0x52: // indc
case 0x72: // indw
case 0x73: // indf
case 0x74: // indb
case 0x91: // indl
// TODO: multiply index by element size .. maybe
code.push(" tmp = " + operand(ins, 1) + ";");
code.push(" " + operand(ins, 0) + " = [tmp[0] + " + operand(ins, 2) + ", tmp[2]];");
break;
case 0x29: // movp
case 0x2a: // movm
case 0x2b: // movmp
case 0x2c: // movb
case 0x2d: // movw
case 0x2e: // movf
case 0x76: // movl
code.push(" " + operand(ins, 2) + " = " + operand(ins, 1) + ";");
break;
case 0x3a: // addw
case 0x53: // addc
case 0x39: // addb
case 0x3b: // addf
code.push(" " + operand(ins, 2) + " = " + operand(ins, 0) + " + " + operand(ins, 1) + ";");
break;
case 0x77: // addl
// TODO: check logic .. negatives?
code.push(" tmp = (" + operand(ins, 1) + "[0] + " + operand(ins, 0) + "[0]) % 0x100000000;");
code.push(" " + operand(ins, 2) + " = [tmp, (tmp < " + operand(ins, 1) + "[0]? 1 : 0) + " +
operand(ins, 1) + "[1] + " + operand(ins, 0) + "[1]];");
break;
case 0x78: // subl
case 0x3c: // subb
case 0x3d: // subw
case 0x3e: // subf
// TODO: long
code.push(" " + operand(ins, 2) + " = " + operand(ins, 0) + " - " + operand(ins, 1) + ";");
break;
case 0x51: // insc
code.push(" " + operand(ins, 2) + " = insc(" + operand(ins, 2) + ", " + operand(ins, 0) + ", " + operand(ins, 1) + ");");
break;
case 0x5a: // bleb
case 0x60: // blew
case 0x66: // blef
case 0x6c: // blec
case 0x83: // blel
case 0x62: // bgew
case 0x85: // bgel
case 0x68: // bgef
case 0x6e: // bgec
case 0x5c: // bgeb
case 0x61: // bgtw
case 0x84: // bgtl
case 0x67: // bgtf
case 0x6d: // bgtc
case 0x5b: // bgtb
case 0x81: // bnel
case 0x64: // bnef
case 0x6a: // bnec
case 0x58: // bneb
case 0x5e: // bnew
// TODO: handle blel
code.push(" if(" + operand(ins, 1) + " " +
([0x5a, 0x60, 0x66, 0x6c, 0x83].indexOf(ins[0]) >= 0? "<=" :
[0x62, 0x85, 0x68, 0x6e, 0x5c].indexOf(ins[0]) >= 0? ">=" :
[0x61, 0x84, 0x67, 0x6d, 0x5b].indexOf(ins[0]) >= 0? ">" :
"!=") +
" " + operand(ins, 0) + "){");
code.push(" pc = " + operand(ins, 2) + ";");
code.push(" break;");
code.push(" }");
break;
case 0x55: // lena
code.push(" " + operand(ins, 2) + " = " + operand(ins, 1) + "[1];");
break;
case 0x63: // beqf
case 0x86: // beql
case 0x69: // beqc
case 0x57: // beqb
case 0x5d: // beqw
if(ins[0] == 0x86) // blel
code.push(" if(" + operand(ins, 1) + "[0] == " + operand(ins, 0) + "[0] && " +
operand(ins, 1) + "[1] == " + operand(ins, 0) + "[1]){");
else
code.push(" if(" + operand(ins, 1) + " == " + operand(ins, 0) + "){");
code.push(" pc = " + operand(ins, 2) + ";");
code.push(" break;");
code.push(" }");
break;
case 0x6f: // slicea
code.push(" tmp = " + operand(ins, 2) + ";");
code.push(" tmq = " + operand(ins, 1) + ";");
code.push(" " + operand(ins, 2) + " = [tmp[0] + tmq, " + operand(ins, 0) + " - tmq, tmp[2]];");
break;
default:
code.push(" // unknown instruction: " + ins[0].toString(16));
}
}
code.push(" default:");
code.push(" throw \"pc out of bounds\";");
code.push(" }");
code.push("fps[2] = 0;");
code.push("return function(){ return main(fps, ret); };");
code.push("}");
code.push("return exporter(importing, exports, main);");
code.push("}");
//return code.join("\n");
print(code.join("\n"));
return Function("exports", "entry", "imports", "exporter", "loader", "spawner", "channel", "insc", "alt", "newmp", code.join("\n"))(
source.links,
source.entry_pc,
source.imports,
exporter,
loader,
spawner,
channel,
insc,
alt,
function(data){ // trying not to keep a reference to `source`
return function newmp(){
return makemp(data);
};
}(source.data));
}
builtin = {
Sys: function(importing){
var x, ret = [];
for(x = 0; x < importing.length; x++)
if(importing[x].name == "print" && importing[x].sig == comp(0xac849033, 32))
ret[x] = function(fp, cont){
// print("fp = " + fp.toSource());
print("sys->print: " + printx(getargs(fp)));
return cont;
};
else
throw "requested invalid export (" + importing[x].name + ", " + importing[x].sig + ") from $Sys";
return ret;
}
};
function printx(args){
var fmt = args.word(), p, c, done, isbig, out = [];
for(p = 0; (c = fmt.indexOf("%", p)) >= 0; p = c){
out.push(fmt.substr(p, c - p));
isbig = false;
for(done = false; !done && c < fmt.length;)
switch(fmt[++c]){
case "s":
out.push(args.word());
done = true;
break;
case "d":
if(isbig)
out.push(args.dword()); // TODO: ..
else
out.push(args.word() | 0);
done = true;
break;
case "b":
isbig = true;
break;
case "%":
out.push("%");
done = true;
break;
}
c++;
}
out.push(fmt.substr(p));
return out.join("");
}
var t;
print(showstuff(t = read(test)));
/*print*/(showstuff(t = compile(t)));
start(t);
runall();
}();
implement ListTest;
include "sys.m";
include "draw.m";
sys: Sys;
ListTest: module {
init: fn(c: ref Draw->Context, a: list of string);
};
init(c: ref Draw->Context, a: list of string){
sys = load Sys Sys->PATH;
l := 42 :: 43 :: nil;
m := l;
m = tl m;
sys->print("%d %d %d\n", hd l, hd tl l, hd m);
}
implement RandTest;
include "sys.m";
include "draw.m";
sys: Sys;
RandTest: module {
init: fn(c: ref Draw->Context, a: list of string);
};
init(c: ref Draw->Context, a: list of string){
sys = load Sys Sys->PATH;
test := array[1000] of int;
for(i := 0; i < len test; i++)
test[i] = i;
randomise(test);
sys->print("before:\n");
printarr(test);
parasort(test, nil);
sys->print("after:\n");
printarr(test);
}
randomise(arr: array of int){
c := chan of int;
d := chan of int;
for(i := 0; i < len arr; i++)
spawn get(arr, i, c, d);
for(i = 0; i < len arr; i++)
<-d;
for(i = 0; i < len arr; i++)
arr[i] = <-c;
}
get(arr: array of int, i: int, c: chan of int, d: chan of int){
t := arr[i];
d<- = 0;
c<- = t;
}
printarr(arr: array of int){
for(x := 0; x < len arr; x++)
sys->print("[%d] = %d\n", x, arr[x]);
}
swap(arr: array of int, m: int, n: int){
t := arr[m];
arr[m] = arr[n];
arr[n] = t;
}
parasort(arr: array of int, notify: chan of int){
if(len arr == 2){
if(arr[0] > arr[1])
swap(arr, 0, 1);
}else if(len arr > 2){
pv := arr[store := 0];
swap(arr, len arr - 1, 0);
for(x := 0; x < len arr - 1; x++)
if(arr[x] < pv)
swap(arr, x, store++);
swap(arr, store, len arr - 1);
c := chan of int;
spawn parasort(arr[0:store], c);
spawn parasort(arr[store+1:], c);
<-c; <-c;
}
if(notify != nil)
notify<- = 0;
}
implement RefTest;
include "sys.m";
include "draw.m";
sys: Sys;
RefTest: module {
init: fn(c: ref Draw->Context, a: list of string);
};
w := big 0;
s := 0;
init(c: ref Draw->Context, a: list of string){
sys = load Sys Sys->PATH;
x := "hello";
x[1] = 'i';
x[5] = 's';
x[5] = 't';
y := array[2] of int;
y[0] = 42;
y[1] = 43;
z := sys->print("%s %bd %d!\n", x, big 1234567, add(y[0], y[1]));
z++;
# if(w++ != big 5)
# init(c, a);
# spawn th1();
# spawn th2();
d := chan of int;
spawn chantest(d);
# spawn thread();
# while(s != 1234);
sys->print("end!!");
sys->print("%d\n", <-d);
test := array[10] of int;
for(i := 0; i < len test; i++)
test[i] = i;
randomise(test);
printarr(test);
}
add(a, b: int): int {
return a + b;
}
thread(){
s = 1234;
}
randomise(arr: array of int){
c := chan of int;
for(i := 0; i < len arr; i++)
spawn put(arr, i, c);
for(i = 0; i < len arr; i++)
c<- = arr[i];
}
put(arr: array of int, i: int, c: chan of int){
arr[i] = <-c;
}
chantest(a: chan of int){
a<- = 42;
}
th1(){
for(;;)
sys->print("thread1!");
}
th2(){
for(;;)
sys->print("thread2!");
}
printarr(arr: array of int){
for(x := 0; x < len arr; x++)
sys->print("[%d] = %d\n", x, arr[x]);
}
swap(arr: array of int, m: int, n: int){
t := arr[m];
arr[m] = arr[n];
arr[n] = t;
}
parasort(arr: array of int, notify: chan of int){
if(len arr < 3){
if(arr[0] > arr[1])
swap(arr, 0, 1);
}else{
pv := arr[store := 0];
for(x := 0; x < len arr; x++)
if(arr[x] <= pv)
swap(arr, x, store++);
c := chan of int;
spawn parasort(arr[0:pv], c);
spawn parasort(arr[pv+1:], c);
<-c; <-c;
}
if(notify != nil)
notify<- = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment