/**** * * Implmentation of where.h. * */ #include "std-macros.h" #include "sym.h" #include "tokens.h" #include "type-preds.h" #include "where.h" #include "where.hP" #include "token-mapping.h" /* * Recursively descend into the given type and do the instantiation. Note that * if a new type is created, a special link is set in the new type pointing * back to the parent type, so that the instantiated type remains subtype * compat with its original parent. This explicit pointer may not be the * slickest way to do it, but it's direct and clear, I believe. This is * accomplished by have the junior partner do all the recursive descending, and * upon its return, the parent link is installed. */ TypeNode* InstantiateWhereDef(TypeNode* type, nodep where) { TypeNode* newtype = InstantiateWhereDef1(type, where); if (not type) return null; if (type != newtype) newtype->components.type.whereparent = type; else newtype->components.type.whereparent = null; return newtype; } TypeNode* InstantiateWhereDef1(TypeNode* type, nodep where) { if (not type) return null; switch (type->header.name) { case 0: return null; case ';': return InstantiateOpaqueType(type, where); case Yident: return InstantiateIdentType(type, where); case YARRAY: return InstantiateArrayType(type, where); case YRECORD: return InstantiateRecordType(type, where); case YOR: return InstantiateOrType(type, where); case YOP: return InstantiateOpType(type, where); } } TypeNode* InstantiateOpaqueType(TypeNode* type, nodep where) { return type; } TypeNode* InstantiateIdentType(TypeNode* type, nodep where) { TypeNode* newtype; if (newtype = WhereRedef(type, where)) { return newtype; } MarkInstantiaters(where); return type; } TypeNode* InstantiateArrayType(TypeNode* type, nodep where) { TypeNode* rtn, *newtype; /* * Check if base type is one of the where'd types. If so return, return * a new array type with the where'd type replaced. */ if (newtype = WhereRedef(GetArrayBaseType(type), where)) { rtn = ShallowCopyNode(type); SetArrayBaseType(rtn, newtype); return rtn; } /* * Otherwise, return the type itself unchanged. */ return type; } TypeNode* InstantiateRecordType(TypeNode* type, nodep where) { TypeNode* newrtype = null, *newftype; Node* n; Node* fname; /* * Check if the type of any of the fields is one of the where'd types. For * each such field, do the where replacement. If any replacements are * made, construct a new record type, with the appro replacements * installed. */ for (n = GetRecordTypeFields(type); n; n = GetDeclNext(n)) { if (newftype = WhereRedef(GetFieldDeclType(n), where)) { if (not newrtype) { newrtype = MakeRecordType(type); } InstantiateRecordField(newrtype, newftype, (fname = GetFieldDeclVars(n)) ? GetAtomTextVal(fname) : hashsave("??")); } } /* * If no replacements were made, return the original type unchanged. */ if (not newrtype) return type; else return newrtype; } void InstantiateRecordField(TypeNode* newrtype, TypeNode* newftype, char* fieldname) { Symtab* recordtab = GetRecordTypeFieldsTab(newrtype); SymtabEntry* fieldsym = LookupIn(fieldname, recordtab); DeleteIn(fieldname, recordtab); EnterIn(AllocSymtabEntry(fieldname, C_Var, newftype, GetSymtabLevel(recordtab)), recordtab); } TypeNode* InstantiateOrType(TypeNode* type, nodep where) { TypeNode* rtn = InstantiateRecordType(type, where); rtn->header.name = YOR; return rtn; } TypeNode* InstantiateOpType(TypeNode* type, nodep where) { return type; } TypeNode* WhereRedef(TypeNode* type, Node* where) { Node* n; if (not isIdentType(type)) return InstantiateWhereDef(type, where); for (n = where; n; n = GetDeclNext(n)) { if (EqualIdentAtoms(GetIdentTypeName(type), GetWhereLHS(n))) { return MakeIdentType(GetWhereRHS(n)); } } return null; } TypeNode* MakeIdentType(Node* t) { TypeNode* rtn; rtn = NewNode(TYPE_NODE, Yident, GetNodeSrcLoc(t)); SetIdentTypeType(rtn, t); return rtn; } TypeNode* MakeRecordType(TypeNode* type) { TypeNode* rtn; rtn = NewNode(TYPE_NODE, YRECORD, GetNodeSrcLoc(type)); SetRecordType(rtn, GetRecordTypeNumFields(type), CopySymtab(GetRecordTypeFieldsTab(type)), GetRecordTypeFields(type)); return rtn; } SymtabEntry* BrowserLookup(char* name); void MarkInstantiaters(nodep where) { nodep n, rhs; SymtabEntry* sym; for (n = where; n; n = GetDeclNext(n)) { rhs = GetWhereRHS(n); if (rhs) { sym = BrowserLookup(rhs->components.atom.val.text); if (sym) { SetSymFlag(sym, isWhereRHS); } } } }