[Instructions] [Search] [Current] [Syllabus] [Handouts] [Outlines] [Assignments]
Held Wednesday, November 4, 1998
Notes
http://www.tuxedo.org/~esr/halloween.html
.
(1) Get the exp/type pair for the base variable. (2) Extract the type from the pair. (3) Get the actual type (dealing with indirections from name variables). (4) Confirm that the actual type is a record. (5) Search through the list of field names to find the field. (5a) When found, return the corresponding type. (6) If not found, report an error and recover.
(1) Get the exp/type pair for the base variable. (2) Extract the type from the pair. (3) Get the actual type (dealing with indiretions). (4) Confirm that the actual type is an array. (5) Get the exp/type pair for the index. (6) Extract the type from the pair. (7) Confirm that the actual type of the index is integer. (8) Return the associated type of the array.
transVar is sketched on page 117. It returns a
struct expty and takes an A_var as a
parameter.
struct expty is defined on page 116. The ty
field gives its type, which is of (C) type Ty_ty.
Ty_ty is defined on p. 113.
A_var is defined on p. 97.
/*
* Compute the type and IRT for a variable.
*/
struct expty
transVar(S_table venv, S_table tenv, A_var v) {
/* Determine which type of variable it is and process accordingly. */
switch (v->kind) {
/* Code for simple variables taken from p. 117 of Appel's green book.
Extended with comments by Sam Rebelsky. */
case A_simpleVar: {
/* Look up the variable in the symbol table. */
E_enventry x = S_look(venv, v->u.simple);
/* Confirm that it was in the table and was the appropriate kind.
of entry. */
if (x && (x->kind==E_varEntry)) {
/* Extract the type and then get the actual type. Note that we
will eventually need to generate code, too. */
return expTy(NULL, actual_ty(x->u.var.ty));
} /* Acceptable variable. */
/* Okay, the Tiger programmer forgot to declare the variables.
Let him or her know. */
else {
EM_error(v->pos, "undefined variable %s", S_name(v->u.simple));
/* Return our default type: integer. */
return expTy(NULL, Ty_Int());
} /* Undeclared variable. */
} /* case A_simpleVar */
/* Code for field variables developed by Sam Rebelsky. */
case A_fieldVar: {
/* Get the exp/type pair for the base variable. */
struct expty et = transVar(venv, tenv, v->u.field.var);
/* Get the type and convert it to an actual type. Note that if
we're careful to always return actual types, this conversion may
not be necessary. For now, we err on the side of safety. */
Ty_ty basety = actual_ty(et.ty);
/* Confirm that the actual type is a record. */
if (basety->kind != Ty_record) {
EM_error(v->pos, "attempt to use a non-record as a record");
return expTy(NULL, Ty_Int());
}
/* Get the field list. */
Ty_fieldList fields = basety->u.record;
while (fields != NULL) {
/* Is it the current field?
if (v->u.field.sym == fields->head->name) {
/* Yes! Return the corresponding type. */
return actual_ty(fields->head->ty);
}
else {
/* No. Advance through the list. */
fields = fields->tail;
}
} /* while */
/* Whoops. We ran out of fields and never found it. */
EM_error(v->pos, "attempt to access non-existent field %s in record",
S_name(v->u.field.sym));
return expTy(NULL, Ty_Int());
} /* case A_fieldVar */
/* Code for array variables to be developed by the appropriate person. */
case A_subscriptVar: {
...
} /* case A_subscriptVar */
/* Hmmm ... we don't know about any other kind of variable. */
default: {
EM_error(v->pos, "unknown type of variable");
return expTy(NULL, Ty_Int());
} /* default */
} /* switch */
} /* transVar(S_table, S_table, A_var) */
switch, we can actually write separate
functions because of overloading.
actual.
transVar is sketched on p. 122. In that version, it
takes an Absyn.SimpleVar
as a parameter and returns a ExpTy. Our version will still
return an ExpTy but will take Absyn.FieldVar
as a parameter.
Absyn.SimpleVar and Abysn.FieldVar are given on
p. 103. Both are subclasses of class var.
ExpTy is given on p. 120. It consists of an IRT and a
Types.Type.
Types.Type is given on p. 116.
/**
* Translate a field variable (a variable representing a field in a
* record) to an intermediate representation tree while doing type
* checking. At present, we just do the type checking.
*/
public ExpTy transVar(AbSyn.FieldVar v) {
// Get the exp/type pair for the base variable.
ExpTy et = transVar(v.var);
// Extract the type from the pair and then get the actual type. Note
// that better programming will eliminate the need to request the
// actual type.
Type basetype = et.ty.actual();
// Confirm that the actual type is a record.
if (!(basetype instanceof RECORD) {
error(v.pos, "attempt to access a field of a non-record");
return new ExpTy(null, INT);
}
// Search through the list of field names to find the field.
RECORD fields = (RECORD) basetype;
while (fields != null) {
// Did we match?
if (v.field == fields.fieldName) {
// Yes! We're almost done.
return new ExpTy(null, fields.fieldType.actual());
}
else {
// No! Go on to the next field.
fields = fields.tail;
}
} // while
// Hmmm ... never found a matching field. Why can't the Tiger
// programmers be more careful? I guess we should tell them.
error(v.pos, "unsuccessful attempt to access nonexistent field " +
v.field.toString());
return new ExpTy(null, INT);
} // transVar(AbSyn.FieldVar)
transVar that operates on
AbSyn.Var, because at compile type (that's compile time for
Java) it's only clear that variables are in class AbSyn.Var
and not a particular subclass.
/**
* Translate a variable to an intermediate representation tree and, while
* we're at it, type check it. Currently only does type checking. This
* particular version is used to dispatch to the appropriate subversion.
*/
public ExpTy transVar(AbSyn.Var v) {
if (v instanceof AbSyn.SimpleVar) {
return transVar((AbSyn.SimpleVar) v);
}
else if (v instanceof AbSyn.FieldVar) {
return transVar((AbSyn.FieldVar) v);
}
else if (v instanceof AbSyn.SubscriptVar) {
return transVar((AbSyn.SubscriptVar) v);
}
else {
// Okay, what bozo decided that we needed yet another kind of
// variable?
error(v.pos, "unknown kind of variable);
return new ExpTy(null, INT);
}
} // transVar(AbSyn.Var)
History
Back to Intermediate representation trees. On to Translating variables and data.
[Instructions] [Search] [Current] [Syllabus] [Handouts] [Outlines] [Assignments]
Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.
Source text last modified Wed Nov 4 14:32:44 1998.
This page generated on Wed Nov 4 14:38:39 1998 by SiteWeaver.
Contact our webmaster at rebelsky@math.grin.edu