]> git.saurik.com Git - cycript.git/commitdiff
Simplify Block, Compound, and (new) Parenthetical.
authorJay Freeman (saurik) <saurik@saurik.com>
Mon, 23 Nov 2015 23:56:10 +0000 (15:56 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Mon, 23 Nov 2015 23:56:10 +0000 (15:56 -0800)
Console.cpp
Cycript.yy.in
ObjectiveC/Replace.cpp
ObjectiveC/Syntax.hpp
Output.cpp
Parser.hpp
Replace.cpp

index 883f03f0977cbf5b13e150f2b3765e7de73fe297..df349966623b4fc912590725f3e3405ad2b1cfc3 100644 (file)
@@ -226,14 +226,17 @@ static CYExpression *ParseExpression(CYUTF8String code) {
     CYOptions options;
     CYContext context(options);
 
-    CYStatement *statement(driver.program_->statements_);
+    CYStatement *statement(driver.program_->code_);
     _assert(statement != NULL);
     _assert(statement->next_ == NULL);
 
-    CYExpress *express(dynamic_cast<CYExpress *>(driver.program_->statements_));
+    CYExpress *express(dynamic_cast<CYExpress *>(driver.program_->code_));
     _assert(express != NULL);
 
-    return express->expression_;
+    CYParenthetical *parenthetical(dynamic_cast<CYParenthetical *>(express->expression_));
+    _assert(parenthetical != NULL);
+
+    return parenthetical->expression_;
 }
 
 static int client_;
index 8eba3a40e0d98c7961fb411ab03d055d39ebdc19..1e9d2bad9e43efe74d8e5898a7c65e75dd1a56fb 100644 (file)
@@ -55,7 +55,6 @@ typedef struct {
         cy::Syntax::Catch *catch_;
         CYComment *comment_;
         CYComprehension *comprehension_;
-        CYCompound *compound_;
         CYDeclaration *declaration_;
         CYDeclarations *declarations_;
         CYElement *element_;
@@ -72,6 +71,7 @@ typedef struct {
         CYModule *module_;
         CYNull *null_;
         CYNumber *number_;
+        CYParenthetical *parenthetical_;
         CYProgram *program_;
         CYProperty *property_;
         CYPropertyName *propertyName_;
@@ -396,8 +396,7 @@ int cylex(YYSTYPE *, CYLocation *, void *);
 %type <statement_> ElseStatementOpt
 %type <statement_> EmptyStatement
 %type <expression_> EqualityExpression
-%type <compound_> Expression_
-%type <compound_> Expression
+%type <expression_> Expression
 %type <expression_> ExpressionOpt
 %type <statement_> ExpressionStatement
 %type <finally_> FinallyOpt
@@ -434,7 +433,7 @@ int cylex(YYSTYPE *, CYLocation *, void *);
 %type <expression_> NewExpression
 %type <null_> NullLiteral
 %type <literal_> ObjectLiteral
-%type <compound_> Parenthetical
+%type <parenthetical_> Parenthetical
 %type <expression_> PostfixExpression
 %type <expression_> PrimaryExpression
 %type <statement_> Program
@@ -766,7 +765,7 @@ TerminatorOpt
 
 /* 11.1 Primary Expressions {{{ */
 Parenthetical
-    : "(" LexPushInOff Expression ")" LexPopIn { $$ = $3; }
+    : "(" LexPushInOff Expression ")" LexPopIn { $$ = CYNew CYParenthetical($3); }
     ;
 
 Variable
@@ -1055,13 +1054,9 @@ AssignmentExpression
     ;
 /* }}} */
 /* 11.14 Comma Operator {{{ */
-Expression_
-    : "," Expression { $$ = $2; }
-    | { $$ = NULL; }
-    ;
-
 Expression
-    : AssignmentExpression Expression_ { $$ = CYNew CYCompound($1, $2); }
+    : AssignmentExpression { $$ = $1; }
+    | AssignmentExpression "," Expression { $$ = CYNew CYCompound($1, $3); }
     ;
 
 ExpressionOpt
@@ -1375,7 +1370,7 @@ ArrowFunction
 ArrowParameters
     : BindingIdentifier { $$ = CYNew CYFunctionParameter(CYNew CYDeclaration($1)); }
     | "(" LexPushInOff LexSetRegExp ")" LexPopIn { $$ = NULL; }
-    | Parenthetical { $$ = $1->Parameters(); if ($$ == NULL) error(@1, "invalid parameter list"); }
+    | Parenthetical { $$ = $1->expression_->Parameter(); if ($$ == NULL) error(@1, "invalid parameter list"); }
     ;
 
 ConciseBody
index b7071f9b8e2cddc36c6c03897886fcc0af6df7dc..086287baab243c0a25878d2a78a656900d442aeb 100644 (file)
@@ -108,7 +108,7 @@ CYStatement *CYMessage::Replace(CYContext &context, bool replace) const { $T(NUL
             cyn,
             $N2($V("Functor"), $F(NULL, $P2($L("self"), $L("_cmd"), parameters_->Parameters(context)), $$->*
                 $ CYVar($L1($L("$cyr", $N2($V("objc_super"), self, _class))))->*
-                $ CYReturn($C1($M($F(NULL, NULL, code_), $S("call")), self))
+                $ CYReturn($C1($M($F(NULL, NULL, code_.code_), $S("call")), self))
             ), cyt),
             cyt
         ))
@@ -142,7 +142,7 @@ CYExpression *CYBox::Replace(CYContext &context) {
 }
 
 CYExpression *CYObjCBlock::Replace(CYContext &context) {
-    return $C1($ CYEncodedType(($ CYTypedIdentifier(*typed_))->Modify($ CYTypeBlockWith(parameters_))), $ CYFunctionExpression(NULL, parameters_->Parameters(context), statements_));
+    return $C1($ CYEncodedType(($ CYTypedIdentifier(*typed_))->Modify($ CYTypeBlockWith(parameters_))), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_));
 }
 
 CYStatement *CYProtocol::Replace(CYContext &context) const { $T(NULL)
index 642aae4e298db6775b56242883fb5d43742372a0..8beabb98342160c2cbee4bed12b912e10b1bed1d 100644 (file)
@@ -45,12 +45,12 @@ struct CYObjCBlock :
 {
     CYTypedIdentifier *typed_;
     CYTypedParameter *parameters_;
-    CYStatement *statements_;
+    CYStatement *code_;
 
-    CYObjCBlock(CYTypedIdentifier *typed, CYTypedParameter *parameters, CYStatement *statements) :
+    CYObjCBlock(CYTypedIdentifier *typed, CYTypedParameter *parameters, CYStatement *code) :
         typed_(typed),
         parameters_(parameters),
-        statements_(statements)
+        code_(code)
     {
     }
 
@@ -151,11 +151,11 @@ struct CYMessage :
     CYMessageParameter *parameters_;
     CYBlock code_;
 
-    CYMessage(bool instance, CYTypedIdentifier *type, CYMessageParameter *parameter, CYStatement *statements) :
+    CYMessage(bool instance, CYTypedIdentifier *type, CYMessageParameter *parameter, CYStatement *code) :
         instance_(instance),
         type_(type),
         parameters_(parameter),
-        code_(statements)
+        code_(code)
     {
     }
 
index 12c72df46b4210e075240c9372619cebd03abd90..50740050b40694f718ef41322e3770d1456901f6 100644 (file)
@@ -137,24 +137,14 @@ void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
     rhs_->Output(out, Precedence(), CYRight(flags));
 }
 
-void CYBlock::Output(CYOutput &out) const {
+void CYBlock::Output(CYOutput &out, CYFlags flags) const {
     out << '{' << '\n';
     ++out.indent_;
-    if (statements_ != NULL)
-        statements_->Multiple(out);
+    out << code_;
     --out.indent_;
     out << '\t' << '}';
 }
 
-void CYBlock::Output(CYOutput &out, CYFlags flags) const {
-    if (statements_ == NULL)
-        out.Terminate();
-    else if (statements_->next_ == NULL)
-        statements_->Single(out, flags);
-    else
-        Output(out);
-}
-
 void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
     out << (Value() ? "true" : "false");
 }
@@ -180,7 +170,12 @@ namespace cy {
 namespace Syntax {
 
 void Catch::Output(CYOutput &out) const {
-    out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
+    out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ';
+    out << '{' << '\n';
+    ++out.indent_;
+    out << code_;
+    --out.indent_;
+    out << '\t' << '}';
 }
 
 } }
@@ -224,8 +219,7 @@ void CYClause::Output(CYOutput &out) const {
     else
         out << "default";
     out << ':' << '\n';
-    if (statements_ != NULL)
-        statements_->Multiple(out);
+    out << code_;
     out << next_;
 }
 
@@ -334,11 +328,16 @@ void CYExternal::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
-    out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << code_;
+    out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << '{' << code_ << '}';
 }
 
 void CYFinally::Output(CYOutput &out) const {
-    out << ' ' << "finally" << ' ' << code_;
+    out << ' ' << "finally" << ' ';
+    out << '{' << '\n';
+    ++out.indent_;
+    out << code_;
+    --out.indent_;
+    out << '\t' << '}';
 }
 
 void CYFor::Output(CYOutput &out, CYFlags flags) const {
@@ -388,8 +387,12 @@ void CYFunction::Output(CYOutput &out, CYFlags flags) const {
     out << "function";
     if (name_ != NULL)
         out << ' ' << *name_;
-    out << '(' << parameters_ << ')';
-    out << ' ' << code_;
+    out << '(' << parameters_ << ')' << ' ';
+    out << '{' << '\n';
+    ++out.indent_;
+    out << code_;
+    --out.indent_;
+    out << '\t' << '}';
     if (protect)
         out << ')';
 }
@@ -475,6 +478,16 @@ void CYLabel::Output(CYOutput &out, CYFlags flags) const {
     statement_->Single(out, CYRight(flags));
 }
 
+void CYParenthetical::Output(CYOutput &out, CYFlags flags) const {
+    out << '(';
+    expression_->Output(out, CYCompound::Precedence_, CYNoFlags);
+    out << ')';
+}
+
+void CYStatement::Output(CYOutput &out) const {
+    Multiple(out);
+}
+
 void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
     next_->Output(out, Precedence(), identifier);
     out << '[';
@@ -619,8 +632,7 @@ void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYProgram::Output(CYOutput &out) const {
-    if (statements_ != NULL)
-        statements_->Multiple(out);
+    out << code_;
 }
 
 void CYProperty::Output(CYOutput &out) const {
@@ -653,7 +665,11 @@ void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
 
 void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
     // XXX: this is not outputting the parameters
+    out << '{' << '\n';
+    ++out.indent_;
     out << code_;
+    --out.indent_;
+    out << '\t' << '}';
 }
 
 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
@@ -750,7 +766,13 @@ void Throw::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void Try::Output(CYOutput &out, CYFlags flags) const {
-    out << "try" << ' ' << code_ << catch_ << finally_;
+    out << "try" << ' ';
+    out << '{' << '\n';
+    ++out.indent_;
+    out << code_;
+    --out.indent_;
+    out << '\t' << '}';
+    out << catch_ << finally_;
 }
 
 } }
index e02a16610eafe199d14c5480baffe5f99230be40..8bd7cdc6f26fbae55e9c024b0d45ae30cee9247b 100644 (file)
@@ -146,13 +146,15 @@ _finline CYFlags CYCenter(CYFlags flags) {
 }
 
 struct CYStatement :
-    CYNext<CYStatement>
+    CYNext<CYStatement>,
+    CYThing
 {
     virtual ~CYStatement() {
     }
 
     void Single(CYOutput &out, CYFlags flags) const;
     void Multiple(CYOutput &out, CYFlags flags = CYNoFlags) const;
+    virtual void Output(CYOutput &out) const;
 
     virtual CYStatement *Replace(CYContext &context) = 0;
 
@@ -329,10 +331,10 @@ struct CYScope {
 struct CYProgram :
     CYThing
 {
-    CYStatement *statements_;
+    CYStatement *code_;
 
-    CYProgram(CYStatement *statements) :
-        statements_(statements)
+    CYProgram(CYStatement *code) :
+        code_(code)
     {
     }
 
@@ -368,14 +370,18 @@ struct CYContext {
     virtual ~CYContext() {
     }
 
-    template <typename Type_>
-    void ReplaceAll(Type_ *&values) {
-        Type_ **last(&values);
-        CYForEach (next, values) {
-            Replace(*last = next);
-            if (*last != NULL)
-                last = &(*last)->next_;
-        }
+    void ReplaceAll(CYStatement *&statement) {
+        if (statement == NULL)
+            return;
+        CYStatement *next(statement->next_);
+
+        Replace(statement);
+        ReplaceAll(next);
+
+        if (statement == NULL)
+            statement = next;
+        else
+            statement->SetNext(next);
     }
 
     template <typename Type_>
@@ -429,28 +435,17 @@ struct CYThisScope :
 };
 
 struct CYBlock :
-    CYStatement,
-    CYThing
+    CYStatement
 {
-    CYStatement *statements_;
+    CYStatement *code_;
 
-    CYBlock(CYStatement *statements) :
-        statements_(statements)
+    CYBlock(CYStatement *code) :
+        code_(code)
     {
     }
 
-    operator CYStatement *() const {
-        return statements_;
-    }
-
-    void AddPrev(CYStatement *statement) {
-        CYSetLast(statement) = statements_;
-        statements_ = statement;
-    }
-
     virtual CYStatement *Replace(CYContext &context);
 
-    virtual void Output(CYOutput &out) const;
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -512,7 +507,6 @@ struct CYExpression :
     }
 
     virtual CYFunctionParameter *Parameter() const;
-    virtual CYFunctionParameter *Parameters() const;
 
     virtual CYNumber *Number(CYContext &context) {
         return NULL;
@@ -549,13 +543,12 @@ struct CYCompound :
     CYExpression *expression_;
     CYExpression *next_;
 
-    CYCompound(CYExpression *expression, CYExpression *next = NULL) :
+    CYCompound(CYExpression *expression, CYExpression *next) :
         expression_(expression),
         next_(next)
     {
-        if (expression_ == NULL)
-            throw;
         _assert(expression_ != NULL);
+        _assert(next != NULL);
     }
 
     CYPrecedence(17)
@@ -563,8 +556,23 @@ struct CYCompound :
     virtual CYExpression *Replace(CYContext &context);
     void Output(CYOutput &out, CYFlags flags) const;
 
-    virtual CYExpression *Primitive(CYContext &context);
-    virtual CYFunctionParameter *Parameters() const;
+    virtual CYFunctionParameter *Parameter() const;
+};
+
+struct CYParenthetical :
+    CYExpression
+{
+    CYExpression *expression_;
+
+    CYParenthetical(CYExpression *expression) :
+        expression_(expression)
+    {
+    }
+
+    CYPrecedence(0)
+
+    virtual CYExpression *Replace(CYContext &context);
+    void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYDeclaration;
@@ -581,7 +589,7 @@ struct CYFunctionParameter :
     {
     }
 
-    void Replace(CYContext &context, CYBlock &code);
+    void Replace(CYContext &context, CYStatement *&statements);
     void Output(CYOutput &out) const;
 };
 
@@ -1037,11 +1045,11 @@ struct CYClause :
     CYNext<CYClause>
 {
     CYExpression *case_;
-    CYStatement *statements_;
+    CYStatement *code_;
 
-    CYClause(CYExpression *_case, CYStatement *statements) :
+    CYClause(CYExpression *_case, CYStatement *code) :
         case_(_case),
-        statements_(statements)
+        code_(code)
     {
     }
 
@@ -1134,7 +1142,7 @@ struct CYDeclarations :
 
     void Replace(CYContext &context);
 
-    CYCompound *Compound(CYContext &context);
+    CYExpression *Expression(CYContext &context);
     CYProperty *Property(CYContext &context);
     CYArgument *Argument(CYContext &context);
     CYFunctionParameter *Parameter(CYContext &context);
@@ -1153,7 +1161,7 @@ struct CYForDeclarations :
     {
     }
 
-    virtual CYCompound *Replace(CYContext &context);
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1429,15 +1437,15 @@ struct CYWhile :
 struct CYFunction {
     CYIdentifier *name_;
     CYFunctionParameter *parameters_;
-    CYBlock code_;
+    CYStatement *code_;
 
     CYNonLocal *nonlocal_;
     CYThisScope this_;
 
-    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *statements) :
+    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *code) :
         name_(name),
         parameters_(parameters),
-        code_(statements),
+        code_(code),
         nonlocal_(NULL)
     {
     }
@@ -1455,8 +1463,8 @@ struct CYFunctionExpression :
     CYFunction,
     CYExpression
 {
-    CYFunctionExpression(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *statements) :
-        CYFunction(name, parameters, statements)
+    CYFunctionExpression(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *code) :
+        CYFunction(name, parameters, code)
     {
     }
 
@@ -1472,8 +1480,8 @@ struct CYFatArrow :
     CYFunction,
     CYExpression
 {
-    CYFatArrow(CYFunctionParameter *parameters, CYStatement *statements) :
-        CYFunction(NULL, parameters, statements)
+    CYFatArrow(CYFunctionParameter *parameters, CYStatement *code) :
+        CYFunction(NULL, parameters, code)
     {
     }
 
@@ -1488,8 +1496,8 @@ struct CYFatArrow :
 struct CYRubyProc :
     CYFunctionExpression
 {
-    CYRubyProc(CYFunctionParameter *parameters, CYStatement *statements) :
-        CYFunctionExpression(NULL, parameters, statements)
+    CYRubyProc(CYFunctionParameter *parameters, CYStatement *code) :
+        CYFunctionExpression(NULL, parameters, code)
     {
     }
 
@@ -1502,8 +1510,8 @@ struct CYFunctionStatement :
     CYFunction,
     CYStatement
 {
-    CYFunctionStatement(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *statements) :
-        CYFunction(name, parameters, statements)
+    CYFunctionStatement(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *code) :
+        CYFunction(name, parameters, code)
     {
     }
 
@@ -1579,10 +1587,10 @@ struct CYEmpty :
 struct CYFinally :
     CYThing
 {
-    CYBlock code_;
+    CYStatement *code_;
 
-    CYFinally(CYStatement *statements) :
-        code_(statements)
+    CYFinally(CYStatement *code) :
+        code_(code)
     {
     }
 
@@ -1846,12 +1854,12 @@ struct CYLambda :
 {
     CYTypedIdentifier *typed_;
     CYTypedParameter *parameters_;
-    CYStatement *statements_;
+    CYStatement *code_;
 
-    CYLambda(CYTypedIdentifier *typed, CYTypedParameter *parameters, CYStatement *statements) :
+    CYLambda(CYTypedIdentifier *typed, CYTypedParameter *parameters, CYStatement *code) :
         typed_(typed),
         parameters_(parameters),
-        statements_(statements)
+        code_(code)
     {
     }
 
@@ -1964,11 +1972,11 @@ struct Catch :
     CYThing
 {
     CYIdentifier *name_;
-    CYBlock code_;
+    CYStatement *code_;
 
-    Catch(CYIdentifier *name, CYStatement *statements) :
+    Catch(CYIdentifier *name, CYStatement *code) :
         name_(name),
-        code_(statements)
+        code_(code)
     {
     }
 
@@ -1979,12 +1987,12 @@ struct Catch :
 struct Try :
     CYStatement
 {
-    CYBlock code_;
+    CYStatement *code_;
     Catch *catch_;
     CYFinally *finally_;
 
-    Try(CYStatement *statements, Catch *_catch, CYFinally *finally) :
-        code_(statements),
+    Try(CYStatement *code, Catch *_catch, CYFinally *finally) :
+        code_(code),
         catch_(_catch),
         finally_(finally)
     {
index 0f53d926a37e828f5aff1e5d74de94a4e1dc1845..74f04d9d489f7712d48366cd7837dc44ca35a32e 100644 (file)
@@ -96,8 +96,8 @@ CYExpression *CYAssignment::Replace(CYContext &context) {
 }
 
 CYStatement *CYBlock::Replace(CYContext &context) {
-    context.ReplaceAll(statements_);
-    if (statements_ == NULL)
+    context.ReplaceAll(code_);
+    if (code_ == NULL)
         return $ CYEmpty();
     return this;
 }
@@ -129,15 +129,15 @@ void Catch::Replace(CYContext &context) { $T()
     context.Replace(name_);
     context.scope_->Declare(context, name_, CYIdentifierCatch);
 
-    code_.Replace(context);
-    scope.Close(context, code_.statements_);
+    context.ReplaceAll(code_);
+    scope.Close(context, code_);
 }
 
 } }
 
 void CYClause::Replace(CYContext &context) { $T()
     context.Replace(case_);
-    context.ReplaceAll(statements_);
+    context.ReplaceAll(code_);
     next_->Replace(context);
 }
 
@@ -146,9 +146,6 @@ CYStatement *CYComment::Replace(CYContext &context) {
 }
 
 CYExpression *CYCompound::Replace(CYContext &context) {
-    if (next_ == NULL)
-        return expression_;
-
     context.Replace(expression_);
     context.Replace(next_);
 
@@ -162,22 +159,10 @@ CYExpression *CYCompound::Replace(CYContext &context) {
     return this;
 }
 
-CYExpression *CYCompound::Primitive(CYContext &context) {
-    CYExpression *expression(expression_);
-    if (expression == NULL || next_ != NULL)
+CYFunctionParameter *CYCompound::Parameter() const {
+    CYFunctionParameter *next(next_->Parameter());
+    if (next == NULL)
         return NULL;
-    return expression->Primitive(context);
-}
-
-CYFunctionParameter *CYCompound::Parameters() const {
-    CYFunctionParameter *next;
-    if (next_ == NULL)
-        next = NULL;
-    else {
-        next = next_->Parameters();
-        if (next == NULL)
-            return NULL;
-    }
 
     CYFunctionParameter *parameter(expression_->Parameter());
     if (parameter == NULL)
@@ -223,6 +208,7 @@ void CYContext::NonLocal(CYStatement *&statements) {
                     $ CYReturn($M($V(cye), $S("$cyv"))))->*
                 $ cy::Syntax::Throw($V(cye))));
 
+        // XXX: I don't understand any of this
         context.Replace(declare);
         rescue->Replace(context);
 
@@ -284,10 +270,13 @@ CYArgument *CYDeclarations::Argument(CYContext &context) { $T(NULL)
     return $ CYArgument(declaration_->initialiser_, next_->Argument(context));
 }
 
-CYCompound *CYDeclarations::Compound(CYContext &context) { $T(NULL)
-    CYCompound *compound(next_->Compound(context));
+CYExpression *CYDeclarations::Expression(CYContext &context) { $T(NULL)
+    CYExpression *compound(next_->Expression(context));
     if (CYAssignment *assignment = declaration_->Assignment(context))
-        compound = $ CYCompound(assignment, compound);
+        if (compound == NULL)
+            compound = assignment;
+        else
+            compound = $ CYCompound(assignment, compound);
     return compound;
 }
 
@@ -299,7 +288,7 @@ CYExpression *CYDirectMember::Replace(CYContext &context) {
 
 CYStatement *CYDoWhile::Replace(CYContext &context) {
     context.Replace(test_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }
 
@@ -317,15 +306,7 @@ CYExpression *CYEncodedType::Replace(CYContext &context) {
 }
 
 CYStatement *CYExpress::Replace(CYContext &context) {
-    while (CYExpress *express = dynamic_cast<CYExpress *>(next_)) {
-        expression_ = $ CYCompound(expression_, express->expression_);
-        SetNext(express->next_);
-    }
-
     context.Replace(expression_);
-    if (expression_ == NULL)
-        return $ CYEmpty();
-
     return this;
 }
 
@@ -349,10 +330,6 @@ CYFunctionParameter *CYExpression::Parameter() const {
     return NULL;
 }
 
-CYFunctionParameter *CYExpression::Parameters() const {
-    return NULL;
-}
-
 CYStatement *CYExternal::Replace(CYContext &context) {
     return $E($ CYAssign($V(typed_->identifier_), $C1(typed_->Replace(context), $C2($V("dlsym"), $V("RTLD_DEFAULT"), $S(typed_->identifier_->Word())))));
 }
@@ -372,20 +349,20 @@ CYExpression *CYFatArrow::Replace(CYContext &context) {
 }
 
 void CYFinally::Replace(CYContext &context) { $T()
-    code_.Replace(context);
+    context.ReplaceAll(code_);
 }
 
 CYStatement *CYFor::Replace(CYContext &context) {
     context.Replace(initialiser_);
     context.Replace(test_);
     context.Replace(increment_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }
 
-CYCompound *CYForDeclarations::Replace(CYContext &context) {
+CYExpression *CYForDeclarations::Replace(CYContext &context) {
     declarations_->Replace(context);
-    return declarations_->Compound(context);
+    return declarations_->Expression(context);
 }
 
 // XXX: this still feels highly suboptimal
@@ -398,7 +375,7 @@ CYStatement *CYForIn::Replace(CYContext &context) {
 
     context.Replace(initialiser_);
     context.Replace(set_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }
 
@@ -474,22 +451,22 @@ void CYFunction::Replace_(CYContext &context, bool outer) {
         Inject(context);
 
     parameters_->Replace(context, code_);
-    code_.Replace(context);
+    context.ReplaceAll(code_);
 
     if (CYIdentifier *identifier = this_.identifier_)
-        code_.statements_ = $$->*
+        code_ = $$->*
             $ CYVar($L1($ CYDeclaration(identifier, $ CYThis())))->*
-            code_.statements_;
+            code_;
 
     if (localize)
-        context.NonLocal(code_.statements_);
+        context.NonLocal(code_);
 
     context.nextlocal_ = nextlocal;
     context.nonlocal_ = nonlocal;
 
     context.this_ = _this;
 
-    scope.Close(context, code_.statements_);
+    scope.Close(context, code_);
 }
 
 CYExpression *CYFunctionExpression::Replace(CYContext &context) {
@@ -497,17 +474,19 @@ CYExpression *CYFunctionExpression::Replace(CYContext &context) {
     return this;
 }
 
-void CYFunctionParameter::Replace(CYContext &context, CYBlock &code) { $T()
+void CYFunctionParameter::Replace(CYContext &context, CYStatement *&statements) { $T()
     CYAssignment *assignment(initialiser_->Assignment(context));
     context.Replace(initialiser_);
 
-    next_->Replace(context, code);
+    next_->Replace(context, statements);
 
     if (assignment != NULL)
-        // XXX: this cast is quite incorrect
-        code.AddPrev($ CYIf($ CYIdentical($ CYTypeOf(dynamic_cast<CYExpression *>(initialiser_)), $S("undefined")), $$->*
-            $E(assignment)
-        ));
+        statements = $$->*
+            // XXX: this cast is quite incorrect
+            $ CYIf($ CYIdentical($ CYTypeOf(dynamic_cast<CYExpression *>(initialiser_)), $S("undefined")), $$->*
+                $E(assignment)
+            )->*
+            statements;
 }
 
 CYStatement *CYFunctionStatement::Replace(CYContext &context) {
@@ -524,8 +503,8 @@ CYIdentifier *CYIdentifier::Replace(CYContext &context) {
 
 CYStatement *CYIf::Replace(CYContext &context) {
     context.Replace(test_);
-    context.Replace(true_);
-    context.Replace(false_);
+    context.ReplaceAll(true_);
+    context.ReplaceAll(false_);
     return this;
 }
 
@@ -561,7 +540,7 @@ CYStatement *CYLabel::Replace(CYContext &context) {
 }
 
 CYExpression *CYLambda::Replace(CYContext &context) {
-    return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), statements_), parameters_->TypeSignature(context, typed_->Replace(context)));
+    return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_), parameters_->TypeSignature(context, typed_->Replace(context)));
 }
 
 CYStatement *CYLetStatement::Replace(CYContext &context) {
@@ -622,6 +601,10 @@ CYExpression *CYObject::Replace(CYContext &context) {
     return this;
 }
 
+CYExpression *CYParenthetical::Replace(CYContext &context) {
+    return expression_;
+}
+
 CYExpression *CYPostfix::Replace(CYContext &context) {
     context.Replace(lhs_);
     return this;
@@ -654,10 +637,10 @@ void CYProgram::Replace(CYContext &context) {
     CYScope scope(true, context);
 
     context.nextlocal_ = $ CYNonLocal();
-    context.ReplaceAll(statements_);
-    context.NonLocal(statements_);
+    context.ReplaceAll(code_);
+    context.NonLocal(code_);
 
-    scope.Close(context, statements_);
+    scope.Close(context, code_);
 
     size_t offset(0);
 
@@ -904,7 +887,7 @@ namespace cy {
 namespace Syntax {
 
 CYStatement *Try::Replace(CYContext &context) {
-    code_.Replace(context);
+    context.ReplaceAll(code_);
     catch_->Replace(context);
     finally_->Replace(context);
     return this;
@@ -1004,8 +987,8 @@ CYExpression *CYTypedParameter::TypeSignature(CYContext &context, CYExpression *
 
 CYStatement *CYVar::Replace(CYContext &context) {
     declarations_->Replace(context);
-    if (CYCompound *compound = declarations_->Compound(context))
-        return $E(compound);
+    if (CYExpression *expression = declarations_->Expression(context))
+        return $E(expression);
     return $ CYEmpty();
 }
 
@@ -1020,13 +1003,13 @@ CYFunctionParameter *CYVariable::Parameter() const {
 
 CYStatement *CYWhile::Replace(CYContext &context) {
     context.Replace(test_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }
 
 CYStatement *CYWith::Replace(CYContext &context) {
     context.Replace(scope_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }