/** * tests varnum() */ static char * test_varnum() { Logo good, b_var, b_number; int ret; printf("Testing %s\n", __FUNCTION__); /* good input */ good = setup(4, "20"); insert_line(good, "H"); /* decimals and negative numbers */ insert_line(good, "2.5"); insert_line(good, "-2.5"); /* bad input */ b_var = setup(1, "AB"); b_number = setup(1, "209x"); /* test them */ ret = varnum(good->lines[0], good); mu_assert("error, ret != 0", ret == 0); ret = varnum(good->lines[1], good); mu_assert("error, ret != 0", ret == 0); ret = varnum(good->lines[2], good); mu_assert("error, ret != 0", ret == 0); ret = varnum(good->lines[3], good); mu_assert("error, ret != 0", ret == 0); ret = varnum(b_var->lines[0], b_var); mu_assert("error, ret != PARSE_ERR", ret == PARSE_ERR); ret = varnum(b_number->lines[0], b_number); mu_assert("error, ret != PARSE_ERR", ret == PARSE_ERR); tear_down(good); tear_down(b_var); tear_down(b_number); return 0; }
/** * tests varnum() */ static char * test_varnum() { Logo good, b_var, b_number; int ret; float op; printf("Testing %s\n", __FUNCTION__); /* good input */ good = setup(4, "20"); /* decimals and negative numbers */ insert_line(good, "2.5"); insert_line(good, "-2.5"); insert_line(good, "A"); /* bad input */ b_var = setup(3, "AB"); /* non existant var */ insert_line(b_var, "C"); insert_line(b_var, "3-"); b_number = setup(1, "209x"); /* test them */ ret = varnum(good->lines[0], good, &op); mu_assert("error, ret != 0", ret == 0); mu_assert("error, op not set correctly", op == 20); ret = varnum(good->lines[1], good, &op); mu_assert("error, ret != 0", ret == 0); mu_assert("error, op not set correctly", op == 2.5); ret = varnum(good->lines[2], good, &op); mu_assert("error, ret != 0", ret == 0); mu_assert("error, op not set correctly", op == -2.5); /* set the var A */ set_var("A", good->vars, 20); ret = varnum(good->lines[3], good, &op); mu_assert("error, ret != 0", ret == 0); mu_assert("error, op not set correctly", op == 20); ret = varnum(b_var->lines[0], b_var, &op); mu_assert("error, ret != PARSE_ERR", ret == PARSE_ERR); ret = varnum(b_var->lines[1], b_var, &op); mu_assert("error, ret != VAR_ERR", ret == VAR_ERR); ret = varnum(b_var->lines[2], b_var, &op); mu_assert("error, ret != VAR_ERR", ret == PARSE_ERR); ret = varnum(b_number->lines[0], b_number, &op); mu_assert("error, ret != PARSE_ERR", ret == PARSE_ERR); tear_down(good); tear_down(b_var); tear_down(b_number); return 0; }
/** * コードを生成する * @param FILE *ofp 出力先 * @param char *file ファイル名 * @param FEnvCPtr fenvc 関数の型環境 * @param EnvCPtr envc 変数の型環境 * @param ExpPtr ep 式 * @return int 成否 */ int codegen(FILE *ofp, const char *file, FEnvCPtr fenv, EnvCPtr env, ExpPtr ep) { TyType t; TyTypesPtr ts; EnvCPtr env1 = NULL; ExpsPtr es = NULL; FuncT ft = {0}; char l[LABEL_NAME_MAX_SIZE] = ""; char m[LABEL_NAME_MAX_SIZE] = ""; char dty[2] = ""; if(NULL == ep) { return 0; } switch(ep->t) { case VAR_EXP: t = find_var_c(ep->of.var, env); switch(t) { case FLOAT_TYPE: pr_instr(ofp, "fload %d", varnum(ep->of.var, env)); break; default: pr_instr(ofp, "iload %d", varnum(ep->of.var, env)); break; } break; case INT_EXP: pr_instr(ofp, "ldc %d", ep->of.intval); break; case FLOAT_EXP: pr_instr(ofp, "ldc %f", ep->of.floatval); break; case PRIM_EXP: codegen(ofp, file, fenv, env, ep->of.Prim.exp1); codegen(ofp, file, fenv, env, ep->of.Prim.exp2); switch(ep->of.Prim.op) { case PLUS_OP: pr_instr(ofp, "iadd"); break; case FPLUS_OP: pr_instr(ofp, "fadd"); break; case MINUS_OP: pr_instr(ofp, "isub"); break; case FMINUS_OP: pr_instr(ofp, "fsub"); break; case MUL_OP: pr_instr(ofp, "imul"); break; case FMUL_OP: pr_instr(ofp, "fmul"); break; } break; case LET_EXP: codegen(ofp, file, fenv, env, ep->of.Let.exp1); switch((norm(ep->of.Let.tvar.ttp))->t) { case FLOAT_TYPE: pr_instr(ofp, "fstore %d", newvar()); break; default: pr_instr(ofp, "istore %d", newvar()); break; } env1 = envc_alloc(); strncpy_s(env1->var, MAX_VAR_NAME_LENGTH, ep->of.Let.tvar.var, strlen(ep->of.Let.tvar.var)); env1->t = (norm(ep->of.Let.tvar.ttp))->t; env1->next = env; codegen(ofp, file, fenv, env1, ep->of.Let.exp2); break; case IF_EXP: newlabel(l, "else"); newlabel(m, "endif"); codegen(ofp, file, fenv, env, ep->of.If.bp->exp1); codegen(ofp, file, fenv, env, ep->of.If.bp->exp2); switch((norm(ep->of.If.bp->ttp))->t) { case FLOAT_TYPE: pr_instr(ofp, "fcmpl"); pr_instr(ofp, "ifne %s", l); break; default: pr_instr(ofp, "if_icmpne %s", l); break; } codegen(ofp, file, fenv, env, ep->of.If.exp1); pr_instr(ofp, "goto %s", m); fprintf_s(ofp, "%s:\n", l); codegen(ofp, file, fenv, env, ep->of.If.exp2); fprintf_s(ofp, "%s:\n", m); break; case APP_EXP: for(es = ep->of.App.exps; NULL != es; es = es->next) { codegen(ofp, file, fenv, env, es->elm); } ft = find_func_c(ep->of.App.var, fenv); fprintf_s(ofp, "\tinvokestatic %s/%s(", file, ep->of.App.var); for(ts = ft.tys; NULL != ts; ts = ts->next) { desc_of_ty(dty, ts->t); fprintf_s(ofp, "%s", dty); printf("dty -> %s\n", dty); } desc_of_ty(dty, ft.fty); fprintf_s(ofp, ")%s\n", dty); break; } return 1; }