/***** * access.cc * Andy Hammerlindl 2003/12/03 * Describes an "access," a representation of where a variable will be * stored at runtime, so that read, write, and call instructions can be * made. *****/ #include "access.h" #include "frame.h" #include "coder.h" #include "callable.h" using vm::item; namespace trans { /* access */ access::~access() {} /* identAccess */ void identAccess::encode(action act, position pos, coder& e) { if (act != CALL) { access::encode(act, pos, e); } // else - do nothing } /* bltinAccess */ static void bltinError(position pos) { em.error(pos); em << "built-in functions cannot be modified"; } void bltinAccess::encode(action act, position pos, coder &e) { switch (act) { case READ: e.encode(inst::constpush,(item)(vm::callable*)new vm::bfunc(f)); break; case WRITE: bltinError(pos); break; case CALL: e.encode(inst::builtin, f); break; } } void bltinAccess::encode(action act, position pos, coder &e, frame *) { e.encode(inst::pop); encode(act, pos, e); } /* callableAccess */ void callableAccess::encode(action act, position pos, coder &e) { switch (act) { case READ: e.encode(inst::constpush, (item)f); break; case WRITE: bltinError(pos); break; case CALL: this->encode(READ, pos, e); e.encode(inst::popcall); break; } } void callableAccess::encode(action act, position pos, coder &e, frame *) { e.encode(inst::pop); encode(act, pos, e); } /* frameAccess */ void frameAccess::encode(action act, position pos, coder &e) { if (act == READ) { if (!e.encode(f)) { em.compiler(pos); em << "encoding frame out of context"; } } else access::encode(act, pos, e); } void frameAccess::encode(action act, position pos, coder &e, frame *top) { if (act == READ) { if (!e.encode(f, top)) { em.compiler(pos); em << "encoding frame out of context"; } } else access::encode(act, pos, e, top); } /* localAccess */ static void frameError(position pos) { // A local variable is being used when its frame is not active. em.error(pos); em << "static use of dynamic variable"; } void localAccess::encode(action act, position pos, coder &e) { // Get the active frame of the virtual machine. frame *active = e.getFrame(); if (level == active) { e.encode(act == WRITE ? inst::varsave : inst::varpush, offset); } else if (e.encode(level)) { e.encode(act == WRITE ? inst::fieldsave : inst::fieldpush, offset); } else { frameError(pos); } if (act == CALL) e.encode(inst::popcall); } void localAccess::encode(action act, position pos, coder &e, frame *top) { if (e.encode(level,top)) { e.encode(act == WRITE ? inst::fieldsave : inst::fieldpush, offset); if (act == CALL) e.encode(inst::popcall); } else { frameError(pos); } } void qualifiedAccess::encode(action act, position pos, coder &e) { qualifier->encode(READ, pos, e); field->encode(act, pos, e, qualifierLevel); } void qualifiedAccess::encode(action act, position pos, coder &e, frame *top) { qualifier->encode(READ, pos, e, top); field->encode(act, pos, e, qualifierLevel); } } // namespace trans