|
str=JSON.stringify; |
|
println=console.log.bind(console.log); |
|
|
|
parse = require('sexpr').parse |
|
|
|
var gensym = function(){ return "_"+(___N+=1) }, ___N = 99 |
|
|
|
function len(arr){return arr.length} |
|
function push(arr,x){arr.push(x)} |
|
function slice(arr,start){return arr.slice(start)} |
|
function extend(arr,arr2){for(var n in arr2) arr.push(arr2[n])} |
|
|
|
;Asm={ |
|
assemble:function(x){ |
|
Asm.asm(Asm.cmp(parse(x))) |
|
}, |
|
asm:function(x){ |
|
println(".") |
|
for(var n in x){ |
|
var stmt = x[n] |
|
if(stmt[0]=='label') |
|
println(stmt.slice(1).join(' ')+ ":") |
|
else |
|
println("\t"+stmt.join('\t')) |
|
} |
|
}, |
|
cmp:function(x){return{ |
|
value : function(){ |
|
return [[ 'load', slice(x[2],1) ]] |
|
}, |
|
reference : function(){ |
|
return [[ 'refr', slice(x[2],1) ]] |
|
}, |
|
funcall: function(){ |
|
var ret = [], n = len(x) |
|
ret.push([ 'addSP', len(x)-3 ]) |
|
while(--n>2){ |
|
extend(ret, Asm.cmp(x[n])) |
|
ret.push([ 'pushA', n-2 ]) |
|
} |
|
ret.push([ 'callf', x[2][2].slice(1)]) |
|
ret.push([ 'subSP', len(x)-3 ]) |
|
return ret |
|
}, |
|
if : function(){ |
|
var n = 0, ret = [], sym = gensym() |
|
ret.push([ 'label', 'defif' + sym ]) |
|
while((n+=2)<len(x)-1){ |
|
var else_sym = gensym() |
|
extend(ret, Asm.cmp(x[n]) ) |
|
ret.push([ 'ifne', 'elsif' + else_sym ]) |
|
extend(ret, Asm.cmp(x[n+1])) |
|
ret.push([ 'jmp', 'endif' + sym ]) |
|
ret.push([ 'label', 'elsif' + else_sym ]) |
|
} |
|
ret.push([ 'label', 'endif' + sym ]) |
|
return ret |
|
}, |
|
while : function(){ |
|
var n = 2, ret = [], sym = gensym() |
|
ret.push([ 'label', 'deflo' + sym ]) |
|
extend(ret, Asm.cmp(x[2])) |
|
ret.push([ 'ifne', 'endlo' + sym ]) |
|
while(++n<len(x)) |
|
extend(ret, Asm.cmp(x[n])) |
|
ret.push([ 'jmp', 'deflo' + sym ]) |
|
ret.push([ 'label', 'endlo' + sym ]) |
|
return ret |
|
}, |
|
defn : function(){ |
|
var n = 2, ret = [], sym = gensym() |
|
ret.push([ 'label', 'defn_' + sym ]) |
|
ret.push([ 'beginfunc', len(x[2])-1, '; '+str(x[2].slice(1)) ]) |
|
while(++n<len(x)) |
|
extend(ret, Asm.cmp(x[n])) |
|
ret.push([ 'label', 'endfn' + sym ]) |
|
ret.push([ 'finisfunc', len(x[2])-1 ]) |
|
ret.push([ 'ret' ]) |
|
return ret |
|
}, |
|
go : function(){ |
|
return[[ 'jmp', slice(x[2],1) ]] |
|
}, |
|
defvar : function(){ |
|
if(x[3][0]!='$') |
|
return[[ 'label', slice(x[2],1) ], |
|
[ 'dq', slice(x[3],1) ]] |
|
return[[ 'label', '___'+slice(x[2],1) ], |
|
[ 'db', '"'+slice(x[3],1)+'", 0' ], |
|
[ 'dq', len(x[3]) ], |
|
[ 'dq', len(x[3])-1 ], |
|
[ 'label', slice(x[2],1) ], |
|
[ 'dq', '___'+slice(x[2],1) ]] |
|
}, |
|
label : function(){ |
|
return[[ 'label', slice(x[2],1) ]] |
|
}, |
|
}[slice(x[1],1)](x)}} |
|
module.exports=Asm; |