]> git.saurik.com Git - cycript.git/blobdiff - Replace.cpp
Add a valueOf to Instance.
[cycript.git] / Replace.cpp
index 37b7068cd455f4a88b35e9931508d58090ff2c72..c06c2a514e91711346494fab13feb64c38c579b5 100644 (file)
@@ -338,8 +338,9 @@ void CYFunction::Replace_(CYContext &context, bool outer) {
     if (outer)
         Inject(context);
 
-    parent_ = context.scope_;
-    context.scope_ = this;
+    CYScope scope;
+    scope.parent_ = context.scope_;
+    context.scope_ = &scope;
 
     if (!outer && name_ != NULL)
         Inject(context);
@@ -347,8 +348,8 @@ void CYFunction::Replace_(CYContext &context, bool outer) {
     parameters_->Replace(context);
     code_.Replace(context);
 
-    context.scope_ = parent_;
-    Scope(context, code_.statements_);
+    context.scope_ = scope.parent_;
+    scope.Scope(context, code_.statements_);
 }
 
 CYExpression *CYFunctionExpression::Replace(CYContext &context) {
@@ -368,8 +369,9 @@ CYStatement *CYFunctionStatement::Replace(CYContext &context) {
 }
 
 CYIdentifier *CYIdentifier::Replace(CYContext &context) {
-    if (replace_ == NULL)
-        replace_ = context.scope_->Lookup(context, this);
+    if (replace_ != NULL && replace_ != this)
+        return replace_->Replace(context);
+    replace_ = context.scope_->Lookup(context, this);
     return replace_;
 }
 
@@ -460,27 +462,44 @@ CYExpression *CYPrefix::Replace(CYContext &context) {
 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
 
-void CYProgram::Replace(CYContext &context) {
-    parent_ = context.scope_;
-    CYProgram *program(context.program_);
+namespace {
+    struct IdentifierUsageLess :
+        std::binary_function<CYIdentifier *, CYIdentifier *, bool>
+    {
+        _finline bool operator ()(CYIdentifier *lhs, CYIdentifier *rhs) const {
+            if (lhs->usage_ != rhs->usage_)
+                return lhs->usage_ > rhs->usage_;
+            return lhs < rhs;
+        }
+    };
 
-    context.scope_ = this;
-    context.program_ = this;
+    typedef std::set<CYIdentifier *, IdentifierUsageLess> IdentifierUsages;
+}
 
+void CYProgram::Replace(CYContext &context) {
+    CYScope scope;
+    scope.parent_ = context.scope_;
+    context.scope_ = &scope;
     statements_ = statements_->ReplaceAll(context);
-
-    context.scope_ = parent_;
-    context.program_ = program;
-    Scope(context, statements_);
+    context.scope_ = scope.parent_;
+    scope.Scope(context, statements_);
 
     size_t offset(0);
 
     CYCStringSet external;
-    for (CYIdentifierValueSet::const_iterator i(identifiers_.begin()); i != identifiers_.end(); ++i)
+    for (CYIdentifierValueSet::const_iterator i(scope.identifiers_.begin()); i != scope.identifiers_.end(); ++i)
         external.insert((*i)->Word());
 
+    IdentifierUsages usages;
+
+    if (offset < context.rename_.size())
+        for (CYIdentifier *i(context.rename_[offset].identifier_); i != NULL; i = i->next_)
+             usages.insert(i);
+
     // XXX: totalling the probable occurrences and sorting by them would improve the result
-    for (CYIdentifierAddressVector::const_iterator i(rename_.begin()); i != rename_.end(); ++i, ++offset) {
+    for (CYIdentifierUsageVector::const_iterator i(context.rename_.begin()); i != context.rename_.end(); ++i, ++offset) {
+        //std::cout << *i << ":" << (*i)->offset_ << std::endl;
+
         const char *name;
 
         if (context.options_.verbose_)
@@ -507,7 +526,7 @@ void CYProgram::Replace(CYContext &context) {
             // XXX: at some point, this could become a keyword
         }
 
-        for (CYIdentifier *identifier(*i); identifier != NULL; identifier = identifier->next_)
+        for (CYIdentifier *identifier(i->identifier_); identifier != NULL; identifier = identifier->next_)
             identifier->Set(name);
     }
 }
@@ -537,6 +556,7 @@ void CYScope::Merge(CYContext &context, CYIdentifier *identifier) {
         if ((*insert.first)->offset_ < identifier->offset_)
             (*insert.first)->offset_ = identifier->offset_;
         identifier->replace_ = *insert.first;
+        (*insert.first)->usage_ += identifier->usage_ + 1;
     }
 }
 
@@ -544,11 +564,13 @@ namespace {
     struct IdentifierOffset {
         size_t offset_;
         CYIdentifierFlags flags_;
+        size_t usage_;
         CYIdentifier *identifier_;
 
-        IdentifierOffset(size_t offset, CYIdentifierFlags flags, CYIdentifier *identifier) :
-            offset_(offset),
+        IdentifierOffset(CYIdentifier *identifier, CYIdentifierFlags flags) :
+            offset_(identifier->offset_),
             flags_(flags),
+            usage_(identifier->usage_),
             identifier_(identifier)
         {
         }
@@ -562,6 +584,8 @@ namespace {
                 return lhs.offset_ < rhs.offset_;
             if (lhs.flags_ != rhs.flags_)
                 return lhs.flags_ < rhs.flags_;
+            /*if (lhs.usage_ != rhs.usage_)
+                return lhs.usage_ < rhs.usage_;*/
             return lhs.identifier_ < rhs.identifier_;
         }
     };
@@ -570,15 +594,16 @@ namespace {
 }
 
 void CYScope::Scope(CYContext &context, CYStatement *&statements) {
+    if (parent_ == NULL)
+        return;
+
     CYDeclarations *last(NULL), *curr(NULL);
-    CYProgram *program(context.program_);
 
     IdentifierOffsets offsets;
 
-    // XXX: we don't want to do this in order, we want to sort it by probable occurrence
     for (CYIdentifierAddressFlagsMap::const_iterator i(internal_.begin()); i != internal_.end(); ++i)
-        if (program != NULL && i->second != CYIdentifierMagic)
-            offsets.insert(IdentifierOffset(i->first->offset_, i->second, i->first));
+        if (i->second != CYIdentifierMagic)
+            offsets.insert(IdentifierOffset(i->first, i->second));
 
     size_t offset(0);
 
@@ -594,12 +619,13 @@ void CYScope::Scope(CYContext &context, CYStatement *&statements) {
 
         if (offset < i->offset_)
             offset = i->offset_;
-        if (program->rename_.size() <= offset)
-            program->rename_.resize(offset + 1);
+        if (context.rename_.size() <= offset)
+            context.rename_.resize(offset + 1);
 
-        CYIdentifier *&identifier(program->rename_[offset++]);
-        i->identifier_->SetNext(identifier);
-        identifier = i->identifier_;
+        CYIdentifierUsage &rename(context.rename_[offset++]);
+        i->identifier_->SetNext(rename.identifier_);
+        rename.identifier_ = i->identifier_;
+        rename.usage_ += i->identifier_->usage_ + 1;
     }
 
     if (last != NULL) {
@@ -610,6 +636,7 @@ void CYScope::Scope(CYContext &context, CYStatement *&statements) {
 
     for (CYIdentifierValueSet::const_iterator i(identifiers_.begin()); i != identifiers_.end(); ++i)
         if (internal_.find(*i) == internal_.end()) {
+            //std::cout << *i << '=' << offset << std::endl;
             if ((*i)->offset_ < offset)
                 (*i)->offset_ = offset;
             parent_->Merge(context, *i);