This commit is contained in:
rogerl%netscape.com 2002-08-30 00:14:03 +00:00
Родитель d8b0565933
Коммит 31f1a64820
8 изменённых файлов: 161 добавлений и 66 удалений

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

@ -49,6 +49,7 @@ namespace MetaData {
class Multiname;
class Frame;
class BytecodeContainer {
public:
@ -85,8 +86,10 @@ public:
static uint16 getShort(void *pc) { return *((uint16 *)pc); }
void addMultiname(Multiname *mn) { mMultinameList.push_back(mn); addShort(mMultinameList.size() - 1); }
static Multiname *getMultiname(void *pc){ return (Multiname *)getLong(pc); }
void addFrame(Frame *f) { mFrameList.push_back(f); addShort(mFrameList.size() - 1); }
void addString(const StringAtom &x, size_t pos) { emitOp(eString, pos); addPointer(&x); }
void addString(String &x, size_t pos) { emitOp(eString, pos); addPointer(&x); }
void addString(String *x, size_t pos) { emitOp(eString, pos); addPointer(x); }
@ -97,6 +100,7 @@ public:
CodeBuffer mBuffer;
std::vector<Multiname *> mMultinameList; // gc tracking
std::vector<Frame *> mFrameList; // gc tracking
int32 mStackTop; // keep these as signed so as to
int32 mStackMax; // track if they go negative.

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

@ -147,7 +147,7 @@ static int readEvalPrint(FILE *in)
metadata->setCurrentParser(&p); // for error reporting
metadata->ValidateStmtList(parsedStatements);
js2val rval = metadata->EvalStmtList(RunPhase, parsedStatements);
js2val rval = metadata->ExecuteStmtList(RunPhase, parsedStatements);
if (!JS2VAL_IS_VOID(rval))
stdOut << *metadata->engine->toString(rval) << '\n';
}

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

@ -209,6 +209,7 @@ JS2Engine::JS2Engine(World &world)
INIT_STRINGATOM(null),
INIT_STRINGATOM(undefined),
INIT_STRINGATOM(public),
INIT_STRINGATOM(private),
INIT_STRINGATOM(object)
{
nanValue = (float64 *)gc_alloc_8();
@ -245,8 +246,9 @@ int JS2Engine::getStackEffect(JS2Op op)
case eMultiname:
return 1; // push the multiname object
case eUse:
return -1; // consume a namespace object
case ePushFrame:
case ePopFrame:
return 0;
default:
ASSERT(false);

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

@ -61,7 +61,8 @@ enum JS2Op {
eReturnVoid,
eNewObject, // <argCount:16>
eMultiname, // <multiname index>
eUse,
ePushFrame, // <frame index>
ePopFrame
};
@ -111,6 +112,7 @@ public:
StringAtom &null_StringAtom;
StringAtom &undefined_StringAtom;
StringAtom &public_StringAtom;
StringAtom &private_StringAtom;
StringAtom &object_StringAtom;
js2val *execStack;

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

@ -71,8 +71,6 @@ namespace MetaData {
* Validate the linked list of statement nodes beginning at 'p'
*/
void JS2Metadata::ValidateStmtList(StmtNode *p) {
cxt.openNamespaces.clear();
cxt.openNamespaces.push_back(publicNamespace);
while (p) {
ValidateStmt(&cxt, &env, p);
p = p->next;
@ -192,14 +190,67 @@ namespace MetaData {
}
}
break;
case StmtNode::Class:
{
ClassStmtNode *classStmt = checked_cast<ClassStmtNode *>(p);
JS2Class *superClass = objectClass;
if (classStmt->superclass) {
ValidateExpression(cxt, env, classStmt->superclass);
js2val av = EvalExpression(env, CompilePhase, classStmt->superclass);
if (JS2VAL_IS_NULL(av) || !JS2VAL_IS_OBJECT(av))
reportError(Exception::badValueError, "Class expected in inheritance", p->pos);
JS2Object *obj = JS2VAL_TO_OBJECT(av);
if (obj->kind != ClassKind)
reportError(Exception::badValueError, "Class expected in inheritance", p->pos);
superClass = checked_cast<JS2Class *>(obj);
}
Attribute *attr = NULL;
if (classStmt->attributes) {
ValidateAttributeExpression(cxt, env, classStmt->attributes);
attr = EvalAttributeExpression(env, CompilePhase, classStmt->attributes);
}
CompoundAttribute *a = Attribute::toCompoundAttribute(attr);
if (!superClass->complete || superClass->final)
reportError(Exception::definitionError, "Illegal inheritance", p->pos);
JS2Object *proto = NULL;
bool final;
switch (a->memberMod) {
case Attribute::NoModifier:
final = false;
break;
case Attribute::Static:
if (env->getTopFrame()->kind != ClassKind)
reportError(Exception::definitionError, "Illegal use of static modifier", p->pos);
final = false;
break;
case Attribute::Final:
final = true;
break;
default:
reportError(Exception::definitionError, "Illegal modifier for class definition", p->pos);
break;
}
JS2Class *c = new JS2Class(superClass, proto, new Namespace(engine->public_StringAtom), (a->dynamic || superClass->dynamic), final);
classStmt->c = c;
Variable *v = new Variable(classClass, OBJECT_TO_JS2VAL(c), true);
defineStaticMember(env, classStmt->name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos);
if (classStmt->body) {
env->addFrame(c);
ValidateStmtList(cxt, env, classStmt->body->statements);
ASSERT(env->getTopFrame() == c);
env->removeTopFrame();
}
c->complete = true;
}
} // switch (p->getKind())
}
/*
* Evaluate the linked list of statement nodes beginning at 'p' (generate bytecode)
* and then execute that bytecode
* Evaluate the linked list of statement nodes beginning at 'p'
* (generate bytecode and then execute that bytecode
*/
js2val JS2Metadata::EvalStmtList(Phase phase, StmtNode *p)
js2val JS2Metadata::ExecuteStmtList(Phase phase, StmtNode *p)
{
BytecodeContainer *saveBacon = bCon;
bCon = new BytecodeContainer();
@ -267,6 +318,25 @@ namespace MetaData {
{
}
break;
case StmtNode::Class:
{
ClassStmtNode *classStmt = checked_cast<ClassStmtNode *>(p);
JS2Class *c = classStmt->c;
if (classStmt->body) {
env->addFrame(c);
bCon->emitOp(ePushFrame, p->pos);
bCon->addFrame(c);
StmtNode *bp = classStmt->body->statements;
while (bp) {
EvalStmt(env, phase, bp);
bp = bp->next;
}
ASSERT(env->getTopFrame() == c);
env->removeTopFrame();
bCon->emitOp(ePopFrame, p->pos);
}
}
break;
default:
NOT_REACHED("Not Yet Implemented");
} // switch (p->getKind())
@ -970,6 +1040,8 @@ namespace MetaData {
glob(world),
env(new MetaData::SystemFrame(), &glob)
{
cxt.openNamespaces.clear();
cxt.openNamespaces.push_back(publicNamespace);
}
// objectType(o) returns an OBJECT o's most specific type.
@ -1365,6 +1437,27 @@ namespace MetaData {
nextPond->moveUnmarkedToFreeList();
}
/************************************************************************************
*
* JS2Class
*
************************************************************************************/
JS2Class::JS2Class(JS2Class *super, JS2Object *proto, Namespace *privateNamespace, bool dynamic, bool final)
: Frame(ClassKind),
instanceInitOrder(NULL),
complete(false),
super(super),
prototype(proto),
privateNamespace(privateNamespace),
dynamic(dynamic),
primitive(false),
final(final),
call(NULL),
construct(NULL)
{ }
/************************************************************************************
*
* JS2Object

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

@ -353,7 +353,7 @@ public:
class JS2Class : public Frame {
public:
JS2Class() : Frame(ClassKind) { }
JS2Class(JS2Class *super, JS2Object *proto, Namespace *privateNamespace, bool dynamic, bool final);
StringAtom &getName();
@ -559,6 +559,9 @@ public:
Frame *getTopFrame() { return firstFrame; }
Frame *getPackageOrGlobalFrame();
void addFrame(Frame *f) { f->nextFrame = firstFrame; firstFrame = f; }
void removeTopFrame() { firstFrame = firstFrame->nextFrame; }
js2val findThis(bool allowPrototypeThis);
js2val lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase);
void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase);
@ -629,7 +632,7 @@ public:
void ValidateExpression(Context *cxt, Environment *env, ExprNode *p);
void ValidateAttributeExpression(Context *cxt, Environment *env, ExprNode *p);
js2val EvalStmtList(Environment *env, Phase phase, StmtNode *p);
js2val ExecuteStmtList(Phase phase, StmtNode *p);
js2val EvalExpression(Environment *env, Phase phase, ExprNode *p);
Reference *EvalExprNode(Environment *env, Phase phase, ExprNode *p);
Attribute *EvalAttributeExpression(Environment *env, Phase phase, ExprNode *p);
@ -680,6 +683,7 @@ public:
JS2Class *stringClass;
JS2Class *objectClass;
JS2Class *namespaceClass;
JS2Class *classClass;
Parser *mParser; // used for error reporting

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

@ -33,62 +33,49 @@
// Get a multiname literal and add the currently open namespaces from the context
// Push the resulting multiname object
case eMultiname: {
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
mn->addNamespace(meta->cxt);
push(OBJECT_TO_JS2VAL(mn));
}
break;
#if 0
// Get a multiname literal and pop a namespace value to add to it
// Push the resulting multiname object
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(checked_cast<Namespace *>(obj));
push(OBJECT_TO_JS2VAL(mn));
}
break;
#endif
case eMultiname:
{
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
mn->addNamespace(meta->cxt);
push(OBJECT_TO_JS2VAL(mn));
}
break;
// Pop a multiname object and read it's value from the environment on to the stack.
case eLexicalRead: {
js2val mnVal = pop();
ASSERT(JS2VAL_IS_OBJECT(mnVal));
JS2Object *obj = JS2VAL_TO_OBJECT(mnVal);
Multiname *mn = checked_cast<Multiname *>(obj);
retval = meta->env.lexicalRead(meta, mn, phase);
push(retval);
}
break;
case eLexicalRead:
{
js2val mnVal = pop();
ASSERT(JS2VAL_IS_OBJECT(mnVal));
JS2Object *obj = JS2VAL_TO_OBJECT(mnVal);
Multiname *mn = checked_cast<Multiname *>(obj);
retval = meta->env.lexicalRead(meta, mn, phase);
push(retval);
}
break;
// Pop a value and a multiname. Write the value to the multiname in the environment, leave
// the value on the stack top.
case eLexicalWrite: {
retval = pop();
js2val mnVal = pop();
ASSERT(JS2VAL_IS_OBJECT(mnVal));
JS2Object *obj = JS2VAL_TO_OBJECT(mnVal);
Multiname *mn = checked_cast<Multiname *>(obj);
meta->env.lexicalWrite(meta, mn, retval, true, phase);
push(retval);
}
break;
case eLexicalWrite:
{
retval = pop();
js2val mnVal = pop();
ASSERT(JS2VAL_IS_OBJECT(mnVal));
JS2Object *obj = JS2VAL_TO_OBJECT(mnVal);
Multiname *mn = checked_cast<Multiname *>(obj);
meta->env.lexicalWrite(meta, mn, retval, true, phase);
push(retval);
}
break;
// Pop a namespace object and add it to the list of currently open namespaces in the context
case eUse: {
js2val nsVal = pop();
if (!JS2VAL_IS_OBJECT(nsVal))
meta->reportError(Exception::badValueError, "Expected a namespace", meta->engine->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->engine->errorPos());
case ePushFrame:
{
Frame *f = bCon->mFrameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
}
break;
}
break;
case ePopFrame:
{
}
break;

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

@ -59,6 +59,7 @@ namespace JavaScript {
#ifdef EPIMETHEUS
namespace MetaData {
class Context;
class JS2Class;
}
#endif
@ -678,7 +679,9 @@ namespace JavaScript {
#ifdef DIKDIK
JS2Runtime::JSType *mType; // used by backend
#endif
#ifdef EPIMETHEUS
MetaData::JS2Class *c;
#endif
ClassStmtNode(size_t pos, ExprNode *attributes, const StringAtom &name, ExprNode *superclass, BlockStmtNode *body):
NamespaceStmtNode(pos, Class, attributes, name), superclass(superclass), body(body) {}