WriteProperty work-in-progress (broken!)

This commit is contained in:
rogerl%netscape.com 2002-09-05 00:26:34 +00:00
Родитель ea786ffe5d
Коммит 4f0cf5d56e
7 изменённых файлов: 122 добавлений и 57 удалений

Просмотреть файл

@ -54,7 +54,8 @@ static const char *const kindStrings[] = {
"User exception", // 'throw' from user code
"Definition error", // a monkey is a small cup of milk
"Bad Value error", // bad value, no biscuit
"Compile Expression error" // invalid compile-time execution
"Compile expression error", // invalid compile-time execution
"Uninitialized error" // read before write
};
// Return a null-terminated string describing the exception's kind.

Просмотреть файл

@ -60,7 +60,8 @@ namespace JavaScript
definitionError,
badValueError,
compileExpressionError,
propertyAccessError
propertyAccessError,
uninitializedError
};
Kind kind; // The exception's kind

Просмотреть файл

@ -108,6 +108,9 @@ public:
float64 toNumber(js2val x) { if (JS2VAL_IS_INT(x)) return JS2VAL_TO_INT(x); else if (JS2VAL_IS_DOUBLE(x)) return *JS2VAL_TO_DOUBLE(x); else return convertValueToDouble(x); }
bool toBoolean(js2val x) { if (JS2VAL_IS_BOOLEAN(x)) return JS2VAL_TO_BOOLEAN(x); else return convertValueToBoolean(x); }
js2val assignmentConversion(js2val val, JS2Class *type) { return val; } // XXX s'more code, please
uint8 *pc;
BytecodeContainer *bCon;
JS2Metadata *meta;

Просмотреть файл

