From e5bc40dbf98979310a3c9fd5d552c710b24d6762 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 15 Oct 2009 08:46:33 +0000 Subject: [PATCH] Added some common methods to Type class, implemented new Type(size), removed some debugging code from the server, simplified Selector.type to one class argument, and refactored property names for the new class name serialization. --- Cycript.y | 12 ++++++-- Library.mm | 53 +++++++++++++++++++++++++++-------- Output.cpp | 81 ++++++++++++++++++++++++++++++++++++++---------------- Parser.hpp | 63 ++++++++++++++++++++++++++---------------- 4 files changed, 149 insertions(+), 60 deletions(-) diff --git a/Cycript.y b/Cycript.y index a82e7f8..9a3480d 100644 --- 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 ClassDeclaration %type ClassMessageDeclaration %type ClassMessageDeclarationListOpt +%type ClassName %type ClassSuperOpt %type ClassFieldList %type ConditionalExpression @@ -338,7 +340,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type PrimaryExpression_ %type PrimaryExpressionNoBF %type Program -%type PropertyName +%type PropertyName %type PropertyNameAndValueList %type PropertyNameAndValueList_ %type 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 diff --git a/Library.mm b/Library.mm index c4289e7..d2c03fe 100644 --- a/Library.mm +++ b/Library.mm @@ -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(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(JSObjectGetPrivate(_this))); - const char *name(sel_getName(data->GetValue())); + Selector_privateData *internal(reinterpret_cast(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(JSObjectGetPrivate(_this))); + Selector_privateData *internal(reinterpret_cast(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(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(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([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; diff --git a/Output.cpp b/Output.cpp index e8112c4..389948a 100644 --- a/Output.cpp +++ b/Output.cpp @@ -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); +} diff --git a/Parser.hpp b/Parser.hpp index 1c5c7ab..79658c2 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -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, 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 { 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, CYThing @@ -736,10 +751,10 @@ struct CYForIn : struct CYProperty : CYNext { - CYName *name_; + CYPropertyName *name_; CYExpression *value_; - CYProperty(CYName *name, CYExpression *value, CYProperty *next) : + CYProperty(CYPropertyName *name, CYExpression *value, CYProperty *next) : CYNext(next), name_(name), value_(value) -- 2.45.2