Ty_ty transTy (S_table tenv, A_ty a) { switch (a->kind) { case A_nameTy: { return Ty_Name (a->u.name, S_look (tenv, a->u.name)); } case A_recordTy: { Ty_fieldList fieldList = NULL; A_fieldList a_fieldList = NULL; for (a_fieldList = a->u.record; a_fieldList; a_fieldList = a_fieldList->tail) { S_symbol name = a_fieldList->head->name; S_symbol typ = a_fieldList->head->typ; //printf("%s ", S_name (name)); //printf("%s\n", S_name (typ)); Ty_ty ty = S_look (tenv, typ); //S_enter(tenv, name, ty); fieldList = Ty_FieldList (Ty_Field (name, ty), fieldList); } return Ty_Record (fieldList); } case A_arrayTy: { return Ty_Array (S_look (tenv, a->u.array)); } } assert (0); }
Ty_ty transTy(Tr_level level, S_table tenv, A_ty a) { switch (a->kind) { case A_nameTy: { return Ty_Name(a->u.name, S_look(tenv, a->u.name)); } case A_recordTy: { Ty_fieldList h = Ty_FieldList(NULL, NULL), p = h, fields; for (A_fieldList efields = a->u.record; efields; efields = efields->tail) { Ty_ty typ = S_look(tenv, efields->head->typ); if (!typ) { EM_error(efields->head->pos, "type '%s' undefined", S_name(efields->head->name)); typ = Ty_Int(); } p->tail = Ty_FieldList(Ty_Field(efields->head->name, typ), NULL); p = p->tail; } fields = h->tail; free(h); return Ty_Record(fields); } case A_arrayTy: { return Ty_Array(S_look(tenv, a->u.array)); } } }
/* translate A_ty in AST to real type representation */ Ty_ty transTy(S_table tenv, S_symbol ty_name, A_ty t) { switch(t->kind) { case A_nameTy: { Ty_ty ty = S_look(tenv, t->u.name); if (ty) return Ty_Name(ty); else return NULL; } case A_recordTy: { A_fieldList a_record = NULL; A_field a_field = NULL; Ty_fieldList t_record = NULL; Ty_fieldList saved_t_record = NULL; Ty_ty ty = NULL; /* we only allow record field type to refer itself or already defined * type: type record = { id : record, id : other_defined_type } */ for (a_record = t->u.record; a_record; a_record = a_record->tail) { a_field = a_record->head; ty = S_look(tenv, a_field->typ); if (ty_name == a_field->typ || ty) { if (t_record) { t_record->tail = Ty_FieldList(Ty_Field(a_field->name, ty), NULL); t_record = t_record->tail; } else { t_record = Ty_FieldList(Ty_Field(a_field->name, ty), NULL); saved_t_record = t_record; } } else { EM_error(a_field->pos, "undefined type %s", S_name(a_field->typ)); return NULL; } } // fill the record's self-recursive reference Ty_ty new_record = Ty_Record(saved_t_record); Ty_fieldList tfl = NULL; for (tfl = t_record; tfl; tfl = tfl->tail) { if (!tfl->head->ty) { tfl->head->ty = new_record; } } return new_record; } case A_arrayTy: { Ty_ty ty = S_look(tenv, t->u.array); if (ty) return Ty_Array(ty); else return NULL; } } }
Ty_ty transTy(S_table tenv, A_ty a) { assert(a != NULL); switch (a->kind) { case A_nameTy: { Ty_ty ty = S_look(tenv, a->u.name); if (ty != NULL) { return ty; } else { return Ty_Int(); } } case A_recordTy: { if (!a->u.record) { return Ty_Record(NULL); } Ty_fieldList tfl, tfl_p; tfl = tfl_p = NULL; A_fieldList fl; for (fl = a->u.record; fl; fl = fl->tail) { Ty_ty ty = S_look(tenv, fl->head->typ); if (!ty) { EM_error(a->pos, "undefined field type"); return Ty_Int(); } if (tfl) { tfl_p->tail = Ty_FieldList(Ty_Field(fl->head->name, ty), NULL); tfl_p = tfl_p->tail; } else { tfl = Ty_FieldList(Ty_Field(fl->head->name, ty), NULL); tfl_p = tfl; } } return Ty_Record(tfl); } case A_arrayTy: { Ty_ty ty; ty = S_look(tenv, a->u.array); if (ty != NULL) { return Ty_Array(ty); } else { return Ty_Int(); } } default: { assert(0); } } }
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); } }
static struct expty transExp(Tr_level level, S_table v, S_table t, A_exp e){ A_oper oper; struct expty left, right, final, final2, final3, final4, final5, lo, hi; A_expList list; A_decList decs; E_enventry callinfo; Ty_ty recty, arrayty; switch (e->kind) { case A_varExp: return transVar(level, v, t, e->u.var); case A_nilExp: return expTy(NULL, Ty_Nil()); case A_callExp: callinfo = S_look(v, e->u.call.func); /*get params and return from tenv*/ if (callinfo && callinfo->kind == E_funEntry){ if (args_match(level, v, t, e->u.call.args, callinfo->u.fun.formals, e)) {/*check params is matched*/ if (callinfo->u.fun.result) { return expTy(NULL, actual_ty(callinfo->u.fun.result)); } else { return expTy(NULL, Ty_Void()); } } } else { EM_error(e->pos, "undefined function %s\n", S_name(e->u.call.func)); } return expTy(NULL, Ty_Void()); case A_recordExp: recty = actual_ty(S_look(t, e->u.record.typ)); if (!recty) { /*cant find record-type in table tenv*/ EM_error(e->pos, "undefined type %s (debug recordExp)", S_name(e->u.record.typ)); } else { if (recty->kind != Ty_record){ EM_error(e->pos, "%s is not a record type", S_name(e->u.record.typ)); return expTy(NULL, Ty_Record(NULL)); } if (efields_match(level, v, t, recty, e)) {/*check record field is matched*/ return expTy(NULL, recty); } } return expTy(NULL, Ty_Record(NULL)); case A_arrayExp: arrayty = actual_ty(S_look(t, e->u.array.typ)); if (!arrayty) { EM_error(e->pos, "undeined array type %s", S_name(e->u.array.typ)); return expTy(NULL, Ty_Array(NULL)); } if (arrayty->kind != Ty_array) { EM_error(e->pos, "%s is not a array type", S_name(e->u.array.typ)); return expTy(NULL, Ty_Array(NULL)); } final2 = transExp(level, v, t, e->u.array.size); final3 = transExp(level, v, t, e->u.array.init); if (final2.ty->kind != Ty_int) { EM_error(e->pos, "array size should be int %s", S_name(e->u.array.typ)); } else if (!ty_match(final3.ty, arrayty->u.array)){ EM_error(e->pos, "unmatched array type in %s", S_name(e->u.array.typ)); } else { return expTy(NULL, arrayty); } return expTy(NULL, Ty_Array(NULL)); case A_seqExp: list = e->u.seq; if (!list) { return expTy(NULL, Ty_Void()); } while (list->tail) { transExp(level, v, t, list->head); list = list->tail; } return transExp(level, v, t, list->head); case A_whileExp: final = transExp(level, v, t, e->u.whilee.test); if (final.ty->kind != Ty_int) { EM_error(e->pos, "int required"); } transExp(level, v, t, e->u.whilee.body); return expTy(NULL, Ty_Void()); case A_assignExp: final4 = transVar(level, v, t, e->u.assign.var); final5 = transExp(level, v, t, e->u.assign.exp); if (!ty_match(final4.ty, final5.ty)) { EM_error(e->pos, "unmatched assign exp"); } return expTy(NULL, Ty_Void()); case A_breakExp: return expTy(NULL, Ty_Void()); case A_forExp: { struct expty lo = transExp(level, v, t, e->u.forr.lo); struct expty hi = transExp(level, v, t, 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(v); transDec(level, v, t, A_VarDec(e->pos, e->u.forr.var, S_Symbol("int"), e->u.forr.lo)); body = transExp(level, v, t, e->u.forr.body); S_endScope(v); return expTy(NULL, Ty_Void()); } case A_letExp: S_beginScope(v); S_beginScope(t); for (decs = e->u.let.decs; decs; decs = decs->tail) { transDec(level, v, t, decs->head); } final = transExp(level, v, t, e->u.let.body); S_endScope(v); S_endScope(t); return final; case A_opExp: oper = e->u.op.oper; left = transExp(level, v, t, e->u.op.left); right = transExp(level, v, t, e->u.op.right); if (0 <= oper && oper < 4) {/* check +,-,*,/ */ if (left.ty->kind != Ty_int && left.ty->kind != Ty_double){ EM_error(e->u.op.left->pos, "int or double required(op)"); } if (right.ty->kind != Ty_int && right.ty->kind != Ty_double) { EM_error(e->u.op.right->pos, "int or double required(op)"); } if (left.ty->kind == Ty_int && right.ty->kind == Ty_int && oper != 3) { return expTy(NULL, Ty_Int()); } else { /*TODO divide when return double when return int*/ /* return expTy(NULL, Ty_Int()); */ return expTy(NULL, Ty_Int()); } } else if (3 < oper && oper < 10) { if (oper == 4 || oper == 5) {/*check record type can be nil*/ if (left.ty->kind == Ty_record && right.ty->kind == Ty_nil) { return expTy(NULL, Ty_Int()); } if (left.ty->kind == Ty_nil && right.ty->kind == Ty_record) { return expTy(NULL, Ty_Int()); } } if(left.ty->kind != Ty_int && left.ty->kind != Ty_double && left.ty->kind != Ty_string){ EM_error(e->u.op.left->pos, "int or double or record-nil required"); } if (right.ty->kind != Ty_int && right.ty->kind != Ty_double && right.ty->kind !=Ty_string) { EM_error(e->u.op.right->pos, "int or double or record-nil required"); } return expTy(NULL, Ty_Int()); } else { assert(0); } case A_ifExp: final = transExp(level, v, t, e->u.iff.test); final2 = transExp(level, v, t, e->u.iff.then); if (e->u.iff.elsee) { /*no else-part*/ final3 = transExp(level, v, t, e->u.iff.elsee); if (final.ty->kind != Ty_int){ EM_error(e->u.iff.test->pos, "int required"); } else if(!ty_match(final2.ty, final3.ty)) {
Ty_ty transTy(S_table tenv, A_ty a) { assert(a != NULL); switch(a->kind) { case A_nameTy: { Ty_ty ty = S_look(tenv, a->u.name); if(ty != NULL) { return ty; } else { //EM_error(a->pos, "undefined type %s", S_name(a->u.name)); return Ty_Int(); } } case A_recordTy: { Ty_ty ty,ty2; Ty_fieldList fields,tailptr; A_fieldList afields; if(a->u.record == NULL) { fields = NULL; ty = Ty_Record(fields); return ty; } else { fields = tailptr = NULL; afields = a->u.record; while(afields != NULL) { ty2 = S_look(tenv, afields->head->typ); if(ty2 != NULL) { if(fields == NULL) { fields = Ty_FieldList(Ty_Field(afields->head->name, ty2), NULL); tailptr = fields; } else { tailptr->tail = Ty_FieldList(Ty_Field(afields->head->name, ty2), NULL); tailptr = tailptr->tail; } } else { //EM_error(a->pos, "undefined field type"); return Ty_Int(); } afields = afields->tail; } ty = Ty_Record(fields); return ty; } } case A_arrayTy: { Ty_ty ty; ty = S_look(tenv, a->u.array); if(ty != NULL) { return Ty_Array(ty); } else { //EM_error(a->pos, "undefined type %s", S_name(a->u.array)); return Ty_Int(); } } default: { assert(0); } } }
//here static struct expty transExp(Tr_level level,Tr_exp breakk,S_table v, S_table t, A_exp e){ A_oper oper; struct expty left,right,final,final2,final3,final4,final5,lo,hi; A_expList list; A_decList decs; E_enventry callinfo; Ty_ty recty,arrayty; if (!e) { return expTy(Tr_noExp(), Ty_Void()); } switch(e->kind){ case A_varExp: return transVar(level,breakk,v,t,e->u.var); break; case A_nilExp: return expTy(Tr_nilExp(),Ty_Nil()); break; case A_callExp: callinfo =S_look(v,e->u.call.func); A_expList args=NULL; Tr_expList argList=NULL; for (args=e->u.call.args;args;args=args->tail){ struct expty arg = transExp(level, breakk, v, t, args->head); Tr_expList_prepend(arg.exp, &argList); } Tr_exp trans = Tr_noExp(); if (callinfo&&callinfo->kind==E_funEntry) { trans = Tr_callExp(callinfo->u.fun.label, callinfo->u.fun.level, level, &argList); //检查参数个数、类型匹配 if (args_match(level, breakk, v, t, e->u.call.args, callinfo->u.fun.formals, e)) {/*check params is matched*/ if (callinfo->u.fun.result) { return expTy(trans, actual_ty(callinfo->u.fun.result)); } } /* if (args_match(level,v,t,e->u.call.args,callinfo->u.fun.formals,e)){ return expTy(NULL, actual_ty(callinfo->u.fun.result)); }else{ return expTy(NULL, Ty_Void()); } */ }else { EM_error(e->pos, "undefined function %s\n", S_name(e->u.call.func)); } return expTy(trans, Ty_Void()); break; case A_recordExp: recty = actual_ty(S_look(t, e->u.record.typ)); if (!recty) { /*cant find record-type in table tenv*/ EM_error(e->pos, "undefined type %s (debug recordExp)", S_name(e->u.record.typ)); }else{ if (recty->kind != Ty_record){ EM_error(e->pos, "%s is not a record type", S_name(e->u.record.typ)); return expTy(Tr_noExp(), Ty_Record(NULL)); } if (efields_match(level,breakk,v, t, recty, e)) {/*check record field is matched*/ Tr_expList l=NULL; int n=0; A_efieldList el; for (el=e->u.record.fields;el;el=el->tail,n++){ struct expty val = transExp(level, breakk, v, t, el->head->exp); Tr_expList_prepend(val.exp,&l); } return expTy(Tr_recordExp(n, l), recty); } } return expTy(Tr_noExp(), Ty_Record(NULL)); break; case A_arrayExp: arrayty=actual_ty(S_look(t,e->u.array.typ)); if (!arrayty) { EM_error(e->pos, "undeined array type %s", S_name(e->u.array.typ)); return expTy(Tr_noExp(), Ty_Array(NULL)); } if (arrayty->kind != Ty_array) { EM_error(e->pos, "%s is not a array type", S_name(e->u.array.typ)); return expTy(Tr_noExp(), Ty_Array(NULL)); } final2 = transExp(level,breakk,v, t, e->u.array.size);//数组大小 表达式 final3 = transExp(level,breakk,v, t, e->u.array.init);//数组初始化 表达式 if (final2.ty->kind != Ty_int) { EM_error(e->pos, "array size should be int %s", S_name(e->u.array.typ)); }else if (!ty_match(final3.ty, arrayty->u.array)){ EM_error(e->pos, "unmatched array type in %s", S_name(e->u.array.typ)); } else { return expTy(Tr_arrayExp(final2.exp, final3.exp), arrayty); } return expTy(Tr_noExp(), Ty_Int()); break; case A_seqExp:{ Tr_expList l = NULL; list = e->u.seq; struct expty seqone; if (!list) { return expTy(Tr_noExp(), Ty_Void()); } /*while (list->tail) { seqone= transExp(level,breakk,v, t, list->head); Tr_expList_prepend(seqone.exp, &l); list = list->tail; } */ for (; list; list = list->tail) { seqone = transExp(level, breakk, v, t, list->head); Tr_expList_prepend(seqone.exp, &l); } printf("A_seqExp\n"); return expTy(Tr_seqExp(l), seqone.ty); } break; case A_whileExp: final = transExp(level,breakk,v, t, e->u.whilee.test); if (final.ty->kind != Ty_int) { EM_error(e->pos, "int required"); } Tr_exp done = Tr_doneExp(); struct expty body=transExp(level,done,v, t, e->u.whilee.body); return expTy(Tr_whileExp(final.exp, body.exp, done), Ty_Void()); break; case A_assignExp: final4 = transVar(level,breakk,v, t, e->u.assign.var); final5 = transExp(level,breakk,v, t, e->u.assign.exp); if (!ty_match(final4.ty, final5.ty)) { EM_error(e->pos, "unmatched assign exp"); } return expTy(Tr_assignExp(final4.exp, final5.exp), Ty_Void()); case A_breakExp: if (!breakk) return expTy(Tr_noExp(), Ty_Void()); return expTy(Tr_breakExp(breakk), Ty_Void()); case A_forExp:{ /* struct expty lo = transExp(level,v, t, e->u.forr.lo); struct expty hi = transExp(level,v, t, 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(v); transDec(level,v, t, A_VarDec(e->pos, e->u.forr.var, S_Symbol("int"), e->u.forr.lo)); body = transExp(level,v, t, e->u.forr.body); S_endScope(v); return expTy(NULL, Ty_Void()); */ EM_error(e->pos, "\nsome one said for is better than while\nmake them unhappy \nahahaha"); return expTy(Tr_noExp(), Ty_Int()); } break; case A_letExp:{ Tr_expList l = NULL; S_beginScope(v); S_beginScope(t); for (decs=e->u.let.decs;decs;decs=decs->tail){ //transDec(level,v,t,decs->head); ; Tr_expList_prepend(transDec(level, breakk, v, t, decs->head), &l); } final=transExp(level,breakk,v,t,e->u.let.body); Tr_expList_prepend(final.exp, &l); S_endScope(t); S_endScope(v); printf("A_letExp\n"); return expTy(Tr_seqExp(l), final.ty);; } break; case A_opExp:{ A_oper oper = e->u.op.oper; struct expty left = transExp(level, breakk, v, t, e->u.op.left); struct expty right = transExp(level, breakk, v, t, e->u.op.right); if (0 <= oper && oper < 4) {/* check +,-,*,/ */ if (left.ty->kind != Ty_int ){ EM_error(e->u.op.left->pos, "int or double required(op)"); } else if (left.ty->kind == Ty_int && right.ty->kind == Ty_int) { return expTy(Tr_arithExp(oper, left.exp, right.exp), Ty_Int()); } return expTy(Tr_noExp(), Ty_Int()); } else if (3 < oper && oper < 10) { Tr_exp translation = Tr_noExp(); if (oper == 4 || oper == 5) {/*check record type can be nil(=, <>)*/ switch(left.ty->kind) { case Ty_int: //case Ty_double:/*see is double query like int TODO*/ if (right.ty->kind == Ty_int ) translation = Tr_eqExp(oper, left.exp, right.exp); else {EM_error(e->u.op.right->pos, "unexpected type in comparsion");} break; case Ty_string: if (ty_match(right.ty, left.ty)) translation = Tr_eqStringExp(oper, left.exp, right.exp); else {EM_error(e->u.op.right->pos, "unexpected type in comparsion");} break; case Ty_array: if (ty_match(right.ty, left.ty)) translation = Tr_eqRef(oper, left.exp, right.exp); else {EM_error(e->u.op.right->pos, "unexpected type in comparsion");} break; case Ty_record: if (ty_match(right.ty, left.ty) || right.ty->kind == Ty_nil) translation = Tr_eqRef(oper, left.exp, right.exp); else {EM_error(e->u.op.right->pos, "unexpected type in comparsion");} break; default: EM_error(e->u.op.right->pos, "unexpected expression in comparsion"); } return expTy(translation, Ty_Int()); } else { switch(left.ty->kind) { //case Ty_double: case Ty_int: if ( right.ty->kind == Ty_int) translation = Tr_relExp(oper, left.exp, right.exp); else {EM_error(e->u.op.right->pos, "unexpected type in comparsion");} break; case Ty_string: if (right.ty->kind == Ty_string) translation = Tr_eqStringExp(oper, left.exp, right.exp); else {EM_error(e->u.op.right->pos, "unexpected type in comparsion");} break; default: EM_error(e->u.op.right->pos, "unexpected type in comparsion"); } return expTy(translation, Ty_Int()); } } else { assert(0); } } break; case A_ifExp: final = transExp(level,breakk,v, t, e->u.iff.test); final2 = transExp(level,breakk,v, t, e->u.iff.then); //final3 = {NULL, NULL}; if (e->u.iff.elsee) { /*no else-part*/ final3 = transExp(level,breakk,v, t, e->u.iff.elsee); if (final.ty->kind != Ty_int){ EM_error(e->u.iff.test->pos, "int required"); } else if(!ty_match(final2.ty, final3.ty)) {