Ejemplo n.º 1
0
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);
	}
}
Ejemplo n.º 2
0
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();
}
Ejemplo n.º 3
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();
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
static struct expty transExp(Tr_level level, Tr_exp breakk, S_table v, S_table t, A_exp e){
    if (!e) { return expTy(Tr_noExp(), Ty_Void()); }
	switch (e->kind) {
	case A_varExp:
		return transVar(level, breakk, v, t, e->u.var);
	case A_nilExp:
		return expTy(Tr_nilExp(), Ty_Nil());
	case A_callExp: {
		E_enventry callinfo = S_look(v, e->u.call.func); /*get params and return from tenv*/
		A_expList args = NULL;
		Tr_expList argList = NULL;
        Ty_tyList formals;
		
		Tr_exp trans = Tr_noExp();
		if (callinfo && callinfo->kind == E_funEntry){
            formals = callinfo->u.fun.formals;
            /*
			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));
				} 
			}*/
            for (args = e->u.call.args; args && formals; args = args->tail, formals = formals->tail) { /*memory args-info by order*/
                struct expty arg = transExp(level, breakk, v, t, args->head);
                if (!ty_match(arg.ty, formals->head)) EM_error(args->head->pos, "unmatched type in function %s", S_name(e->u.call.func));
                Tr_expList_prepend(arg.exp, &argList);			
		    }
            if (!args && formals) EM_error(e->pos, "short few paras");
            if (args && !formals) EM_error(e->pos, "too many paras");
			trans = Tr_callExp(callinfo->u.fun.label, callinfo->u.fun.level, level, &argList);
            return expTy(trans, actual_ty(callinfo->u.fun.result));
		} else {
			EM_error(e->pos, "undefined function %s\n", S_name(e->u.call.func));
            return expTy(trans, Ty_Int());
		}
	}
	case A_recordExp: {/*record create*/
		Ty_ty 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);
			}*/
            Ty_fieldList fieldTys = recty->u.record;
			A_efieldList recList;
			Tr_expList list = NULL;
			int n = 0;
			for (recList = e->u.record.fields; recList; recList = recList->tail, fieldTys = fieldTys->tail, n++) {
				struct expty et = transExp(level, breakk, v, t, recList->head->exp);
				if (recList->head->name != fieldTys->head->name) EM_error(e->pos, "%s not a valid field name", recList->head->name);
				if (!ty_match(fieldTys->head->ty, et.ty)) EM_error(recList->head->exp->pos, "type error: given %s but expected %s");
				Tr_expList_prepend(et.exp, &list);
			}
			return expTy(Tr_recordExp(n, list), recty);

		}
		return expTy(Tr_noExp(), Ty_Record(NULL));
		}
	case A_arrayExp: {/*array create*/
		Ty_ty 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_Int());
		}
		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_Int());
		}
	    struct expty final2 = transExp(level, breakk, v, t, e->u.array.size);
		struct expty 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());
	}
	case A_seqExp: {
		Tr_expList l = NULL;
		A_expList list = e->u.seq;
		struct expty seqone;
		if (!list) {
			return expTy(Tr_noExp(), Ty_Void());
		}
		for (; list; list = list->tail) {
			seqone = transExp(level, breakk, v, t, list->head);
			Tr_expList_prepend(seqone.exp, &l);
		}
		return expTy(Tr_seqExp(l), seqone.ty);
	}
	case A_whileExp: {
		struct expty 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());
	}
	case A_assignExp: {
		struct expty final4 = transVar(level, breakk, v, t, e->u.assign.var);
		struct expty 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: {
		EM_error(e->pos, "\nsome one said for is better than while\nmake them unhappy \nahahaha");
		return expTy(Tr_noExp(), Ty_Int());
	}
	case A_letExp: {
		A_decList decs;
		Tr_expList l = NULL;
		S_beginScope(v);
		S_beginScope(t);
		for (decs = e->u.let.decs; decs; decs = decs->tail) {
			Tr_expList_prepend(transDec(level, breakk, v, t, decs->head), &l);
		}
		struct expty final = transExp(level, breakk, v, t, e->u.let.body);
		Tr_expList_prepend(final.exp, &l);
		S_endScope(v);
		S_endScope(t);
		return expTy(Tr_seqExp(l), final.ty);
	}
	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 && left.ty->kind != Ty_double){
				EM_error(e->u.op.left->pos, "int or double required(op)");	
			} else if (right.ty->kind != Ty_int && right.ty->kind != Ty_double) {
				EM_error(e->u.op.right->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());
			} else {
				return expTy(Tr_arithExp(oper, left.exp, right.exp), Ty_Double());
			}
			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 || right.ty->kind == Ty_double) 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_double || 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);	
		}
	}
	case A_ifExp: {
		struct expty final =  transExp(level, breakk, v, t, e->u.iff.test);
		struct expty final2 = transExp(level, breakk, v, t, e->u.iff.then);
		struct expty 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");
			} 
			if(!ty_match(final2.ty, final3.ty)) {
				EM_error(e->pos, "if-else sentence must return same type");
			}
		}
		return expTy(Tr_ifExp(final.exp, final2.exp, final3.exp), final2.ty);
	}
	case A_stringExp:
		return expTy(Tr_stringExp(e->u.stringg), Ty_String());
	case A_intExp:
		return expTy(Tr_intExp(e->u.intt), Ty_Int());
	case A_doubleExp:
		return expTy(Tr_doubleExp(e->u.doublee), Ty_Double());
	default:
		assert(0);
	}
Ejemplo n.º 6
0
Archivo: semant.c Proyecto: 0XCC1/tiger
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());
	}
	E_enventry x;
	struct expty et,et2;
	Ty_fieldList fl;
	Tr_exp trans;

	switch(v->kind){
		case A_simpleVar: /*var id*/
			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:/* a.b   a.b.c*/
			//得到 a  的type 是 record还是 array还是 simplevar
			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");
				return expTy(NULL, Ty_Record(NULL));
			}else{
				int i=0;
				for (fl = et.ty->u.record;fl;fl=fl->tail,i++)
				{
					//地址比较
					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:/*a[i]*/
			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());
		break;
	}

}
Ejemplo n.º 7
0
Archivo: semant.c Proyecto: 0XCC1/tiger
//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)) {