RosettaCodeData/Task/Compiler-virtual-machine-interpreter/J/compiler-virtual-machine-interpreter-1.j
2023-07-01 13:44:08 -04:00

76 lines
1.9 KiB
Text

(opcodes)=: opcodes=: ;:{{)n
fetch store push add sub mul div mod lt gt le ge
eq ne and or neg not jmp jz prtc prts prti halt
}}-.LF
unpack=: {{
lines=. <;._2 y
'ds0 ds s0 s'=.;:0{::lines
assert.'Datasize:Strings:'-:ds0,s0
vars=: (".ds)#0
strings=: rplc&('\\';'\';'\n';LF)L:0 '"'-.L:0~(1+i.".s){lines
object=: ;xlate L:1 (;:'()[]') -.~L:1 ;:L:0 '-_' rplc~L:0 (1+".s)}.lines
outbuf=: stack=: i.0
}}
xlate=: {{
if.2<#y do.
(opcodes i. 1{y),(4#256)#:".2{::y
else.
opcodes i. 1{y
end.
}}
NB. ensure we maintain 32 bit signed int representation
signadj=: _2147483648+4294967296|2147483648+]
getint=: signadj@(256 #. ])
PUSH=: {{ stack=:stack,signadj y }}
POP=: {{ (stack=: _1 }. stack) ] _1 { stack }}
POP2=: {{ (stack=: _2 }. stack) ] _2 {. stack }}
emit=:{{
outbuf=: outbuf,y
if.LF e. outbuf do.
ndx=. outbuf i:LF
echo ndx{.outbuf
outbuf=: }.ndx}.outbuf
end.
}}
run_vm=: {{
unpack y
stack=: i.pc=:0
lim=. <:#object
while.do.
pc=: pc+1 [ op=: (pc { object){opcodes
i=. getint (lim<.pc+i.4) { object
k=. 0
select.op
case.fetch do. k=.4 [PUSH i{vars
case.store do. k=.4 [vars=: (POP'') i} vars
case.push do. k=.4 [PUSH i
case.add do. PUSH +/POP2''
case.sub do. PUSH -/POP2''
case.mul do. PUSH */POP2''
case.div do. PUSH<.%/POP2''
case.mod do. PUSH |~/POP2''
case.lt do. PUSH </POP2''
case.le do. PUSH <:/POP2''
case.eq do. PUSH =/POP2''
case.ne do. PUSH ~:/POP2''
case.ge do. PUSH >:/POP2''
case.gt do. PUSH >/POP2''
case.and do. PUSH */0~:POP2''
case.or do. PUSH +./0~:POP2''
case.neg do. PUSH -POP''
case.not do. PUSH 0=POP''
case.jmp do. k=. i
case.jz do. k=. (0=POP''){4,i
case.prtc do. emit u:POP''
case.prts do. emit (POP''){::strings
case.prti do. emit rplc&'_-'":POP''
case.halt do. if.#outbuf do.echo outbuf end.EMPTY return.
end.
pc=: pc+k
end.
}}