Added labelled statements, fixed some VC++'isms

This commit is contained in:
rogerl%netscape.com 2000-04-21 00:37:51 +00:00
parent 0aa794713c
commit 8c81be5a55
8 changed files with 284 additions and 96 deletions

View File

@ -59,6 +59,7 @@ namespace ICG {
{
#ifdef DEBUG
ASSERT(stitcher.empty());
ASSERT(statementLabels.empty());
for (LabelList::iterator i = labels.begin();
i != labels.end(); i++) {
ASSERT((*i)->mBase == iCode);
@ -207,6 +208,26 @@ namespace ICG {
iCode->push_back(instr);
}
void ICodeGenerator::branchNotConditional(Label *label, Register condition)
{
ICodeOp branchOp = getBranchOp();
if (branchOp == NOP) {
// XXXX emit convert to boolean / Test / ...
branchOp = BRANCH_NE;
}
switch (branchOp) {
case BRANCH_EQ : branchOp = BRANCH_NE; break;
case BRANCH_GE : branchOp = BRANCH_LT; break;
case BRANCH_GT : branchOp = BRANCH_LE; break;
case BRANCH_LE : branchOp = BRANCH_GT; break;
case BRANCH_LT : branchOp = BRANCH_GE; break;
case BRANCH_NE : branchOp = BRANCH_EQ; break;
default : NOT_REACHED("Expected a branch op"); break;
}
GenericBranch *instr = new GenericBranch(branchOp, label, condition);
iCode->push_back(instr);
}
/********************************************************************/
Label *ICodeGenerator::getLabel()
@ -262,7 +283,7 @@ namespace ICG {
branch(whileConditionTop);
// save off the current stream while we gen code for the condition
stitcher.push_back(new WhileCodeState(whileConditionTop,
addStitcher(new WhileCodeState(whileConditionTop,
whileBlockStart, this));
iCode = new InstructionStream();
@ -314,7 +335,7 @@ namespace ICG {
branch(forCondition);
stitcher.push_back(ics);
addStitcher(ics);
// begin the stream for collecting the condition expression
iCode = new InstructionStream();
@ -383,7 +404,7 @@ namespace ICG {
Label *doCondition = getLabel();
setLabel(doBlock);
stitcher.push_back(new DoCodeState(doBlock, doCondition, this));
addStitcher(new DoCodeState(doBlock, doCondition, this));
iCode = new InstructionStream();
}
@ -430,7 +451,7 @@ namespace ICG {
InstructionStream *x = new InstructionStream();
SwitchCodeState *ics = new SwitchCodeState(control, this);
ics->swapStream(x);
stitcher.push_back(ics);
addStitcher(ics);
}
void ICodeGenerator::endCaseCondition(Register expression)
@ -448,7 +469,7 @@ namespace ICG {
resetTopRegister();
}
void ICodeGenerator::beginCaseStatement()
void ICodeGenerator::beginCaseStatement(uint32 pos)
{
SwitchCodeState *ics =
static_cast<SwitchCodeState *>(stitcher.back());
@ -468,7 +489,7 @@ namespace ICG {
resetTopRegister();
}
void ICodeGenerator::beginDefaultStatement()
void ICodeGenerator::beginDefaultStatement(uint32 pos)
{
SwitchCodeState *ics =
static_cast<SwitchCodeState *>(stitcher.back());
@ -525,10 +546,9 @@ namespace ICG {
{
Label *elseLabel = getLabel();
stitcher.push_back(new IfCodeState(elseLabel, NULL, this));
addStitcher(new IfCodeState(elseLabel, NULL, this));
Register notCond = op(NOT, condition);
branchConditional(elseLabel, notCond);
branchNotConditional(elseLabel, condition);
resetTopRegister();
}
@ -563,7 +583,7 @@ namespace ICG {
/************************************************************************/
void ICodeGenerator::breakStatement()
void ICodeGenerator::breakStatement(uint32 pos)
{
for (std::vector<ICodeState *>::reverse_iterator p =
stitcher.rbegin(); p != stitcher.rend(); p++) {
@ -583,7 +603,30 @@ namespace ICG {
NOT_REACHED("no break target available");
}
void ICodeGenerator::continueStatement()
void ICodeGenerator::breakStatement(uint32 pos, const StringAtom &label)
{
uint32 statementLabelCeiling = statementLabels.size();
for (std::vector<ICodeState *>::reverse_iterator p =
stitcher.rbegin(); p != stitcher.rend(); p++) {
for (std::vector<const StringAtom *>::iterator lbl =
statementLabels.begin() + (*p)->statementLabelBase;
lbl != statementLabels.begin() + statementLabelCeiling;
lbl++) {
if ((*lbl) == &label) {
if ((*p)->breakLabel == NULL)
(*p)->breakLabel = getLabel();
branch((*p)->breakLabel);
return;
}
}
statementLabelCeiling = (*p)->statementLabelBase;
}
NOT_REACHED("no break target available");
}
void ICodeGenerator::continueStatement(uint32 pos)
{
for (std::vector<ICodeState *>::reverse_iterator p =
stitcher.rbegin(); p != stitcher.rend(); p++) {
@ -602,7 +645,32 @@ namespace ICG {
NOT_REACHED("no continue target available");
}
Formatter& ICodeGenerator::print(Formatter& f)
void ICodeGenerator::continueStatement(uint32 pos, const StringAtom &label)
{
uint32 statementLabelCeiling = statementLabels.size();
for (std::vector<ICodeState *>::reverse_iterator p =
stitcher.rbegin(); p != stitcher.rend(); p++) {
for (std::vector<const StringAtom *>::iterator lbl =
statementLabels.begin() + (*p)->statementLabelBase;
lbl != statementLabels.begin() + statementLabelCeiling;
lbl++) {
if ((*lbl) == &label) {
if ((*p)->continueLabel == NULL)
(*p)->continueLabel = getLabel();
branch((*p)->continueLabel);
return;
}
}
statementLabelCeiling = (*p)->statementLabelBase;
}
NOT_REACHED("no continue target available");
}
/************************************************************************/
Formatter& ICodeGenerator::print(Formatter& f)
{
f << "ICG! " << (uint32)iCode->size() << "\n";
for (InstructionIterator i = iCode->begin();

View File

@ -72,6 +72,7 @@ namespace ICG {
StateKind stateKind;
Register registerBase;
uint32 statementLabelBase;
Label *breakLabel;
Label *continueLabel;
};
@ -97,6 +98,7 @@ namespace ICG {
InstructionStream *iCode;
LabelList labels;
std::vector<ICodeState *> stitcher;
std::vector<const StringAtom *> statementLabels;
void markMaxRegister() \
{ if (topRegister > maxRegister) maxRegister = topRegister; }
@ -107,21 +109,26 @@ namespace ICG {
{ markMaxRegister(); topRegister = stitcher.empty() ? registerBase : \
stitcher.back()->registerBase; }
ICodeOp getBranchOp() \
{ ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); }
void addStitcher(ICodeState *ics) \
{ stitcher.push_back(ics); statementLabelBase = statementLabels.size(); }
ICodeOp getBranchOp() \
{ return (iCode->empty()) ? NOP : iCode->back()->getBranchOp(); }
Register topRegister;
Register registerBase;
uint32 maxRegister;
uint32 maxRegister;
uint32 statementLabelBase;;
void setLabel(Label *label);
void setLabel(InstructionStream *stream, Label *label);
void branch(Label *label);
void branchConditional(Label *label, Register condition);
void branchNotConditional(Label *label, Register condition);
public:
ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0)
ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0), statementLabelBase(0)
{ iCode = new InstructionStream(); }
virtual ~ICodeGenerator() { if (iCode) delete iCode; }
@ -140,6 +147,7 @@ namespace ICG {
Register call(Register target, RegisterList args);
void move(Register destination, Register source);
void not(Register destination, Register source);
Register compare(ICodeOp op, Register source1, Register source2);
@ -157,8 +165,9 @@ namespace ICG {
Register getElement(Register base, Register index);
void setElement(Register base, Register index, Register value);
Register getRegisterBase() { return topRegister; }
InstructionStream *get_iCode() { return iCode; }
Register getRegisterBase() { return topRegister; }
InstructionStream *get_iCode() { return iCode; }
uint32 getStatementLabelBase() { return statementLabelBase; }
Label *getLabel();
@ -202,26 +211,28 @@ namespace ICG {
void endCaseCondition(Register expression);
void beginCaseStatement();
void beginCaseStatement(uint32 pos);
void endCaseStatement();
// optionally
void beginDefaultStatement();
void beginDefaultStatement(uint32 pos);
void endDefaultStatement();
void endSwitchStatement();
void labelStatement(const StringAtom &label); // adds to label set
// for next statement, removed when that statement is finished
void continueStatement();
void breakStatement();
void beginLabelStatement(uint32 pos, const StringAtom &label)
{ statementLabels.push_back(&label); }
void endLabelStatement() { statementLabels.pop_back(); }
void continueStatement(const StringAtom &label);
void breakStatement(const StringAtom &label);
void continueStatement(uint32 pos);
void breakStatement(uint32 pos);
void throwStatement(Register expression);
void continueStatement(uint32 pos, const StringAtom &label);
void breakStatement(uint32 pos, const StringAtom &label);
void beginCatchStatement();
void throwStatement(uint32 pos, Register expression);
void beginCatchStatement(uint32 pos);
void endCatchExpression(Register expression);
void endCatchStatement();
@ -318,7 +329,8 @@ namespace ICG {
inline ICodeState::ICodeState(StateKind kind, ICodeGenerator *icg)
: stateKind(kind), registerBase(icg->getRegisterBase()),
breakLabel(NULL), continueLabel(NULL) { }
breakLabel(NULL), continueLabel(NULL),
statementLabelBase(icg->getStatementLabelBase()) { }
inline SwitchCodeState::SwitchCodeState(Register control,
ICodeGenerator *icg)

View File

@ -47,6 +47,9 @@ namespace JavaScript {
#define src2(i) op3(i)
#define ofs(i) (i->getOffset())
using namespace ICG;
using namespace JSTypes;
JSValue
Context::interpret(ICodeModule* iCode, const JSValues& args)
{

View File

@ -26,6 +26,7 @@
#include "world.h"
#include "interpreter.h"
#include "icodegenerator.h"
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
@ -57,6 +58,10 @@ static void initConsole(StringPtr consoleName,
namespace JavaScript {
namespace Shell {
using namespace ICG;
using namespace JSTypes;
// using namespace VMTypes;
// Interactively read a line from the input stream in and put it into
// s Return false if reached the end of input before reading anything.
static bool promptLine(LineReader &inReader, string &s,
@ -117,9 +122,7 @@ namespace Shell {
}
stdOut << '\n';
}
#include "icodegenerator.h"
static void testICG(World &world)
{
//
@ -127,7 +130,7 @@ namespace Shell {
//
uint32 pos = 0;
ICodeGenerator icg;
// var i,j;
// i is bound to var #0, j to var #1
Register r_i = icg.allocateVariable(world.identifiers[widenCString("i")]);
@ -136,19 +139,27 @@ namespace Shell {
// i = j + 2;
icg.beginStatement(pos);
Register r1 = icg.loadImmediate(2.0);
icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.move(r_i, icg.op(ADD, r1, r_j));
// j = a.b
icg.beginStatement(pos);
r1 = icg.loadName(world.identifiers[widenCString("a")]);
r1 = icg.getProperty(r1, world.identifiers[widenCString("b")]);
icg.move(r_j, r1);
// while (i) i = i + j;
// label1 : while (i) { while (i) { i = i + j; break label1; } }
icg.beginLabelStatement(pos, world.identifiers[widenCString("label1")]);
icg.beginWhileStatement(pos);
icg.endWhileExpression(r_i);
icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.beginWhileStatement(pos);
icg.endWhileExpression(r_i);
icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.breakStatement(pos, world.identifiers[widenCString("label1")]);
icg.endWhileStatement();
icg.endWhileStatement();
icg.endLabelStatement();
// if (i) if (j) i = 3; else j = 4;
icg.beginIfStatement(pos, r_i);
@ -159,35 +170,35 @@ namespace Shell {
icg.endIfStatement();
icg.beginElseStatement(false);
icg.endIfStatement();
// switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; }
icg.beginSwitchStatement(pos, r_i);
// case 3, note empty case statement (?necessary???)
icg.endCaseCondition(icg.loadImmediate(3));
icg.beginCaseStatement();
icg.beginCaseStatement(pos);
icg.endCaseStatement();
// case 4
icg.endCaseCondition(icg.loadImmediate(4));
icg.beginCaseStatement();
icg.beginCaseStatement(pos);
icg.beginStatement(pos);
icg.move(r_j, icg.loadImmediate(4));
icg.breakStatement();
icg.breakStatement(pos);
icg.endCaseStatement();
// case 5
icg.endCaseCondition(icg.loadImmediate(5));
icg.beginCaseStatement();
icg.beginCaseStatement(pos);
icg.beginStatement(pos);
icg.move(r_j, icg.loadImmediate(5));
icg.breakStatement();
icg.breakStatement(pos);
icg.endCaseStatement();
// default
icg.beginDefaultStatement();
icg.beginDefaultStatement(pos);
icg.beginStatement(pos);
icg.move(r_j, icg.loadImmediate(6));
icg.endDefaultStatement();
icg.endSwitchStatement();
// for ( ; i; i = i + 1 ) j = 99;
icg.beginForStatement(pos);
icg.forCondition(r_i);
@ -389,14 +400,14 @@ int main(int /* argc */, char /* **argv */)
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv);
#endif
JavaScript::World world;
JavaScript::World world;
#if 1
assert(JavaScript::Shell::testFactorial(world, 5) == 120);
assert(JavaScript::Shell::testObjects(world, 5) == 5);
// testICG(world);
// JavaScript::Shell::testICG(world);
assert(JavaScript::Shell::testFunctionCall(world, 5) == 5);
#endif
JavaScript::Shell::readEvalPrint(stdin, world);
JavaScript::Shell::readEvalPrint(stdin, world);
return 0;
// return ProcessArgs(argv + 1, argc - 1);
}

View File

@ -59,6 +59,7 @@ namespace ICG {
{
#ifdef DEBUG
ASSERT(stitcher.empty());
ASSERT(statementLabels.empty());
for (LabelList::iterator i = labels.begin();
i != labels.end(); i++) {
ASSERT((*i)->mBase == iCode);
@ -207,6 +208,26 @@ namespace ICG {
iCode->push_back(instr);
}
void ICodeGenerator::branchNotConditional(Label *label, Register condition)
{
ICodeOp branchOp = getBranchOp();
if (branchOp == NOP) {
// XXXX emit convert to boolean / Test / ...
branchOp = BRANCH_NE;
}
switch (branchOp) {
case BRANCH_EQ : branchOp = BRANCH_NE; break;
case BRANCH_GE : branchOp = BRANCH_LT; break;
case BRANCH_GT : branchOp = BRANCH_LE; break;
case BRANCH_LE : branchOp = BRANCH_GT; break;
case BRANCH_LT : branchOp = BRANCH_GE; break;
case BRANCH_NE : branchOp = BRANCH_EQ; break;
default : NOT_REACHED("Expected a branch op"); break;
}
GenericBranch *instr = new GenericBranch(branchOp, label, condition);
iCode->push_back(instr);
}
/********************************************************************/
Label *ICodeGenerator::getLabel()
@ -262,7 +283,7 @@ namespace ICG {
branch(whileConditionTop);
// save off the current stream while we gen code for the condition
stitcher.push_back(new WhileCodeState(whileConditionTop,
addStitcher(new WhileCodeState(whileConditionTop,
whileBlockStart, this));
iCode = new InstructionStream();
@ -314,7 +335,7 @@ namespace ICG {
branch(forCondition);
stitcher.push_back(ics);
addStitcher(ics);
// begin the stream for collecting the condition expression
iCode = new InstructionStream();
@ -383,7 +404,7 @@ namespace ICG {
Label *doCondition = getLabel();
setLabel(doBlock);
stitcher.push_back(new DoCodeState(doBlock, doCondition, this));
addStitcher(new DoCodeState(doBlock, doCondition, this));
iCode = new InstructionStream();
}
@ -430,7 +451,7 @@ namespace ICG {
InstructionStream *x = new InstructionStream();
SwitchCodeState *ics = new SwitchCodeState(control, this);
ics->swapStream(x);
stitcher.push_back(ics);
addStitcher(ics);
}
void ICodeGenerator::endCaseCondition(Register expression)
@ -448,7 +469,7 @@ namespace ICG {
resetTopRegister();
}
void ICodeGenerator::beginCaseStatement()
void ICodeGenerator::beginCaseStatement(uint32 pos)
{
SwitchCodeState *ics =
static_cast<SwitchCodeState *>(stitcher.back());
@ -468,7 +489,7 @@ namespace ICG {
resetTopRegister();
}
void ICodeGenerator::beginDefaultStatement()
void ICodeGenerator::beginDefaultStatement(uint32 pos)
{
SwitchCodeState *ics =
static_cast<SwitchCodeState *>(stitcher.back());
@ -525,10 +546,9 @@ namespace ICG {
{
Label *elseLabel = getLabel();
stitcher.push_back(new IfCodeState(elseLabel, NULL, this));
addStitcher(new IfCodeState(elseLabel, NULL, this));
Register notCond = op(NOT, condition);
branchConditional(elseLabel, notCond);
branchNotConditional(elseLabel, condition);
resetTopRegister();
}
@ -563,7 +583,7 @@ namespace ICG {
/************************************************************************/
void ICodeGenerator::breakStatement()
void ICodeGenerator::breakStatement(uint32 pos)
{
for (std::vector<ICodeState *>::reverse_iterator p =
stitcher.rbegin(); p != stitcher.rend(); p++) {
@ -583,7 +603,30 @@ namespace ICG {
NOT_REACHED("no break target available");
}
void ICodeGenerator::continueStatement()
void ICodeGenerator::breakStatement(uint32 pos, const StringAtom &label)
{
uint32 statementLabelCeiling = statementLabels.size();
for (std::vector<ICodeState *>::reverse_iterator p =
stitcher.rbegin(); p != stitcher.rend(); p++) {
for (std::vector<const StringAtom *>::iterator lbl =
statementLabels.begin() + (*p)->statementLabelBase;
lbl != statementLabels.begin() + statementLabelCeiling;
lbl++) {
if ((*lbl) == &label) {
if ((*p)->breakLabel == NULL)
(*p)->breakLabel = getLabel();
branch((*p)->breakLabel);
return;
}
}
statementLabelCeiling = (*p)->statementLabelBase;
}
NOT_REACHED("no break target available");
}
void ICodeGenerator::continueStatement(uint32 pos)
{
for (std::vector<ICodeState *>::reverse_iterator p =
stitcher.rbegin(); p != stitcher.rend(); p++) {
@ -602,7 +645,32 @@ namespace ICG {
NOT_REACHED("no continue target available");
}
Formatter& ICodeGenerator::print(Formatter& f)
void ICodeGenerator::continueStatement(uint32 pos, const StringAtom &label)
{
uint32 statementLabelCeiling = statementLabels.size();
for (std::vector<ICodeState *>::reverse_iterator p =
stitcher.rbegin(); p != stitcher.rend(); p++) {
for (std::vector<const StringAtom *>::iterator lbl =
statementLabels.begin() + (*p)->statementLabelBase;
lbl != statementLabels.begin() + statementLabelCeiling;
lbl++) {
if ((*lbl) == &label) {
if ((*p)->continueLabel == NULL)
(*p)->continueLabel = getLabel();
branch((*p)->continueLabel);
return;
}
}
statementLabelCeiling = (*p)->statementLabelBase;
}
NOT_REACHED("no continue target available");
}
/************************************************************************/
Formatter& ICodeGenerator::print(Formatter& f)
{
f << "ICG! " << (uint32)iCode->size() << "\n";
for (InstructionIterator i = iCode->begin();

View File

@ -72,6 +72,7 @@ namespace ICG {
StateKind stateKind;
Register registerBase;
uint32 statementLabelBase;
Label *breakLabel;
Label *continueLabel;
};
@ -97,6 +98,7 @@ namespace ICG {
InstructionStream *iCode;
LabelList labels;
std::vector<ICodeState *> stitcher;
std::vector<const StringAtom *> statementLabels;
void markMaxRegister() \
{ if (topRegister > maxRegister) maxRegister = topRegister; }
@ -107,21 +109,26 @@ namespace ICG {
{ markMaxRegister(); topRegister = stitcher.empty() ? registerBase : \
stitcher.back()->registerBase; }
ICodeOp getBranchOp() \
{ ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); }
void addStitcher(ICodeState *ics) \
{ stitcher.push_back(ics); statementLabelBase = statementLabels.size(); }
ICodeOp getBranchOp() \
{ return (iCode->empty()) ? NOP : iCode->back()->getBranchOp(); }
Register topRegister;
Register registerBase;
uint32 maxRegister;
uint32 maxRegister;
uint32 statementLabelBase;;
void setLabel(Label *label);
void setLabel(InstructionStream *stream, Label *label);
void branch(Label *label);
void branchConditional(Label *label, Register condition);
void branchNotConditional(Label *label, Register condition);
public:
ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0)
ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0), statementLabelBase(0)
{ iCode = new InstructionStream(); }
virtual ~ICodeGenerator() { if (iCode) delete iCode; }
@ -140,6 +147,7 @@ namespace ICG {
Register call(Register target, RegisterList args);
void move(Register destination, Register source);
void not(Register destination, Register source);
Register compare(ICodeOp op, Register source1, Register source2);
@ -157,8 +165,9 @@ namespace ICG {
Register getElement(Register base, Register index);
void setElement(Register base, Register index, Register value);
Register getRegisterBase() { return topRegister; }
InstructionStream *get_iCode() { return iCode; }
Register getRegisterBase() { return topRegister; }
InstructionStream *get_iCode() { return iCode; }
uint32 getStatementLabelBase() { return statementLabelBase; }
Label *getLabel();
@ -202,26 +211,28 @@ namespace ICG {
void endCaseCondition(Register expression);
void beginCaseStatement();
void beginCaseStatement(uint32 pos);
void endCaseStatement();
// optionally
void beginDefaultStatement();
void beginDefaultStatement(uint32 pos);
void endDefaultStatement();
void endSwitchStatement();
void labelStatement(const StringAtom &label); // adds to label set
// for next statement, removed when that statement is finished
void continueStatement();
void breakStatement();
void beginLabelStatement(uint32 pos, const StringAtom &label)
{ statementLabels.push_back(&label); }
void endLabelStatement() { statementLabels.pop_back(); }
void continueStatement(const StringAtom &label);
void breakStatement(const StringAtom &label);
void continueStatement(uint32 pos);
void breakStatement(uint32 pos);
void throwStatement(Register expression);
void continueStatement(uint32 pos, const StringAtom &label);
void breakStatement(uint32 pos, const StringAtom &label);
void beginCatchStatement();
void throwStatement(uint32 pos, Register expression);
void beginCatchStatement(uint32 pos);
void endCatchExpression(Register expression);
void endCatchStatement();
@ -318,7 +329,8 @@ namespace ICG {
inline ICodeState::ICodeState(StateKind kind, ICodeGenerator *icg)
: stateKind(kind), registerBase(icg->getRegisterBase()),
breakLabel(NULL), continueLabel(NULL) { }
breakLabel(NULL), continueLabel(NULL),
statementLabelBase(icg->getStatementLabelBase()) { }
inline SwitchCodeState::SwitchCodeState(Register control,
ICodeGenerator *icg)

View File

@ -47,6 +47,9 @@ namespace JavaScript {
#define src2(i) op3(i)
#define ofs(i) (i->getOffset())
using namespace ICG;
using namespace JSTypes;
JSValue
Context::interpret(ICodeModule* iCode, const JSValues& args)
{

View File

@ -26,6 +26,7 @@
#include "world.h"
#include "interpreter.h"
#include "icodegenerator.h"
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
@ -57,6 +58,10 @@ static void initConsole(StringPtr consoleName,
namespace JavaScript {
namespace Shell {
using namespace ICG;
using namespace JSTypes;
// using namespace VMTypes;
// Interactively read a line from the input stream in and put it into
// s Return false if reached the end of input before reading anything.
static bool promptLine(LineReader &inReader, string &s,
@ -117,9 +122,7 @@ namespace Shell {
}
stdOut << '\n';
}
#include "icodegenerator.h"
static void testICG(World &world)
{
//
@ -127,7 +130,7 @@ namespace Shell {
//
uint32 pos = 0;
ICodeGenerator icg;
// var i,j;
// i is bound to var #0, j to var #1
Register r_i = icg.allocateVariable(world.identifiers[widenCString("i")]);
@ -136,19 +139,27 @@ namespace Shell {
// i = j + 2;
icg.beginStatement(pos);
Register r1 = icg.loadImmediate(2.0);
icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.move(r_i, icg.op(ADD, r1, r_j));
// j = a.b
icg.beginStatement(pos);
r1 = icg.loadName(world.identifiers[widenCString("a")]);
r1 = icg.getProperty(r1, world.identifiers[widenCString("b")]);
icg.move(r_j, r1);
// while (i) i = i + j;
// label1 : while (i) { while (i) { i = i + j; break label1; } }
icg.beginLabelStatement(pos, world.identifiers[widenCString("label1")]);
icg.beginWhileStatement(pos);
icg.endWhileExpression(r_i);
icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.beginWhileStatement(pos);
icg.endWhileExpression(r_i);
icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.breakStatement(pos, world.identifiers[widenCString("label1")]);
icg.endWhileStatement();
icg.endWhileStatement();
icg.endLabelStatement();
// if (i) if (j) i = 3; else j = 4;
icg.beginIfStatement(pos, r_i);
@ -159,35 +170,35 @@ namespace Shell {
icg.endIfStatement();
icg.beginElseStatement(false);
icg.endIfStatement();
// switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; }
icg.beginSwitchStatement(pos, r_i);
// case 3, note empty case statement (?necessary???)
icg.endCaseCondition(icg.loadImmediate(3));
icg.beginCaseStatement();
icg.beginCaseStatement(pos);
icg.endCaseStatement();
// case 4
icg.endCaseCondition(icg.loadImmediate(4));
icg.beginCaseStatement();
icg.beginCaseStatement(pos);
icg.beginStatement(pos);
icg.move(r_j, icg.loadImmediate(4));
icg.breakStatement();
icg.breakStatement(pos);
icg.endCaseStatement();
// case 5
icg.endCaseCondition(icg.loadImmediate(5));
icg.beginCaseStatement();
icg.beginCaseStatement(pos);
icg.beginStatement(pos);
icg.move(r_j, icg.loadImmediate(5));
icg.breakStatement();
icg.breakStatement(pos);
icg.endCaseStatement();
// default
icg.beginDefaultStatement();
icg.beginDefaultStatement(pos);
icg.beginStatement(pos);
icg.move(r_j, icg.loadImmediate(6));
icg.endDefaultStatement();
icg.endSwitchStatement();
// for ( ; i; i = i + 1 ) j = 99;
icg.beginForStatement(pos);
icg.forCondition(r_i);
@ -389,14 +400,14 @@ int main(int /* argc */, char /* **argv */)
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv);
#endif
JavaScript::World world;
JavaScript::World world;
#if 1
assert(JavaScript::Shell::testFactorial(world, 5) == 120);
assert(JavaScript::Shell::testObjects(world, 5) == 5);
// testICG(world);
// JavaScript::Shell::testICG(world);
assert(JavaScript::Shell::testFunctionCall(world, 5) == 5);
#endif
JavaScript::Shell::readEvalPrint(stdin, world);
JavaScript::Shell::readEvalPrint(stdin, world);
return 0;
// return ProcessArgs(argv + 1, argc - 1);
}