]> git.saurik.com Git - cycript.git/commitdiff
Started working on variable name replacement strategies and generally improved compiler.
authorJay Freeman (saurik) <saurik@saurik.com>
Mon, 16 Nov 2009 10:11:09 +0000 (10:11 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Mon, 16 Nov 2009 10:11:09 +0000 (10:11 +0000)
12 files changed:
Console.cpp
Context.hpp [new file with mode: 0644]
Execute.cpp
Handler.mm
Library.cpp
ObjectiveC/Replace.mm
Options.hpp [new file with mode: 0644]
Output.cpp
Parser.hpp
Replace.cpp
makefile
todo.txt

index 44cadc7ad470bb9c3584f26d8fc967ded222a752..0ed0bfe220d03421f63e1471d50f4e3e20ca62ba 100644 (file)
@@ -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 (file)
index 0000000..dfa0b62
--- /dev/null
@@ -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 <typename Type_>
+    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*/
index a517fb4df08c8d1b17c8b47b37e05b0ef8fb55d7..3f094191652c548ad502052322771ee7214a75a8 100644 (file)
@@ -181,14 +181,6 @@ void CYFinalize(JSObjectRef object) {
     delete reinterpret_cast<CYData *>(JSObjectGetPrivate(object));
 }
 
-struct CStringMapLess :
-    std::binary_function<const char *, const char *, bool>
-{
-    _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<const char *, Type_privateData *, CStringMapLess> TypeMap;
+typedef std::map<const char *, Type_privateData *, CStringLess> TypeMap;
 static TypeMap Types_;
 
 JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
index 38ef638182fe2d37dbd0733a0159d29b4ecf2765..40b79f8ec20801e056ee6efd5dab7188d016ff6c 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "Pooling.hpp"
 #include "Parser.hpp"
+#include "Context.hpp"
 
 #include "Cycript.tab.hh"
 
index 8068e821bae4f8b2b3aa7a339c1459e93f60c9a0..610e11b97868bf3b95ed7fa94c0176da57e07bcb 100644 (file)
@@ -43,6 +43,7 @@
 #include "cycript.hpp"
 
 #include "Pooling.hpp"
+#include "Context.hpp"
 
 #include <sys/mman.h>
 
@@ -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());
 
index 92fc77c027f129fdc698263bada1743f000004be..6d40c3c2ef04d918f35a2962609322054537067f 100644 (file)
@@ -38,6 +38,7 @@
 /* }}} */
 
 #include "Replace.hpp"
+#include "Context.hpp"
 #include "ObjectiveC/Syntax.hpp"
 
 #include <Foundation/Foundation.h>
diff --git a/Options.hpp b/Options.hpp
new file mode 100644 (file)
index 0000000..68958d8
--- /dev/null
@@ -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*/
index 04f893c9299d74671fb812a04a1975ed40ee2980..27ea3fcff21b87fbd7a4e537bdfb1546f51e4111 100644 (file)
@@ -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<const CYScope *>(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_;
+}
index 8f42bc367582e792cfaf608a7498b2b8752dbfad..dc3c907f30976b0aa02af2f712aee32917c97b95 100644 (file)
 
 #include <string>
 #include <vector>
+#include <map>
+#include <set>
 
 #include <cstdlib>
 
 #include "location.hh"
 #include "Pooling.hpp"
+#include "Options.hpp"
+
+class CYContext;
 
 template <typename Type_>
 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 <typename Type_>
-    void Replace(Type_ *&value) {
-        if (value != NULL)
-            while (Type_ *replace = value->Replace(*this))
-                value = replace;
-    }
-};
-
 struct CYStatement :
     CYNext<CYStatement>
 {
@@ -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<const char *, const char *, bool>
+{
+    _finline bool operator ()(const char *lhs, const char *rhs) const {
+        return strcmp(lhs, rhs) < 0;
+    }
+};
+
+struct CYIdentifierValueLess :
+    std::binary_function<CYIdentifier *, CYIdentifier *, bool>
+{
+    _finline bool operator ()(CYIdentifier *lhs, CYIdentifier *rhs) const {
+        return CStringLess()(lhs->Word(), rhs->Word());
+    }
+};
+
+enum CYIdentifierFlags {
+    CYIdentifierArgument,
+    CYIdentifierInternal,
+    CYIdentifierVariable
+};
+
+typedef std::set<CYIdentifier *, CYIdentifierValueLess> CYIdentifierValueSet;
+typedef std::set<CYIdentifier *> CYIdentifierAddressSet;
+typedef std::map<CYIdentifier *, CYIdentifierFlags> 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<CYDeclarations>,
-    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;
 };
index 80391180ecb1a5556625a203aae79ac043fba287..fc024612461a84fa7849cca8cf2ce12d0133bf77 100644 (file)
@@ -38,6 +38,7 @@
 /* }}} */
 
 #include "Parser.hpp"
+#include "Context.hpp"
 
 #include <iomanip>
 
@@ -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<CYExpress *>(next_)) {
+        CYCompound *next(dynamic_cast<CYCompound *>(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<CYIdentifierValueSet::iterator, bool> 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<CYIdentifierAddressSet::iterator, bool> 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<const CYWord *>(*i);
+            external.insert(*i);
+        } else {
+            if (context.options_.verbose_) {
+                std::cout << ' ' << offset_ << ':' << (*i)->Word() << '@' << static_cast<const CYWord *>(*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) {
index 8ea1d3da2c834e18521b92e089a92753e89042b0..430e6d6c6e069438931a2bd54f9cff0f624069b6 100644 (file)
--- 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
index 14c0fb72d48e60912d26b389b5c08ecd486ea448..8426abed151823a068f953c6e48ec61353093233 100644 (file)
--- 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