]> git.saurik.com Git - cycript.git/commitdiff
Completely rewrote the output serializer to instead do replacement on the parse tree...
authorJay Freeman (saurik) <saurik@saurik.com>
Thu, 22 Oct 2009 05:48:50 +0000 (05:48 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Thu, 22 Oct 2009 05:48:50 +0000 (05:48 +0000)
Console.cpp
Cycript.y
Library.mm
Output.cpp
Parser.hpp
Replace.cpp [new file with mode: 0644]
makefile

index 3a911cd2e0d5b013488eee85493029947aa93969..9a60679ce5d2b3aab178307b026b5c872bd17694 100644 (file)
@@ -106,8 +106,11 @@ void Setup(CYDriver &driver, cy::parser &parser) {
         driver.strict_ = true;
 }
 
-void Setup(CYOutput &out) {
+void Setup(CYOutput &out, CYDriver &driver) {
     out.pretty_ = pretty_;
+
+    CYContext context(driver.pool_);
+    driver.program_->Replace(context);
 }
 
 void Run(int socket, const char *data, size_t size, FILE *fout = NULL, bool expand = false) {
@@ -293,8 +296,8 @@ static void Console(int socket) {
             else {
                 std::ostringstream str;
                 CYOutput out(str);
-                Setup(out);
-                driver.program_->Multiple(out);
+                Setup(out, driver);
+                out << *driver.program_;
                 code = str.str();
             }
         }
@@ -464,8 +467,8 @@ int main(int argc, char *argv[]) {
             else {
                 std::ostringstream str;
                 CYOutput out(str);
-                Setup(out);
-                driver.program_->Multiple(out);
+                Setup(out, driver);
+                out << *driver.program_;
                 std::string code(str.str());
                 if (compile)
                     std::cout << code;
index 151f950725ea7047d0cea8f3f27a2a2dc50a51a2..7fdc17245fea856fea26cefd64074652cb0ebc2d 100644 (file)
--- a/Cycript.y
+++ b/Cycript.y
@@ -80,6 +80,7 @@ typedef struct {
         CYMessageParameter *messageParameter_;
         CYNull *null_;
         CYNumber *number_;
+        CYProgram *program_;
         CYProperty *property_;
         CYPropertyName *propertyName_;
         CYSelectorPart *selector_;
@@ -1244,7 +1245,7 @@ DefaultClause
 /* }}} */
 /* 12.12 Labelled Statements {{{ */
 LabelledStatement
-    : Identifier ":" Statement { $3->AddLabel($1); $$ = $3; }
+    : Identifier ":" Statement { $$ = new(driver.pool_) CYLabel($1, $3); }
     ;
 /* }}} */
 /* 12.13 The throw Statement {{{ */
@@ -1293,7 +1294,7 @@ FunctionBody
 /* }}} */
 /* 14 Program {{{ */
 Program
-    : SourceElements { driver.program_ = $1; }
+    : SourceElements { driver.program_ = new(driver.pool_) CYProgram($1); }
     ;
 
 SourceElements
@@ -1438,7 +1439,8 @@ UnaryExpression_
     ;
 
 MemberAccess
-    : "->" Identifier { $$ = new(driver.pool_) CYIndirectMember(NULL, new(driver.pool_) CYString($2)); }
+    : "->" "[" Expression "]" { $$ = new(driver.pool_) CYIndirectMember(NULL, $3); }
+    | "->" Identifier { $$ = new(driver.pool_) CYIndirectMember(NULL, new(driver.pool_) CYString($2)); }
     ;
 /* }}} */
 /* ECMAScript5: Object Literal Trailing Comma {{{ */
index 45126dceebb44126a6028e6fa94e3b1929de23b4..eb64e4567c46ca53f5daa7aa1165e655f607f22b 100644 (file)
@@ -3477,7 +3477,7 @@ struct CYClient :
             } else {
                 std::ostringstream str;
                 CYOutput out(str);
-                driver.program_->Multiple(out);
+                out << *driver.program_;
                 std::string code(str.str());
                 CYExecute_ execute = {pool, code.c_str()};
                 [client performSelectorOnMainThread:@selector(execute:) withObject:[NSValue valueWithPointer:&execute] waitUntilDone:YES];
index 1e4d437045d77f3804fff807cfce8b1bd22be462..efbf55b1ea73cbc02c88cdd2efc854fdb944f641 100644 (file)
@@ -111,20 +111,6 @@ CYOutput &CYOutput::operator <<(const char *rhs) {
     return *this;
 }
 
-void OutputBody(CYOutput &out, CYStatement *body) {
-    out << ' ' << '{' << '\n';
-    ++out.indent_;
-    if (body != NULL)
-        body->Multiple(out);
-    --out.indent_;
-    out << '\t' << '}';
-}
-
-void CYAddressOf::Output(CYOutput &out, CYFlags flags) const {
-    rhs_->Output(out, 1, CYLeft(flags));
-    out << ".$cya()";
-}
-
 void CYArgument::Output(CYOutput &out) const {
     if (name_ != NULL) {
         out << *name_;
@@ -168,8 +154,22 @@ void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
     rhs_->Output(out, Precedence(), CYRight(flags));
 }
 
+void CYBlock::Output(CYOutput &out) const {
+    out << '{' << '\n';
+    ++out.indent_;
+    if (statements_ != NULL)
+        statements_->Multiple(out);
+    --out.indent_;
+    out << '\t' << '}';
+}
+
 void CYBlock::Output(CYOutput &out, CYFlags flags) const {
-    statements_->Single(out, flags);
+    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 {
@@ -194,10 +194,7 @@ void CYCall::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYCatch::Output(CYOutput &out) const {
-    out << "catch" << ' ' << '(' << *name_ << ')' << ' ' << '{';
-    if (code_ != NULL)
-        code_->Multiple(out);
-    out << '}';
+    out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
 }
 
 void CYCategory::Output(CYOutput &out, CYFlags flags) const {
@@ -288,8 +285,8 @@ void CYClause::Output(CYOutput &out) const {
     else
         out << "default";
     out << ':' << '\n';
-    if (code_ != NULL)
-        code_->Multiple(out, CYNoFlags);
+    if (statements_ != NULL)
+        statements_->Multiple(out);
     out << next_;
 }
 
@@ -410,10 +407,7 @@ void CYField::Output(CYOutput &out) const {
 }
 
 void CYFinally::Output(CYOutput &out) const {
-    out << "finally" << ' ' << '{';
-    if (code_ != NULL)
-        code_->Multiple(out);
-    out << '}';
+    out << ' ' << "finally" << ' ' << code_;
 }
 
 void CYFor::Output(CYOutput &out, CYFlags flags) const {
@@ -481,7 +475,7 @@ void CYFunction::Output(CYOutput &out, CYFlags flags) const {
     if (name_ != NULL)
         out << ' ' << *name_;
     out << '(' << parameters_ << ')';
-    OutputBody(out, body_);
+    out << ' ' << code_;
     if (protect)
         out << ')';
 }
@@ -517,10 +511,9 @@ void CYIf::Output(CYOutput &out, CYFlags flags) const {
     else
         jacks |= protect ? CYNoFlags : CYCenter(flags);
 
-    bool single(true_->Single(out, jacks));
+    true_->Single(out, jacks);
 
     if (false_ != NULL) {
-        out << (single ? '\t' : ' ');
         out << "else";
         false_->Single(out, right);
     }
@@ -533,18 +526,12 @@ void CYIfComprehension::Begin_(CYOutput &out) const {
     out << "if" << '(' << *test_ << ')';
 }
 
-void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
-    rhs_->Output(out, 1, CYLeft(flags));
-    out << ".$cyi";
-}
-
 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
     object_->Output(out, Precedence(), CYLeft(flags));
-    out << ".$cyi";
     if (const char *word = property_->Word())
-        out << '.' << word;
+        out << "->" << word;
     else
-        out << '[' << *property_ << ']';
+        out << "->" << '[' << *property_ << ']';
 }
 
 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
@@ -561,33 +548,35 @@ void CYInfix::Output(CYOutput &out, CYFlags flags) const {
         out << ')';
 }
 
+void CYLabel::Output(CYOutput &out, CYFlags flags) const {
+    out << *name_ << ':' << ' ';
+    statement_->Single(out, CYRight(flags));
+}
+
 void CYLet::Output(CYOutput &out, CYFlags flags) const {
-    out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << '{';
-    if (statements_ != NULL)
-        statements_->Multiple(out);
-    out << '}';
+    out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
 }
 
 void CYMessage::Output(CYOutput &out, bool replace) const {
     if (next_ != NULL)
         next_->Output(out, replace);
     out << "$cyn=new Selector(\"";
-    for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
+    for (CYMessageParameter *parameter(parameters_); parameter != NULL; parameter = parameter->next_)
         if (parameter->tag_ != NULL) {
             out << *parameter->tag_;
             if (parameter->name_ != NULL)
                 out << ':';
         }
     out << "\");";
-    out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");";
-    out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
+    out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ')' << ';';
+    out << (replace ? "class_replaceMethod" : "class_addMethod") << '(' << (instance_ ? "$cyc" : "$cym") << ',' << "$cyn" << ',';
     out << "new Functor(function(self,_cmd";
-    for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
+    for (CYMessageParameter *parameter(parameters_); parameter != NULL; parameter = parameter->next_)
         if (parameter->name_ != NULL)
             out << ',' << *parameter->name_;
     out << "){return function(){";
-    if (body_ != NULL)
-        body_->Multiple(out);
+    if (statements_ != NULL)
+        statements_->Multiple(out);
     out << "}.call(self);},$cyt),$cyt);";
 }
 
@@ -619,7 +608,7 @@ void CYObject::Output(CYOutput &out, CYFlags flags) const {
         out << '(';
     out << '{' << '\n';
     ++out.indent_;
-    out << property_;
+    out << properties_;
     --out.indent_;
     out << '\t' << '}';
     if (protect)
@@ -639,6 +628,11 @@ void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
     rhs_->Output(out, Precedence(), CYRight(flags));
 }
 
+void CYProgram::Output(CYOutput &out) const {
+    if (statements_ != NULL)
+        statements_->Multiple(out);
+}
+
 void CYProperty::Output(CYOutput &out) const {
     out << '\t';
     name_->PropertyName(out);
@@ -662,10 +656,7 @@ void CYReturn::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYSelector::Output(CYOutput &out, CYFlags flags) const {
-    out << "new Selector(\"";
-    if (name_ != NULL)
-        name_->Output(out);
-    out << "\")";
+    out << "@selector" << '(' << name_ << ')';
 }
 
 void CYSelectorPart::Output(CYOutput &out) const {
@@ -676,9 +667,10 @@ void CYSelectorPart::Output(CYOutput &out) const {
 }
 
 void CYSend::Output(CYOutput &out, CYFlags flags) const {
-    out << "objc_msgSend(";
+    out << '[';
     self_->Output(out, CYPA, CYNoFlags);
-    out << ',';
+    out << ']';
+
     std::ostringstream name;
     for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
         if (argument->name_ != NULL) {
@@ -686,6 +678,7 @@ void CYSend::Output(CYOutput &out, CYFlags flags) const {
             if (argument->value_ != NULL)
                 name << ':';
         }
+
     out.out_ << reinterpret_cast<void *>(sel_registerName(name.str().c_str()));
     for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
         if (argument->value_ != NULL) {
@@ -707,25 +700,14 @@ void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
     }
 }
 
-bool CYStatement::Single(CYOutput &out, CYFlags flags) const {
-    if (next_ != NULL) {
-        out << ' ' << '{' << '\n';
-        ++out.indent_;
-        Multiple(out);
-        --out.indent_;
-        out << '\t' << '}';
-        return false;
-    } else {
-        for (CYLabel *label(labels_); label != NULL; label = label->next_)
-            out << ' ' << *label->name_ << ':';
-        out << '\n';
-        ++out.indent_;
-        out << '\t';
-        Output(out, flags);
-        out << '\n';
-        --out.indent_;
-        return true;
-    }
+void CYStatement::Single(CYOutput &out, CYFlags flags) const {
+    _assert(next_ == NULL);
+    out << '\n';
+    ++out.indent_;
+    out << '\t';
+    Output(out, flags);
+    out << '\n';
+    --out.indent_;
 }
 
 void CYString::Output(CYOutput &out, CYFlags flags) const {
@@ -836,12 +818,7 @@ void CYThrow::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYTry::Output(CYOutput &out, CYFlags flags) const {
-    out << "try" << ' ' << '{';
-    if (code_ != NULL)
-        code_->Multiple(out);
-    out << '}';
-    out << catch_;
-    out << finally_;
+    out << "try" << ' ' << code_ << catch_ << finally_;
 }
 
 void CYVar::Output(CYOutput &out, CYFlags flags) const {
index a9a881296312c5dc9b520601c428861ed10ac2ab..e954748e6a01fb667ef86f3651a3873932d4b811 100644 (file)
@@ -113,7 +113,86 @@ struct CYPropertyName {
     virtual void PropertyName(CYOutput &out) const = 0;
 };
 
+struct CYExpression;
+
+enum CYNeeded {
+    CYNever     = -1,
+    CYSometimes =  0,
+    CYAlways    =  1,
+};
+
+enum CYFlags {
+    CYNoFlags =      0,
+    CYNoBrace =      (1 << 0),
+    CYNoFunction =   (1 << 1),
+    CYNoIn =         (1 << 2),
+    CYNoCall =       (1 << 3),
+    CYNoRightHand =  (1 << 4),
+    CYNoDangle =     (1 << 5),
+    CYNoBF =         (CYNoBrace | CYNoFunction),
+};
+
+struct CYContext {
+    apr_pool_t *pool_;
+
+    CYContext(apr_pool_t *pool) :
+        pool_(pool)
+    {
+    }
+
+    template <typename Type_>
+    void Replace(Type_ *&value) {
+        if (value != NULL)
+            while (Type_ *replace = value->Replace(*this))
+                value = replace;
+    }
+};
+
+struct CYStatement :
+    CYNext<CYStatement>
+{
+    void Single(CYOutput &out, CYFlags flags) const;
+    void Multiple(CYOutput &out, CYFlags flags = CYNoFlags) const;
+
+    CYStatement *ReplaceAll(CYContext &context);
+
+    virtual CYStatement *Replace(CYContext &context) = 0;
+
+  private:
+    virtual void Output(CYOutput &out, CYFlags flags) const = 0;
+};
+
+struct CYStatements {
+    CYStatement *first_;
+    CYStatement *last_;
+
+    CYStatements() :
+        first_(NULL),
+        last_(NULL)
+    {
+    }
+
+    operator CYStatement *() const {
+        return first_;
+    }
+
+    CYStatements &operator ->*(CYStatement *next) {
+        if (next != NULL)
+            if (first_ == NULL) {
+                first_ = next;
+                last_ = next;
+            } else for (;; last_ = last_->next_)
+                if (last_->next_ == NULL) {
+                    last_->next_ = next;
+                    last_ = next;
+                    break;
+                }
+        return *this;
+    }
+};
+
 struct CYClassName {
+    virtual CYExpression *ClassName(CYContext &context, bool object) = 0;
     virtual void ClassName(CYOutput &out, bool object) const = 0;
 };
 
@@ -135,6 +214,7 @@ struct CYWord :
 
     virtual void Output(CYOutput &out) const;
 
+    virtual CYExpression *ClassName(CYContext &context, bool object);
     virtual void ClassName(CYOutput &out, bool object) const;
     virtual void PropertyName(CYOutput &out) const;
 };
@@ -153,57 +233,39 @@ struct CYIdentifier :
 };
 
 struct CYLabel :
-    CYNext<CYLabel>
+    CYStatement
 {
     CYIdentifier *name_;
+    CYStatement *statement_;
 
-    CYLabel(CYIdentifier *name, CYLabel *next) :
-        CYNext<CYLabel>(next),
-        name_(name)
+    CYLabel(CYIdentifier *name, CYStatement *statement) :
+        name_(name),
+        statement_(statement)
     {
     }
-};
-
-enum CYNeeded {
-    CYNever     = -1,
-    CYSometimes =  0,
-    CYAlways    =  1,
-};
 
-enum CYFlags {
-    CYNoFlags =      0,
-    CYNoBrace =      (1 << 0),
-    CYNoFunction =   (1 << 1),
-    CYNoIn =         (1 << 2),
-    CYNoCall =       (1 << 3),
-    CYNoRightHand =  (1 << 4),
-    CYNoDangle =     (1 << 5),
-    CYNoBF =         (CYNoBrace | CYNoFunction),
+    virtual CYStatement *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
-struct CYStatement :
-    CYNext<CYStatement>
+struct CYProgram :
+    CYThing
 {
-    CYLabel *labels_;
+    CYStatement *statements_;
 
-    CYStatement() :
-        labels_(NULL)
+    CYProgram(CYStatement *statements) :
+        statements_(statements)
     {
     }
 
-    void AddLabel(CYIdentifier *identifier) {
-        labels_ = new CYLabel(identifier, labels_);
-    }
-
-    bool Single(CYOutput &out, CYFlags flags) const;
-    void Multiple(CYOutput &out, CYFlags flags = CYNoFlags) const;
+    virtual void Replace(CYContext &context);
 
-  private:
-    virtual void Output(CYOutput &out, CYFlags flags) const = 0;
+    virtual void Output(CYOutput &out) const;
 };
 
 struct CYBlock :
-    CYStatement
+    CYStatement,
+    CYThing
 {
     CYStatement *statements_;
 
@@ -212,6 +274,9 @@ struct CYBlock :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
+
+    virtual void Output(CYOutput &out) const;
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -249,7 +314,7 @@ class CYDriver {
 
     typedef std::vector<Error> Errors;
 
-    CYStatement *program_;
+    CYProgram *program_;
     Errors errors_;
 
   private:
@@ -273,6 +338,7 @@ struct CYForInInitialiser {
     virtual void ForIn(CYOutput &out, CYFlags flags) const = 0;
     virtual const char *ForEachIn() const = 0;
     virtual void ForEachIn(CYOutput &out) const = 0;
+    virtual CYExpression *ForEachIn(CYContext &out) = 0;
 };
 
 struct CYExpression :
@@ -293,13 +359,19 @@ struct CYExpression :
 
     virtual const char *ForEachIn() const;
     virtual void ForEachIn(CYOutput &out) const;
+    virtual CYExpression *ForEachIn(CYContext &out);
 
     virtual void Output(CYOutput &out) const;
     virtual void Output(CYOutput &out, CYFlags flags) const = 0;
     void Output(CYOutput &out, unsigned precedence, CYFlags flags) const;
 
+    virtual CYExpression *ClassName(CYContext &context, bool object);
     virtual void ClassName(CYOutput &out, bool object) const;
 
+    CYExpression *ReplaceAll(CYContext &context);
+
+    virtual CYExpression *Replace(CYContext &context) = 0;
+
     virtual const char *Word() const {
         return NULL;
     }
@@ -340,9 +412,25 @@ struct CYCompound :
 
     CYPrecedence(17)
 
+    virtual CYExpression *Replace(CYContext &context);
     void Output(CYOutput &out, CYFlags flags) const;
 };
 
+struct CYFunctionParameter :
+    CYNext<CYFunctionParameter>,
+    CYThing
+{
+    CYIdentifier *name_;
+
+    CYFunctionParameter(CYIdentifier *name, CYFunctionParameter *next = NULL) :
+        CYNext<CYFunctionParameter>(next),
+        name_(name)
+    {
+    }
+
+    virtual void Output(CYOutput &out) const;
+};
+
 struct CYComprehension :
     CYNext<CYComprehension>,
     CYThing
@@ -354,6 +442,10 @@ struct CYComprehension :
 
     virtual void End_(CYOutput &out) const {
     }
+
+    virtual CYFunctionParameter *Parameter(CYContext &context) const = 0;
+    CYFunctionParameter *Parameters(CYContext &context) const;
+    virtual CYStatement *Replace(CYContext &context, CYStatement *statement) const;
 };
 
 struct CYForInComprehension :
@@ -373,6 +465,9 @@ struct CYForInComprehension :
     }
 
     virtual void Begin_(CYOutput &out) const;
+
+    virtual CYFunctionParameter *Parameter(CYContext &context) const;
+    virtual CYStatement *Replace(CYContext &context, CYStatement *statement) const;
 };
 
 struct CYForEachInComprehension :
@@ -393,6 +488,9 @@ struct CYForEachInComprehension :
 
     virtual void Begin_(CYOutput &out) const;
     virtual void End_(CYOutput &out) const;
+
+    virtual CYFunctionParameter *Parameter(CYContext &context) const;
+    virtual CYStatement *Replace(CYContext &context, CYStatement *statement) const;
 };
 
 struct CYIfComprehension :
@@ -410,6 +508,9 @@ struct CYIfComprehension :
     }
 
     virtual void Begin_(CYOutput &out) const;
+
+    virtual CYFunctionParameter *Parameter(CYContext &context) const;
+    virtual CYStatement *Replace(CYContext &context, CYStatement *statement) const;
 };
 
 struct CYArrayComprehension :
@@ -426,6 +527,7 @@ struct CYArrayComprehension :
 
     CYPrecedence(0)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -436,6 +538,12 @@ struct CYLiteral :
     CYRightHand(false)
 };
 
+struct CYTrivial :
+    CYLiteral
+{
+    virtual CYExpression *Replace(CYContext &context);
+};
+
 struct CYMagic :
     CYExpression
 {
@@ -443,38 +551,6 @@ struct CYMagic :
     CYRightHand(false)
 };
 
-struct CYSelectorPart :
-    CYNext<CYSelectorPart>,
-    CYThing
-{
-    CYWord *name_;
-    bool value_;
-
-    CYSelectorPart(CYWord *name, bool value, CYSelectorPart *next) :
-        CYNext<CYSelectorPart>(next),
-        name_(name),
-        value_(value)
-    {
-    }
-
-    virtual void Output(CYOutput &out) const;
-};
-
-struct CYSelector :
-    CYLiteral
-{
-    CYSelectorPart *name_;
-
-    CYSelector(CYSelectorPart *name) :
-        name_(name)
-    {
-    }
-
-    CYPrecedence(1)
-
-    virtual void Output(CYOutput &out, CYFlags flags) const;
-};
-
 struct CYRange {
     uint64_t lo_;
     uint64_t hi_;
@@ -500,20 +576,32 @@ extern CYRange WordStartRange_;
 extern CYRange WordEndRange_;
 
 struct CYString :
-    CYLiteral,
+    CYTrivial,
     CYPropertyName
 {
     const char *value_;
     size_t size_;
 
+    CYString() :
+        value_(NULL),
+        size_(0)
+    {
+    }
+
+    CYString(const char *value) :
+        value_(value),
+        size_(strlen(value))
+    {
+    }
+
     CYString(const char *value, size_t size) :
         value_(value),
         size_(size)
     {
     }
 
-    CYString(const CYIdentifier *identifier) :
-        value_(identifier->Value()),
+    CYString(const CYWord *word) :
+        value_(word->Value()),
         size_(strlen(value_))
     {
     }
@@ -528,8 +616,42 @@ struct CYString :
     virtual void PropertyName(CYOutput &out) const;
 };
 
+struct CYSelectorPart :
+    CYNext<CYSelectorPart>,
+    CYThing
+{
+    CYWord *name_;
+    bool value_;
+
+    CYSelectorPart(CYWord *name, bool value, CYSelectorPart *next) :
+        CYNext<CYSelectorPart>(next),
+        name_(name),
+        value_(value)
+    {
+    }
+
+    CYString *Replace(CYContext &context);
+    virtual void Output(CYOutput &out) const;
+};
+
+struct CYSelector :
+    CYLiteral
+{
+    CYSelectorPart *name_;
+
+    CYSelector(CYSelectorPart *name) :
+        name_(name)
+    {
+    }
+
+    CYPrecedence(1)
+
+    virtual CYExpression *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
 struct CYNumber :
-    CYLiteral,
+    CYTrivial,
     CYPropertyName
 {
     double value_;
@@ -548,7 +670,7 @@ struct CYNumber :
 };
 
 struct CYRegEx :
-    CYLiteral
+    CYTrivial
 {
     const char *value_;
 
@@ -566,7 +688,7 @@ struct CYRegEx :
 
 struct CYNull :
     CYWord,
-    CYLiteral
+    CYTrivial
 {
     CYNull() :
         CYWord("null")
@@ -585,11 +707,12 @@ struct CYThis :
     {
     }
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYBoolean :
-    CYLiteral
+    CYTrivial
 {
     virtual bool Value() const = 0;
     virtual void Output(CYOutput &out, CYFlags flags) const;
@@ -636,6 +759,7 @@ struct CYVariable :
     CYPrecedence(0)
     CYRightHand(false)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -652,6 +776,9 @@ struct CYPrefix :
     virtual bool Alphabetic() const = 0;
     virtual const char *Operator() const = 0;
 
+    CYPrecedence(4)
+
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -674,6 +801,7 @@ struct CYInfix :
     virtual bool Alphabetic() const = 0;
     virtual const char *Operator() const = 0;
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -689,6 +817,9 @@ struct CYPostfix :
 
     virtual const char *Operator() const = 0;
 
+    CYPrecedence(3)
+
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -710,6 +841,7 @@ struct CYAssignment :
 
     virtual const char *Operator() const = 0;
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -720,6 +852,13 @@ struct CYArgument :
     CYWord *name_;
     CYExpression *value_;
 
+    CYArgument(CYExpression *value, CYArgument *next = NULL) :
+        CYNext<CYArgument>(next),
+        name_(NULL),
+        value_(value)
+    {
+    }
+
     CYArgument(CYWord *name, CYExpression *value, CYArgument *next = NULL) :
         CYNext<CYArgument>(next),
         name_(name),
@@ -727,6 +866,7 @@ struct CYArgument :
     {
     }
 
+    void Replace(CYContext &context);
     void Output(CYOutput &out) const;
 };
 
@@ -744,14 +884,15 @@ struct CYClause :
     CYNext<CYClause>
 {
     CYExpression *case_;
-    CYStatement *code_;
+    CYStatement *statements_;
 
-    CYClause(CYExpression *_case, CYStatement *code) :
+    CYClause(CYExpression *_case, CYStatement *statements) :
         case_(_case),
-        code_(code)
+        statements_(statements)
     {
     }
 
+    virtual void Replace(CYContext &context);
     virtual void Output(CYOutput &out) const;
 };
 
@@ -767,6 +908,7 @@ struct CYElement :
     {
     }
 
+    void Replace(CYContext &context);
     void Output(CYOutput &out) const;
 };
 
@@ -775,11 +917,12 @@ struct CYArray :
 {
     CYElement *elements_;
 
-    CYArray(CYElement *elements) :
+    CYArray(CYElement *elements = NULL) :
         elements_(elements)
     {
     }
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -799,6 +942,9 @@ struct CYDeclaration :
 
     virtual const char *ForEachIn() const;
     virtual void ForEachIn(CYOutput &out) const;
+    virtual CYExpression *ForEachIn(CYContext &out);
+
+    void Replace(CYContext &context);
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
@@ -818,6 +964,8 @@ struct CYDeclarations :
 
     virtual void For(CYOutput &out) const;
 
+    void Replace(CYContext &context);
+
     virtual void Output(CYOutput &out) const;
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
@@ -832,6 +980,7 @@ struct CYVar :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -839,21 +988,23 @@ struct CYLet :
     CYStatement
 {
     CYDeclarations *declarations_;
-    CYStatement *statements_;
+    CYBlock code_;
 
     CYLet(CYDeclarations *declarations, CYStatement *statements) :
         declarations_(declarations),
-        statements_(statements)
+        code_(statements)
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYField :
     CYNext<CYField>
 {
-    virtual void Output(CYOutput &out) const;
+    CYStatement *Replace(CYContext &context) const;
+    void Output(CYOutput &out) const;
 };
 
 struct CYMessageParameter :
@@ -869,6 +1020,10 @@ struct CYMessageParameter :
         name_(name)
     {
     }
+
+    CYFunctionParameter *Parameters(CYContext &context) const;
+    CYSelector *Selector(CYContext &context) const;
+    CYSelectorPart *SelectorPart(CYContext &context) const;
 };
 
 struct CYMessage :
@@ -876,18 +1031,19 @@ struct CYMessage :
 {
     bool instance_;
     CYExpression *type_;
-    CYMessageParameter *parameter_;
-    CYStatement *body_;
+    CYMessageParameter *parameters_;
+    CYStatement *statements_;
 
-    CYMessage(bool instance, CYExpression *type, CYMessageParameter *parameter, CYStatement *body) :
+    CYMessage(bool instance, CYExpression *type, CYMessageParameter *parameter, CYStatement *statements) :
         instance_(instance),
         type_(type),
-        parameter_(parameter),
-        body_(body)
+        parameters_(parameter),
+        statements_(statements)
     {
     }
 
-    virtual void Output(CYOutput &out, bool replace) const;
+    CYStatement *Replace(CYContext &context, bool replace) const;
+    void Output(CYOutput &out, bool replace) const;
 };
 
 struct CYClass {
@@ -904,6 +1060,7 @@ struct CYClass {
     {
     }
 
+    CYExpression *Replace_(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -918,6 +1075,7 @@ struct CYClassExpression :
 
     CYPrecedence(0)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -930,6 +1088,7 @@ struct CYClassStatement :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -945,24 +1104,10 @@ struct CYCategory :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
-struct CYFunctionParameter :
-    CYNext<CYFunctionParameter>,
-    CYThing
-{
-    CYIdentifier *name_;
-
-    CYFunctionParameter(CYIdentifier *name, CYFunctionParameter *next) :
-        CYNext<CYFunctionParameter>(next),
-        name_(name)
-    {
-    }
-
-    virtual void Output(CYOutput &out) const;
-};
-
 struct CYFor :
     CYStatement
 {
@@ -979,6 +1124,7 @@ struct CYFor :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -996,6 +1142,7 @@ struct CYForIn :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1013,6 +1160,7 @@ struct CYForEachIn :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1023,26 +1171,28 @@ struct CYProperty :
     CYPropertyName *name_;
     CYExpression *value_;
 
-    CYProperty(CYPropertyName *name, CYExpression *value, CYProperty *next) :
+    CYProperty(CYPropertyName *name, CYExpression *value, CYProperty *next = NULL) :
         CYNext<CYProperty>(next),
         name_(name),
         value_(value)
     {
     }
 
+    void Replace(CYContext &context);
     virtual void Output(CYOutput &out) const;
 };
 
 struct CYObject :
     CYLiteral
 {
-    CYProperty *property_;
+    CYProperty *properties_;
 
-    CYObject(CYProperty *property) :
-        property_(property)
+    CYObject(CYProperty *properties) :
+        properties_(properties)
     {
     }
 
+    virtual CYExpression *Replace(CYContext &context);
     void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1050,14 +1200,15 @@ struct CYCatch :
     CYThing
 {
     CYIdentifier *name_;
-    CYStatement *code_;
+    CYBlock code_;
 
-    CYCatch(CYIdentifier *name, CYStatement *code) :
+    CYCatch(CYIdentifier *name, CYStatement *statements) :
         name_(name),
-        code_(code)
+        code_(statements)
     {
     }
 
+    void Replace(CYContext &context);
     virtual void Output(CYOutput &out) const;
 };
 
@@ -1075,6 +1226,7 @@ struct CYSend :
 
     CYPrecedence(0)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1093,6 +1245,8 @@ struct CYMember :
     void SetLeft(CYExpression *object) {
         object_ = object;
     }
+
+    void Replace_(CYContext &context);
 };
 
 struct CYDirectMember :
@@ -1106,6 +1260,7 @@ struct CYDirectMember :
     CYPrecedence(1)
     CYRightHand(false)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1120,6 +1275,7 @@ struct CYIndirectMember :
     CYPrecedence(1)
     CYRightHand(false)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1141,6 +1297,7 @@ struct CYNew :
 
     CYRightHand(false)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1150,7 +1307,7 @@ struct CYCall :
     CYExpression *function_;
     CYArgument *arguments_;
 
-    CYCall(CYExpression *function, CYArgument *arguments) :
+    CYCall(CYExpression *function, CYArgument *arguments = NULL) :
         function_(function),
         arguments_(arguments)
     {
@@ -1159,6 +1316,7 @@ struct CYCall :
     CYPrecedence(1)
     CYRightHand(false)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1169,13 +1327,14 @@ struct CYIf :
     CYStatement *true_;
     CYStatement *false_;
 
-    CYIf(CYExpression *test, CYStatement *_true, CYStatement *_false) :
+    CYIf(CYExpression *test, CYStatement *_true, CYStatement *_false = NULL) :
         test_(test),
         true_(_true),
         false_(_false)
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1191,6 +1350,7 @@ struct CYDoWhile :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1206,21 +1366,23 @@ struct CYWhile :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYFunction {
     CYIdentifier *name_;
     CYFunctionParameter *parameters_;
-    CYStatement *body_;
+    CYBlock code_;
 
-    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
+    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *statements) :
         name_(name),
         parameters_(parameters),
-        body_(body)
+        code_(statements)
     {
     }
 
+    virtual void Replace_(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1228,14 +1390,15 @@ struct CYFunctionExpression :
     CYFunction,
     CYExpression
 {
-    CYFunctionExpression(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
-        CYFunction(name, parameters, body)
+    CYFunctionExpression(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *statements) :
+        CYFunction(name, parameters, statements)
     {
     }
 
     CYPrecedence(0)
     CYRightHand(false)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1243,11 +1406,12 @@ struct CYFunctionStatement :
     CYFunction,
     CYStatement
 {
-    CYFunctionStatement(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
-        CYFunction(name, parameters, body)
+    CYFunctionStatement(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *statements) :
+        CYFunction(name, parameters, statements)
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1261,6 +1425,7 @@ struct CYExpress :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1274,6 +1439,7 @@ struct CYContinue :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1287,6 +1453,7 @@ struct CYBreak :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1300,42 +1467,46 @@ struct CYReturn :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYEmpty :
     CYStatement
 {
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYFinally :
     CYThing
 {
-    CYStatement *code_;
+    CYBlock code_;
 
-    CYFinally(CYStatement *code) :
-        code_(code)
+    CYFinally(CYStatement *statements) :
+        code_(statements)
     {
     }
 
+    void Replace(CYContext &context);
     virtual void Output(CYOutput &out) const;
 };
 
 struct CYTry :
     CYStatement
 {
-    CYStatement *code_;
+    CYBlock code_;
     CYCatch *catch_;
     CYFinally *finally_;
 
-    CYTry(CYStatement *code, CYCatch *_catch, CYFinally *finally) :
-        code_(code),
+    CYTry(CYStatement *statements, CYCatch *_catch, CYFinally *finally) :
+        code_(statements),
         catch_(_catch),
         finally_(finally)
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1349,6 +1520,7 @@ struct CYThrow :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1364,6 +1536,7 @@ struct CYWith :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1379,6 +1552,7 @@ struct CYSwitch :
     {
     }
 
+    virtual CYStatement *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1398,6 +1572,7 @@ struct CYCondition :
 
     CYPrecedence(15)
 
+    virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -1414,9 +1589,8 @@ struct CYAddressOf :
     }
 
     CYAlphabetic(false)
-    CYPrecedence(2)
 
-    virtual void Output(CYOutput &out, CYFlags flags) const;
+    virtual CYExpression *Replace(CYContext &context);
 };
 
 struct CYIndirect :
@@ -1432,9 +1606,8 @@ struct CYIndirect :
     }
 
     CYAlphabetic(false)
-    CYPrecedence(1)
 
-    virtual void Output(CYOutput &out, CYFlags flags) const;
+    virtual CYExpression *Replace(CYContext &context);
 };
 
 #define CYPostfix_(op, name) \
@@ -1445,8 +1618,6 @@ struct CYIndirect :
             CYPostfix(lhs) \
         { \
         } \
-    \
-        CYPrecedence(3) \
     \
         virtual const char *Operator() const { \
             return op; \
@@ -1463,7 +1634,6 @@ struct CYIndirect :
         } \
     \
         CYAlphabetic(alphabetic) \
-        CYPrecedence(4) \
     \
         virtual const char *Operator() const { \
             return op; \
diff --git a/Replace.cpp b/Replace.cpp
new file mode 100644 (file)
index 0000000..7d861c9
--- /dev/null
@@ -0,0 +1,557 @@
+#include "Parser.hpp"
+
+#include <iostream>
+#include <iomanip>
+
+#include <objc/runtime.h>
+#include <sstream>
+
+#define $ \
+    new(context.pool_)
+
+#define $D(args...) \
+    ($ CYNumber(args))
+#define $E(args...) \
+    ($ CYExpress(args))
+#define $F(args...) \
+    ($ CYFunctionExpression(args))
+#define $I(args...) \
+    ($ CYIdentifier(args))
+#define $M(args...) \
+    ($ CYDirectMember(args))
+#define $P(args...) \
+    ($ CYFunctionParameter(args))
+#define $S(args...) \
+    ($ CYString(args))
+#define $V(name) \
+    ($ CYVariable($I(name)))
+
+#define $T(value) \
+    if (this == NULL) \
+        return value;
+#define $$ \
+    CYStatements()
+
+#define $P1(arg0, args...) \
+    $P($I(arg0), ##args)
+#define $P2(arg0, arg1, args...) \
+    $P($I(arg0), $P1(arg1, ##args))
+#define $P3(arg0, arg1, arg2, args...) \
+    $P($I(arg0), $P2(arg1, arg2, ##args))
+#define $P4(arg0, arg1, arg2, arg3, args...) \
+    $P($I(arg0), $P3(arg1, arg2, arg3, ##args))
+#define $P5(arg0, arg1, arg2, arg3, arg4, args...) \
+    $P($I(arg0), $P4(arg1, arg2, arg3, arg4, ##args))
+#define $P6(arg0, arg1, arg2, arg3, arg4, arg5, args...) \
+    $P($I(arg0), $P5(arg1, arg2, arg3, arg4, arg5, ##args))
+
+#define $C(args...) \
+    ($ CYCall(args))
+#define $C_(args...) \
+    ($ CYArgument(args))
+#define $N(args...) \
+    ($ CYNew(args))
+
+#define $C1_(arg0, args...) \
+    $C_(arg0, ##args)
+#define $C2_(arg0, arg1, args...) \
+    $C_(arg0, $C1_(arg1, ##args))
+#define $C3_(arg0, arg1, arg2, args...) \
+    $C_(arg0, $C2_(arg1, arg2, ##args))
+#define $C4_(arg0, arg1, arg2, arg3, args...) \
+    $C_(arg0, $C3_(arg1, arg2, arg3, ##args))
+#define $C5_(arg0, arg1, arg2, arg3, arg4, args...) \
+    $C_(arg0, $C4_(arg1, arg2, arg3, arg4, ##args))
+#define $C6_(arg0, arg1, arg2, arg3, arg4, arg5, args...) \
+    $C_(arg0, $C5_(arg1, arg2, arg3, arg4, arg5, ##args))
+
+#define $C0(func, args...) \
+    $C(func, ##args)
+#define $C1(func, args...) \
+    $C(func, $C1_(args))
+#define $C2(func, args...) \
+    $C(func, $C2_(args))
+#define $C3(func, args...) \
+    $C(func, $C3_(args))
+#define $C4(func, args...) \
+    $C(func, $C4_(args))
+#define $C5(func, args...) \
+    $C(func, $C5_(args))
+
+#define $N0(func, args...) \
+    $N(func, ##args)
+#define $N1(func, args...) \
+    $N(func, $C1_(args))
+#define $N2(func, args...) \
+    $N(func, $C2_(args))
+#define $N3(func, args...) \
+    $N(func, $C3_(args))
+#define $N4(func, args...) \
+    $N(func, $C4_(args))
+#define $N5(func, args...) \
+    $N(func, $C5_(args))
+
+CYExpression *CYAddressOf::Replace(CYContext &context) {
+    CYPrefix::Replace(context);
+    return $C0($M(rhs_, $S("$cya")));
+}
+
+void CYArgument::Replace(CYContext &context) { $T()
+    context.Replace(value_);
+    next_->Replace(context);
+}
+
+CYExpression *CYArray::Replace(CYContext &context) {
+    elements_->Replace(context);
+    return NULL;
+}
+
+CYExpression *CYArrayComprehension::Replace(CYContext &context) {
+    CYVariable *cyv($V("$cyv"));
+
+    return $C0($F(NULL, $P1("$cyv", comprehensions_->Parameters(context)), $$->*
+        $E($ CYAssign(cyv, $ CYArray()))->*
+        comprehensions_->Replace(context, $E($C1($M(cyv, $S("push")), expression_)))->*
+        $ CYReturn(cyv)
+    ));
+}
+
+CYExpression *CYAssignment::Replace(CYContext &context) {
+    context.Replace(lhs_);
+    context.Replace(rhs_);
+    return NULL;
+}
+
+CYStatement *CYBlock::Replace(CYContext &context) {
+    statements_ = statements_->ReplaceAll(context);
+    return NULL;
+}
+
+CYStatement *CYBreak::Replace(CYContext &context) {
+    return NULL;
+}
+
+CYExpression *CYCall::Replace(CYContext &context) {
+    context.Replace(function_);
+    arguments_->Replace(context);
+    return NULL;
+}
+
+void CYCatch::Replace(CYContext &context) { $T()
+    code_.Replace(context);
+}
+
+CYStatement *CYCategory::Replace(CYContext &context) {
+    CYVariable *cyc($V("$cyc")), *cys($V("$cys"));
+
+    return $E($C1($F(NULL, $P5("$cys", "$cyp", "$cyc", "$cyn", "$cyt"), $$->*
+        $E($ CYAssign($V("$cyp"), $C1($V("object_getClass"), cys)))->*
+        $E($ CYAssign(cyc, cys))->*
+        messages_->Replace(context, true)
+    ), name_->ClassName(context, true)));
+}
+
+CYExpression *CYClass::Replace_(CYContext &context) {
+    CYVariable *cyc($V("$cyc")), *cys($V("$cys"));
+
+    CYExpression *name(name_ != NULL ? name_->ClassName(context, false) : $C1($V("$cyq"), $S("CY$")));
+
+    return $C1($F(NULL, $P6("$cys", "$cyp", "$cyc", "$cyn", "$cyt", "$cym"), $$->*
+        $E($ CYAssign($V("$cyp"), $C1($V("object_getClass"), cys)))->*
+        $E($ CYAssign(cyc, $C3($V("objc_allocateClassPair"), cys, name, $D(0))))->*
+        $E($ CYAssign($V("$cym"), $C1($V("object_getClass"), cyc)))->*
+        fields_->Replace(context)->*
+        messages_->Replace(context, false)->*
+        $E($C1($V("objc_registerClassPair"), cyc))->*
+        $ CYReturn(cyc)
+    ), super_ == NULL ? $ CYNull() : super_);
+}
+
+CYExpression *CYClassExpression::Replace(CYContext &context) {
+    return Replace_(context);
+}
+
+CYStatement *CYClassStatement::Replace(CYContext &context) {
+    return $E(Replace_(context));
+}
+
+void CYClause::Replace(CYContext &context) { $T()
+    context.Replace(case_);
+    statements_ = statements_->ReplaceAll(context);
+    next_->Replace(context);
+}
+
+CYExpression *CYCompound::Replace(CYContext &context) {
+    expressions_ = expressions_->ReplaceAll(context);
+    return NULL;
+}
+
+CYFunctionParameter *CYComprehension::Parameters(CYContext &context) const { $T(NULL)
+    CYFunctionParameter *next(next_->Parameters(context));
+    if (CYFunctionParameter *parameter = Parameter(context)) {
+        parameter->SetNext(next);
+        return parameter;
+    } else
+        return next;
+}
+
+CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement) const {
+    return next_ == NULL ? statement : next_->Replace(context, statement);
+}
+
+CYExpression *CYCondition::Replace(CYContext &context) {
+    context.Replace(test_);
+    context.Replace(true_);
+    context.Replace(false_);
+    return NULL;
+}
+
+CYStatement *CYContinue::Replace(CYContext &context) {
+    return NULL;
+}
+
+CYExpression *CYDeclaration::ForEachIn(CYContext &context) {
+    return $ CYVariable(identifier_);
+}
+
+void CYDeclaration::Replace(CYContext &context) {
+    context.Replace(initialiser_);
+}
+
+void CYDeclarations::Replace(CYContext &context) { $T()
+    declaration_->Replace(context);
+    next_->Replace(context);
+}
+
+CYExpression *CYDirectMember::Replace(CYContext &context) {
+    Replace_(context);
+    return NULL;
+}
+
+CYStatement *CYDoWhile::Replace(CYContext &context) {
+    context.Replace(test_);
+    context.Replace(code_);
+    return NULL;
+}
+
+void CYElement::Replace(CYContext &context) { $T()
+    context.Replace(value_);
+    next_->Replace(context);
+}
+
+CYStatement *CYEmpty::Replace(CYContext &context) {
+    return NULL;
+}
+
+CYStatement *CYExpress::Replace(CYContext &context) {
+    context.Replace(expression_);
+    return NULL;
+}
+
+CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
+    return this;
+}
+
+CYExpression *CYExpression::ForEachIn(CYContext &context) {
+    return this;
+}
+
+CYExpression *CYExpression::ReplaceAll(CYContext &context) { $T(NULL)
+    CYExpression *replace(this);
+    context.Replace(replace);
+
+    if (CYExpression *next = next_->ReplaceAll(context))
+        replace->SetNext(next);
+    else
+        replace->SetNext(next_);
+
+    return replace;
+}
+
+CYStatement *CYField::Replace(CYContext &context) const {
+    return NULL;
+}
+
+void CYFinally::Replace(CYContext &context) { $T()
+    code_.Replace(context);
+}
+
+CYStatement *CYFor::Replace(CYContext &context) {
+    // XXX: initialiser_
+    context.Replace(test_);
+    context.Replace(increment_);
+    context.Replace(code_);
+    return NULL;
+}
+
+CYStatement *CYForIn::Replace(CYContext &context) {
+    // XXX: initialiser_
+    context.Replace(set_);
+    context.Replace(code_);
+    return NULL;
+}
+
+CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
+    return $ CYFunctionParameter(name_);
+}
+
+CYStatement *CYForInComprehension::Replace(CYContext &context, CYStatement *statement) const {
+    return $ CYForIn($ CYVariable(name_), set_, CYComprehension::Replace(context, statement));
+}
+
+CYStatement *CYForEachIn::Replace(CYContext &context) {
+    CYVariable *cys($V("$cys")), *cyt($V("$cyt"));
+
+    return $ CYWith($ CYObject($ CYProperty($S("$cys"), $D(0), $ CYProperty($S("$cyt"), $D(0)))), $ CYBlock($$->*
+        $E($ CYAssign(cys, set_))->*
+        $ CYForIn(cyt, cys, $ CYBlock($$->*
+            $E($ CYAssign(initialiser_->ForEachIn(context), $M(cys, cyt)))->*
+            code_
+        ))
+    ));
+}
+
+CYFunctionParameter *CYForEachInComprehension::Parameter(CYContext &context) const {
+    return $ CYFunctionParameter(name_);
+}
+
+CYStatement *CYForEachInComprehension::Replace(CYContext &context, CYStatement *statement) const {
+    CYVariable *cys($V("$cys")), *name($ CYVariable(name_));
+
+    return $E($C0($F(NULL, $P1("$cys"), $$->*
+        $E($ CYAssign(cys, set_))->*
+        $ CYForIn(name, cys, $ CYBlock($$->*
+            $E($ CYAssign(name, $M(cys, name)))->*
+            CYComprehension::Replace(context, statement)
+        ))
+    )));
+}
+
+void CYFunction::Replace_(CYContext &context) {
+    code_.Replace(context);
+}
+
+CYExpression *CYFunctionExpression::Replace(CYContext &context) {
+    Replace_(context);
+    return NULL;
+}
+
+CYStatement *CYFunctionStatement::Replace(CYContext &context) {
+    Replace_(context);
+    return NULL;
+}
+
+CYStatement *CYIf::Replace(CYContext &context) {
+    context.Replace(test_);
+    context.Replace(true_);
+    context.Replace(false_);
+    return NULL;
+}
+
+CYFunctionParameter *CYIfComprehension::Parameter(CYContext &context) const {
+    return NULL;
+}
+
+CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *statement) const {
+    return $ CYIf(test_, CYComprehension::Replace(context, statement));
+}
+
+CYExpression *CYIndirect::Replace(CYContext &context) {
+    CYPrefix::Replace(context);
+    return $M(rhs_, $S("$cyi"));
+}
+
+CYExpression *CYIndirectMember::Replace(CYContext &context) {
+    Replace_(context);
+    return $M($ CYIndirect(object_), property_);
+}
+
+CYExpression *CYInfix::Replace(CYContext &context) {
+    context.Replace(lhs_);
+    context.Replace(rhs_);
+    return NULL;
+}
+
+CYStatement *CYLabel::Replace(CYContext &context) {
+    context.Replace(statement_);
+    return NULL;
+}
+
+void CYMember::Replace_(CYContext &context) {
+    context.Replace(object_);
+    context.Replace(property_);
+}
+
+CYStatement *CYMessage::Replace(CYContext &context, bool replace) const { $T(NULL)
+    CYVariable *cyn($V("$cyn"));
+    CYVariable *cyt($V("$cyt"));
+
+    return $ CYBlock($$->*
+        next_->Replace(context, replace)->*
+        $E($ CYAssign(cyn, parameters_->Selector(context)))->*
+        $E($ CYAssign(cyt, $C1($M(cyn, $S("type")), $V(instance_ ? "$cys" : "$cyp"))))->*
+        $E($C4($V(replace ? "class_replaceMethod" : "class_addMethod"),
+            $V(instance_ ? "$cyc" : "$cym"),
+            cyn,
+            $N2($V("Functor"), $F(NULL, $P2("self", "_cmd", parameters_->Parameters(context)), $$->*
+                $ CYReturn($C1($M($F(NULL, NULL, statements_), $S("call")), $V("self")))
+            ), cyt),
+            cyt
+        ))
+    );
+}
+
+CYFunctionParameter *CYMessageParameter::Parameters(CYContext &context) const { $T(NULL)
+    CYFunctionParameter *next(next_->Parameters(context));
+    return name_ == NULL ? next : $ CYFunctionParameter(name_, next);
+}
+
+CYSelector *CYMessageParameter::Selector(CYContext &context) const {
+    return $ CYSelector(SelectorPart(context));
+}
+
+CYSelectorPart *CYMessageParameter::SelectorPart(CYContext &context) const { $T(NULL)
+    CYSelectorPart *next(next_->SelectorPart(context));
+    return tag_ == NULL ? next : $ CYSelectorPart(tag_, name_ != NULL, next);
+}
+
+CYExpression *CYNew::Replace(CYContext &context) {
+    context.Replace(constructor_);
+    arguments_->Replace(context);
+    return NULL;
+}
+
+CYExpression *CYObject::Replace(CYContext &context) {
+    properties_->Replace(context);
+    return NULL;
+}
+
+CYExpression *CYPostfix::Replace(CYContext &context) {
+    context.Replace(lhs_);
+    return NULL;
+}
+
+CYExpression *CYPrefix::Replace(CYContext &context) {
+    context.Replace(rhs_);
+    return NULL;
+}
+
+void CYProgram::Replace(CYContext &context) {
+    statements_ = statements_->ReplaceAll(context);
+}
+
+void CYProperty::Replace(CYContext &context) { $T()
+    context.Replace(value_);
+    next_->Replace(context);
+}
+
+CYStatement *CYReturn::Replace(CYContext &context) {
+    context.Replace(value_);
+    return NULL;
+}
+
+CYExpression *CYSelector::Replace(CYContext &context) {
+    return $N1($V("Selector"), name_->Replace(context));
+}
+
+CYExpression *CYSend::Replace(CYContext &context) {
+    std::ostringstream name;
+    CYArgument **argument(&arguments_);
+
+    while (*argument != NULL) {
+        if ((*argument)->name_ != NULL) {
+            name << *(*argument)->name_;
+            (*argument)->name_ = NULL;
+            if ((*argument)->value_ != NULL)
+                name << ':';
+        }
+
+        if ((*argument)->value_ == NULL)
+            *argument = (*argument)->next_;
+        else
+            argument = &(*argument)->next_;
+    }
+
+    SEL sel(sel_registerName(name.str().c_str()));
+    double address(static_cast<double>(reinterpret_cast<uintptr_t>(sel)));
+
+    return $C2($V("objc_msgSend"), self_, $D(address), arguments_);
+}
+
+CYString *CYSelectorPart::Replace(CYContext &context) {
+    std::ostringstream str;
+    for (const CYSelectorPart *part(this); part != NULL; part = part->next_) {
+        if (part->name_ != NULL)
+            str << part->name_->Value();
+        if (part->value_)
+            str << ':';
+    }
+    return $S(apr_pstrdup(context.pool_, str.str().c_str()));
+}
+
+CYStatement *CYStatement::ReplaceAll(CYContext &context) { $T(NULL)
+    CYStatement *replace(this);
+    context.Replace(replace);
+
+    if (CYStatement *next = next_->ReplaceAll(context))
+        replace->SetNext(next);
+    else
+        replace->SetNext(next_);
+
+    return replace;
+}
+
+CYStatement *CYSwitch::Replace(CYContext &context) {
+    context.Replace(value_);
+    clauses_->Replace(context);
+    return NULL;
+}
+
+CYExpression *CYThis::Replace(CYContext &context) {
+    return NULL;
+}
+
+CYStatement *CYThrow::Replace(CYContext &context) {
+    context.Replace(value_);
+    return NULL;
+}
+
+CYExpression *CYTrivial::Replace(CYContext &context) {
+    return NULL;
+}
+
+CYStatement *CYTry::Replace(CYContext &context) {
+    code_.Replace(context);
+    catch_->Replace(context);
+    finally_->Replace(context);
+    return NULL;
+}
+
+CYStatement *CYVar::Replace(CYContext &context) {
+    declarations_->Replace(context);
+    return NULL;
+}
+
+CYExpression *CYVariable::Replace(CYContext &context) {
+    return NULL;
+}
+
+CYStatement *CYWhile::Replace(CYContext &context) {
+    context.Replace(test_);
+    context.Replace(code_);
+    return NULL;
+}
+
+CYStatement *CYWith::Replace(CYContext &context) {
+    context.Replace(scope_);
+    context.Replace(code_);
+    return NULL;
+}
+
+CYExpression *CYWord::ClassName(CYContext &context, bool object) {
+    CYString *name($S(this));
+    if (object)
+        return $C1($V("objc_getClass"), name);
+    else
+        return name;
+}
index 6827307e8b8432fe0c8e52da3fa31ab28682df97..82b9c3aedf5b2a63508fc812bbc4f735c42123bc 100644 (file)
--- a/makefile
+++ b/makefile
@@ -73,7 +73,7 @@ Cycript.dylib: Connector.o
            -framework CoreFoundation
        ldid -S $@
 
-libcycript.dylib: ffi_type.o parse.o Output.o Cycript.tab.o lex.cy.o Library.o
+libcycript.dylib: ffi_type.o parse.o Replace.o Output.o Cycript.tab.o lex.cy.o Library.o
        $(target)g++ $(flags) -dynamiclib -o $@ $(filter %.o,$^) \
            -install_name /usr/lib/libcycript.dylib \
            -lobjc -lapr-1 -lffi -lsubstrate \