/* }}} */
#include "Parser.hpp"
-#include "Context.hpp"
+#include "Replace.hpp"
#include <iomanip>
-#include "Replace.hpp"
-
CYExpression *CYAdd::Replace(CYContext &context) {
CYInfix::Replace(context);
}
CYExpression *CYDeclaration::Replace(CYContext &context) {
- CYIdentifier *identifier(identifier_->Replace(context));
- context.scope_->internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, CYIdentifierVariable));
- return $ CYVariable(identifier);
+ context.Replace(identifier_);
+ context.scope_->Declare(context, identifier_, CYIdentifierVariable);
+ return $ CYVariable(identifier_);
}
CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL)
}
void CYFunction::Inject(CYContext &context) {
- name_ = name_->Replace(context);
- context.scope_->internal_.insert(CYIdentifierAddressFlagsMap::value_type(name_, CYIdentifierOther));
+ context.Replace(name_);
+ context.scope_->Declare(context, name_, CYIdentifierOther);
}
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);
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) {
void CYFunctionParameter::Replace(CYContext &context) { $T()
name_ = name_->Replace(context);
- context.scope_->internal_.insert(CYIdentifierAddressFlagsMap::value_type(name_, CYIdentifierArgument));
+ context.scope_->Declare(context, name_, CYIdentifierArgument);
next_->Replace(context);
}
}
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;
+ if (replace_ != NULL && replace_ != this)
+ return replace_->Replace(context);
+ replace_ = context.scope_->Lookup(context, this);
+ return replace_;
}
CYStatement *CYIf::Replace(CYContext &context) {
return this;
}
-void CYProgram::Replace(CYContext &context) {
- parent_ = context.scope_;
- CYProgram *program(context.program_);
+// XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
+#define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
+//#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
+
+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_;
- Scope(context, statements_);
- context.program_ = program;
+ context.scope_ = scope.parent_;
+ scope.Scope(context, statements_);
size_t offset(0);
+ CYCStringSet external;
+ 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_)
unsigned position(7), local(offset + 1);
do {
- unsigned index(local % 53);
- local /= 53;
- id[--position] = index == 0 ? '0' : index < 27 ? index - 1 + 'a' : index - 27 + 'A';
+ unsigned index(local % (sizeof(MappingSet) - 1));
+ local /= sizeof(MappingSet) - 1;
+ id[--position] = MappingSet[index];
} while (local != 0);
- if (external_.find(id + position) != external_.end()) {
+ if (external.find(id + position) != external.end()) {
++offset;
goto id;
}
// 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);
}
}
return this;
}
-void CYScope::Add(CYContext &context, CYIdentifierAddressVector &external) {
- for (CYIdentifierAddressVector::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::Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags) {
+ internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, flags));
+}
+
+CYIdentifier *CYScope::Lookup(CYContext &context, CYIdentifier *identifier) {
+ std::pair<CYIdentifierValueSet::iterator, bool> insert(identifiers_.insert(identifier));
+ return *insert.first;
+}
+
+void CYScope::Merge(CYContext &context, CYIdentifier *identifier) {
+ std::pair<CYIdentifierValueSet::iterator, bool> insert(identifiers_.insert(identifier));
+ if (!insert.second) {
+ if ((*insert.first)->offset_ < identifier->offset_)
+ (*insert.first)->offset_ = identifier->offset_;
+ identifier->replace_ = *insert.first;
+ (*insert.first)->usage_ += identifier->usage_ + 1;
}
}
-void CYScope::Scope(CYContext &context, CYStatement *&statements) {
- CYIdentifierAddressVector external;
+namespace {
+ struct IdentifierOffset {
+ size_t offset_;
+ CYIdentifierFlags flags_;
+ size_t usage_;
+ CYIdentifier *identifier_;
- for (CYIdentifierValueSet::const_iterator i(identifiers_.begin()); i != identifiers_.end(); ++i)
- if (internal_.find(*i) == internal_.end())
- external.push_back(*i);
+ IdentifierOffset(CYIdentifier *identifier, CYIdentifierFlags flags) :
+ offset_(identifier->offset_),
+ flags_(flags),
+ usage_(identifier->usage_),
+ identifier_(identifier)
+ {
+ }
+ };
+
+ struct IdentifierOffsetLess :
+ std::binary_function<const IdentifierOffset &, const IdentifierOffset &, bool>
+ {
+ _finline bool operator ()(const IdentifierOffset &lhs, const IdentifierOffset &rhs) const {
+ if (lhs.offset_ != rhs.offset_)
+ 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_;
+ }
+ };
+
+ typedef std::set<IdentifierOffset, IdentifierOffsetLess> IdentifierOffsets;
+}
+
+void CYScope::Scope(CYContext &context, CYStatement *&statements) {
+ if (parent_ == NULL)
+ return;
CYDeclarations *last(NULL), *curr(NULL);
- CYProgram *program(context.program_);
-
- // 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) {
- if (program->rename_.size() <= offset_)
- program->rename_.resize(offset_ + 1);
- CYIdentifier *&identifier(program->rename_[offset_++]);
- i->first->SetNext(identifier);
- identifier = i->first;
- }
- if (i->second == CYIdentifierVariable) {
- CYDeclarations *next($ CYDeclarations($ CYDeclaration(i->first)));
+ IdentifierOffsets offsets;
+
+ for (CYIdentifierAddressFlagsMap::const_iterator i(internal_.begin()); i != internal_.end(); ++i)
+ if (i->second != CYIdentifierMagic)
+ offsets.insert(IdentifierOffset(i->first, i->second));
+
+ size_t offset(0);
+
+ for (IdentifierOffsets::const_iterator i(offsets.begin()); i != offsets.end(); ++i) {
+ if (i->flags_ == CYIdentifierVariable) {
+ CYDeclarations *next($ CYDeclarations($ CYDeclaration(i->identifier_)));
if (last == NULL)
last = next;
if (curr != NULL)
curr->SetNext(next);
curr = next;
}
+
+ if (offset < i->offset_)
+ offset = i->offset_;
+ if (context.rename_.size() <= offset)
+ context.rename_.resize(offset + 1);
+
+ CYIdentifierUsage &rename(context.rename_[offset++]);
+ i->identifier_->SetNext(rename.identifier_);
+ rename.identifier_ = i->identifier_;
+ rename.usage_ += i->identifier_->usage_ + 1;
}
if (last != NULL) {
statements = var;
}
- if (parent_ != NULL) {
- if (parent_->offset_ < offset_)
- parent_->offset_ = offset_;
- parent_->Add(context, external);
- } else if (program != NULL)
- for (CYIdentifierAddressVector::const_iterator i(external.begin()); i != external.end(); ++i)
- program->external_.insert((*i)->Word());
+ 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);
+ }
}
CYStatement *CYStatement::Collapse(CYContext &context) {