Rubyist Magazine - YARV Maniacs 【第 2 回】 VM ってなんだろうのVMをCで
ruby1.9のソース読もうかなーと思ったのでまずYARV Maniacsなど読んでます。で第二回のvmをc書いてみました。エラー処理とかはまったくしていません。
#include <stdio.h> #define STACK_SIZE 30000 typedef enum Instruction Instruction; typedef struct Code Code; enum Instruction { I_PUSH, I_POP, I_DUP, I_ADD, I_SUB, I_MUL, I_DIV, I_NOT, I_JUMP, I_IF, I_EQ, I_LT, I_GT }; struct Code { Instruction inst; int value; }; int eval(Code program[], int program_len) { int stack[STACK_SIZE]; int stack_index = 0; int pc; int x, y; for(pc=0;pc<program_len;++pc) { Code code = program[pc]; switch(code.inst) { case I_PUSH: stack[stack_index++] = code.value; break; case I_POP: --stack_index; break; case I_DUP: x = stack[stack_index-1]; stack[stack_index++] = x; break; case I_ADD: x = stack[--stack_index]; stack[stack_index-1] += x; break; case I_SUB: x = stack[--stack_index]; stack[stack_index-1] -= x; break; case I_MUL: x = stack[--stack_index]; stack[stack_index-1] *= x; break; case I_DIV: x = stack[--stack_index]; stack[stack_index-1] /= x; break; case I_NOT: x = stack[stack_index-1]; stack[stack_index-1] = !x; break; case I_JUMP: pc = code.value-1; break; case I_IF: x = stack[--stack_index]; if(x) { pc = code.value-1; } break; case I_EQ: x = stack[--stack_index]; y = stack[stack_index-1]; stack[stack_index-1] = x==y; break; case I_LT: x = stack[--stack_index]; y = stack[stack_index-1]; stack[stack_index-1] = x<y; break; case I_GT: x = stack[--stack_index]; y = stack[stack_index-1]; stack[stack_index-1] = x>y; break; default: break; } } return stack[0]; } int main(int argc, char **argv) { Code program[] = { {I_PUSH, 1}, {I_PUSH, 1}, {I_ADD, 0}, {I_DUP, 0}, {I_PUSH, 100000}, {I_GT, 0}, {I_IF, 1} }; int program_len = sizeof(program)/sizeof(Code); int result; result = eval(program, program_len); printf("%d\n", result); return 0; }
実行結果
$ time ./a.out 100000 0.028 user 0.000 system 0.030 total
一瞬! えらい!
修正
I_EQ:のbreak書き忘れてたのだけ修正