]> git.saurik.com Git - cycript.git/commitdiff
Added some common methods to Type class, implemented new Type(size), removed some...
authorJay Freeman (saurik) <saurik@saurik.com>
Thu, 15 Oct 2009 08:46:33 +0000 (08:46 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Thu, 15 Oct 2009 08:46:33 +0000 (08:46 +0000)
Cycript.y
Library.mm
Output.cpp
Parser.hpp

index a82e7f8cd22e9e8a6ff2726a210c5c41d770bc04..9a3480de4cd6ea2e62587f4cff734174f76081ad 100644 (file)
--- a/Cycript.y
+++ b/Cycript.y
@@ -56,6 +56,7 @@ typedef struct {
         CYBoolean *boolean_;
         CYClause *clause_;
         CYCatch *catch_;
+        CYClassName *className_;
         CYCompound *compound_;
         CYDeclaration *declaration_;
         CYDeclarations *declarations_;
@@ -70,10 +71,10 @@ typedef struct {
         CYLiteral *literal_;
         CYMessage *message_;
         CYMessageParameter *messageParameter_;
-        CYName *name_;
         CYNull *null_;
         CYNumber *number_;
         CYProperty *property_;
+        CYPropertyName *propertyName_;
         CYSelectorPart *selector_;
         CYSource *source_;
         CYStatement *statement_;
@@ -264,6 +265,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <source_> ClassDeclaration
 %type <message_> ClassMessageDeclaration
 %type <message_> ClassMessageDeclarationListOpt
+%type <className_> ClassName
 %type <expression_> ClassSuperOpt
 %type <field_> ClassFieldList
 %type <expression_> ConditionalExpression
@@ -338,7 +340,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <expression_> PrimaryExpression_
 %type <expression_> PrimaryExpressionNoBF
 %type <source_> Program
-%type <name_> PropertyName
+%type <propertyName_> PropertyName
 %type <property_> PropertyNameAndValueList
 %type <property_> PropertyNameAndValueList_
 %type <property_> PropertyNameAndValueListOpt
@@ -1227,8 +1229,14 @@ ClassMessageDeclarationListOpt
     | { $$ = NULL; }
     ;
 
+ClassName
+    : Identifier { $$ = $1; }
+    | "(" AssignmentExpression ")" { $$ = $2; }
+    ;
+
 ClassDeclaration
     : "@class" Identifier ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new CYClass($2, $3, $4, $5); }
+    | "@class" ClassName ClassMessageDeclarationListOpt "@end" { $$ = new CYCategory($2, $3); }
     ;
 
 SourceElement
index c4289e7086a8d937c709cae8f01709384b9ecfc4..d2c03fe24efdf5b6b36ac1e3c5b74f1573b528e3 100644 (file)
@@ -2107,8 +2107,9 @@ static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef obje
         if (count > 1)
             @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to type cast function" userInfo:nil];
         Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+        size_t size(count == 0 ? 0 : CYCastDouble(context, arguments[0]));
         // XXX: alignment?
-        void *value(malloc(internal->GetFFI()->size));
+        void *value(malloc(internal->GetFFI()->size * size));
         return CYMakePointer(context, value, internal->type_, NULL);
     } CYCatch
 }
@@ -2201,8 +2202,8 @@ static JSValueRef Selector_callAsFunction_toJSON(JSContextRef context, JSObjectR
 
 static JSValueRef Selector_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
     CYTry {
-        Selector_privateData *data(reinterpret_cast<Selector_privateData *>(JSObjectGetPrivate(_this)));
-        const char *name(sel_getName(data->GetValue()));
+        Selector_privateData *internal(reinterpret_cast<Selector_privateData *>(JSObjectGetPrivate(_this)));
+        const char *name(sel_getName(internal->GetValue()));
         CYPoolTry {
             return CYCastJSValue(context, CYJSString([NSString stringWithFormat:@"@selector(%s)", name]));
         } CYPoolCatch(NULL)
@@ -2211,14 +2212,13 @@ static JSValueRef Selector_callAsFunction_toCYON(JSContextRef context, JSObjectR
 
 static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
     CYTry {
-        if (count != 2)
+        if (count != 1)
             @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector.type" userInfo:nil];
         CYPool pool;
-        Selector_privateData *data(reinterpret_cast<Selector_privateData *>(JSObjectGetPrivate(_this)));
+        Selector_privateData *internal(reinterpret_cast<Selector_privateData *>(JSObjectGetPrivate(_this)));
         Class _class(CYCastNSObject(pool, context, arguments[0]));
-        bool instance(CYCastBool(context, arguments[1]));
-        SEL sel(data->GetValue());
-        if (Method method = (*(instance ? &class_getInstanceMethod : class_getClassMethod))(_class, sel))
+        SEL sel(internal->GetValue());
+        if (Method method = class_getInstanceMethod(_class, sel))
             return CYCastJSValue(context, method_getTypeEncoding(method));
         else if (NSString *type = [[Bridge_ objectAtIndex:1] objectForKey:CYCastNSString(pool, sel_getName(sel))])
             return CYCastJSValue(context, CYJSString(type));
@@ -2227,6 +2227,32 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef
     } CYCatch
 }
 
+static JSValueRef Type_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    CYTry {
+        Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+        CYPool pool;
+        const char *type(sig::Unparse(pool, internal->type_));
+        CYPoolTry {
+            return CYCastJSValue(context, CYJSString(type));
+        } CYPoolCatch(NULL)
+    } CYCatch
+}
+
+static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    CYTry {
+        Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+        CYPool pool;
+        const char *type(sig::Unparse(pool, internal->type_));
+        CYPoolTry {
+            return CYCastJSValue(context, CYJSString([NSString stringWithFormat:@"new Type(%@)", [[NSString stringWithUTF8String:type] cy$toCYON]]));
+        } CYPoolCatch(NULL)
+    } CYCatch
+}
+
+static JSValueRef Type_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    return Type_callAsFunction_toString(context, object, _this, count, arguments, exception);
+}
+
 static JSStaticValue CYValue_staticValues[2] = {
     {"value", &CYValue_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete},
     {NULL, NULL, NULL, 0}
@@ -2266,6 +2292,13 @@ static JSStaticFunction Selector_staticFunctions[5] = {
     {NULL, NULL, 0}
 };
 
+static JSStaticFunction Type_staticFunctions[5] = {
+    {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"toJSON", &Type_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"toString", &Type_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {NULL, NULL, 0}
+};
+
 CYDriver::CYDriver(const std::string &filename) :
     state_(CYClear),
     data_(NULL),
@@ -2365,10 +2398,7 @@ struct CYExecute_ {
 
 - (void) execute:(NSValue *)value {
     CYExecute_ *execute(reinterpret_cast<CYExecute_ *>([value pointerValue]));
-    NSLog(@"b:%p", execute->data_);
-    NSLog(@"s:%s", execute->data_);
     execute->data_ = CYExecute(execute->pool_, execute->data_);
-    NSLog(@"a:%p", execute->data_);
 }
 
 @end
@@ -2537,6 +2567,7 @@ JSGlobalContextRef CYGetJSContext() {
 
         definition = kJSClassDefinitionEmpty;
         definition.className = "Type";
+        definition.staticFunctions = Type_staticFunctions;
         definition.callAsFunction = &Type_callAsFunction;
         definition.callAsConstructor = &Type_callAsConstructor;
         definition.finalize = &CYData::Finalize;
index e8112c4d9851e0ce1baa04c54c353af47eb94d3c..389948aafa86b36e6f2b6776da670c3c58dfa029 100644 (file)
@@ -107,14 +107,26 @@ void CYCatch::Output(std::ostream &out) const {
     code_->Output(out, true);
 }
 
+void CYCategory::Output(std::ostream &out) const {
+    out << "(function($cys,$cyp,$cyc,$cyn,$cyt){";
+    out << "$cyp=object_getClass($cys);";
+    out << "$cyc=$cys;";
+    if (messages_ != NULL)
+        messages_->Output(out, true);
+    out << "})(";
+    name_->ClassName(out);
+    out << ");";
+}
+
 void CYClass::Output(std::ostream &out) const {
-    out << "(function($cys,$cyc,$cym,$cyn,$cyt){";
+    out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
+    out << "$cyp=object_getClass($cys);";
     out << "$cyc=objc_allocateClassPair($cys,\"" << *name_ << "\",0);";
     out << "$cym=object_getClass($cyc);";
     if (fields_ != NULL)
         fields_->Output(out);
     if (messages_ != NULL)
-        messages_->Output(out);
+        messages_->Output(out, false);
     out << "objc_registerClassPair($cyc);";
     out << "})(";
     if (super_ != NULL)
@@ -124,6 +136,22 @@ void CYClass::Output(std::ostream &out) const {
     out << ");";
 }
 
+void CYCompound::Output(std::ostream &out, CYFlags flags) const {
+    if (CYExpression *expression = expressions_)
+        if (CYExpression *next = expression->next_) {
+            expression->Output(out, CYLeft(flags));
+            CYFlags center(CYCenter(flags));
+            while (next != NULL) {
+                expression = next;
+                out << ',';
+                next = expression->next_;
+                CYFlags right(next != NULL ? center : CYRight(flags));
+                expression->Output(out, right);
+            }
+        } else
+            expression->Output(out, flags);
+}
+
 void CYCondition::Output(std::ostream &out, CYFlags flags) const {
     test_->Output(out, Precedence() - 1, CYLeft(flags));
     out << '?';
@@ -220,27 +248,15 @@ void CYExpress::Output(std::ostream &out) const {
     out << ';';
 }
 
+void CYExpression::ClassName(std::ostream &out) const {
+    Output(out, CYPA, CYNoFlags);
+}
+
 void CYExpression::Part(std::ostream &out) const {
     // XXX: this should handle LeftHandSideExpression
     Output(out, CYNoIn);
 }
 
-void CYCompound::Output(std::ostream &out, CYFlags flags) const {
-    if (CYExpression *expression = expressions_)
-        if (CYExpression *next = expression->next_) {
-            expression->Output(out, CYLeft(flags));
-            CYFlags center(CYCenter(flags));
-            while (next != NULL) {
-                expression = next;
-                out << ',';
-                next = expression->next_;
-                CYFlags right(next != NULL ? center : CYRight(flags));
-                expression->Output(out, right);
-            }
-        } else
-            expression->Output(out, flags);
-}
-
 void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const {
     if (precedence < Precedence()) {
         out << '(';
@@ -355,9 +371,9 @@ void CYMember::Output(std::ostream &out, CYFlags flags) const {
     }
 }
 
-void CYMessage::Output(std::ostream &out) const {
+void CYMessage::Output(std::ostream &out, bool replace) const {
     if (next_ != NULL)
-        next_->Output(out);
+        next_->Output(out, replace);
     out << "$cyn=new Selector(\"";
     for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
         if (parameter->tag_ != NULL) {
@@ -366,8 +382,8 @@ void CYMessage::Output(std::ostream &out) const {
                 out << ':';
         }
     out << "\");";
-    out << "$cyt=$cyn.type($cys," << (instance_ ? "true" : "false") << ");";
-    out << "class_addMethod($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
+    out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");";
+    out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
     out << "new Functor(function(self,_cmd";
     for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
         if (parameter->name_ != NULL)
@@ -406,6 +422,10 @@ void CYNumber::Output(std::ostream &out, CYFlags flags) const {
         out << ' ';
 }
 
+void CYNumber::PropertyName(std::ostream &out) const {
+    Output(out);
+}
+
 void CYObject::Output(std::ostream &out, CYFlags flags) const {
     bool protect((flags & CYNoBrace) != 0);
     if (protect)
@@ -433,7 +453,7 @@ void CYPrefix::Output(std::ostream &out, CYFlags flags) const {
 }
 
 void CYProperty::Output(std::ostream &out) const {
-    out << *name_;
+    name_->PropertyName(out);
     out << ':';
     value_->Output(out, CYPA, CYNoFlags);
     if (next_ != NULL) {
@@ -544,6 +564,13 @@ void CYString::Output(std::ostream &out, CYFlags flags) const {
     out << (single ? '\'' : '"');
 }
 
+void CYString::PropertyName(std::ostream &out) const {
+    if (const char *word = Word())
+        out << word;
+    else
+        Output(out);
+}
+
 void CYSwitch::Output(std::ostream &out) const {
     out << "switch(";
     value_->Output(out, CYNoFlags);
@@ -601,6 +628,14 @@ void CYWith::Output(std::ostream &out) const {
     code_->Output(out, false);
 }
 
+void CYWord::ClassName(std::ostream &out) const {
+    out << "objc_getClass(\"" << Value() << "\")";
+}
+
 void CYWord::Output(std::ostream &out) const {
     out << Value();
 }
+
+void CYWord::PropertyName(std::ostream &out) const {
+    Output(out);
+}
index 1c5c7abd0a6004d666b1fa5cdf6a256cf6e88959..79658c29aa1c655ba4cf800621aa0393bff76121 100644 (file)
@@ -83,14 +83,18 @@ struct CYSource :
     virtual void Output(std::ostream &out, bool block) const;
 };
 
-struct CYName :
-    CYThing
-{
-    virtual const char *Name() const = 0;
+struct CYPropertyName {
+    virtual void PropertyName(std::ostream &out) const = 0;
+};
+
+struct CYClassName {
+    virtual void ClassName(std::ostream &out) const = 0;
 };
 
 struct CYWord :
-    CYName
+    CYThing,
+    CYPropertyName,
+    CYClassName
 {
     const char *word_;
 
@@ -103,11 +107,10 @@ struct CYWord :
         return word_;
     }
 
-    virtual const char *Name() const {
-        return Value();
-    }
-
     virtual void Output(std::ostream &out) const;
+
+    virtual void ClassName(std::ostream &out) const;
+    virtual void PropertyName(std::ostream &out) const;
 };
 
 struct CYIdentifier :
@@ -204,13 +207,16 @@ enum CYFlags {
 struct CYExpression :
     CYNext<CYExpression>,
     CYForInitialiser,
-    CYForInInitialiser
+    CYForInInitialiser,
+    CYClassName
 {
     virtual unsigned Precedence() const = 0;
     virtual void Part(std::ostream &out) const;
     virtual void Output(std::ostream &out, CYFlags flags) const = 0;
     void Output(std::ostream &out, unsigned precedence, CYFlags flags) const;
 
+    virtual void ClassName(std::ostream &out) const;
+
     virtual const char *Word() const {
         return NULL;
     }
@@ -318,7 +324,7 @@ extern CYRange WordEndRange_;
 
 struct CYString :
     CYLiteral,
-    CYName
+    CYPropertyName
 {
     const char *value_;
     size_t size_;
@@ -339,10 +345,6 @@ struct CYString :
         return value_;
     }
 
-    virtual const char *Name() const {
-        return Value();
-    }
-
     virtual const char *Word() const {
         if (size_ == 0 || !WordStartRange_[value_[0]])
             return NULL;
@@ -357,11 +359,12 @@ struct CYString :
     }
 
     virtual void Output(std::ostream &out, CYFlags flags) const;
+    virtual void PropertyName(std::ostream &out) const;
 };
 
 struct CYNumber :
     CYLiteral,
-    CYName
+    CYPropertyName
 {
     double value_;
 
@@ -374,15 +377,12 @@ struct CYNumber :
         return value_;
     }
 
-    virtual const char *Name() const {
-        throw;
-    }
-
     virtual void Output(std::ostream &out) const {
         return Output(out, CYNoFlags);
     }
 
     virtual void Output(std::ostream &out, CYFlags flags) const;
+    virtual void PropertyName(std::ostream &out) const;
 };
 
 struct CYNull :
@@ -645,7 +645,7 @@ struct CYMessageParameter :
 };
 
 struct CYMessage :
-    CYSource
+    CYNext<CYMessage>
 {
     bool instance_;
     CYExpression *type_;
@@ -660,7 +660,7 @@ struct CYMessage :
     {
     }
 
-    virtual void Output(std::ostream &out) const;
+    virtual void Output(std::ostream &out, bool replace) const;
 };
 
 struct CYClass :
@@ -682,6 +682,21 @@ struct CYClass :
     virtual void Output(std::ostream &out) const;
 };
 
+struct CYCategory :
+    CYSource
+{
+    CYClassName *name_;
+    CYMessage *messages_;
+
+    CYCategory(CYClassName *name, CYMessage *messages) :
+        name_(name),
+        messages_(messages)
+    {
+    }
+
+    virtual void Output(std::ostream &out) const;
+};
+
 struct CYFunctionParameter :
     CYNext<CYFunctionParameter>,
     CYThing
@@ -736,10 +751,10 @@ struct CYForIn :
 struct CYProperty :
     CYNext<CYProperty>
 {
-    CYName *name_;
+    CYPropertyName *name_;
     CYExpression *value_;
 
-    CYProperty(CYName *name, CYExpression *value, CYProperty *next) :
+    CYProperty(CYPropertyName *name, CYExpression *value, CYProperty *next) :
         CYNext<CYProperty>(next),
         name_(name),
         value_(value)