Various bug fixings. Added 'dynamic' attribute.
git-svn-id: svn://10.0.0.236/trunk@135505 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
487ae18e8b
commit
c0a00027a6
@ -339,23 +339,24 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint
|
||||
|
||||
js2val load(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint32 argc)
|
||||
{
|
||||
// Set the environment to global object and system frame so that the
|
||||
// load happens into the top frame.
|
||||
if (argc) {
|
||||
// Save off the current top frame and root it.
|
||||
Frame *curTopFrame = meta->env.getTopFrame();
|
||||
JS2Object::RootIterator ri = JS2Object::addRoot(&curTopFrame);
|
||||
meta->env.setTopFrame(meta->env.getPackageOrGlobalFrame());
|
||||
Environment *curEnv = meta->env;
|
||||
JS2Object::RootIterator ri = JS2Object::addRoot(&curEnv);
|
||||
// Set the environment to global object and system frame so that the
|
||||
// load happens into the top frame.
|
||||
meta->env = new Environment(curEnv->getSystemFrame(), curEnv->getPackageOrGlobalFrame());
|
||||
|
||||
js2val result = JS2VAL_UNDEFINED;
|
||||
try {
|
||||
result = meta->readEvalFile(*meta->toString(argv[0]));
|
||||
}
|
||||
catch (Exception x) {
|
||||
meta->env.setTopFrame(curTopFrame);
|
||||
meta->env = curEnv;
|
||||
JS2Object::removeRoot(ri);
|
||||
throw x;
|
||||
}
|
||||
meta->env.setTopFrame(curTopFrame);
|
||||
meta->env = curEnv;
|
||||
JS2Object::removeRoot(ri);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -754,7 +754,7 @@ namespace MetaData {
|
||||
activationStackTop->bCon = bCon;
|
||||
activationStackTop->pc = pc;
|
||||
activationStackTop->phase = phase;
|
||||
activationStackTop->topFrame = meta->env.getTopFrame();
|
||||
activationStackTop->topFrame = meta->env->getTopFrame();
|
||||
activationStackTop->execStackBase = stackBase;
|
||||
activationStackTop->retval = returnVal;
|
||||
activationStackTop++;
|
||||
@ -774,8 +774,8 @@ namespace MetaData {
|
||||
bCon = activationStackTop->bCon;
|
||||
pc = activationStackTop->pc;
|
||||
phase = activationStackTop->phase;
|
||||
while (meta->env.getTopFrame() != activationStackTop->topFrame)
|
||||
meta->env.removeTopFrame();
|
||||
while (meta->env->getTopFrame() != activationStackTop->topFrame)
|
||||
meta->env->removeTopFrame();
|
||||
sp = activationStackTop->execStackBase;
|
||||
if (!JS2VAL_IS_VOID(activationStackTop->retval)) // XXX might need an actual 'returnValue' flag instead
|
||||
retval = activationStackTop->retval;
|
||||
|
||||
@ -306,13 +306,13 @@ void initMathObject(JS2Metadata *meta)
|
||||
publicNamespaceList.push_back(meta->publicNamespace);
|
||||
|
||||
uint32 i;
|
||||
meta->env.addFrame(meta->mathClass);
|
||||
meta->env->addFrame(meta->mathClass);
|
||||
for (i = 0; i < M_CONSTANTS_COUNT; i++)
|
||||
{
|
||||
Variable *v = new Variable(meta->numberClass, meta->engine->allocNumber(MathObjectConstants[i].value), true);
|
||||
meta->defineStaticMember(&meta->env, &meta->world.identifiers[MathObjectConstants[i].name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
meta->defineStaticMember(meta->env, &meta->world.identifiers[MathObjectConstants[i].name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
}
|
||||
meta->env.removeTopFrame();
|
||||
meta->env->removeTopFrame();
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
@ -343,16 +343,16 @@ void initMathObject(JS2Metadata *meta)
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
meta->env.addFrame(meta->mathClass);
|
||||
meta->env->addFrame(meta->mathClass);
|
||||
PrototypeFunction *pf = &prototypeFunctions[0];
|
||||
while (pf->name) {
|
||||
CallableInstance *fInst = new CallableInstance(meta->functionClass);
|
||||
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
|
||||
Variable *v = new Variable(meta->functionClass, OBJECT_TO_JS2VAL(fInst), true);
|
||||
meta->defineStaticMember(&meta->env, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
meta->defineStaticMember(meta->env, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
pf++;
|
||||
}
|
||||
meta->env.removeTopFrame();
|
||||
meta->env->removeTopFrame();
|
||||
|
||||
|
||||
|
||||
|
||||
@ -147,7 +147,7 @@ namespace MetaData {
|
||||
*/
|
||||
void JS2Metadata::ValidateStmtList(StmtNode *p) {
|
||||
while (p) {
|
||||
ValidateStmt(&cxt, &env, Singular, p);
|
||||
ValidateStmt(&cxt, env, Singular, p);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
@ -162,37 +162,47 @@ namespace MetaData {
|
||||
CallableInstance *JS2Metadata::validateStaticFunction(FunctionStmtNode *f, js2val compileThis, bool prototype, bool unchecked, Context *cxt, Environment *env)
|
||||
{
|
||||
ParameterFrame *compileFrame = new ParameterFrame(compileThis, prototype);
|
||||
CompilationData *oldData = startCompilationUnit(f->fWrap->bCon, bCon->mSource, bCon->mSourceLocation);
|
||||
env->addFrame(compileFrame);
|
||||
VariableBinding *pb = f->function.parameters;
|
||||
if (pb) {
|
||||
NamespaceList publicNamespaceList;
|
||||
publicNamespaceList.push_back(publicNamespace);
|
||||
uint32 pCount = 0;
|
||||
while (pb) {
|
||||
pCount++;
|
||||
pb = pb->next;
|
||||
}
|
||||
pb = f->function.parameters;
|
||||
compileFrame->positional = new Variable *[pCount];
|
||||
compileFrame->positionalCount = pCount;
|
||||
pCount = 0;
|
||||
while (pb) {
|
||||
// XXX define a static binding for each parameter
|
||||
Variable *v = new Variable();
|
||||
compileFrame->positional[pCount++] = v;
|
||||
pb->mn = defineStaticMember(env, pb->name, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, pb->pos);
|
||||
pb = pb->next;
|
||||
}
|
||||
}
|
||||
ValidateStmt(cxt, env, Plural, f->function.body);
|
||||
env->removeTopFrame();
|
||||
restoreCompilationUnit(oldData);
|
||||
|
||||
CallableInstance *fInst = new CallableInstance(functionClass);
|
||||
fInst->fWrap = new FunctionWrapper(unchecked, compileFrame);
|
||||
f->fWrap = fInst->fWrap;
|
||||
|
||||
JS2Object::RootIterator ri = JS2Object::addRoot(&fInst);
|
||||
Frame *curTopFrame = env->getTopFrame();
|
||||
|
||||
try {
|
||||
CompilationData *oldData = startCompilationUnit(f->fWrap->bCon, bCon->mSource, bCon->mSourceLocation);
|
||||
env->addFrame(compileFrame);
|
||||
VariableBinding *pb = f->function.parameters;
|
||||
if (pb) {
|
||||
NamespaceList publicNamespaceList;
|
||||
publicNamespaceList.push_back(publicNamespace);
|
||||
uint32 pCount = 0;
|
||||
while (pb) {
|
||||
pCount++;
|
||||
pb = pb->next;
|
||||
}
|
||||
pb = f->function.parameters;
|
||||
compileFrame->positional = new Variable *[pCount];
|
||||
compileFrame->positionalCount = pCount;
|
||||
pCount = 0;
|
||||
while (pb) {
|
||||
// XXX define a static binding for each parameter
|
||||
Variable *v = new Variable();
|
||||
compileFrame->positional[pCount++] = v;
|
||||
pb->mn = defineStaticMember(env, pb->name, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, pb->pos);
|
||||
pb = pb->next;
|
||||
}
|
||||
}
|
||||
ValidateStmt(cxt, env, Plural, f->function.body);
|
||||
env->removeTopFrame();
|
||||
restoreCompilationUnit(oldData);
|
||||
}
|
||||
catch (Exception x) {
|
||||
env->setTopFrame(curTopFrame);
|
||||
JS2Object::removeRoot(ri);
|
||||
throw x;
|
||||
}
|
||||
JS2Object::removeRoot(ri);
|
||||
return fInst;
|
||||
}
|
||||
|
||||
@ -478,8 +488,6 @@ namespace MetaData {
|
||||
compileThis = JS2VAL_INACCESSIBLE;
|
||||
Frame *topFrame = env->getTopFrame();
|
||||
|
||||
CallableInstance *fInst = validateStaticFunction(f, compileThis, prototype, unchecked, cxt, env);
|
||||
|
||||
switch (memberMod) {
|
||||
case Attribute::NoModifier:
|
||||
case Attribute::Static:
|
||||
@ -488,6 +496,7 @@ namespace MetaData {
|
||||
// XXX getter/setter --> ????
|
||||
}
|
||||
else {
|
||||
CallableInstance *fInst = validateStaticFunction(f, compileThis, prototype, unchecked, cxt, env);
|
||||
if (unchecked
|
||||
&& (f->attributes == NULL)
|
||||
&& ((topFrame->kind == GlobalObjectKind)
|
||||
@ -507,6 +516,7 @@ namespace MetaData {
|
||||
case Attribute::Final:
|
||||
{
|
||||
// XXX Here the spec. has ???, so the following is tentative
|
||||
CallableInstance *fInst = validateStaticFunction(f, compileThis, prototype, unchecked, cxt, env);
|
||||
JS2Class *c = checked_cast<JS2Class *>(env->getTopFrame());
|
||||
InstanceMember *m = new InstanceMethod(fInst);
|
||||
defineInstanceMember(c, cxt, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, m, p->pos);
|
||||
@ -515,6 +525,7 @@ namespace MetaData {
|
||||
case Attribute::Constructor:
|
||||
{
|
||||
// XXX Here the spec. has ???, so the following is tentative
|
||||
CallableInstance *fInst = validateStaticFunction(f, compileThis, prototype, unchecked, cxt, env);
|
||||
ConstructorMethod *cm = new ConstructorMethod(OBJECT_TO_JS2VAL(fInst));
|
||||
defineStaticMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, cm, p->pos);
|
||||
}
|
||||
@ -702,7 +713,7 @@ namespace MetaData {
|
||||
{
|
||||
size_t lastPos = p->pos;
|
||||
while (p) {
|
||||
SetupStmt(&env, phase, p);
|
||||
SetupStmt(env, phase, p);
|
||||
lastPos = p->pos;
|
||||
p = p->next;
|
||||
}
|
||||
@ -729,7 +740,7 @@ namespace MetaData {
|
||||
ASSERT(phase == CompilePhase);
|
||||
if (v->vb->type) {
|
||||
v->type = NULL;
|
||||
v->type = EvalTypeExpression(&env, CompilePhase, v->vb->type);
|
||||
v->type = EvalTypeExpression(env, CompilePhase, v->vb->type);
|
||||
}
|
||||
else
|
||||
v->type = objectClass;
|
||||
@ -1423,6 +1434,12 @@ namespace MetaData {
|
||||
ca->memberMod = Attribute::Virtual;
|
||||
return ca;
|
||||
}
|
||||
else
|
||||
if (name == world.identifiers["dynamic"]) {
|
||||
ca = new CompoundAttribute();
|
||||
ca->dynamic = true;
|
||||
return ca;
|
||||
}
|
||||
}
|
||||
}
|
||||
// fall thru to execute a readReference on the identifier...
|
||||
@ -2376,7 +2393,7 @@ doUnary:
|
||||
break;
|
||||
fi++;
|
||||
}
|
||||
if ((fi != getEnd()) && ((*fi)->kind == ClassKind))
|
||||
if ((fi != getBegin()) && ((*fi)->kind == ClassKind))
|
||||
fi--;
|
||||
return fi;
|
||||
}
|
||||
@ -2384,7 +2401,7 @@ doUnary:
|
||||
// Returns the penultimate frame, either Package or Global
|
||||
Frame *Environment::getPackageOrGlobalFrame()
|
||||
{
|
||||
return *(getEnd() - 1);
|
||||
return *(getEnd() - 2);
|
||||
}
|
||||
|
||||
// findThis returns the value of this. If allowPrototypeThis is true, allow this to be defined
|
||||
@ -2497,7 +2514,7 @@ doUnary:
|
||||
// need to mark all the frames in the environment - otherwise a marked frame that
|
||||
// came initially from the bytecodeContainer may prevent the markChildren call
|
||||
// from finding frames further down the list.
|
||||
void Environment::mark()
|
||||
void Environment::markChildren()
|
||||
{
|
||||
FrameListIterator fi = getBegin();
|
||||
while (fi != getEnd()) {
|
||||
@ -2606,6 +2623,16 @@ doUnary:
|
||||
}
|
||||
fr = *++fi;
|
||||
}
|
||||
fi = env->getBegin();
|
||||
fr = *++fi;
|
||||
while (fr != regionalFrame) {
|
||||
for (b = fr->staticWriteBindings.lower_bound(*id),
|
||||
end = fr->staticWriteBindings.upper_bound(*id); (b != end); b++) {
|
||||
if (mn->matches(b->second->qname) && (b->second->content->kind != StaticMember::Forbidden))
|
||||
reportError(Exception::definitionError, "Duplicate definition {0}", pos, id);
|
||||
}
|
||||
fr = *++fi;
|
||||
}
|
||||
}
|
||||
if (regionalFrame->kind == GlobalObjectKind) {
|
||||
GlobalObject *gObj = checked_cast<GlobalObject *>(regionalFrame);
|
||||
@ -2625,6 +2652,7 @@ doUnary:
|
||||
}
|
||||
|
||||
if (localFrame != regionalFrame) {
|
||||
fi = env->getBegin();
|
||||
Frame *fr = *++fi;
|
||||
while (fr != regionalFrame) {
|
||||
for (NamespaceListIterator nli = mn->nsList.begin(), nlend = mn->nsList.end(); (nli != nlend); nli++) {
|
||||
@ -2642,7 +2670,7 @@ doUnary:
|
||||
return mn;
|
||||
}
|
||||
|
||||
// Look through 'c' and all it's super classes for a identifier
|
||||
// Look through 'c' and all it's super classes for an identifier
|
||||
// matching the qualified name and access.
|
||||
InstanceMember *JS2Metadata::findInstanceMember(JS2Class *c, QualifiedName *qname, Access access)
|
||||
{
|
||||
@ -2933,7 +2961,7 @@ doUnary:
|
||||
publicNamespace(new Namespace(engine->public_StringAtom)),
|
||||
bCon(new BytecodeContainer()),
|
||||
glob(new GlobalObject(world)),
|
||||
env(new MetaData::SystemFrame(), glob),
|
||||
env(new Environment(new MetaData::SystemFrame(), glob)),
|
||||
showTrees(false)
|
||||
{
|
||||
engine->meta = this;
|
||||
@ -2959,6 +2987,22 @@ doUnary:
|
||||
// A 'forbidden' member, used to mark hidden bindings
|
||||
forbiddenMember = new StaticMember(Member::Forbidden);
|
||||
|
||||
// needed for class instance variables etc...
|
||||
NamespaceList publicNamespaceList;
|
||||
publicNamespaceList.push_back(publicNamespace);
|
||||
Variable *v;
|
||||
|
||||
|
||||
|
||||
// XXX Built-in Attributes... XXX
|
||||
/*
|
||||
XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
||||
|
||||
CompoundAttribute *attr = new CompoundAttribute();
|
||||
attr->dynamic = true;
|
||||
v = new Variable(attributeClass, OBJECT_TO_JS2VAL(attr), true);
|
||||
defineStaticMember(env, &world.identifiers["dynamic"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
*/
|
||||
|
||||
/*** ECMA 3 Global Object ***/
|
||||
// Non-function properties of the global object : 'undefined', 'NaN' and 'Infinity'
|
||||
@ -2978,49 +3022,44 @@ doUnary:
|
||||
writeDynamicProperty(objectClass->prototype, new Multiname(engine->toString_StringAtom, publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
|
||||
|
||||
|
||||
// needed for class instance variables etc...
|
||||
NamespaceList publicNamespaceList;
|
||||
publicNamespaceList.push_back(publicNamespace);
|
||||
Variable *v;
|
||||
|
||||
/*** ECMA 3 Date Class ***/
|
||||
MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, &world.identifiers["Date"]);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(dateClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["Date"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
defineStaticMember(env, &world.identifiers["Date"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
// dateClass->prototype = new PrototypeInstance(NULL, dateClass);
|
||||
initDateObject(this);
|
||||
|
||||
/*** ECMA 3 RegExp Class ***/
|
||||
MAKEBUILTINCLASS(regexpClass, objectClass, true, true, true, &world.identifiers["RegExp"]);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(regexpClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["RegExp"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
defineStaticMember(env, &world.identifiers["RegExp"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initRegExpObject(this);
|
||||
|
||||
/*** ECMA 3 String Class ***/
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(stringClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["String"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
defineStaticMember(env, &world.identifiers["String"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initStringObject(this);
|
||||
|
||||
/*** ECMA 3 Number Class ***/
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(numberClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["Number"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
defineStaticMember(env, &world.identifiers["Number"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initNumberObject(this);
|
||||
|
||||
/*** ECMA 3 Math Class ***/
|
||||
MAKEBUILTINCLASS(mathClass, objectClass, true, true, true, &world.identifiers["Math"]);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(mathClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["Math"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
defineStaticMember(env, &world.identifiers["Math"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initMathObject(this);
|
||||
|
||||
/*** ECMA 3 Array Class ***/
|
||||
MAKEBUILTINCLASS(arrayClass, objectClass, true, true, true, &world.identifiers["Array"]);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(arrayClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["Array"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
defineStaticMember(env, &world.identifiers["Array"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initArrayObject(this);
|
||||
|
||||
/*** ECMA 3 Function Class ***/
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(functionClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["Function"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
defineStaticMember(env, &world.identifiers["Function"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
// XXX more here!
|
||||
|
||||
}
|
||||
@ -3090,7 +3129,7 @@ doUnary:
|
||||
bool JS2Metadata::relaxedHasType(js2val objVal, JS2Class *c)
|
||||
{
|
||||
JS2Class *t = objectType(objVal);
|
||||
return c->isAncestor(t) || (JS2VAL_IS_NULL(objVal) && t->allowNull);
|
||||
return t->isAncestor(c) || (JS2VAL_IS_NULL(objVal) && t->allowNull);
|
||||
}
|
||||
|
||||
|
||||
@ -3237,6 +3276,8 @@ doUnary:
|
||||
dMap = &(checked_cast<GlobalObject *>(container))->dynamicProperties;
|
||||
else
|
||||
dMap = &(checked_cast<PrototypeInstance *>(container))->dynamicProperties;
|
||||
if (dMap == NULL)
|
||||
return false; // 'None'
|
||||
for (DynamicPropertyIterator i = dMap->begin(), end = dMap->end(); (i != end); i++) {
|
||||
if (i->first == *name) {
|
||||
i->second = newValue;
|
||||
@ -3879,7 +3920,7 @@ deleteClassProperty:
|
||||
bCon->mark();
|
||||
if (engine)
|
||||
engine->mark();
|
||||
env.mark();
|
||||
GCMARKOBJECT(env);
|
||||
|
||||
GCMARKOBJECT(glob);
|
||||
|
||||
@ -4206,7 +4247,7 @@ deleteClassProperty:
|
||||
}
|
||||
}
|
||||
|
||||
// return true if 'heir' is a member of this class or of any antecedent
|
||||
// return true if 'heir' is this class or is any antecedent
|
||||
bool JS2Class::isAncestor(JS2Class *heir)
|
||||
{
|
||||
JS2Class *kinsman = this;
|
||||
|
||||
@ -94,7 +94,9 @@ enum ObjectKind {
|
||||
MultinameKind,
|
||||
MethodClosureKind,
|
||||
AlienInstanceKind,
|
||||
ForIteratorKind
|
||||
ForIteratorKind,
|
||||
|
||||
EnvironmentKind // Not an available JS2 runtime kind
|
||||
};
|
||||
|
||||
enum Plurality { Singular, Plural };
|
||||
@ -877,9 +879,10 @@ public:
|
||||
typedef std::deque<Frame *> FrameList;
|
||||
typedef FrameList::iterator FrameListIterator;
|
||||
|
||||
class Environment {
|
||||
// Deriving from JS2Object for gc sake only, these are supposed to be found as JS2 values
|
||||
class Environment : public JS2Object {
|
||||
public:
|
||||
Environment(SystemFrame *systemFrame, Frame *nextToLast) { frameList.push_back(nextToLast); frameList.push_back(systemFrame); }
|
||||
Environment(SystemFrame *systemFrame, Frame *nextToLast) : JS2Object(EnvironmentKind) { frameList.push_back(nextToLast); frameList.push_back(systemFrame); }
|
||||
|
||||
JS2Class *getEnclosingClass();
|
||||
FrameListIterator getRegionalFrame();
|
||||
@ -887,7 +890,7 @@ public:
|
||||
FrameListIterator getBegin() { return frameList.begin(); }
|
||||
FrameListIterator getEnd() { return frameList.end(); }
|
||||
Frame *getPackageOrGlobalFrame();
|
||||
Frame *getSystemFrame() { return frameList.back(); }
|
||||
SystemFrame *getSystemFrame() { return checked_cast<SystemFrame *>(frameList.back()); }
|
||||
|
||||
void setTopFrame(Frame *f) { while (frameList.front() != f) frameList.pop_front(); }
|
||||
|
||||
@ -901,7 +904,7 @@ public:
|
||||
|
||||
void instantiateFrame(Frame *pluralFrame, Frame *singularFrame);
|
||||
|
||||
void mark();
|
||||
void markChildren();
|
||||
|
||||
private:
|
||||
FrameList frameList;
|
||||
@ -986,6 +989,7 @@ public:
|
||||
js2val readEvalFile(const String& fileName);
|
||||
js2val readEvalFile(const char *fileName);
|
||||
|
||||
// XXX - passing (Context *cxt, Environment *env) throughout - but do these really change?
|
||||
|
||||
void ValidateStmtList(Context *cxt, Environment *env, Plurality pl, StmtNode *p);
|
||||
void ValidateTypeExpression(Context *cxt, Environment *env, ExprNode *e) { ValidateExpression(cxt, env, e); }
|
||||
@ -1110,7 +1114,7 @@ public:
|
||||
BConList bConList;
|
||||
|
||||
GlobalObject *glob;
|
||||
Environment env;
|
||||
Environment *env;
|
||||
Context cxt;
|
||||
|
||||
TargetList targetList; // stack of potential break/continue targets
|
||||
|
||||
@ -100,13 +100,13 @@ namespace MetaData {
|
||||
publicNamespaceList.push_back(meta->publicNamespace);
|
||||
|
||||
uint32 i;
|
||||
meta->env.addFrame(meta->numberClass);
|
||||
meta->env->addFrame(meta->numberClass);
|
||||
for (i = 0; i < N_CONSTANTS_COUNT; i++)
|
||||
{
|
||||
Variable *v = new Variable(meta->numberClass, meta->engine->allocNumber(NumberObjectConstants[i].value), true);
|
||||
meta->defineStaticMember(&meta->env, &meta->world.identifiers[NumberObjectConstants[i].name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
meta->defineStaticMember(meta->env, &meta->world.identifiers[NumberObjectConstants[i].name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
}
|
||||
meta->env.removeTopFrame();
|
||||
meta->env->removeTopFrame();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
{
|
||||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
push(meta->env.lexicalRead(meta, mn, phase));
|
||||
push(meta->env->lexicalRead(meta, mn, phase));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -98,7 +98,7 @@
|
||||
{
|
||||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
push(BOOLEAN_TO_JS2VAL(meta->env.lexicalDelete(meta, mn, phase)));
|
||||
push(BOOLEAN_TO_JS2VAL(meta->env->lexicalDelete(meta, mn, phase)));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -109,7 +109,7 @@
|
||||
a = top();
|
||||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
meta->env.lexicalWrite(meta, mn, a, true, phase);
|
||||
meta->env->lexicalWrite(meta, mn, a, true, phase);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -118,7 +118,7 @@
|
||||
{
|
||||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
a = meta->env.lexicalRead(meta, mn, phase);
|
||||
a = meta->env->lexicalRead(meta, mn, phase);
|
||||
push(JS2VAL_NULL);
|
||||
push(a);
|
||||
}
|
||||
@ -221,7 +221,7 @@
|
||||
{
|
||||
uint16 slotIndex = BytecodeContainer::getShort(pc);
|
||||
pc += sizeof(short);
|
||||
Frame *f = meta->env.getTopFrame();
|
||||
Frame *f = meta->env->getTopFrame();
|
||||
a = pop();
|
||||
(*f->temps)[slotIndex] = a;
|
||||
}
|
||||
@ -231,7 +231,7 @@
|
||||
{
|
||||
uint16 slotIndex = BytecodeContainer::getShort(pc);
|
||||
pc += sizeof(short);
|
||||
Frame *f = meta->env.getTopFrame();
|
||||
Frame *f = meta->env->getTopFrame();
|
||||
push((*f->temps)[slotIndex]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -834,23 +834,23 @@
|
||||
{
|
||||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
a = meta->env.lexicalRead(meta, mn, phase);
|
||||
a = meta->env->lexicalRead(meta, mn, phase);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 i = *JS2VAL_TO_LONG(a);
|
||||
JSLL_ADD(i, i, 1);
|
||||
meta->env.lexicalWrite(meta, mn, allocLong(i), true, phase);
|
||||
meta->env->lexicalWrite(meta, mn, allocLong(i), true, phase);
|
||||
push(a);
|
||||
}
|
||||
else {
|
||||
if (JS2VAL_IS_ULONG(a)) {
|
||||
uint64 i = *JS2VAL_TO_ULONG(a);
|
||||
JSLL_ADD(i, i, 1);
|
||||
meta->env.lexicalWrite(meta, mn, allocULong(i), true, phase);
|
||||
meta->env->lexicalWrite(meta, mn, allocULong(i), true, phase);
|
||||
push(a);
|
||||
}
|
||||
else {
|
||||
float64 num = meta->toFloat64(a);
|
||||
meta->env.lexicalWrite(meta, mn, allocNumber(num + 1.0), true, phase);
|
||||
meta->env->lexicalWrite(meta, mn, allocNumber(num + 1.0), true, phase);
|
||||
pushNumber(num);
|
||||
}
|
||||
}
|
||||
@ -860,9 +860,9 @@
|
||||
{
|
||||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
a = meta->env.lexicalRead(meta, mn, phase);
|
||||
a = meta->env->lexicalRead(meta, mn, phase);
|
||||
float64 num = meta->toFloat64(a);
|
||||
meta->env.lexicalWrite(meta, mn, allocNumber(num - 1.0), true, phase);
|
||||
meta->env->lexicalWrite(meta, mn, allocNumber(num - 1.0), true, phase);
|
||||
pushNumber(num);
|
||||
}
|
||||
break;
|
||||
@ -870,20 +870,20 @@
|
||||
{
|
||||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
a = meta->env.lexicalRead(meta, mn, phase);
|
||||
a = meta->env->lexicalRead(meta, mn, phase);
|
||||
float64 num = meta->toFloat64(a);
|
||||
a = pushNumber(num + 1.0);
|
||||
meta->env.lexicalWrite(meta, mn, a, true, phase);
|
||||
meta->env->lexicalWrite(meta, mn, a, true, phase);
|
||||
}
|
||||
break;
|
||||
case eLexicalPreDec:
|
||||
{
|
||||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
a = meta->env.lexicalRead(meta, mn, phase);
|
||||
a = meta->env->lexicalRead(meta, mn, phase);
|
||||
float64 num = meta->toFloat64(a);
|
||||
a = pushNumber(num - 1.0);
|
||||
meta->env.lexicalWrite(meta, mn, a, true, phase);
|
||||
meta->env->lexicalWrite(meta, mn, a, true, phase);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@ -72,17 +72,17 @@
|
||||
}
|
||||
|
||||
ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame);
|
||||
runtimeFrame->instantiate(&meta->env);
|
||||
runtimeFrame->instantiate(meta->env);
|
||||
PrototypeInstance *pInst = new PrototypeInstance(protoObj, meta->objectClass);
|
||||
baseVal = OBJECT_TO_JS2VAL(pInst);
|
||||
runtimeFrame->thisObject = baseVal;
|
||||
// assignArguments(runtimeFrame, fWrap->compileFrame->signature);
|
||||
if (!fWrap->code)
|
||||
jsr(phase, fWrap->bCon, base(argCount + 1), baseVal); // seems out of order, but we need to catch the current top frame
|
||||
meta->env.addFrame(runtimeFrame);
|
||||
meta->env->addFrame(runtimeFrame);
|
||||
if (fWrap->code) { // native code, pass pointer to argument base
|
||||
a = fWrap->code(meta, a, base(argCount), argCount);
|
||||
meta->env.removeTopFrame();
|
||||
meta->env->removeTopFrame();
|
||||
pop(argCount + 1);
|
||||
push(a);
|
||||
}
|
||||
@ -114,23 +114,23 @@
|
||||
a = JS2VAL_VOID;
|
||||
else {
|
||||
if (JS2VAL_IS_INACCESSIBLE(compileThis)) {
|
||||
Frame *g = meta->env.getPackageOrGlobalFrame();
|
||||
Frame *g = meta->env->getPackageOrGlobalFrame();
|
||||
if (fWrap->compileFrame->prototype && (JS2VAL_IS_NULL(a) || JS2VAL_IS_VOID(a)) && (g->kind == GlobalObjectKind))
|
||||
a = OBJECT_TO_JS2VAL(g);
|
||||
}
|
||||
}
|
||||
ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame);
|
||||
runtimeFrame->instantiate(&meta->env);
|
||||
runtimeFrame->instantiate(meta->env);
|
||||
runtimeFrame->thisObject = a;
|
||||
// assignArguments(runtimeFrame, fWrap->compileFrame->signature);
|
||||
// XXX
|
||||
runtimeFrame->assignArguments(base(argCount), argCount);
|
||||
if (!fWrap->code)
|
||||
jsr(phase, fWrap->bCon, base(argCount + 2), JS2VAL_VOID); // seems out of order, but we need to catch the current top frame
|
||||
meta->env.addFrame(runtimeFrame);
|
||||
meta->env->addFrame(runtimeFrame);
|
||||
if (fWrap->code) { // native code, pass pointer to argument base
|
||||
a = fWrap->code(meta, a, base(argCount), argCount);
|
||||
meta->env.removeTopFrame();
|
||||
meta->env->removeTopFrame();
|
||||
pop(argCount + 2);
|
||||
push(a);
|
||||
}
|
||||
@ -141,17 +141,17 @@
|
||||
CallableInstance *fInst = mc->method->fInst;
|
||||
FunctionWrapper *fWrap = fInst->fWrap;
|
||||
ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame);
|
||||
runtimeFrame->instantiate(&meta->env);
|
||||
runtimeFrame->instantiate(meta->env);
|
||||
runtimeFrame->thisObject = mc->thisObject;
|
||||
// assignArguments(runtimeFrame, fWrap->compileFrame->signature);
|
||||
if (!fWrap->code)
|
||||
jsr(phase, fWrap->bCon, base(argCount + 2), JS2VAL_VOID); // seems out of order, but we need to catch the current top frame
|
||||
meta->env.addFrame(meta->objectType(mc->thisObject));
|
||||
meta->env.addFrame(runtimeFrame);
|
||||
meta->env->addFrame(meta->objectType(mc->thisObject));
|
||||
meta->env->addFrame(runtimeFrame);
|
||||
if (fWrap->code) {
|
||||
a = fWrap->code(meta, mc->thisObject, base(argCount), argCount);
|
||||
meta->env.removeTopFrame();
|
||||
meta->env.removeTopFrame();
|
||||
meta->env->removeTopFrame();
|
||||
meta->env->removeTopFrame();
|
||||
pop(argCount + 2);
|
||||
push(a);
|
||||
}
|
||||
@ -190,14 +190,14 @@
|
||||
{
|
||||
Frame *f = bCon->mFrameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
meta->env.addFrame(f);
|
||||
f->instantiate(&meta->env);
|
||||
meta->env->addFrame(f);
|
||||
f->instantiate(meta->env);
|
||||
}
|
||||
break;
|
||||
|
||||
case ePopFrame:
|
||||
{
|
||||
meta->env.removeTopFrame();
|
||||
meta->env->removeTopFrame();
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
|
||||
case eThis: // XXX literal?
|
||||
{
|
||||
a = meta->env.findThis(true);
|
||||
a = meta->env->findThis(true);
|
||||
if (JS2VAL_IS_INACCESSIBLE(a))
|
||||
meta->reportError(Exception::compileExpressionError, "'this' not available", errorPos());
|
||||
push(a);
|
||||
|
||||
@ -67,7 +67,6 @@
|
||||
|
||||
/* Type tag bitfield length and derived macros. */
|
||||
#define JS2VAL_TAGBITS 4
|
||||
#define JS2VAL_UNNUMBER_MASK JS2_BIT(3)
|
||||
#define JS2VAL_TAGMASK JS2_BITMASK(JS2VAL_TAGBITS)
|
||||
#define JS2VAL_TAG(v) ((v) & JS2VAL_TAGMASK)
|
||||
#define JS2VAL_SETTAG(v,t) ((v) | (t))
|
||||
@ -89,7 +88,8 @@
|
||||
|
||||
/* Predicates for type testing. */
|
||||
#define JS2VAL_IS_OBJECT(v) ((JS2VAL_TAG(v) == JS2VAL_OBJECT) && !JS2VAL_IS_SPECIALREF(v))
|
||||
#define JS2VAL_IS_NUMBER(v) ((JS2VAL_TAG(v) != JS2VAL_OBJECT) && !(JS2VAL_TAG(v) & JS2VAL_UNNUMBER_MASK))
|
||||
// XXX think about some way of making this faster...
|
||||
#define JS2VAL_IS_NUMBER(v) (JS2VAL_IS_INT(v) || JS2VAL_IS_DOUBLE(v) || JS2VAL_IS_LONG(v) || JS2VAL_IS_ULONG(v) || JS2VAL_IS_FLOAT(v))
|
||||
#define JS2VAL_IS_INT(v) (((v) & JS2VAL_INT) && (v) != JS2VAL_VOID)
|
||||
#define JS2VAL_IS_DOUBLE(v) (JS2VAL_TAG(v) == JS2VAL_DOUBLE)
|
||||
#define JS2VAL_IS_STRING(v) (JS2VAL_TAG(v) == JS2VAL_STRING)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user