Last active
April 6, 2016 22:42
-
-
Save fujidig/61267ec2c19b2fa50818dac332e5fd30 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* 関数プログラムのインタプリタ */ | |
| /* すなわち,compはジャンププログラムのインタプリタだったが */ | |
| /* これを第1章で定義される関数プログラムのインタプリタとして */ | |
| /* 作ればどの程度複雑になるのか見てみる */ | |
| int pair(int x, int y); | |
| int ELM(int a, int i); | |
| int length(int a); | |
| int sequence(int a, int i); | |
| int replace(int a, int i, int x); | |
| int comp(int p, int x); | |
| int eval_stmt_seq(int vars, int node); | |
| int eval_stmt(int vars, int node); | |
| int eval_subst(int vars, int node); | |
| int eval_if(int vars, int node); | |
| int eval_while(int vars, int node); | |
| int eval_loop(int vars, int node); | |
| int eval_return(int vars, int node); | |
| int eval_expr(int vars, int node); | |
| int eval_varref(int vars, int node); | |
| int eval_literal(int node); | |
| int eval_funccall(int vars, int node); | |
| int new_res(int vars, int isreturn, int value); | |
| int res_vars(int res); | |
| int res_isreturn(int res); | |
| int res_value(int res); | |
| /* 本当はグローバル変数でなく各関数の引数として連れまわしたい */ | |
| int functable; | |
| int comp(int p, int x) { | |
| int k = ELM(p, 1); | |
| int m = ELM(p, 2); | |
| int node = ELM(p, 3); | |
| int vars = sequence(0, m); | |
| int i = 1; | |
| while (i <= k) { | |
| vars = replace(vars, i, ELM(x, i)); | |
| i ++; | |
| } | |
| int res = eval_stmt_seq(vars, node); | |
| return res_value(res); | |
| } | |
| int eval_stmt_seq(int vars, int node) { | |
| int nodes = ELM(node, 2); | |
| int n = length(nodes); | |
| int i = 1; | |
| while (i <= n) { | |
| int res = eval_stmt(vars, ELM(nodes, i)); | |
| if (res_isreturn(res)) return res; | |
| vars = res_vars(res); | |
| i ++; | |
| } | |
| return new_res(vars, 0, 0); | |
| } | |
| int eval_stmt(int vars, int node) { | |
| int type = ELM(node, 1); | |
| if (type == 1) { | |
| return eval_subst(vars, node); | |
| } else if (type == 2) { | |
| return eval_if(vars, node); | |
| } else if (type == 3) { | |
| return eval_while(vars, node); | |
| } else if (type == 4) { | |
| return eval_loop(vars, node); | |
| } else if (type == 5) { | |
| return eval_return(vars, node); | |
| } | |
| } | |
| int eval_subst(int vars, int node) { | |
| int i = ELM(node, 2); | |
| int rhs = ELM(node, 3); | |
| vars = replace(vars, i, eval_expr(vars, rhs)); | |
| return new_res(vars, 0, 0); | |
| } | |
| int eval_if(int vars, int node) { | |
| int condnode = ELM(node, 2); | |
| int thennode = ELM(node, 3); | |
| int elsenode = ELM(node, 4); | |
| int nd; | |
| if (eval_expr(vars, condnode)) { | |
| nd = thennode; | |
| } else { | |
| nd = elsenode; | |
| } | |
| return eval_stmt_seq(vars, nd); | |
| } | |
| int eval_while(int vars, int node) { | |
| int condnode = ELM(node, 2); | |
| int bodynode = ELM(node, 3); | |
| while (eval_expr(vars, condnode)) { | |
| int res = eval_stmt_seq(vars, bodynode); | |
| if (res_isreturn(res)) return res; | |
| vars = res_vars(res); | |
| } | |
| return new_res(vars, 0, 0); | |
| } | |
| int eval_loop(int vars, int node) { | |
| int numnode = ELM(node, 2); | |
| int bodynode = ELM(node, 3); | |
| int num = eval_expr(vars, numnode); | |
| int i = 0; | |
| while (i < num) { | |
| int res = eval_stmt_seq(vars, bodynode); | |
| if (res_isreturn(res)) return res; | |
| vars = res_vars(res); | |
| i ++; | |
| } | |
| return new_res(vars, 0, 0); | |
| } | |
| int eval_return(int vars, int node) { | |
| int exprnode = ELM(node, 2); | |
| return new_res(vars, 1, eval_expr(vars, exprnode)); | |
| } | |
| /* 比較演算子,条件演算子は教科書では数式演算子として定義していないが */ | |
| /* 0か1を返す数式演算子として実装すると楽なのでそうする */ | |
| int eval_expr(int vars, int node) { | |
| int type = ELM(node, 1); | |
| int lhs = ELM(node, 2); | |
| int rhs = ELM(node, 3); | |
| if (type == 11) { | |
| return eval_varref(vars, node); | |
| } else if (type == 12) { | |
| return eval_literal(node); | |
| } else if (type == 13) { | |
| return eval_funccall(vars, node); | |
| } else if (type == 14) { | |
| return eval_expr(vars, lhs) + eval_expr(vars, rhs); | |
| } else if (type == 15) { | |
| return eval_expr(vars, lhs) - eval_expr(vars, rhs); | |
| } else if (type == 16) { | |
| return eval_expr(vars, lhs) * eval_expr(vars, rhs); | |
| } else if (type == 17) { | |
| return eval_expr(vars, lhs) / eval_expr(vars, rhs); | |
| } else if (type == 18) { | |
| return eval_expr(vars, lhs) % eval_expr(vars, rhs); | |
| } else if (type == 19) { | |
| return eval_expr(vars, lhs) == eval_expr(vars, rhs); | |
| } else if (type == 20) { | |
| return eval_expr(vars, lhs) != eval_expr(vars, rhs); | |
| } else if (type == 21) { | |
| return eval_expr(vars, lhs) < eval_expr(vars, rhs); | |
| } else if (type == 22) { | |
| return eval_expr(vars, lhs) > eval_expr(vars, rhs); | |
| } else if (type == 23) { | |
| return eval_expr(vars, lhs) <= eval_expr(vars, rhs); | |
| } else if (type == 24) { | |
| return eval_expr(vars, lhs) >= eval_expr(vars, rhs); | |
| } else if (type == 25) { | |
| return eval_expr(vars, lhs) && eval_expr(vars, rhs); | |
| } else if (type == 26) { | |
| return eval_expr(vars, lhs) || eval_expr(vars, rhs); | |
| } else if (type == 27) { | |
| return !eval_expr(vars, lhs); | |
| } | |
| } | |
| int eval_varref(int vars, int node) { | |
| int varno = ELM(node, 2); | |
| return ELM(vars, varno); | |
| } | |
| int eval_literal(int node) { | |
| return ELM(node, 2); | |
| } | |
| int eval_funccall(int vars, int node) { | |
| int funcno = ELM(node, 2); | |
| int argnodes = ELM(node, 3); | |
| int k = length(argnodes); | |
| int args = sequence(0, k); | |
| int i = 1; | |
| while (i <= k) { | |
| args = replace(args, i, eval_expr(vars, ELM(argnodes, i))); | |
| i ++; | |
| } | |
| return comp(ELM(functable, funcno), args); | |
| } | |
| int new_res(int vars, int isreturn, int value) { | |
| return pair(vars, pair(isreturn, value)); | |
| } | |
| int res_vars(int res) { | |
| return ELM(res, 1); | |
| } | |
| int res_isreturn(int res) { | |
| return ELM(res, 2); | |
| } | |
| int res_value(int res) { | |
| return ELM(res, 3); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment