**/
/* }}} */
-#include "Parser.hpp"
-#include "Replace.hpp"
-
#include <iomanip>
+#include "Replace.hpp"
+#include "Syntax.hpp"
+
CYFunctionExpression *CYNonLocalize(CYContext &context, CYFunctionExpression *function) {
function->nonlocal_ = context.nextlocal_;
return function;
}
+CYFunctionExpression *CYSuperize(CYContext &context, CYFunctionExpression *function) {
+ function->super_ = context.super_;
+ return function;
+}
+
+CYStatement *CYDefineProperty(CYExpression *object, CYExpression *name, bool configurable, bool enumerable, CYProperty *descriptor) {
+ return $E($C3($M($V("Object"), $S("defineProperty")), object, name, $ CYObject(CYList<CYProperty>()
+ ->* (configurable ? $ CYPropertyValue($S("configurable"), $ CYTrue()) : NULL)
+ ->* (enumerable ? $ CYPropertyValue($S("enumerable"), $ CYTrue()) : NULL)
+ ->* descriptor)));
+}
+
+static void CYImplicitReturn(CYStatement *&code) {
+ if (CYStatement *&last = CYGetLast(code))
+ last = last->Return();
+}
+
CYExpression *CYAdd::Replace(CYContext &context) {
CYInfix::Replace(context);
}
CYExpression *CYArray::Replace(CYContext &context) {
- elements_->Replace(context);
+ if (elements_ != NULL)
+ elements_->Replace(context);
return this;
}
CYExpression *CYArrayComprehension::Replace(CYContext &context) {
CYVariable *cyv($V("$cyv"));
- return $C0($F(NULL, $P1($L("$cyv"), comprehensions_->Parameters(context)), $$->*
+ return $C0($F(NULL, $P1($L($I("$cyv")), comprehensions_->Parameters(context)), $$->*
$E($ CYAssign(cyv, $ CYArray()))->*
comprehensions_->Replace(context, $E($C1($M(cyv, $S("push")), expression_)))->*
$ CYReturn(cyv)
return this;
}
+CYStatement *CYBlock::Return() {
+ CYImplicitReturn(code_);
+ return this;
+}
+
CYStatement *CYBlock::Replace(CYContext &context) {
context.ReplaceAll(code_);
if (code_ == NULL)
} }
+CYExpression *CYClassExpression::Replace(CYContext &context) {
+ CYBuilder builder;
+
+ CYIdentifier *super(context.Unique());
+
+ CYIdentifier *old(context.super_);
+ context.super_ = super;
+
+ CYIdentifier *constructor(context.Unique());
+ CYForEach (member, tail_->static_)
+ member->Replace(context, builder, $V(constructor), true);
+
+ CYIdentifier *prototype(context.Unique());
+ CYForEach (member, tail_->instance_)
+ member->Replace(context, builder, $V(prototype), true);
+
+ if (tail_->constructor_ == NULL)
+ tail_->constructor_ = $ CYFunctionExpression(NULL, NULL, NULL);
+ tail_->constructor_ = CYSuperize(context, tail_->constructor_);
+
+ context.super_ = old;
+
+ return $C1($ CYFunctionExpression(NULL, $P($L(super)), $$
+ ->* $ CYVar($L1($L(constructor, tail_->constructor_)))
+ ->* $ CYVar($L1($L(prototype, $ CYFunctionExpression(NULL, NULL, NULL))))
+ ->* $E($ CYAssign($M($V(prototype), $S("prototype")), $M($V(super), $S("prototype"))))
+ ->* $E($ CYAssign($V(prototype), $N($V(prototype))))
+ ->* CYDefineProperty($V(prototype), $S("constructor"), false, false, $ CYPropertyValue($S("value"), $V(constructor)))
+ ->* $ CYVar(builder.declarations_)
+ ->* builder.statements_
+ ->* CYDefineProperty($V(constructor), $S("prototype"), false, false, $ CYPropertyValue($S("value"), $V(prototype)))
+ ->* $ CYReturn($V(constructor))
+ ), tail_->extends_ ?: $V($I("Object")));
+}
+
+CYStatement *CYClassStatement::Replace(CYContext &context) {
+ return $ CYVar($L1($L(name_, $ CYClassExpression(name_, tail_))));
+}
+
void CYClause::Replace(CYContext &context) { $T()
context.Replace(case_);
context.ReplaceAll(code_);
next_->Replace(context);
}
-CYStatement *CYComment::Replace(CYContext &context) {
- return this;
-}
-
CYExpression *CYCompound::Replace(CYContext &context) {
context.Replace(expression_);
context.Replace(next_);
return next_ == NULL ? statement : next_->Replace(context, statement);
}
+CYExpression *CYComputed::PropertyName(CYContext &context) {
+ return expression_;
+}
+
CYExpression *CYCondition::Replace(CYContext &context) {
context.Replace(test_);
context.Replace(true_);
CYIdentifier *unique(nextlocal_->identifier_->Replace(context));
CYStatement *declare(
- $ CYVar($L1($ CYDeclaration(unique, $ CYObject()))));
+ $ CYVar($L1($L(unique, $ CYObject()))));
cy::Syntax::Catch *rescue(
$ cy::Syntax::Catch(cye, $$->*
next_->Replace(context);
}
-CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL)
- return $ CYProperty(declaration_->identifier_, declaration_->initialiser_, next_->Property(context));
-}
-
CYFunctionParameter *CYDeclarations::Parameter(CYContext &context) { $T(NULL)
return $ CYFunctionParameter($ CYDeclaration(declaration_->identifier_), next_->Parameter(context));
}
return this;
}
-void CYElement::Replace(CYContext &context) { $T()
+void CYElementSpread::Replace(CYContext &context) {
context.Replace(value_);
- next_->Replace(context);
+}
+
+void CYElementValue::Replace(CYContext &context) {
+ context.Replace(value_);
+ if (next_ != NULL)
+ next_->Replace(context);
}
CYStatement *CYEmpty::Replace(CYContext &context) {
return typed_->Replace(context);
}
+CYStatement *CYExpress::Return() {
+ return $ CYReturn(expression_);
+}
+
CYStatement *CYExpress::Replace(CYContext &context) {
context.Replace(expression_);
return this;
return $C1(this, value);
}
-CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
- return this;
-}
-
CYStatement *CYExpression::ForEachIn(CYContext &context, CYExpression *value) {
return $E($ CYAssign(this, value));
}
}
CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
- return $ CYFunctionParameter($ CYDeclaration(name_));
+ return $ CYFunctionParameter(declaration_);
}
CYStatement *CYForInComprehension::Replace(CYContext &context, CYStatement *statement) const {
- return $ CYForIn($V(name_), set_, CYComprehension::Replace(context, statement));
+ return $ CYForIn(declaration_->Variable(context), set_, CYComprehension::Replace(context, statement));
}
CYStatement *CYForOf::Replace(CYContext &context) {
this
);
- CYIdentifier *cys($I("$cys")), *cyt($I("$cyt"));
+ CYIdentifier *cys(context.Unique()), *cyt(context.Unique());
- return $ CYLetStatement($L2($ CYDeclaration(cys, set_), $ CYDeclaration(cyt)), $$->*
- $ CYForIn($V(cyt), $V(cys), $ CYBlock($$->*
- initialiser_->ForEachIn(context, $M($V(cys), $V(cyt)))->*
- code_
- ))
- );
+ return $ CYBlock($$
+ ->* $ CYLet($L2($L(cys, set_), $L(cyt)))
+ ->* $ CYForIn($V(cyt), $V(cys), $ CYBlock($$
+ ->* initialiser_->ForEachIn(context, $M($V(cys), $V(cyt)))
+ ->* code_
+ )));
}
CYFunctionParameter *CYForOfComprehension::Parameter(CYContext &context) const {
- return $ CYFunctionParameter($ CYDeclaration(name_));
+ return $ CYFunctionParameter(declaration_);
}
CYStatement *CYForOfComprehension::Replace(CYContext &context, CYStatement *statement) const {
CYIdentifier *cys($I("$cys"));
- return $E($C0($F(NULL, $P1($L("$cys")), $$->*
+ return $E($C0($F(NULL, $P1($L($I("$cys"))), $$->*
$E($ CYAssign($V(cys), set_))->*
- $ CYForIn($V(name_), $V(cys), $ CYBlock($$->*
- $E($ CYAssign($V(name_), $M($V(cys), $V(name_))))->*
+ $ CYForIn(declaration_->Variable(context), $V(cys), $ CYBlock($$->*
+ $E($ CYAssign(declaration_->Variable(context), $M($V(cys), declaration_->Variable(context))))->*
CYComprehension::Replace(context, statement)
))
)));
}
-void CYFunction::Inject(CYContext &context) {
- context.Replace(name_);
- context.scope_->Declare(context, name_, CYIdentifierOther);
-}
-
-void CYFunction::Replace_(CYContext &context, bool outer) {
- if (outer)
- Inject(context);
-
+void CYFunction::Replace(CYContext &context) {
CYThisScope *_this(context.this_);
- context.this_ = CYGetLast(&this_);
+ context.this_ = &this_;
+ context.this_ = CYGetLast(context.this_);
+
+ CYIdentifier *super(context.super_);
+ context.super_ = super_;
CYNonLocal *nonlocal(context.nonlocal_);
CYNonLocal *nextlocal(context.nextlocal_);
CYScope scope(!localize, context);
- if (!outer && name_ != NULL)
- Inject(context);
-
parameters_->Replace(context, code_);
+
context.ReplaceAll(code_);
- if (CYIdentifier *identifier = this_.identifier_)
- code_ = $$->*
- $ CYVar($L1($ CYDeclaration(identifier, $ CYThis())))->*
- code_;
+ if (implicit_)
+ CYImplicitReturn(code_);
+
+ if (CYIdentifier *identifier = this_.identifier_) {
+ context.scope_->Declare(context, identifier, CYIdentifierVariable);
+ code_ = $$
+ ->*$E($ CYAssign($V(identifier), $ CYThis()))
+ ->*code_
+ ;
+ }
if (localize)
context.NonLocal(code_);
context.nextlocal_ = nextlocal;
context.nonlocal_ = nonlocal;
+ context.super_ = super;
context.this_ = _this;
scope.Close(context, code_);
}
CYExpression *CYFunctionExpression::Replace(CYContext &context) {
- Replace_(context, false);
+ CYScope scope(false, context);
+ if (name_ != NULL)
+ context.scope_->Declare(context, name_, CYIdentifierOther);
+ CYFunction::Replace(context);
+ scope.Close(context, code_);
return this;
}
}
CYStatement *CYFunctionStatement::Replace(CYContext &context) {
- Replace_(context, true);
+ context.scope_->Declare(context, name_, CYIdentifierOther);
+ CYFunction::Replace(context);
return this;
}
return replace_;
}
+CYStatement *CYIf::Return() {
+ CYImplicitReturn(true_);
+ CYImplicitReturn(false_);
+ return this;
+}
+
CYStatement *CYIf::Replace(CYContext &context) {
context.Replace(test_);
context.ReplaceAll(true_);
}
CYStatement *CYImport::Replace(CYContext &context) {
- return $ CYVar($L1($L(module_->part_->Word(), $C1($V("require"), module_->Replace(context, "/")))));
+ return $ CYVar($L1($L($I(module_->part_->Word()), $C1($V("require"), module_->Replace(context, "/")))));
}
CYExpression *CYIndirect::Replace(CYContext &context) {
return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_), parameters_->TypeSignature(context, typed_->Replace(context)));
}
-CYStatement *CYLetStatement::Replace(CYContext &context) {
- return $E($ CYCall(CYNonLocalize(context, $ CYFunctionExpression(NULL, declarations_->Parameter(context), code_)), declarations_->Argument(context)));
+CYStatement *CYLet::Replace(CYContext &context) {
+ declarations_->Replace(context);
+ if (CYExpression *expression = declarations_->Expression(context))
+ return $E(expression);
+ return $ CYEmpty();
+}
+
+CYFunctionExpression *CYMethod::Constructor() {
+ return NULL;
+}
+
+void CYMethod::Replace(CYContext &context) {
+ CYFunction::Replace(context);
}
CYString *CYModule::Replace(CYContext &context, const char *separator) const {
return $S($pool.sprintf(24, "%.17g", Value()));
}
+CYExpression *CYNumber::PropertyName(CYContext &context) {
+ return String(context);
+}
+
CYExpression *CYObject::Replace(CYContext &context) {
- properties_->Replace(context);
+ CYBuilder builder;
+ if (properties_ != NULL)
+ properties_ = properties_->ReplaceAll(context, builder, $ CYThis(), false);
+
+ if (builder) {
+ return $C1($M($ CYFunctionExpression(NULL, builder.declarations_->Parameter(context),
+ builder.statements_->*
+ $ CYReturn($ CYThis())
+ ), $S("call")), this, builder.declarations_->Argument(context));
+ }
+
+ CYForEach (property, properties_)
+ property->Replace(context);
return this;
}
return this;
}
+CYProperty *CYProperty::ReplaceAll(CYContext &context, CYBuilder &builder, CYExpression *self, bool update) {
+ update |= name_->Computed();
+ if (update)
+ Replace(context, builder, self, false);
+ if (next_ != NULL)
+ next_ = next_->ReplaceAll(context, builder, self, update);
+ return update ? next_ : this;
+}
+
+void CYProperty::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, bool protect) {
+ CYExpression *name(name_->PropertyName(context));
+ if (name_->Computed()) {
+ CYIdentifier *unique(context.Unique());
+ builder.declarations_->*$L1($L(unique, name));
+ name = $V(unique);
+ }
+
+ Replace(context, builder, self, name, protect);
+}
+
+void CYPropertyGetter::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name, bool protect) {
+ CYIdentifier *unique(context.Unique());
+ builder.declarations_
+ ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_))));
+ builder.statements_
+ ->* CYDefineProperty(self, name, true, !protect, $ CYPropertyValue($S("get"), $V(unique)));
+}
+
+CYFunctionExpression *CYPropertyMethod::Constructor() {
+ return name_->Constructor() ? $ CYFunctionExpression(NULL, parameters_, code_) : NULL;
+}
+
+void CYPropertyMethod::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name, bool protect) {
+ CYIdentifier *unique(context.Unique());
+ builder.declarations_
+ ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_))));
+ builder.statements_
+ ->* (!protect ? $E($ CYAssign($M(self, name), $V(unique))) :
+ CYDefineProperty(self, name, true, !protect, $ CYPropertyValue($S("value"), $V(unique), $ CYPropertyValue($S("writable"), $ CYTrue()))));
+}
+
+void CYPropertySetter::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name, bool protect) {
+ CYIdentifier *unique(context.Unique());
+ builder.declarations_
+ ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_))));
+ builder.statements_
+ ->* CYDefineProperty(self, name, true, !protect, $ CYPropertyValue($S("set"), $V(unique)));
+}
+
+void CYPropertyValue::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name, bool protect) {
+ _assert(!protect);
+ CYIdentifier *unique(context.Unique());
+ builder.declarations_
+ ->* $L1($L(unique, value_));
+ builder.statements_
+ ->* $E($ CYAssign($M(self, name), $V(unique)));
+}
+
+void CYPropertyValue::Replace(CYContext &context) {
+ context.Replace(value_);
+}
+
// XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
#define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
//#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
typedef std::set<CYIdentifier *, IdentifierUsageLess> IdentifierUsages;
}
-void CYProgram::Replace(CYContext &context) {
+void CYScript::Replace(CYContext &context) {
CYScope scope(true, context);
context.nextlocal_ = $ CYNonLocal();
}
}
-void CYProperty::Replace(CYContext &context) { $T()
- context.Replace(value_);
- next_->Replace(context);
- if (value_ == NULL)
- value_ = $U;
-}
-
CYStatement *CYReturn::Replace(CYContext &context) {
if (context.nonlocal_ != NULL) {
- CYProperty *value(value_ == NULL ? NULL : $ CYProperty($S("$cyv"), value_));
+ CYProperty *value(value_ == NULL ? NULL : $ CYPropertyValue($S("$cyv"), value_));
return $ cy::Syntax::Throw($ CYObject(
- $ CYProperty($S("$cyk"), $V(context.nonlocal_->Target(context)), value)
+ $ CYPropertyValue($S("$cyk"), $V(context.nonlocal_->Target(context)), value)
));
}
}
CYExpression *CYRubyBlock::Replace(CYContext &context) {
- // XXX: this needs to do something much more epic to handle return
return call_->AddArgument(context, proc_->Replace(context));
}
+CYExpression *CYRubyBlock::AddArgument(CYContext &context, CYExpression *value) {
+ return Replace(context)->AddArgument(context, value);
+}
+
CYExpression *CYRubyProc::Replace(CYContext &context) {
- return CYNonLocalize(context, $ CYFunctionExpression(NULL, parameters_, code_));
+ CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters_, code_));
+ function = CYNonLocalize(context, function);
+ function->implicit_ = true;
+ return function;
}
CYScope::CYScope(bool transparent, CYContext &context) :
}
}
+CYElementValue *CYSpan::Replace(CYContext &context) { $T(NULL)
+ return $ CYElementValue(expression_, $ CYElementValue(string_, next_->Replace(context)));
+}
+
+CYStatement *CYStatement::Return() {
+ return this;
+}
+
CYString *CYString::Concat(CYContext &context, CYString *rhs) const {
size_t size(size_ + rhs->size_);
char *value($ char[size + 1]);
return NULL;
}
+CYExpression *CYString::PropertyName(CYContext &context) {
+ return this;
+}
+
CYString *CYString::String(CYContext &context) {
return this;
}
+CYExpression *CYSuperAccess::Replace(CYContext &context) {
+ return $C1($M($M($M($V(context.super_), $S("prototype")), property_), $S("bind")), $ CYThis());
+}
+
+CYExpression *CYSuperCall::Replace(CYContext &context) {
+ return $C($C1($M($V(context.super_), $S("bind")), $ CYThis()), arguments_);
+}
+
CYStatement *CYSwitch::Replace(CYContext &context) {
context.Replace(value_);
clauses_->Replace(context);
return this;
}
+CYExpression *CYTemplate::Replace(CYContext &context) {
+ return $C2($M($M($M($V("String"), $S("prototype")), $S("concat")), $S("apply")), $S(""), $ CYArray($ CYElementValue(string_, spans_->Replace(context))));
+}
+
CYExpression *CYThis::Replace(CYContext &context) {
if (context.this_ != NULL)
return $V(context.this_->Identifier(context));
return this;
}
-CYExpression *CYWord::ClassName(CYContext &context, bool object) {
- CYString *name($S(this));
- if (object)
- return $C1($V("objc_getClass"), name);
- else
- return name;
+CYExpression *CYWord::PropertyName(CYContext &context) {
+ return $S(this);
}