Changed ArgumentList to ArgumentList*. Changed ICodeGenerator to take a
Context instead of world & global pair. Connected to ICodeAssembler from XMLParser. git-svn-id: svn://10.0.0.236/trunk@81552 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
8f3b350acd
commit
289f607a92
@ -153,18 +153,18 @@
|
||||
/* print() and printOperands() inherited from GenericBranch */
|
||||
};
|
||||
|
||||
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList> {
|
||||
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList*> {
|
||||
public:
|
||||
/* result, target, this, args */
|
||||
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, ArgumentList aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList>
|
||||
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, ArgumentList* aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList*>
|
||||
(CALL, aOp1, aOp2, aOp3, aOp4) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first) << ", " << ArgList(mOp4, registers);
|
||||
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first);
|
||||
return f;
|
||||
}
|
||||
};
|
||||
@ -328,18 +328,18 @@
|
||||
}
|
||||
};
|
||||
|
||||
class DirectCall : public Instruction_3<TypedRegister, JSFunction*, ArgumentList> {
|
||||
class DirectCall : public Instruction_3<TypedRegister, JSFunction*, ArgumentList*> {
|
||||
public:
|
||||
/* result, target, args */
|
||||
DirectCall (TypedRegister aOp1, JSFunction* aOp2, ArgumentList aOp3) :
|
||||
Instruction_3<TypedRegister, JSFunction*, ArgumentList>
|
||||
DirectCall (TypedRegister aOp1, JSFunction* aOp2, ArgumentList* aOp3) :
|
||||
Instruction_3<TypedRegister, JSFunction*, ArgumentList*>
|
||||
(DIRECT_CALL, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[DIRECT_CALL] << "\t" << mOp1 << ", " << "JSFunction" << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << getRegisterValue(registers, mOp1.first) << ", " << ArgList(mOp3, registers);
|
||||
f << getRegisterValue(registers, mOp1.first);
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
@ -31,6 +31,12 @@
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef _WIN32 // Microsoft Visual C++ 6.0 whines about name lengths over 255 getting truncated in the browser database
|
||||
#pragma warning( disable : 4786)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __icodeasm_h
|
||||
|
||||
#define __icodeasm_h
|
||||
|
||||
@ -73,20 +73,19 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
|
||||
//
|
||||
|
||||
|
||||
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags)
|
||||
ICodeGenerator::ICodeGenerator(Context *cx, JSClass *aClass, ICodeGeneratorFlags flags)
|
||||
: mTopRegister(0),
|
||||
mParameterCount(0),
|
||||
mExceptionRegister(TypedRegister(NotARegister, &None_Type)),
|
||||
variableList(new VariableList()),
|
||||
mWorld(world),
|
||||
mGlobal(global),
|
||||
mContext(cx),
|
||||
mInstructionMap(new InstructionMap()),
|
||||
mClass(aClass),
|
||||
mFlags(flags),
|
||||
pLabels(NULL),
|
||||
mHasRestParameter(false),
|
||||
mHasNamedRestParameter(false),
|
||||
mInitName(world->identifiers["__init__"])
|
||||
mInitName(cx->getWorld().identifiers["__init__"])
|
||||
{
|
||||
iCode = new InstructionStream();
|
||||
iCodeOwner = true;
|
||||
@ -94,12 +93,22 @@ ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, I
|
||||
|
||||
JSType *ICodeGenerator::findType(const StringAtom& typeName)
|
||||
{
|
||||
const JSValue& type = mGlobal->getVariable(typeName);
|
||||
const JSValue& type = mContext->getGlobalObject()->getVariable(typeName);
|
||||
if (type.isType())
|
||||
return type.type;
|
||||
return &Any_Type;
|
||||
}
|
||||
|
||||
/*
|
||||
-Called to allocate parameter and variable registers, aka 'permanent' registers.
|
||||
-mTopRegister is the current high-water mark.
|
||||
-mPermanentRegister marks those registers given to variables/parameters.
|
||||
-Theoretically, mPermanentRegister[n] can be become false when a scope ends and
|
||||
the registers allocated to contained variables are then available for re-use.
|
||||
-Mostly the need is to handle overlapping allocation of temps & permanents as the
|
||||
variables declarations are encountered. This wouldn't be necessary if a function
|
||||
presented a list of all variables, or a pre-pass executed to discover same.
|
||||
*/
|
||||
TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *type)
|
||||
{
|
||||
Register r = mTopRegister;
|
||||
@ -121,25 +130,16 @@ TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *t
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
|
||||
{
|
||||
if (mExceptionRegister.first == NotARegister) {
|
||||
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
|
||||
}
|
||||
return allocateRegister(name, findType(typeName));
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
|
||||
{
|
||||
if (mExceptionRegister.first == NotARegister) {
|
||||
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
|
||||
}
|
||||
return allocateRegister(name, &Any_Type);
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, JSType *type)
|
||||
{
|
||||
if (mExceptionRegister.first == NotARegister) {
|
||||
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
|
||||
}
|
||||
return allocateRegister(name, type);
|
||||
}
|
||||
|
||||
@ -493,7 +493,7 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1,
|
||||
TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg, ArgumentList *args)
|
||||
{
|
||||
TypedRegister dest(getTempRegister(), &Any_Type);
|
||||
Call *instr = new Call(dest, target, thisArg, *args);
|
||||
Call *instr = new Call(dest, target, thisArg, args);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
@ -501,7 +501,7 @@ TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg,
|
||||
TypedRegister ICodeGenerator::directCall(JSFunction *target, ArgumentList *args)
|
||||
{
|
||||
TypedRegister dest(getTempRegister(), &Any_Type);
|
||||
DirectCall *instr = new DirectCall(dest, target, *args);
|
||||
DirectCall *instr = new DirectCall(dest, target, args);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
@ -757,7 +757,7 @@ ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &n
|
||||
return (isConstructor) ? Constructor : Static;
|
||||
}
|
||||
}
|
||||
v.second = mGlobal->getType(name);
|
||||
v.second = mContext->getGlobalObject()->getType(name);
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
@ -946,7 +946,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
|
||||
// handle <class name>.<static field>
|
||||
//
|
||||
if (base.second == &Type_Type) {
|
||||
const JSValue &v = mGlobal->getVariable(baseName);
|
||||
const JSValue &v = mContext->getGlobalObject()->getVariable(baseName);
|
||||
bool isConstructor;
|
||||
ASSERT(v.isType()); // there's no other way that base.second could be &Type_Type, right?
|
||||
clazz = dynamic_cast<JSClass*>(v.type);
|
||||
@ -1154,23 +1154,23 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::New:
|
||||
{
|
||||
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
|
||||
ArgumentList args;
|
||||
ArgumentList *args = new ArgumentList();
|
||||
ExprPairList *p = i->pairs;
|
||||
while (p) {
|
||||
if (p->field && (p->field->getKind() == ExprNode::identifier))
|
||||
args.push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
|
||||
args->push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
|
||||
else
|
||||
args.push_back(Argument(genExpr(p->value), NULL ));
|
||||
args->push_back(Argument(genExpr(p->value), NULL ));
|
||||
p = p->next;
|
||||
}
|
||||
if (i->op->getKind() == ExprNode::identifier) {
|
||||
const StringAtom &className = static_cast<IdentifierExprNode *>(i->op)->name;
|
||||
const JSValue& value = mGlobal->getVariable(className);
|
||||
const JSValue& value = mContext->getGlobalObject()->getVariable(className);
|
||||
if (value.isType()) {
|
||||
JSClass* clazz = dynamic_cast<JSClass*>(value.type);
|
||||
if (clazz) {
|
||||
ret = newClass(clazz);
|
||||
ret = call(getStatic(clazz, className), ret, &args);
|
||||
ret = call(getStatic(clazz, className), ret, args);
|
||||
}
|
||||
else {
|
||||
//
|
||||
@ -1178,7 +1178,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
//
|
||||
JSFunction *f = value.type->getConstructor();
|
||||
if (f)
|
||||
ret = directCall(f, &args);
|
||||
ret = directCall(f, args);
|
||||
else
|
||||
NOT_REACHED("new <name>, where <name> is not a new-able type (whatever that means)"); // XXX Runtime error.
|
||||
}
|
||||
@ -1187,7 +1187,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (value.isFunction()) {
|
||||
TypedRegister f = loadName(className, value.type);
|
||||
ret = newObject(f);
|
||||
ret = call(f, ret, &args);
|
||||
ret = call(f, ret, args);
|
||||
}
|
||||
else
|
||||
NOT_REACHED("new <name>, where <name> is not a function"); // XXX Runtime error.
|
||||
@ -1207,23 +1207,23 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::call :
|
||||
{
|
||||
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
|
||||
ArgumentList args;
|
||||
ArgumentList *args = new ArgumentList();
|
||||
ExprPairList *p = i->pairs;
|
||||
uint32 count = 0;
|
||||
StringFormatter s;
|
||||
while (p) {
|
||||
if (p->field && (p->field->getKind() == ExprNode::identifier))
|
||||
args.push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
|
||||
args->push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
|
||||
else
|
||||
if (p->field && (p->field->getKind() == ExprNode::string))
|
||||
args.push_back(Argument(genExpr(p->value), &mWorld->identifiers[(static_cast<StringExprNode *>(p->field))->str]));
|
||||
args->push_back(Argument(genExpr(p->value), &mContext->getWorld().identifiers[(static_cast<StringExprNode *>(p->field))->str]));
|
||||
else {
|
||||
/* do this for new argument style to provide default 'positional' name
|
||||
s << count;
|
||||
args.push_back(Argument(genExpr(p->value), &mWorld->identifiers[s] ));
|
||||
args->push_back(Argument(genExpr(p->value), &mContext->getWorld().identifiers[s] ));
|
||||
s.clear();
|
||||
*/
|
||||
args.push_back(Argument(genExpr(p->value), NULL ));
|
||||
args->push_back(Argument(genExpr(p->value), NULL ));
|
||||
}
|
||||
count++;
|
||||
p = p->next;
|
||||
@ -1231,17 +1231,17 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
|
||||
if (i->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
|
||||
ret = handleDot(b, ExprNode::call, xcrementOp, ret, &args, false);
|
||||
ret = handleDot(b, ExprNode::call, xcrementOp, ret, args, false);
|
||||
}
|
||||
else
|
||||
if (i->op->getKind() == ExprNode::identifier) {
|
||||
ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, ret, &args, false);
|
||||
ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, ret, args, false);
|
||||
}
|
||||
else
|
||||
if (i->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = call(getElement(base, genExpr(b->op2)), base, &args);
|
||||
ret = call(getElement(base, genExpr(b->op2)), base, args);
|
||||
}
|
||||
else
|
||||
ASSERT("WAH!");
|
||||
@ -1279,7 +1279,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
ret = loadImmediate((static_cast<NumberExprNode *>(p))->value);
|
||||
break;
|
||||
case ExprNode::string :
|
||||
ret = loadString(mWorld->identifiers[(static_cast<StringExprNode *>(p))->str]);
|
||||
ret = loadString(mContext->getWorld().identifiers[(static_cast<StringExprNode *>(p))->str]);
|
||||
break;
|
||||
case ExprNode::preDecrement:
|
||||
xcrementOp = SUBTRACT;
|
||||
@ -1564,8 +1564,8 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::functionLiteral:
|
||||
{
|
||||
FunctionExprNode *f = static_cast<FunctionExprNode *>(p);
|
||||
ICodeGenerator icg(mWorld, mGlobal);
|
||||
icg.allocateParameter(mWorld->identifiers["this"]); // always parameter #0
|
||||
ICodeGenerator icg(mContext);
|
||||
icg.allocateParameter(mContext->getWorld().identifiers["this"]); // always parameter #0
|
||||
VariableBinding *v = f->function.parameters;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
@ -1590,7 +1590,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
const StringAtom &name = (static_cast<IdentifierExprNode *>(b->op2))->name;
|
||||
/*LValueKind lvk = resolveIdentifier(name, t, slotIndex);*/
|
||||
ASSERT(t.second == &Type_Type);
|
||||
const JSValue &v = mGlobal->getVariable(name);
|
||||
const JSValue &v = mContext->getGlobalObject()->getVariable(name);
|
||||
ASSERT(v.isType());
|
||||
JSClass *clazz = dynamic_cast<JSClass*>(v.type);
|
||||
if (clazz)
|
||||
@ -1648,8 +1648,8 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
|
||||
bool isStatic = hasAttribute(f->attributes, Token::Static);
|
||||
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
|
||||
|
||||
ICodeGenerator icg(mWorld, mGlobal, mClass, flags);
|
||||
icg.allocateParameter(mWorld->identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
|
||||
ICodeGenerator icg(mContext, mClass, flags);
|
||||
icg.allocateParameter(mContext->getWorld().identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
|
||||
VariableBinding *v = f->function.parameters;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
|
||||
@ -1703,7 +1703,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
|
||||
superclass constructor ourselves.
|
||||
*/
|
||||
TypedRegister thisValue = TypedRegister(0, mClass);
|
||||
ArgumentList args;
|
||||
ArgumentList *args = new ArgumentList();
|
||||
if (superclass) {
|
||||
bool foundSuperCall = false;
|
||||
BlockStmtNode *b = f->function.body;
|
||||
@ -1724,11 +1724,11 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
|
||||
}
|
||||
}
|
||||
if (!foundSuperCall) { // invoke the default superclass constructor
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
|
||||
}
|
||||
}
|
||||
if (mClass->hasStatic(mInitName))
|
||||
icg.call(icg.getStatic(mClass, mInitName), thisValue, &args); // ok, so it's mis-named
|
||||
icg.call(icg.getStatic(mClass, mInitName), thisValue, args); // ok, so it's mis-named
|
||||
|
||||
}
|
||||
if (f->function.body)
|
||||
@ -1745,9 +1745,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
|
||||
startStatement(p->pos);
|
||||
if (mExceptionRegister.first == NotARegister) {
|
||||
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
|
||||
}
|
||||
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::Class:
|
||||
@ -1760,14 +1757,14 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
if (classStmt->superclass) {
|
||||
ASSERT(classStmt->superclass->getKind() == ExprNode::identifier);
|
||||
IdentifierExprNode* superclassExpr = static_cast<IdentifierExprNode*>(classStmt->superclass);
|
||||
const JSValue& superclassValue = mGlobal->getVariable(superclassExpr->name);
|
||||
const JSValue& superclassValue = mContext->getGlobalObject()->getVariable(superclassExpr->name);
|
||||
ASSERT(superclassValue.isObject() && !superclassValue.isNull());
|
||||
superclass = static_cast<JSClass*>(superclassValue.object);
|
||||
}
|
||||
JSClass* thisClass = new JSClass(mGlobal, nameExpr->name, superclass);
|
||||
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), nameExpr->name, superclass);
|
||||
// is it ok for a partially defined class to appear in global scope? this is needed
|
||||
// to handle recursive types, such as linked list nodes.
|
||||
mGlobal->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
|
||||
mContext->getGlobalObject()->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
|
||||
|
||||
|
||||
/*
|
||||
@ -1849,14 +1846,15 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
if (classStmt->body) {
|
||||
JSScope* thisScope = thisClass->getScope();
|
||||
ICodeGenerator *ccg = NULL;
|
||||
Context *classContext = new Context(mContext->getWorld(), thisScope);
|
||||
if (needsInstanceInitializer) {
|
||||
// constructor code generator. Slot variable
|
||||
// initializers get added to this function.
|
||||
ccg = new ICodeGenerator(mWorld, thisScope, thisClass, kNoFlags);
|
||||
ccg->allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
|
||||
ccg = new ICodeGenerator(classContext, thisClass, kNoFlags);
|
||||
ccg->allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
|
||||
}
|
||||
|
||||
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod); // static initializer code generator.
|
||||
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod); // static initializer code generator.
|
||||
// static field inits, plus code to initialize
|
||||
// static method slots.
|
||||
StmtNode* s = classStmt->body->statements;
|
||||
@ -1895,7 +1893,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
bool isConstructor = (s->getKind() == StmtNode::Constructor);
|
||||
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
|
||||
|
||||
ICodeGenerator mcg(mWorld, thisScope, thisClass, flags); // method code generator.
|
||||
ICodeGenerator mcg(classContext, thisClass, flags); // method code generator.
|
||||
ICodeModule *icm = mcg.genFunction(f, isConstructor, superclass);
|
||||
if (f->function.name->getKind() == ExprNode::identifier) {
|
||||
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
|
||||
@ -1939,13 +1937,13 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
// initializer and the superclass default constructor
|
||||
if (!hasDefaultConstructor) {
|
||||
TypedRegister thisValue = TypedRegister(0, thisClass);
|
||||
ArgumentList args;
|
||||
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
|
||||
icg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
|
||||
ArgumentList *args = new ArgumentList();
|
||||
ICodeGenerator icg(classContext, thisClass, kIsStaticMethod);
|
||||
icg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
|
||||
if (superclass)
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
|
||||
if (thisClass->hasStatic(mInitName))
|
||||
icg.call(icg.getStatic(thisClass, mInitName), thisValue, &args);
|
||||
icg.call(icg.getStatic(thisClass, mInitName), thisValue, args);
|
||||
icg.returnStmt(thisValue);
|
||||
thisClass->defineConstructor(nameExpr->name);
|
||||
scg.setStatic(thisClass, nameExpr->name, scg.newFunction(icg.complete(&Void_Type)));
|
||||
@ -1956,11 +1954,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
|
||||
// REVISIT: using the scope of the class to store both methods and statics.
|
||||
if (scg.getICode()->size()) {
|
||||
Interpreter::Context cx(*mWorld, thisScope);
|
||||
ICodeModule* clinit = scg.complete(&Void_Type);
|
||||
cx.interpret(clinit, JSValues());
|
||||
classContext->interpret(clinit, JSValues());
|
||||
delete clinit;
|
||||
}
|
||||
delete classContext;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1974,8 +1972,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
switch (f->function.prefix) {
|
||||
case FunctionName::Get:
|
||||
if (isTopLevel()) {
|
||||
mGlobal->defineVariable(name, resultType);
|
||||
mGlobal->setGetter(name, new JSFunction(icm));
|
||||
mContext->getGlobalObject()->defineVariable(name, resultType);
|
||||
mContext->getGlobalObject()->setGetter(name, new JSFunction(icm));
|
||||
}
|
||||
else {
|
||||
// is this legal - a nested getter?
|
||||
@ -1985,8 +1983,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
break;
|
||||
case FunctionName::Set:
|
||||
if (isTopLevel()) {
|
||||
mGlobal->defineVariable(name, resultType);
|
||||
mGlobal->setSetter(name, new JSFunction(icm));
|
||||
mContext->getGlobalObject()->defineVariable(name, resultType);
|
||||
mContext->getGlobalObject()->setSetter(name, new JSFunction(icm));
|
||||
}
|
||||
else {
|
||||
// is this legal - a nested setter?
|
||||
@ -1995,7 +1993,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
}
|
||||
break;
|
||||
case FunctionName::normal:
|
||||
mGlobal->defineFunction(name, icm);
|
||||
mContext->getGlobalObject()->defineFunction(name, icm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2010,8 +2008,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
std::transform(fileName->begin(), fileName->end(), str.begin(), narrow);
|
||||
FILE* f = fopen(str.c_str(), "r");
|
||||
if (f) {
|
||||
Context cx(*mWorld, mGlobal);
|
||||
(void)cx.readEvalFile(f, *fileName);
|
||||
(void)mContext->readEvalFile(f, *fileName);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
@ -2025,7 +2022,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
|
||||
JSType *type = extractType(v->type);
|
||||
if (isTopLevel())
|
||||
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
|
||||
mContext->getGlobalObject()->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
|
||||
else
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
|
||||
if (v->initializer) {
|
||||
@ -2326,6 +2323,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
CatchClause *c = t->catches;
|
||||
while (c) {
|
||||
// Bind the incoming exception ...
|
||||
if (mExceptionRegister.first == NotABanana)
|
||||
mExceptionRegister = allocateRegister(mContext->getWorld().identifiers["__exceptionObject__"], &Any_Type);
|
||||
variableList->setRegisterForVariable(c->name, mExceptionRegister);
|
||||
|
||||
genStmt(c->stmt);
|
||||
@ -2412,17 +2411,18 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
|
||||
node->getValue(widenCString("name"), className);
|
||||
if (node->getValue(widenCString("super"), superName)) {
|
||||
const JSValue& superclassValue = mGlobal->getVariable(superName);
|
||||
const JSValue& superclassValue = mContext->getGlobalObject()->getVariable(superName);
|
||||
superclass = static_cast<JSClass*>(superclassValue.object);
|
||||
}
|
||||
JSClass* thisClass = new JSClass(mGlobal, className, superclass);
|
||||
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), className, superclass);
|
||||
JSScope* thisScope = thisClass->getScope();
|
||||
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod);
|
||||
ICodeGenerator ccg(mWorld, thisScope, thisClass, kNoFlags);
|
||||
ccg.allocateParameter(mWorld->identifiers["this"], thisClass);
|
||||
Context *classContext = new Context(mContext->getWorld(), thisScope);
|
||||
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod);
|
||||
ICodeGenerator ccg(classContext, thisClass, kNoFlags);
|
||||
ccg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass);
|
||||
thisClass->defineStatic(mInitName, &Function_Type);
|
||||
|
||||
mGlobal->defineVariable(className, &Type_Type, JSValue(thisClass));
|
||||
mContext->getGlobalObject()->defineVariable(className, &Type_Type, JSValue(thisClass));
|
||||
|
||||
bool hasDefaultConstructor = false;
|
||||
XMLNodeList &elements = node->children();
|
||||
@ -2432,31 +2432,44 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
if (element->name().compare(widenCString("method")) == 0) {
|
||||
String methodName, resultTypeName;
|
||||
element->getValue(widenCString("name"), methodName);
|
||||
element->getValue(widenCString("result"), resultTypeName);
|
||||
#ifdef ROB_DONE
|
||||
JSType *resultType = findType(mWorld->identifiers[resultTypeName]);
|
||||
element->getValue(widenCString("type"), resultTypeName);
|
||||
VariableList *theVariableList = new VariableList();
|
||||
theVariableList->add(mContext->getWorld().identifiers["this"], TypedRegister(0, thisClass));
|
||||
uint32 pCount = 1;
|
||||
XMLNodeList ¶meters = element->children();
|
||||
for (XMLNodeList::const_iterator k = parameters.begin(); k != parameters.end(); k++) {
|
||||
XMLNode *parameter = *k;
|
||||
if (parameter->name().compare(widenCString("parameter")) == 0) {
|
||||
String parameterName;
|
||||
String parameterTypeName;
|
||||
element->getValue(widenCString("name"), parameterName);
|
||||
element->getValue(widenCString("type"), parameterTypeName);
|
||||
JSType *parameterType = findType(mContext->getWorld().identifiers[parameterTypeName]);
|
||||
theVariableList->add(mContext->getWorld().identifiers[parameterName], TypedRegister(pCount++, parameterType));
|
||||
}
|
||||
}
|
||||
|
||||
JSType *resultType = findType(mContext->getWorld().identifiers[resultTypeName]);
|
||||
String &body = element->body();
|
||||
if (body.length()) {
|
||||
std::string str(body.length(), char());
|
||||
std::transform(body.begin(), body.end(), str.begin(), narrow);
|
||||
ICodeParser icp;
|
||||
ICodeParser icp(mContext);
|
||||
|
||||
stdOut << "Calling ICodeParser with :\n" << str << "\n";
|
||||
|
||||
icp.ParseSourceFromString(str);
|
||||
|
||||
ICodeModule *icm = new ICodeModule(icp.instructionStream(),
|
||||
NULL, /* VariableList *variables */
|
||||
icp.maxRegister,
|
||||
1, /* uint32 maxParameter, */
|
||||
NULL, /* InstructionMap *instructionMap */
|
||||
false, /* bool hasRestParameter, */
|
||||
false, /* bool hasNamedRestParameter */
|
||||
ICodeModule *icm = new ICodeModule(icp.mInstructions,
|
||||
theVariableList, /* VariableList *variables */
|
||||
icp.mMaxRegister,
|
||||
pCount, /* uint32 maxParameter, */
|
||||
NULL, /* InstructionMap *instructionMap */
|
||||
false, /* bool hasRestParameter, */
|
||||
false, /* bool hasNamedRestParameter */
|
||||
resultType);
|
||||
thisClass->defineMethod(methodName, new JSFunction(icm));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
if (element->name().compare(widenCString("field")) == 0) {
|
||||
@ -2465,7 +2478,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
|
||||
element->getValue(widenCString("name"), fieldName);
|
||||
element->getValue(widenCString("type"), fieldType);
|
||||
JSType *type = findType(mWorld->identifiers[fieldType]);
|
||||
JSType *type = findType(mContext->getWorld().identifiers[fieldType]);
|
||||
|
||||
if (element->hasAttribute(widenCString("static")))
|
||||
thisClass->defineStatic(fieldName, type);
|
||||
@ -2478,28 +2491,39 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
|
||||
if (!hasDefaultConstructor) {
|
||||
TypedRegister thisValue = TypedRegister(0, thisClass);
|
||||
ArgumentList args;
|
||||
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
|
||||
icg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
|
||||
ArgumentList *args = new ArgumentList(0);
|
||||
ICodeGenerator icg(mContext, thisClass, kIsStaticMethod);
|
||||
icg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
|
||||
if (superclass)
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
|
||||
if (thisClass->hasStatic(mInitName))
|
||||
icg.call(icg.getStatic(thisClass, mInitName), thisValue, &args);
|
||||
icg.call(icg.getStatic(thisClass, mInitName), thisValue, args);
|
||||
icg.returnStmt(thisValue);
|
||||
thisClass->defineConstructor(className);
|
||||
scg.setStatic(thisClass, mWorld->identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
|
||||
scg.setStatic(thisClass, mContext->getWorld().identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
|
||||
}
|
||||
thisClass->complete();
|
||||
|
||||
if (scg.getICode()->size()) {
|
||||
Interpreter::Context cx(*mWorld, thisScope);
|
||||
ICodeModule* clinit = scg.complete(&Void_Type);
|
||||
cx.interpret(clinit, JSValues());
|
||||
classContext->interpret(clinit, JSValues());
|
||||
delete clinit;
|
||||
}
|
||||
delete classContext;
|
||||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("script")) == 0) {
|
||||
// build an icode module and execute it
|
||||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("instance")) == 0) {
|
||||
// find the appropriate class and initialize the fields
|
||||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("object")) == 0) {
|
||||
// an object literal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -171,14 +171,13 @@ namespace ICG {
|
||||
bool iCodeOwner;
|
||||
LabelList labels;
|
||||
|
||||
Register mTopRegister; // highest (currently) alloacated register
|
||||
Register mTopRegister; // highest (currently) allocated register
|
||||
uint32 mParameterCount; // number of parameters declared for the function
|
||||
// these must come before any variables declared.
|
||||
TypedRegister mExceptionRegister; // reserved to carry the exception object.
|
||||
VariableList *variableList; // name|register pair for each variable
|
||||
|
||||
World *mWorld; // used to register strings
|
||||
JSScope *mGlobal; // the scope for compiling within
|
||||
|
||||
Context *mContext; // the world and global object
|
||||
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
|
||||
// maps source position to instruction index
|
||||
InstructionMap *mInstructionMap;
|
||||
@ -254,7 +253,7 @@ namespace ICG {
|
||||
|
||||
public:
|
||||
|
||||
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
|
||||
ICodeGenerator(Context *cx, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
|
||||
|
||||
~ICodeGenerator()
|
||||
{
|
||||
|
||||
@ -155,7 +155,7 @@ namespace ICodeASM {
|
||||
i = new BranchTrue (reinterpret_cast<Label*>(node->operand[0].data), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
|
||||
break;
|
||||
case 7:
|
||||
i = new Call (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0), *(reinterpret_cast<ArgumentList *>(node->operand[3].data)));
|
||||
i = new Call (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0), reinterpret_cast<ArgumentList*>(node->operand[3].data));
|
||||
break;
|
||||
case 8:
|
||||
i = new Cast (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<JSType*>(node->operand[2].data));
|
||||
@ -188,7 +188,7 @@ namespace ICodeASM {
|
||||
i = new DeleteProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data));
|
||||
break;
|
||||
case 18:
|
||||
i = new DirectCall (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSFunction*>(node->operand[1].data), *(reinterpret_cast<ArgumentList *>(node->operand[2].data)));
|
||||
i = new DirectCall (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSFunction*>(node->operand[1].data), reinterpret_cast<ArgumentList*>(node->operand[2].data));
|
||||
break;
|
||||
case 19:
|
||||
i = new Divide (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
|
||||
|
||||
@ -96,15 +96,15 @@ struct Activation : public gc_base {
|
||||
}
|
||||
|
||||
Activation(ICodeModule* iCode, Activation* caller, const JSValue thisArg,
|
||||
const ArgumentList& list)
|
||||
const ArgumentList* list)
|
||||
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
|
||||
{
|
||||
// copy caller's parameter list to initial registers.
|
||||
JSValues::iterator dest = mRegisters.begin();
|
||||
*dest++ = thisArg;
|
||||
const JSValues& params = caller->mRegisters;
|
||||
for (ArgumentList::const_iterator src = list.begin(),
|
||||
end = list.end(); src != end; ++src, ++dest) {
|
||||
for (ArgumentList::const_iterator src = list->begin(),
|
||||
end = list->end(); src != end; ++src, ++dest) {
|
||||
Register r = (*src).first.first;
|
||||
if (r != NotARegister)
|
||||
*dest = params[r];
|
||||
@ -157,7 +157,7 @@ ICodeModule* Context::compileFunction(const String &source)
|
||||
String filename = widenCString("Some source source");
|
||||
Parser p(getWorld(), a, source, filename);
|
||||
ExprNode* e = p.parseExpression(false);
|
||||
ICodeGenerator icg(&getWorld(), getGlobalObject());
|
||||
ICodeGenerator icg(this);
|
||||
ASSERT(e->getKind() == ExprNode::functionLiteral);
|
||||
FunctionExprNode* f = static_cast<FunctionExprNode*>(e);
|
||||
icg.allocateParameter(getWorld().identifiers["this"]); // always parameter #0
|
||||
@ -232,7 +232,7 @@ JSValue Context::readEvalFile(FILE* in, const String& fileName)
|
||||
|
||||
ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
|
||||
{
|
||||
ICodeGenerator icg(&getWorld(), getGlobalObject());
|
||||
ICodeGenerator icg(this);
|
||||
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
while (p) {
|
||||
@ -248,7 +248,7 @@ ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
|
||||
|
||||
void Context::loadClass(const char *fileName)
|
||||
{
|
||||
ICodeGenerator icg(&getWorld(), getGlobalObject());
|
||||
ICodeGenerator icg(this);
|
||||
icg.readICode(fileName); // loads it into the global object
|
||||
}
|
||||
|
||||
@ -702,11 +702,11 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
if (!target)
|
||||
throw new JSException("Call to non callable object");
|
||||
if (target->isNative()) {
|
||||
ArgumentList ¶ms = op4(call);
|
||||
JSValues argv(params.size() + 1);
|
||||
ArgumentList *params = op4(call);
|
||||
JSValues argv(params->size() + 1);
|
||||
argv[0] = (*registers)[op3(call).first];
|
||||
JSValues::size_type i = 1;
|
||||
for (ArgumentList::const_iterator src = params.begin(), end = params.end();
|
||||
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
|
||||
src != end; ++src, ++i) {
|
||||
argv[i] = (*registers)[src->first.first];
|
||||
}
|
||||
@ -717,12 +717,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
}
|
||||
else {
|
||||
ICodeModule *icm = target->getICode();
|
||||
ArgumentList &args = op4(call);
|
||||
ArgumentList *args = op4(call);
|
||||
|
||||
// mParameterCount includes 'this' and also 1 for a named rest parameter
|
||||
//
|
||||
uint32 pCount = icm->mParameterCount - 1;
|
||||
ArgumentList callArgs(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
|
||||
ArgumentList *callArgs = new ArgumentList(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
|
||||
if (icm->mHasNamedRestParameter) pCount--;
|
||||
|
||||
/*
|
||||
@ -740,19 +740,19 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
JSArray *restArg = NULL;
|
||||
uint32 restIndex = 0;
|
||||
uint32 i;
|
||||
for (i = 0; i < args.size(); i++) {
|
||||
if (args[i].second) { // a named argument
|
||||
TypedRegister r = icm->itsVariables->findVariable(*(args[i].second));
|
||||
for (i = 0; i < args->size(); i++) {
|
||||
if ((*args)[i].second) { // a named argument
|
||||
TypedRegister r = icm->itsVariables->findVariable(*((*args)[i].second));
|
||||
bool isParameter = false;
|
||||
if (r.first != NotABanana) { // we found the name in the target's list of variables
|
||||
if (r.first < icm->mParameterCount) { // make sure we didn't match a local var
|
||||
ASSERT(r.first <= callArgs.size());
|
||||
ASSERT(r.first <= callArgs->size());
|
||||
// the named argument is arriving in slot i, but needs to be r instead
|
||||
// r.first is the intended target register, we subtract 1 since the callArgs array doesn't include 'this'
|
||||
// here's where we could detect over-writing a positional arg with a named one if that is illegal
|
||||
// if (callArgs[r.first - 1].first.first != NotARegister)...
|
||||
(*registers)[args[i].first.first] = (*registers)[args[i].first.first].convert(r.second);
|
||||
callArgs[r.first - 1] = Argument(args[i].first, NULL); // no need to copy the name through?
|
||||
(*registers)[(*args)[i].first.first] = (*registers)[(*args)[i].first.first].convert(r.second);
|
||||
(*callArgs)[r.first - 1] = Argument((*args)[i].first, NULL); // no need to copy the name through?
|
||||
isParameter = true;
|
||||
}
|
||||
}
|
||||
@ -761,12 +761,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
if (icm->mHasNamedRestParameter) {
|
||||
if (restArg == NULL) {
|
||||
restArg = new JSArray();
|
||||
restArg->setProperty(*args[i].second, (*registers)[args[i].first.first]);
|
||||
(*registers)[args[i].first.first] = restArg;
|
||||
callArgs[pCount] = Argument(TypedRegister(args[i].first.first, &Array_Type), NULL);
|
||||
restArg->setProperty(*(*args)[i].second, (*registers)[(*args)[i].first.first]);
|
||||
(*registers)[(*args)[i].first.first] = restArg;
|
||||
(*callArgs)[pCount] = Argument(TypedRegister((*args)[i].first.first, &Array_Type), NULL);
|
||||
}
|
||||
else
|
||||
restArg->setProperty(*args[i].second, (*registers)[args[i].first.first]);
|
||||
restArg->setProperty(*(*args)[i].second, (*registers)[(*args)[i].first.first]);
|
||||
|
||||
}
|
||||
// else just throw it away
|
||||
@ -782,12 +782,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
if (icm->mHasNamedRestParameter) {
|
||||
if (restArg == NULL) {
|
||||
restArg = new JSArray();
|
||||
(*restArg)[restIndex++] = (*registers)[args[i].first.first];
|
||||
(*registers)[args[i].first.first] = restArg;
|
||||
callArgs[pCount] = Argument(TypedRegister(args[i].first.first, &Array_Type), NULL);
|
||||
(*restArg)[restIndex++] = (*registers)[(*args)[i].first.first];
|
||||
(*registers)[(*args)[i].first.first] = restArg;
|
||||
(*callArgs)[pCount] = Argument(TypedRegister((*args)[i].first.first, &Array_Type), NULL);
|
||||
}
|
||||
else
|
||||
(*restArg)[restIndex++] = (*registers)[args[i].first.first];
|
||||
(*restArg)[restIndex++] = (*registers)[(*args)[i].first.first];
|
||||
}
|
||||
// else just throw it away
|
||||
}
|
||||
@ -796,14 +796,14 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
}
|
||||
else {
|
||||
TypedRegister r = icm->itsVariables->getRegister(i + 1); // the variable list includes 'this'
|
||||
(*registers)[args[i].first.first] = (*registers)[args[i].first.first].convert(r.second);
|
||||
callArgs[i] = args[i]; // it's a positional, just slap it in place
|
||||
(*registers)[(*args)[i].first.first] = (*registers)[(*args)[i].first.first].convert(r.second);
|
||||
(*callArgs)[i] = (*args)[i]; // it's a positional, just slap it in place
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32 contiguousArgs = 0;
|
||||
for (i = 0; i < args.size(); i++) {
|
||||
Argument &arg = args[i];
|
||||
for (i = 0; i < args->size(); i++) {
|
||||
Argument &arg = (*args)[i];
|
||||
if (arg.first.first == NotARegister) break;
|
||||
contiguousArgs++;
|
||||
}
|
||||
@ -824,10 +824,10 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
DirectCall* call = static_cast<DirectCall*>(instruction);
|
||||
JSFunction *target = op2(call);
|
||||
if (target->isNative()) {
|
||||
ArgumentList ¶ms = op3(call);
|
||||
JSValues argv(params.size() + 1);
|
||||
ArgumentList *params = op3(call);
|
||||
JSValues argv(params->size() + 1);
|
||||
JSValues::size_type i = 1;
|
||||
for (ArgumentList::const_iterator src = params.begin(), end = params.end();
|
||||
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
|
||||
src != end; ++src, ++i) {
|
||||
argv[i] = (*registers)[src->first.first];
|
||||
}
|
||||
|
||||
@ -213,6 +213,7 @@ class Tracer : public Context::Listener {
|
||||
};
|
||||
|
||||
//#define HAVE_GEORGE_TRACE_IT
|
||||
//#define TEST_XML_LOADER
|
||||
|
||||
static void readEvalPrint(FILE *in, World &world)
|
||||
{
|
||||
@ -302,7 +303,7 @@ static void readEvalPrint(FILE *in, World &world)
|
||||
stdOut << '\n';
|
||||
}
|
||||
|
||||
|
||||
//#define HAVE_GEORGE_TRACE_IT
|
||||
|
||||
char * tests[] = {
|
||||
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
|
||||
@ -327,7 +328,7 @@ static void testCompile()
|
||||
Arena a;
|
||||
Parser p(world, a, testScript, widenCString("testCompile"));
|
||||
StmtNode *parsedStatements = p.parseProgram();
|
||||
ICodeGenerator icg(&world, &glob);
|
||||
ICodeGenerator icg(&cx);
|
||||
StmtNode *s = parsedStatements;
|
||||
while (s) {
|
||||
icg.genStmt(s);
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef jsclasses_h
|
||||
#define jsclasses_h
|
||||
|
||||
|
||||
@ -47,12 +47,12 @@ Formatter& operator<< (Formatter& f, Instruction& i)
|
||||
return i.print(f);
|
||||
}
|
||||
|
||||
Formatter& operator<< (Formatter& f, ArgumentList& rl)
|
||||
Formatter& operator<< (Formatter& f, ArgumentList* rl)
|
||||
{
|
||||
Argument* e = rl.end();
|
||||
Argument* e = rl->end();
|
||||
|
||||
f << "(";
|
||||
for (ArgumentList::iterator r = rl.begin(); r != e; r++) {
|
||||
for (ArgumentList::iterator r = rl->begin(); r != e; r++) {
|
||||
f << "R" << r->first.first;
|
||||
if ((r + 1) != e)
|
||||
f << ", ";
|
||||
@ -64,10 +64,10 @@ Formatter& operator<< (Formatter& f, ArgumentList& rl)
|
||||
|
||||
Formatter& operator<< (Formatter& f, const ArgList& al)
|
||||
{
|
||||
const ArgumentList& rl = al.mList;
|
||||
const ArgumentList* rl = al.mList;
|
||||
const JSValues& registers = al.mRegisters;
|
||||
f << "(";
|
||||
ArgumentList::const_iterator i = rl.begin(), e = rl.end();
|
||||
ArgumentList::const_iterator i = rl->begin(), e = rl->end();
|
||||
if (i != e) {
|
||||
Argument r = *i++;
|
||||
f << getRegisterValue(registers, r.first.first);
|
||||
|
||||
@ -97,16 +97,16 @@ namespace VM {
|
||||
* Helper to print Call operands.
|
||||
*/
|
||||
struct ArgList {
|
||||
const ArgumentList& mList;
|
||||
const ArgumentList* mList;
|
||||
const JSValues& mRegisters;
|
||||
ArgList(const ArgumentList& rl, const JSValues& registers)
|
||||
ArgList(const ArgumentList* rl, const JSValues& registers)
|
||||
: mList(rl), mRegisters(registers) {}
|
||||
};
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
Formatter& operator<< (Formatter& f, Instruction& i);
|
||||
Formatter& operator<< (Formatter& f, ArgumentList& rl);
|
||||
Formatter& operator<< (Formatter& f, ArgumentList* rl);
|
||||
Formatter& operator<< (Formatter& f, const ArgList& al);
|
||||
Formatter& operator<< (Formatter& f, InstructionStream& is);
|
||||
Formatter& operator<< (Formatter& f, TypedRegister& r);
|
||||
|
||||
@ -124,12 +124,32 @@ void XMLParser::parseAttrValue(String &val)
|
||||
}
|
||||
}
|
||||
|
||||
void XMLParser::parseStringLiteral(String &val)
|
||||
{
|
||||
char quotech = mReader.get();
|
||||
if ((quotech != '\"') || (quotech != '\''))
|
||||
syntaxError("\" or \' expected");
|
||||
else {
|
||||
mReader.beginRecording(val);
|
||||
while (true) {
|
||||
char ch = mReader.get();
|
||||
if (mReader.getEof())
|
||||
syntaxError("Unterminated string literal");
|
||||
if (ch == quotech)
|
||||
break;
|
||||
mReader.recordChar(ch);
|
||||
}
|
||||
mReader.endRecording();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XMLTag *XMLParser::parseTag()
|
||||
{
|
||||
XMLTag *tag = new XMLTag();
|
||||
char ch = mReader.peek();
|
||||
if (ch == '/') {
|
||||
tag->setEndTag();
|
||||
tag->setTag(EndTag);
|
||||
mReader.skip(1);
|
||||
}
|
||||
else {
|
||||
@ -137,7 +157,7 @@ XMLTag *XMLParser::parseTag()
|
||||
mReader.skip(1);
|
||||
if (mReader.match("--", 2)) {
|
||||
mReader.skip(2);
|
||||
tag->setComment();
|
||||
tag->setTag(CommentTag);
|
||||
while (true) {
|
||||
ch = mReader.get();
|
||||
if (mReader.getEof())
|
||||
@ -154,6 +174,25 @@ XMLTag *XMLParser::parseTag()
|
||||
if (mReader.isLineBreak(ch))
|
||||
mReader.beginLine();
|
||||
}
|
||||
} else {
|
||||
if (mReader.match("[CDATA[", 7)) {
|
||||
mReader.skip(7);
|
||||
tag->setTag(CDataTag);
|
||||
while (true) {
|
||||
ch = mReader.get();
|
||||
if (mReader.getEof())
|
||||
syntaxError("Unterminated CDATA tag");
|
||||
if (ch == ']') {
|
||||
if (mReader.match("]>", 2)) {
|
||||
mReader.skip(2);
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (mReader.isLineBreak(ch))
|
||||
mReader.beginLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,7 +213,7 @@ XMLTag *XMLParser::parseTag()
|
||||
if (mReader.getEof())
|
||||
syntaxError("Unterminated tag");
|
||||
if (ch == '/') {
|
||||
tag->setEmpty();
|
||||
tag->setTag(EmptyTag);
|
||||
ch = mReader.get();
|
||||
}
|
||||
if (ch != '>')
|
||||
@ -197,7 +236,7 @@ void XMLParser::parseTagBody(XMLNode *parent, XMLTag *startTag)
|
||||
break;
|
||||
else {
|
||||
XMLNode *child = new XMLNode(parent, tag);
|
||||
if (!tag->isEmpty())
|
||||
if (tag->hasContent())
|
||||
parseTagBody(child, tag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag } TagFlag;
|
||||
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag, CDataTag } TagFlag;
|
||||
|
||||
|
||||
class XMLLexer
|
||||
@ -68,14 +68,14 @@ public:
|
||||
|
||||
String &name() { return mName; }
|
||||
|
||||
void setEmpty() { mFlag = EmptyTag; }
|
||||
void setComment() { mFlag = EmptyTag; }
|
||||
void setEndTag() { mFlag = EndTag; }
|
||||
void setTag(TagFlag f) { mFlag = f; }
|
||||
|
||||
bool isEmpty() const { return mFlag == EmptyTag; }
|
||||
bool isEndTag() const { return mFlag == EndTag; }
|
||||
bool isComment() const { return mFlag == CommentTag; }
|
||||
|
||||
bool hasContent() const { return mFlag == Tag; }
|
||||
|
||||
String mName;
|
||||
TagFlag mFlag;
|
||||
AttributeList mAttributeList;
|
||||
@ -152,6 +152,7 @@ public:
|
||||
|
||||
XMLParser(const char *fileName) : mReader(fileName) { }
|
||||
|
||||
void parseStringLiteral(String &val);
|
||||
|
||||
void parseName(String &id);
|
||||
void parseWhiteSpace();
|
||||
|
||||
@ -153,18 +153,18 @@
|
||||
/* print() and printOperands() inherited from GenericBranch */
|
||||
};
|
||||
|
||||
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList> {
|
||||
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList*> {
|
||||
public:
|
||||
/* result, target, this, args */
|
||||
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, ArgumentList aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList>
|
||||
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, ArgumentList* aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList*>
|
||||
(CALL, aOp1, aOp2, aOp3, aOp4) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first) << ", " << ArgList(mOp4, registers);
|
||||
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first);
|
||||
return f;
|
||||
}
|
||||
};
|
||||
@ -328,18 +328,18 @@
|
||||
}
|
||||
};
|
||||
|
||||
class DirectCall : public Instruction_3<TypedRegister, JSFunction*, ArgumentList> {
|
||||
class DirectCall : public Instruction_3<TypedRegister, JSFunction*, ArgumentList*> {
|
||||
public:
|
||||
/* result, target, args */
|
||||
DirectCall (TypedRegister aOp1, JSFunction* aOp2, ArgumentList aOp3) :
|
||||
Instruction_3<TypedRegister, JSFunction*, ArgumentList>
|
||||
DirectCall (TypedRegister aOp1, JSFunction* aOp2, ArgumentList* aOp3) :
|
||||
Instruction_3<TypedRegister, JSFunction*, ArgumentList*>
|
||||
(DIRECT_CALL, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[DIRECT_CALL] << "\t" << mOp1 << ", " << "JSFunction" << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << getRegisterValue(registers, mOp1.first) << ", " << ArgList(mOp3, registers);
|
||||
f << getRegisterValue(registers, mOp1.first);
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
@ -31,6 +31,12 @@
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef _WIN32 // Microsoft Visual C++ 6.0 whines about name lengths over 255 getting truncated in the browser database
|
||||
#pragma warning( disable : 4786)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __icodeasm_h
|
||||
|
||||
#define __icodeasm_h
|
||||
|
||||
@ -73,20 +73,19 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
|
||||
//
|
||||
|
||||
|
||||
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags)
|
||||
ICodeGenerator::ICodeGenerator(Context *cx, JSClass *aClass, ICodeGeneratorFlags flags)
|
||||
: mTopRegister(0),
|
||||
mParameterCount(0),
|
||||
mExceptionRegister(TypedRegister(NotARegister, &None_Type)),
|
||||
variableList(new VariableList()),
|
||||
mWorld(world),
|
||||
mGlobal(global),
|
||||
mContext(cx),
|
||||
mInstructionMap(new InstructionMap()),
|
||||
mClass(aClass),
|
||||
mFlags(flags),
|
||||
pLabels(NULL),
|
||||
mHasRestParameter(false),
|
||||
mHasNamedRestParameter(false),
|
||||
mInitName(world->identifiers["__init__"])
|
||||
mInitName(cx->getWorld().identifiers["__init__"])
|
||||
{
|
||||
iCode = new InstructionStream();
|
||||
iCodeOwner = true;
|
||||
@ -94,12 +93,22 @@ ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, I
|
||||
|
||||
JSType *ICodeGenerator::findType(const StringAtom& typeName)
|
||||
{
|
||||
const JSValue& type = mGlobal->getVariable(typeName);
|
||||
const JSValue& type = mContext->getGlobalObject()->getVariable(typeName);
|
||||
if (type.isType())
|
||||
return type.type;
|
||||
return &Any_Type;
|
||||
}
|
||||
|
||||
/*
|
||||
-Called to allocate parameter and variable registers, aka 'permanent' registers.
|
||||
-mTopRegister is the current high-water mark.
|
||||
-mPermanentRegister marks those registers given to variables/parameters.
|
||||
-Theoretically, mPermanentRegister[n] can be become false when a scope ends and
|
||||
the registers allocated to contained variables are then available for re-use.
|
||||
-Mostly the need is to handle overlapping allocation of temps & permanents as the
|
||||
variables declarations are encountered. This wouldn't be necessary if a function
|
||||
presented a list of all variables, or a pre-pass executed to discover same.
|
||||
*/
|
||||
TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *type)
|
||||
{
|
||||
Register r = mTopRegister;
|
||||
@ -121,25 +130,16 @@ TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *t
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
|
||||
{
|
||||
if (mExceptionRegister.first == NotARegister) {
|
||||
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
|
||||
}
|
||||
return allocateRegister(name, findType(typeName));
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
|
||||
{
|
||||
if (mExceptionRegister.first == NotARegister) {
|
||||
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
|
||||
}
|
||||
return allocateRegister(name, &Any_Type);
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, JSType *type)
|
||||
{
|
||||
if (mExceptionRegister.first == NotARegister) {
|
||||
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
|
||||
}
|
||||
return allocateRegister(name, type);
|
||||
}
|
||||
|
||||
@ -493,7 +493,7 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1,
|
||||
TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg, ArgumentList *args)
|
||||
{
|
||||
TypedRegister dest(getTempRegister(), &Any_Type);
|
||||
Call *instr = new Call(dest, target, thisArg, *args);
|
||||
Call *instr = new Call(dest, target, thisArg, args);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
@ -501,7 +501,7 @@ TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg,
|
||||
TypedRegister ICodeGenerator::directCall(JSFunction *target, ArgumentList *args)
|
||||
{
|
||||
TypedRegister dest(getTempRegister(), &Any_Type);
|
||||
DirectCall *instr = new DirectCall(dest, target, *args);
|
||||
DirectCall *instr = new DirectCall(dest, target, args);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
@ -757,7 +757,7 @@ ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &n
|
||||
return (isConstructor) ? Constructor : Static;
|
||||
}
|
||||
}
|
||||
v.second = mGlobal->getType(name);
|
||||
v.second = mContext->getGlobalObject()->getType(name);
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
@ -946,7 +946,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
|
||||
// handle <class name>.<static field>
|
||||
//
|
||||
if (base.second == &Type_Type) {
|
||||
const JSValue &v = mGlobal->getVariable(baseName);
|
||||
const JSValue &v = mContext->getGlobalObject()->getVariable(baseName);
|
||||
bool isConstructor;
|
||||
ASSERT(v.isType()); // there's no other way that base.second could be &Type_Type, right?
|
||||
clazz = dynamic_cast<JSClass*>(v.type);
|
||||
@ -1154,23 +1154,23 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::New:
|
||||
{
|
||||
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
|
||||
ArgumentList args;
|
||||
ArgumentList *args = new ArgumentList();
|
||||
ExprPairList *p = i->pairs;
|
||||
while (p) {
|
||||
if (p->field && (p->field->getKind() == ExprNode::identifier))
|
||||
args.push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
|
||||
args->push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
|
||||
else
|
||||
args.push_back(Argument(genExpr(p->value), NULL ));
|
||||
args->push_back(Argument(genExpr(p->value), NULL ));
|
||||
p = p->next;
|
||||
}
|
||||
if (i->op->getKind() == ExprNode::identifier) {
|
||||
const StringAtom &className = static_cast<IdentifierExprNode *>(i->op)->name;
|
||||
const JSValue& value = mGlobal->getVariable(className);
|
||||
const JSValue& value = mContext->getGlobalObject()->getVariable(className);
|
||||
if (value.isType()) {
|
||||
JSClass* clazz = dynamic_cast<JSClass*>(value.type);
|
||||
if (clazz) {
|
||||
ret = newClass(clazz);
|
||||
ret = call(getStatic(clazz, className), ret, &args);
|
||||
ret = call(getStatic(clazz, className), ret, args);
|
||||
}
|
||||
else {
|
||||
//
|
||||
@ -1178,7 +1178,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
//
|
||||
JSFunction *f = value.type->getConstructor();
|
||||
if (f)
|
||||
ret = directCall(f, &args);
|
||||
ret = directCall(f, args);
|
||||
else
|
||||
NOT_REACHED("new <name>, where <name> is not a new-able type (whatever that means)"); // XXX Runtime error.
|
||||
}
|
||||
@ -1187,7 +1187,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (value.isFunction()) {
|
||||
TypedRegister f = loadName(className, value.type);
|
||||
ret = newObject(f);
|
||||
ret = call(f, ret, &args);
|
||||
ret = call(f, ret, args);
|
||||
}
|
||||
else
|
||||
NOT_REACHED("new <name>, where <name> is not a function"); // XXX Runtime error.
|
||||
@ -1207,23 +1207,23 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::call :
|
||||
{
|
||||
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
|
||||
ArgumentList args;
|
||||
ArgumentList *args = new ArgumentList();
|
||||
ExprPairList *p = i->pairs;
|
||||
uint32 count = 0;
|
||||
StringFormatter s;
|
||||
while (p) {
|
||||
if (p->field && (p->field->getKind() == ExprNode::identifier))
|
||||
args.push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
|
||||
args->push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
|
||||
else
|
||||
if (p->field && (p->field->getKind() == ExprNode::string))
|
||||
args.push_back(Argument(genExpr(p->value), &mWorld->identifiers[(static_cast<StringExprNode *>(p->field))->str]));
|
||||
args->push_back(Argument(genExpr(p->value), &mContext->getWorld().identifiers[(static_cast<StringExprNode *>(p->field))->str]));
|
||||
else {
|
||||
/* do this for new argument style to provide default 'positional' name
|
||||
s << count;
|
||||
args.push_back(Argument(genExpr(p->value), &mWorld->identifiers[s] ));
|
||||
args->push_back(Argument(genExpr(p->value), &mContext->getWorld().identifiers[s] ));
|
||||
s.clear();
|
||||
*/
|
||||
args.push_back(Argument(genExpr(p->value), NULL ));
|
||||
args->push_back(Argument(genExpr(p->value), NULL ));
|
||||
}
|
||||
count++;
|
||||
p = p->next;
|
||||
@ -1231,17 +1231,17 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
|
||||
if (i->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
|
||||
ret = handleDot(b, ExprNode::call, xcrementOp, ret, &args, false);
|
||||
ret = handleDot(b, ExprNode::call, xcrementOp, ret, args, false);
|
||||
}
|
||||
else
|
||||
if (i->op->getKind() == ExprNode::identifier) {
|
||||
ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, ret, &args, false);
|
||||
ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, ret, args, false);
|
||||
}
|
||||
else
|
||||
if (i->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = call(getElement(base, genExpr(b->op2)), base, &args);
|
||||
ret = call(getElement(base, genExpr(b->op2)), base, args);
|
||||
}
|
||||
else
|
||||
ASSERT("WAH!");
|
||||
@ -1279,7 +1279,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
ret = loadImmediate((static_cast<NumberExprNode *>(p))->value);
|
||||
break;
|
||||
case ExprNode::string :
|
||||
ret = loadString(mWorld->identifiers[(static_cast<StringExprNode *>(p))->str]);
|
||||
ret = loadString(mContext->getWorld().identifiers[(static_cast<StringExprNode *>(p))->str]);
|
||||
break;
|
||||
case ExprNode::preDecrement:
|
||||
xcrementOp = SUBTRACT;
|
||||
@ -1564,8 +1564,8 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::functionLiteral:
|
||||
{
|
||||
FunctionExprNode *f = static_cast<FunctionExprNode *>(p);
|
||||
ICodeGenerator icg(mWorld, mGlobal);
|
||||
icg.allocateParameter(mWorld->identifiers["this"]); // always parameter #0
|
||||
ICodeGenerator icg(mContext);
|
||||
icg.allocateParameter(mContext->getWorld().identifiers["this"]); // always parameter #0
|
||||
VariableBinding *v = f->function.parameters;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
@ -1590,7 +1590,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
const StringAtom &name = (static_cast<IdentifierExprNode *>(b->op2))->name;
|
||||
/*LValueKind lvk = resolveIdentifier(name, t, slotIndex);*/
|
||||
ASSERT(t.second == &Type_Type);
|
||||
const JSValue &v = mGlobal->getVariable(name);
|
||||
const JSValue &v = mContext->getGlobalObject()->getVariable(name);
|
||||
ASSERT(v.isType());
|
||||
JSClass *clazz = dynamic_cast<JSClass*>(v.type);
|
||||
if (clazz)
|
||||
@ -1648,8 +1648,8 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
|
||||
bool isStatic = hasAttribute(f->attributes, Token::Static);
|
||||
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
|
||||
|
||||
ICodeGenerator icg(mWorld, mGlobal, mClass, flags);
|
||||
icg.allocateParameter(mWorld->identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
|
||||
ICodeGenerator icg(mContext, mClass, flags);
|
||||
icg.allocateParameter(mContext->getWorld().identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
|
||||
VariableBinding *v = f->function.parameters;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
|
||||
@ -1703,7 +1703,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
|
||||
superclass constructor ourselves.
|
||||
*/
|
||||
TypedRegister thisValue = TypedRegister(0, mClass);
|
||||
ArgumentList args;
|
||||
ArgumentList *args = new ArgumentList();
|
||||
if (superclass) {
|
||||
bool foundSuperCall = false;
|
||||
BlockStmtNode *b = f->function.body;
|
||||
@ -1724,11 +1724,11 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
|
||||
}
|
||||
}
|
||||
if (!foundSuperCall) { // invoke the default superclass constructor
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
|
||||
}
|
||||
}
|
||||
if (mClass->hasStatic(mInitName))
|
||||
icg.call(icg.getStatic(mClass, mInitName), thisValue, &args); // ok, so it's mis-named
|
||||
icg.call(icg.getStatic(mClass, mInitName), thisValue, args); // ok, so it's mis-named
|
||||
|
||||
}
|
||||
if (f->function.body)
|
||||
@ -1745,9 +1745,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
|
||||
startStatement(p->pos);
|
||||
if (mExceptionRegister.first == NotARegister) {
|
||||
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
|
||||
}
|
||||
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::Class:
|
||||
@ -1760,14 +1757,14 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
if (classStmt->superclass) {
|
||||
ASSERT(classStmt->superclass->getKind() == ExprNode::identifier);
|
||||
IdentifierExprNode* superclassExpr = static_cast<IdentifierExprNode*>(classStmt->superclass);
|
||||
const JSValue& superclassValue = mGlobal->getVariable(superclassExpr->name);
|
||||
const JSValue& superclassValue = mContext->getGlobalObject()->getVariable(superclassExpr->name);
|
||||
ASSERT(superclassValue.isObject() && !superclassValue.isNull());
|
||||
superclass = static_cast<JSClass*>(superclassValue.object);
|
||||
}
|
||||
JSClass* thisClass = new JSClass(mGlobal, nameExpr->name, superclass);
|
||||
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), nameExpr->name, superclass);
|
||||
// is it ok for a partially defined class to appear in global scope? this is needed
|
||||
// to handle recursive types, such as linked list nodes.
|
||||
mGlobal->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
|
||||
mContext->getGlobalObject()->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
|
||||
|
||||
|
||||
/*
|
||||
@ -1849,14 +1846,15 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
if (classStmt->body) {
|
||||
JSScope* thisScope = thisClass->getScope();
|
||||
ICodeGenerator *ccg = NULL;
|
||||
Context *classContext = new Context(mContext->getWorld(), thisScope);
|
||||
if (needsInstanceInitializer) {
|
||||
// constructor code generator. Slot variable
|
||||
// initializers get added to this function.
|
||||
ccg = new ICodeGenerator(mWorld, thisScope, thisClass, kNoFlags);
|
||||
ccg->allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
|
||||
ccg = new ICodeGenerator(classContext, thisClass, kNoFlags);
|
||||
ccg->allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
|
||||
}
|
||||
|
||||
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod); // static initializer code generator.
|
||||
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod); // static initializer code generator.
|
||||
// static field inits, plus code to initialize
|
||||
// static method slots.
|
||||
StmtNode* s = classStmt->body->statements;
|
||||
@ -1895,7 +1893,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
bool isConstructor = (s->getKind() == StmtNode::Constructor);
|
||||
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
|
||||
|
||||
ICodeGenerator mcg(mWorld, thisScope, thisClass, flags); // method code generator.
|
||||
ICodeGenerator mcg(classContext, thisClass, flags); // method code generator.
|
||||
ICodeModule *icm = mcg.genFunction(f, isConstructor, superclass);
|
||||
if (f->function.name->getKind() == ExprNode::identifier) {
|
||||
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
|
||||
@ -1939,13 +1937,13 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
// initializer and the superclass default constructor
|
||||
if (!hasDefaultConstructor) {
|
||||
TypedRegister thisValue = TypedRegister(0, thisClass);
|
||||
ArgumentList args;
|
||||
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
|
||||
icg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
|
||||
ArgumentList *args = new ArgumentList();
|
||||
ICodeGenerator icg(classContext, thisClass, kIsStaticMethod);
|
||||
icg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
|
||||
if (superclass)
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
|
||||
if (thisClass->hasStatic(mInitName))
|
||||
icg.call(icg.getStatic(thisClass, mInitName), thisValue, &args);
|
||||
icg.call(icg.getStatic(thisClass, mInitName), thisValue, args);
|
||||
icg.returnStmt(thisValue);
|
||||
thisClass->defineConstructor(nameExpr->name);
|
||||
scg.setStatic(thisClass, nameExpr->name, scg.newFunction(icg.complete(&Void_Type)));
|
||||
@ -1956,11 +1954,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
|
||||
// REVISIT: using the scope of the class to store both methods and statics.
|
||||
if (scg.getICode()->size()) {
|
||||
Interpreter::Context cx(*mWorld, thisScope);
|
||||
ICodeModule* clinit = scg.complete(&Void_Type);
|
||||
cx.interpret(clinit, JSValues());
|
||||
classContext->interpret(clinit, JSValues());
|
||||
delete clinit;
|
||||
}
|
||||
delete classContext;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1974,8 +1972,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
switch (f->function.prefix) {
|
||||
case FunctionName::Get:
|
||||
if (isTopLevel()) {
|
||||
mGlobal->defineVariable(name, resultType);
|
||||
mGlobal->setGetter(name, new JSFunction(icm));
|
||||
mContext->getGlobalObject()->defineVariable(name, resultType);
|
||||
mContext->getGlobalObject()->setGetter(name, new JSFunction(icm));
|
||||
}
|
||||
else {
|
||||
// is this legal - a nested getter?
|
||||
@ -1985,8 +1983,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
break;
|
||||
case FunctionName::Set:
|
||||
if (isTopLevel()) {
|
||||
mGlobal->defineVariable(name, resultType);
|
||||
mGlobal->setSetter(name, new JSFunction(icm));
|
||||
mContext->getGlobalObject()->defineVariable(name, resultType);
|
||||
mContext->getGlobalObject()->setSetter(name, new JSFunction(icm));
|
||||
}
|
||||
else {
|
||||
// is this legal - a nested setter?
|
||||
@ -1995,7 +1993,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
}
|
||||
break;
|
||||
case FunctionName::normal:
|
||||
mGlobal->defineFunction(name, icm);
|
||||
mContext->getGlobalObject()->defineFunction(name, icm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2010,8 +2008,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
std::transform(fileName->begin(), fileName->end(), str.begin(), narrow);
|
||||
FILE* f = fopen(str.c_str(), "r");
|
||||
if (f) {
|
||||
Context cx(*mWorld, mGlobal);
|
||||
(void)cx.readEvalFile(f, *fileName);
|
||||
(void)mContext->readEvalFile(f, *fileName);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
@ -2025,7 +2022,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
|
||||
JSType *type = extractType(v->type);
|
||||
if (isTopLevel())
|
||||
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
|
||||
mContext->getGlobalObject()->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
|
||||
else
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
|
||||
if (v->initializer) {
|
||||
@ -2326,6 +2323,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
CatchClause *c = t->catches;
|
||||
while (c) {
|
||||
// Bind the incoming exception ...
|
||||
if (mExceptionRegister.first == NotABanana)
|
||||
mExceptionRegister = allocateRegister(mContext->getWorld().identifiers["__exceptionObject__"], &Any_Type);
|
||||
variableList->setRegisterForVariable(c->name, mExceptionRegister);
|
||||
|
||||
genStmt(c->stmt);
|
||||
@ -2412,17 +2411,18 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
|
||||
node->getValue(widenCString("name"), className);
|
||||
if (node->getValue(widenCString("super"), superName)) {
|
||||
const JSValue& superclassValue = mGlobal->getVariable(superName);
|
||||
const JSValue& superclassValue = mContext->getGlobalObject()->getVariable(superName);
|
||||
superclass = static_cast<JSClass*>(superclassValue.object);
|
||||
}
|
||||
JSClass* thisClass = new JSClass(mGlobal, className, superclass);
|
||||
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), className, superclass);
|
||||
JSScope* thisScope = thisClass->getScope();
|
||||
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod);
|
||||
ICodeGenerator ccg(mWorld, thisScope, thisClass, kNoFlags);
|
||||
ccg.allocateParameter(mWorld->identifiers["this"], thisClass);
|
||||
Context *classContext = new Context(mContext->getWorld(), thisScope);
|
||||
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod);
|
||||
ICodeGenerator ccg(classContext, thisClass, kNoFlags);
|
||||
ccg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass);
|
||||
thisClass->defineStatic(mInitName, &Function_Type);
|
||||
|
||||
mGlobal->defineVariable(className, &Type_Type, JSValue(thisClass));
|
||||
mContext->getGlobalObject()->defineVariable(className, &Type_Type, JSValue(thisClass));
|
||||
|
||||
bool hasDefaultConstructor = false;
|
||||
XMLNodeList &elements = node->children();
|
||||
@ -2432,31 +2432,44 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
if (element->name().compare(widenCString("method")) == 0) {
|
||||
String methodName, resultTypeName;
|
||||
element->getValue(widenCString("name"), methodName);
|
||||
element->getValue(widenCString("result"), resultTypeName);
|
||||
#ifdef ROB_DONE
|
||||
JSType *resultType = findType(mWorld->identifiers[resultTypeName]);
|
||||
element->getValue(widenCString("type"), resultTypeName);
|
||||
VariableList *theVariableList = new VariableList();
|
||||
theVariableList->add(mContext->getWorld().identifiers["this"], TypedRegister(0, thisClass));
|
||||
uint32 pCount = 1;
|
||||
XMLNodeList ¶meters = element->children();
|
||||
for (XMLNodeList::const_iterator k = parameters.begin(); k != parameters.end(); k++) {
|
||||
XMLNode *parameter = *k;
|
||||
if (parameter->name().compare(widenCString("parameter")) == 0) {
|
||||
String parameterName;
|
||||
String parameterTypeName;
|
||||
element->getValue(widenCString("name"), parameterName);
|
||||
element->getValue(widenCString("type"), parameterTypeName);
|
||||
JSType *parameterType = findType(mContext->getWorld().identifiers[parameterTypeName]);
|
||||
theVariableList->add(mContext->getWorld().identifiers[parameterName], TypedRegister(pCount++, parameterType));
|
||||
}
|
||||
}
|
||||
|
||||
JSType *resultType = findType(mContext->getWorld().identifiers[resultTypeName]);
|
||||
String &body = element->body();
|
||||
if (body.length()) {
|
||||
std::string str(body.length(), char());
|
||||
std::transform(body.begin(), body.end(), str.begin(), narrow);
|
||||
ICodeParser icp;
|
||||
ICodeParser icp(mContext);
|
||||
|
||||
stdOut << "Calling ICodeParser with :\n" << str << "\n";
|
||||
|
||||
icp.ParseSourceFromString(str);
|
||||
|
||||
ICodeModule *icm = new ICodeModule(icp.instructionStream(),
|
||||
NULL, /* VariableList *variables */
|
||||
icp.maxRegister,
|
||||
1, /* uint32 maxParameter, */
|
||||
NULL, /* InstructionMap *instructionMap */
|
||||
false, /* bool hasRestParameter, */
|
||||
false, /* bool hasNamedRestParameter */
|
||||
ICodeModule *icm = new ICodeModule(icp.mInstructions,
|
||||
theVariableList, /* VariableList *variables */
|
||||
icp.mMaxRegister,
|
||||
pCount, /* uint32 maxParameter, */
|
||||
NULL, /* InstructionMap *instructionMap */
|
||||
false, /* bool hasRestParameter, */
|
||||
false, /* bool hasNamedRestParameter */
|
||||
resultType);
|
||||
thisClass->defineMethod(methodName, new JSFunction(icm));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
if (element->name().compare(widenCString("field")) == 0) {
|
||||
@ -2465,7 +2478,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
|
||||
element->getValue(widenCString("name"), fieldName);
|
||||
element->getValue(widenCString("type"), fieldType);
|
||||
JSType *type = findType(mWorld->identifiers[fieldType]);
|
||||
JSType *type = findType(mContext->getWorld().identifiers[fieldType]);
|
||||
|
||||
if (element->hasAttribute(widenCString("static")))
|
||||
thisClass->defineStatic(fieldName, type);
|
||||
@ -2478,28 +2491,39 @@ void ICodeGenerator::readICode(const char *fileName)
|
||||
|
||||
if (!hasDefaultConstructor) {
|
||||
TypedRegister thisValue = TypedRegister(0, thisClass);
|
||||
ArgumentList args;
|
||||
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
|
||||
icg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
|
||||
ArgumentList *args = new ArgumentList(0);
|
||||
ICodeGenerator icg(mContext, thisClass, kIsStaticMethod);
|
||||
icg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
|
||||
if (superclass)
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
|
||||
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
|
||||
if (thisClass->hasStatic(mInitName))
|
||||
icg.call(icg.getStatic(thisClass, mInitName), thisValue, &args);
|
||||
icg.call(icg.getStatic(thisClass, mInitName), thisValue, args);
|
||||
icg.returnStmt(thisValue);
|
||||
thisClass->defineConstructor(className);
|
||||
scg.setStatic(thisClass, mWorld->identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
|
||||
scg.setStatic(thisClass, mContext->getWorld().identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
|
||||
}
|
||||
thisClass->complete();
|
||||
|
||||
if (scg.getICode()->size()) {
|
||||
Interpreter::Context cx(*mWorld, thisScope);
|
||||
ICodeModule* clinit = scg.complete(&Void_Type);
|
||||
cx.interpret(clinit, JSValues());
|
||||
classContext->interpret(clinit, JSValues());
|
||||
delete clinit;
|
||||
}
|
||||
delete classContext;
|
||||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("script")) == 0) {
|
||||
// build an icode module and execute it
|
||||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("instance")) == 0) {
|
||||
// find the appropriate class and initialize the fields
|
||||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("object")) == 0) {
|
||||
// an object literal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -171,14 +171,13 @@ namespace ICG {
|
||||
bool iCodeOwner;
|
||||
LabelList labels;
|
||||
|
||||
Register mTopRegister; // highest (currently) alloacated register
|
||||
Register mTopRegister; // highest (currently) allocated register
|
||||
uint32 mParameterCount; // number of parameters declared for the function
|
||||
// these must come before any variables declared.
|
||||
TypedRegister mExceptionRegister; // reserved to carry the exception object.
|
||||
VariableList *variableList; // name|register pair for each variable
|
||||
|
||||
World *mWorld; // used to register strings
|
||||
JSScope *mGlobal; // the scope for compiling within
|
||||
|
||||
Context *mContext; // the world and global object
|
||||
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
|
||||
// maps source position to instruction index
|
||||
InstructionMap *mInstructionMap;
|
||||
@ -254,7 +253,7 @@ namespace ICG {
|
||||
|
||||
public:
|
||||
|
||||
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
|
||||
ICodeGenerator(Context *cx, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
|
||||
|
||||
~ICodeGenerator()
|
||||
{
|
||||
|
||||
@ -155,7 +155,7 @@ namespace ICodeASM {
|
||||
i = new BranchTrue (reinterpret_cast<Label*>(node->operand[0].data), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
|
||||
break;
|
||||
case 7:
|
||||
i = new Call (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0), *(reinterpret_cast<ArgumentList *>(node->operand[3].data)));
|
||||
i = new Call (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0), reinterpret_cast<ArgumentList*>(node->operand[3].data));
|
||||
break;
|
||||
case 8:
|
||||
i = new Cast (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<JSType*>(node->operand[2].data));
|
||||
@ -188,7 +188,7 @@ namespace ICodeASM {
|
||||
i = new DeleteProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data));
|
||||
break;
|
||||
case 18:
|
||||
i = new DirectCall (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSFunction*>(node->operand[1].data), *(reinterpret_cast<ArgumentList *>(node->operand[2].data)));
|
||||
i = new DirectCall (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSFunction*>(node->operand[1].data), reinterpret_cast<ArgumentList*>(node->operand[2].data));
|
||||
break;
|
||||
case 19:
|
||||
i = new Divide (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
|
||||
|
||||
@ -96,15 +96,15 @@ struct Activation : public gc_base {
|
||||
}
|
||||
|
||||
Activation(ICodeModule* iCode, Activation* caller, const JSValue thisArg,
|
||||
const ArgumentList& list)
|
||||
const ArgumentList* list)
|
||||
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
|
||||
{
|
||||
// copy caller's parameter list to initial registers.
|
||||
JSValues::iterator dest = mRegisters.begin();
|
||||
*dest++ = thisArg;
|
||||
const JSValues& params = caller->mRegisters;
|
||||
for (ArgumentList::const_iterator src = list.begin(),
|
||||
end = list.end(); src != end; ++src, ++dest) {
|
||||
for (ArgumentList::const_iterator src = list->begin(),
|
||||
end = list->end(); src != end; ++src, ++dest) {
|
||||
Register r = (*src).first.first;
|
||||
if (r != NotARegister)
|
||||
*dest = params[r];
|
||||
@ -157,7 +157,7 @@ ICodeModule* Context::compileFunction(const String &source)
|
||||
String filename = widenCString("Some source source");
|
||||
Parser p(getWorld(), a, source, filename);
|
||||
ExprNode* e = p.parseExpression(false);
|
||||
ICodeGenerator icg(&getWorld(), getGlobalObject());
|
||||
ICodeGenerator icg(this);
|
||||
ASSERT(e->getKind() == ExprNode::functionLiteral);
|
||||
FunctionExprNode* f = static_cast<FunctionExprNode*>(e);
|
||||
icg.allocateParameter(getWorld().identifiers["this"]); // always parameter #0
|
||||
@ -232,7 +232,7 @@ JSValue Context::readEvalFile(FILE* in, const String& fileName)
|
||||
|
||||
ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
|
||||
{
|
||||
ICodeGenerator icg(&getWorld(), getGlobalObject());
|
||||
ICodeGenerator icg(this);
|
||||
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
while (p) {
|
||||
@ -248,7 +248,7 @@ ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
|
||||
|
||||
void Context::loadClass(const char *fileName)
|
||||
{
|
||||
ICodeGenerator icg(&getWorld(), getGlobalObject());
|
||||
ICodeGenerator icg(this);
|
||||
icg.readICode(fileName); // loads it into the global object
|
||||
}
|
||||
|
||||
@ -702,11 +702,11 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
if (!target)
|
||||
throw new JSException("Call to non callable object");
|
||||
if (target->isNative()) {
|
||||
ArgumentList ¶ms = op4(call);
|
||||
JSValues argv(params.size() + 1);
|
||||
ArgumentList *params = op4(call);
|
||||
JSValues argv(params->size() + 1);
|
||||
argv[0] = (*registers)[op3(call).first];
|
||||
JSValues::size_type i = 1;
|
||||
for (ArgumentList::const_iterator src = params.begin(), end = params.end();
|
||||
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
|
||||
src != end; ++src, ++i) {
|
||||
argv[i] = (*registers)[src->first.first];
|
||||
}
|
||||
@ -717,12 +717,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
}
|
||||
else {
|
||||
ICodeModule *icm = target->getICode();
|
||||
ArgumentList &args = op4(call);
|
||||
ArgumentList *args = op4(call);
|
||||
|
||||
// mParameterCount includes 'this' and also 1 for a named rest parameter
|
||||
//
|
||||
uint32 pCount = icm->mParameterCount - 1;
|
||||
ArgumentList callArgs(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
|
||||
ArgumentList *callArgs = new ArgumentList(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
|
||||
if (icm->mHasNamedRestParameter) pCount--;
|
||||
|
||||
/*
|
||||
@ -740,19 +740,19 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
JSArray *restArg = NULL;
|
||||
uint32 restIndex = 0;
|
||||
uint32 i;
|
||||
for (i = 0; i < args.size(); i++) {
|
||||
if (args[i].second) { // a named argument
|
||||
TypedRegister r = icm->itsVariables->findVariable(*(args[i].second));
|
||||
for (i = 0; i < args->size(); i++) {
|
||||
if ((*args)[i].second) { // a named argument
|
||||
TypedRegister r = icm->itsVariables->findVariable(*((*args)[i].second));
|
||||
bool isParameter = false;
|
||||
if (r.first != NotABanana) { // we found the name in the target's list of variables
|
||||
if (r.first < icm->mParameterCount) { // make sure we didn't match a local var
|
||||
ASSERT(r.first <= callArgs.size());
|
||||
ASSERT(r.first <= callArgs->size());
|
||||
// the named argument is arriving in slot i, but needs to be r instead
|
||||
// r.first is the intended target register, we subtract 1 since the callArgs array doesn't include 'this'
|
||||
// here's where we could detect over-writing a positional arg with a named one if that is illegal
|
||||
// if (callArgs[r.first - 1].first.first != NotARegister)...
|
||||
(*registers)[args[i].first.first] = (*registers)[args[i].first.first].convert(r.second);
|
||||
callArgs[r.first - 1] = Argument(args[i].first, NULL); // no need to copy the name through?
|
||||
(*registers)[(*args)[i].first.first] = (*registers)[(*args)[i].first.first].convert(r.second);
|
||||
(*callArgs)[r.first - 1] = Argument((*args)[i].first, NULL); // no need to copy the name through?
|
||||
isParameter = true;
|
||||
}
|
||||
}
|
||||
@ -761,12 +761,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
if (icm->mHasNamedRestParameter) {
|
||||
if (restArg == NULL) {
|
||||
restArg = new JSArray();
|
||||
restArg->setProperty(*args[i].second, (*registers)[args[i].first.first]);
|
||||
(*registers)[args[i].first.first] = restArg;
|
||||
callArgs[pCount] = Argument(TypedRegister(args[i].first.first, &Array_Type), NULL);
|
||||
restArg->setProperty(*(*args)[i].second, (*registers)[(*args)[i].first.first]);
|
||||
(*registers)[(*args)[i].first.first] = restArg;
|
||||
(*callArgs)[pCount] = Argument(TypedRegister((*args)[i].first.first, &Array_Type), NULL);
|
||||
}
|
||||
else
|
||||
restArg->setProperty(*args[i].second, (*registers)[args[i].first.first]);
|
||||
restArg->setProperty(*(*args)[i].second, (*registers)[(*args)[i].first.first]);
|
||||
|
||||
}
|
||||
// else just throw it away
|
||||
@ -782,12 +782,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
if (icm->mHasNamedRestParameter) {
|
||||
if (restArg == NULL) {
|
||||
restArg = new JSArray();
|
||||
(*restArg)[restIndex++] = (*registers)[args[i].first.first];
|
||||
(*registers)[args[i].first.first] = restArg;
|
||||
callArgs[pCount] = Argument(TypedRegister(args[i].first.first, &Array_Type), NULL);
|
||||
(*restArg)[restIndex++] = (*registers)[(*args)[i].first.first];
|
||||
(*registers)[(*args)[i].first.first] = restArg;
|
||||
(*callArgs)[pCount] = Argument(TypedRegister((*args)[i].first.first, &Array_Type), NULL);
|
||||
}
|
||||
else
|
||||
(*restArg)[restIndex++] = (*registers)[args[i].first.first];
|
||||
(*restArg)[restIndex++] = (*registers)[(*args)[i].first.first];
|
||||
}
|
||||
// else just throw it away
|
||||
}
|
||||
@ -796,14 +796,14 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
}
|
||||
else {
|
||||
TypedRegister r = icm->itsVariables->getRegister(i + 1); // the variable list includes 'this'
|
||||
(*registers)[args[i].first.first] = (*registers)[args[i].first.first].convert(r.second);
|
||||
callArgs[i] = args[i]; // it's a positional, just slap it in place
|
||||
(*registers)[(*args)[i].first.first] = (*registers)[(*args)[i].first.first].convert(r.second);
|
||||
(*callArgs)[i] = (*args)[i]; // it's a positional, just slap it in place
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32 contiguousArgs = 0;
|
||||
for (i = 0; i < args.size(); i++) {
|
||||
Argument &arg = args[i];
|
||||
for (i = 0; i < args->size(); i++) {
|
||||
Argument &arg = (*args)[i];
|
||||
if (arg.first.first == NotARegister) break;
|
||||
contiguousArgs++;
|
||||
}
|
||||
@ -824,10 +824,10 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
||||
DirectCall* call = static_cast<DirectCall*>(instruction);
|
||||
JSFunction *target = op2(call);
|
||||
if (target->isNative()) {
|
||||
ArgumentList ¶ms = op3(call);
|
||||
JSValues argv(params.size() + 1);
|
||||
ArgumentList *params = op3(call);
|
||||
JSValues argv(params->size() + 1);
|
||||
JSValues::size_type i = 1;
|
||||
for (ArgumentList::const_iterator src = params.begin(), end = params.end();
|
||||
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
|
||||
src != end; ++src, ++i) {
|
||||
argv[i] = (*registers)[src->first.first];
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef jsclasses_h
|
||||
#define jsclasses_h
|
||||
|
||||
|
||||
@ -47,12 +47,12 @@ Formatter& operator<< (Formatter& f, Instruction& i)
|
||||
return i.print(f);
|
||||
}
|
||||
|
||||
Formatter& operator<< (Formatter& f, ArgumentList& rl)
|
||||
Formatter& operator<< (Formatter& f, ArgumentList* rl)
|
||||
{
|
||||
Argument* e = rl.end();
|
||||
Argument* e = rl->end();
|
||||
|
||||
f << "(";
|
||||
for (ArgumentList::iterator r = rl.begin(); r != e; r++) {
|
||||
for (ArgumentList::iterator r = rl->begin(); r != e; r++) {
|
||||
f << "R" << r->first.first;
|
||||
if ((r + 1) != e)
|
||||
f << ", ";
|
||||
@ -64,10 +64,10 @@ Formatter& operator<< (Formatter& f, ArgumentList& rl)
|
||||
|
||||
Formatter& operator<< (Formatter& f, const ArgList& al)
|
||||
{
|
||||
const ArgumentList& rl = al.mList;
|
||||
const ArgumentList* rl = al.mList;
|
||||
const JSValues& registers = al.mRegisters;
|
||||
f << "(";
|
||||
ArgumentList::const_iterator i = rl.begin(), e = rl.end();
|
||||
ArgumentList::const_iterator i = rl->begin(), e = rl->end();
|
||||
if (i != e) {
|
||||
Argument r = *i++;
|
||||
f << getRegisterValue(registers, r.first.first);
|
||||
|
||||
@ -97,16 +97,16 @@ namespace VM {
|
||||
* Helper to print Call operands.
|
||||
*/
|
||||
struct ArgList {
|
||||
const ArgumentList& mList;
|
||||
const ArgumentList* mList;
|
||||
const JSValues& mRegisters;
|
||||
ArgList(const ArgumentList& rl, const JSValues& registers)
|
||||
ArgList(const ArgumentList* rl, const JSValues& registers)
|
||||
: mList(rl), mRegisters(registers) {}
|
||||
};
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
Formatter& operator<< (Formatter& f, Instruction& i);
|
||||
Formatter& operator<< (Formatter& f, ArgumentList& rl);
|
||||
Formatter& operator<< (Formatter& f, ArgumentList* rl);
|
||||
Formatter& operator<< (Formatter& f, const ArgList& al);
|
||||
Formatter& operator<< (Formatter& f, InstructionStream& is);
|
||||
Formatter& operator<< (Formatter& f, TypedRegister& r);
|
||||
|
||||
@ -124,12 +124,32 @@ void XMLParser::parseAttrValue(String &val)
|
||||
}
|
||||
}
|
||||
|
||||
void XMLParser::parseStringLiteral(String &val)
|
||||
{
|
||||
char quotech = mReader.get();
|
||||
if ((quotech != '\"') || (quotech != '\''))
|
||||
syntaxError("\" or \' expected");
|
||||
else {
|
||||
mReader.beginRecording(val);
|
||||
while (true) {
|
||||
char ch = mReader.get();
|
||||
if (mReader.getEof())
|
||||
syntaxError("Unterminated string literal");
|
||||
if (ch == quotech)
|
||||
break;
|
||||
mReader.recordChar(ch);
|
||||
}
|
||||
mReader.endRecording();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XMLTag *XMLParser::parseTag()
|
||||
{
|
||||
XMLTag *tag = new XMLTag();
|
||||
char ch = mReader.peek();
|
||||
if (ch == '/') {
|
||||
tag->setEndTag();
|
||||
tag->setTag(EndTag);
|
||||
mReader.skip(1);
|
||||
}
|
||||
else {
|
||||
@ -137,7 +157,7 @@ XMLTag *XMLParser::parseTag()
|
||||
mReader.skip(1);
|
||||
if (mReader.match("--", 2)) {
|
||||
mReader.skip(2);
|
||||
tag->setComment();
|
||||
tag->setTag(CommentTag);
|
||||
while (true) {
|
||||
ch = mReader.get();
|
||||
if (mReader.getEof())
|
||||
@ -154,6 +174,25 @@ XMLTag *XMLParser::parseTag()
|
||||
if (mReader.isLineBreak(ch))
|
||||
mReader.beginLine();
|
||||
}
|
||||
} else {
|
||||
if (mReader.match("[CDATA[", 7)) {
|
||||
mReader.skip(7);
|
||||
tag->setTag(CDataTag);
|
||||
while (true) {
|
||||
ch = mReader.get();
|
||||
if (mReader.getEof())
|
||||
syntaxError("Unterminated CDATA tag");
|
||||
if (ch == ']') {
|
||||
if (mReader.match("]>", 2)) {
|
||||
mReader.skip(2);
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (mReader.isLineBreak(ch))
|
||||
mReader.beginLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,7 +213,7 @@ XMLTag *XMLParser::parseTag()
|
||||
if (mReader.getEof())
|
||||
syntaxError("Unterminated tag");
|
||||
if (ch == '/') {
|
||||
tag->setEmpty();
|
||||
tag->setTag(EmptyTag);
|
||||
ch = mReader.get();
|
||||
}
|
||||
if (ch != '>')
|
||||
@ -197,7 +236,7 @@ void XMLParser::parseTagBody(XMLNode *parent, XMLTag *startTag)
|
||||
break;
|
||||
else {
|
||||
XMLNode *child = new XMLNode(parent, tag);
|
||||
if (!tag->isEmpty())
|
||||
if (tag->hasContent())
|
||||
parseTagBody(child, tag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag } TagFlag;
|
||||
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag, CDataTag } TagFlag;
|
||||
|
||||
|
||||
class XMLLexer
|
||||
@ -68,14 +68,14 @@ public:
|
||||
|
||||
String &name() { return mName; }
|
||||
|
||||
void setEmpty() { mFlag = EmptyTag; }
|
||||
void setComment() { mFlag = EmptyTag; }
|
||||
void setEndTag() { mFlag = EndTag; }
|
||||
void setTag(TagFlag f) { mFlag = f; }
|
||||
|
||||
bool isEmpty() const { return mFlag == EmptyTag; }
|
||||
bool isEndTag() const { return mFlag == EndTag; }
|
||||
bool isComment() const { return mFlag == CommentTag; }
|
||||
|
||||
bool hasContent() const { return mFlag == Tag; }
|
||||
|
||||
String mName;
|
||||
TagFlag mFlag;
|
||||
AttributeList mAttributeList;
|
||||
@ -152,6 +152,7 @@ public:
|
||||
|
||||
XMLParser(const char *fileName) : mReader(fileName) { }
|
||||
|
||||
void parseStringLiteral(String &val);
|
||||
|
||||
void parseName(String &id);
|
||||
void parseWhiteSpace();
|
||||
|
||||
@ -213,6 +213,7 @@ class Tracer : public Context::Listener {
|
||||
};
|
||||
|
||||
//#define HAVE_GEORGE_TRACE_IT
|
||||
//#define TEST_XML_LOADER
|
||||
|
||||
static void readEvalPrint(FILE *in, World &world)
|
||||
{
|
||||
@ -302,7 +303,7 @@ static void readEvalPrint(FILE *in, World &world)
|
||||
stdOut << '\n';
|
||||
}
|
||||
|
||||
|
||||
//#define HAVE_GEORGE_TRACE_IT
|
||||
|
||||
char * tests[] = {
|
||||
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
|
||||
@ -327,7 +328,7 @@ static void testCompile()
|
||||
Arena a;
|
||||
Parser p(world, a, testScript, widenCString("testCompile"));
|
||||
StmtNode *parsedStatements = p.parseProgram();
|
||||
ICodeGenerator icg(&world, &glob);
|
||||
ICodeGenerator icg(&cx);
|
||||
StmtNode *s = parsedStatements;
|
||||
while (s) {
|
||||
icg.genStmt(s);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user