]> git.saurik.com Git - cycript.git/blobdiff - Replace.cpp
Remove flex/gperf hacks (this was fixed upstream).
[cycript.git] / Replace.cpp
index b3d1c828e972983caf9eceb549956a1008150d01..7b99022fd957473ffe52b8de2608284000483b5f 100644 (file)
@@ -1,5 +1,5 @@
 /* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2014  Jay Freeman (saurik)
+ * Copyright (C) 2009-2015  Jay Freeman (saurik)
 */
 
 /* GNU Affero General Public License, Version 3 {{{ */
@@ -29,6 +29,11 @@ CYFunctionExpression *CYNonLocalize(CYContext &context, CYFunctionExpression *fu
     return function;
 }
 
+static void CYImplicitReturn(CYStatement *&code) {
+    if (CYStatement *&last = CYGetLast(code))
+        last = last->Return();
+}
+
 CYExpression *CYAdd::Replace(CYContext &context) {
     CYInfix::Replace(context);
 
@@ -95,9 +100,14 @@ CYExpression *CYAssignment::Replace(CYContext &context) {
     return this;
 }
 
+CYStatement *CYBlock::Return() {
+    CYImplicitReturn(code_);
+    return this;
+}
+
 CYStatement *CYBlock::Replace(CYContext &context) {
-    context.ReplaceAll(statements_);
-    if (statements_ == NULL)
+    context.ReplaceAll(code_);
+    if (code_ == NULL)
         return $ CYEmpty();
     return this;
 }
@@ -124,20 +134,20 @@ namespace cy {
 namespace Syntax {
 
 void Catch::Replace(CYContext &context) { $T()
-    CYScope scope(true, context, code_.statements_);
+    CYScope scope(true, context);
 
     context.Replace(name_);
     context.scope_->Declare(context, name_, CYIdentifierCatch);
 
-    code_.Replace(context);
-    scope.Close();
+    context.ReplaceAll(code_);
+    scope.Close(context, code_);
 }
 
 } }
 
 void CYClause::Replace(CYContext &context) { $T()
     context.Replace(case_);
-    context.ReplaceAll(statements_);
+    context.ReplaceAll(code_);
     next_->Replace(context);
 }
 
@@ -146,9 +156,6 @@ CYStatement *CYComment::Replace(CYContext &context) {
 }
 
 CYExpression *CYCompound::Replace(CYContext &context) {
-    if (next_ == NULL)
-        return expression_;
-
     context.Replace(expression_);
     context.Replace(next_);
 
@@ -162,11 +169,17 @@ CYExpression *CYCompound::Replace(CYContext &context) {
     return this;
 }
 
-CYExpression *CYCompound::Primitive(CYContext &context) {
-    CYExpression *expression(expression_);
-    if (expression == NULL || next_ != NULL)
+CYFunctionParameter *CYCompound::Parameter() const {
+    CYFunctionParameter *next(next_->Parameter());
+    if (next == NULL)
         return NULL;
-    return expression->Primitive(context);
+
+    CYFunctionParameter *parameter(expression_->Parameter());
+    if (parameter == NULL)
+        return NULL;
+
+    parameter->SetNext(next);
+    return parameter;
 }
 
 CYFunctionParameter *CYComprehension::Parameters(CYContext &context) const { $T(NULL)
@@ -205,6 +218,7 @@ void CYContext::NonLocal(CYStatement *&statements) {
                     $ CYReturn($M($V(cye), $S("$cyv"))))->*
                 $ cy::Syntax::Throw($V(cye))));
 
+        // XXX: I don't understand any of this
         context.Replace(declare);
         rescue->Replace(context);
 
@@ -266,10 +280,13 @@ CYArgument *CYDeclarations::Argument(CYContext &context) { $T(NULL)
     return $ CYArgument(declaration_->initialiser_, next_->Argument(context));
 }
 
-CYCompound *CYDeclarations::Compound(CYContext &context) { $T(NULL)
-    CYCompound *compound(next_->Compound(context));
+CYExpression *CYDeclarations::Expression(CYContext &context) { $T(NULL)
+    CYExpression *compound(next_->Expression(context));
     if (CYAssignment *assignment = declaration_->Assignment(context))
-        compound = $ CYCompound(assignment, compound);
+        if (compound == NULL)
+            compound = assignment;
+        else
+            compound = $ CYCompound(assignment, compound);
     return compound;
 }
 
@@ -281,7 +298,7 @@ CYExpression *CYDirectMember::Replace(CYContext &context) {
 
 CYStatement *CYDoWhile::Replace(CYContext &context) {
     context.Replace(test_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }
 
@@ -298,16 +315,12 @@ CYExpression *CYEncodedType::Replace(CYContext &context) {
     return typed_->Replace(context);
 }
 
-CYStatement *CYExpress::Replace(CYContext &context) {
-    while (CYExpress *express = dynamic_cast<CYExpress *>(next_)) {
-        expression_ = $ CYCompound(expression_, express->expression_);
-        SetNext(express->next_);
-    }
+CYStatement *CYExpress::Return() {
+    return $ CYReturn(expression_);
+}
 
+CYStatement *CYExpress::Replace(CYContext &context) {
     context.Replace(expression_);
-    if (expression_ == NULL)
-        return $ CYEmpty();
-
     return this;
 }
 
@@ -327,6 +340,14 @@ CYAssignment *CYExpression::Assignment(CYContext &context) {
     return NULL;
 }
 
+CYFunctionParameter *CYExpression::Parameter() const {
+    return NULL;
+}
+
+CYStatement *CYExternal::Replace(CYContext &context) {
+    return $E($ CYAssign($V(typed_->identifier_), $C1(typed_->Replace(context), $C2($V("dlsym"), $V("RTLD_DEFAULT"), $S(typed_->identifier_->Word())))));
+}
+
 CYNumber *CYFalse::Number(CYContext &context) {
     return $D(0);
 }
@@ -342,20 +363,20 @@ CYExpression *CYFatArrow::Replace(CYContext &context) {
 }
 
 void CYFinally::Replace(CYContext &context) { $T()
-    code_.Replace(context);
+    context.ReplaceAll(code_);
 }
 
 CYStatement *CYFor::Replace(CYContext &context) {
     context.Replace(initialiser_);
     context.Replace(test_);
     context.Replace(increment_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }
 
-CYCompound *CYForDeclarations::Replace(CYContext &context) {
+CYExpression *CYForDeclarations::Replace(CYContext &context) {
     declarations_->Replace(context);
-    return declarations_->Compound(context);
+    return declarations_->Expression(context);
 }
 
 // XXX: this still feels highly suboptimal
@@ -368,7 +389,7 @@ CYStatement *CYForIn::Replace(CYContext &context) {
 
     context.Replace(initialiser_);
     context.Replace(set_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }
 
@@ -402,7 +423,7 @@ CYFunctionParameter *CYForOfComprehension::Parameter(CYContext &context) const {
 }
 
 CYStatement *CYForOfComprehension::Replace(CYContext &context, CYStatement *statement) const {
-    CYIdentifier *cys($I("cys"));
+    CYIdentifier *cys($I("$cys"));
 
     return $E($C0($F(NULL, $P1($L("$cys")), $$->*
         $E($ CYAssign($V(cys), set_))->*
@@ -423,7 +444,8 @@ void CYFunction::Replace_(CYContext &context, bool outer) {
         Inject(context);
 
     CYThisScope *_this(context.this_);
-    context.this_ = CYGetLast(&this_);
+    context.this_ = &this_;
+    context.this_ = CYGetLast(context.this_);
 
     CYNonLocal *nonlocal(context.nonlocal_);
     CYNonLocal *nextlocal(context.nextlocal_);
@@ -438,28 +460,31 @@ void CYFunction::Replace_(CYContext &context, bool outer) {
         context.nextlocal_ = nonlocal_;
     }
 
-    CYScope scope(!localize, context, code_.statements_);
+    CYScope scope(!localize, context);
 
     if (!outer && name_ != NULL)
         Inject(context);
 
     parameters_->Replace(context, code_);
-    code_.Replace(context);
+    context.ReplaceAll(code_);
+
+    if (implicit_)
+        CYImplicitReturn(code_);
 
     if (CYIdentifier *identifier = this_.identifier_)
-        code_.statements_ = $$->*
+        code_ = $$->*
             $ CYVar($L1($ CYDeclaration(identifier, $ CYThis())))->*
-            code_.statements_;
+            code_;
 
     if (localize)
-        context.NonLocal(code_.statements_);
+        context.NonLocal(code_);
 
     context.nextlocal_ = nextlocal;
     context.nonlocal_ = nonlocal;
 
     context.this_ = _this;
 
-    scope.Close();
+    scope.Close(context, code_);
 }
 
 CYExpression *CYFunctionExpression::Replace(CYContext &context) {
@@ -467,17 +492,19 @@ CYExpression *CYFunctionExpression::Replace(CYContext &context) {
     return this;
 }
 
-void CYFunctionParameter::Replace(CYContext &context, CYBlock &code) { $T()
+void CYFunctionParameter::Replace(CYContext &context, CYStatement *&statements) { $T()
     CYAssignment *assignment(initialiser_->Assignment(context));
     context.Replace(initialiser_);
 
-    next_->Replace(context, code);
+    next_->Replace(context, statements);
 
     if (assignment != NULL)
-        // XXX: this cast is quite incorrect
-        code.AddPrev($ CYIf($ CYIdentical($ CYTypeOf(dynamic_cast<CYExpression *>(initialiser_)), $S("undefined")), $$->*
-            $E(assignment)
-        ));
+        statements = $$->*
+            // XXX: this cast is quite incorrect
+            $ CYIf($ CYIdentical($ CYTypeOf(dynamic_cast<CYExpression *>(initialiser_)), $S("undefined")), $$->*
+                $E(assignment)
+            )->*
+            statements;
 }
 
 CYStatement *CYFunctionStatement::Replace(CYContext &context) {
@@ -492,10 +519,16 @@ CYIdentifier *CYIdentifier::Replace(CYContext &context) {
     return replace_;
 }
 
+CYStatement *CYIf::Return() {
+    CYImplicitReturn(true_);
+    CYImplicitReturn(false_);
+    return this;
+}
+
 CYStatement *CYIf::Replace(CYContext &context) {
     context.Replace(test_);
-    context.Replace(true_);
-    context.Replace(false_);
+    context.ReplaceAll(true_);
+    context.ReplaceAll(false_);
     return this;
 }
 
@@ -531,7 +564,7 @@ CYStatement *CYLabel::Replace(CYContext &context) {
 }
 
 CYExpression *CYLambda::Replace(CYContext &context) {
-    return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), statements_), parameters_->TypeSignature(context, typed_->Replace(context)));
+    return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_), parameters_->TypeSignature(context, typed_->Replace(context)));
 }
 
 CYStatement *CYLetStatement::Replace(CYContext &context) {
@@ -592,6 +625,10 @@ CYExpression *CYObject::Replace(CYContext &context) {
     return this;
 }
 
+CYExpression *CYParenthetical::Replace(CYContext &context) {
+    return expression_;
+}
+
 CYExpression *CYPostfix::Replace(CYContext &context) {
     context.Replace(lhs_);
     return this;
@@ -621,13 +658,13 @@ namespace {
 }
 
 void CYProgram::Replace(CYContext &context) {
-    CYScope scope(true, context, statements_);
+    CYScope scope(true, context);
 
     context.nextlocal_ = $ CYNonLocal();
-    context.ReplaceAll(statements_);
-    context.NonLocal(statements_);
+    context.ReplaceAll(code_);
+    context.NonLocal(code_);
 
-    scope.Close();
+    scope.Close(context, code_);
 
     size_t offset(0);
 
@@ -696,29 +733,21 @@ CYStatement *CYReturn::Replace(CYContext &context) {
 }
 
 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 *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, CYStatement *&statements) :
+CYScope::CYScope(bool transparent, CYContext &context) :
     transparent_(transparent),
-    context_(context),
-    statements_(statements),
     parent_(context.scope_)
 {
-    context_.scope_ = this;
-}
-
-CYScope::~CYScope() {
-}
-
-void CYScope::Close() {
-    context_.scope_ = parent_;
-    Scope(context_, statements_);
+    context.scope_ = this;
 }
 
 void CYScope::Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags) {
@@ -776,7 +805,9 @@ namespace {
     typedef std::set<IdentifierOffset, IdentifierOffsetLess> IdentifierOffsets;
 }
 
-void CYScope::Scope(CYContext &context, CYStatement *&statements) {
+void CYScope::Close(CYContext &context, CYStatement *&statements) {
+    context.scope_ = parent_;
+
     if (parent_ == NULL)
         return;
 
@@ -826,6 +857,10 @@ void CYScope::Scope(CYContext &context, CYStatement *&statements) {
         }
 }
 
+CYStatement *CYStatement::Return() {
+    return this;
+}
+
 CYString *CYString::Concat(CYContext &context, CYString *rhs) const {
     size_t size(size_ + rhs->size_);
     char *value($ char[size + 1]);
@@ -882,7 +917,7 @@ namespace cy {
 namespace Syntax {
 
 CYStatement *Try::Replace(CYContext &context) {
-    code_.Replace(context);
+    context.ReplaceAll(code_);
     catch_->Replace(context);
     finally_->Replace(context);
     return this;
@@ -955,6 +990,19 @@ CYExpression *CYTypedIdentifier::Replace(CYContext &context) {
     return modifier_->Replace(context, specifier_->Replace(context));
 }
 
+CYTypeFunctionWith *CYTypedIdentifier::Function() {
+    CYTypeModifier **modifier(&modifier_);
+    if (*modifier == NULL)
+        return NULL;
+    while ((*modifier)->next_ != NULL)
+        modifier = &(*modifier)->next_;
+    CYTypeFunctionWith *function((*modifier)->Function());
+    if (function == NULL)
+        return NULL;
+    *modifier = NULL;
+    return function;
+}
+
 CYArgument *CYTypedParameter::Argument(CYContext &context) { $T(NULL)
     return $ CYArgument(typed_->Replace(context), next_->Argument(context));
 }
@@ -969,8 +1017,8 @@ CYExpression *CYTypedParameter::TypeSignature(CYContext &context, CYExpression *
 
 CYStatement *CYVar::Replace(CYContext &context) {
     declarations_->Replace(context);
-    if (CYCompound *compound = declarations_->Compound(context))
-        return $E(compound);
+    if (CYExpression *expression = declarations_->Expression(context))
+        return $E(expression);
     return $ CYEmpty();
 }
 
@@ -979,15 +1027,19 @@ CYExpression *CYVariable::Replace(CYContext &context) {
     return this;
 }
 
+CYFunctionParameter *CYVariable::Parameter() const {
+    return $ CYFunctionParameter($ CYDeclaration(name_));
+}
+
 CYStatement *CYWhile::Replace(CYContext &context) {
     context.Replace(test_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }
 
 CYStatement *CYWith::Replace(CYContext &context) {
     context.Replace(scope_);
-    context.Replace(code_);
+    context.ReplaceAll(code_);
     return this;
 }