From 534fb6da44730df33f71e88b7a14253eb8212eb7 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Mon, 19 Oct 2009 22:08:37 +0000 Subject: [PATCH] Support array ffi_type through some shady argumentaton, implement Type[] syntax for arrays, setup bridging for common C types, reorganized keywords based on actual reservation, removed let(){} and associated GLR, and added static in numerous places I wanted it. --- Bridge.def | 14 +++++ Cycript.l | 67 ++++++++++++----------- Cycript.y | 136 +++++++++++++++++++++++++++-------------------- Library.mm | 133 +++++++++++++++++++++++++++++++-------------- sig/ffi_type.cpp | 23 ++++++-- 5 files changed, 241 insertions(+), 132 deletions(-) diff --git a/Bridge.def b/Bridge.def index 2994bd1..7ce9cda 100644 --- a/Bridge.def +++ b/Bridge.def @@ -4,6 +4,20 @@ C nil null : applicationDidFinishLaunching: v12@0:4@8 +T id @ + +T short s +T int i +T long l + +T uint I +T ulong L +T ushort S + +T char c +T boolean B +T float f +T double d S CGPoint "x"f"y"f S CGRect "origin"{CGPoint}"size"{CGSize} diff --git a/Cycript.l b/Cycript.l index 063e900..20a4ede 100644 --- a/Cycript.l +++ b/Cycript.l @@ -126,6 +126,10 @@ Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n "@end" L C return tk::AtEnd; "@selector" L C return tk::AtSelector; +"false" L C yylval->false_ = new CYFalse(); return tk::False; +"null" L C yylval->null_ = new CYNull(); return tk::Null; +"true" L C yylval->true_ = new CYTrue(); return tk::True; + "break" L R yylval->word_ = new CYWord("break"); return tk::Break; "case" L C yylval->word_ = new CYWord("case"); return tk::Case; "catch" L C yylval->word_ = new CYWord("catch"); return tk::Catch; @@ -134,7 +138,6 @@ Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n "delete" L C yylval->word_ = new CYWord("delete"); return tk::Delete; "do" L C yylval->word_ = new CYWord("do"); return tk::Do; "else" L C yylval->word_ = new CYWord("else"); return tk::Else; -"false" L C yylval->false_ = new CYFalse(); return tk::False; "finally" L C yylval->word_ = new CYWord("finally"); return tk::Finally; "for" L C yylval->word_ = new CYWord("for"); return tk::For; "function" L C yylval->word_ = new CYWord("function"); return tk::Function; @@ -142,12 +145,10 @@ Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n "in" L C yylval->word_ = new CYWord("in"); return tk::In; "instanceof" L C yylval->word_ = new CYWord("instanceof"); return tk::InstanceOf; "new" L C yylval->word_ = new CYWord("new"); return tk::New; -"null" L C yylval->null_ = new CYNull(); return tk::Null; "return" L R yylval->word_ = new CYWord("return"); return tk::Return; "switch" L C yylval->word_ = new CYWord("switch"); return tk::Switch; "this" L C yylval->this_ = new CYThis(); return tk::This; "throw" L R yylval->word_ = new CYWord("throw"); return tk::Throw; -"true" L C yylval->true_ = new CYTrue(); return tk::True; "try" L C yylval->word_ = new CYWord("try"); return tk::Try; "typeof" L C yylval->word_ = new CYWord("typeof"); return tk::TypeOf; "var" L C yylval->word_ = new CYWord("var"); return tk::Var; @@ -155,40 +156,46 @@ Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n "while" L C yylval->word_ = new CYWord("while"); return tk::While; "with" L C yylval->word_ = new CYWord("with"); return tk::With; -"abstract" L C yylval->word_ = new CYWord("abstract"); return tk::Abstract; -"boolean" L C yylval->word_ = new CYWord("boolean"); return tk::Boolean; -"byte" L C yylval->word_ = new CYWord("byte"); return tk::Byte; -"char" L C yylval->word_ = new CYWord("char"); return tk::Char; -"class" L C yylval->word_ = new CYWord("class"); return tk::Class; -"const" L C yylval->word_ = new CYWord("const"); return tk::Const; "debugger" L C yylval->word_ = new CYWord("debugger"); return tk::Debugger; -"double" L C yylval->word_ = new CYWord("double"); return tk::Double; + +"const" L C yylval->word_ = new CYWord("const"); return tk::Const; + +"class" L C yylval->word_ = new CYWord("class"); return tk::Class; "enum" L C yylval->word_ = new CYWord("enum"); return tk::Enum; "export" L C yylval->word_ = new CYWord("export"); return tk::Export; "extends" L C yylval->word_ = new CYWord("extends"); return tk::Extends; -"final" L C yylval->word_ = new CYWord("final"); return tk::Final; -"float" L C yylval->word_ = new CYWord("float"); return tk::Float; -"goto" L C yylval->word_ = new CYWord("goto"); return tk::Goto; -"implements" L C yylval->word_ = new CYWord("implements"); return tk::Implements; "import" L C yylval->word_ = new CYWord("import"); return tk::Import; -"int" L C yylval->word_ = new CYWord("int"); return tk::Int; -"interface" L C yylval->word_ = new CYWord("interface"); return tk::Interface; -"long" L C yylval->word_ = new CYWord("long"); return tk::Long; -"native" L C yylval->word_ = new CYWord("native"); return tk::Native; -"package" L C yylval->word_ = new CYWord("package"); return tk::Package; -"private" L C yylval->word_ = new CYWord("private"); return tk::Private; -"protected" L C yylval->word_ = new CYWord("protected"); return tk::Protected; -"public" L C yylval->word_ = new CYWord("public"); return tk::Public; -"short" L C yylval->word_ = new CYWord("short"); return tk::Short; -"static" L C yylval->word_ = new CYWord("static"); return tk::Static; "super" L C yylval->word_ = new CYWord("super"); return tk::Super; -"synchronized" L C yylval->word_ = new CYWord("synchronized"); return tk::Synchronized; -"throws" L C yylval->word_ = new CYWord("throws"); return tk::Throws; -"transient" L C yylval->word_ = new CYWord("transient"); return tk::Transient; -"volatile" L C yylval->word_ = new CYWord("volatile"); return tk::Volatile; -"each" L C yylval->word_ = new CYIdentifier("each"); return tk::Each; -"let" L C yylval->word_ = new CYIdentifier("let"); return tk::Let; +"implements" L C yylval->identifier_ = new CYIdentifier("implements"); return tk::Implements; +"interface" L C yylval->identifier_ = new CYIdentifier("interface"); return tk::Interface; +"package" L C yylval->identifier_ = new CYIdentifier("package"); return tk::Package; +"private" L C yylval->identifier_ = new CYIdentifier("private"); return tk::Private; +"protected" L C yylval->identifier_ = new CYIdentifier("protected"); return tk::Protected; +"public" L C yylval->identifier_ = new CYIdentifier("public"); return tk::Public; +"static" L C yylval->identifier_ = new CYIdentifier("static"); return tk::Static; + +"abstract" L C yylval->identifier_ = new CYIdentifier("abstract"); return tk::Abstract; +"boolean" L C yylval->identifier_ = new CYIdentifier("boolean"); return tk::Boolean; +"byte" L C yylval->identifier_ = new CYIdentifier("byte"); return tk::Byte; +"char" L C yylval->identifier_ = new CYIdentifier("char"); return tk::Char; +"double" L C yylval->identifier_ = new CYIdentifier("double"); return tk::Double; +"final" L C yylval->identifier_ = new CYIdentifier("final"); return tk::Final; +"float" L C yylval->identifier_ = new CYIdentifier("float"); return tk::Float; +"goto" L C yylval->identifier_ = new CYIdentifier("goto"); return tk::Goto; +"int" L C yylval->identifier_ = new CYIdentifier("int"); return tk::Int; +"long" L C yylval->identifier_ = new CYIdentifier("long"); return tk::Long; +"native" L C yylval->identifier_ = new CYIdentifier("native"); return tk::Native; +"short" L C yylval->identifier_ = new CYIdentifier("short"); return tk::Short; +"synchronized" L C yylval->identifier_ = new CYIdentifier("synchronized"); return tk::Synchronized; +"throws" L C yylval->identifier_ = new CYIdentifier("throws"); return tk::Throws; +"transient" L C yylval->identifier_ = new CYIdentifier("transient"); return tk::Transient; +"volatile" L C yylval->identifier_ = new CYIdentifier("volatile"); return tk::Volatile; + +"let" L C yylval->identifier_ = new CYIdentifier("let"); return tk::Let; +"yield" L C yylval->identifier_ = new CYIdentifier("yield"); return tk::Yield; + +"each" L C yylval->identifier_ = new CYIdentifier("each"); return tk::Each; [a-zA-Z$_][a-zA-Z$_0-9]* yylval->identifier_ = new CYIdentifier(apr_pstrmemdup(yyextra->pool_, yytext, yyleng)); L C return tk::Identifier_; diff --git a/Cycript.y b/Cycript.y index 6a304b3..f1cbcfe 100644 --- a/Cycript.y +++ b/Cycript.y @@ -107,8 +107,8 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %defines -%glr-parser -%expect 1 +//%glr-parser +//%expect 1 %debug @@ -178,6 +178,11 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %token AtSelector "@selector" %token AtEnd "@end" +%token False "false" +%token Null "null" +%token True "true" + +// ES3/ES5/WIE/JSC Reserved %token Break "break" %token Case "case" %token Catch "catch" @@ -186,7 +191,6 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %token Delete "delete" %token Do "do" %token Else "else" -%token False "false" %token Finally "finally" %token For "for" %token Function "function" @@ -194,12 +198,10 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %token In "in" %token InstanceOf "instanceof" %token New "new" -%token Null "null" %token Return "return" %token Switch "switch" %token This "this" %token Throw "throw" -%token True "true" %token Try "try" %token TypeOf "typeof" %token Var "var" @@ -207,40 +209,53 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %token While "while" %token With "with" -%token Abstract "abstract" -%token Boolean "boolean" -%token Byte "byte" -%token Char "char" -%token Class "class" -%token Const "const" +// ES3/IE6 Future, ES5/JSC Reserved %token Debugger "debugger" -%token Double "double" + +// ES3/ES5/IE6 Future, JSC Reserved +%token Const "const" + +// ES3/ES5/IE6/JSC Future +%token Class "class" %token Enum "enum" %token Export "export" %token Extends "extends" -%token Final "final" -%token Float "float" -%token Goto "goto" -%token Implements "implements" %token Import "import" -%token Int "int" -%token Interface "interface" -%token Long "long" -%token Native "native" -%token Package "package" -%token Private "private" -%token Protected "protected" -%token Public "public" -%token Short "short" -%token Static "static" %token Super "super" -%token Synchronized "synchronized" -%token Throws "throws" -%token Transient "transient" -%token Volatile "volatile" -%token Each "each" +// ES3 Future, ES5 Strict Future +%token Implements "implements" +%token Interface "interface" +%token Package "package" +%token Private "private" +%token Protected "protected" +%token Public "public" +%token Static "static" + +// ES3 Future +%token Abstract "abstract" +%token Boolean "boolean" +%token Byte "byte" +%token Char "char" +%token Double "double" +%token Final "final" +%token Float "float" +%token Goto "goto" +%token Int "int" +%token Long "long" +%token Native "native" +%token Short "short" +%token Synchronized "synchronized" +%token Throws "throws" +%token Transient "transient" +%token Volatile "volatile" + +// ES5 Strict %token Let "let" +%token Yield "yield" + +// Woah?! +%token Each "each" %token Identifier_ %token NumericLiteral @@ -335,7 +350,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type LabelledStatement %type LeftHandSideExpression %type LeftHandSideExpressionNoBF -%type LetStatement +//%type LetStatement %type Literal %type LogicalANDExpression %type LogicalANDExpressionNoBF @@ -459,13 +474,9 @@ WordOpt Word : Identifier { $$ = $1; } - | "abstract" { $$ = $1; } - | "boolean" { $$ = $1; } | "break" NewLineOpt { $$ = $1; } - | "byte" { $$ = $1; } | "case" { $$ = $1; } | "catch" { $$ = $1; } - | "char" { $$ = $1; } | "class" { $$ = $1; } | "const" { $$ = $1; } | "continue" NewLineOpt { $$ = $1; } @@ -473,57 +484,66 @@ Word | "default" { $$ = $1; } | "delete" { $$ = $1; } | "do" { $$ = $1; } - | "double" { $$ = $1; } | "else" { $$ = $1; } | "enum" { $$ = $1; } | "export" { $$ = $1; } | "extends" { $$ = $1; } | "false" { $$ = $1; } - | "final" { $$ = $1; } | "finally" { $$ = $1; } - | "float" { $$ = $1; } | "for" { $$ = $1; } | "function" { $$ = $1; } - | "goto" { $$ = $1; } | "if" { $$ = $1; } - | "implements" { $$ = $1; } | "import" { $$ = $1; } /* XXX: | "in" { $$ = $1; } */ /* XXX: | "instanceof" { $$ = $1; } */ - | "int" { $$ = $1; } - | "interface" { $$ = $1; } - | "long" { $$ = $1; } - | "native" { $$ = $1; } | "new" { $$ = $1; } | "null" { $$ = $1; } - | "package" { $$ = $1; } - | "private" { $$ = $1; } - | "protected" { $$ = $1; } - | "public" { $$ = $1; } | "return" NewLineOpt { $$ = $1; } - | "short" { $$ = $1; } - | "static" { $$ = $1; } | "super" { $$ = $1; } | "switch" { $$ = $1; } - | "synchronized" { $$ = $1; } | "this" { $$ = $1; } | "throw" NewLineOpt { $$ = $1; } - | "throws" { $$ = $1; } - | "transient" { $$ = $1; } | "true" { $$ = $1; } | "try" { $$ = $1; } | "typeof" { $$ = $1; } | "var" { $$ = $1; } | "void" { $$ = $1; } - | "volatile" { $$ = $1; } | "while" { $$ = $1; } | "with" { $$ = $1; } ; Identifier : Identifier_ { $$ = $1; } - | "each" { $$ = $1; } + + | "implements" { $$ = $1; } + | "interface" { $$ = $1; } + | "package" { $$ = $1; } + | "private" { $$ = $1; } + | "protected" { $$ = $1; } + | "public" { $$ = $1; } + | "static" { $$ = $1; } + + | "abstract" { $$ = $1; } + | "boolean" { $$ = $1; } + | "byte" { $$ = $1; } + | "char" { $$ = $1; } + | "double" { $$ = $1; } + | "final" { $$ = $1; } + | "float" { $$ = $1; } + | "goto" { $$ = $1; } + | "int" { $$ = $1; } + | "long" { $$ = $1; } + | "native" { $$ = $1; } + | "short" { $$ = $1; } + | "synchronized" { $$ = $1; } + | "throws" { $$ = $1; } + | "transient" { $$ = $1; } + | "volatile" { $$ = $1; } + | "let" { $$ = $1; } + | "yield" { $$ = $1; } + + | "each" { $$ = $1; } ; IdentifierOpt @@ -1384,7 +1404,7 @@ ForInStatement : "for" "each" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForEachIn($4, $6, $8); } ; /* }}} */ -/* JavaScript 1.7: Let Statements {{{ */ +/* JavaScript 1.7: Let Statements {{{ *//* LetStatement : "let" "(" VariableDeclarationList ")" Block_ { $$ = new(driver.pool_) CYLet($3, $5); } ; @@ -1392,6 +1412,6 @@ LetStatement Statement : LetStatement ; -/* }}} */ +*//* }}} */ %% diff --git a/Library.mm b/Library.mm index 61eafe1..b550bf5 100644 --- a/Library.mm +++ b/Library.mm @@ -756,10 +756,17 @@ size_t CYGetIndex(const char *value) { return _not(size_t); } +// XXX: fix this +static const char *CYPoolCString(apr_pool_t *pool, JSStringRef value); + size_t CYGetIndex(apr_pool_t *pool, NSString *value) { return CYGetIndex(CYPoolCString(pool, value)); } +size_t CYGetIndex(apr_pool_t *pool, JSStringRef value) { + return CYGetIndex(CYPoolCString(pool, value)); +} + bool CYGetOffset(const char *value, ssize_t &index) { if (value[0] != '0') { char *end; @@ -1730,23 +1737,24 @@ struct CYInternal : } }; -JSObjectRef CYMakeSelector(JSContextRef context, SEL sel) { +static JSObjectRef CYMakeSelector(JSContextRef context, SEL sel) { Selector_privateData *internal(new Selector_privateData(sel)); return JSObjectMake(context, Selector_, internal); } -JSObjectRef CYMakePointer(JSContextRef context, void *pointer, sig::Type *type, ffi_type *ffi, JSObjectRef owner) { +static JSObjectRef CYMakePointer(JSContextRef context, void *pointer, sig::Type *type, ffi_type *ffi, JSObjectRef owner) { Pointer *internal(new Pointer(pointer, context, owner, type)); return JSObjectMake(context, Pointer_, internal); } -JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) { +static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) { Functor_privateData *internal(new Functor_privateData(type, function)); return JSObjectMake(context, Functor_, internal); } -const char *CYPoolCString(apr_pool_t *pool, JSStringRef value) { +static const char *CYPoolCString(apr_pool_t *pool, JSStringRef value) { if (pool == NULL) { + // XXX: this could be much more efficient const char *string([CYCastNSString(NULL, value) UTF8String]); return string; } else { @@ -1757,11 +1765,11 @@ const char *CYPoolCString(apr_pool_t *pool, JSStringRef value) { } } -const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value) { +static const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value) { return JSValueIsNull(context, value) ? NULL : CYPoolCString(pool, CYJSString(context, value)); } -bool CYGetOffset(apr_pool_t *pool, JSStringRef value, ssize_t &index) { +static bool CYGetOffset(apr_pool_t *pool, JSStringRef value, ssize_t &index) { return CYGetOffset(CYPoolCString(pool, value), index); } @@ -1780,7 +1788,7 @@ bool CYGetOffset(apr_pool_t *pool, JSStringRef value, ssize_t &index) { utf8; \ }) -void *CYCastPointer_(JSContextRef context, JSValueRef value) { +static void *CYCastPointer_(JSContextRef context, JSValueRef value) { switch (JSValueGetType(context, value)) { case kJSTypeNull: return NULL; @@ -1800,11 +1808,11 @@ void *CYCastPointer_(JSContextRef context, JSValueRef value) { } template -_finline Type_ CYCastPointer(JSContextRef context, JSValueRef value) { +static _finline Type_ CYCastPointer(JSContextRef context, JSValueRef value) { return reinterpret_cast(CYCastPointer_(context, value)); } -SEL CYCastSEL(JSContextRef context, JSValueRef value) { +static SEL CYCastSEL(JSContextRef context, JSValueRef value) { if (JSValueIsObjectOfClass(context, value, Selector_)) { Selector_privateData *internal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); return reinterpret_cast(internal->value_); @@ -1812,7 +1820,7 @@ SEL CYCastSEL(JSContextRef context, JSValueRef value) { return CYCastPointer(context, value); } -void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) { +static void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) { switch (type->primitive) { case sig::boolean_P: *reinterpret_cast(data) = JSValueToBoolean(context, value); @@ -1890,7 +1898,7 @@ void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type } } -JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize = false, JSObjectRef owner = NULL) { +static JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize = false, JSObjectRef owner = NULL) { JSValueRef value; switch (type->primitive) { @@ -1980,7 +1988,7 @@ static bool CYImplements(id object, Class _class, SEL selector, bool devoid) { return false; } -const char *CYPoolTypeEncoding(apr_pool_t *pool, Class _class, SEL sel, Method method) { +static const char *CYPoolTypeEncoding(apr_pool_t *pool, Class _class, SEL sel, Method method) { if (method != NULL) return method_getTypeEncoding(method); else if (NSString *type = [[Bridge_ objectAtIndex:1] objectForKey:CYCastNSString(pool, sel_getName(sel))]) @@ -1989,7 +1997,7 @@ const char *CYPoolTypeEncoding(apr_pool_t *pool, Class _class, SEL sel, Method m return NULL; } -void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { +static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { Closure_privateData *internal(reinterpret_cast(arg)); JSContextRef context(internal->context_); @@ -2004,7 +2012,7 @@ void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { CYPoolFFI(NULL, context, internal->signature_.elements[0].type, internal->cif_.rtype, result, value); } -void MessageClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { +static void MessageClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { Closure_privateData *internal(reinterpret_cast(arg)); JSContextRef context(internal->context_); @@ -2021,7 +2029,7 @@ void MessageClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { CYPoolFFI(NULL, context, internal->signature_.elements[0].type, internal->cif_.rtype, result, value); } -Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const char *type, void (*callback)(ffi_cif *, void *, void **, void *)) { +static Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const char *type, void (*callback)(ffi_cif *, void *, void **, void *)) { // XXX: in case of exceptions this will leak // XXX: in point of fact, this may /need/ to leak :( Closure_privateData *internal(new Closure_privateData(CYGetJSContext(), function, type)); @@ -2042,7 +2050,7 @@ Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, return internal; } -JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char *type) { +static JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char *type) { Closure_privateData *internal(CYMakeFunctor_(context, function, type, &FunctionClosure_)); return JSObjectMake(context, Functor_, internal); } @@ -2328,7 +2336,7 @@ static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef } CYCatch } -bool CYIsClass(id self) { +static bool CYIsClass(id self) { // XXX: this is a lame object_isClass return class_getInstanceMethod(object_getClass(self), @selector(alloc)) != NULL; } @@ -2424,7 +2432,7 @@ static JSValueRef Internal_callAsFunction_$cya(JSContextRef context, JSObjectRef return internal->GetOwner(); } -bool Index_(apr_pool_t *pool, Struct_privateData *internal, JSStringRef property, ssize_t &index, uint8_t *&base) { +static bool Index_(apr_pool_t *pool, Struct_privateData *internal, JSStringRef property, ssize_t &index, uint8_t *&base) { Type_privateData *typical(internal->type_); sig::Type *type(typical->type_); if (type == NULL) @@ -2739,6 +2747,16 @@ static void ObjectiveC_Protocols_getPropertyNames(JSContextRef context, JSObject free(data); } +static JSObjectRef CYMakeType(JSContextRef context, const char *type) { + Type_privateData *internal(new Type_privateData(NULL, type)); + return JSObjectMake(context, Type_, internal); +} + +static JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) { + Type_privateData *internal(new Type_privateData(type)); + return JSObjectMake(context, Type_, internal); +} + static JSValueRef Runtime_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { if (JSStringIsEqualToUTF8CString(property, "nil")) return Instance::Make(context, nil); @@ -2762,11 +2780,17 @@ static JSValueRef Runtime_getProperty(JSContextRef context, JSObjectRef object, sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif); return CYFromFFI(context, signature.elements[0].type, cif.rtype, [name cy$symbol]); } + if (NSMutableArray *entry = [[Bridge_ objectAtIndex:2] objectForKey:name]) + switch ([[entry objectAtIndex:0] intValue]) { + // XXX: implement case 0 + case 1: + return CYMakeType(context, CYPoolCString(pool, [entry objectAtIndex:1])); + } return NULL; } CYCatch } -bool stret(ffi_type *ffi_type) { +static bool stret(ffi_type *ffi_type) { return ffi_type->type == FFI_TYPE_STRUCT && ( ffi_type->size > OBJC_MAX_STRUCT_BY_VALUE || struct_forward_array[ffi_type->size] != 0 @@ -2918,7 +2942,7 @@ static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef objec return CYCallFunction(pool, context, 0, NULL, count, arguments, false, exception, &internal->signature_, &internal->cif_, internal->GetValue()); } -JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { +static JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 1) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector constructor" userInfo:nil]; @@ -2927,7 +2951,7 @@ JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t count, } CYCatch } -JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { +static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 2) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Functor constructor" userInfo:nil]; @@ -2944,25 +2968,47 @@ JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, } CYCatch } -JSObjectRef CYMakeType(JSContextRef context, JSObjectRef object, const char *type) { - Type_privateData *internal(new Type_privateData(NULL, type)); - return JSObjectMake(context, Type_, internal); -} - -JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { +static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 1) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Type constructor" userInfo:nil]; const char *type(CYCastCString(context, arguments[0])); - return CYMakeType(context, object, type); + return CYMakeType(context, type); + } CYCatch +} + +static JSValueRef Type_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + + CYTry { + sig::Type type; + + if (JSStringIsEqualToUTF8CString(property, "$cyi")) { + type.primitive = sig::pointer_P; + type.data.data.size = 0; + } else { + size_t index(CYGetIndex(NULL, property)); + if (index == _not(size_t)) + return NULL; + type.primitive = sig::array_P; + type.data.data.size = index; + } + + type.name = NULL; + type.flags = 0; + + type.data.data.type = internal->type_; + + return CYMakeType(context, &type); } CYCatch } static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + CYTry { 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))); sig::Type *type(internal->type_); ffi_type *ffi(internal->GetFFI()); // XXX: alignment? @@ -2975,17 +3021,26 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - if (count > 1) + if (count != 0) @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 * size)); - return CYMakePointer(context, value, internal->type_, internal->ffi_, NULL); + + sig::Type *type(internal->type_); + size_t size; + + if (type->primitive != sig::array_P) + size = 0; + else { + size = type->data.data.size; + type = type->data.data.type; + } + + void *value(malloc(internal->GetFFI()->size)); + return CYMakePointer(context, value, type, NULL, NULL); } CYCatch } -JSObjectRef Instance_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { +static JSObjectRef Instance_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count > 1) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Instance constructor" userInfo:nil]; @@ -2994,7 +3049,7 @@ JSObjectRef Instance_new(JSContextRef context, JSObjectRef object, size_t count, } CYCatch } -JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { +static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 2) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Functor constructor" userInfo:nil]; @@ -3003,7 +3058,7 @@ JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, } CYCatch } -JSValueRef CYValue_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { +static JSValueRef CYValue_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYValue *internal(reinterpret_cast(JSObjectGetPrivate(object))); return CYCastJSValue(context, reinterpret_cast(internal->value_)); } @@ -3328,7 +3383,7 @@ bool CYSendAll_(int socket, const uint8_t *data, size_t size) { return true; } -apr_pool_t *Pool_; +static apr_pool_t *Pool_; struct CYExecute_ { apr_pool_t *pool_; @@ -3536,7 +3591,7 @@ JSGlobalContextRef CYGetJSContext() { definition = kJSClassDefinitionEmpty; definition.className = "Type"; definition.staticFunctions = Type_staticFunctions; - //definition.getProperty = &Type_getProperty; + definition.getProperty = &Type_getProperty; definition.callAsFunction = &Type_callAsFunction; definition.callAsConstructor = &Type_callAsConstructor; definition.finalize = &Finalize; diff --git a/sig/ffi_type.cpp b/sig/ffi_type.cpp index 7092dda..b38d652 100644 --- a/sig/ffi_type.cpp +++ b/sig/ffi_type.cpp @@ -79,10 +79,23 @@ ffi_type *ObjectiveC(apr_pool_t *pool, struct Type *type) { case ulonglong_P: return &ffi_type_ulonglong; case ushort_P: return &ffi_type_ushort; - case array_P: - /* XXX: implement */ - _assert(false); - break; + case array_P: { + // XXX: this is really lame + ffi_type *aggregate(reinterpret_cast(apr_palloc(pool, sizeof(ffi_type)))); + aggregate->size = 0; + aggregate->alignment = 0; + aggregate->type = FFI_TYPE_STRUCT; + + ffi_type *element(ObjectiveC(pool, type->data.data.type)); + size_t size(type->data.data.size); + + aggregate->elements = reinterpret_cast(apr_palloc(pool, (size + 1) * sizeof(ffi_type *))); + for (size_t i(0); i != size; ++i) + aggregate->elements[i] = element; + aggregate->elements[size] = NULL; + + return aggregate; + } break; case pointer_P: return &ffi_type_pointer; @@ -102,7 +115,7 @@ ffi_type *ObjectiveC(apr_pool_t *pool, struct Type *type) { case void_P: return &ffi_type_void; case struct_P: { - ffi_type *aggregate = reinterpret_cast(apr_palloc(pool, sizeof(ffi_type))); + ffi_type *aggregate(reinterpret_cast(apr_palloc(pool, sizeof(ffi_type)))); aggregate->size = 0; aggregate->alignment = 0; aggregate->type = FFI_TYPE_STRUCT; -- 2.45.2