зеркало из https://github.com/mozilla/pjs.git
Mucking about with operator overlaoding plus initializing global context
- beginning type stuff.
This commit is contained in:
Родитель
c36f967be2
Коммит
63047e7baf
|
@ -498,12 +498,13 @@ static bool generatedBoolean(ExprNode *p)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
if trueBranch OR falseBranch are not null, the sub-expression should generate
|
||||
a conditional branch to the appropriate target. If either branch is NULL, it
|
||||
indicates that the label is immediately forthcoming.
|
||||
*/
|
||||
Register ICodeGenerator::genExpr(ExprNode *p,
|
||||
Result ICodeGenerator::genExpr(ExprNode *p,
|
||||
bool needBoolValueInBranch,
|
||||
Label *trueBranch,
|
||||
Label *falseBranch)
|
||||
|
@ -533,7 +534,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::parentheses:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
ret = genExpr(u->op, needBoolValueInBranch, trueBranch, falseBranch);
|
||||
ret = genExpr(u->op, needBoolValueInBranch, trueBranch, falseBranch).reg;
|
||||
}
|
||||
break;
|
||||
case ExprNode::New:
|
||||
|
@ -545,11 +546,11 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::call :
|
||||
{
|
||||
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
|
||||
Register fn = genExpr(i->op);
|
||||
Register fn = genExpr(i->op).reg;
|
||||
RegisterList args;
|
||||
ExprPairList *p = i->pairs;
|
||||
while (p) {
|
||||
args.push_back(genExpr(p->value));
|
||||
args.push_back(genExpr(p->value).reg);
|
||||
p = p->next;
|
||||
}
|
||||
ret = call(fn, args);
|
||||
|
@ -558,15 +559,15 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::index :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = getElement(base, index);
|
||||
}
|
||||
break;
|
||||
case ExprNode::dot :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
break;
|
||||
|
@ -594,7 +595,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name, ret);
|
||||
|
@ -620,8 +621,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = getElement(base, index);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
|
@ -633,7 +634,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = propertyInc(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
else
|
||||
|
@ -651,8 +652,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = elementInc(base, index);
|
||||
}
|
||||
}
|
||||
|
@ -662,7 +663,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name, ret);
|
||||
|
@ -688,8 +689,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = getElement(base, index);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
|
@ -701,7 +702,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = propertyDec(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
else
|
||||
|
@ -719,8 +720,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = elementInc(base, index);
|
||||
}
|
||||
}
|
||||
|
@ -730,7 +731,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::complement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
Register r = genExpr(u->op);
|
||||
Register r = genExpr(u->op).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r);
|
||||
}
|
||||
break;
|
||||
|
@ -747,15 +748,15 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::bitwiseOr:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1);
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
}
|
||||
break;
|
||||
case ExprNode::assignment:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2);
|
||||
ret = genExpr(b->op2).reg;
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
|
@ -770,14 +771,14 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1);
|
||||
Register index = genExpr(lb->op2);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register index = genExpr(lb->op2).reg;
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
}
|
||||
|
@ -795,7 +796,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::bitwiseOrEquals:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2);
|
||||
ret = genExpr(b->op2).reg;
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
|
@ -818,7 +819,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register v = getProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
|
@ -826,8 +827,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1);
|
||||
Register index = genExpr(lb->op2);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register index = genExpr(lb->op2).reg;
|
||||
Register v = getElement(base, index);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setElement(base, index, ret);
|
||||
|
@ -842,8 +843,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::Instanceof:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1);
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -860,8 +861,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::greaterThanOrEqual:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1);
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r2, r1); // will return reverse case
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -879,8 +880,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::notIdentical:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1);
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -906,12 +907,12 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else {
|
||||
Label *fBranch = getLabel();
|
||||
Register r1 = genExpr(b->op1, true, NULL, fBranch);
|
||||
Register r1 = genExpr(b->op1, true, NULL, fBranch).reg;
|
||||
if (!generatedBoolean(b->op1)) {
|
||||
r1 = test(r1);
|
||||
branchFalse(fBranch, r1);
|
||||
}
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
if (!generatedBoolean(b->op2)) {
|
||||
r2 = test(r2);
|
||||
}
|
||||
|
@ -931,12 +932,12 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else {
|
||||
Label *tBranch = getLabel();
|
||||
Register r1 = genExpr(b->op1, true, tBranch, NULL);
|
||||
Register r1 = genExpr(b->op1, true, tBranch, NULL).reg;
|
||||
if (!generatedBoolean(b->op1)) {
|
||||
r1 = test(r1);
|
||||
branchTrue(tBranch, r1);
|
||||
}
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
if (!generatedBoolean(b->op2)) {
|
||||
r2 = test(r2);
|
||||
}
|
||||
|
@ -953,13 +954,13 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
TernaryExprNode *t = static_cast<TernaryExprNode *>(p);
|
||||
Label *fBranch = getLabel();
|
||||
Label *beyondBranch = getLabel();
|
||||
Register c = genExpr(t->op1, false, NULL, fBranch);
|
||||
Register c = genExpr(t->op1, false, NULL, fBranch).reg;
|
||||
if (!generatedBoolean(t->op1))
|
||||
branchFalse(fBranch, test(c));
|
||||
Register r1 = genExpr(t->op2);
|
||||
Register r1 = genExpr(t->op2).reg;
|
||||
branch(beyondBranch);
|
||||
setLabel(fBranch);
|
||||
Register r2 = genExpr(t->op3);
|
||||
Register r2 = genExpr(t->op3).reg;
|
||||
if (r1 != r2) // FIXME, need a way to specify a dest???
|
||||
move(r1, r2);
|
||||
setLabel(beyondBranch);
|
||||
|
@ -975,7 +976,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
ExprPairList *e = plen->pairs;
|
||||
while (e) {
|
||||
if (e->field && e->value && (e->field->getKind() == ExprNode::identifier))
|
||||
setProperty(ret, (static_cast<IdentifierExprNode *>(e->field))->name, genExpr(e->value));
|
||||
setProperty(ret, (static_cast<IdentifierExprNode *>(e->field))->name, genExpr(e->value).reg);
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
|
@ -986,7 +987,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
NOT_REACHED("Unsupported ExprNode kind");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return Result(ret, Any_Type);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1026,7 +1027,11 @@ void ICodeGenerator::preprocess(StmtNode *p)
|
|||
VariableBinding *v = vs->bindings;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
|
||||
if (v->type->getKind() == ExprNode::identifier)
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name,
|
||||
(static_cast<IdentifierExprNode *>(v->type))->name);
|
||||
else
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
|
@ -1141,12 +1146,12 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
if (v->name && v->initializer) {
|
||||
if (v->name->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register r = genExpr(v->name);
|
||||
Register val = genExpr(v->initializer);
|
||||
Register r = genExpr(v->name).reg;
|
||||
Register val = genExpr(v->initializer).reg;
|
||||
move(r, val);
|
||||
}
|
||||
else {
|
||||
Register val = genExpr(v->initializer);
|
||||
Register val = genExpr(v->initializer).reg;
|
||||
saveName((static_cast<IdentifierExprNode *>(v->name))->name, val);
|
||||
}
|
||||
}
|
||||
|
@ -1159,20 +1164,20 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::expression:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
ret = genExpr(e->expr);
|
||||
ret = genExpr(e->expr).reg;
|
||||
}
|
||||
break;
|
||||
case StmtNode::Throw:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
throwStmt(genExpr(e->expr));
|
||||
throwStmt(genExpr(e->expr).reg);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Return:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
if (e->expr)
|
||||
returnStmt(ret = genExpr(e->expr));
|
||||
returnStmt(ret = genExpr(e->expr).reg);
|
||||
else
|
||||
returnStmt(NotARegister);
|
||||
}
|
||||
|
@ -1181,7 +1186,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
{
|
||||
Label *falseLabel = getLabel();
|
||||
UnaryStmtNode *i = static_cast<UnaryStmtNode *>(p);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel).reg;
|
||||
if (!generatedBoolean(i->expr))
|
||||
branchFalse(falseLabel, test(c));
|
||||
genStmt(i->stmt);
|
||||
|
@ -1193,7 +1198,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
Label *falseLabel = getLabel();
|
||||
Label *beyondLabel = getLabel();
|
||||
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel).reg;
|
||||
if (!generatedBoolean(i->expr))
|
||||
branchFalse(falseLabel, test(c));
|
||||
genStmt(i->stmt);
|
||||
|
@ -1206,7 +1211,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::With:
|
||||
{
|
||||
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
|
||||
Register o = genExpr(w->expr);
|
||||
Register o = genExpr(w->expr).reg;
|
||||
bool withinWith = mWithinWith;
|
||||
mWithinWith = true;
|
||||
beginWith(o);
|
||||
|
@ -1221,7 +1226,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
LabelEntry *e = new LabelEntry(currentLabelSet, getLabel());
|
||||
mLabelStack.push_back(e);
|
||||
SwitchStmtNode *sw = static_cast<SwitchStmtNode *>(p);
|
||||
Register sc = genExpr(sw->expr);
|
||||
Register sc = genExpr(sw->expr).reg;
|
||||
StmtNode *s = sw->statements;
|
||||
// ECMA requires case & default statements to be immediate children of switch
|
||||
// unlike C where they can be arbitrarily deeply nested in other statements.
|
||||
|
@ -1234,7 +1239,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
if (nextCaseLabel)
|
||||
setLabel(nextCaseLabel);
|
||||
nextCaseLabel = getLabel();
|
||||
Register r = genExpr(c->expr);
|
||||
Register r = genExpr(c->expr).reg;
|
||||
Register eq = op(COMPARE_EQ, r, sc);
|
||||
lastBranch = branchFalse(nextCaseLabel, eq);
|
||||
}
|
||||
|
@ -1265,7 +1270,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
setLabel(doBodyTopLabel);
|
||||
genStmt(d->stmt);
|
||||
setLabel(e->continueLabel);
|
||||
Register c = genExpr(d->expr, false, doBodyTopLabel, NULL);
|
||||
Register c = genExpr(d->expr, false, doBodyTopLabel, NULL).reg;
|
||||
if (!generatedBoolean(d->expr))
|
||||
branchTrue(doBodyTopLabel, test(c));
|
||||
setLabel(e->breakLabel);
|
||||
|
@ -1285,7 +1290,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
genStmt(w->stmt);
|
||||
|
||||
setLabel(e->continueLabel);
|
||||
Register c = genExpr(w->expr, false, whileBodyTopLabel, NULL);
|
||||
Register c = genExpr(w->expr, false, whileBodyTopLabel, NULL).reg;
|
||||
if (!generatedBoolean(w->expr))
|
||||
branchTrue(whileBodyTopLabel, test(c));
|
||||
|
||||
|
@ -1310,11 +1315,11 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
|
||||
setLabel(e->continueLabel);
|
||||
if (f->expr3)
|
||||
genExpr(f->expr3);
|
||||
genExpr(f->expr3).reg;
|
||||
|
||||
setLabel(forTestLabel);
|
||||
if (f->expr2) {
|
||||
Register c = genExpr(f->expr2, false, forBlockTop, NULL);
|
||||
Register c = genExpr(f->expr2, false, forBlockTop, NULL).reg;
|
||||
if (!generatedBoolean(f->expr2))
|
||||
branchTrue(forBlockTop, test(c));
|
||||
}
|
||||
|
|
|
@ -105,6 +105,12 @@ namespace ICG {
|
|||
// function/script, adds statements and expressions to it and then
|
||||
// converts it into an ICodeModule, ready for execution.
|
||||
|
||||
struct Result {
|
||||
Result(Register reg, JSTypes::JSType type) : reg(reg), type(type) {}
|
||||
Register reg;
|
||||
JSTypes::JSType type;
|
||||
};
|
||||
|
||||
class ICodeGenerator {
|
||||
private:
|
||||
InstructionStream *iCode;
|
||||
|
@ -187,7 +193,7 @@ namespace ICG {
|
|||
|
||||
ICodeModule *complete();
|
||||
|
||||
Register genExpr(ExprNode *p,
|
||||
Result genExpr(ExprNode *p,
|
||||
bool needBoolValueInBranch = false,
|
||||
Label *trueBranch = NULL,
|
||||
Label *falseBranch = NULL);
|
||||
|
@ -201,6 +207,9 @@ namespace ICG {
|
|||
{ iCode->push_back(new Throw(r)); }
|
||||
|
||||
Register allocateVariable(const StringAtom& name);
|
||||
Register allocateVariable(const StringAtom& name, const StringAtom& /*type */)
|
||||
{ return allocateVariable(name); }
|
||||
|
||||
Register findVariable(const StringAtom& name)
|
||||
{ VariableList::iterator i = variableList->find(name);
|
||||
return (i == variableList->end()) ? NotARegister : (*i).second; }
|
||||
|
|
|
@ -349,11 +349,14 @@ public:
|
|||
BinaryOperator(const JSType *t1, const JSType *t2, JSBinaryOperator *function) :
|
||||
t1(t1), t2(t2), function(function) { }
|
||||
|
||||
BinaryOperator(const JSType *t1, const JSType *t2, JSFunction *function) :
|
||||
t1(t1), t2(t2), function(function) { }
|
||||
|
||||
static BinaryOp mapICodeOp(ICodeOp op);
|
||||
|
||||
const JSType *t1;
|
||||
const JSType *t2;
|
||||
JSBinaryOperator *function;
|
||||
JSFunction *function;
|
||||
|
||||
};
|
||||
|
||||
|
@ -389,28 +392,74 @@ typedef std::vector<BinaryOperator *> BinaryOperatorList;
|
|||
BinaryOperatorList binaryOperators[15];
|
||||
|
||||
|
||||
JSBinaryOperator::JSBinaryCode defaultFunction[] = {
|
||||
add_Default,
|
||||
subtract_Default,
|
||||
multiply_Default,
|
||||
divide_Default,
|
||||
remainder_Default,
|
||||
shiftLeft_Default,
|
||||
shiftRight_Default,
|
||||
UshiftRight_Default,
|
||||
or_Default,
|
||||
xor_Default,
|
||||
and_Default,
|
||||
less_Default,
|
||||
lessEqual_Default,
|
||||
equal_Default,
|
||||
identical_Default
|
||||
};
|
||||
|
||||
class InitBinaryOperators {
|
||||
|
||||
public:
|
||||
InitBinaryOperators() {
|
||||
binaryOperators[BinaryOperator::Add].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(add_Default)));
|
||||
binaryOperators[BinaryOperator::Subtract].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(subtract_Default)));
|
||||
binaryOperators[BinaryOperator::Multiply].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(multiply_Default)));
|
||||
binaryOperators[BinaryOperator::Divide].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(divide_Default)));
|
||||
binaryOperators[BinaryOperator::Remainder].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(remainder_Default)));
|
||||
binaryOperators[BinaryOperator::LeftShift].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(shiftLeft_Default)));
|
||||
binaryOperators[BinaryOperator::RightShift].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(shiftRight_Default)));
|
||||
binaryOperators[BinaryOperator::LogicalRightShift].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(UshiftRight_Default)));
|
||||
binaryOperators[BinaryOperator::BitwiseOr].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(or_Default)));
|
||||
binaryOperators[BinaryOperator::BitwiseXor].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(xor_Default)));
|
||||
binaryOperators[BinaryOperator::BitwiseAnd].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(and_Default)));
|
||||
binaryOperators[BinaryOperator::Less].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(less_Default)));
|
||||
binaryOperators[BinaryOperator::LessEqual].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(lessEqual_Default)));
|
||||
binaryOperators[BinaryOperator::Equal].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(equal_Default)));
|
||||
binaryOperators[BinaryOperator::Identical].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(identical_Default)));
|
||||
}
|
||||
|
||||
for (int i = BinaryOperator::Add; i <= BinaryOperator::Identical; i++)
|
||||
binaryOperators[i].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(defaultFunction[i])));
|
||||
}
|
||||
} initializer = InitBinaryOperators();
|
||||
|
||||
static JSValue defineAdd(const JSValues& argv)
|
||||
{
|
||||
// should be three args, first two are types, third is a function.
|
||||
ASSERT(argv[0].isType());
|
||||
ASSERT(argv[1].isType());
|
||||
ASSERT(argv[2].isFunction());
|
||||
|
||||
// XXX need to prove that argv[2].function takes T1 and T2 as args and returns Boolean for the relational operators ?
|
||||
|
||||
// stdOut << *argv[2].function->getICode();
|
||||
binaryOperators[BinaryOperator::Add].push_back(new BinaryOperator(argv[0].type, argv[1].type, argv[2].function));
|
||||
|
||||
return kUndefinedValue;
|
||||
}
|
||||
|
||||
void Context::initContext()
|
||||
{
|
||||
// predefine the predefined types;
|
||||
|
||||
mGlobal->defineVariable(widenCString("any"), JSValue(&Any_Type));
|
||||
mGlobal->defineVariable(widenCString("Integer"), JSValue(&Integer_Type));
|
||||
mGlobal->defineVariable(widenCString("Number"), JSValue(&Number_Type));
|
||||
mGlobal->defineVariable(widenCString("Character"), JSValue(&Character_Type));
|
||||
mGlobal->defineVariable(widenCString("String"), JSValue(&String_Type));
|
||||
mGlobal->defineVariable(widenCString("Function"), JSValue(&Function_Type));
|
||||
mGlobal->defineVariable(widenCString("Array"), JSValue(&Array_Type));
|
||||
mGlobal->defineVariable(widenCString("Type"), JSValue(&Type_Type));
|
||||
mGlobal->defineVariable(widenCString("Boolean"), JSValue(&Boolean_Type));
|
||||
mGlobal->defineVariable(widenCString("Null"), JSValue(&Null_Type));
|
||||
mGlobal->defineVariable(widenCString("Void"), JSValue(&Void_Type));
|
||||
mGlobal->defineVariable(widenCString("none"), JSValue(&None_Type));
|
||||
|
||||
|
||||
// hack - the following should be available only after importing the 'Operators' package
|
||||
// (hmm, how will that work - the import needs to connect the functions into this mechanism
|
||||
// do we watch for the specific package name???)
|
||||
|
||||
StringAtom& name = mWorld.identifiers[widenCString("defineAdd")];
|
||||
mGlobal->defineNativeFunction(name, defineAdd);
|
||||
}
|
||||
|
||||
static const JSValue findBinaryOverride(JSValue &operand1, JSValue &operand2, BinaryOperator::BinaryOp op)
|
||||
{
|
||||
|
|
|
@ -37,9 +37,10 @@ namespace Interpreter {
|
|||
struct Linkage;
|
||||
|
||||
class Context : public gc_base {
|
||||
void initContext();
|
||||
public:
|
||||
explicit Context(World& world, JSScope* aGlobal)
|
||||
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0) {}
|
||||
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0) { initContext(); }
|
||||
|
||||
World& getWorld() { return mWorld; }
|
||||
JSScope* getGlobalObject() { return mGlobal; }
|
||||
|
|
|
@ -189,7 +189,7 @@ Formatter& operator<<(Formatter& f, const JSValue& value)
|
|||
printFormat(f, "Function @ 0x%08X", value.object);
|
||||
break;
|
||||
case JSValue::string_tag:
|
||||
f << "\"" << *value.string << "\"";
|
||||
f << *value.string;
|
||||
break;
|
||||
case JSValue::boolean_tag:
|
||||
f << ((value.boolean) ? "true" : "false");
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace JSTypes {
|
|||
JSArray* array;
|
||||
JSFunction *function;
|
||||
JSString *string;
|
||||
JSType *type;
|
||||
const JSType *type;
|
||||
bool boolean;
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ namespace JSTypes {
|
|||
explicit JSValue(JSFunction* function) : function(function), tag(function_tag) {}
|
||||
explicit JSValue(JSString* string) : string(string), tag(string_tag) {}
|
||||
explicit JSValue(bool boolean) : boolean(boolean), tag(boolean_tag) {}
|
||||
explicit JSValue(JSType* type) : type(type), tag(type_tag) {}
|
||||
explicit JSValue(const JSType* type) : type(type), tag(type_tag) {}
|
||||
|
||||
int32& operator=(int32 i32) { return (tag = i32_tag, this->i32 = i32); }
|
||||
uint32& operator=(uint32 u32) { return (tag = u32_tag, this->u32 = u32); }
|
||||
|
@ -116,7 +116,7 @@ namespace JSTypes {
|
|||
JSFunction*& operator=(JSFunction* function) { return (tag = function_tag, this->function = function); }
|
||||
JSString*& operator=(JSString* string) { return (tag = string_tag, this->string = string); }
|
||||
bool& operator=(bool boolean) { return (tag = boolean_tag, this->boolean = boolean); }
|
||||
JSType*& operator=(JSType* type) { return (tag = type_tag, this->type = type); }
|
||||
const JSType*& operator=(const JSType* type) { return (tag = type_tag, this->type = type); }
|
||||
|
||||
bool isFunction() const { return (tag == function_tag); }
|
||||
bool isObject() const { return ((tag == object_tag) || (tag == function_tag) || (tag == array_tag)); }
|
||||
|
@ -129,6 +129,7 @@ namespace JSTypes {
|
|||
bool isUndefined() const { return (tag == undefined_tag); }
|
||||
bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); }
|
||||
bool isNaN() const;
|
||||
bool isType() const { return (tag == type_tag); }
|
||||
|
||||
JSValue toString() const { return (isString() ? *this : valueToString(*this)); }
|
||||
JSValue toNumber() const { return (isNumber() ? *this : valueToNumber(*this)); }
|
||||
|
@ -146,7 +147,7 @@ namespace JSTypes {
|
|||
static JSValue valueToBoolean(const JSValue& value);
|
||||
|
||||
|
||||
const JSType *getType() const;
|
||||
const JSType *getType() const; // map from tag type to JS2 type
|
||||
|
||||
int operator==(const JSValue& value) const;
|
||||
};
|
||||
|
|
|
@ -498,12 +498,13 @@ static bool generatedBoolean(ExprNode *p)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
if trueBranch OR falseBranch are not null, the sub-expression should generate
|
||||
a conditional branch to the appropriate target. If either branch is NULL, it
|
||||
indicates that the label is immediately forthcoming.
|
||||
*/
|
||||
Register ICodeGenerator::genExpr(ExprNode *p,
|
||||
Result ICodeGenerator::genExpr(ExprNode *p,
|
||||
bool needBoolValueInBranch,
|
||||
Label *trueBranch,
|
||||
Label *falseBranch)
|
||||
|
@ -533,7 +534,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::parentheses:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
ret = genExpr(u->op, needBoolValueInBranch, trueBranch, falseBranch);
|
||||
ret = genExpr(u->op, needBoolValueInBranch, trueBranch, falseBranch).reg;
|
||||
}
|
||||
break;
|
||||
case ExprNode::New:
|
||||
|
@ -545,11 +546,11 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::call :
|
||||
{
|
||||
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
|
||||
Register fn = genExpr(i->op);
|
||||
Register fn = genExpr(i->op).reg;
|
||||
RegisterList args;
|
||||
ExprPairList *p = i->pairs;
|
||||
while (p) {
|
||||
args.push_back(genExpr(p->value));
|
||||
args.push_back(genExpr(p->value).reg);
|
||||
p = p->next;
|
||||
}
|
||||
ret = call(fn, args);
|
||||
|
@ -558,15 +559,15 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::index :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = getElement(base, index);
|
||||
}
|
||||
break;
|
||||
case ExprNode::dot :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
break;
|
||||
|
@ -594,7 +595,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name, ret);
|
||||
|
@ -620,8 +621,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = getElement(base, index);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
|
@ -633,7 +634,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = propertyInc(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
else
|
||||
|
@ -651,8 +652,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = elementInc(base, index);
|
||||
}
|
||||
}
|
||||
|
@ -662,7 +663,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name, ret);
|
||||
|
@ -688,8 +689,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = getElement(base, index);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
|
@ -701,7 +702,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
ret = propertyDec(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
else
|
||||
|
@ -719,8 +720,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
ret = elementInc(base, index);
|
||||
}
|
||||
}
|
||||
|
@ -730,7 +731,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::complement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
Register r = genExpr(u->op);
|
||||
Register r = genExpr(u->op).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r);
|
||||
}
|
||||
break;
|
||||
|
@ -747,15 +748,15 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::bitwiseOr:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1);
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
}
|
||||
break;
|
||||
case ExprNode::assignment:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2);
|
||||
ret = genExpr(b->op2).reg;
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
|
@ -770,14 +771,14 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1);
|
||||
Register index = genExpr(lb->op2);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register index = genExpr(lb->op2).reg;
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
}
|
||||
|
@ -795,7 +796,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::bitwiseOrEquals:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2);
|
||||
ret = genExpr(b->op2).reg;
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
|
@ -818,7 +819,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register v = getProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
|
@ -826,8 +827,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1);
|
||||
Register index = genExpr(lb->op2);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register index = genExpr(lb->op2).reg;
|
||||
Register v = getElement(base, index);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setElement(base, index, ret);
|
||||
|
@ -842,8 +843,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::Instanceof:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1);
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -860,8 +861,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::greaterThanOrEqual:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1);
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r2, r1); // will return reverse case
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -879,8 +880,8 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::notIdentical:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1);
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -906,12 +907,12 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else {
|
||||
Label *fBranch = getLabel();
|
||||
Register r1 = genExpr(b->op1, true, NULL, fBranch);
|
||||
Register r1 = genExpr(b->op1, true, NULL, fBranch).reg;
|
||||
if (!generatedBoolean(b->op1)) {
|
||||
r1 = test(r1);
|
||||
branchFalse(fBranch, r1);
|
||||
}
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
if (!generatedBoolean(b->op2)) {
|
||||
r2 = test(r2);
|
||||
}
|
||||
|
@ -931,12 +932,12 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else {
|
||||
Label *tBranch = getLabel();
|
||||
Register r1 = genExpr(b->op1, true, tBranch, NULL);
|
||||
Register r1 = genExpr(b->op1, true, tBranch, NULL).reg;
|
||||
if (!generatedBoolean(b->op1)) {
|
||||
r1 = test(r1);
|
||||
branchTrue(tBranch, r1);
|
||||
}
|
||||
Register r2 = genExpr(b->op2);
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
if (!generatedBoolean(b->op2)) {
|
||||
r2 = test(r2);
|
||||
}
|
||||
|
@ -953,13 +954,13 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
TernaryExprNode *t = static_cast<TernaryExprNode *>(p);
|
||||
Label *fBranch = getLabel();
|
||||
Label *beyondBranch = getLabel();
|
||||
Register c = genExpr(t->op1, false, NULL, fBranch);
|
||||
Register c = genExpr(t->op1, false, NULL, fBranch).reg;
|
||||
if (!generatedBoolean(t->op1))
|
||||
branchFalse(fBranch, test(c));
|
||||
Register r1 = genExpr(t->op2);
|
||||
Register r1 = genExpr(t->op2).reg;
|
||||
branch(beyondBranch);
|
||||
setLabel(fBranch);
|
||||
Register r2 = genExpr(t->op3);
|
||||
Register r2 = genExpr(t->op3).reg;
|
||||
if (r1 != r2) // FIXME, need a way to specify a dest???
|
||||
move(r1, r2);
|
||||
setLabel(beyondBranch);
|
||||
|
@ -975,7 +976,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
ExprPairList *e = plen->pairs;
|
||||
while (e) {
|
||||
if (e->field && e->value && (e->field->getKind() == ExprNode::identifier))
|
||||
setProperty(ret, (static_cast<IdentifierExprNode *>(e->field))->name, genExpr(e->value));
|
||||
setProperty(ret, (static_cast<IdentifierExprNode *>(e->field))->name, genExpr(e->value).reg);
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
|
@ -986,7 +987,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
NOT_REACHED("Unsupported ExprNode kind");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return Result(ret, Any_Type);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1026,7 +1027,11 @@ void ICodeGenerator::preprocess(StmtNode *p)
|
|||
VariableBinding *v = vs->bindings;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
|
||||
if (v->type->getKind() == ExprNode::identifier)
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name,
|
||||
(static_cast<IdentifierExprNode *>(v->type))->name);
|
||||
else
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
|
@ -1141,12 +1146,12 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
if (v->name && v->initializer) {
|
||||
if (v->name->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register r = genExpr(v->name);
|
||||
Register val = genExpr(v->initializer);
|
||||
Register r = genExpr(v->name).reg;
|
||||
Register val = genExpr(v->initializer).reg;
|
||||
move(r, val);
|
||||
}
|
||||
else {
|
||||
Register val = genExpr(v->initializer);
|
||||
Register val = genExpr(v->initializer).reg;
|
||||
saveName((static_cast<IdentifierExprNode *>(v->name))->name, val);
|
||||
}
|
||||
}
|
||||
|
@ -1159,20 +1164,20 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::expression:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
ret = genExpr(e->expr);
|
||||
ret = genExpr(e->expr).reg;
|
||||
}
|
||||
break;
|
||||
case StmtNode::Throw:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
throwStmt(genExpr(e->expr));
|
||||
throwStmt(genExpr(e->expr).reg);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Return:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
if (e->expr)
|
||||
returnStmt(ret = genExpr(e->expr));
|
||||
returnStmt(ret = genExpr(e->expr).reg);
|
||||
else
|
||||
returnStmt(NotARegister);
|
||||
}
|
||||
|
@ -1181,7 +1186,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
{
|
||||
Label *falseLabel = getLabel();
|
||||
UnaryStmtNode *i = static_cast<UnaryStmtNode *>(p);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel).reg;
|
||||
if (!generatedBoolean(i->expr))
|
||||
branchFalse(falseLabel, test(c));
|
||||
genStmt(i->stmt);
|
||||
|
@ -1193,7 +1198,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
Label *falseLabel = getLabel();
|
||||
Label *beyondLabel = getLabel();
|
||||
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel).reg;
|
||||
if (!generatedBoolean(i->expr))
|
||||
branchFalse(falseLabel, test(c));
|
||||
genStmt(i->stmt);
|
||||
|
@ -1206,7 +1211,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::With:
|
||||
{
|
||||
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
|
||||
Register o = genExpr(w->expr);
|
||||
Register o = genExpr(w->expr).reg;
|
||||
bool withinWith = mWithinWith;
|
||||
mWithinWith = true;
|
||||
beginWith(o);
|
||||
|
@ -1221,7 +1226,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
LabelEntry *e = new LabelEntry(currentLabelSet, getLabel());
|
||||
mLabelStack.push_back(e);
|
||||
SwitchStmtNode *sw = static_cast<SwitchStmtNode *>(p);
|
||||
Register sc = genExpr(sw->expr);
|
||||
Register sc = genExpr(sw->expr).reg;
|
||||
StmtNode *s = sw->statements;
|
||||
// ECMA requires case & default statements to be immediate children of switch
|
||||
// unlike C where they can be arbitrarily deeply nested in other statements.
|
||||
|
@ -1234,7 +1239,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
if (nextCaseLabel)
|
||||
setLabel(nextCaseLabel);
|
||||
nextCaseLabel = getLabel();
|
||||
Register r = genExpr(c->expr);
|
||||
Register r = genExpr(c->expr).reg;
|
||||
Register eq = op(COMPARE_EQ, r, sc);
|
||||
lastBranch = branchFalse(nextCaseLabel, eq);
|
||||
}
|
||||
|
@ -1265,7 +1270,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
setLabel(doBodyTopLabel);
|
||||
genStmt(d->stmt);
|
||||
setLabel(e->continueLabel);
|
||||
Register c = genExpr(d->expr, false, doBodyTopLabel, NULL);
|
||||
Register c = genExpr(d->expr, false, doBodyTopLabel, NULL).reg;
|
||||
if (!generatedBoolean(d->expr))
|
||||
branchTrue(doBodyTopLabel, test(c));
|
||||
setLabel(e->breakLabel);
|
||||
|
@ -1285,7 +1290,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
genStmt(w->stmt);
|
||||
|
||||
setLabel(e->continueLabel);
|
||||
Register c = genExpr(w->expr, false, whileBodyTopLabel, NULL);
|
||||
Register c = genExpr(w->expr, false, whileBodyTopLabel, NULL).reg;
|
||||
if (!generatedBoolean(w->expr))
|
||||
branchTrue(whileBodyTopLabel, test(c));
|
||||
|
||||
|
@ -1310,11 +1315,11 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
|
||||
setLabel(e->continueLabel);
|
||||
if (f->expr3)
|
||||
genExpr(f->expr3);
|
||||
genExpr(f->expr3).reg;
|
||||
|
||||
setLabel(forTestLabel);
|
||||
if (f->expr2) {
|
||||
Register c = genExpr(f->expr2, false, forBlockTop, NULL);
|
||||
Register c = genExpr(f->expr2, false, forBlockTop, NULL).reg;
|
||||
if (!generatedBoolean(f->expr2))
|
||||
branchTrue(forBlockTop, test(c));
|
||||
}
|
||||
|
|
|
@ -105,6 +105,12 @@ namespace ICG {
|
|||
// function/script, adds statements and expressions to it and then
|
||||
// converts it into an ICodeModule, ready for execution.
|
||||
|
||||
struct Result {
|
||||
Result(Register reg, JSTypes::JSType type) : reg(reg), type(type) {}
|
||||
Register reg;
|
||||
JSTypes::JSType type;
|
||||
};
|
||||
|
||||
class ICodeGenerator {
|
||||
private:
|
||||
InstructionStream *iCode;
|
||||
|
@ -187,7 +193,7 @@ namespace ICG {
|
|||
|
||||
ICodeModule *complete();
|
||||
|
||||
Register genExpr(ExprNode *p,
|
||||
Result genExpr(ExprNode *p,
|
||||
bool needBoolValueInBranch = false,
|
||||
Label *trueBranch = NULL,
|
||||
Label *falseBranch = NULL);
|
||||
|
@ -201,6 +207,9 @@ namespace ICG {
|
|||
{ iCode->push_back(new Throw(r)); }
|
||||
|
||||
Register allocateVariable(const StringAtom& name);
|
||||
Register allocateVariable(const StringAtom& name, const StringAtom& /*type */)
|
||||
{ return allocateVariable(name); }
|
||||
|
||||
Register findVariable(const StringAtom& name)
|
||||
{ VariableList::iterator i = variableList->find(name);
|
||||
return (i == variableList->end()) ? NotARegister : (*i).second; }
|
||||
|
|
|
@ -349,11 +349,14 @@ public:
|
|||
BinaryOperator(const JSType *t1, const JSType *t2, JSBinaryOperator *function) :
|
||||
t1(t1), t2(t2), function(function) { }
|
||||
|
||||
BinaryOperator(const JSType *t1, const JSType *t2, JSFunction *function) :
|
||||
t1(t1), t2(t2), function(function) { }
|
||||
|
||||
static BinaryOp mapICodeOp(ICodeOp op);
|
||||
|
||||
const JSType *t1;
|
||||
const JSType *t2;
|
||||
JSBinaryOperator *function;
|
||||
JSFunction *function;
|
||||
|
||||
};
|
||||
|
||||
|
@ -389,28 +392,74 @@ typedef std::vector<BinaryOperator *> BinaryOperatorList;
|
|||
BinaryOperatorList binaryOperators[15];
|
||||
|
||||
|
||||
JSBinaryOperator::JSBinaryCode defaultFunction[] = {
|
||||
add_Default,
|
||||
subtract_Default,
|
||||
multiply_Default,
|
||||
divide_Default,
|
||||
remainder_Default,
|
||||
shiftLeft_Default,
|
||||
shiftRight_Default,
|
||||
UshiftRight_Default,
|
||||
or_Default,
|
||||
xor_Default,
|
||||
and_Default,
|
||||
less_Default,
|
||||
lessEqual_Default,
|
||||
equal_Default,
|
||||
identical_Default
|
||||
};
|
||||
|
||||
class InitBinaryOperators {
|
||||
|
||||
public:
|
||||
InitBinaryOperators() {
|
||||
binaryOperators[BinaryOperator::Add].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(add_Default)));
|
||||
binaryOperators[BinaryOperator::Subtract].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(subtract_Default)));
|
||||
binaryOperators[BinaryOperator::Multiply].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(multiply_Default)));
|
||||
binaryOperators[BinaryOperator::Divide].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(divide_Default)));
|
||||
binaryOperators[BinaryOperator::Remainder].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(remainder_Default)));
|
||||
binaryOperators[BinaryOperator::LeftShift].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(shiftLeft_Default)));
|
||||
binaryOperators[BinaryOperator::RightShift].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(shiftRight_Default)));
|
||||
binaryOperators[BinaryOperator::LogicalRightShift].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(UshiftRight_Default)));
|
||||
binaryOperators[BinaryOperator::BitwiseOr].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(or_Default)));
|
||||
binaryOperators[BinaryOperator::BitwiseXor].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(xor_Default)));
|
||||
binaryOperators[BinaryOperator::BitwiseAnd].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(and_Default)));
|
||||
binaryOperators[BinaryOperator::Less].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(less_Default)));
|
||||
binaryOperators[BinaryOperator::LessEqual].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(lessEqual_Default)));
|
||||
binaryOperators[BinaryOperator::Equal].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(equal_Default)));
|
||||
binaryOperators[BinaryOperator::Identical].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(identical_Default)));
|
||||
}
|
||||
|
||||
for (int i = BinaryOperator::Add; i <= BinaryOperator::Identical; i++)
|
||||
binaryOperators[i].push_back(new BinaryOperator(&Any_Type, &Any_Type, new JSBinaryOperator(defaultFunction[i])));
|
||||
}
|
||||
} initializer = InitBinaryOperators();
|
||||
|
||||
static JSValue defineAdd(const JSValues& argv)
|
||||
{
|
||||
// should be three args, first two are types, third is a function.
|
||||
ASSERT(argv[0].isType());
|
||||
ASSERT(argv[1].isType());
|
||||
ASSERT(argv[2].isFunction());
|
||||
|
||||
// XXX need to prove that argv[2].function takes T1 and T2 as args and returns Boolean for the relational operators ?
|
||||
|
||||
// stdOut << *argv[2].function->getICode();
|
||||
binaryOperators[BinaryOperator::Add].push_back(new BinaryOperator(argv[0].type, argv[1].type, argv[2].function));
|
||||
|
||||
return kUndefinedValue;
|
||||
}
|
||||
|
||||
void Context::initContext()
|
||||
{
|
||||
// predefine the predefined types;
|
||||
|
||||
mGlobal->defineVariable(widenCString("any"), JSValue(&Any_Type));
|
||||
mGlobal->defineVariable(widenCString("Integer"), JSValue(&Integer_Type));
|
||||
mGlobal->defineVariable(widenCString("Number"), JSValue(&Number_Type));
|
||||
mGlobal->defineVariable(widenCString("Character"), JSValue(&Character_Type));
|
||||
mGlobal->defineVariable(widenCString("String"), JSValue(&String_Type));
|
||||
mGlobal->defineVariable(widenCString("Function"), JSValue(&Function_Type));
|
||||
mGlobal->defineVariable(widenCString("Array"), JSValue(&Array_Type));
|
||||
mGlobal->defineVariable(widenCString("Type"), JSValue(&Type_Type));
|
||||
mGlobal->defineVariable(widenCString("Boolean"), JSValue(&Boolean_Type));
|
||||
mGlobal->defineVariable(widenCString("Null"), JSValue(&Null_Type));
|
||||
mGlobal->defineVariable(widenCString("Void"), JSValue(&Void_Type));
|
||||
mGlobal->defineVariable(widenCString("none"), JSValue(&None_Type));
|
||||
|
||||
|
||||
// hack - the following should be available only after importing the 'Operators' package
|
||||
// (hmm, how will that work - the import needs to connect the functions into this mechanism
|
||||
// do we watch for the specific package name???)
|
||||
|
||||
StringAtom& name = mWorld.identifiers[widenCString("defineAdd")];
|
||||
mGlobal->defineNativeFunction(name, defineAdd);
|
||||
}
|
||||
|
||||
static const JSValue findBinaryOverride(JSValue &operand1, JSValue &operand2, BinaryOperator::BinaryOp op)
|
||||
{
|
||||
|
|
|
@ -37,9 +37,10 @@ namespace Interpreter {
|
|||
struct Linkage;
|
||||
|
||||
class Context : public gc_base {
|
||||
void initContext();
|
||||
public:
|
||||
explicit Context(World& world, JSScope* aGlobal)
|
||||
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0) {}
|
||||
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0) { initContext(); }
|
||||
|
||||
World& getWorld() { return mWorld; }
|
||||
JSScope* getGlobalObject() { return mGlobal; }
|
||||
|
|
|
@ -189,7 +189,7 @@ Formatter& operator<<(Formatter& f, const JSValue& value)
|
|||
printFormat(f, "Function @ 0x%08X", value.object);
|
||||
break;
|
||||
case JSValue::string_tag:
|
||||
f << "\"" << *value.string << "\"";
|
||||
f << *value.string;
|
||||
break;
|
||||
case JSValue::boolean_tag:
|
||||
f << ((value.boolean) ? "true" : "false");
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace JSTypes {
|
|||
JSArray* array;
|
||||
JSFunction *function;
|
||||
JSString *string;
|
||||
JSType *type;
|
||||
const JSType *type;
|
||||
bool boolean;
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ namespace JSTypes {
|
|||
explicit JSValue(JSFunction* function) : function(function), tag(function_tag) {}
|
||||
explicit JSValue(JSString* string) : string(string), tag(string_tag) {}
|
||||
explicit JSValue(bool boolean) : boolean(boolean), tag(boolean_tag) {}
|
||||
explicit JSValue(JSType* type) : type(type), tag(type_tag) {}
|
||||
explicit JSValue(const JSType* type) : type(type), tag(type_tag) {}
|
||||
|
||||
int32& operator=(int32 i32) { return (tag = i32_tag, this->i32 = i32); }
|
||||
uint32& operator=(uint32 u32) { return (tag = u32_tag, this->u32 = u32); }
|
||||
|
@ -116,7 +116,7 @@ namespace JSTypes {
|
|||
JSFunction*& operator=(JSFunction* function) { return (tag = function_tag, this->function = function); }
|
||||
JSString*& operator=(JSString* string) { return (tag = string_tag, this->string = string); }
|
||||
bool& operator=(bool boolean) { return (tag = boolean_tag, this->boolean = boolean); }
|
||||
JSType*& operator=(JSType* type) { return (tag = type_tag, this->type = type); }
|
||||
const JSType*& operator=(const JSType* type) { return (tag = type_tag, this->type = type); }
|
||||
|
||||
bool isFunction() const { return (tag == function_tag); }
|
||||
bool isObject() const { return ((tag == object_tag) || (tag == function_tag) || (tag == array_tag)); }
|
||||
|
@ -129,6 +129,7 @@ namespace JSTypes {
|
|||
bool isUndefined() const { return (tag == undefined_tag); }
|
||||
bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); }
|
||||
bool isNaN() const;
|
||||
bool isType() const { return (tag == type_tag); }
|
||||
|
||||
JSValue toString() const { return (isString() ? *this : valueToString(*this)); }
|
||||
JSValue toNumber() const { return (isNumber() ? *this : valueToNumber(*this)); }
|
||||
|
@ -146,7 +147,7 @@ namespace JSTypes {
|
|||
static JSValue valueToBoolean(const JSValue& value);
|
||||
|
||||
|
||||
const JSType *getType() const;
|
||||
const JSType *getType() const; // map from tag type to JS2 type
|
||||
|
||||
int operator==(const JSValue& value) const;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче