示例#1
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();
}
示例#2
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);
			 }
	}
}
示例#3
0
Tr_exp transDec_varDec(Tr_level level, S_table venv, S_table tenv, A_dec d, Temp_label breakk) {
  struct expty init = transExp(level, venv, tenv, d->u.var.init, breakk);

  if (d->u.var.typ) {
    Ty_ty typ = S_look(tenv, d->u.var.typ);

    if (!has_same_ty(typ, init.ty))
      EM_error(d->u.var.init->pos,
               "cannot initialize a variable of type '%s' with an rvalue of "
               "type '%s'",
               type_msg(typ), type_msg(init.ty));
  } else if (init.ty->kind == Ty_nil)
    EM_error(d->u.var.init->pos,
             "cannot initialize a nil type without specified record type");

  Tr_access access = Tr_allocLocal(level, TRUE); // todo check escape = false
  S_enter(venv, d->u.var.var, E_VarEntry(access, init.ty));

  return Tr_assignExp(Tr_simpleVar(access, level), init.exp);
}
示例#4
0
/* 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);
}
示例#5
0
/* translate variable declaration
 * var id:type-id := exp
 */
void transVarDec(S_table venv, S_table tenv, A_dec d)
{
  struct expty e = transExp(venv, tenv, d->u.var.init);
  if (d->u.var.typ) {
    /* 1. check the type constraint if any
     * 2. init value of type Ty_Nil must be constrainted 
     * by a Ty_Record type
     */
    Ty_ty expected_ty = S_look(tenv, d->u.var.typ);
    if (!expected_ty) {
      EM_error(d->pos, "undefined type %s", S_name(d->u.var.typ));
      return;
    }

    if ((expected_ty->kind != Ty_record && e.ty == Ty_Nil())
        || expected_ty != e.ty) {
      EM_error(d->pos, "inconsistent var type %s",
          S_name(d->u.var.var));
      return;
    }
  }

  S_enter(venv, d->u.var.var, E_VarEntry(e.ty));
}
示例#6
0
struct expty transExp (S_table venv, S_table tenv, A_exp a)
{
  switch (a->kind) {
    case A_opExp: {
        A_oper oper = a->u.op.oper;
        struct expty left = transExp (venv, tenv, a->u.op.left);
        struct expty right = transExp (venv, tenv, a->u.op.right);

        if (oper == A_plusOp || oper == A_minusOp || oper == A_timesOp || oper == A_divideOp) {
          if (left.ty->kind != Ty_int) {
            EM_error (a->u.op.left->pos, "integer required");
          }

          if (right.ty->kind != Ty_int) {
            EM_error (a->u.op.right->pos, "integer required");
          }
        } else {
          if (left.ty->kind != right.ty->kind) {
            EM_error (a->u.op.right->pos, "left type should be same as right");
          }
        }
        return expTy (NULL, Ty_Int());
      }

    case A_varExp: {
        return transVar (venv, tenv, a->u.var);
      }

    case A_nilExp: {
        return expTy (NULL, Ty_Nil());
      }

    case A_intExp: {
        return expTy (NULL, Ty_Int());
      }

    case A_stringExp: {
        return expTy (NULL, Ty_String());
      }

    case A_callExp: {
        E_enventry x = S_look (venv, a->u.call.func);

        if (x && x->kind == E_funEntry) {
          Ty_tyList tList;
          A_expList eList;

          for (tList = x->u.fun.formals, eList = a->u.call.args; tList &&  eList; tList = tList->tail, eList = eList->tail) {
            Ty_ty expTyName = transExp (venv, tenv, eList->head).ty;

            if (tList->head->kind != expTyName->kind) {
              if (tList->head->kind == Ty_record && expTyName->kind == Ty_nil) {
                continue;
              }
              EM_error (eList->head->pos, "field type is wrong");
              return expTy (NULL, Ty_Int());
            }
          }

          if (tList || eList) {
            EM_error (a->u.call.args->head->pos, "field type number is wrong");
            return expTy (NULL, Ty_Int());
          }

          return expTy (NULL, x->u.fun.result);
        }

        EM_error (a->pos, "undefined function name %s", S_name (a->u.call.func));
        return expTy (NULL, Ty_Int());
      }

    case A_recordExp: {
        Ty_ty record = S_look (tenv, a->u.record.typ);

        if (!record) {
           EM_error (a->pos, "undefined record type %s", S_name (a->u.record.typ));
           return expTy (NULL, record);
        }

        if (record->kind != Ty_record) {
          EM_error (a->pos, "type should be an record");
          return expTy (NULL, Ty_Int());
        } else {
          A_efieldList efieldList = NULL;
          Ty_fieldList fieldList = record->u.record;
          for (efieldList = a->u.record.fields; efieldList && fieldList; efieldList = efieldList->tail, fieldList = fieldList->tail) {
            Ty_ty field = actual_ty(fieldList->head->ty);
            Ty_ty expTyName = transExp (venv, tenv, efieldList->head->exp).ty;

            if (field->kind != expTyName->kind) {
              if (field->kind == Ty_record && expTyName->kind == Ty_nil) {
                continue;
              }
              EM_error (a->pos, "field type wrong");
            }
          }

          if (efieldList || fieldList) {
            EM_error (a->pos, "field number wrong");
          }

          return expTy (NULL, record);
        }
      }

    case A_arrayExp: {
        Ty_ty array = S_look (tenv, a->u.array.typ);

        if (!array) {
          EM_error (a->pos, "undefined array type %s", S_name (a->u.array.typ));
          return expTy (NULL, array);
        }

        if (array->kind != Ty_array) {
          EM_error (a->pos, "type should be an array");
          return expTy (NULL, Ty_Int());
        } else {
          if (transExp (venv, tenv, a->u.array.size).ty->kind != Ty_int) {
            EM_error (a->pos, "array size should be int");
          }
          if (transExp (venv, tenv, a->u.array.init).ty->kind != array->u.array->kind) {
            EM_error (a->pos, "array type should be same as init");
          }
          return expTy (NULL, array);
        }
      }

    case A_seqExp: {
        A_expList d;

        for (d = a->u.seq; d && d->tail; d = d->tail) {
          transExp (venv, tenv, d->head);
        }
        if (d) {
          return transExp (venv, tenv, d->head);
        } else {
          return expTy (NULL, Ty_Void());
        }
      }

    case A_assignExp: {
        transVar (venv, tenv, a->u.assign.var);
        transExp (venv, tenv, a->u.assign.exp);
        return expTy (NULL, Ty_Void());
      }

    case A_ifExp: {
        transExp (venv, tenv, a->u.iff.test);

        if (a->u.iff.elsee) {
          struct expty then = transExp (venv, tenv, a->u.iff.then);
          struct expty elsee = transExp (venv, tenv, a->u.iff.elsee);

          if (then.ty->kind != elsee.ty->kind) {
            EM_error (a->u.iff.elsee->pos, "then should be same as else");
          }

          return then;
        } else {
          struct expty then = transExp (venv, tenv, a->u.iff.then);

          if (then.ty->kind != Ty_void) {
            EM_error (a->u.iff.then->pos, "then should be void");
          }

          return expTy (NULL, Ty_Void());
        }
      }

    case A_whileExp: {
        transExp (venv, tenv, a->u.whilee.test);
        struct expty body = transExp (venv, tenv, a->u.whilee.body);

        if (body.ty->kind != Ty_void) {
          EM_error (a->u.whilee.body->pos, "body of while error, it should return void");
        }

        return expTy (NULL, Ty_Void());
      }

    case A_forExp: {
        S_enter (venv, a->u.forr.var, E_VarEntry (Ty_Int()));

        struct expty lo = transExp (venv, tenv, a->u.forr.lo);
        struct expty hi = transExp (venv, tenv, a->u.forr.hi);
        if (lo.ty->kind != Ty_int) {
          EM_error (a->u.forr.lo->pos, "lo exp of for should be int");
        }

        if (hi.ty->kind != Ty_int) {
          EM_error(a->u.forr.hi->pos, "hi exp of for should be int");
        }

        S_beginScope (venv);
        //if (a->u.forr.body->kind == A_seqExp) {
        //  A_expList test = a->u.forr.body->u.seq;
        //  while (test) {
        //    if (test->head->kind == A_assignExp) {

        //    }
        //  }
        //}

        struct expty body = transExp (venv, tenv, a->u.forr.body);

        if (body.ty->kind != Ty_void) {
          EM_error (a->u.forr.body->pos, "body of for error, it should return void");
        }
        S_endScope(venv);
        return expTy (NULL, Ty_Void());
      }

    case A_breakExp: {
        return expTy (NULL, Ty_Void());
      }

    case A_letExp: {
        struct expty exp;
        A_decList d;
        S_beginScope (venv);
        S_beginScope (tenv);

        for (d = a->u.let.decs; d; d = d->tail) {
          transDec (venv, tenv, d->head);
        }

        exp = transExp (venv, tenv, a->u.let.body);
        S_endScope (tenv);
        S_endScope (venv);
        return exp;
      }
  }

  assert (0);
}
示例#7
0
void transDec (S_table venv, S_table tenv, A_dec d)
{
  switch (d->kind) {
    case A_varDec: {
        Ty_ty typ = NULL;
        if (d->u.var.typ) {
          typ = S_look(tenv, d->u.var.typ);
        }

        struct expty e = transExp (venv, tenv, d->u.var.init);
        if (!typ || typ->kind == e.ty->kind) {
          if (e.ty->kind == Ty_nil && (!typ || typ->kind != Ty_record)) {
            EM_error (d->u.var.init->pos, "nil should be constrained by record");
          }
          S_enter (venv, d->u.var.var, E_VarEntry (e.ty));
        } else {
          EM_error (d->u.var.init->pos, "var type should be same as init");
        }
        break;
      }

    case A_typeDec: {
        A_nametyList nList = NULL;

        for (nList = d->u.type; nList; nList = nList->tail) {
          bool flag;
          A_nametyList scanList = NULL;
          for (scanList = nList->tail; scanList; scanList = scanList->tail) {
            if (strcmp(S_name(nList->head->name), S_name(scanList->head->name)) == 0) {
              flag = TRUE;
              break;
            }
          }
          if (flag) {
            EM_error (d->pos, "type redefined error");
          }
          S_enter(tenv, nList->head->name, Ty_Name (nList->head->ty->u.name, NULL));
        }
        for (nList = d->u.type; nList; nList = nList->tail) {
          Ty_ty waitFill = S_look(tenv, nList->head->name);
          if (waitFill->kind == Ty_name) {
            waitFill->u.name.ty = transTy (tenv, nList->head->ty);
          }
          Ty_ty trueType = actual_ty(waitFill);
          if (trueType) {
            S_enter(tenv, nList->head->name, actual_ty(waitFill));
          } else {
            EM_error (d->pos, "recursive types should through record or array");
            break;
          }

        }

        break;
      }

    case A_functionDec: {
        A_fundecList funList = NULL;

        for (funList = d->u.function; funList; funList = funList->tail) {
           bool flag;
          A_fundecList scanList = NULL;
          for (scanList = funList->tail; scanList; scanList = scanList->tail) {
            if (strcmp(S_name(funList->head->name), S_name(scanList->head->name)) == 0) {
              flag = TRUE;
              break;
            }
          }
          if (flag) {
            EM_error (d->pos, "function redefined error");
          }
          A_fundec f = funList->head;
          if (!f->result) {
            f->result = S_Symbol("void");
          }
          Ty_ty resultTy = S_look (tenv, f->result);
          Ty_tyList formalTys = makeFormalTyList (tenv, f->params);
          S_enter (venv, f->name, E_FunEntry (formalTys, resultTy));
        }
        for (funList = d->u.function; funList; funList = funList->tail) {
          A_fundec f = funList->head;
          Ty_tyList formalTys = makeFormalTyList (tenv, f->params);

          S_beginScope (venv);
          {
            A_fieldList l;
            Ty_tyList t;

            for (l = f->params, t = formalTys; l; l = l->tail, t = t->tail) {
              S_enter (venv, l->head->name, E_VarEntry (t->head));
            }
          }
          Ty_ty returnTy = S_look (tenv, f->result);
          if (returnTy->kind != transExp (venv, tenv, f->body).ty->kind) {
            EM_error (f->body->pos, "return type wrong");
          }
          S_endScope (venv);

        }

        break;
      }
  }
}
示例#8
0
struct expty transExp(S_table venv, S_table tenv, A_exp e) {
	if (e == NULL) {
		return expTy(NULL, Ty_Void());
	}
	switch (e->kind) {
		case A_varExp: {
			return transVar(venv, tenv, e->u.var);
		}
		case A_nilExp: {
			return expTy(NULL, Ty_Nil());
		}
		case A_intExp: {
			return expTy(NULL, Ty_Int());
		}
		case A_stringExp: {
			return expTy(NULL, Ty_String());
		}
		case A_callExp: {
			E_enventry fun = (E_enventry)S_look(venv, e->u.call.func);
			if (!fun || fun->kind == E_varEntry) {
				EM_error(e->pos, (string)"undefined function '%s'", S_name(e->u.call.func));
				return expTy(NULL, Ty_Int());
			}
			if ((!fun->u.fun.formals && e->u.call.args) || (fun->u.fun.formals && !e->u.call.args)) {
				EM_error(e->pos, (string)"incorrect function prototype '%s'", S_name(e->u.call.func));
				return expTy(NULL, Ty_Int());
			}
			Ty_tyList ttl;
			A_expList el;
			for (ttl = fun->u.fun.formals, el = e->u.call.args; ttl || el; ttl = ttl->tail, el = el->tail) {
				if (ttl && !el) {
					EM_error(e->pos, (string)"formals are more than actuals");
					return expTy(NULL, Ty_Int());
				}
				if (!ttl && el) {
					EM_error(e->pos, (string)"formals are less than actuals");
					return expTy(NULL, Ty_Int());
				}
				struct expty arg = transExp(venv, tenv, el->head);
				if (actual_ty(ttl->head)->kind != actual_ty(arg.ty)->kind) {
					EM_error(e->pos, (string)"formals and actuals have different types");
					return expTy(NULL, Ty_Int());
				}
			}
			if (!fun->u.fun.result) {
				return expTy(NULL, Ty_Void());
			}
			return expTy(NULL, actual_ty(fun->u.fun.result));
		}
		case A_opExp: {
			A_oper oper = e->u.op.oper;
			struct expty left = transExp(venv, tenv, e->u.op.left);
			struct expty right = transExp(venv, tenv, e->u.op.right);
			if (oper == A_plusOp || oper == A_minusOp || oper == A_timesOp || oper == A_divideOp) {
				if (left.ty->kind != Ty_int || right.ty->kind != Ty_int) {
					EM_error(e->u.op.left->pos, (string)"integer required");
					return expTy(NULL, Ty_Int());
				}
				return expTy(NULL, Ty_Int());
			}
			if (oper == A_eqOp || oper == A_neqOp) {
				if (isSameTy(left.ty, right.ty)) {
					return expTy(NULL, Ty_Int());
				}
				EM_error(e->pos, (string)"same type required");
				return expTy(NULL, Ty_Int());
			}
			if (oper == A_ltOp || oper == A_leOp || oper == A_gtOp || oper == A_geOp) {
				if (left.ty->kind == Ty_int && right.ty->kind == Ty_int) {
					return expTy(NULL, Ty_Int());
				}
				if (left.ty->kind == Ty_string && right.ty->kind == Ty_string) {
					return expTy(NULL, Ty_Int());
				}
				EM_error(e->pos, "comparison of incompatible type");
				return expTy(NULL, Ty_Int());
			}
			assert(0);
		}
		case A_recordExp: {
			Ty_ty ty = (Ty_ty)S_look(tenv, e->u.record.typ);
			if (!ty) {
				EM_error(e->pos, "undefined record type '%s'", S_name(e->u.record.typ));
				return expTy(NULL, Ty_Nil());
			}
			ty = actual_ty(ty);
			if (ty->kind != Ty_record) {
				EM_error(e->pos, "'%s' is not a record", S_name(e->u.record.typ));
			}
			else {
				Ty_fieldList tfl;
				A_efieldList efl;
				for (tfl = ty->u.record, efl = e->u.record.fields; tfl || efl; tfl = tfl->tail, efl = efl->tail) {
					if (tfl && !efl) {
						EM_error(e->pos, "record field is less than need");
						return expTy(NULL, Ty_Nil());
					}
					if (!tfl && efl) {
						EM_error(e->pos, "record field is more than need");
						return expTy(NULL, Ty_Nil());
					}
					if (tfl->head->name != efl->head->name) {
						EM_error(e->pos, "record field mismatch");
						return expTy(NULL, Ty_Nil());
					}
					struct expty res = transExp(venv, tenv, efl->head->exp);
					Ty_ty fieldty = actual_ty(tfl->head->ty);
					if (!isSameTy(fieldty, res.ty)) {
						EM_error(e->pos, (string)"record field mismatch");
						return expTy(NULL, Ty_Nil());
					}
				}
			}
			return expTy(NULL, ty);
		}
		case A_seqExp: {
			A_expList el = e->u.seq;
			if (el) {
				while (el->tail) {
					transExp(venv, tenv, el->head);
					el = el->tail;
				}
				return expTy(NULL, transExp(venv, tenv, el->head).ty);
			}
			return expTy(NULL, Ty_Void());
		}
		case A_assignExp: {
			struct expty left = transVar(venv, tenv, e->u.assign.var);
			struct expty right = transExp(venv, tenv, e->u.assign.exp);
			if (isSameTy(left.ty, right.ty)) {
				return expTy(NULL, Ty_Void());
			}
			EM_error(e->pos, "type mismatch");
			return expTy(NULL, Ty_Void());
		}
		case A_ifExp: {
			struct expty test = transExp(venv, tenv, e->u.iff.test);
			if (test.ty->kind != Ty_int) {
				EM_error(e->pos, "if-else clause integer test required");
				return expTy(NULL, Ty_Void());
			}
			struct expty then = transExp(venv, tenv, e->u.iff.then);
			if (e->u.iff.elsee == NULL) {
				if (then.ty->kind != Ty_void) {
					EM_error(e->pos, "if-then returns non unit");
					return expTy(NULL, Ty_Void());
				}
				return expTy(NULL, Ty_Void());
			}
			struct expty elsee = transExp(venv, tenv, e->u.iff.elsee);
			if (isSameTy(then.ty, elsee.ty)) {
				return expTy(NULL, then.ty);
			}
			EM_error(e->pos, "types of then - else differ");
			return expTy(NULL, Ty_Void());
		}
		case A_whileExp: {
			struct expty test = transExp(venv, tenv, e->u.whilee.test);
			struct expty body = transExp(venv, tenv, e->u.whilee.body);
			if (test.ty->kind != Ty_int) {
				EM_error(e->pos, "test clause integer required");
				return expTy(NULL, Ty_Void());
			}
			if (body.ty->kind != Ty_void) {
				EM_error(e->pos, "body of while not void");
				return expTy(NULL, Ty_Void());
			}
			return expTy(NULL, Ty_Void());
		}
		case A_forExp: {
			struct expty lo = transExp(venv, tenv, e->u.forr.lo);
			struct expty hi = transExp(venv, tenv, e->u.forr.hi);
			if (lo.ty->kind != Ty_int || hi.ty->kind != Ty_int) {
				EM_error(e->pos, "for clause lo and hi integer required");
				return expTy(NULL, Ty_Void());
			}
			S_beginScope(venv);
			if (!S_look(venv, e->u.forr.var)) {
				S_enter(venv, e->u.forr.var, E_VarEntry(Ty_Int()));
			}
			struct expty body = transExp(venv, tenv, e->u.forr.body);
			S_endScope(venv);
			if (body.ty->kind != Ty_void) {
				EM_error(e->pos, "for clause body no-value required");
				return expTy(NULL, Ty_Void());
			}
			return expTy(NULL, Ty_Void());
		}
		case A_breakExp: {
			return expTy(NULL, Ty_Void());
		}
		case A_letExp: {
			A_decList d;
			S_beginScope(venv);
			S_beginScope(tenv);
			for (d = e->u.let.decs; d; d = d->tail) {
				transDec(venv, tenv, d->head);
			}
			struct expty exp = transExp(venv, tenv, e->u.let.body);
			S_endScope(venv);
			S_endScope(tenv);
			return exp;
		}
		case A_arrayExp: {
			struct expty size = transExp(venv, tenv, e->u.array.size);
			struct expty init = transExp(venv, tenv, e->u.array.init);
			Ty_ty ty = (Ty_ty)S_look(tenv, e->u.array.typ);
			if (!ty) {
				EM_error(e->pos, "undefined array type '%s'", S_name(e->u.array.typ));
				return expTy(NULL, Ty_Void());
			}
			ty = actual_ty(ty);
			if (ty->kind != Ty_array) {
				EM_error(e->pos, "'%s' is not a array", S_name(e->u.array.typ));
				return expTy(NULL, Ty_Void());
			}
			if (size.ty->kind != Ty_int) {
				EM_error(e->pos, "size int value required");
				return expTy(NULL, actual_ty(ty));
			}
			Ty_ty ty2 = actual_ty(ty->u.array);
			if (!isSameTy(ty2, init.ty)) {
				EM_error(e->pos, "initializing exp and array type differ");
				return expTy(NULL, Ty_Void());
			}
			return expTy(NULL, ty);
		}
		default: {
			assert(0);
		}
	}
}
示例#9
0
void transDec(S_table venv, S_table tenv, A_dec d) {
	if (!d) {
		return;
	}
	switch (d->kind) {
		case A_varDec: {
			struct expty e = transExp(venv, tenv, d->u.var.init);
			if (d->u.var.typ) {
				Ty_ty ty = (Ty_ty)S_look(tenv, d->u.var.typ);
				if (!ty) {
					EM_error(d->pos, "undefined type '%s'", S_name(d->u.var.typ));
					return;
				}
				ty = actual_ty(ty);
				if (!isSameTy(ty, e.ty)) {
					EM_error(d->pos, (string)"type mismatch");
					return;
				}
				S_enter(venv, d->u.var.var, E_VarEntry(ty));
				return;
			}
			if (e.ty->kind == Ty_nil) {
				EM_error(d->pos, "initializing nil expressions not constrained by record type");
				return;
			}
			S_enter(venv, d->u.var.var, E_VarEntry(e.ty));
			return;
		}
		case A_typeDec: {
			S_table tmp = S_empty();
			A_nametyList ntl;
			for (ntl = d->u.type; ntl; ntl = ntl->tail) {
				if (S_look(tmp, ntl->head->name)) {
					EM_error(d->pos, "type '%s' redefined", S_name(ntl->head->name));
					return;
				}
				S_enter(tmp, ntl->head->name, "-tmp-");
				S_enter(tenv, ntl->head->name, Ty_Name(ntl->head->name, NULL));
			}
			for (ntl = d->u.type; ntl; ntl = ntl->tail) {
				Ty_ty ty = (Ty_ty)S_look(tenv, ntl->head->name);
				ty->u.name.ty = transTy(tenv, ntl->head->ty);
			}
			for (ntl = d->u.type; ntl; ntl = ntl->tail) {
				Ty_ty ty = (Ty_ty)S_look(tenv, ntl->head->name);
				if (ty->u.name.ty->kind != Ty_name) {
					return;
				}
			}
			EM_error(d->pos, "infinite recursive");
			return;
		}
		case A_functionDec: {
			S_table tmp = S_empty();
			A_fundecList fdl;
			for (fdl = d->u.function; fdl; fdl = fdl->tail) {
				if (S_look(tmp, fdl->head->name)) {
					EM_error(d->pos, "function '%s' redefined", S_name(fdl->head->name));
					return;
				}
				S_enter(tmp, fdl->head->name, "-tmp-");
			}
			for (fdl = d->u.function; fdl; fdl = fdl->tail) {
				Ty_tyList formalTys = makeFormalTyList(tenv, fdl->head->params);
				if (fdl->head->result) {
					Ty_ty resultTy = S_look(tenv, fdl->head->result);
					S_enter(venv, fdl->head->name, E_FunEntry(formalTys, resultTy));
				}
				else {
					S_enter(venv, fdl->head->name, E_FunEntry(formalTys, NULL));
				}
			}
			for (fdl = d->u.function; fdl; fdl = fdl->tail) {
				Ty_tyList formalTys = makeFormalTyList(tenv, fdl->head->params);
				S_beginScope(venv);
				{
					A_fieldList l;
					Ty_tyList t;
					for (l = fdl->head->params, t = formalTys; l; l = l->tail, t = t->tail) {
						S_enter(venv, l->head->name, E_VarEntry(t->head));
					}
				}
				transExp(venv, tenv, fdl->head->body);
				S_endScope(venv);
			}
			break;
		}
		default: {
			assert(0);
		}
	}
}
示例#10
0
文件: semant.c 项目: Shenjiaqi/tiger
struct expty transDec(S_table venv, S_table tenv, A_dec d)
{
  switch( d->kind )
    {
    case A_functionDec:
      {
	//whether already in funcdeclar
	if(InFunc())
	  EM_error( d->pos , "already in func declare");
	A_fundecList funcs = d->u.function;
	// for every fun declare in fundecList
	for( ; funcs != NULL ; funcs = funcs->tail )
	  {
	    A_fundec func = funcs->head;
	    // get ty of params and result
	    Ty_tyList funentry = makeFormalTyList( tenv , func->params );
	    Ty_ty res;
	    if( func->result == NULL )
	      res = Ty_Nil();
	    else
	      res = S_look( tenv , func->result );
	    if( res == NULL )
	      EM_error( func->pos , "no " , S_name( func->result ) , "type ");
	    //whether already defined
	    if( S_look( venv , func->name ) != NULL )
	      EM_error( func->pos , S_name( func->result ) ,
			"already defined" );
	    S_enter( venv ,  func->name , E_FunEntry( funentry , res ) );
	  }
	funcs = d->u.function;
	// for every fun in fundecList, call tranexp on its body
	for( ; funcs != NULL ; funcs = funcs->tail )
	  {
	    A_fundec func = funcs->head;
	    S_beginScope( venv );
	    A_fieldList args = func->params;
	    Ty_tyList funentries = ((E_entry)S_look( venv , func->name ))
	      ->fun.formalTys ;
	    for( ; args != NULL ; args = args->tail ,
		   funentries = funentries->tail)
	      {
		A_field arg = args->head;
		Ty_ty type = funentries->head;
		S_enter( venv , arg->name , type );
	      }
	    SetInFunc();
	    transExp( venv , tenv , func->body );
	    UsetInFunc();
	    S_endScope( venv );
	  }
	return _expTy( NULL , Ty_Void() );
      }
    case A_varDec:
      {
	Ty_ty type = S_look( tenv , d->u.var.typ );
	if( type == NULL )
	  EM_error( d->pos , S_name( d->u.var.typ ) , " not defined " );
	struct expty init = transExp( venv , tenv , d->u.var.init );
	if( init.ty->kind != Ty_nil && init.ty->kind != type->kind )
	  EM_error( d->pos , "Expect " , tyKindName( type->kind ) , " but " ,
		    tyKindName( init.ty->kind ) );
	if( S_look( venv , d->u.var.var ) != NULL )
	  EM_error( d->pos , S_name( d->u.var.var ) , " already defined " );
	S_enter( venv , d->u.var.var , type );
	return _expTy( NULL , Ty_Void() );
      }
    case A_typeDec:
      {
	A_nametyList tylist = d->u.type;
	for( ; tylist != NULL ; tylist = tylist->tail )
	  {
	    A_namety tydec = tylist->head;
	    if( S_look( tenv , tydec->name ) != NULL )
	      EM_error( tydec->ty->pos , S_name( tydec->name ) ,
			" already declared " );
	    A_ty ty = tydec->ty;
	    switch( ty->kind )
	      {
	      case A_nameTy:
		{
		  Ty_ty tyy = S_look( tenv , ty->u.name ) ;
		  if( tyy == NULL )
		    S_enter( tenv , tydec->name ,
			     Ty_Name( ty->u.name , NULL ) );
		  else
		    S_enter( tenv , tydec->name , tyy );
		}
	      case A_recordTy:
		{
		  A_fieldList records = ty->u.record;
		  Ty_fieldList types = dfsRecordTy( tenv , records );
		  S_enter( tenv , tydec->name , Ty_Record( types ) );
		}
	      case A_arrayTy:
	      default:
		assert(0);
	      }
	    S_enter( tenv , tydec->name , E_VarEntry( NULL ) );
	  }
	tylist = d->u.type;
	for( ; tylist != NULL ; tylist = tylist->tail )
	  {
	    A_namety tydec = tylist->head;
	    A_ty ty = tydec->ty;
	    switch( ty->kind )
	      {
	      case A_nameTy:
		{
		  Ty_ty tyy = S_look( tenv , ty->u.name );
		  if( tyy->u.name.ty == NULL )
		    tyy->u.name.ty = dfsTypeDec( ty->pos , tenv ,
						 tyy->u.name.sym ,
						 tydec->name );
		}
	      case A_recordTy:
	      case A_arrayTy:
	      default:
		assert(0);
	      }
	  }
      }
    default:
      assert(0);
    }
}