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)); }
Tr_exp transDec_typeDec(Tr_level level, S_table venv, S_table tenv, A_dec d, Temp_label breakk) { for (A_nametyList decs = d->u.type; decs; decs = decs->tail) { S_symbol name = decs->head->name; for (A_nametyList ds = d->u.type; ds != decs; ds = ds->tail) if (ds->head->name == name) EM_error(d->pos, "there are two types with the same name in the same batch of " "mutually recursive types"); S_enter(tenv, name, Ty_Name(name, NULL)); } for (A_nametyList decs = d->u.type; decs; decs = decs->tail) { Ty_ty type = S_look(tenv, decs->head->name); type->u.name.ty = transTy(level, tenv, decs->head->ty); } for (A_nametyList decs = d->u.type; decs; decs = decs->tail) { Ty_ty type = S_look(tenv, decs->head->name); if (type->u.name.sym == actual_ty(type)->u.name.sym) { EM_error(decs->head->ty->pos, "mutually recursive types declaration"); type->u.name.ty = Ty_Int(); } } return Tr_noExp(); }
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)); } } }
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(); }
/* 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); } } }
//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 ); }
Ty_tyList makeFormalTyList(S_table tenv, A_fieldList params) { A_fieldList ptr = params; Ty_tyList ret, ptr2; Ty_ty ty; ret = NULL; ptr2 = NULL; while(ptr != NULL) { ty = S_look(tenv, ptr->head->typ); if(ty != NULL) { if(ret == NULL) { ret = Ty_TyList(ty, NULL); ptr2 = ret; } else { ptr2->tail = Ty_TyList(ty, NULL); ptr2 = ptr2->tail; } } else { EM_error(ptr->head->pos, "undefined type %s", S_name(ptr->head->typ)); exit(1); } ptr = ptr->tail; } return ret; }
/* 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); }
Ty_tyList makeFormalTyList(S_table tenv, A_fieldList afields) { Ty_tyList head = Ty_TyList(NULL, NULL), slow = head; for (; afields; afields = afields->tail) { Ty_tyList fast = Ty_TyList(S_look(tenv, afields->head->typ), NULL); slow->tail = fast; slow = fast; } return head->tail; }
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); } }
Ty_tyList makeFormalTyList( S_table tenv, A_fieldList args) { if( args == NULL ) return NULL; A_field arg = args->head; Ty_ty ty = S_look( tenv, arg->typ ); if( ty == NULL ) EM_error( arg->pos, "wrong ty"); return Ty_TyList( ty, makeFormalTyList( tenv, args->tail ) ); }
A_exp A_StringExp(A_pos pos, S_table table, string s) {A_exp p = checked_malloc(sizeof(*p)); p->kind=A_stringExp; p->pos=pos; A_ty t=S_look(table,S_Symbol(s)); if(t==NULL) p->dec_type=S_Symbol(s); else p->dec_type=t->dec_type; p->u.stringg=s; return p; }
struct expty transVar_simpleVar(Tr_level level, S_table venv, S_table tenv, A_var v, Temp_label breakk) { E_enventry x = S_look(venv, v->u.simple); if (!x || x->kind != E_varEntry) { EM_error(v->pos, "undeclared variable '%s'", S_name(v->u.simple)); return expTy(NULL, Ty_Int()); } return expTy(Tr_simpleVar(x->u.var.access, level), actual_ty(x->u.var.ty)); }
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)); }
Ty_tyList makeFormalTyList (S_table tenv, A_fieldList params) { Ty_tyList tList = NULL; A_fieldList pList = NULL; for (pList = params; pList; pList = pList->tail) { Ty_ty ty = S_look (tenv, pList->head->typ); tList = Ty_TyList (ty, tList); } return tList; }
static Ty_fieldList dfsRecordTy( S_table tenv , A_fieldList records ) { if( records == NULL ) return NULL ; A_field record = records->head ; Ty_ty type = S_look( tenv , record->typ ); Ty_field field; if( type == NULL ) field = Ty_Field( record->name , Ty_Name( record->typ , NULL ) ); else field = Ty_Field( record->name , type ); Ty_fieldList rest = dfsRecordTy( tenv , records->tail ); return Ty_FieldList( field , rest ); }
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); } } }
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); } }
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); } } }
// translate function call: check that arguments match the // formal params struct expty transCallExp(S_table venv, S_table tenv, A_exp e) { E_enventry ee = S_look(venv, e->u.call.func); if (!ee) { EM_error(e->pos, "undefined function %s", S_name(e->u.call.func)); return ExpTy(NULL, NULL); } Ty_tyList formals = ee->u.fun.formals; A_expList args = e->u.call.args; for (; formals && args; formals = formals->tail, args = args->tail) { if (!Ty_is_compatible(formals->head, transExp(venv, tenv, args->head).ty)) { EM_error(e->pos, "arguments type mismatch"); return ExpTy(NULL, NULL); } } return ExpTy(NULL, ee->u.fun.result); }
struct expty transVar(S_table venv, S_table tenv, A_var v) { switch( v->kind ) { case A_simpleVar: { string varName = S_name( v->u.simple ); E_entry var = (E_entry) S_look( venv , v->u.simple ); if( var == NULL ) EM_error( v->pos , "can't find" , varName); if( var->kind != E_varEntry ) EM_error( v->pos , varName , " is not variable " ); return _expTy( NULL , var->var ); } case A_fieldVar: { struct expty var = transVar( venv , tenv , v->u.field.var); Ty_ty varType = var.ty; string fieldName = S_name( v->u.field.sym ); if( varType->kind != Ty_record ) EM_error( v->pos , " is not record " ); Ty_fieldList fields = varType->u.record; for( ; fields != NULL ; fields = fields->tail ) { Ty_field field = fields->head ; if( field->name == v->u.field.sym ) return _expTy( NULL , field->ty ); } EM_error( v->pos , "can't find field " , S_name( v->u.field.sym ) ); } case A_subscriptVar: { struct expty var = transVar( venv , tenv , v->u.subscript.var ); struct expty subs = transExp( venv , tenv , v->u.subscript.exp ); if( subs.ty->kind != Ty_int ) EM_error( v->pos , "array subs should be int" ); return var; } default : assert(0); } }
/* 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); }
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); }
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, x->u.var.ty); else { EM_error(v->pos, "undefined variable %s", S_name(v->u.simple)); return ExpTy(NULL, NULL); } } case A_fieldVar: { struct expty et = transVar(venv, tenv, v->u.field.var); if (et.ty && et.ty->kind == Ty_record) { Ty_fieldList fl = et.ty->u.record; for(; fl; fl = fl->tail) { if (fl->head->name == v->u.field.sym) { return ExpTy(NULL, fl->head->ty); } } } // can NOT get the v's name, use field name instaed EM_error(v->pos, "undefined variable %s", S_name(v->u.field.sym)); return ExpTy(NULL, NULL); } case A_subscriptVar: { struct expty et = transVar(venv, tenv, v->u.field.var); if (et.ty && et.ty->kind == Ty_array) { return ExpTy(NULL, et.ty->u.array); } // can NOT get v's name EM_error(v->pos, "undefined variable"); return ExpTy(NULL, NULL); } } }
static Ty_ty dfsTypeDec( A_pos pos , S_table tenv , S_symbol s , S_symbol origin ) { if( s == origin ) { EM_error( pos , " loop in definition " , S_name(s) ); return NULL ; } Ty_ty ty = S_look( tenv , s ); if( ty == NULL ) EM_error( pos , " can't find " , s ); if( ty->kind == Ty_name ) { if( ty->u.name.ty == NULL ) ty->u.name.ty = dfsTypeDec( pos , tenv , ty->u.name.sym , origin ); return ty->u.name.ty; } return ty; }
/* 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); }
Ty_tyList makeFormalTyList(S_table tenv, A_fieldList fieldList) { A_fieldList fl = fieldList; Ty_tyList tl = NULL; Ty_tyList ret = NULL; Ty_ty ty; // 从左到右构造参数 for (; fl; fl = fl->tail) { ty = S_look(tenv, fl->head->typ); if (ty) { if (tl) { tl = tl->tail = Ty_TyList(ty, NULL); } else { ret = tl = Ty_TyList(ty, tl); } } else { EM_error(fl->head->pos, "undefined type %s", S_name(fl->head->typ)); } } return ret; }