概要
ilasmでstack machineやってみた。
練習問題やってみた。
練習問題
Rustでilasmを実行する、インタープリタを書け。
fizzbuzzを実行せよ。
サンプルコード
const MAXVAL: usize = 10;
fn push(val: &mut [f32; MAXVAL], sp: &mut i32, op: f32) {
if *sp < MAXVAL as i32
{
val[*sp as usize] = op;
*sp += 1;
}
else
{
println!("error: stack full, can't push {}", op);
}
}
fn pop(val: &mut [f32; MAXVAL], sp: &mut i32) -> f32 {
if *sp > 0
{
*sp -= 1;
return val[*sp as usize];
}
else
{
println!("error: stack empty");
return 0.0;
}
}
fn jmp(s: &str, l: &str) -> usize {
let mut pc: usize = 0;
let mut v: Vec<&str> = s.split('\n').collect();
//println!("{:?}", v[0]);
loop
{
let cs: Vec<&str> = v[pc].split_whitespace().collect::<Vec<_>>();
//println!("{:?}", cs);
if cs[0] == format!("{}:", l)
{
break;
}
pc = pc + 1
}
return pc;
}
fn ilasm(s: &str) {
let mut sp: i32 = 0;
let mut n: f32 = 0.0;
let mut i: f32 = 0.0;
let mut pc: usize = 0;
let mut lp: usize = 0;
let mut bu: &str = "";
let mut val: [f32; MAXVAL] = [0.0; MAXVAL];
//println!("{}", s);
let mut v: Vec<&str> = s.split('\n').collect();
//println!("{:?}", v[0]);
loop
{
//println!("{:?}", pc);
if lp > 2500
{
break;
}
if pc > v.len() - 1
{
break;
}
let cs: Vec<&str> = v[pc].split_whitespace().collect::<Vec<_>>();
//println!("{:?}", cs);
match cs[0]
{
"bgt" => {
let right = pop(&mut val, &mut sp);
let left = pop(&mut val, &mut sp);
if left > right
{
pc = jmp(s, cs[1]);
}
}
"brfalse" => {
if pop(&mut val, &mut sp) == 0.0
{
pc = jmp(s, cs[1]);
}
}
"br" => {
pc = jmp(s, cs[1]);
}
"ldstr" => {
bu = cs[1];
}
"ldc.i4" => {
let number: f32 = cs[1].parse::<f32>().expect("REASON");
push(&mut val, &mut sp, number);
}
"stloc" => {
if cs[1] == "n"
{
n = pop(&mut val, &mut sp);
}
if cs[1] == "i"
{
i = pop(&mut val, &mut sp);
}
}
"ldloc" => {
if cs[1] == "n"
{
push(&mut val, &mut sp, n);
}
if cs[1] == "i"
{
push(&mut val, &mut sp, i);
}
}
"add" => {
let right = pop(&mut val, &mut sp);
let left = pop(&mut val, &mut sp);
push(&mut val, &mut sp, left + right);
}
"sub" => {
let right = pop(&mut val, &mut sp);
let left = pop(&mut val, &mut sp);
push(&mut val, &mut sp, left - right);
}
"mul" => {
let right = pop(&mut val, &mut sp);
let left = pop(&mut val, &mut sp);
push(&mut val, &mut sp, left * right);
}
"div" => {
let right = pop(&mut val, &mut sp);
let left = pop(&mut val, &mut sp);
push(&mut val, &mut sp, left / right);
}
"rem" => {
let right = pop(&mut val, &mut sp);
let left = pop(&mut val, &mut sp);
push(&mut val, &mut sp, left % right);
}
"call" => {
if cs[3] == "System.Console::WriteLine(int32)"
{
let right = pop(&mut val, &mut sp);
println!("{}", right);
}
if cs[3] == "System.Console::WriteLine(string)"
{
println!("{}", bu);
}
}
"dup" => {
let right = pop(&mut val, &mut sp);
push(&mut val, &mut sp, right);
push(&mut val, &mut sp, right);
}
"pop" => {
let right = pop(&mut val, &mut sp);
}
_ => {
//println!("{}", cs[0]);
}
}
pc = pc + 1;
lp = lp + 1;
}
}
fn main() {
ilasm(" ldc.i4 100
stloc n
ldc.i4 1
stloc i
loop:
ldloc i
ldloc n
bgt bye
ldloc i
ldc.i4 15
rem
brfalse fb
ldloc i
ldc.i4 5
rem
brfalse b
ldloc i
ldc.i4 3
rem
brfalse f
ldloc i
call void [mscorlib] System.Console::WriteLine(int32)
br tugi
fb:
ldstr \"fizzbuzz\"
br print
b:
ldstr \"buzz\"
br print
f:
ldstr \"fizz\"
print:
call void [mscorlib] System.Console::WriteLine(string)
tugi:
ldloc i
ldc.i4 1
add
stloc i
br loop
bye:
ret ");
}
実行結果
1
2
"fizz"
4
"buzz"
"fizz"
7
8
"fizz"
"buzz"
11
"fizz"
13
14
"fizzbuzz"
16
17
"fizz"
19
"buzz"
"fizz"
22
23
"fizz"
"buzz"
26
"fizz"
28
29
"fizzbuzz"
31
32
"fizz"
34
"buzz"
"fizz"
37
38
"fizz"
"buzz"
41
"fizz"
43
44
"fizzbuzz"
46
47
"fizz"
49
"buzz"
"fizz"
52
53
"fizz"
"buzz"
56
"fizz"
58
59
"fizzbuzz"
61
62
"fizz"
64
"buzz"
"fizz"
67
68
"fizz"
"buzz"
71
"fizz"
73
74
"fizzbuzz"
76
77
"fizz"
79
"buzz"
"fizz"
82
83
"fizz"
"buzz"
86
"fizz"
88
89
"fizzbuzz"
91
92
"fizz"
94
"buzz"
"fizz"
97
98
"fizz"
"buzz"
成果物
以上。