@ -159,30 +159,17 @@ namespace MetaData {
// the type and the value are 'future'
}
break;
case Attribute::Abstract:
case Attribute::Virtual:
case Attribute::Final:
{
JS2Class *c = checked_cast<JS2Class *>(env->getTopFrame());
InstanceMember *m = NULL;
switch (memberMod) {
case Attribute::Abstract:
if (v->initializer)
reportError(Exception::syntaxError, "Abstract member may not have initializer", p->pos);
m = new InstanceAccessor(NULL, false);
break;
case Attribute::Virtual:
m = new InstanceVariable(immutable, false);
c->slotCount++;
break;
case Attribute::Final:
m = new InstanceVariable(immutable, true);
c->slotCount++;
break;
}
InstanceMember *m = new InstanceVariable(immutable, (memberMod == Attribute::Final), c->slotCount++);
defineInstanceMember(c, cxt, *name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, m, p->pos);
}
break;
default:
reportError(Exception::definitionError, "Illegal attribute", p->pos);
break;
}
}
@ -1219,13 +1206,13 @@ doBinary:
else
writeStatus = new OverrideStatus(NULL, id);
if ((!readStatus->overriddenMember && (readStatus->overriddenMember != PotentialConflict))
|| (!writeStatus->overriddenMember && (writeStatus->overriddenMember != PotentialConflict))) {
if ((readStatus->overriddenMember && (readStatus->overriddenMember != PotentialConflict))
|| (writeStatus->overriddenMember && (writeStatus->overriddenMember != PotentialConflict))) {
if ((overrideMod != Attribute::DoOverride) && (overrideMod != Attribute::OverrideUndefined))
reportError(Exception::definitionError, "Illegal override", pos);
}
else {
if ((readStatus->overriddenMember = PotentialConflict) || (writeStatus->overriddenMember == PotentialConflict)) {
if ((readStatus->overriddenMember == PotentialConflict) || (writeStatus->overriddenMember == PotentialConflict)) {
if ((overrideMod != Attribute::DontOverride) && (overrideMod != Attribute::OverrideUndefined))
reportError(Exception::definitionError, "Illegal override", pos);
}
@ -1411,7 +1398,7 @@ doBinary:
return false; // 'None'
}
bool JS2Metadata::writeDynamicProperty(Frame *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase)
bool JS2Metadata::writeDynamicProperty(JS2Object *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase)
{
ASSERT(container && ((container->kind == DynamicInstanceKind)
|| (container->kind == GlobalObjectKind)
@ -1533,14 +1520,8 @@ readClassProperty:
case PackageKind:
case FunctionKind:
case BlockKind:
{
StaticMember *m = findFlatMember(checked_cast<Frame *>(container), multiname, ReadAccess, phase);
if (!m && (container->kind == GlobalObjectKind))
return readDynamicProperty(container, multiname, lookupKind, phase, rval);
else
return readStaticMember(m, phase, rval);
}
break;
return readProperty(checked_cast<Frame *>(container), multiname, lookupKind, ReadAccess, phase);
case ClassKind:
{
MemberDescriptor m2;
@ -1559,6 +1540,7 @@ readClassProperty:
case PrototypeInstanceKind:
return readDynamicProperty(container, multiname, lookupKind, phase, rval);
default:
ASSERT(false);
return false;
@ -1571,22 +1553,10 @@ readClassProperty:
&& ((JS2VAL_TO_OBJECT(thisObjVal)->kind == DynamicInstanceKind)
|| (JS2VAL_TO_OBJECT(thisObjVal)->kind == FixedInstanceKind)));
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisObjVal);
Slot *s;
uint32 slotCount;
if (thisObj->kind == DynamicInstanceKind) {
s = checked_cast<DynamicInstance *>(thisObj)->slots;
slotCount = checked_cast<DynamicInstance *>(thisObj)->type->slotCount;
}
else {
s = checked_cast<FixedInstance *>(thisObj)->slots;
slotCount = checked_cast<FixedInstance *>(thisObj)->type->slotCount;
}
for (uint32 i = 0; i < slotCount; i++) {
if (s[i].id == id)
return &s[i];
}
ASSERT(false);
return NULL;
if (thisObj->kind == DynamicInstanceKind)
return &checked_cast<DynamicInstance *>(thisObj)->slots[id->slotIndex];
else
return &checked_cast<FixedInstance *>(thisObj)->slots[id->slotIndex];
}
@ -1601,7 +1571,8 @@ readClassProperty:
if ((phase == CompilePhase) && !mv->immutable)
reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos());
Slot *s = findSlot(containerVal, mv);
if (JS2VAL_IS_UNINITIALIZED(s->value))
reportError(Exception::uninitializedError, "Reference to uninitialized instance variable", engine->errorPos());
*rval = s->value;
return true;
}
@ -1626,6 +1597,75 @@ readClassProperty:
return readStaticMember(m, phase, rval);
}
// Write the value of a property in the container. Return true/false if that container has
// the property or not.
bool JS2Metadata::writeProperty(js2val containerVal, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase)
{
if (JS2VAL_IS_PRIMITIVE(containerVal))
return false;
JS2Object *container = JS2VAL_TO_OBJECT(containerVal);
switch (container->kind) {
case AttributeObjectKind:
case MultinameKind:
return false;
case FixedInstanceKind:
case DynamicInstanceKind:
{
InstanceBinding *ib = resolveInstanceMemberName(objectType(containerVal), multiname, WriteAccess, phase);
if ((ib == NULL) && (container->kind == DynamicInstanceKind))
return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase);
else
return writeInstanceMember();
}
case SystemKind:
case GlobalObjectKind:
case PackageKind:
case FunctionKind:
case BlockKind:
return writeProperty(checked_cast<Frame *>(container), multiname, lookupKind, createIfMissing, newValue, phase);
case ClassKind:
break;
case PrototypeInstanceKind:
return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase);
default:
ASSERT(false);
return false;
}
}
bool JS2Metadata::writeInstanceMember(JS2Object *thisObj, JS2Class *c, QualifiedName *qname, js2val newValue, Phase phase)
{
if (phase == CompilePhase)
reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos());
InstanceMember *m = findInstanceMember(c, qname, WriteAccess);
if (m == NULL) return false;
switch (m->kind) {
case InstanceMember::InstanceVariableKind:
{
InstanceVariable *mv = checked_cast<InstanceVariable *>(m);
Slot *s = findSlot(containerVal, mv);
if (mv->immutable && JS2VAL_IS_INITIALIZED(s->value))
reportError(Exception::propertyAccessError, "Reinitialization of constant", engine->errorPos());
s->value = engine->assignmentConversion(newValue, mv->type);
return true;
}
case InstanceMember::InstanceMethodKind:
case InstanceMember::InstanceAccessorKind:
reportError(Exception::propertyAccessError, "Attempt to write to a method", engine->errorPos());
break;
}
ASSERT(false);
return false;
}
// Write the value of a property in the frame. Return true/false if that frame has
// the property or not.
bool JS2Metadata::writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase)

