Skip to content

Instantly share code, notes, and snippets.

@fujidig
Last active April 6, 2016 22:42
Show Gist options
  • Select an option

  • Save fujidig/61267ec2c19b2fa50818dac332e5fd30 to your computer and use it in GitHub Desktop.

Select an option

Save fujidig/61267ec2c19b2fa50818dac332e5fd30 to your computer and use it in GitHub Desktop.
/* 関数プログラムのインタプリタ */
/* すなわち,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