1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
/*****
* 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
|