зеркало из https://github.com/mozilla/pjs.git
For statements.
This commit is contained in:
Родитель
a319d852b3
Коммит
3714722cf4
|
@ -161,19 +161,19 @@ void ICodeGenerator::setLabel(InstructionStream *stream, int32 label)
|
||||||
|
|
||||||
/***********************************************************************************************/
|
/***********************************************************************************************/
|
||||||
|
|
||||||
void MultiPathICodeState::mergeStream(InstructionStream *mainStream, LabelList &labels)
|
void MultiPathICodeState::mergeStream(InstructionStream *sideStream, InstructionStream *mainStream, LabelList &labels)
|
||||||
{
|
{
|
||||||
// change InstructionStream to be a class that also remembers
|
// change InstructionStream to be a class that also remembers
|
||||||
// if it contains any labels (maybe even remembers the labels
|
// if it contains any labels (maybe even remembers the labels
|
||||||
// themselves?) in order to avoid running this loop unnecessarily.
|
// themselves?) in order to avoid running this loop unnecessarily.
|
||||||
for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) {
|
for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) {
|
||||||
if ((*i)->itsBase == its_iCode) {
|
if ((*i)->itsBase == sideStream) {
|
||||||
(*i)->itsBase = mainStream;
|
(*i)->itsBase = mainStream;
|
||||||
(*i)->itsOffset += mainStream->size();
|
(*i)->itsOffset += mainStream->size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (InstructionIterator ii = its_iCode->begin(); ii != its_iCode->end(); ii++)
|
for (InstructionIterator ii = sideStream->begin(); ii != sideStream->end(); ii++)
|
||||||
mainStream->push_back(*ii);
|
mainStream->push_back(*ii);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -231,6 +231,66 @@ void ICodeGenerator::endWhileStatement()
|
||||||
|
|
||||||
/***********************************************************************************************/
|
/***********************************************************************************************/
|
||||||
|
|
||||||
|
void ICodeGenerator::beginForStatement(const SourcePosition &pos)
|
||||||
|
{
|
||||||
|
int32 forCondition = getLabel();
|
||||||
|
|
||||||
|
ForCodeState *ics = new ForCodeState(forCondition, getLabel(), this);
|
||||||
|
ics->continueLabel = getLabel();
|
||||||
|
|
||||||
|
branch(forCondition);
|
||||||
|
|
||||||
|
stitcher.push_back(ics);
|
||||||
|
|
||||||
|
iCode = new InstructionStream(); // begin the stream for collecting the test expression
|
||||||
|
setLabel(forCondition);
|
||||||
|
|
||||||
|
resetTopRegister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICodeGenerator::forCondition(Register condition)
|
||||||
|
{
|
||||||
|
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
|
||||||
|
ASSERT(ics->stateKind == For_state);
|
||||||
|
|
||||||
|
// finsh off the test expression by adding the branch to the body
|
||||||
|
branchConditional(ics->forBody, condition);
|
||||||
|
|
||||||
|
iCode = ics->swapStream(iCode); // switch back to main stream
|
||||||
|
iCode = new InstructionStream(); // begin the stream for collecting the increment expression
|
||||||
|
|
||||||
|
setLabel(ics->continueLabel); // which is where continues will target
|
||||||
|
resetTopRegister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICodeGenerator::forIncrement()
|
||||||
|
{
|
||||||
|
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
|
||||||
|
ASSERT(ics->stateKind == For_state);
|
||||||
|
|
||||||
|
// now switch back to the main stream
|
||||||
|
iCode = ics->swapStream2(iCode);
|
||||||
|
setLabel(ics->forBody);
|
||||||
|
|
||||||
|
resetTopRegister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICodeGenerator::endForStatement()
|
||||||
|
{
|
||||||
|
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
|
||||||
|
ASSERT(ics->stateKind == For_state);
|
||||||
|
|
||||||
|
ics->mergeStream2(iCode, labels); // merges the increment sequence
|
||||||
|
ics->mergeStream(iCode, labels); // merges the test sequence
|
||||||
|
|
||||||
|
if (ics->breakLabel != -1)
|
||||||
|
setLabel(ics->breakLabel);
|
||||||
|
|
||||||
|
delete ics;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************/
|
||||||
|
|
||||||
void ICodeGenerator::beginDoStatement(const SourcePosition &pos)
|
void ICodeGenerator::beginDoStatement(const SourcePosition &pos)
|
||||||
{
|
{
|
||||||
resetTopRegister();
|
resetTopRegister();
|
||||||
|
@ -279,12 +339,12 @@ void ICodeGenerator::beginSwitchStatement(const SourcePosition &pos, Register ex
|
||||||
{
|
{
|
||||||
// stash the control expression value
|
// stash the control expression value
|
||||||
resetTopRegister();
|
resetTopRegister();
|
||||||
op(MOVE_TO, getRegister(), expression);
|
Register control = op(MOVE_TO, expression);
|
||||||
// build an instruction stream for the case statements, the case
|
// build an instruction stream for the case statements, the case
|
||||||
// expressions are generated into the main stream directly, the
|
// expressions are generated into the main stream directly, the
|
||||||
// case statements are then added back in afterwards.
|
// case statements are then added back in afterwards.
|
||||||
InstructionStream *x = new InstructionStream();
|
InstructionStream *x = new InstructionStream();
|
||||||
SwitchCodeState *ics = new SwitchCodeState(expression, this);
|
SwitchCodeState *ics = new SwitchCodeState(control, this);
|
||||||
ics->swapStream(x);
|
ics->swapStream(x);
|
||||||
stitcher.push_back(ics);
|
stitcher.push_back(ics);
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,9 @@ namespace JavaScript {
|
||||||
|
|
||||||
InstructionStream *its_iCode;
|
InstructionStream *its_iCode;
|
||||||
|
|
||||||
void mergeStream(InstructionStream *mainStream, LabelList &labels);
|
static void mergeStream(InstructionStream *sideStream, InstructionStream *mainStream, LabelList &labels);
|
||||||
|
|
||||||
|
void mergeStream(InstructionStream *mainStream, LabelList &labels) { mergeStream(its_iCode, mainStream, labels); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WhileCodeState : public MultiPathICodeState {
|
class WhileCodeState : public MultiPathICodeState {
|
||||||
|
@ -142,6 +144,16 @@ namespace JavaScript {
|
||||||
int32 whileBody;
|
int32 whileBody;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ForCodeState : public MultiPathICodeState {
|
||||||
|
public:
|
||||||
|
ForCodeState(int32 conditionLabel, int32 bodyLabel, ICodeGenerator *icg); // inline below
|
||||||
|
InstructionStream *swapStream2(InstructionStream *iCode) { InstructionStream *t = its_iCode_2; its_iCode_2 = iCode; return t; }
|
||||||
|
void mergeStream2(InstructionStream *mainStream, LabelList &labels) { mergeStream(its_iCode_2, mainStream, labels); }
|
||||||
|
int32 forCondition;
|
||||||
|
int32 forBody;
|
||||||
|
InstructionStream *its_iCode_2;
|
||||||
|
};
|
||||||
|
|
||||||
class IfCodeState : public ICodeState {
|
class IfCodeState : public ICodeState {
|
||||||
public:
|
public:
|
||||||
IfCodeState(int32 a, int32 b, ICodeGenerator *icg)
|
IfCodeState(int32 a, int32 b, ICodeGenerator *icg)
|
||||||
|
@ -241,9 +253,9 @@ namespace JavaScript {
|
||||||
|
|
||||||
|
|
||||||
// for ( ... in ...) statements get turned into generic for statements by the parser (ok?)
|
// for ( ... in ...) statements get turned into generic for statements by the parser (ok?)
|
||||||
void beginForStatement(); // for initialization is emitted prior to this call
|
void beginForStatement(const SourcePosition &pos); // for initialization is emitted prior to this call
|
||||||
void forCondition(Register condition); // required with optional <operand>
|
void forCondition(Register condition); // required
|
||||||
void forIncrement(Register expression); // required with optional <operand>
|
void forIncrement(); // required
|
||||||
void endForStatement();
|
void endForStatement();
|
||||||
|
|
||||||
|
|
||||||
|
@ -290,5 +302,8 @@ namespace JavaScript {
|
||||||
|
|
||||||
inline MultiPathICodeState::MultiPathICodeState(StateKind kind, ICodeGenerator *icg)
|
inline MultiPathICodeState::MultiPathICodeState(StateKind kind, ICodeGenerator *icg)
|
||||||
: ICodeState(kind, icg), its_iCode(icg->get_iCode()) {}
|
: ICodeState(kind, icg), its_iCode(icg->get_iCode()) {}
|
||||||
|
|
||||||
|
inline ForCodeState::ForCodeState(int32 conditionLabel, int32 bodyLabel, ICodeGenerator *icg)
|
||||||
|
: MultiPathICodeState(For_state, icg), forCondition(conditionLabel), forBody(bodyLabel), its_iCode_2(icg->get_iCode()) { }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -400,6 +400,17 @@ void testICG(World &world)
|
||||||
icg.endDefaultStatement();
|
icg.endDefaultStatement();
|
||||||
icg.endSwitchStatement();
|
icg.endSwitchStatement();
|
||||||
|
|
||||||
|
// for ( ; i; i + 1 ) j = 99;
|
||||||
|
icg.beginForStatement(pos);
|
||||||
|
r1 = icg.loadVariable(0);
|
||||||
|
icg.forCondition(r1);
|
||||||
|
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadImmediate(1)));
|
||||||
|
icg.forIncrement();
|
||||||
|
icg.saveVariable(0, icg.loadImmediate(99));
|
||||||
|
icg.endForStatement();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
InstructionStream *iCode = icg.complete();
|
InstructionStream *iCode = icg.complete();
|
||||||
|
|
||||||
std::cout << icg;
|
std::cout << icg;
|
||||||
|
|
|
@ -161,19 +161,19 @@ void ICodeGenerator::setLabel(InstructionStream *stream, int32 label)
|
||||||
|
|
||||||
/***********************************************************************************************/
|
/***********************************************************************************************/
|
||||||
|
|
||||||
void MultiPathICodeState::mergeStream(InstructionStream *mainStream, LabelList &labels)
|
void MultiPathICodeState::mergeStream(InstructionStream *sideStream, InstructionStream *mainStream, LabelList &labels)
|
||||||
{
|
{
|
||||||
// change InstructionStream to be a class that also remembers
|
// change InstructionStream to be a class that also remembers
|
||||||
// if it contains any labels (maybe even remembers the labels
|
// if it contains any labels (maybe even remembers the labels
|
||||||
// themselves?) in order to avoid running this loop unnecessarily.
|
// themselves?) in order to avoid running this loop unnecessarily.
|
||||||
for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) {
|
for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) {
|
||||||
if ((*i)->itsBase == its_iCode) {
|
if ((*i)->itsBase == sideStream) {
|
||||||
(*i)->itsBase = mainStream;
|
(*i)->itsBase = mainStream;
|
||||||
(*i)->itsOffset += mainStream->size();
|
(*i)->itsOffset += mainStream->size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (InstructionIterator ii = its_iCode->begin(); ii != its_iCode->end(); ii++)
|
for (InstructionIterator ii = sideStream->begin(); ii != sideStream->end(); ii++)
|
||||||
mainStream->push_back(*ii);
|
mainStream->push_back(*ii);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -231,6 +231,66 @@ void ICodeGenerator::endWhileStatement()
|
||||||
|
|
||||||
/***********************************************************************************************/
|
/***********************************************************************************************/
|
||||||
|
|
||||||
|
void ICodeGenerator::beginForStatement(const SourcePosition &pos)
|
||||||
|
{
|
||||||
|
int32 forCondition = getLabel();
|
||||||
|
|
||||||
|
ForCodeState *ics = new ForCodeState(forCondition, getLabel(), this);
|
||||||
|
ics->continueLabel = getLabel();
|
||||||
|
|
||||||
|
branch(forCondition);
|
||||||
|
|
||||||
|
stitcher.push_back(ics);
|
||||||
|
|
||||||
|
iCode = new InstructionStream(); // begin the stream for collecting the test expression
|
||||||
|
setLabel(forCondition);
|
||||||
|
|
||||||
|
resetTopRegister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICodeGenerator::forCondition(Register condition)
|
||||||
|
{
|
||||||
|
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
|
||||||
|
ASSERT(ics->stateKind == For_state);
|
||||||
|
|
||||||
|
// finsh off the test expression by adding the branch to the body
|
||||||
|
branchConditional(ics->forBody, condition);
|
||||||
|
|
||||||
|
iCode = ics->swapStream(iCode); // switch back to main stream
|
||||||
|
iCode = new InstructionStream(); // begin the stream for collecting the increment expression
|
||||||
|
|
||||||
|
setLabel(ics->continueLabel); // which is where continues will target
|
||||||
|
resetTopRegister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICodeGenerator::forIncrement()
|
||||||
|
{
|
||||||
|
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
|
||||||
|
ASSERT(ics->stateKind == For_state);
|
||||||
|
|
||||||
|
// now switch back to the main stream
|
||||||
|
iCode = ics->swapStream2(iCode);
|
||||||
|
setLabel(ics->forBody);
|
||||||
|
|
||||||
|
resetTopRegister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICodeGenerator::endForStatement()
|
||||||
|
{
|
||||||
|
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
|
||||||
|
ASSERT(ics->stateKind == For_state);
|
||||||
|
|
||||||
|
ics->mergeStream2(iCode, labels); // merges the increment sequence
|
||||||
|
ics->mergeStream(iCode, labels); // merges the test sequence
|
||||||
|
|
||||||
|
if (ics->breakLabel != -1)
|
||||||
|
setLabel(ics->breakLabel);
|
||||||
|
|
||||||
|
delete ics;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************/
|
||||||
|
|
||||||
void ICodeGenerator::beginDoStatement(const SourcePosition &pos)
|
void ICodeGenerator::beginDoStatement(const SourcePosition &pos)
|
||||||
{
|
{
|
||||||
resetTopRegister();
|
resetTopRegister();
|
||||||
|
@ -279,12 +339,12 @@ void ICodeGenerator::beginSwitchStatement(const SourcePosition &pos, Register ex
|
||||||
{
|
{
|
||||||
// stash the control expression value
|
// stash the control expression value
|
||||||
resetTopRegister();
|
resetTopRegister();
|
||||||
op(MOVE_TO, getRegister(), expression);
|
Register control = op(MOVE_TO, expression);
|
||||||
// build an instruction stream for the case statements, the case
|
// build an instruction stream for the case statements, the case
|
||||||
// expressions are generated into the main stream directly, the
|
// expressions are generated into the main stream directly, the
|
||||||
// case statements are then added back in afterwards.
|
// case statements are then added back in afterwards.
|
||||||
InstructionStream *x = new InstructionStream();
|
InstructionStream *x = new InstructionStream();
|
||||||
SwitchCodeState *ics = new SwitchCodeState(expression, this);
|
SwitchCodeState *ics = new SwitchCodeState(control, this);
|
||||||
ics->swapStream(x);
|
ics->swapStream(x);
|
||||||
stitcher.push_back(ics);
|
stitcher.push_back(ics);
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,9 @@ namespace JavaScript {
|
||||||
|
|
||||||
InstructionStream *its_iCode;
|
InstructionStream *its_iCode;
|
||||||
|
|
||||||
void mergeStream(InstructionStream *mainStream, LabelList &labels);
|
static void mergeStream(InstructionStream *sideStream, InstructionStream *mainStream, LabelList &labels);
|
||||||
|
|
||||||
|
void mergeStream(InstructionStream *mainStream, LabelList &labels) { mergeStream(its_iCode, mainStream, labels); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WhileCodeState : public MultiPathICodeState {
|
class WhileCodeState : public MultiPathICodeState {
|
||||||
|
@ -142,6 +144,16 @@ namespace JavaScript {
|
||||||
int32 whileBody;
|
int32 whileBody;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ForCodeState : public MultiPathICodeState {
|
||||||
|
public:
|
||||||
|
ForCodeState(int32 conditionLabel, int32 bodyLabel, ICodeGenerator *icg); // inline below
|
||||||
|
InstructionStream *swapStream2(InstructionStream *iCode) { InstructionStream *t = its_iCode_2; its_iCode_2 = iCode; return t; }
|
||||||
|
void mergeStream2(InstructionStream *mainStream, LabelList &labels) { mergeStream(its_iCode_2, mainStream, labels); }
|
||||||
|
int32 forCondition;
|
||||||
|
int32 forBody;
|
||||||
|
InstructionStream *its_iCode_2;
|
||||||
|
};
|
||||||
|
|
||||||
class IfCodeState : public ICodeState {
|
class IfCodeState : public ICodeState {
|
||||||
public:
|
public:
|
||||||
IfCodeState(int32 a, int32 b, ICodeGenerator *icg)
|
IfCodeState(int32 a, int32 b, ICodeGenerator *icg)
|
||||||
|
@ -241,9 +253,9 @@ namespace JavaScript {
|
||||||
|
|
||||||
|
|
||||||
// for ( ... in ...) statements get turned into generic for statements by the parser (ok?)
|
// for ( ... in ...) statements get turned into generic for statements by the parser (ok?)
|
||||||
void beginForStatement(); // for initialization is emitted prior to this call
|
void beginForStatement(const SourcePosition &pos); // for initialization is emitted prior to this call
|
||||||
void forCondition(Register condition); // required with optional <operand>
|
void forCondition(Register condition); // required
|
||||||
void forIncrement(Register expression); // required with optional <operand>
|
void forIncrement(); // required
|
||||||
void endForStatement();
|
void endForStatement();
|
||||||
|
|
||||||
|
|
||||||
|
@ -290,5 +302,8 @@ namespace JavaScript {
|
||||||
|
|
||||||
inline MultiPathICodeState::MultiPathICodeState(StateKind kind, ICodeGenerator *icg)
|
inline MultiPathICodeState::MultiPathICodeState(StateKind kind, ICodeGenerator *icg)
|
||||||
: ICodeState(kind, icg), its_iCode(icg->get_iCode()) {}
|
: ICodeState(kind, icg), its_iCode(icg->get_iCode()) {}
|
||||||
|
|
||||||
|
inline ForCodeState::ForCodeState(int32 conditionLabel, int32 bodyLabel, ICodeGenerator *icg)
|
||||||
|
: MultiPathICodeState(For_state, icg), forCondition(conditionLabel), forBody(bodyLabel), its_iCode_2(icg->get_iCode()) { }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -400,6 +400,17 @@ void testICG(World &world)
|
||||||
icg.endDefaultStatement();
|
icg.endDefaultStatement();
|
||||||
icg.endSwitchStatement();
|
icg.endSwitchStatement();
|
||||||
|
|
||||||
|
// for ( ; i; i + 1 ) j = 99;
|
||||||
|
icg.beginForStatement(pos);
|
||||||
|
r1 = icg.loadVariable(0);
|
||||||
|
icg.forCondition(r1);
|
||||||
|
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadImmediate(1)));
|
||||||
|
icg.forIncrement();
|
||||||
|
icg.saveVariable(0, icg.loadImmediate(99));
|
||||||
|
icg.endForStatement();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
InstructionStream *iCode = icg.complete();
|
InstructionStream *iCode = icg.complete();
|
||||||
|
|
||||||
std::cout << icg;
|
std::cout << icg;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче