Tr_exp transDec_functionDec(Tr_level level, S_table venv, S_table tenv, A_dec d, Temp_label breakk) { for (A_fundecList fundecs = d->u.function; fundecs; fundecs = fundecs->tail) { S_symbol name = fundecs->head->name; Ty_tyList formals = makeFormalTyList(tenv, fundecs->head->params); for (A_fundecList f = d->u.function; f != fundecs; f = f->tail) if (f->head->name == name) EM_error(f->head->pos, "there are two functions with the same name in the same batch " "of mutually recursive functions"); Ty_ty result = (fundecs->head->result)? S_look(tenv, fundecs->head->result) : Ty_Void(); Temp_label label = Temp_newlabel(); U_boolList escapeList = NULL; for (A_fieldList l = fundecs->head->params; l; l = l->tail) // todo: handle no escape escapeList = U_BoolList(TRUE, escapeList); S_enter(venv, name, E_FunEntry(Tr_newLevel(level, label, escapeList), label, formals, result)); } for (A_fundecList fundecs = d->u.function; fundecs; fundecs = fundecs->tail) { S_symbol name = fundecs->head->name; E_enventry x = S_look(venv, name); Ty_tyList formals = x->u.fun.formals; Ty_ty result = x->u.fun.result; Tr_level lev = x->u.fun.level; S_beginScope(venv); { A_fieldList l; Ty_tyList t; Tr_accessList a; for (l = fundecs->head->params, t = formals, a = Tr_formals(lev); l; l = l->tail, t = t->tail, a = a->tail) S_enter(venv, l->head->name, E_VarEntry(a->head, t->head)); // check return type struct expty body = transExp(lev, venv, tenv, fundecs->head->body, breakk); if (!has_same_ty(result, body.ty)) { if (has_same_ty(result, Ty_Void())) EM_error(fundecs->head->pos, "procedure returns value '%s'", type_msg(body.ty)); else EM_error(fundecs->head->pos, "return type mismatched '%s' and '%s')", type_msg(result), type_msg(body.ty)); } Tr_procEntryExit(lev, body.exp, a); } S_endScope(venv); } return Tr_noExp(); }
void transDec(S_table venv, S_table tenv, A_dec d) { if(d == NULL) { return; } switch(d->kind) { case A_varDec: { struct expty e = transExp(venv, tenv, d->u.var.init); S_enter(venv, d->u.var.var, E_VarEntry(e.ty)); break; } case A_typeDec: { S_enter(venv, d->u.type->head->name, transTy(tenv, d->u.type->head->ty)); break; } case A_functionDec: { A_fundec f = d->u.function->head; Ty_ty resultTy = S_look(tenv, f->result); Ty_tyList formalTys = makeFormalTyList(tenv, f->params); S_enter(venv, f->name, E_FunEntry(formalTys, resultTy)); S_beginScope(venv); { A_fieldList l; Ty_tyList t; for (l = f->params, t = formalTys; l; l = l->tail, t = t->tail) { S_enter(venv, l->head->name, E_VarEntry(t->head)); } } transExp(venv, tenv, d->u.function->head->body); S_endScope(venv); break; } default: { assert(0); } } }
Tr_exp transDec_varDec(Tr_level level, S_table venv, S_table tenv, A_dec d, Temp_label breakk) { struct expty init = transExp(level, venv, tenv, d->u.var.init, breakk); if (d->u.var.typ) { Ty_ty typ = S_look(tenv, d->u.var.typ); if (!has_same_ty(typ, init.ty)) EM_error(d->u.var.init->pos, "cannot initialize a variable of type '%s' with an rvalue of " "type '%s'", type_msg(typ), type_msg(init.ty)); } else if (init.ty->kind == Ty_nil) EM_error(d->u.var.init->pos, "cannot initialize a nil type without specified record type"); Tr_access access = Tr_allocLocal(level, TRUE); // todo check escape = false S_enter(venv, d->u.var.var, E_VarEntry(access, init.ty)); return Tr_assignExp(Tr_simpleVar(access, level), init.exp); }
/* translate function declaration * TODO * reduce the result type from the body and check that * it maps the specified result(including the void case * -it is a procedure) */ void transFuncDec(S_table venv, S_table tenv, A_dec d) { // add the function itself Ty_ty resultTy; if (d->u.function.result) resultTy = S_look(tenv, d->u.function.result); else resultTy = Ty_Void(); Ty_tyList formalTys = makeFormalTyList(tenv, d->u.function.params); S_enter(venv, d->u.function.name, E_FunEntry(formalTys, resultTy)); // re-parse the formal params and add them as variable // binding for the body S_beginScope(venv); A_fieldList fl = d->u.function.params; Ty_tyList tl = formalTys; for (; fl; fl = fl->tail, tl = tl->tail) { S_enter(venv, fl->head->name, E_VarEntry(tl->head)); } transExp(venv, tenv, d->u.function.body); S_endScope(venv); }
/* translate variable declaration * var id:type-id := exp */ void transVarDec(S_table venv, S_table tenv, A_dec d) { struct expty e = transExp(venv, tenv, d->u.var.init); if (d->u.var.typ) { /* 1. check the type constraint if any * 2. init value of type Ty_Nil must be constrainted * by a Ty_Record type */ Ty_ty expected_ty = S_look(tenv, d->u.var.typ); if (!expected_ty) { EM_error(d->pos, "undefined type %s", S_name(d->u.var.typ)); return; } if ((expected_ty->kind != Ty_record && e.ty == Ty_Nil()) || expected_ty != e.ty) { EM_error(d->pos, "inconsistent var type %s", S_name(d->u.var.var)); return; } } S_enter(venv, d->u.var.var, E_VarEntry(e.ty)); }
struct expty transExp (S_table venv, S_table tenv, A_exp a) { switch (a->kind) { case A_opExp: { A_oper oper = a->u.op.oper; struct expty left = transExp (venv, tenv, a->u.op.left); struct expty right = transExp (venv, tenv, a->u.op.right); if (oper == A_plusOp || oper == A_minusOp || oper == A_timesOp || oper == A_divideOp) { if (left.ty->kind != Ty_int) { EM_error (a->u.op.left->pos, "integer required"); } if (right.ty->kind != Ty_int) { EM_error (a->u.op.right->pos, "integer required"); } } else { if (left.ty->kind != right.ty->kind) { EM_error (a->u.op.right->pos, "left type should be same as right"); } } return expTy (NULL, Ty_Int()); } case A_varExp: { return transVar (venv, tenv, a->u.var); } case A_nilExp: { return expTy (NULL, Ty_Nil()); } case A_intExp: { return expTy (NULL, Ty_Int()); } case A_stringExp: { return expTy (NULL, Ty_String()); } case A_callExp: { E_enventry x = S_look (venv, a->u.call.func); if (x && x->kind == E_funEntry) { Ty_tyList tList; A_expList eList; for (tList = x->u.fun.formals, eList = a->u.call.args; tList && eList; tList = tList->tail, eList = eList->tail) { Ty_ty expTyName = transExp (venv, tenv, eList->head).ty; if (tList->head->kind != expTyName->kind) { if (tList->head->kind == Ty_record && expTyName->kind == Ty_nil) { continue; } EM_error (eList->head->pos, "field type is wrong"); return expTy (NULL, Ty_Int()); } } if (tList || eList) { EM_error (a->u.call.args->head->pos, "field type number is wrong"); return expTy (NULL, Ty_Int()); } return expTy (NULL, x->u.fun.result); } EM_error (a->pos, "undefined function name %s", S_name (a->u.call.func)); return expTy (NULL, Ty_Int()); } case A_recordExp: { Ty_ty record = S_look (tenv, a->u.record.typ); if (!record) { EM_error (a->pos, "undefined record type %s", S_name (a->u.record.typ)); return expTy (NULL, record); } if (record->kind != Ty_record) { EM_error (a->pos, "type should be an record"); return expTy (NULL, Ty_Int()); } else { A_efieldList efieldList = NULL; Ty_fieldList fieldList = record->u.record; for (efieldList = a->u.record.fields; efieldList && fieldList; efieldList = efieldList->tail, fieldList = fieldList->tail) { Ty_ty field = actual_ty(fieldList->head->ty); Ty_ty expTyName = transExp (venv, tenv, efieldList->head->exp).ty; if (field->kind != expTyName->kind) { if (field->kind == Ty_record && expTyName->kind == Ty_nil) { continue; } EM_error (a->pos, "field type wrong"); } } if (efieldList || fieldList) { EM_error (a->pos, "field number wrong"); } return expTy (NULL, record); } } case A_arrayExp: { Ty_ty array = S_look (tenv, a->u.array.typ); if (!array) { EM_error (a->pos, "undefined array type %s", S_name (a->u.array.typ)); return expTy (NULL, array); } if (array->kind != Ty_array) { EM_error (a->pos, "type should be an array"); return expTy (NULL, Ty_Int()); } else { if (transExp (venv, tenv, a->u.array.size).ty->kind != Ty_int) { EM_error (a->pos, "array size should be int"); } if (transExp (venv, tenv, a->u.array.init).ty->kind != array->u.array->kind) { EM_error (a->pos, "array type should be same as init"); } return expTy (NULL, array); } } case A_seqExp: { A_expList d; for (d = a->u.seq; d && d->tail; d = d->tail) { transExp (venv, tenv, d->head); } if (d) { return transExp (venv, tenv, d->head); } else { return expTy (NULL, Ty_Void()); } } case A_assignExp: { transVar (venv, tenv, a->u.assign.var); transExp (venv, tenv, a->u.assign.exp); return expTy (NULL, Ty_Void()); } case A_ifExp: { transExp (venv, tenv, a->u.iff.test); if (a->u.iff.elsee) { struct expty then = transExp (venv, tenv, a->u.iff.then); struct expty elsee = transExp (venv, tenv, a->u.iff.elsee); if (then.ty->kind != elsee.ty->kind) { EM_error (a->u.iff.elsee->pos, "then should be same as else"); } return then; } else { struct expty then = transExp (venv, tenv, a->u.iff.then); if (then.ty->kind != Ty_void) { EM_error (a->u.iff.then->pos, "then should be void"); } return expTy (NULL, Ty_Void()); } } case A_whileExp: { transExp (venv, tenv, a->u.whilee.test); struct expty body = transExp (venv, tenv, a->u.whilee.body); if (body.ty->kind != Ty_void) { EM_error (a->u.whilee.body->pos, "body of while error, it should return void"); } return expTy (NULL, Ty_Void()); } case A_forExp: { S_enter (venv, a->u.forr.var, E_VarEntry (Ty_Int())); struct expty lo = transExp (venv, tenv, a->u.forr.lo); struct expty hi = transExp (venv, tenv, a->u.forr.hi); if (lo.ty->kind != Ty_int) { EM_error (a->u.forr.lo->pos, "lo exp of for should be int"); } if (hi.ty->kind != Ty_int) { EM_error(a->u.forr.hi->pos, "hi exp of for should be int"); } S_beginScope (venv); //if (a->u.forr.body->kind == A_seqExp) { // A_expList test = a->u.forr.body->u.seq; // while (test) { // if (test->head->kind == A_assignExp) { // } // } //} struct expty body = transExp (venv, tenv, a->u.forr.body); if (body.ty->kind != Ty_void) { EM_error (a->u.forr.body->pos, "body of for error, it should return void"); } S_endScope(venv); return expTy (NULL, Ty_Void()); } case A_breakExp: { return expTy (NULL, Ty_Void()); } case A_letExp: { struct expty exp; A_decList d; S_beginScope (venv); S_beginScope (tenv); for (d = a->u.let.decs; d; d = d->tail) { transDec (venv, tenv, d->head); } exp = transExp (venv, tenv, a->u.let.body); S_endScope (tenv); S_endScope (venv); return exp; } } assert (0); }
void transDec (S_table venv, S_table tenv, A_dec d) { switch (d->kind) { case A_varDec: { Ty_ty typ = NULL; if (d->u.var.typ) { typ = S_look(tenv, d->u.var.typ); } struct expty e = transExp (venv, tenv, d->u.var.init); if (!typ || typ->kind == e.ty->kind) { if (e.ty->kind == Ty_nil && (!typ || typ->kind != Ty_record)) { EM_error (d->u.var.init->pos, "nil should be constrained by record"); } S_enter (venv, d->u.var.var, E_VarEntry (e.ty)); } else { EM_error (d->u.var.init->pos, "var type should be same as init"); } break; } case A_typeDec: { A_nametyList nList = NULL; for (nList = d->u.type; nList; nList = nList->tail) { bool flag; A_nametyList scanList = NULL; for (scanList = nList->tail; scanList; scanList = scanList->tail) { if (strcmp(S_name(nList->head->name), S_name(scanList->head->name)) == 0) { flag = TRUE; break; } } if (flag) { EM_error (d->pos, "type redefined error"); } S_enter(tenv, nList->head->name, Ty_Name (nList->head->ty->u.name, NULL)); } for (nList = d->u.type; nList; nList = nList->tail) { Ty_ty waitFill = S_look(tenv, nList->head->name); if (waitFill->kind == Ty_name) { waitFill->u.name.ty = transTy (tenv, nList->head->ty); } Ty_ty trueType = actual_ty(waitFill); if (trueType) { S_enter(tenv, nList->head->name, actual_ty(waitFill)); } else { EM_error (d->pos, "recursive types should through record or array"); break; } } break; } case A_functionDec: { A_fundecList funList = NULL; for (funList = d->u.function; funList; funList = funList->tail) { bool flag; A_fundecList scanList = NULL; for (scanList = funList->tail; scanList; scanList = scanList->tail) { if (strcmp(S_name(funList->head->name), S_name(scanList->head->name)) == 0) { flag = TRUE; break; } } if (flag) { EM_error (d->pos, "function redefined error"); } A_fundec f = funList->head; if (!f->result) { f->result = S_Symbol("void"); } Ty_ty resultTy = S_look (tenv, f->result); Ty_tyList formalTys = makeFormalTyList (tenv, f->params); S_enter (venv, f->name, E_FunEntry (formalTys, resultTy)); } for (funList = d->u.function; funList; funList = funList->tail) { A_fundec f = funList->head; Ty_tyList formalTys = makeFormalTyList (tenv, f->params); S_beginScope (venv); { A_fieldList l; Ty_tyList t; for (l = f->params, t = formalTys; l; l = l->tail, t = t->tail) { S_enter (venv, l->head->name, E_VarEntry (t->head)); } } Ty_ty returnTy = S_look (tenv, f->result); if (returnTy->kind != transExp (venv, tenv, f->body).ty->kind) { EM_error (f->body->pos, "return type wrong"); } S_endScope (venv); } break; } } }
struct expty transExp(S_table venv, S_table tenv, A_exp e) { if (e == NULL) { return expTy(NULL, Ty_Void()); } switch (e->kind) { case A_varExp: { return transVar(venv, tenv, e->u.var); } case A_nilExp: { return expTy(NULL, Ty_Nil()); } case A_intExp: { return expTy(NULL, Ty_Int()); } case A_stringExp: { return expTy(NULL, Ty_String()); } case A_callExp: { E_enventry fun = (E_enventry)S_look(venv, e->u.call.func); if (!fun || fun->kind == E_varEntry) { EM_error(e->pos, (string)"undefined function '%s'", S_name(e->u.call.func)); return expTy(NULL, Ty_Int()); } if ((!fun->u.fun.formals && e->u.call.args) || (fun->u.fun.formals && !e->u.call.args)) { EM_error(e->pos, (string)"incorrect function prototype '%s'", S_name(e->u.call.func)); return expTy(NULL, Ty_Int()); } Ty_tyList ttl; A_expList el; for (ttl = fun->u.fun.formals, el = e->u.call.args; ttl || el; ttl = ttl->tail, el = el->tail) { if (ttl && !el) { EM_error(e->pos, (string)"formals are more than actuals"); return expTy(NULL, Ty_Int()); } if (!ttl && el) { EM_error(e->pos, (string)"formals are less than actuals"); return expTy(NULL, Ty_Int()); } struct expty arg = transExp(venv, tenv, el->head); if (actual_ty(ttl->head)->kind != actual_ty(arg.ty)->kind) { EM_error(e->pos, (string)"formals and actuals have different types"); return expTy(NULL, Ty_Int()); } } if (!fun->u.fun.result) { return expTy(NULL, Ty_Void()); } return expTy(NULL, actual_ty(fun->u.fun.result)); } case A_opExp: { A_oper oper = e->u.op.oper; struct expty left = transExp(venv, tenv, e->u.op.left); struct expty right = transExp(venv, tenv, e->u.op.right); if (oper == A_plusOp || oper == A_minusOp || oper == A_timesOp || oper == A_divideOp) { if (left.ty->kind != Ty_int || right.ty->kind != Ty_int) { EM_error(e->u.op.left->pos, (string)"integer required"); return expTy(NULL, Ty_Int()); } return expTy(NULL, Ty_Int()); } if (oper == A_eqOp || oper == A_neqOp) { if (isSameTy(left.ty, right.ty)) { return expTy(NULL, Ty_Int()); } EM_error(e->pos, (string)"same type required"); return expTy(NULL, Ty_Int()); } if (oper == A_ltOp || oper == A_leOp || oper == A_gtOp || oper == A_geOp) { if (left.ty->kind == Ty_int && right.ty->kind == Ty_int) { return expTy(NULL, Ty_Int()); } if (left.ty->kind == Ty_string && right.ty->kind == Ty_string) { return expTy(NULL, Ty_Int()); } EM_error(e->pos, "comparison of incompatible type"); return expTy(NULL, Ty_Int()); } assert(0); } case A_recordExp: { Ty_ty ty = (Ty_ty)S_look(tenv, e->u.record.typ); if (!ty) { EM_error(e->pos, "undefined record type '%s'", S_name(e->u.record.typ)); return expTy(NULL, Ty_Nil()); } ty = actual_ty(ty); if (ty->kind != Ty_record) { EM_error(e->pos, "'%s' is not a record", S_name(e->u.record.typ)); } else { Ty_fieldList tfl; A_efieldList efl; for (tfl = ty->u.record, efl = e->u.record.fields; tfl || efl; tfl = tfl->tail, efl = efl->tail) { if (tfl && !efl) { EM_error(e->pos, "record field is less than need"); return expTy(NULL, Ty_Nil()); } if (!tfl && efl) { EM_error(e->pos, "record field is more than need"); return expTy(NULL, Ty_Nil()); } if (tfl->head->name != efl->head->name) { EM_error(e->pos, "record field mismatch"); return expTy(NULL, Ty_Nil()); } struct expty res = transExp(venv, tenv, efl->head->exp); Ty_ty fieldty = actual_ty(tfl->head->ty); if (!isSameTy(fieldty, res.ty)) { EM_error(e->pos, (string)"record field mismatch"); return expTy(NULL, Ty_Nil()); } } } return expTy(NULL, ty); } case A_seqExp: { A_expList el = e->u.seq; if (el) { while (el->tail) { transExp(venv, tenv, el->head); el = el->tail; } return expTy(NULL, transExp(venv, tenv, el->head).ty); } return expTy(NULL, Ty_Void()); } case A_assignExp: { struct expty left = transVar(venv, tenv, e->u.assign.var); struct expty right = transExp(venv, tenv, e->u.assign.exp); if (isSameTy(left.ty, right.ty)) { return expTy(NULL, Ty_Void()); } EM_error(e->pos, "type mismatch"); return expTy(NULL, Ty_Void()); } case A_ifExp: { struct expty test = transExp(venv, tenv, e->u.iff.test); if (test.ty->kind != Ty_int) { EM_error(e->pos, "if-else clause integer test required"); return expTy(NULL, Ty_Void()); } struct expty then = transExp(venv, tenv, e->u.iff.then); if (e->u.iff.elsee == NULL) { if (then.ty->kind != Ty_void) { EM_error(e->pos, "if-then returns non unit"); return expTy(NULL, Ty_Void()); } return expTy(NULL, Ty_Void()); } struct expty elsee = transExp(venv, tenv, e->u.iff.elsee); if (isSameTy(then.ty, elsee.ty)) { return expTy(NULL, then.ty); } EM_error(e->pos, "types of then - else differ"); return expTy(NULL, Ty_Void()); } case A_whileExp: { struct expty test = transExp(venv, tenv, e->u.whilee.test); struct expty body = transExp(venv, tenv, e->u.whilee.body); if (test.ty->kind != Ty_int) { EM_error(e->pos, "test clause integer required"); return expTy(NULL, Ty_Void()); } if (body.ty->kind != Ty_void) { EM_error(e->pos, "body of while not void"); return expTy(NULL, Ty_Void()); } return expTy(NULL, Ty_Void()); } case A_forExp: { struct expty lo = transExp(venv, tenv, e->u.forr.lo); struct expty hi = transExp(venv, tenv, e->u.forr.hi); if (lo.ty->kind != Ty_int || hi.ty->kind != Ty_int) { EM_error(e->pos, "for clause lo and hi integer required"); return expTy(NULL, Ty_Void()); } S_beginScope(venv); if (!S_look(venv, e->u.forr.var)) { S_enter(venv, e->u.forr.var, E_VarEntry(Ty_Int())); } struct expty body = transExp(venv, tenv, e->u.forr.body); S_endScope(venv); if (body.ty->kind != Ty_void) { EM_error(e->pos, "for clause body no-value required"); return expTy(NULL, Ty_Void()); } return expTy(NULL, Ty_Void()); } case A_breakExp: { return expTy(NULL, Ty_Void()); } case A_letExp: { A_decList d; S_beginScope(venv); S_beginScope(tenv); for (d = e->u.let.decs; d; d = d->tail) { transDec(venv, tenv, d->head); } struct expty exp = transExp(venv, tenv, e->u.let.body); S_endScope(venv); S_endScope(tenv); return exp; } case A_arrayExp: { struct expty size = transExp(venv, tenv, e->u.array.size); struct expty init = transExp(venv, tenv, e->u.array.init); Ty_ty ty = (Ty_ty)S_look(tenv, e->u.array.typ); if (!ty) { EM_error(e->pos, "undefined array type '%s'", S_name(e->u.array.typ)); return expTy(NULL, Ty_Void()); } ty = actual_ty(ty); if (ty->kind != Ty_array) { EM_error(e->pos, "'%s' is not a array", S_name(e->u.array.typ)); return expTy(NULL, Ty_Void()); } if (size.ty->kind != Ty_int) { EM_error(e->pos, "size int value required"); return expTy(NULL, actual_ty(ty)); } Ty_ty ty2 = actual_ty(ty->u.array); if (!isSameTy(ty2, init.ty)) { EM_error(e->pos, "initializing exp and array type differ"); return expTy(NULL, Ty_Void()); } return expTy(NULL, ty); } default: { assert(0); } } }
void transDec(S_table venv, S_table tenv, A_dec d) { if (!d) { return; } switch (d->kind) { case A_varDec: { struct expty e = transExp(venv, tenv, d->u.var.init); if (d->u.var.typ) { Ty_ty ty = (Ty_ty)S_look(tenv, d->u.var.typ); if (!ty) { EM_error(d->pos, "undefined type '%s'", S_name(d->u.var.typ)); return; } ty = actual_ty(ty); if (!isSameTy(ty, e.ty)) { EM_error(d->pos, (string)"type mismatch"); return; } S_enter(venv, d->u.var.var, E_VarEntry(ty)); return; } if (e.ty->kind == Ty_nil) { EM_error(d->pos, "initializing nil expressions not constrained by record type"); return; } S_enter(venv, d->u.var.var, E_VarEntry(e.ty)); return; } case A_typeDec: { S_table tmp = S_empty(); A_nametyList ntl; for (ntl = d->u.type; ntl; ntl = ntl->tail) { if (S_look(tmp, ntl->head->name)) { EM_error(d->pos, "type '%s' redefined", S_name(ntl->head->name)); return; } S_enter(tmp, ntl->head->name, "-tmp-"); S_enter(tenv, ntl->head->name, Ty_Name(ntl->head->name, NULL)); } for (ntl = d->u.type; ntl; ntl = ntl->tail) { Ty_ty ty = (Ty_ty)S_look(tenv, ntl->head->name); ty->u.name.ty = transTy(tenv, ntl->head->ty); } for (ntl = d->u.type; ntl; ntl = ntl->tail) { Ty_ty ty = (Ty_ty)S_look(tenv, ntl->head->name); if (ty->u.name.ty->kind != Ty_name) { return; } } EM_error(d->pos, "infinite recursive"); return; } case A_functionDec: { S_table tmp = S_empty(); A_fundecList fdl; for (fdl = d->u.function; fdl; fdl = fdl->tail) { if (S_look(tmp, fdl->head->name)) { EM_error(d->pos, "function '%s' redefined", S_name(fdl->head->name)); return; } S_enter(tmp, fdl->head->name, "-tmp-"); } for (fdl = d->u.function; fdl; fdl = fdl->tail) { Ty_tyList formalTys = makeFormalTyList(tenv, fdl->head->params); if (fdl->head->result) { Ty_ty resultTy = S_look(tenv, fdl->head->result); S_enter(venv, fdl->head->name, E_FunEntry(formalTys, resultTy)); } else { S_enter(venv, fdl->head->name, E_FunEntry(formalTys, NULL)); } } for (fdl = d->u.function; fdl; fdl = fdl->tail) { Ty_tyList formalTys = makeFormalTyList(tenv, fdl->head->params); S_beginScope(venv); { A_fieldList l; Ty_tyList t; for (l = fdl->head->params, t = formalTys; l; l = l->tail, t = t->tail) { S_enter(venv, l->head->name, E_VarEntry(t->head)); } } transExp(venv, tenv, fdl->head->body); S_endScope(venv); } break; } default: { assert(0); } } }
struct expty transDec(S_table venv, S_table tenv, A_dec d) { switch( d->kind ) { case A_functionDec: { //whether already in funcdeclar if(InFunc()) EM_error( d->pos , "already in func declare"); A_fundecList funcs = d->u.function; // for every fun declare in fundecList for( ; funcs != NULL ; funcs = funcs->tail ) { A_fundec func = funcs->head; // get ty of params and result Ty_tyList funentry = makeFormalTyList( tenv , func->params ); Ty_ty res; if( func->result == NULL ) res = Ty_Nil(); else res = S_look( tenv , func->result ); if( res == NULL ) EM_error( func->pos , "no " , S_name( func->result ) , "type "); //whether already defined if( S_look( venv , func->name ) != NULL ) EM_error( func->pos , S_name( func->result ) , "already defined" ); S_enter( venv , func->name , E_FunEntry( funentry , res ) ); } funcs = d->u.function; // for every fun in fundecList, call tranexp on its body for( ; funcs != NULL ; funcs = funcs->tail ) { A_fundec func = funcs->head; S_beginScope( venv ); A_fieldList args = func->params; Ty_tyList funentries = ((E_entry)S_look( venv , func->name )) ->fun.formalTys ; for( ; args != NULL ; args = args->tail , funentries = funentries->tail) { A_field arg = args->head; Ty_ty type = funentries->head; S_enter( venv , arg->name , type ); } SetInFunc(); transExp( venv , tenv , func->body ); UsetInFunc(); S_endScope( venv ); } return _expTy( NULL , Ty_Void() ); } case A_varDec: { Ty_ty type = S_look( tenv , d->u.var.typ ); if( type == NULL ) EM_error( d->pos , S_name( d->u.var.typ ) , " not defined " ); struct expty init = transExp( venv , tenv , d->u.var.init ); if( init.ty->kind != Ty_nil && init.ty->kind != type->kind ) EM_error( d->pos , "Expect " , tyKindName( type->kind ) , " but " , tyKindName( init.ty->kind ) ); if( S_look( venv , d->u.var.var ) != NULL ) EM_error( d->pos , S_name( d->u.var.var ) , " already defined " ); S_enter( venv , d->u.var.var , type ); return _expTy( NULL , Ty_Void() ); } case A_typeDec: { A_nametyList tylist = d->u.type; for( ; tylist != NULL ; tylist = tylist->tail ) { A_namety tydec = tylist->head; if( S_look( tenv , tydec->name ) != NULL ) EM_error( tydec->ty->pos , S_name( tydec->name ) , " already declared " ); A_ty ty = tydec->ty; switch( ty->kind ) { case A_nameTy: { Ty_ty tyy = S_look( tenv , ty->u.name ) ; if( tyy == NULL ) S_enter( tenv , tydec->name , Ty_Name( ty->u.name , NULL ) ); else S_enter( tenv , tydec->name , tyy ); } case A_recordTy: { A_fieldList records = ty->u.record; Ty_fieldList types = dfsRecordTy( tenv , records ); S_enter( tenv , tydec->name , Ty_Record( types ) ); } case A_arrayTy: default: assert(0); } S_enter( tenv , tydec->name , E_VarEntry( NULL ) ); } tylist = d->u.type; for( ; tylist != NULL ; tylist = tylist->tail ) { A_namety tydec = tylist->head; A_ty ty = tydec->ty; switch( ty->kind ) { case A_nameTy: { Ty_ty tyy = S_look( tenv , ty->u.name ); if( tyy->u.name.ty == NULL ) tyy->u.name.ty = dfsTypeDec( ty->pos , tenv , tyy->u.name.sym , tydec->name ); } case A_recordTy: case A_arrayTy: default: assert(0); } } } default: assert(0); } }