%type <statement_> LabelledStatement
%type <expression_> LeftHandSideExpression
%type <expression_> LeftHandSideExpressionNoBF
-//%type <statement_> LetStatement
+%type <statement_> LetStatement
%type <literal_> Literal
%type <literal_> LiteralNoRE
%type <literal_> LiteralRE
ForStatementInitialiser
: ExpressionNoInOpt { $$ = $1; }
- | LexSetRegExp "var" VariableDeclarationListNoIn { $$ = $3; }
+ | LexSetRegExp "var" VariableDeclarationListNoIn { $$ = CYNew CYForDeclarations($3); }
;
/* }}} */
/* 12.6.4 The for-in Statement {{{ */
: "for" "each" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = CYNew CYForEachIn($4, $6, $8); }
;
/* }}} */
-/* JavaScript 1.7: let Statements {{{ *//*
+/* JavaScript 1.7: let Statements {{{ */
LetStatement
- : "let" "(" VariableDeclarationList ")" Block_ { $$ = CYNew CYLet($3, $5); }
+ : "let" "(" VariableDeclarationList ")" Statement { $$ = CYNew CYLet($3, $5); }
;
Statement_
: LetStatement
;
-*//* }}} */
+/* }}} */
/* JavaScript FTW: Function Statements {{{ */
Statement
}
}
-void CYDeclarations::For(CYOutput &out) const {
+void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
out << "var";
- Output(out, CYNoIn);
+ Output(out, CYRight(flags));
}
void CYDeclarations::Output(CYOutput &out) const {
Output(out, CYAssign::Precedence_, CYNoFlags);
}
-void CYExpression::For(CYOutput &out) const {
- Output(out, CYNoIn);
-}
-
void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
Output(out, flags | CYNoRightHand);
}
void CYFor::Output(CYOutput &out, CYFlags flags) const {
out << "for" << ' ' << '(';
if (initialiser_ != NULL)
- initialiser_->For(out);
+ initialiser_->Output(out, CYNoIn);
out.Terminate();
if (test_ != NULL)
out << ' ';
}
void CYLet::Output(CYOutput &out, CYFlags flags) const {
- out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
+ out << "let" << ' ' << '(' << *declarations_ << ')';
+ code_->Single(out, CYRight(flags));
}
namespace cy {
virtual ~CYForInitialiser() {
}
- virtual void For(CYOutput &out) const = 0;
virtual CYExpression *Replace(CYContext &context) = 0;
+ virtual void Output(CYOutput &out, CYFlags flags) const = 0;
};
struct CYForInInitialiser {
return true;
}
- virtual void For(CYOutput &out) const;
virtual void ForIn(CYOutput &out, CYFlags flags) const;
virtual CYStatement *ForEachIn(CYContext &out, CYExpression *value);
virtual CYStatement *ForEachIn(CYContext &out, CYExpression *value);
virtual CYExpression *Replace(CYContext &context);
+
virtual CYAssignment *Assignment(CYContext &context);
+ CYVariable *Variable(CYContext &context);
virtual void Output(CYOutput &out, CYFlags flags) const;
};
struct CYDeclarations :
CYNext<CYDeclarations>,
- CYThing,
- CYForInitialiser
+ CYThing
{
CYDeclaration *declaration_;
{
}
- virtual void For(CYOutput &out) const;
+ void Replace(CYContext &context);
- virtual CYCompound *Replace(CYContext &context);
+ CYCompound *Compound(CYContext &context);
CYProperty *Property(CYContext &context);
+ CYArgument *Argument(CYContext &context);
+ CYFunctionParameter *Parameter(CYContext &context);
virtual void Output(CYOutput &out) const;
virtual void Output(CYOutput &out, CYFlags flags) const;
};
+struct CYForDeclarations :
+ CYForInitialiser
+{
+ CYDeclarations *declarations_;
+
+ CYForDeclarations(CYDeclarations *declarations) :
+ declarations_(declarations)
+ {
+ }
+
+ virtual CYCompound *Replace(CYContext &context);
+ virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
struct CYVar :
CYStatement
{
CYStatement
{
CYDeclarations *declarations_;
- CYBlock code_;
+ CYStatement *code_;
- CYLet(CYDeclarations *declarations, CYStatement *statements) :
+ CYLet(CYDeclarations *declarations, CYStatement *code) :
declarations_(declarations),
- code_(statements)
+ code_(code)
{
}
}
CYAssignment *CYDeclaration::Assignment(CYContext &context) {
- context.Replace(identifier_);
- CYExpression *variable(Replace(context));
- context.scope_->Declare(context, identifier_, CYIdentifierVariable);
- return initialiser_ == NULL ? NULL : $ CYAssign(variable, initialiser_);
+ if (initialiser_ == NULL)
+ return NULL;
+ return $ CYAssign(Variable(context), initialiser_);
+}
+
+CYVariable *CYDeclaration::Variable(CYContext &context) {
+ return $V(identifier_);
}
CYStatement *CYDeclaration::ForEachIn(CYContext &context, CYExpression *value) {
}
CYExpression *CYDeclaration::Replace(CYContext &context) {
- return $V(identifier_);
+ context.Replace(identifier_);
+ context.scope_->Declare(context, identifier_, CYIdentifierVariable);
+ return Variable(context);
+}
+
+void CYDeclarations::Replace(CYContext &context) { $T()
+ declaration_->Replace(context);
+ next_->Replace(context);
}
CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL)
return $ CYProperty(declaration_->identifier_, declaration_->initialiser_ ?: $U, next_->Property(context));
}
-CYCompound *CYDeclarations::Replace(CYContext &context) {
- CYCompound *compound(next_ == NULL ? $ CYCompound() : next_->Replace(context));
+CYFunctionParameter *CYDeclarations::Parameter(CYContext &context) { $T(NULL)
+ return $ CYFunctionParameter(declaration_->identifier_, next_->Parameter(context));
+}
+
+CYArgument *CYDeclarations::Argument(CYContext &context) { $T(NULL)
+ return $ CYArgument(declaration_->initialiser_ ?: $U, next_->Argument(context));
+}
+
+CYCompound *CYDeclarations::Compound(CYContext &context) { $T(NULL)
+ CYCompound *compound(next_->Compound(context) ?: $ CYCompound());
if (CYAssignment *assignment = declaration_->Assignment(context))
compound->AddPrev(assignment);
return compound;
return this;
}
+CYCompound *CYForDeclarations::Replace(CYContext &context) {
+ declarations_->Replace(context);
+ return declarations_->Compound(context);
+}
+
+// XXX: this still feels highly suboptimal
CYStatement *CYForIn::Replace(CYContext &context) {
- CYAssignment *assignment(initialiser_->Assignment(context));
+ CYForInInitialiser *initialiser(initialiser_);
context.Replace(initialiser_);
context.Replace(set_);
context.Replace(code_);
- if (assignment == NULL)
- return this;
+ if (CYAssignment *assignment = initialiser->Assignment(context))
+ return $ CYBlock($$->*
+ $E(assignment)->*
+ this
+ );
- return $ CYBlock($$->*
- $E(assignment)->*
- this
- );
+ return this;
}
CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
}
CYStatement *CYLet::Replace(CYContext &context) {
- return $ CYWith($ CYObject(declarations_->Property(context)), &code_);
+ declarations_->Replace(context);
+ return $ CYWith($ CYObject(declarations_->Property(context)), code_);
}
void CYMember::Replace_(CYContext &context) {
} }
CYStatement *CYVar::Replace(CYContext &context) {
- return $E(declarations_->Replace(context));
+ declarations_->Replace(context);
+ return $E(declarations_->Compound(context));
}
CYExpression *CYVariable::Replace(CYContext &context) {