From 029bc65b46de676c6733fff684000c7363eda512 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Mon, 16 Nov 2009 10:11:09 +0000 Subject: [PATCH] Started working on variable name replacement strategies and generally improved compiler. --- Console.cpp | 10 +- Context.hpp | 72 ++++++++++++++ Execute.cpp | 10 +- Handler.mm | 1 + Library.cpp | 6 +- ObjectiveC/Replace.mm | 1 + Options.hpp | 52 ++++++++++ Output.cpp | 22 +++- Parser.hpp | 129 ++++++++++++++++++------ Replace.cpp | 226 ++++++++++++++++++++++++++++++++---------- makefile | 6 +- todo.txt | 2 + 12 files changed, 432 insertions(+), 105 deletions(-) create mode 100644 Context.hpp create mode 100644 Options.hpp diff --git a/Console.cpp b/Console.cpp index 44cadc7..0ed0bfe 100644 --- a/Console.cpp +++ b/Console.cpp @@ -38,6 +38,7 @@ /* }}} */ #include "cycript.hpp" +#include "Context.hpp" #ifdef CY_EXECUTE #include "JavaScript.hpp" @@ -115,7 +116,8 @@ void Setup(CYDriver &driver, cy::parser &parser) { void Setup(CYOutput &out, CYDriver &driver) { out.pretty_ = pretty_; - CYContext context(driver.pool_); + CYOptions options; + CYContext context(driver.pool_, options); driver.program_->Replace(context); } @@ -324,7 +326,8 @@ static void Console(apr_pool_t *pool, int client) { code = command; else { std::ostringstream str; - CYOutput out(str); + CYOptions options; + CYOutput out(str, options); Setup(out, driver); out << *driver.program_; code = str.str(); @@ -606,7 +609,8 @@ int Main(int argc, char const * const argv[], char const * const envp[]) { Run(client, code, stdout); } else { std::ostringstream str; - CYOutput out(str); + CYOptions options; + CYOutput out(str, options); Setup(out, driver); out << *driver.program_; std::string code(str.str()); diff --git a/Context.hpp b/Context.hpp new file mode 100644 index 0000000..dfa0b62 --- /dev/null +++ b/Context.hpp @@ -0,0 +1,72 @@ +/* Cycript - Inlining/Optimizing JavaScript Compiler + * Copyright (C) 2009 Jay Freeman (saurik) +*/ + +/* Modified BSD License {{{ */ +/* + * Redistribution and use in source and binary + * forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the + * above copyright notice, this list of conditions + * and the following disclaimer. + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions + * and the following disclaimer in the documentation + * and/or other materials provided with the + * distribution. + * 3. The name of the author may not be used to endorse + * or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* }}} */ + +#ifndef CYCRIPT_CONTEXT_HPP +#define CYCRIPT_CONTEXT_HPP + +#include "Options.hpp" + +class CYScope; + +struct CYContext { + apr_pool_t *pool_; + CYOptions &options_; + CYScope *scope_; + + CYContext(apr_pool_t *pool, CYOptions &options) : + pool_(pool), + options_(options), + scope_(NULL) + { + } + + template + void Replace(Type_ *&value) { + for (;;) if (value == NULL) + break; + else { + Type_ *replace(value->Replace(*this)); + if (replace != value) + value = replace; + else break; + } + } +}; + +#endif/*CYCRIPT_CONTEXT_HPP*/ diff --git a/Execute.cpp b/Execute.cpp index a517fb4..3f09419 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -181,14 +181,6 @@ void CYFinalize(JSObjectRef object) { delete reinterpret_cast(JSObjectGetPrivate(object)); } -struct CStringMapLess : - std::binary_function -{ - _finline bool operator ()(const char *lhs, const char *rhs) const { - return strcmp(lhs, rhs) < 0; - } -}; - void Structor_(apr_pool_t *pool, sig::Type *&type) { if ( type->primitive == sig::pointer_P && @@ -288,7 +280,7 @@ struct Struct_privateData : } }; -typedef std::map TypeMap; +typedef std::map TypeMap; static TypeMap Types_; JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_type *ffi, JSObjectRef owner) { diff --git a/Handler.mm b/Handler.mm index 38ef638..40b79f8 100644 --- a/Handler.mm +++ b/Handler.mm @@ -42,6 +42,7 @@ #include "Pooling.hpp" #include "Parser.hpp" +#include "Context.hpp" #include "Cycript.tab.hh" diff --git a/Library.cpp b/Library.cpp index 8068e82..610e11b 100644 --- a/Library.cpp +++ b/Library.cpp @@ -43,6 +43,7 @@ #include "cycript.hpp" #include "Pooling.hpp" +#include "Context.hpp" #include @@ -251,10 +252,11 @@ extern "C" void CydgetPoolParse(apr_pool_t *pool, const uint16_t **data, size_t if (parser.parse() != 0 || !driver.errors_.empty()) return; - CYContext context(driver.pool_); + CYOptions options; + CYContext context(driver.pool_, options); driver.program_->Replace(context); std::ostringstream str; - CYOutput out(str); + CYOutput out(str, options); out << *driver.program_; std::string code(str.str()); diff --git a/ObjectiveC/Replace.mm b/ObjectiveC/Replace.mm index 92fc77c..6d40c3c 100644 --- a/ObjectiveC/Replace.mm +++ b/ObjectiveC/Replace.mm @@ -38,6 +38,7 @@ /* }}} */ #include "Replace.hpp" +#include "Context.hpp" #include "ObjectiveC/Syntax.hpp" #include diff --git a/Options.hpp b/Options.hpp new file mode 100644 index 0000000..68958d8 --- /dev/null +++ b/Options.hpp @@ -0,0 +1,52 @@ +/* Cycript - Inlining/Optimizing JavaScript Compiler + * Copyright (C) 2009 Jay Freeman (saurik) +*/ + +/* Modified BSD License {{{ */ +/* + * Redistribution and use in source and binary + * forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the + * above copyright notice, this list of conditions + * and the following disclaimer. + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions + * and the following disclaimer in the documentation + * and/or other materials provided with the + * distribution. + * 3. The name of the author may not be used to endorse + * or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* }}} */ + +#ifndef CYCRIPT_OPTIONS_HPP +#define CYCRIPT_OPTIONS_HPP + +struct CYOptions { + bool verbose_; + + CYOptions() : + verbose_(false) + { + } +}; + +#endif/*CYCRIPT_OPTIONS_HPP*/ diff --git a/Output.cpp b/Output.cpp index 04f893c..27ea3fc 100644 --- a/Output.cpp +++ b/Output.cpp @@ -284,7 +284,7 @@ void CYClause::Output(CYOutput &out) const { } const char *CYDeclaration::ForEachIn() const { - return identifier_->Value(); + return identifier_->Word(); } void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const { @@ -352,6 +352,7 @@ void CYElement::Output(CYOutput &out) const { } void CYEmpty::Output(CYOutput &out, CYFlags flags) const { + out << '`'; out.Terminate(); } @@ -416,7 +417,8 @@ void CYForEachInComprehension::Output(CYOutput &out) const { void CYForIn::Output(CYOutput &out, CYFlags flags) const { out << "for" << ' ' << '('; - initialiser_->ForIn(out, CYNoIn); + if (initialiser_ != NULL) + initialiser_->ForIn(out, CYNoIn); out << "in" << *set_ << ')'; code_->Single(out, CYRight(flags)); } @@ -431,6 +433,8 @@ void CYFunction::Output(CYOutput &out, CYFlags flags) const { if (protect) out << '('; out << "function"; + if (out.options_.verbose_) + out.out_ << ':' << static_cast(this); if (name_ != NULL) out << ' ' << *name_; out << '(' << parameters_ << ')'; @@ -453,6 +457,10 @@ void CYFunctionParameter::Output(CYOutput &out) const { out << ',' << ' ' << *next_; } +const char *CYIdentifier::Word() const { + return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word(); +} + void CYIf::Output(CYOutput &out, CYFlags flags) const { bool protect(false); if (false_ == NULL && (flags & CYNoDangle) != 0) { @@ -716,15 +724,21 @@ void CYWith::Output(CYOutput &out, CYFlags flags) const { void CYWord::ClassName(CYOutput &out, bool object) const { if (object) out << "objc_getClass("; - out << '"' << Value() << '"'; + out << '"' << Word() << '"'; if (object) out << ')'; } void CYWord::Output(CYOutput &out) const { - out << Value(); + out << Word(); + if (out.options_.verbose_) + out.out_ << '@' << this; } void CYWord::PropertyName(CYOutput &out) const { Output(out); } + +const char *CYWord::Word() const { + return word_; +} diff --git a/Parser.hpp b/Parser.hpp index 8f42bc3..dc3c907 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -47,11 +47,16 @@ #include #include +#include +#include #include #include "location.hh" #include "Pooling.hpp" +#include "Options.hpp" + +class CYContext; template struct CYNext { @@ -81,6 +86,7 @@ struct CYThing { struct CYOutput { std::ostream &out_; + CYOptions &options_; bool pretty_; unsigned indent_; bool right_; @@ -93,8 +99,9 @@ struct CYOutput { Terminated } mode_; - CYOutput(std::ostream &out) : + CYOutput(std::ostream &out, CYOptions &options) : out_(out), + options_(options), pretty_(false), indent_(0), right_(false), @@ -147,22 +154,6 @@ enum CYFlags { 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 { @@ -173,6 +164,7 @@ struct CYStatement : void Multiple(CYOutput &out, CYFlags flags = CYNoFlags) const; CYStatement *ReplaceAll(CYContext &context); + virtual CYStatement *Collapse(CYContext &context); virtual CYStatement *Replace(CYContext &context) = 0; @@ -229,10 +221,11 @@ struct CYWord : { } - const char *Value() const { - return word_; + void Set(const char *value) { + word_ = value; } + virtual const char *Word() const; virtual void Output(CYOutput &out) const; virtual CYExpression *ClassName(CYContext &context, bool object); @@ -241,16 +234,23 @@ struct CYWord : }; _finline std::ostream &operator <<(std::ostream &lhs, const CYWord &rhs) { - return lhs << rhs.Value(); + lhs << &rhs << '='; + return lhs << rhs.Word(); } struct CYIdentifier : CYWord { + CYIdentifier *replace_; + CYIdentifier(const char *word) : - CYWord(word) + CYWord(word), + replace_(NULL) { } + + virtual const char *Word() const; + CYIdentifier *Replace(CYContext &context); }; struct CYComment : @@ -283,7 +283,50 @@ struct CYLabel : virtual void Output(CYOutput &out, CYFlags flags) const; }; +struct CStringLess : + std::binary_function +{ + _finline bool operator ()(const char *lhs, const char *rhs) const { + return strcmp(lhs, rhs) < 0; + } +}; + +struct CYIdentifierValueLess : + std::binary_function +{ + _finline bool operator ()(CYIdentifier *lhs, CYIdentifier *rhs) const { + return CStringLess()(lhs->Word(), rhs->Word()); + } +}; + +enum CYIdentifierFlags { + CYIdentifierArgument, + CYIdentifierInternal, + CYIdentifierVariable +}; + +typedef std::set CYIdentifierValueSet; +typedef std::set CYIdentifierAddressSet; +typedef std::map CYIdentifierAddressFlagsMap; + +struct CYScope { + CYScope *parent_; + CYIdentifierValueSet identifiers_; + CYIdentifierAddressFlagsMap internal_; + unsigned offset_; + + CYScope() : + parent_(NULL), + offset_(0) + { + } + + void Add(CYContext &context, CYIdentifierAddressSet &external); + void Scope(CYContext &context, CYStatement *&statements); +}; + struct CYProgram : + CYScope, CYThing { CYStatement *statements_; @@ -303,9 +346,11 @@ struct CYBlock : CYThing { CYStatement *statements_; + CYScope *scope_; - CYBlock(CYStatement *statements) : - statements_(statements) + CYBlock(CYStatement *statements, CYScope *scope = NULL) : + statements_(statements), + scope_(scope) { } @@ -313,6 +358,14 @@ struct CYBlock : return statements_; } + void AddPrev(CYStatement *statement) { + CYStatement *last(statement); + while (last->next_ != NULL) + last = last->next_; + last->SetNext(statements_); + statements_ = statement; + } + virtual CYStatement *Replace(CYContext &context); virtual void Output(CYOutput &out) const; @@ -379,6 +432,7 @@ struct CYForInitialiser { } virtual void For(CYOutput &out) const = 0; + virtual CYExpression *Replace(CYContext &context) = 0; }; struct CYForInInitialiser { @@ -388,6 +442,7 @@ struct CYForInInitialiser { virtual void ForIn(CYOutput &out, CYFlags flags) const = 0; virtual const char *ForEachIn() const = 0; virtual CYExpression *ForEachIn(CYContext &out) = 0; + virtual CYExpression *Replace(CYContext &context) = 0; }; struct CYNumber; @@ -460,7 +515,7 @@ struct CYCompound : { CYExpression *expressions_; - CYCompound(CYExpression *expressions) : + CYCompound(CYExpression *expressions = NULL) : expressions_(expressions) { } @@ -491,6 +546,7 @@ struct CYFunctionParameter : { } + void Replace(CYContext &context); virtual void Output(CYOutput &out) const; }; @@ -519,7 +575,7 @@ struct CYForInComprehension : } virtual const char *Name() const { - return name_->Value(); + return name_->Word(); } virtual CYFunctionParameter *Parameter(CYContext &context) const; @@ -540,7 +596,7 @@ struct CYForEachInComprehension : } virtual const char *Name() const { - return name_->Value(); + return name_->Word(); } virtual CYFunctionParameter *Parameter(CYContext &context) const; @@ -655,7 +711,7 @@ struct CYString : } CYString(const CYWord *word) : - value_(word->Value()), + value_(word->Word()), size_(strlen(value_)) { } @@ -999,15 +1055,16 @@ struct CYDeclaration : virtual const char *ForEachIn() const; virtual CYExpression *ForEachIn(CYContext &out); - void Replace(CYContext &context); + virtual CYExpression *Replace(CYContext &context); + virtual CYAssignment *Assignment(CYContext &context); virtual void Output(CYOutput &out, CYFlags flags) const; }; struct CYDeclarations : CYNext, - CYForInitialiser, - CYThing + CYThing, + CYForInitialiser { CYDeclaration *declaration_; @@ -1019,7 +1076,7 @@ struct CYDeclarations : virtual void For(CYOutput &out) const; - void Replace(CYContext &context); + virtual CYCompound *Replace(CYContext &context); CYProperty *Property(CYContext &context); virtual void Output(CYOutput &out) const; @@ -1266,7 +1323,9 @@ struct CYWhile : virtual void Output(CYOutput &out, CYFlags flags) const; }; -struct CYFunction { +struct CYFunction : + CYScope +{ CYIdentifier *name_; CYFunctionParameter *parameters_; CYBlock code_; @@ -1274,7 +1333,7 @@ struct CYFunction { CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *statements) : name_(name), parameters_(parameters), - code_(statements) + code_(statements, this) { } @@ -1322,8 +1381,11 @@ struct CYExpress : CYExpress(CYExpression *expression) : expression_(expression) { + if (expression == NULL) + throw; } + virtual CYStatement *Collapse(CYContext &context); virtual CYStatement *Replace(CYContext &context); virtual void Output(CYOutput &out, CYFlags flags) const; }; @@ -1373,6 +1435,7 @@ struct CYReturn : struct CYEmpty : CYStatement { + virtual CYStatement *Collapse(CYContext &context); virtual CYStatement *Replace(CYContext &context); virtual void Output(CYOutput &out, CYFlags flags) const; }; diff --git a/Replace.cpp b/Replace.cpp index 8039118..fc02461 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -38,6 +38,7 @@ /* }}} */ #include "Parser.hpp" +#include "Context.hpp" #include @@ -56,11 +57,11 @@ CYExpression *CYAdd::Replace(CYContext &context) { if (lhs == NULL) { lhs = lhp->String(context); if (lhs == NULL) - return NULL; + return this; } else if (rhs == NULL) { rhs = rhp->String(context); if (rhs == NULL) - return NULL; + return this; } return lhs->Concat(context, rhs); @@ -70,7 +71,7 @@ CYExpression *CYAdd::Replace(CYContext &context) { if (CYNumber *rhn = rhp->Number(context)) return $D(lhn->Value() + rhn->Value()); - return NULL; + return this; } CYExpression *CYAddressOf::Replace(CYContext &context) { @@ -85,7 +86,7 @@ void CYArgument::Replace(CYContext &context) { $T() CYExpression *CYArray::Replace(CYContext &context) { elements_->Replace(context); - return NULL; + return this; } CYExpression *CYArrayComprehension::Replace(CYContext &context) { @@ -101,22 +102,24 @@ CYExpression *CYArrayComprehension::Replace(CYContext &context) { CYExpression *CYAssignment::Replace(CYContext &context) { context.Replace(lhs_); context.Replace(rhs_); - return NULL; + return this; } CYStatement *CYBlock::Replace(CYContext &context) { statements_ = statements_->ReplaceAll(context); - return NULL; + if (statements_ == NULL) + return $ CYEmpty(); + return this; } CYStatement *CYBreak::Replace(CYContext &context) { - return NULL; + return this; } CYExpression *CYCall::Replace(CYContext &context) { context.Replace(function_); arguments_->Replace(context); - return NULL; + return this; } namespace cy { @@ -135,12 +138,12 @@ void CYClause::Replace(CYContext &context) { $T() } CYStatement *CYComment::Replace(CYContext &context) { - return NULL; + return this; } CYExpression *CYCompound::Replace(CYContext &context) { expressions_ = expressions_->ReplaceAll(context); - return NULL; + return expressions_ == NULL ? NULL : this; } CYFunctionParameter *CYComprehension::Parameters(CYContext &context) const { $T(NULL) @@ -160,39 +163,56 @@ CYExpression *CYCondition::Replace(CYContext &context) { context.Replace(test_); context.Replace(true_); context.Replace(false_); - return NULL; + return this; } CYStatement *CYContinue::Replace(CYContext &context) { - return NULL; + return this; +} + +CYAssignment *CYDeclaration::Assignment(CYContext &context) { + CYExpression *variable(Replace(context)); + return initialiser_ == NULL ? NULL : $ CYAssign(variable, initialiser_); } CYExpression *CYDeclaration::ForEachIn(CYContext &context) { return $ CYVariable(identifier_); } -void CYDeclaration::Replace(CYContext &context) { - context.Replace(initialiser_); +CYExpression *CYDeclaration::Replace(CYContext &context) { + CYIdentifier *identifier(identifier_->Replace(context)); + context.scope_->internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, CYIdentifierVariable)); + return $ CYVariable(identifier); } CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL) return $ CYProperty(declaration_->identifier_, declaration_->initialiser_ ?: $U, next_->Property(context)); } -void CYDeclarations::Replace(CYContext &context) { $T() - declaration_->Replace(context); - next_->Replace(context); +CYCompound *CYDeclarations::Replace(CYContext &context) { + CYCompound *compound; + if (next_ == NULL) compound: + compound = $ CYCompound(); + else { + compound = next_->Replace(context); + if (compound == NULL) + goto compound; + } + + if (CYAssignment *assignment = declaration_->Assignment(context)) + compound->AddPrev(assignment); + return compound; } CYExpression *CYDirectMember::Replace(CYContext &context) { Replace_(context); - return NULL; + return this; } CYStatement *CYDoWhile::Replace(CYContext &context) { context.Replace(test_); context.Replace(code_); - return NULL; + return this; } void CYElement::Replace(CYContext &context) { $T() @@ -200,13 +220,32 @@ void CYElement::Replace(CYContext &context) { $T() next_->Replace(context); } +CYStatement *CYEmpty::Collapse(CYContext &context) { + return next_; +} + CYStatement *CYEmpty::Replace(CYContext &context) { - return NULL; + return this; +} + +CYStatement *CYExpress::Collapse(CYContext &context) { + if (CYExpress *express = dynamic_cast(next_)) { + CYCompound *next(dynamic_cast(express->expression_)); + if (next == NULL) + next = $ CYCompound(express->expression_); + next->AddPrev(expression_); + expression_ = next; + SetNext(express->next_); + } + + return this; } CYStatement *CYExpress::Replace(CYContext &context) { context.Replace(expression_); - return NULL; + if (expression_ == NULL) + return $ CYEmpty(); + return this; } CYExpression *CYExpression::ClassName(CYContext &context, bool object) { @@ -242,18 +281,19 @@ void CYFinally::Replace(CYContext &context) { $T() } CYStatement *CYFor::Replace(CYContext &context) { - // XXX: initialiser_ + context.Replace(initialiser_); context.Replace(test_); context.Replace(increment_); context.Replace(code_); - return NULL; + return this; } CYStatement *CYForIn::Replace(CYContext &context) { - // XXX: initialiser_ + // XXX: this actually might need a prefix statement + context.Replace(initialiser_); context.Replace(set_); context.Replace(code_); - return NULL; + return this; } CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const { @@ -292,24 +332,50 @@ CYStatement *CYForEachInComprehension::Replace(CYContext &context, CYStatement * } void CYFunction::Replace_(CYContext &context) { + parent_ = context.scope_; + context.scope_ = this; + + parameters_->Replace(context); code_.Replace(context); + + context.scope_ = parent_; + Scope(context, code_.statements_); } CYExpression *CYFunctionExpression::Replace(CYContext &context) { Replace_(context); - return NULL; + return this; +} + +void CYFunctionParameter::Replace(CYContext &context) { $T() + name_ = name_->Replace(context); + context.scope_->internal_.insert(CYIdentifierAddressFlagsMap::value_type(name_, CYIdentifierArgument)); + next_->Replace(context); } CYStatement *CYFunctionStatement::Replace(CYContext &context) { Replace_(context); - return NULL; + return this; +} + +CYIdentifier *CYIdentifier::Replace(CYContext &context) { + if (replace_ != NULL) + return replace_; + + CYIdentifierValueSet &identifiers(context.scope_->identifiers_); + std::pair insert(identifiers.insert(this)); + if (!insert.second) + return *insert.first; + + replace_ = this; + return this; } CYStatement *CYIf::Replace(CYContext &context) { context.Replace(test_); context.Replace(true_); context.Replace(false_); - return NULL; + return this; } CYFunctionParameter *CYIfComprehension::Parameter(CYContext &context) const { @@ -333,12 +399,12 @@ CYExpression *CYIndirectMember::Replace(CYContext &context) { CYExpression *CYInfix::Replace(CYContext &context) { context.Replace(lhs_); context.Replace(rhs_); - return NULL; + return this; } CYStatement *CYLabel::Replace(CYContext &context) { context.Replace(statement_); - return NULL; + return this; } CYStatement *CYLet::Replace(CYContext &context) { @@ -353,7 +419,7 @@ void CYMember::Replace_(CYContext &context) { CYExpression *CYNew::Replace(CYContext &context) { context.Replace(constructor_); arguments_->Replace(context); - return NULL; + return this; } CYNumber *CYNull::Number(CYContext &context) { @@ -375,21 +441,25 @@ CYString *CYNumber::String(CYContext &context) { CYExpression *CYObject::Replace(CYContext &context) { properties_->Replace(context); - return NULL; + return this; } CYExpression *CYPostfix::Replace(CYContext &context) { context.Replace(lhs_); - return NULL; + return this; } CYExpression *CYPrefix::Replace(CYContext &context) { context.Replace(rhs_); - return NULL; + return this; } void CYProgram::Replace(CYContext &context) { + parent_ = context.scope_; + context.scope_ = this; statements_ = statements_->ReplaceAll(context); + context.scope_ = parent_; + Scope(context, statements_); } void CYProperty::Replace(CYContext &context) { $T() @@ -399,19 +469,71 @@ void CYProperty::Replace(CYContext &context) { $T() CYStatement *CYReturn::Replace(CYContext &context) { context.Replace(value_); - return NULL; + return this; +} + +void CYScope::Add(CYContext &context, CYIdentifierAddressSet &external) { + for (CYIdentifierAddressSet::const_iterator i(external.begin()); i != external.end(); ++i) { + std::pair insert(identifiers_.insert(*i)); + if (!insert.second) + (*i)->replace_ = *insert.first; + } +} + +void CYScope::Scope(CYContext &context, CYStatement *&statements) { + CYIdentifierAddressSet external; + + if (context.options_.verbose_) + std::cout << this << ':'; + + CYDeclarations *last(NULL), *curr(NULL); + + for (CYIdentifierValueSet::const_iterator i(identifiers_.begin()); i != identifiers_.end(); ++i) + if (internal_.find(*i) == internal_.end()) { + if (context.options_.verbose_) + std::cout << ' ' << (*i)->Word() << '@' << static_cast(*i); + external.insert(*i); + } else { + if (context.options_.verbose_) { + std::cout << ' ' << offset_ << ':' << (*i)->Word() << '@' << static_cast(*i); + (*i)->Set(apr_psprintf(context.pool_, "$%u", offset_++)); + } else { + (*i)->Set(apr_psprintf(context.pool_, "$%u", offset_++)); + } + + CYDeclarations *next($ CYDeclarations($ CYDeclaration(*i))); + if (last == NULL) + last = next; + if (curr != NULL) + curr->SetNext(next); + curr = next; + } + + if (context.options_.verbose_) + std::cout << " ->" << parent_ << std::endl; + + if (last != NULL) { + CYVar *var($ CYVar(last)); + var->SetNext(statements); + statements = var; + } + + if (parent_ != NULL) { + if (parent_->offset_ < offset_) + parent_->offset_ = offset_; + parent_->Add(context, external); + } +} + +CYStatement *CYStatement::Collapse(CYContext &context) { + return this; } 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; + replace->SetNext(next_->ReplaceAll(context)); + return replace->Collapse(context); } CYString *CYString::Concat(CYContext &context, CYString *rhs) const { @@ -435,11 +557,11 @@ CYString *CYString::String(CYContext &context) { CYStatement *CYSwitch::Replace(CYContext &context) { context.Replace(value_); clauses_->Replace(context); - return NULL; + return this; } CYExpression *CYThis::Replace(CYContext &context) { - return NULL; + return this; } namespace cy { @@ -447,13 +569,13 @@ namespace Syntax { CYStatement *Throw::Replace(CYContext &context) { context.Replace(value_); - return NULL; + return this; } } } CYExpression *CYTrivial::Replace(CYContext &context) { - return NULL; + return this; } CYNumber *CYTrue::Number(CYContext &context) { @@ -471,30 +593,30 @@ CYStatement *Try::Replace(CYContext &context) { code_.Replace(context); catch_->Replace(context); finally_->Replace(context); - return NULL; + return this; } } } CYStatement *CYVar::Replace(CYContext &context) { - declarations_->Replace(context); - return NULL; + return $E(declarations_->Replace(context)); } CYExpression *CYVariable::Replace(CYContext &context) { - return NULL; + name_ = name_->Replace(context); + return this; } CYStatement *CYWhile::Replace(CYContext &context) { context.Replace(test_); context.Replace(code_); - return NULL; + return this; } CYStatement *CYWith::Replace(CYContext &context) { context.Replace(scope_); context.Replace(code_); - return NULL; + return this; } CYExpression *CYWord::ClassName(CYContext &context, bool object) { diff --git a/makefile b/makefile index 8ea1d3d..430e6d6 100644 --- a/makefile +++ b/makefile @@ -22,7 +22,7 @@ ifneq ($(dpkg_architecture),) arch := $(shell $(dpkg_architecture) -qDEB_HOST_ARCH 2>/dev/null) endif -header := Cycript.tab.hh Parser.hpp Pooling.hpp cycript.hpp Internal.hpp Error.hpp String.hpp Exception.hpp Standard.hpp +header := Cycript.tab.hh Parser.hpp Pooling.hpp cycript.hpp Internal.hpp Error.hpp String.hpp Exception.hpp Standard.hpp Context.hpp code := code += Replace.o Output.o @@ -139,6 +139,8 @@ package: $(deb) test: $(deb) dpkg -i $(deb) - cycript test.cy + if [[ -e target.cy ]]; then cycript -c target.cy && echo; fi + if [[ -e jquery.js ]]; then cycript -c jquery.js >jquery.cyc.js; gzip -9c jquery.cyc.js >jquery.cyc.js.gz; ls -la jquery.{cyc,yui}.js{,.gz}; fi + if [[ -e test.cy ]]; then cycript test.cy; fi .PHONY: all clean extra package control diff --git a/todo.txt b/todo.txt index 14c0fb7..8426abe 100644 --- a/todo.txt +++ b/todo.txt @@ -24,3 +24,5 @@ the concept of NULL pooling is entirely incorrect and sad... bad... evil... need NSArray's .toString() and .toLocaleString() fail hard, as Array.prototype.to*String are Array-specific (4).toString() is legal, but I'm stripping the ()'s somehow in the serializer applyOnMainThread, when done at console, loops the cyonifier + +!! CYScope has a bunch of STL container objects that are leaking /all/ of their memory -- 2.45.2