From: Jay Freeman (saurik) Date: Sun, 12 Jan 2014 04:59:09 +0000 (-0800) Subject: {Functor,Selector}.type should return @encode(). X-Git-Tag: v0.9.500~71 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/9a39f7051ad983d4377917e66222727dcbe6c099 {Functor,Selector}.type should return @encode(). --- diff --git a/Cycript.yy.in b/Cycript.yy.in index 94d804b..8593f26 100644 --- a/Cycript.yy.in +++ b/Cycript.yy.in @@ -91,7 +91,7 @@ typedef struct { CYMessageParameter *messageParameter_; CYProtocol *protocol_; CYSelectorPart *selector_; - CYTypeModifier *type_; + CYTypeModifier *modifier_; CYTypedIdentifier *typedIdentifier_; CYTypedParameter *typedParameter_; @end @@ -482,16 +482,15 @@ int cylex(YYSTYPE *, cy::location *, void *); %type ClassProtocolListOpt %type ClassProtocols %type ClassProtocolsOpt -%type ConcreteType %type EncodedType +%type FunctionedType %type MessageExpression %type MessageParameter %type MessageParameters %type MessageParameterList %type MessageParameterListOpt %type MessageScope -%type ModifiedType_ -%type ModifiedType +%type ModifiedType %type PrefixedType %type PrimitiveType %type SelectorCall_ @@ -504,8 +503,8 @@ int cylex(YYSTYPE *, cy::location *, void *); %type SuffixedType %type TypeOpt %type TypeParenthetical -%type TypeQualifierLeft -%type TypeQualifierRight +%type TypeQualifierLeft +%type TypeQualifierRight %type TypeSignifier %type TypedIdentifier %type TypedParameterList_ @@ -1370,42 +1369,44 @@ ProgramBodyOpt @begin ObjectiveC /* Cycript (Objective-C): Type Encoding {{{ */ TypeParenthetical - : "(" PrefixedType ")" { $$ = $2; } + : "(" LexPushInOff PrefixedType ")" LexPopIn { $$ = $3; } ; TypeSignifier : Identifier { $$ = CYNew CYTypedIdentifier($1); } - | TypeParenthetical + | TypeParenthetical { $$ = $1; } ; ArrayedType - : ArrayedType "[" NumericLiteral "]" { $$ = $1; CYSetLast($$->type_) = CYNew CYTypeArrayOf($3); } + : ArrayedType "[" NumericLiteral "]" { $$ = $1; $$->modifier_ = CYNew CYTypeArrayOf($3, $$->modifier_); } | TypeSignifier { $$ = $1; } - | { $$ = CYNew CYTypedIdentifier(NULL); } + | { $$ = CYNew CYTypedIdentifier(); } + ; + +FunctionedType + : "(" LexPushInOff TypedParameterListOpt ")" LexPopIn { $$ = CYNew CYTypeFunctionWith($3); } ; SuffixedType : ArrayedType { $$ = $1; } - | TypeParenthetical "(" LexPushInOff TypedParameterListOpt ")" LexPopIn { $$ = $1; CYSetLast($$->type_) = CYNew CYTypeFunctionWith($4); } + | TypeParenthetical FunctionedType { $$ = $1; CYSetLast($2) = $$->modifier_; $$->modifier_ = $2; } + | FunctionedType { $$ = CYNew CYTypedIdentifier(); CYSetLast($1) = $$->modifier_; $$->modifier_ = $1; } ; PrefixedType - : "*" TypeQualifierRight PrefixedType { $$ = $3; CYSetLast($$->type_) = $2; CYSetLast($$->type_) = CYNew CYTypePointerTo(); } - | SuffixedType { $$ = $1; } + : "*" TypeQualifierRight { $$ = $2; $$->modifier_ = CYNew CYTypePointerTo($$->modifier_); } ; TypeQualifierLeft - : "const" TypeQualifierLeft { $$ = CYNew CYTypeConstant(); CYSetLast($$) = $2; } + : "const" TypeQualifierLeft { $$ = $2; CYSetLast($$) = CYNew CYTypeConstant(); } + /* XXX: | "volatile" TypeQualifierLeft { $$ = $2; CYSetLast($$) = CYNew CYTypeVolatile(); } */ | { $$ = NULL; } ; TypeQualifierRight - : TypeQualifierRight "const" { $$ = CYNew CYTypeConstant($1); } - | { $$ = NULL; } - ; - -ConcreteType - : TypeQualifierLeft PrimitiveType TypeQualifierRight { $$ = $3; CYSetLast($$) = $1; CYSetLast($$) = CYNew CYTypeVariable($2); } + : "const" TypeQualifierRight { $$ = $2; $$->modifier_ = CYNew CYTypeConstant($$->modifier_); } + | PrefixedType { $$ = $1; } + | SuffixedType { $$ = $1; } ; PrimitiveType @@ -1414,20 +1415,11 @@ PrimitiveType ; TypedIdentifier - : ConcreteType PrefixedType { $$ = $2; CYSetLast($$->type_) = $1; } + : TypeQualifierLeft PrimitiveType TypeQualifierRight { $$ = $3; $$->type_ = $2; CYSetLast($1) = $$->modifier_; $$->modifier_ = $1; } ; EncodedType - : TypedIdentifier { $$ = CYNew CYEncodedType($1->type_); } - ; - -ModifiedType_ - : TypeQualifierLeft PrimitiveType { $$ = $1; CYSetLast($$) = CYNew CYTypeVariable($2); } - | ModifiedType "*" { $$ = CYNew CYTypePointerTo($1); } - ; - -ModifiedType - : ModifiedType_ TypeQualifierRight { $$ = $2; CYSetLast($$) = $1; } + : TypedIdentifier { $$ = CYNew CYEncodedType($1); } ; PrimaryExpression @@ -1622,6 +1614,11 @@ PrimaryExpression ; /* }}} */ /* Cycript (Objective-C): Block Expressions {{{ */ +ModifiedType + : TypeQualifierLeft PrimitiveType { $$ = CYNew CYTypedIdentifier(); $$->type_ = $2; $$->modifier_ = $1; } + | ModifiedType "*" { $$ = $1; $$->modifier_ = CYNew CYTypePointerTo($$->modifier_); } + ; + PrimaryExpression : "^" ModifiedType "(" LexPushInOff TypedParameterListOpt ")" LexPopIn BRACE LexPushInOff FunctionBody "}" LexPopIn { $$ = CYNew CYObjCBlock($2, $5, $10); } ; @@ -1665,7 +1662,7 @@ TypedParameterListOpt ; PrimaryExpression - : "[" LexPushInOff LexSetRegExp "&" LexSetRegExp "]" LexPopIn "(" LexPushInOff TypedParameterListOpt ")" LexPopIn "->" TypedIdentifier BRACE LexPushInOff FunctionBody "}" LexPopIn { $$ = CYNew CYLambda($14->type_, $10, $17); } + : "[" LexPushInOff LexSetRegExp "&" LexSetRegExp "]" LexPopIn "(" LexPushInOff TypedParameterListOpt ")" LexPopIn "->" TypedIdentifier BRACE LexPushInOff FunctionBody "}" LexPopIn { $$ = CYNew CYLambda($14, $10, $17); } ; /* }}} */ /* Cycript (C): Type Definitions {{{ */ diff --git a/Decode.cpp b/Decode.cpp new file mode 100644 index 0000000..7901515 --- /dev/null +++ b/Decode.cpp @@ -0,0 +1,95 @@ +/* Cycript - Optimizing JavaScript Compiler/Runtime + * Copyright (C) 2009-2013 Jay Freeman (saurik) +*/ + +/* GNU General Public License, Version 3 {{{ */ +/* + * Cycript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Cycript is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cycript. If not, see . +**/ +/* }}} */ + +#include + +#include "Decode.hpp" +#include "Replace.hpp" + +CYTypedIdentifier *Decode_(CYPool &pool, struct sig::Type *type) { + switch (type->primitive) { + case sig::function_P: { + _assert(type->data.signature.count != 0); + CYTypedParameter *parameter(NULL); + for (size_t i(type->data.signature.count - 1); i != 0; --i) + parameter = $ CYTypedParameter(Decode(pool, type->data.signature.elements[i].type), parameter); + return Decode(pool, type->data.signature.elements[0].type)->Modify($ CYTypeFunctionWith(parameter)); + } break; + + case sig::typename_P: return $ CYTypedIdentifier($V("Class")); + case sig::union_P: _assert(false); break; + case sig::string_P: return $ CYTypedIdentifier($V("char"), $ CYTypeConstant($ CYTypePointerTo())); + case sig::selector_P: return $ CYTypedIdentifier($V("SEL")); + case sig::block_P: _assert(false); break; + + case sig::object_P: { + if (type->name == NULL) + return $ CYTypedIdentifier($V("id")); + else + return $ CYTypedIdentifier($V(type->name), $ CYTypePointerTo()); + } break; + + case sig::boolean_P: return $ CYTypedIdentifier($V("bool")); + case sig::uchar_P: return $ CYTypedIdentifier($V("uchar")); + case sig::uint_P: return $ CYTypedIdentifier($V("uint")); + case sig::ulong_P: return $ CYTypedIdentifier($V("ulong")); + case sig::ulonglong_P: return $ CYTypedIdentifier($V("ulonglong")); + case sig::ushort_P: return $ CYTypedIdentifier($V("ushort")); + case sig::array_P: return Decode(pool, type->data.data.type)->Modify($ CYTypeArrayOf($D(type->data.data.size))); + + // XXX: once again, the issue of void here is incorrect + case sig::pointer_P: { + CYTypedIdentifier *typed; + if (type->data.data.type == NULL) + typed = $ CYTypedIdentifier($V("void")); + else + typed = Decode(pool, type->data.data.type); + return typed->Modify($ CYTypePointerTo()); + } break; + + case sig::bit_P: _assert(false); break; + case sig::char_P: return $ CYTypedIdentifier($V("char")); + case sig::double_P: return $ CYTypedIdentifier($V("double")); + case sig::float_P: return $ CYTypedIdentifier($V("float")); + case sig::int_P: return $ CYTypedIdentifier($V("int")); + case sig::long_P: return $ CYTypedIdentifier($V("long")); + case sig::longlong_P: return $ CYTypedIdentifier($V("longlong")); + case sig::short_P: return $ CYTypedIdentifier($V("short")); + + // XXX: this happens to work, but is totally wrong + case sig::void_P: return $ CYTypedIdentifier($V("void")); + + case sig::struct_P: { + _assert(type->name != NULL); + return $ CYTypedIdentifier($V(type->name)); + } break; + } + + _assert(false); + return NULL; +} + +CYTypedIdentifier *Decode(CYPool &pool, struct sig::Type *type) { + CYTypedIdentifier *typed(Decode_(pool, type)); + if ((type->flags & JOC_TYPE_CONST) != 0) + typed = typed->Modify($ CYTypeConstant()); + return typed; +} diff --git a/Decode.hpp b/Decode.hpp new file mode 100644 index 0000000..5aff706 --- /dev/null +++ b/Decode.hpp @@ -0,0 +1,31 @@ +/* Cycript - Optimizing JavaScript Compiler/Runtime + * Copyright (C) 2009-2013 Jay Freeman (saurik) +*/ + +/* GNU General Public License, Version 3 {{{ */ +/* + * Cycript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Cycript is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cycript. If not, see . +**/ +/* }}} */ + +#ifndef DECODE_HPP +#define DECODE_HPP + +#include + +#include "Parser.hpp" + +CYTypedIdentifier *Decode(CYPool &pool, struct sig::Type *type); + +#endif//DECODE_HPP diff --git a/Execute.cpp b/Execute.cpp index 7641df7..4282965 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -46,6 +46,7 @@ #include "Parser.hpp" +#include "Decode.hpp" #include "Error.hpp" #include "JavaScript.hpp" #include "String.hpp" @@ -958,8 +959,8 @@ static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef objec return CYCallFunction(pool, context, 0, NULL, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue()); } CYCatch(NULL) } -JSObjectRef CYMakeType(JSContextRef context, const char *type) { - Type_privateData *internal(new Type_privateData(type)); +JSObjectRef CYMakeType(JSContextRef context, const char *encoding) { + Type_privateData *internal(new Type_privateData(encoding)); return JSObjectMake(context, Type_privateData::Class_, internal); } @@ -968,6 +969,19 @@ JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) { return JSObjectMake(context, Type_privateData::Class_, internal); } +JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature) { + CYPool pool; + + sig::Type type; + type.name = NULL; + type.flags = 0; + + type.primitive = sig::function_P; + sig::Copy(pool, type.data.signature, *signature); + + return CYMakeType(context, &type); +} + static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { JSObjectRef global(CYGetGlobalObject(context)); JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript")))); @@ -1086,6 +1100,38 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef return CYMakeType(context, &type); } CYCatch(NULL) } +static JSValueRef Type_callAsFunction_functionWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + CYPool pool; + + sig::Type type; + type.name = NULL; + type.flags = 0; + + type.primitive = sig::function_P; + type.data.signature.elements = new(pool) sig::Element[1 + count]; + type.data.signature.count = 1 + count; + + type.data.signature.elements[0].name = NULL; + type.data.signature.elements[0].type = internal->type_; + type.data.signature.elements[0].offset = _not(size_t); + + for (size_t i(0); i != count; ++i) { + sig::Element &element(type.data.signature.elements[i + 1]); + element.name = NULL; + element.offset = _not(size_t); + + JSObjectRef object(CYCastJSObject(context, arguments[i])); + _assert(JSValueIsObjectOfClass(context, object, Type_privateData::Class_)); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + + element.type = internal->type_; + } + + return CYMakeType(context, &type); +} CYCatch(NULL) } + static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 0) throw CYJSError(context, "incorrect number of arguments to Type.pointerTo"); @@ -1187,8 +1233,7 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe static JSValueRef Functor_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(object))); - CYPool pool; - return CYCastJSValue(context, Unparse(pool, &internal->signature_)); + return CYMakeType(context, &internal->signature_); } CYCatch(NULL) } static JSValueRef Type_getProperty_alignment(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1215,12 +1260,12 @@ static JSValueRef Type_callAsFunction_toString(JSContextRef context, JSObjectRef 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_)); - std::ostringstream str; - CYStringify(str, type, strlen(type)); - char *cyon(pool.strcat("new Type(", str.str().c_str(), ")", NULL)); - return CYCastJSValue(context, CYJSString(cyon)); + CYLocalPool pool; + std::ostringstream out; + CYOptions options; + CYOutput output(out, options); + (new(pool) CYEncodedType(Decode(pool, internal->type_)))->Output(output, CYNoFlags); + return CYCastJSValue(context, CYJSString(out.str().c_str())); } CYCatch(NULL) } static JSValueRef Type_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { @@ -1262,9 +1307,10 @@ static JSStaticValue Type_staticValues[4] = { {NULL, NULL, NULL, 0} }; -static JSStaticFunction Type_staticFunctions[8] = { +static JSStaticFunction Type_staticFunctions[9] = { {"arrayOf", &Type_callAsFunction_arrayOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"constant", &Type_callAsFunction_constant, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"functionWith", &Type_callAsFunction_functionWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"withName", &Type_callAsFunction_withName, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, diff --git a/JavaScript.hpp b/JavaScript.hpp index 1ede364..70887c4 100644 --- a/JavaScript.hpp +++ b/JavaScript.hpp @@ -125,6 +125,10 @@ extern struct CYHooks *hooks_; JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner); +JSObjectRef CYMakeType(JSContextRef context, const char *encoding); +JSObjectRef CYMakeType(JSContextRef context, sig::Type *type); +JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature); + void CYFinalize(JSObjectRef object); size_t CYArrayLength(JSContextRef context, JSObjectRef array); diff --git a/Makefile.am b/Makefile.am index d92adb5..757ca29 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,7 +43,7 @@ lib_LTLIBRARIES += libcycript.la libcycript_la_LDFLAGS = $(CY_LDFLAGS) libcycript_la_LIBADD = $(LTLIBFFI) $(LTLIBGCC) -ldl -libcycript_la_SOURCES = ConvertUTF.c Driver.cpp Highlight.cpp Library.cpp Network.cpp Output.cpp Parser.cpp Replace.cpp +libcycript_la_SOURCES = ConvertUTF.c Decode.cpp Driver.cpp Highlight.cpp Library.cpp Network.cpp Output.cpp Parser.cpp Replace.cpp libcycript_la_SOURCES += Cycript.tab.cc lex.cy.cpp filters = $(CY_FILTERS) diff --git a/Makefile.in b/Makefile.in index fe3ef22..f9df08b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -184,12 +184,12 @@ am__DEPENDENCIES_1 = libcycript_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ $(am__DEPENDENCIES_3) -am__libcycript_la_SOURCES_DIST = ConvertUTF.c Driver.cpp Highlight.cpp \ - Library.cpp Network.cpp Output.cpp Parser.cpp Replace.cpp \ - Cycript.tab.cc lex.cy.cpp sig/ffi_type.cpp sig/parse.cpp \ - sig/copy.cpp Bridge.cpp Execute.cpp JavaScriptCore.cpp \ - ObjectiveC/Output.cpp ObjectiveC/Replace.cpp \ - ObjectiveC/Library.mm Handler.mm +am__libcycript_la_SOURCES_DIST = ConvertUTF.c Decode.cpp Driver.cpp \ + Highlight.cpp Library.cpp Network.cpp Output.cpp Parser.cpp \ + Replace.cpp Cycript.tab.cc lex.cy.cpp sig/ffi_type.cpp \ + sig/parse.cpp sig/copy.cpp Bridge.cpp Execute.cpp \ + JavaScriptCore.cpp ObjectiveC/Output.cpp \ + ObjectiveC/Replace.cpp ObjectiveC/Library.mm Handler.mm am__dirstamp = $(am__leading_dot)dirstamp @CY_EXECUTE_TRUE@am__objects_1 = sig/ffi_type.lo sig/parse.lo \ @CY_EXECUTE_TRUE@ sig/copy.lo Bridge.lo Execute.lo \ @@ -198,10 +198,10 @@ am__dirstamp = $(am__leading_dot)dirstamp @CY_OBJECTIVEC_TRUE@ ObjectiveC/Replace.lo \ @CY_OBJECTIVEC_TRUE@ ObjectiveC/Library.lo @CY_MACH_TRUE@am__objects_3 = Handler.lo -am_libcycript_la_OBJECTS = ConvertUTF.lo Driver.lo Highlight.lo \ - Library.lo Network.lo Output.lo Parser.lo Replace.lo \ - Cycript.tab.lo lex.cy.lo $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) +am_libcycript_la_OBJECTS = ConvertUTF.lo Decode.lo Driver.lo \ + Highlight.lo Library.lo Network.lo Output.lo Parser.lo \ + Replace.lo Cycript.tab.lo lex.cy.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) libcycript_la_OBJECTS = $(am_libcycript_la_OBJECTS) libcycript_la_LINK = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(OBJCXXLD) $(AM_OBJCXXFLAGS) \ @@ -549,10 +549,10 @@ lib_LTLIBRARIES = $(am__append_1) libcycript.la libcycript_la_LDFLAGS = $(CY_LDFLAGS) libcycript_la_LIBADD = $(LTLIBFFI) $(LTLIBGCC) -ldl $(am__append_3) \ $(am__append_9) -libcycript_la_SOURCES = ConvertUTF.c Driver.cpp Highlight.cpp \ - Library.cpp Network.cpp Output.cpp Parser.cpp Replace.cpp \ - Cycript.tab.cc lex.cy.cpp $(am__append_2) $(am__append_8) \ - $(am__append_10) +libcycript_la_SOURCES = ConvertUTF.c Decode.cpp Driver.cpp \ + Highlight.cpp Library.cpp Network.cpp Output.cpp Parser.cpp \ + Replace.cpp Cycript.tab.cc lex.cy.cpp $(am__append_2) \ + $(am__append_8) $(am__append_10) filters = $(CY_FILTERS) $(am__append_5) $(am__append_7) @CY_CONSOLE_TRUE@cycript_SOURCES = Console.cpp Display.cpp \ @CY_CONSOLE_TRUE@ $(am__append_11) @@ -752,6 +752,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Console.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConvertUTF.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Cycript.tab.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Decode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Display.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Driver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Execute.Plo@am__quote@ diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index 7b0785a..bb62fc4 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -2647,10 +2647,13 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef else method = NULL; - if (const char *type = CYPoolTypeEncoding(pool, context, sel, method)) - return CYCastJSValue(context, CYJSString(type)); + const char *encoding(CYPoolTypeEncoding(pool, context, sel, method)); + if (encoding == NULL) + return CYJSNull(context); - return CYJSNull(context); + sig::Signature signature; + sig::Parse(pool, &signature, encoding, &Structor_); + return CYMakeType(context, &signature); } CYCatch(NULL) } static JSStaticValue Selector_staticValues[2] = { diff --git a/ObjectiveC/Output.cpp b/ObjectiveC/Output.cpp index 658a8f5..fd2a8d8 100644 --- a/ObjectiveC/Output.cpp +++ b/ObjectiveC/Output.cpp @@ -74,12 +74,6 @@ void CYClassStatement::Output(CYOutput &out, CYFlags flags) const { CYClass::Output(out, flags); } -void CYEncodedType::Output(CYOutput &out, CYFlags flags) const { - out << "@encode("; - // XXX: this is seriously wrong - out << ")"; -} - void CYField::Output(CYOutput &out) const { } diff --git a/ObjectiveC/Replace.cpp b/ObjectiveC/Replace.cpp index 7c47eea..e7d687f 100644 --- a/ObjectiveC/Replace.cpp +++ b/ObjectiveC/Replace.cpp @@ -78,10 +78,6 @@ CYStatement *CYClassStatement::Replace(CYContext &context) { return $E(Replace_(context)); } -CYExpression *CYEncodedType::Replace(CYContext &context) { - return type_->Replace(context); -} - CYStatement *CYField::Replace(CYContext &context) const { $T(NULL) CYVariable *cyn($V("$cyn")); CYVariable *cyt($V("$cyt")); @@ -151,7 +147,7 @@ CYExpression *CYBox::Replace(CYContext &context) { } CYExpression *CYObjCBlock::Replace(CYContext &context) { - return $N2($V("Functor"), $ CYFunctionExpression(NULL, $ CYFunctionParameter($ CYDeclaration($ CYIdentifier("$cyt")), parameters_->Parameters(context)), statements_), parameters_->TypeSignature(context, $ CYAdd(type_->Replace(context), $ CYString("@")))); + return $N2($V("Functor"), $ CYFunctionExpression(NULL, $ CYFunctionParameter($ CYDeclaration($ CYIdentifier("$cyt")), parameters_->Parameters(context)), statements_), parameters_->TypeSignature(context, $ CYAdd(typed_->Replace(context), $ CYString("@")))); } CYStatement *CYProtocol::Replace(CYContext &context) const { $T(NULL) diff --git a/ObjectiveC/Syntax.hpp b/ObjectiveC/Syntax.hpp index 343cb37..618a25e 100644 --- a/ObjectiveC/Syntax.hpp +++ b/ObjectiveC/Syntax.hpp @@ -27,12 +27,12 @@ struct CYObjCBlock : CYExpression { - CYTypeModifier *type_; + CYTypedIdentifier *typed_; CYTypedParameter *parameters_; CYStatement *statements_; - CYObjCBlock(CYTypeModifier *type, CYTypedParameter *parameters, CYStatement *statements) : - type_(type), + CYObjCBlock(CYTypedIdentifier *typed, CYTypedParameter *parameters, CYStatement *statements) : + typed_(typed), parameters_(parameters), statements_(statements) { @@ -44,22 +44,6 @@ struct CYObjCBlock : virtual void Output(CYOutput &out, CYFlags flags) const; }; -struct CYEncodedType : - CYExpression -{ - CYTypeModifier *type_; - - CYEncodedType(CYTypeModifier *type) : - type_(type) - { - } - - CYPrecedence(1) - - virtual CYExpression *Replace(CYContext &context); - virtual void Output(CYOutput &out, CYFlags flags) const; -}; - struct CYBox : CYExpression { diff --git a/Output.cpp b/Output.cpp index 3bf157f..17f7bde 100644 --- a/Output.cpp +++ b/Output.cpp @@ -329,7 +329,7 @@ void CYExpression::Output(CYOutput &out) const { Output(out, CYNoFlags); } -void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const { +void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const { if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand()) out << '(' << *this << ')'; else @@ -474,9 +474,61 @@ void CYLabel::Output(CYOutput &out, CYFlags flags) const { statement_->Single(out, CYRight(flags)); } +void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const { + next_->Output(out, Precedence(), identifier); + out << '['; + out << size_; + out << ']'; +} + +void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const { + out << "const"; + next_->Output(out, Precedence(), identifier); +} + +void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const { + next_->Output(out, Precedence(), identifier); + out << '(' << parameters_ << ')'; +} + +void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const { + out << '*'; + next_->Output(out, Precedence(), identifier); +} + +void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const { + out << "volatile"; + next_->Output(out, Precedence(), identifier); +} + +void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const { + if (this == NULL) { + out << identifier; + return; + } + + bool protect(precedence > Precedence()); + + if (protect) + out << '('; + Output(out, identifier); + if (protect) + out << ')'; +} + void CYTypedIdentifier::Output(CYOutput &out) const { - // XXX: this is clearly wrong - out << "XXX"; + type_->Output(out, 0, CYNoFlags); + modifier_->Output(out, 0, identifier_); +} + +void CYEncodedType::Output(CYOutput &out, CYFlags flags) const { + out << "@encode(" << typed_ << ")"; +} + +void CYTypedParameter::Output(CYOutput &out) const { + out << typed_; + if (next_ != NULL) + out << ',' << ' ' << next_; } void CYLambda::Output(CYOutput &out, CYFlags flags) const { diff --git a/Parser.hpp b/Parser.hpp index be97c0b..e68cf1a 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -512,7 +512,7 @@ struct CYExpression : CYClassName, CYThing { - virtual unsigned Precedence() const = 0; + virtual int Precedence() const = 0; virtual bool RightHand() const { return true; @@ -525,7 +525,7 @@ struct CYExpression : virtual void Output(CYOutput &out) const; virtual void Output(CYOutput &out, CYFlags flags) const = 0; - void Output(CYOutput &out, unsigned precedence, CYFlags flags) const; + void Output(CYOutput &out, int precedence, CYFlags flags) const; virtual CYExpression *ClassName(CYContext &context, bool object); virtual void ClassName(CYOutput &out, bool object) const; @@ -556,8 +556,8 @@ struct CYExpression : } #define CYPrecedence(value) \ - static const unsigned Precedence_ = value; \ - virtual unsigned Precedence() const { \ + static const int Precedence_ = value; \ + virtual int Precedence() const { \ return Precedence_; \ } @@ -1329,7 +1329,7 @@ struct New : { } - virtual unsigned Precedence() const { + virtual int Precedence() const { return arguments_ == NULL ? 2 : 1; } @@ -1608,7 +1608,13 @@ struct CYTypeModifier : { } - virtual CYExpression *Replace(CYContext &context) = 0; + virtual int Precedence() const = 0; + + virtual CYExpression *Replace_(CYContext &context, CYExpression *type) = 0; + CYExpression *Replace(CYContext &context, CYExpression *type); + + virtual void Output(CYOutput &out, CYIdentifier *identifier) const = 0; + void Output(CYOutput &out, int precedence, CYIdentifier *identifier) const; }; struct CYTypeArrayOf : @@ -1622,9 +1628,10 @@ struct CYTypeArrayOf : { } - CYPrecedence(2) + CYPrecedence(1) - virtual CYExpression *Replace(CYContext &context); + virtual CYExpression *Replace_(CYContext &context, CYExpression *type); + virtual void Output(CYOutput &out, CYIdentifier *identifier) const; }; struct CYTypeConstant : @@ -1635,9 +1642,10 @@ struct CYTypeConstant : { } - CYPrecedence(3) + CYPrecedence(0) - virtual CYExpression *Replace(CYContext &context); + virtual CYExpression *Replace_(CYContext &context, CYExpression *type); + virtual void Output(CYOutput &out, CYIdentifier *identifier) const; }; struct CYTypePointerTo : @@ -1648,25 +1656,24 @@ struct CYTypePointerTo : { } - CYPrecedence(3) + CYPrecedence(0) - virtual CYExpression *Replace(CYContext &context); + virtual CYExpression *Replace_(CYContext &context, CYExpression *type); + virtual void Output(CYOutput &out, CYIdentifier *identifier) const; }; -struct CYTypeVariable : +struct CYTypeVolatile : CYTypeModifier { - CYExpression *expression_; - - CYTypeVariable(CYExpression *expression) : - CYTypeModifier(NULL), - expression_(expression) + CYTypeVolatile(CYTypeModifier *next = NULL) : + CYTypeModifier(next) { } - CYPrecedence(1) + CYPrecedence(0) - virtual CYExpression *Replace(CYContext &context); + virtual CYExpression *Replace_(CYContext &context, CYExpression *type); + virtual void Output(CYOutput &out, CYIdentifier *identifier) const; }; struct CYTypedIdentifier : @@ -1674,19 +1681,51 @@ struct CYTypedIdentifier : CYThing { CYIdentifier *identifier_; - CYTypeModifier *type_; + CYExpression *type_; + CYTypeModifier *modifier_; - CYTypedIdentifier(CYIdentifier *identifier) : + CYTypedIdentifier(CYIdentifier *identifier = NULL) : identifier_(identifier), - type_(NULL) + type_(NULL), + modifier_(NULL) { } + CYTypedIdentifier(CYExpression *type, CYTypeModifier *modifier = NULL) : + identifier_(NULL), + type_(type), + modifier_(modifier) + { + } + + inline CYTypedIdentifier *Modify(CYTypeModifier *modifier) { + CYSetLast(modifier_) = modifier; + return this; + } + + virtual CYExpression *Replace(CYContext &context); virtual void Output(CYOutput &out) const; }; +struct CYEncodedType : + CYExpression +{ + CYTypedIdentifier *typed_; + + CYEncodedType(CYTypedIdentifier *typed) : + typed_(typed) + { + } + + CYPrecedence(1) + + virtual CYExpression *Replace(CYContext &context); + virtual void Output(CYOutput &out, CYFlags flags) const; +}; + struct CYTypedParameter : - CYNext + CYNext, + CYThing { CYTypedIdentifier *typed_; @@ -1699,17 +1738,19 @@ struct CYTypedParameter : CYArgument *Argument(CYContext &context); CYFunctionParameter *Parameters(CYContext &context); CYExpression *TypeSignature(CYContext &context, CYExpression *prefix); + + virtual void Output(CYOutput &out) const; }; struct CYLambda : CYExpression { - CYTypeModifier *type_; + CYTypedIdentifier *typed_; CYTypedParameter *parameters_; CYStatement *statements_; - CYLambda(CYTypeModifier *type, CYTypedParameter *parameters, CYStatement *statements) : - type_(type), + CYLambda(CYTypedIdentifier *typed, CYTypedParameter *parameters, CYStatement *statements) : + typed_(typed), parameters_(parameters), statements_(statements) { @@ -1746,9 +1787,10 @@ struct CYTypeFunctionWith : { } - CYPrecedence(2) + CYPrecedence(1) - virtual CYExpression *Replace(CYContext &context); + virtual CYExpression *Replace_(CYContext &context, CYExpression *type); + virtual void Output(CYOutput &out, CYIdentifier *identifier) const; }; namespace cy { diff --git a/Replace.cpp b/Replace.cpp index f1283de..3f02fa0 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -289,6 +289,10 @@ CYStatement *CYEmpty::Replace(CYContext &context) { return NULL; } +CYExpression *CYEncodedType::Replace(CYContext &context) { + return typed_->Replace(context); +} + CYStatement *CYExpress::Replace(CYContext &context) { while (CYExpress *express = dynamic_cast(next_)) { CYCompound *compound(dynamic_cast(express->expression_)); @@ -522,7 +526,7 @@ CYStatement *CYLabel::Replace(CYContext &context) { } CYExpression *CYLambda::Replace(CYContext &context) { - return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), statements_), parameters_->TypeSignature(context, type_->Replace(context))); + return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), statements_), parameters_->TypeSignature(context, typed_->Replace(context))); } CYStatement *CYLetStatement::Replace(CYContext &context) { @@ -865,32 +869,40 @@ CYStatement *Try::Replace(CYContext &context) { } } -CYExpression *CYTypeArrayOf::Replace(CYContext &context) { - return $ CYCall($ CYDirectMember(next_->Replace(context), $ CYString("arrayOf")), $ CYArgument(size_)); +CYExpression *CYTypeArrayOf::Replace_(CYContext &context, CYExpression *type) { + return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("arrayOf")), $ CYArgument(size_))); } -CYExpression *CYTypeConstant::Replace(CYContext &context) { - return $ CYCall($ CYDirectMember(next_->Replace(context), $ CYString("constant"))); +CYExpression *CYTypeConstant::Replace_(CYContext &context, CYExpression *type) { + return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("constant")))); } CYStatement *CYTypeDefinition::Replace(CYContext &context) { return $E($ CYAssign($V(typed_->identifier_), typed_->type_->Replace(context))); } -CYExpression *CYTypeFunctionWith::Replace(CYContext &context) { - return $ CYCall($ CYDirectMember(next_->Replace(context), $ CYString("functionWith")), parameters_->Argument(context)); +CYExpression *CYTypeModifier::Replace(CYContext &context, CYExpression *type) { $T(type) + return Replace_(context, type); +} + +CYExpression *CYTypeFunctionWith::Replace_(CYContext &context, CYExpression *type) { + return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), parameters_->Argument(context))); +} + +CYExpression *CYTypePointerTo::Replace_(CYContext &context, CYExpression *type) { + return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("pointerTo")))); } -CYExpression *CYTypePointerTo::Replace(CYContext &context) { - return $ CYCall($ CYDirectMember(next_->Replace(context), $ CYString("pointerTo"))); +CYExpression *CYTypeVolatile::Replace_(CYContext &context, CYExpression *type) { + return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("volatile")))); } -CYExpression *CYTypeVariable::Replace(CYContext &context) { - return expression_; +CYExpression *CYTypedIdentifier::Replace(CYContext &context) { + return modifier_->Replace(context, type_); } CYArgument *CYTypedParameter::Argument(CYContext &context) { $T(NULL) - return $ CYArgument(typed_->type_->Replace(context), next_->Argument(context)); + return $ CYArgument(typed_->Replace(context), next_->Argument(context)); } CYFunctionParameter *CYTypedParameter::Parameters(CYContext &context) { $T(NULL) diff --git a/sig/copy.cpp b/sig/copy.cpp index b38405e..b85640c 100644 --- a/sig/copy.cpp +++ b/sig/copy.cpp @@ -58,7 +58,7 @@ void Copy(CYPool &pool, Type &lhs, Type &rhs) { lhs.name = pool.strdup(rhs.name); lhs.flags = rhs.flags; - if (sig::IsAggregate(rhs.primitive)) + if (rhs.primitive == '\0' || sig::IsAggregate(rhs.primitive)) Copy(pool, lhs.data.signature, rhs.data.signature); else { sig::Type *&lht(lhs.data.data.type); diff --git a/sig/parse.cpp b/sig/parse.cpp index 436e3cd..da590a8 100644 --- a/sig/parse.cpp +++ b/sig/parse.cpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace sig { @@ -247,6 +248,19 @@ const char *Unparse(CYPool &pool, struct Signature *signature) { const char *Unparse_(CYPool &pool, struct Type *type) { switch (type->primitive) { + case function_P: { + if (type->data.signature.count == 0) + return "?"; + std::ostringstream out; + for (size_t i(0); i != type->data.signature.count; ++i) { + Element &element(type->data.signature.elements[i]); + out << Unparse(pool, element.type); + if (element.offset != _not(size_t)) + out << pool.itoa(element.offset); + } + return pool.strdup(out.str().c_str()); + } break; + case typename_P: return "#"; case union_P: return pool.strcat("(", Unparse(pool, &type->data.signature), ")", NULL); case string_P: return "*"; @@ -265,7 +279,15 @@ const char *Unparse_(CYPool &pool, struct Type *type) { return pool.strcat("[", pool.itoa(type->data.data.size), value, "]", NULL); } break; - case pointer_P: return pool.strcat("^", type->data.data.type == NULL ? "v" : Unparse(pool, type->data.data.type), NULL); + case pointer_P: { + if (type->data.data.type == NULL) + return "^v"; + else if (type->data.data.type->primitive == function_P) + return "^?"; + else + return pool.strcat("^", Unparse(pool, type->data.data.type), NULL); + } break; + case bit_P: return pool.strcat("b", pool.itoa(type->data.data.size), NULL); case char_P: return "c"; case double_P: return "d"; diff --git a/sig/types.hpp b/sig/types.hpp index d2367af..e66e0c3 100644 --- a/sig/types.hpp +++ b/sig/types.hpp @@ -30,6 +30,7 @@ namespace sig { enum Primitive { + function_P = '\0', typename_P = '#', union_P = '(', string_P = '*',