Просмотреть файл

@ -134,7 +134,7 @@ public:
class Attribute : public JS2Object {
public:
enum AttributeKind { TrueAttr, FalseAttr, NamespaceAttr, CompoundAttr };
enum MemberModifier { NoModifier, Static, Constructor, Operator, Abstract, Virtual, Final};
enum MemberModifier { NoModifier, Static, Constructor, Abstract, Virtual, Final};
enum OverrideModifier { NoOverride, DoOverride, DontOverride, OverrideUndefined };
@ -308,10 +308,11 @@ public:
class InstanceVariable : public InstanceMember {
public:
InstanceVariable(bool immutable, bool final) : InstanceMember(InstanceVariableKind, final), immutable(immutable) { }
InstanceVariable(bool immutable, bool final, uint32 slotIndex) : InstanceMember(InstanceVariableKind, final), immutable(immutable), slotIndex(slotIndex) { }
JS2Class *type; // Type of values that may be stored in this variable
Invokable *evalInitialValue; // A function that computes this variable's initial value
bool immutable; // true if this variable's value may not be changed once set
uint32 slotIndex; // The index into an instance's slot array in which this variable is stored
};
class InstanceMethod : public InstanceMember {
@ -418,7 +419,8 @@ public:
// A SLOT record describes the value of one fixed property of one instance.
class Slot {
public:
InstanceVariable *id; // The instance variable whose value this slot carries
// We keep the slotIndex in the InstanceVariable rather than go looking for a specific id
// InstanceVariable *id; // The instance variable whose value this slot carries
js2val value; // This fixed property's current value; uninitialised if the fixed property is an uninitialised constant
};
@ -509,8 +511,8 @@ public:
Multiname *propertyMultiname; // A nonempty set of qualified names to which this reference can refer (b
// qualified with the namespace q or all currently open namespaces in the
// example above)
virtual void emitReadBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eDotRead, pos); }
virtual void emitWriteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eDotWrite, pos); }
virtual void emitReadBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eDotRead, pos); bCon->addMultiname(propertyMultiname); }
virtual void emitWriteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eDotWrite, pos); bCon->addMultiname(propertyMultiname); }
};
@ -699,8 +701,9 @@ public:
bool readInstanceMember(js2val containerVal, JS2Class *c, QualifiedName *qname, Phase phase, js2val *rval);
bool writeProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase);
bool writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase);
bool writeDynamicProperty(Frame *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase);
bool writeDynamicProperty(JS2Object *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase);
bool writeStaticMember(StaticMember *m, js2val newValue, Phase phase);

Просмотреть файл

@ -31,6 +31,7 @@
* file under either the NPL or the GPL.
*/
// Read a multiname property from a base object, push the value onto the stack
case eDotRead:
{
LookupKind lookup(false, NULL);
@ -42,7 +43,22 @@
}
break;
// Pop a multiname object and read it's value from the environment on to the stack.
// Write the top value to a multiname property in a base object, leave
// the value on the stack top
case eDotWrite:
{
retval = pop();
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val baseVal = pop();
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &retval))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
push(retval);
}
break;
// Read the multiname from the current environment, push it's value on the stack
case eLexicalRead:
{
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
@ -52,14 +68,14 @@
}
break;
// Pop a value and a multiname. Write the value to the multiname in the environment, leave
// Write the top value to the multiname in the environment, leave
// the value on the stack top.
case eLexicalWrite:
{
retval = top();
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
meta->env.lexicalWrite(meta, mn, retval, true, phase);
push(retval);
}
break;

Просмотреть файл

@ -49,6 +49,7 @@
#define JS2VAL_UNINITIALIZED 0x80 /* reserve this object reference value as an indication
that a variable has yet to be initialized */
#define JS2VAL_IS_INITIALIZED(v) (v != JS2VAL_UNINITIALIZED)
#define JS2VAL_IS_UNINITIALIZED(v) (v == JS2VAL_UNINITIALIZED)
/* Type tag bitfield length and derived macros. */
#define JS2VAL_TAGBITS 3