DefineStaticMember & multiname changes

This commit is contained in:
rogerl%netscape.com 2002-08-26 23:41:19 +00:00
Родитель 8505058394
Коммит 016eae89e3
5 изменённых файлов: 202 добавлений и 46 удалений

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

@ -224,6 +224,7 @@ int JS2Engine::getStackEffect(JS2Op op)
case eReturn:
case ePlus:
return -1;
case eString:
case eTrue:
case eFalse:
@ -231,13 +232,18 @@ int JS2Engine::getStackEffect(JS2Op op)
return 1;
case eLexicalRead:
return 0;
return 0; // consumes a multiname, pushes the value
case eLexicalWrite:
return -1;
return -2; // consumes a multiname and the value
case eReturnVoid:
return 0;
case eMultiname:
case eQMultiname:
return 1; // push the multiname object
default:
ASSERT(false);
}

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

@ -55,11 +55,13 @@ enum JS2Op {
eNumber,
eString, // <string pointer>
eObject, // <named argument count>
eLexicalRead, // <multiname index>
eLexicalWrite, // <multiname index>
eLexicalRead,
eLexicalWrite,
eReturn,
eReturnVoid,
eNewObject // <argCount:16>
eNewObject, // <argCount:16>
eMultiname, // <multiname index>
eQMultiname, // <multiname index>
};

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

