/* exp op exp, rules: * 1. +,-,*,/ only apply to integer operands * 2. =,<>,>,<,>=,<= apply to: * integers * record or array of the same type: compare pointers * strings: compare contents */ struct expty transOpExp(S_table venv, S_table tenv, A_exp e) { struct expty left = transExp(venv, tenv, e->u.op.left); struct expty right = transExp(venv, tenv, e->u.op.right); switch (e->u.op.oper) { case A_plusOp: case A_minusOp: case A_timesOp: case A_divideOp: if (left.ty->kind != Ty_int) { EM_error(e->u.op.left->pos, "integer required"); } if (right.ty->kind != Ty_int) { EM_error(e->u.op.right->pos, "integer required"); } return ExpTy(NULL, Ty_Int()); case A_eqOp: case A_neqOp: case A_ltOp: case A_leOp: case A_gtOp: case A_geOp: if (!Ty_is_compatible(left.ty, right.ty)) { EM_error(e->pos, "operands type mismatch"); } return ExpTy(NULL, Ty_Int()); } assert(0); }
// evaluate the exp list from left to right, use the last // exp's result as the result of the whole list struct expty transSeqExp(S_table venv, S_table tenv, A_expList el) { while (el->tail) { transExp(venv, tenv, el->head); el = el->tail; } return transExp(venv, tenv, el->head); }
struct expty transExp_whileExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { struct expty test = transExp(level, venv, tenv, a->u.whilee.test, breakk); struct expty body = transExp(level, venv, tenv, a->u.whilee.body, breakk); if (test.ty->kind != Ty_int) EM_error(a->u.whilee.test->pos, "expected unqualified-id"); if (body.ty->kind != Ty_void) EM_error(a->u.whilee.test->pos, "body of while not unit"); Temp_label newbreak = Temp_newlabel(); return expTy(Tr_whileExp(test.exp, body.exp, newbreak), Ty_Void()); }
/* while exp1 do exp2 * 1. exp1's type is integer * 2. exp2 produces no value */ struct expty transWhileExp(S_table venv, S_table tenv, A_exp e) { struct expty test = transExp(venv, tenv, e->u.whilee.test); struct expty body = transExp(venv, tenv, e->u.whilee.body); if (test.ty != Ty_Int()) { EM_error(e->pos, "test type of while is not integer"); } if (body.ty != Ty_Void()) { EM_error(e->pos, "body's type of while must be void"); } return ExpTy(NULL, Ty_Void()); }
struct expty transExp_seqExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { A_expList seq = a->u.seq; if (!seq || !seq->head) return expTy(Tr_noExp(), Ty_Void()); Tr_expList head = Tr_ExpList(NULL, NULL), p = head; for (; seq && seq->tail; seq = seq->tail) { struct expty s = transExp(level, venv, tenv, seq->head, breakk); p->tail = Tr_ExpList(s.exp, NULL); p = p->tail; } struct expty last = transExp(level, venv, tenv, seq->head, breakk); head->head = last.exp; return expTy(Tr_eseqExp(head), last.ty); }
void SEM_transProg(A_exp exp) { S_table tenv = E_base_tenv(); S_table venv = E_base_venv(); Tr_level level = Tr_outermost(); struct expty et = transExp(level, venv, tenv, exp, NULL); Tr_printTree(et.exp); }
struct expty transExp_recordExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { Ty_ty typ = actual_ty(S_look(tenv, a->u.record.typ)); A_pos pos = a->pos; // check record type if (!typ || typ->kind != Ty_record) { EM_error(pos, "record type '%s' mismatched", S_name(a->u.record.typ)); return expTy(NULL, Ty_Void()); } // check exp field type A_efieldList efields = a->u.record.fields; Ty_fieldList fields = typ->u.record; Tr_expList expl_h = Tr_ExpList(NULL, NULL), expl_p = expl_h; int size = 0; while (efields && fields) { struct expty efield = transExp(level, venv, tenv, efields->head->exp, breakk); pos = efields->head->exp->pos; if (!has_same_ty(fields->head->ty, efield.ty)) { EM_error(pos, "record field type mismatched: '%s' and '%s'", type_msg(fields->head->ty), type_msg(efield.ty)); break; } efields = efields->tail; fields = fields->tail; expl_p->tail = Tr_ExpList(efield.exp, NULL); expl_p = expl_p->tail; size += 1; } if (efields || fields) EM_error(pos, "record type mismatched"); expl_p = expl_h->tail; free(expl_h); return expTy(Tr_recordExp(expl_p, size), S_look(tenv, a->u.record.typ)); }
//check function call exp static struct expty transExpCall( S_table venv, S_table tenv, A_exp e) { //make sure e is funcall, just in case assertKind( e->pos, e->kind, A_callExp , "function call" ); //find function type in tenv E_entry funentry = (E_entry)S_look( venv, e->u.call.func ); //may be not a function name or can't find at all if( funentry == NULL) EM_error( e->pos , S_name( e->u.call.func ) , "not defined" ); if( funentry->kind != E_funEntry ) EM_error( e->pos , S_name( e->u.call.func ) , "is not function name" ); //traverse all arguments Ty_tyList params = funentry->fun.formalTys; A_expList args = e->u.call.args; for( ; args!=NULL && params!=NULL ; args = args->tail, params = params->tail ) { Ty_ty param = params->head; //evaluate argument exp first A_exp arg = args->head; struct expty exp = transExp( venv, tenv, arg ); assertKind( arg->pos, exp.ty->kind , param->kind , tyKindName(param->kind) ); } //if argument number satisfy argument list in function if( args != NULL ) EM_error( e->pos, "Too much arguments" ); else if( params != NULL ) EM_error( e->pos, "Expect more arguments" ); return _expTy( NULL, funentry->fun.resultTy ); }
int main(int argc, char **argv) { if (argc!=2) {fprintf(stderr,"usage: a.out filename\n"); exit(1);} S_table tenv = E_base_tenv(); S_table venv = E_base_venv(); transExp(venv, tenv, parse(argv[1])); return 0; }
void SEM_transProg(A_exp exp){ struct expty et; S_table t = E_base_tenv(); S_table v = E_base_venv(); et = transExp(Tr_outermost(), v, t, exp); printf("this exp return: %d\n", et.ty->kind); /* check the return result (use Ty_ty->kind stand) */ }
/* type-id { id = exp {, id = exp}} or type-id {} * the field names and types of the record exp must match * those of the named type, in the order given */ struct expty transRecordExp(S_table venv, S_table tenv, A_exp e) { Ty_ty recordType = S_look(tenv, e->u.record.typ); if (!recordType) { EM_error(e->pos, "undefined record type %s", S_name(e->u.record.typ)); return ExpTy(NULL, NULL); } A_efieldList efl = e->u.record.fields; Ty_fieldList tfl = recordType->u.record; while (efl && tfl) { if (efl->head->name != tfl->head->name) { EM_error(e->pos, "field name error %s", S_name(efl->head->name)); } if (transExp(venv, tenv, efl->head->exp).ty != tfl->head->ty) { EM_error(e->pos, "field type error %s", S_name(efl->head->name)); } efl = efl->tail; tfl = tfl->tail; } return ExpTy(NULL, recordType); }
struct expty transExp_opExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { A_oper oper = a->u.op.oper; struct expty left = transExp(level, venv, tenv, a->u.op.left , breakk); struct expty right = transExp(level, venv, tenv, a->u.op.right, breakk); if (oper == A_plusOp || oper == A_minusOp || oper == A_timesOp || oper == A_divideOp || oper == A_ltOp || oper == A_leOp || oper == A_gtOp || oper == A_geOp) { if (left.ty->kind != Ty_int) EM_error(a->u.op.left->pos, "operate of incompatible types"); if (right.ty->kind != Ty_int) EM_error(a->u.op.right->pos, "operate of incompatible types"); } if (oper == A_eqOp || oper == A_neqOp) { if (left.ty->kind != right.ty->kind && !(left.ty->kind == Ty_nil && right.ty->kind == Ty_record) && !(left.ty->kind == Ty_record && right.ty->kind == Ty_nil)) EM_error(a->u.op.right->pos, "same type required"); } Tr_exp op_exp; switch (oper) { case A_plusOp: op_exp = Tr_addOpExp( left.exp, right.exp); break; case A_minusOp: op_exp = Tr_minusOpExp( left.exp, right.exp); break; case A_timesOp: op_exp = Tr_timesOpExp( left.exp, right.exp); break; case A_divideOp: op_exp = Tr_divideOpExp(left.exp, right.exp); break; case A_ltOp: op_exp = Tr_ltOpExp( left.exp, right.exp); break; case A_leOp: op_exp = Tr_leOpExp( left.exp, right.exp); break; case A_gtOp: op_exp = Tr_gtOpExp( left.exp, right.exp); break; case A_geOp: op_exp = Tr_geOpExp( left.exp, right.exp); break; case A_eqOp: if (left.ty->kind == Ty_string) op_exp = Tr_stringEqExp(left.exp, right.exp); else op_exp = Tr_eqExp( left.exp, right.exp);break; case A_neqOp: if (left.ty->kind == Ty_string) op_exp = Tr_stringNeExp(left.exp, right.exp); else op_exp = Tr_neqExp( left.exp, right.exp); break; } return expTy(op_exp, Ty_Int()); }
static struct expty transVar(Tr_level level, Tr_exp breakk, S_table venv, S_table tenv, A_var v) { if (!v) {return expTy(Tr_noExp(), Ty_Void());} /*!those several var is ugly*/ E_enventry x; struct expty et,et2; Ty_fieldList fl; Tr_exp trans; switch (v->kind) { case A_simpleVar:/* var id (a)*/ x = S_look(venv, v->u.simple); trans = Tr_noExp(); if (x && x->kind == E_varEntry) { trans = Tr_simpleVar(x->u.var.access, level); return expTy(trans, actual_ty(x->u.var.ty)); } else { EM_error(v->pos, "undefined var %s", S_name(v->u.simple)); return expTy(trans, Ty_Int()); } break; case A_fieldVar:/* var record (a.b)*/ et = transVar(level, breakk, venv, tenv, v->u.field.var); trans = Tr_noExp(); if (et.ty->kind != Ty_record) { EM_error(v->pos, "not a record type"); } else { int i = 0; for (fl = et.ty->u.record; fl; fl = fl->tail, i++) { /*fl is Ty_fieldList*/ if (fl->head->name == v->u.field.sym) { trans = Tr_fieldVar(et.exp, i); return expTy(trans, actual_ty(fl->head->ty)); } } EM_error(v->pos, "no such field in record %s", S_name(v->u.field.sym)); } return expTy(trans, Ty_Int()); break; case A_subscriptVar: /*var array (a[b])*/ et = transVar(level, breakk, venv, tenv, v->u.subscript.var); trans = Tr_noExp(); if (et.ty->kind != Ty_array) { EM_error(v->pos, "not a array type"); } else { et2 = transExp(level, breakk, venv, tenv, v->u.subscript.exp); if (et2.ty->kind != Ty_int) { EM_error(v->pos, "int required"); } else { trans = Tr_subscriptVar(et.exp, et2.exp); return expTy(trans, actual_ty(et.ty->u.array)); } } return expTy(trans, Ty_Int()); default: assert(0); } }
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(); }
/* lvalue := exp * evaluates lvalue, then exp; set the contents of the lvalue * to the result of exp; check that the types of lvalue and * the exp are the same, but the whole assignment exp produce * no value, so (a := b) + c is illegal */ struct expty transAssignExp(S_table venv, S_table tenv, A_exp e) { struct expty lv = transVar(venv, tenv, e->u.assign.var); struct expty exp = transExp(venv, tenv, e->u.assign.exp); if (!Ty_is_compatible(lv.ty, exp.ty)) { EM_error(e->pos, "assignment types mismatch"); } return ExpTy(NULL, Ty_Void()); }
F_fragList SEM_transProg(A_exp exp){ struct expty et; S_table t = E_base_tenv(); S_table v = E_base_venv(); et = transExp(Tr_outermost(),NULL,v, t, exp); printf("@this expr return:\n"); /* check the return result (use Ty_ty->kind stand) */ F_fragList resl = Tr_getResult(); return resl; }
/* type-id[exp1] of exp2 * 1. type-id is array * 2. exp1 is integer */ struct expty transArrayExp(S_table venv, S_table tenv, A_exp e) { struct expty size = transExp(venv, tenv, e->u.array.size); struct expty init = transExp(venv, tenv, e->u.array.init); Ty_ty typ = S_look(tenv, e->u.array.typ); if (size.ty != Ty_Int()) { EM_error(e->pos, "type of array size is not integer"); } if (typ->kind != Ty_array) { EM_error(e->pos, "%s is not a array", S_name(e->u.array.typ)); } if (init.ty != typ->u.array) { EM_error(e->pos, "type of element of array mismatch"); } return ExpTy(NULL, typ); }
struct expty transExp_assignExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { struct expty lvar = transVar(level, venv, tenv, a->u.assign.var, breakk); struct expty rvar = transExp(level, venv, tenv, a->u.assign.exp, breakk); if (!has_same_ty(lvar.ty, rvar.ty)) EM_error( a->u.assign.exp->pos, "cannot initialize a variable of type '%s' with an rvalue of type '%s'", type_msg(lvar.ty), type_msg(rvar.ty)); return expTy(Tr_assignExp(lvar.exp, rvar.exp), Ty_Void()); }
struct expty transExp_arrayExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { Ty_ty typ = actual_ty(S_look(tenv, a->u.array.typ)); struct expty size = transExp(level, venv, tenv, a->u.array.size, breakk); struct expty init = transExp(level, venv, tenv, a->u.array.init, breakk); if (!typ || typ->kind != Ty_array) { EM_error(a->pos, "array type '%s' mismatched", S_name(a->u.array.typ)); return expTy(NULL, Ty_Void()); } if (size.ty->kind != Ty_int) EM_error(a->u.array.size->pos, "integer type required"); if (!has_same_ty(init.ty, typ->u.array)) EM_error( a->u.array.init->pos, "cannot initialize a variable of type '%s' with an rvalue of type '%s'", type_msg(typ), type_msg(init.ty)); return expTy(Tr_arrayExp(size.exp, init.exp), S_look(tenv, a->u.array.typ)); }
/* if exp1 then exp2 [else exp3] * 1. exp1 is integer type * 2. exp2 and exp3 are the same type if exp3 exists * 3. exp2 produce no value if exp3 does not exists */ struct expty transIfExp(S_table venv, S_table tenv, A_exp e) { struct expty test = transExp(venv, tenv, e->u.iff.test); struct expty then = transExp(venv, tenv, e->u.iff.then); if (test.ty != Ty_Int()) { EM_error(e->pos, "test exp of if is not integer"); } if (e->u.iff.elsee) { struct expty elsee = transExp(venv, tenv, e->u.iff.elsee); if (!Ty_is_compatible(then.ty, elsee.ty)) { EM_error(e->pos, "then and elsee type of if mismatch"); } return ExpTy(NULL, elsee.ty); } else { if (then.ty != Ty_Void()) { EM_error(e->pos, "then type of if is NOT void"); } return ExpTy(NULL, Ty_Void()); } }
/* for id := exp1 to exp2 do exp3 * 1. both exp1 and exp2 are integer type * 2. exp3 is void type * 3. id is a new variable implicitly declared by the for * statement, whose scope covers only exp3 */ struct expty transForExp(S_table venv, S_table tenv, A_exp e) { struct expty lo = transExp(venv, tenv, e->u.forr.lo); struct expty hi = transExp(venv, tenv, e->u.forr.hi); struct expty body; if (lo.ty != Ty_Int() || hi.ty != Ty_Int()) { EM_error(e->pos, "low or high range type is not integer"); } S_beginScope(venv); transDec(venv, tenv, A_VarDec(e->pos, e->u.forr.var, S_Symbol("int"), e->u.forr.lo)); body = transExp(venv, tenv, e->u.forr.body); if (body.ty != Ty_Void()) { EM_error(e->pos, "body of for is not void"); } S_endScope(venv); return ExpTy(NULL, Ty_Void()); }
struct expty transExp_ifExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { struct expty test = transExp(level, venv, tenv, a->u.iff.test, breakk); struct expty then = transExp(level, venv, tenv, a->u.iff.then, breakk); if (test.ty->kind != Ty_int) EM_error(a->u.iff.test->pos, "integer type required"); if (a->u.iff.elsee) { struct expty elsee = transExp(level, venv, tenv, a->u.iff.elsee, breakk); if (!has_same_ty(then.ty, elsee.ty)) EM_error(a->u.iff.elsee->pos, "types of then - else differ ('%s' and '%s')", type_msg(then.ty), type_msg(elsee.ty)); if (then.ty == Ty_Void()) return expTy(Tr_ifExp_noValue(test.exp, then.exp, elsee.exp), Ty_Void()); return expTy(Tr_ifExp(test.exp, then.exp, elsee.exp), then.ty); } if (then.ty->kind != Ty_void) EM_error(a->u.iff.then->pos, "if-then returns non unit"); return expTy(Tr_ifExp_noValue(test.exp, then.exp, NULL), then.ty); return expTy(NULL, Ty_Void()); }
struct expty transVar(S_table venv, S_table tenv, A_var v) { switch (v->kind) { case A_simpleVar: { E_enventry x = S_look(venv, v->u.simple); if (x && x->kind == E_varEntry) return expTy(NULL, actual_ty(x->u.var.ty)); else { //EM_error(v->pos, "undefined variable %s", S_name(v->u.simple)); return expTy(NULL, Ty_Int()); } } case A_fieldVar: { struct expty res = transVar(venv, tenv, v->u.field.var); Ty_ty ty = res.ty; if (ty->kind == Ty_record) { Ty_fieldList fieldList = ty->u.record; while (fieldList != NULL) { if (fieldList->head->name == v->u.field.sym) { return expTy(NULL, actual_ty(fieldList->head->ty)); } else { fieldList = fieldList->tail; } } //EM_error(v->pos, "undefined field %s", S_name(v->u.field.sym)); return expTy(NULL, Ty_Int()); } else { //EM_error(v->pos, "undefined field %s", S_name(v->u.field.sym)); return expTy(NULL, Ty_Int()); } } case A_subscriptVar: { struct expty res = transVar(venv, tenv, v->u.subscript.var); struct expty index = transExp(venv, tenv, v->u.subscript.exp); Ty_ty ty = res.ty; if (ty->kind == Ty_array && index.ty->kind == Ty_int) { return expTy(NULL, actual_ty(ty->u.array)); } else { EM_error(v->pos, "array index error"); return expTy(NULL, Ty_Int()); } } default: { assert(0); } } }
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); } } }
struct expty transExp_forExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { struct expty lo = transExp(level, venv, tenv, a->u.forr.lo, breakk); struct expty hi = transExp(level, venv, tenv, a->u.forr.hi, breakk); if (lo.ty->kind != Ty_int || hi.ty->kind != Ty_int) EM_error(a->u.forr.lo->pos, "lo or hi expr is not int"); /* * LET VAR i := lo * VAR lmt := hi * IN * IF lo < hi THEN * WHILE i <= lmt DO * (body; * i := i+1) */ A_pos pos1 = a->pos; A_pos pos2 = a->u.forr.body->pos; S_symbol var = a->u.forr.var; S_symbol lmt = S_Symbol("limit"); A_exp ebody = a->u.forr.body; A_exp transformed = A_LetExp(pos1, A_DecList(A_VarDec(pos1, var, S_Symbol("int"), a->u.forr.lo), A_DecList(A_VarDec(pos1, lmt, S_Symbol("int"), a->u.forr.hi), NULL)), A_IfExp(pos1, A_OpExp(pos1, A_ltOp, a->u.forr.lo, a->u.forr.hi), A_WhileExp(pos1, A_OpExp(pos1, A_leOp, A_VarExp(pos1, A_SimpleVar(pos1, var)), A_VarExp(pos1, A_SimpleVar(pos1, lmt))), A_SeqExp(pos2, A_ExpList(ebody, A_ExpList(A_OpExp(pos1, A_plusOp, A_VarExp(pos1, A_SimpleVar(pos1, var)), A_IntExp(pos1, 1)), A_ExpList(A_SeqExp(pos2, NULL), // return no value NULL))))), NULL) ); return transExp(level, venv, tenv, transformed, breakk); }
struct expty transExp_letExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { S_beginScope(venv); S_beginScope(tenv); Tr_expList h = Tr_ExpList(NULL, NULL), p = h; for (A_decList d = a->u.let.decs; d; d = d->tail) { p->tail = Tr_ExpList(transDec(level, venv, tenv, d->head, breakk), NULL); p = p->tail; } p = h->tail; free(h); struct expty body = transExp(level, venv, tenv, a->u.let.body, breakk); S_endScope(venv); S_endScope(tenv); return expTy(Tr_LetExp(p, body.exp), body.ty); }
static struct expty transVar(Tr_level level, S_table venv, S_table tenv, A_var v) { E_enventry x; struct expty et,et2; Ty_fieldList fl; switch (v->kind) { case A_simpleVar:/* var id (a)*/ x = S_look(venv, v->u.simple); if (x && x->kind == E_varEntry) { return expTy(NULL, actual_ty(x->u.var.ty)); } else { EM_error(v->pos, "undefined var %s", S_name(v->u.simple)); return expTy(NULL, Ty_Int()); } break; case A_fieldVar:/* var record (a.b)*/ et = transVar(level, venv, tenv, v->u.field.var); if (et.ty->kind != Ty_record) { EM_error(v->pos, "not a record type"); return expTy(NULL, Ty_Record(NULL)); } else { for (fl = et.ty->u.record; fl; fl = fl->tail) { if (fl->head->name == v->u.field.sym) { return expTy(NULL, actual_ty(fl->head->ty)); } } EM_error(v->pos, "no such field in record %s", S_name(v->u.field.sym)); } return expTy(NULL, Ty_Record(NULL)); break; case A_subscriptVar:/*var array (a[b])*/ et = transVar(level, venv, tenv, v->u.subscript.var); if (et.ty->kind != Ty_array) { EM_error(v->pos, "not a array type"); } else { et2 = transExp(level, venv, tenv, v->u.subscript.exp); if (et2.ty->kind != Ty_int) { EM_error(v->pos, "int required"); } else { return expTy(NULL, actual_ty(et.ty->u.array)); } } return expTy(NULL, Ty_Array(NULL)); default: assert(0); } }
F_fragList SEM_transProg(A_exp exp){ struct expty et; S_table t = E_base_tenv(); S_table v = E_base_venv(); //puts("@before trans:"); et = transExp(Tr_outermost(), NULL, v, t, exp); //puts("@end trans, begin pr-main:"); //if(!anyErrors) print(et.exp); else printf("@error cant pr"); //puts("\n@end pr-main, begin ref:"); //printf("this exp return: %d\n", et.ty->kind); //puts("@end ref, begin pr-frag"); //puts("@@@@@@@@@@@@@@@@@@@@@@@"); F_fragList resl = Tr_getResult(); //print_frag(resl); //puts("\n@end pr-falg"); return resl; }
struct expty transVar (S_table venv, S_table tenv, A_var v) { switch (v->kind) { case A_simpleVar: { E_enventry x = S_look (venv, v->u.simple); if (x && x->kind == E_varEntry) { return expTy (NULL, actual_ty (x->u.var.ty)); } else { EM_error (v->pos, "undefined variable %s", S_name (v->u.simple)); return expTy (NULL, Ty_Int()); } } case A_fieldVar: { struct expty var = transVar (venv, tenv, v->u.field.var); Ty_fieldList fList = var.ty->u.record; while (fList && fList->head->name != v->u.field.sym) { fList = fList->tail; } if (!fList) { EM_error (v->pos, "undefined subName %s", S_name (v->u.field.sym)); return expTy (NULL, Ty_Int()); } else { return expTy (NULL, actual_ty (fList->head->ty)); } } case A_subscriptVar: { struct expty var = transVar (venv, tenv, v->u.subscript.var); struct expty exp = transExp (venv, tenv, v->u.subscript.exp); if (exp.ty->kind != Ty_int) { EM_error (v->pos, "subscript should be int"); return expTy (NULL, Ty_Int()); } else { return expTy (NULL, actual_ty (var.ty->u.array)); } } } assert (0); }
struct expty transVar(S_table venv, S_table tenv, A_var v) { switch (v->kind) { case A_simpleVar: { E_enventry x = S_look(venv, v->u.simple); if (x && x->kind == E_varEntry) { return expTy(NULL, actual_ty(x->u.var.ty)); } EM_error(v->pos, (string)"undeclared variable '%s'", S_name(v->u.simple)); return expTy(NULL, Ty_Int()); } case A_fieldVar: { struct expty res = transVar(venv, tenv, v->u.field.var); Ty_ty ty = res.ty; if (ty->kind == Ty_record) { Ty_fieldList tfl = ty->u.record; for (tfl = ty->u.record; tfl; tfl = tfl->tail) { if (tfl->head->name == v->u.field.sym) { return expTy(NULL, actual_ty(tfl->head->ty)); } } EM_error(v->pos, "field '%s' not in record type", S_name(v->u.field.sym)); return expTy(NULL, Ty_Int()); } EM_error(v->pos, "variable not record"); return expTy(NULL, Ty_Int()); } case A_subscriptVar: { struct expty res = transVar(venv, tenv, v->u.subscript.var); struct expty index = transExp(venv, tenv, v->u.subscript.exp); Ty_ty ty = res.ty; if (ty->kind != Ty_array) { EM_error(v->pos, "variable not array"); return expTy(NULL, Ty_Int()); } if (index.ty->kind != Ty_int) { EM_error(v->pos, "array index error"); return expTy(NULL, Ty_Int()); } return expTy(NULL, actual_ty(ty->u.array)); } default: { assert(0); } } }