/***** * record.h * Andy Hammerlindl 2003/07/09 * * The type for records and modules in the language. *****/ #ifndef RECORD_H #define RECORD_H #include "types.h" #include "env.h" #include "frame.h" #include "access.h" namespace vm { struct lambda; } using trans::frame; using trans::protoenv; using trans::varEntry; using trans::tyEntry; using trans::AutoUnravelRegistry; namespace types { class record : public ty { // The base name of this type. symbol name; // The frame. Like a frame for a function, it allocates the accesses // for fields and specifies the size of the record. frame *level; // The runtime representation of the record used by the virtual machine. vm::lambda *init; ty *kType = nullptr; ty *vType = nullptr; public: // The name bindings for fields of the record. protoenv e; // These are name bindings that should be added to the enclosing environment // after translation of the record is completed. Constructors implicitly // defined by "operator init" are stored here. protoenv postdefenv; // Registry of autounravel entries for this record. Populated during // translation; read by addNameOps when the record is used as a type. AutoUnravelRegistry autounravelRegistry; record(symbol name, frame *level); ~record(); symbol getName() { return name; } symbol getTemplateIndex() { return getName(); // May change in the future. } bool isReference() override { return true; } size_t hash() const override{ // Use the pointer, as two records are equivalent only if they are the // same object. return (size_t)this; } // Initialize to null by default. trans::access *initializer() override; frame *getLevel(bool statically = false) { if (statically) { frame *f=level->getParent(); return f ? f : level; } else return level; } vm::lambda *getInit() { return init; } // Allocates a new dynamic field in the record. trans::access *allocField(bool statically) { frame *underlevel = getLevel(statically); assert(underlevel); return underlevel->allocLocal(); } // Create a statically enclosed record from this record. record *newRecord(symbol id, bool statically); // Sets the keytype and valuetype based on operator[] and operator[=]. void computeKVTypes(const position& pos); // Returns the key type of the record, or primError() if it cannot be // determined. May be called before computeKVTypes, in which case it will // compute the key type on demand but will not set the kType field, so that if // operator[] is defined later, the correct key type will be returned. ty* keyType() override; // Returns the value type of the record, or primError() if it cannot be // determined. May be called before computeKVTypes, in which case it will // compute the value type on demand but will not set the vType field, so that // if operator[] or operator[=] is defined later, the correct value type will // be returned. ty *valType(); void print(ostream& out) const override { out << name; } void debug(ostream& out) const { out << "struct " << name << endl; out << "types:" << endl; out << "re-implement" << endl; //out << te; out << "fields: " << endl; out << "re-implement" << endl; //out << ve; } }; // A record that is being used just for its fields and types, and has no real // initializer. This is for modules such as settings that are built into the // language. class dummyRecord : public record { public: dummyRecord(symbol name); dummyRecord(string s); // Convenient functions for adding fields. void add(string name, ty *t, trans::access *a, trans::permission perm=trans::PUBLIC); void add(string name, function *t, vm::bltin f, trans::permission perm=trans::PUBLIC); }; } //namespace types #endif