@ -154,6 +154,20 @@ namespace MetaData {
ValidateExpression(cxt, env, e->expr);
}
break;
case StmtNode::Namespace:
{
NamespaceStmtNode *ns = checked_cast<NamespaceStmtNode *>(p);
ValidateAttributeExpression(cxt, env, ns->attributes);
Attribute *attr = EvalAttributeExpression(env, CompilePhase, ns->attributes);
CompoundAttribute *a = Attribute::toCompoundAttribute(attr);
if (a->dynamic || a->prototype)
reportError(Exception::definitionError, "Illegal attribute", p->pos);
if ( ! ((a->memberMod == Attribute::NoModifier) || ((a->memberMod == Attribute::Static) && (env->getTopFrame()->kind == ClassKind))) )
reportError(Exception::definitionError, "Illegal attribute", p->pos);
Variable *v = new Variable(namespaceClass, OBJECT_TO_JS2VAL(new Namespace(ns->name)), true);
env->defineStaticMember(this, ns->name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v);
}
break;
} // switch (p->getKind())
}
@ -215,6 +229,10 @@ namespace MetaData {
if (r) r->emitReadBytecode(bCon);
}
break;
case StmtNode::Namespace:
{
}
break;
default:
NOT_REACHED("Not Yet Implemented");
} // switch (p->getKind())
@ -293,7 +311,7 @@ namespace MetaData {
{
BinaryExprNode *j = checked_cast<BinaryExprNode *>(p);
Attribute *a = EvalAttributeExpression(env, phase, j->op1);
if (a && (a->kind == Attribute::FalseKind))
if (a && (a->attrKind == Attribute::FalseAttr))
return a;
Attribute *b = EvalAttributeExpression(env, phase, j->op2);
try {
@ -352,25 +370,25 @@ namespace MetaData {
// a is not false
Attribute *Attribute::combineAttributes(Attribute *a, Attribute *b)
{
if (b && (b->kind == FalseKind)) {
if (b && (b->attrKind == FalseAttr)) {
if (a) delete a;
return b;
}
if (!a || (a->kind == TrueKind)) {
if (!a || (a->attrKind == TrueAttr)) {
if (a) delete a;
return b;
}
if (!b || (b->kind == TrueKind)) {
if (!b || (b->attrKind == TrueAttr)) {
if (b) delete b;
return a;
}
if (a->kind == NamespaceKind) {
if (a->attrKind == NamespaceAttr) {
if (a == b) {
delete b;
return a;
}
Namespace *na = checked_cast<Namespace *>(a);
if (b->kind == NamespaceKind) {
if (b->kind == NamespaceAttr) {
Namespace *nb = checked_cast<Namespace *>(b);
CompoundAttribute *c = new CompoundAttribute();
c->addNamespace(na);
@ -380,7 +398,7 @@ namespace MetaData {
return (Attribute *)c;
}
else {
ASSERT(b->kind == CompoundKind);
ASSERT(b->attrKind == CompoundAttr);
CompoundAttribute *cb = checked_cast<CompoundAttribute *>(b);
cb->addNamespace(na);
delete a;
@ -389,7 +407,7 @@ namespace MetaData {
}
else {
// Both a and b are compound attributes. Ensure that they have no conflicting contents.
ASSERT((a->kind == CompoundKind) && (b->kind == CompoundKind));
ASSERT((a->attrKind == CompoundAttr) && (b->attrKind == CompoundAttr));
CompoundAttribute *ca = checked_cast<CompoundAttribute *>(a);
CompoundAttribute *cb = checked_cast<CompoundAttribute *>(b);
if ((ca->memberMod != NoModifier) && (cb->memberMod != NoModifier) && (ca->memberMod != cb->memberMod))
@ -420,7 +438,7 @@ namespace MetaData {
namespaces->push_back(n);
}
CompoundAttribute::CompoundAttribute() : Attribute(CompoundKind),
CompoundAttribute::CompoundAttribute() : Attribute(CompoundAttr),
namespaces(NULL), xplicit(false), dynamic(false), memberMod(NoModifier),
overrideMod(NoOverride), prototype(false), unused(false)
{
@ -551,9 +569,8 @@ namespace MetaData {
{
QualifyExprNode *qe = checked_cast<QualifyExprNode *>(p);
const StringAtom &name = checked_cast<IdentifierExprNode *>(p)->name;
const StringAtom &qualifierName = checked_cast<IdentifierExprNode *>(qe->qualifier)->name;
returnRef = new LexicalReference(i->name, cxt.strict);
EvalExprNode(env, phase, qe->qualifier);
returnRef = new LexicalReference(name, cxt.strict, true);
}
break;
case ExprNode::identifier:
@ -606,6 +623,7 @@ namespace MetaData {
if (b->op2->getKind() == ExprNode::qualify) {
}
}
}
break;
default:
NOT_REACHED("Not Yet Implemented");
@ -713,6 +731,58 @@ namespace MetaData {
meta->reportError(Exception::referenceError, "{0} is undefined", meta->errorPos, multiname->name);
}
void Environment::defineStaticMember(JS2Metadata *meta, const StringAtom &id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, StaticMember *m)
{
NamespaceList publicNamespaceList;
Frame *localFrame = firstFrame;
if ((overrideMod != Attribute::NoOverride) || (xplicit && localFrame->kind != PackageKind))
meta->reportError(Exception::definitionError, "Illegal definition", meta->errorPos);
if (namespaces->empty()) {
publicNamespaceList.push_back(meta->publicNamespace);
namespaces = &publicNamespaceList;
}
Multiname *mn = new Multiname(id, true);
mn->addNamespace(namespaces);
for (StaticBindingIterator b = localFrame->staticReadBindings.lower_bound(id),
end = localFrame->staticReadBindings.upper_bound(id); (b != end); b++) {
if (b->second->qname == qName)
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
}
Frame *regionalFrame = getRegionalFrame();
Frame *fr = firstFrame->nextFrame;
while (true) {
for (b = fr->staticReadBindings.lower_bound(id),
end = fr->staticReadBindings.upper_bound(id); (b != end); b++) {
if ((b->second->qname == qName) && (b->second->content->kind != Forbidden))
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
}
fr = fr->nextFrame;
if (fr == regionalFrame) break;
}
if (regionalFrame->kind == GlobalObjectKind) {
GlobalObject *gObj = checked_cast<GlobalObject *>(regionalFrame);
DynamicPropertyIterator dp = gObj->dynamicProperties.find(id);
if (dp != gObj->dynamicProperties.end())
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
}
for (NamespaceListIterator nli = mn->nsList.begin(), end = mn->nsList.end(); (nli != end); nli++) {
QualifiedName qName(*nli, id);
StaticBinding *sb = new StaticBinding(qName, new HoistedVar());
const StaticBindingMap::value_type e(id, sb);
if ((access == ReadAccess) || (access == ReadWriteAccess))
regionalFrame->staticReadBindings.insert(e);
if ((access == WriteAccess) || (access == ReadWriteAccess))
regionalFrame->staticWriteBindings.insert(e);
}
}
/************************************************************************************
*
@ -720,10 +790,13 @@ namespace MetaData {
*
************************************************************************************/
// clone a context
Context::Context(Context *cxt) : strict(cxt->strict), openNamespaces(cxt->openNamespaces)
{
ASSERT(false); // ?? used ??
}
/************************************************************************************
*
* Multiname
@ -742,7 +815,14 @@ namespace MetaData {
void Multiname::addNamespace(Context &cxt)
{
for (NamespaceListIterator nli = cxt.openNamespaces.begin(), end = cxt.openNamespaces.end();
addNamespace(&cxt.openNamespaces);
}
// add every namespace from the list to this Multiname
void Multiname::addNamespace(NamespaceList *ns)
{
for (NamespaceListIterator nli = ns->begin(), end = ns->end();
(nli != end); nli++)
nsList.push_back(*nli);
}
@ -1120,15 +1200,44 @@ namespace MetaData {
reportError(kind, message, pos, str.c_str());
}
/************************************************************************************
*
* Pond
*
************************************************************************************/
Pond::Pond(size_t sz, Pond *next) : pondSize(sz + POND_SIZE), pondBase(new uint8[pondSize]), pondTop(pondBase), nextPond(next)
{
}
void *Pond::allocFromPond(size_t sz)
{
if (sz > (pondSize - (pondTop - pondBase))) {
if (nextPond == NULL)
nextPond = new Pond(sz, nextPond);
return nextPond->allocFromPond(sz);
}
void *p = pondTop;
pondTop += sz;
return p;
}
/************************************************************************************
*
* JS2Object
*
************************************************************************************/
Pond JS2Object::pond(POND_SIZE, NULL);
void *JS2Object::operator new(size_t s)
{
return STD::malloc(s);
// make sure that the thing is 8-byte aligned
if (s & 0x7) s += 8 - (s & 0x7);
return pond.allocFromPond(s);
}
}; // namespace MetaData

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

@ -64,7 +64,23 @@ enum ObjectKind {
BlockKind,
PrototypeInstanceKind,
FixedInstanceKind,
DynamicInstanceKind };
DynamicInstanceKind,
MultinameKind
};
#define POND_SIZE (8000)
class Pond {
public:
Pond(size_t sz, Pond *nextPond);
void *allocFromPond(size_t t);
size_t pondSize;
uint8 *pondBase;
uint8 *pondTop;
Pond *nextPond;
};
class JS2Object {
// Every object is either undefined, null, a Boolean,
@ -76,7 +92,7 @@ public:
ObjectKind kind;
static Pond pond;
void *operator new(size_t s);
@ -87,28 +103,31 @@ public:
class Attribute : public JS2Object {
public:
enum AttributeKind { TrueKind, FalseKind, NamespaceKind, CompoundKind } kind;
enum AttributeKind { TrueAttr, FalseAttr, NamespaceAttr, CompoundAttr };
enum MemberModifier { NoModifier, Static, Constructor, Operator, Abstract, Virtual, Final};
enum OverrideModifier { NoOverride, DoOverride, DontOverride, OverrideUndefined };
Attribute(AttributeKind kind) : JS2Object(AttributeObjectKind), kind(kind) { }
Attribute(AttributeKind akind) : JS2Object(AttributeObjectKind), attrKind(akind) { }
static Attribute *combineAttributes(Attribute *a, Attribute *b);
static CompoundAttribute *toCompoundAttribute(Attribute *a);
virtual CompoundAttribute *toCompoundAttribute() { ASSERT(false); return NULL; }
AttributeKind attrKind;
};
// A Namespace (is also an attribute)
class Namespace : public Attribute {
public:
Namespace(StringAtom &name) : Attribute(NamespaceKind), name(name) { }
Namespace(const StringAtom &name) : Attribute(NamespaceAttr), name(name) { }
virtual CompoundAttribute *toCompoundAttribute();
StringAtom &name; // The namespace's name used by toString
const StringAtom &name; // The namespace's name used by toString
};
// A QualifiedName is the combination of an identifier and a namespace
@ -128,12 +147,17 @@ public:
// Pointers to Multiname instances get embedded in the bytecode.
typedef std::vector<Namespace *> NamespaceList;
typedef NamespaceList::iterator NamespaceListIterator;
class Multiname {
class Multiname : public JS2Object {
public:
Multiname(const StringAtom &name) : name(name) { }
Multiname(const StringAtom &name, Context &cxt) : name(name) { addNamespace(cxt); }
Multiname(const StringAtom &name) : JS2Object(MultinameKind), name(name), qualified(false) { }
Multiname(const StringAtom &name, bool qualified) : JS2Object(MultinameKind), name(name), qualified(qualified) { }
void emitBytecode(BytecodeContainer *bCon) { bCon->emitOp(qualified ? eQMultiname : eMultiname); bCon->addMultiname(this); }
void addNamespace(Namespace *ns) { nsList.push_back(ns); }
void addNamespace(NamespaceList *ns);
void addNamespace(Context &cxt);
bool matches(QualifiedName &q) { return (name == q.id) && onList(q.nameSpace); }
@ -141,6 +165,7 @@ public:
NamespaceList nsList;
const StringAtom &name;
bool qualified; // true for q::a, otherwise false
};
@ -184,6 +209,7 @@ public:
class Variable : public StaticMember {
public:
Variable() : StaticMember(StaticMember::Variable), type(NULL), value(JS2VAL_VOID), immutable(false) { }
Variable(JS2Class *type, js2val value, bool immutable) : StaticMember(StaticMember::Variable), type(type), value(value), immutable(immutable) { }
JS2Class *type; // Type of values that may be stored in this variable
js2val value; // This variable's current value; future if the variable has not been declared yet;
@ -401,8 +427,8 @@ class LexicalReference : public Reference {
// q::a.
public:
LexicalReference(const StringAtom &name, bool strict) : variableMultiname(new Multiname(name)), env(NULL), strict(strict) { }
LexicalReference(const StringAtom &name, const StringAtom &qualifiedName, bool strict) : variableMultiname(new Multiname(name)), env(NULL), strict(strict) { }
LexicalReference(Multiname *vm, Environment *env, bool strict) : variableMultiname(vm), env(env), strict(strict) { }
LexicalReference(const StringAtom &name, bool strict, bool qualified) : variableMultiname(new Multiname(name, qualified)), env(NULL), strict(strict) { }
Multiname *variableMultiname; // A nonempty set of qualified names to which this reference can refer
Environment *env; // The environment in which the reference was created.
@ -410,8 +436,8 @@ public:
virtual void emitReadBytecode(BytecodeContainer *bCon) { bCon->emitOp(eLexicalRead); bCon->addMultiname(variableMultiname); }
virtual void emitWriteBytecode(BytecodeContainer *bCon) { bCon->emitOp(eLexicalWrite); bCon->addMultiname(variableMultiname); }
virtual void emitReadBytecode(BytecodeContainer *bCon) { variableMultiname->emitBytecode(bCon); bCon->emitOp(eLexicalRead); }
virtual void emitWriteBytecode(BytecodeContainer *bCon) { variableMultiname->emitBytecode(bCon); bCon->emitOp(eLexicalWrite); }
};
class DotReference : public Reference {
@ -511,6 +537,7 @@ public:
js2val lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase);
void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase);
void defineStaticMember(JS2Metadata *meta, const StringAtom &id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, StaticMember *m);
private:
Frame *firstFrame;
@ -532,14 +559,14 @@ public:
// The 'true' attribute
class TrueAttribute : public Attribute {
public:
TrueAttribute() : Attribute(TrueKind) { }
TrueAttribute() : Attribute(TrueAttr) { }
virtual CompoundAttribute *toCompoundAttribute();
};
// The 'false' attribute
class FalseAttribute : public Attribute {
public:
FalseAttribute() : Attribute(FalseKind) { }
FalseAttribute() : Attribute(FalseAttr) { }
};
// Compound attribute objects are all values obtained from combining zero or more syntactic attributes
@ -624,6 +651,7 @@ public:
JS2Class *characterClass;
JS2Class *stringClass;
JS2Class *objectClass;
JS2Class *namespaceClass;
Parser *mParser; // used for error reporting
size_t errorPos;

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

@ -35,27 +35,38 @@
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
mn->addNamespace(meta->cxt);
push(OBJECT_TO_JS2VAL(mn));
}
break;
case eQualifiedMultiname: {
case eQMultiname: {
js2val nsVal = pop();
if (!JS2VAL_IS_OBJECT(nsVal))
meta->reportError(Exception::badValueError, "Expected a namespace", meta->errorPos);
JS2Object *obj = JS2VAL_TO_OBJECT(nsVal);
if ((obj->kind != AttributeObjectKind) || ((checked_cast<Attribute *>(obj))->attrKind != Attribute::NamespaceAttr))
meta->reportError(Exception::badValueError, "Expected a namespace", meta->errorPos);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
mn->addNamespace(meta->cxt);
mn->addNamespace(checked_cast<Namespace *>(obj));
push(OBJECT_TO_JS2VAL(mn));
}
break;
case eLexicalRead: {
js2val n = pop();
ASSERT(JS2VAL_IS_OBJECT(n));
meta->env.lexicalRead(meta, mn, phase);
js2val mnVal = pop();
ASSERT(JS2VAL_IS_OBJECT(mnVal));
JS2Object *obj = JS2VAL_TO_OBJECT(mnVal);
Multiname *mn = checked_cast<Multiname *>(obj);
push(meta->env.lexicalRead(meta, mn, phase));
}
break;
case eLexicalWrite: {
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
mn->addNamespace(meta->cxt);
js2val mnVal = pop();
ASSERT(JS2VAL_IS_OBJECT(mnVal));
JS2Object *obj = JS2VAL_TO_OBJECT(mnVal);
Multiname *mn = checked_cast<Multiname *>(obj);
retval = pop();
meta->env.lexicalWrite(meta, mn, retval, true, phase);
}