From: Jay Freeman (saurik) Date: Thu, 22 Oct 2009 05:48:50 +0000 (+0000) Subject: Completely rewrote the output serializer to instead do replacement on the parse tree... X-Git-Tag: v0.9.432~293 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/3b52fd1a20c639d7a716d3e0f3176a55f2fcba72?ds=sidebyside;hp=d09e527c381abbc21b5ad603c3b55fe07c35d505 Completely rewrote the output serializer to instead do replacement on the parse tree (seriously: this is epic ;P), refactored labeled statements into CYLabel (a bad move: I regret it and will likely undo this), and redid blocks in a way that (mostly) makes sense. --- diff --git a/Console.cpp b/Console.cpp index 3a911cd..9a60679 100644 --- a/Console.cpp +++ b/Console.cpp @@ -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; diff --git a/Cycript.y b/Cycript.y index 151f950..7fdc172 100644 --- 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 {{{ */ diff --git a/Library.mm b/Library.mm index 45126dc..eb64e45 100644 --- a/Library.mm +++ b/Library.mm @@ -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]; diff --git a/Output.cpp b/Output.cpp index 1e4d437..efbf55b 100644 --- a/Output.cpp +++ b/Output.cpp @@ -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(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 { diff --git a/Parser.hpp b/Parser.hpp index a9a8812..e954748 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -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 + void Replace(Type_ *&value) { + if (value != NULL) + while (Type_ *replace = value->Replace(*this)) + value = replace; + } +}; + +struct CYStatement : + CYNext +{ + 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 + CYStatement { CYIdentifier *name_; + CYStatement *statement_; - CYLabel(CYIdentifier *name, CYLabel *next) : - CYNext(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 +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 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, + CYThing +{ + CYIdentifier *name_; + + CYFunctionParameter(CYIdentifier *name, CYFunctionParameter *next = NULL) : + CYNext(next), + name_(name) + { + } + + virtual void Output(CYOutput &out) const; +}; + struct CYComprehension : CYNext, 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, - CYThing -{ - CYWord *name_; - bool value_; - - CYSelectorPart(CYWord *name, bool value, CYSelectorPart *next) : - CYNext(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, + CYThing +{ + CYWord *name_; + bool value_; + + CYSelectorPart(CYWord *name, bool value, CYSelectorPart *next) : + CYNext(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(next), + name_(NULL), + value_(value) + { + } + CYArgument(CYWord *name, CYExpression *value, CYArgument *next = NULL) : CYNext(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 { 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 { - 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, - CYThing -{ - CYIdentifier *name_; - - CYFunctionParameter(CYIdentifier *name, CYFunctionParameter *next) : - CYNext(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(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 index 0000000..7d861c9 --- /dev/null +++ b/Replace.cpp @@ -0,0 +1,557 @@ +#include "Parser.hpp" + +#include +#include + +#include +#include + +#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(reinterpret_cast(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; +} diff --git a/makefile b/makefile index 6827307..82b9c3a 100644 --- 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 \