From b09da87b6557610325d46e3294ea0b6aba69ebf0 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 8 Oct 2009 00:50:58 +0000 Subject: [PATCH] Drastic improvements to memory management, handle many more minimization corner cases via CYFlags (like NoIn), added support for @class, implemented Selector.type, and support execution of script files. --- Application.mm | 118 +++++++++++--- Bridge.def | 3 + Cycript.l | 2 + Cycript.y | 82 +++++++++- Library.mm | 415 +++++++++++++++++++++++++++++++++++++++---------- Output.cpp | 341 ++++++++++++++++++++++++++++------------ Parser.hpp | 229 ++++++++++++++++++--------- cycript.hpp | 7 +- documents.txt | 7 +- makefile | 27 ++-- 10 files changed, 925 insertions(+), 306 deletions(-) diff --git a/Application.mm b/Application.mm index 7b58023..aaf1d5e 100644 --- a/Application.mm +++ b/Application.mm @@ -11,6 +11,15 @@ #include #include +#include + +#include +#include + +#include +#include +#include + #include "Cycript.tab.hh" static jmp_buf ctrlc_; @@ -19,7 +28,39 @@ void sigint(int) { longjmp(ctrlc_, 1); } -int main(int argc, const char *argv[]) { +void Run(const char *code, FILE *fout) { _pooled + JSStringRef script(JSStringCreateWithUTF8CString(code)); + + JSContextRef context(CYGetJSContext()); + + JSValueRef exception(NULL); + JSValueRef result(JSEvaluateScript(context, script, NULL, NULL, 0, &exception)); + JSStringRelease(script); + + if (exception != NULL) + result = exception; + + if (!JSValueIsUndefined(context, result)) { + CFStringRef json; + + @try { json: + json = CYCopyJSONString(context, result); + } @catch (id error) { + CYThrow(context, error, &result); + goto json; + } + + if (fout != NULL) { + fputs([reinterpret_cast(json) UTF8String], fout); + fputs("\n", fout); + fflush(fout); + } + + CFRelease(json); + } +} + +void Console() { bool bypass(false); bool debug(false); @@ -114,40 +155,69 @@ int main(int argc, const char *argv[]) { if (debug) std::cout << code << std::endl; - _pooled + Run(code.c_str(), fout); + } - JSStringRef script(JSStringCreateWithUTF8CString(code.c_str())); + fputs("\n", fout); + fflush(fout); +} - JSContextRef context(CYGetJSContext()); +void *Map(const char *path, size_t *psize) { + int fd; + _syscall(fd = open(path, O_RDONLY)); - JSValueRef exception(NULL); - JSValueRef result(JSEvaluateScript(context, script, NULL, NULL, 0, &exception)); - JSStringRelease(script); + struct stat stat; + _syscall(fstat(fd, &stat)); + size_t size(stat.st_size); - if (exception != NULL) - result = exception; + *psize = size; - if (JSValueIsUndefined(context, result)) - goto restart; + void *base; + _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)); - CFStringRef json; + _syscall(close(fd)); + return base; +} - @try { json: - json = CYCopyJSONString(context, result); - } @catch (id error) { - CYThrow(context, error, &result); - goto json; +int main(int argc, const char *argv[]) { + const char *script; + + if (argc == 1) + script = NULL; + else { + CYSetArgs(argc - 1, argv + 1); + script = argv[1]; + } + + if (script == NULL || strcmp(script, "-") == 0) + Console(); + else { + CYDriver driver(script); + cy::parser parser(driver); + + size_t size; + char *start(reinterpret_cast(Map(script, &size))); + char *end(start + size); + + if (size >= 2 && start[0] == '#' && start[1] == '!') { + start += 2; + while (start != end && *start++ != '\n'); } - fputs([reinterpret_cast(json) UTF8String], fout); - CFRelease(json); + driver.data_ = start; + driver.size_ = end - start; - fputs("\n", fout); - fflush(fout); + if (parser.parse() != 0 || !driver.errors_.empty()) { + for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i) + std::cerr << i->location_.begin << ": " << i->message_ << std::endl; + } else if (driver.source_ != NULL) { + std::ostringstream str; + driver.source_->Show(str); + std::string code(str.str()); + std::cout << code << std::endl; + Run(code.c_str(), stdout); + } } - fputs("\n", fout); - fflush(fout); - return 0; } diff --git a/Bridge.def b/Bridge.def index 26870d7..cea2284 100644 --- a/Bridge.def +++ b/Bridge.def @@ -49,6 +49,7 @@ F method_getReturnType v^{objc_method=}^cL F method_getTypeEncoding *^{objc_method=} F method_setImplementation ^?^{objc_method=}^? +# this should return # or ^v ? F objc_allocateClassPair ##*L F objc_copyProtocolList ^@^I F objc_duplicateClass ##*L @@ -505,3 +506,5 @@ C MKPinAnnotationColorPurple 2 # MKCoordinateRegionMake # MKCoordinateRegionMakeWithDistance # MKCoordinateSpanMake + +: applicationDidFinishLaunching: v@ diff --git a/Cycript.l b/Cycript.l index b1ff59a..43c9285 100644 --- a/Cycript.l +++ b/Cycript.l @@ -119,6 +119,8 @@ Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4} "[" L C return tk::OpenBracket; "]" L C return tk::CloseBracket; +"@class" L C return tk::AtClass; +"@end" L C return tk::AtEnd; "@selector" L C return tk::AtSelector; "break" L R yylval->word_ = new CYWord("break"); return tk::Break; diff --git a/Cycript.y b/Cycript.y index 4b90f42..e51a0ec 100644 --- a/Cycript.y +++ b/Cycript.y @@ -11,6 +11,8 @@ typedef struct { bool newline_; union { + bool bool_; + CYArgument *argument_; CYBoolean *boolean_; CYClause *clause_; @@ -21,14 +23,17 @@ typedef struct { CYElement *element_; CYExpression *expression_; CYFalse *false_; + CYField *field_; CYForInitialiser *for_; CYForInInitialiser *forin_; + CYFunctionParameter *functionParameter_; CYIdentifier *identifier_; CYLiteral *literal_; + CYMessage *message_; + CYMessageParameter *messageParameter_; CYName *name_; CYNull *null_; CYNumber *number_; - CYParameter *parameter_; CYProperty *property_; CYSelectorPart *selector_; CYSource *source_; @@ -120,8 +125,8 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %token OpenBracket "[" %token CloseBracket "]" +%token AtClass "@class" %token AtSelector "@selector" -%token AtImplementation "@implementation" %token AtEnd "@end" %token Break "break" @@ -217,6 +222,11 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type CaseClause %type CaseClausesOpt %type CatchOpt +%type ClassDeclaration +%type ClassMessageDeclaration +%type ClassMessageDeclarationListOpt +%type ClassSuperOpt +%type ClassFieldList %type ConditionalExpression %type ConditionalExpressionNoBF %type ConditionalExpressionNoIn @@ -245,8 +255,8 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type ForStatementInitialiser %type ForInStatement %type ForInStatementInitialiser -%type FormalParameterList -%type FormalParameterList_ +%type FormalParameterList +%type FormalParameterList_ %type FunctionBody %type FunctionDeclaration %type FunctionExpression @@ -271,6 +281,11 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type MemberExpression %type MemberExpression_ %type MemberExpressionNoBF +%type MessageParameter +%type MessageParameters +%type MessageParameterList +%type MessageParameterListOpt +%type MessageScope %type MultiplicativeExpression %type MultiplicativeExpressionNoBF %type NewExpression @@ -305,6 +320,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type SwitchStatement %type ThrowStatement %type TryStatement +%type TypeOpt %type UnaryExpression %type UnaryExpression_ %type UnaryExpressionNoBF @@ -1103,7 +1119,7 @@ FormalParameterList_ ; FormalParameterList - : Identifier FormalParameterList_ { $$ = new(driver.pool_) CYParameter($1, $2); } + : Identifier FormalParameterList_ { $$ = new(driver.pool_) CYFunctionParameter($1, $2); } | { $$ = NULL; } ; @@ -1126,6 +1142,60 @@ SourceElement ; /* Objective-C Extensions {{{ */ +ClassSuperOpt + : ":" MemberExpressionNoBF { $$ = $2; } + | { $$ = NULL; } + ; + +ClassFieldList + : "{" "}" { $$ = NULL; } + ; + +MessageScope + : "+" { $$ = false; } + | "-" { $$ = true; } + ; + +TypeOpt + : "(" Expression ")" { $$ = $2; } + | { $$ = NULL; } + ; + +MessageParameter + : Word ":" TypeOpt Identifier { $$ = new CYMessageParameter($1, $3, $4); } + ; + +MessageParameterListOpt + : MessageParameterList { $$ = $1; } + | { $$ = NULL; } + ; + +MessageParameterList + : MessageParameter MessageParameterListOpt { $1->SetNext($2); $$ = $1; } + ; + +MessageParameters + : MessageParameterList { $$ = $1; } + | Word { $$ = new CYMessageParameter($1, NULL, NULL); } + ; + +ClassMessageDeclaration + : MessageScope TypeOpt MessageParameters "{" FunctionBody "}" { $$ = new CYMessage($1, $2, $3, $5); } + ; + +ClassMessageDeclarationListOpt + : ClassMessageDeclarationListOpt ClassMessageDeclaration { if ($1) { $1->SetNext($2); $$ = $1; } else $$ = $2; } + | { $$ = NULL; } + ; + +ClassDeclaration + : "@class" Identifier ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new CYClass($2, $3, $4, $5); } + ; + +SourceElement + : ClassDeclaration { $$ = $1; } + ; + VariadicCall : "," AssignmentExpression VariadicCall { $$ = new(driver.pool_) CYArgument(NULL, $2, $3); } | { $$ = NULL; } @@ -1146,7 +1216,7 @@ SelectorList ; MessageExpression - : "[" AssignmentExpression SelectorList "]" { $$ = new(driver.pool_) CYMessage($2, $3); } + : "[" AssignmentExpression SelectorList "]" { $$ = new(driver.pool_) CYSend($2, $3); } ; SelectorExpressionOpt diff --git a/Library.mm b/Library.mm index 0dceaea..574d944 100644 --- a/Library.mm +++ b/Library.mm @@ -60,6 +60,7 @@ #include #include #include +#include #include #include @@ -81,8 +82,8 @@ CFLog(kCFLogLevelNotice, CFSTR("_trace():%u"), __LINE__); \ } while (false) - static JSContextRef Context_; +static JSObjectRef System_; static JSClassRef Functor_; static JSClassRef Instance_; @@ -105,8 +106,32 @@ struct Client { CFSocketRef socket_; }; -JSObjectRef CYMakeObject(JSContextRef context, id object) { - return JSObjectMake(context, Instance_, [object retain]); +JSObjectRef CYMakeInstance(JSContextRef context, id object) { + return JSObjectMake(context, Instance_, object); +} + +JSValueRef CYCastJSValue(JSContextRef context, bool value) { + return JSValueMakeBoolean(context, value); +} + +JSValueRef CYCastJSValue(JSContextRef context, double value) { + return JSValueMakeNumber(context, value); +} + +#define CYCastJSValue_(Type_) \ + JSValueRef CYCastJSValue(JSContextRef context, Type_ value) { \ + return JSValueMakeNumber(context, static_cast(value)); \ + } + +CYCastJSValue_(int) +CYCastJSValue_(unsigned int) +CYCastJSValue_(long int) +CYCastJSValue_(long unsigned int) +CYCastJSValue_(long long int) +CYCastJSValue_(long long unsigned int) + +JSValueRef CYJSUndefined(JSContextRef context) { + return JSValueMakeUndefined(context); } @interface NSMethodSignature (Cycript) @@ -138,7 +163,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { } - (JSValueRef) cy$JSValueInContext:(JSContextRef)context { - return CYMakeObject(context, self); + return CYMakeInstance(context, self); } @end @@ -154,7 +179,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { } - (JSValueRef) cy$JSValueInContext:(JSContextRef)context { - return JSValueMakeUndefined(context); + return CYJSUndefined(context); } @end @@ -216,7 +241,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { } - (JSValueRef) cy$JSValueInContext:(JSContextRef)context { - return [self class] != NSCFBoolean_ ? JSValueMakeNumber(context, [self doubleValue]) : JSValueMakeBoolean(context, [self boolValue]); + return [self class] != NSCFBoolean_ ? CYCastJSValue(context, [self doubleValue]) : CYCastJSValue(context, [self boolValue]); } - (void *) cy$symbol { @@ -284,60 +309,98 @@ JSContextRef CYGetJSContext() { #define CYCatch \ @catch (id error) { \ + NSLog(@"e:%@", error); \ CYThrow(context, error, exception); \ return NULL; \ } void CYThrow(JSContextRef context, JSValueRef value); -id CYCastNSObject(JSContextRef context, JSObjectRef object) { +apr_status_t CYPoolRelease_(void *data) { + id object(reinterpret_cast(data)); + [object release]; + return APR_SUCCESS; +} + +id CYPoolRelease(apr_pool_t *pool, id object) { + if (pool == NULL) + return [object autorelease]; + else { + apr_pool_cleanup_register(pool, object, &CYPoolRelease_, &apr_pool_cleanup_null); + return object; + } +} + +id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { if (JSValueIsObjectOfClass(context, object, Instance_)) return reinterpret_cast(JSObjectGetPrivate(object)); JSValueRef exception(NULL); bool array(JSValueIsInstanceOfConstructor(context, object, Array_, &exception)); CYThrow(context, exception); - if (array) - return [[[CYJSArray alloc] initWithJSObject:object inContext:context] autorelease]; - return [[[CYJSObject alloc] initWithJSObject:object inContext:context] autorelease]; + id value(array ? [CYJSArray alloc] : [CYJSObject alloc]); + return CYPoolRelease(pool, [value initWithJSObject:object inContext:context]); } JSStringRef CYCopyJSString(id value) { - return JSStringCreateWithCFString(reinterpret_cast([value description])); + return value == NULL ? NULL : JSStringCreateWithCFString(reinterpret_cast([value description])); } JSStringRef CYCopyJSString(const char *value) { - return JSStringCreateWithUTF8CString(value); + return value == NULL ? NULL : JSStringCreateWithUTF8CString(value); } JSStringRef CYCopyJSString(JSStringRef value) { - return JSStringRetain(value); + return value == NULL ? NULL : JSStringRetain(value); } JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value) { + if (JSValueIsNull(context, value)) + return NULL; JSValueRef exception(NULL); JSStringRef string(JSValueToStringCopy(context, value, &exception)); CYThrow(context, exception); return string; } -// XXX: this is not a safe handle class CYJSString { private: JSStringRef string_; + void Clear_() { + JSStringRelease(string_); + } + public: + CYJSString(const CYJSString &rhs) : + string_(CYCopyJSString(rhs.string_)) + { + } + template - CYJSString(Arg0_ arg0) { - string_ = CYCopyJSString(arg0); + CYJSString(Arg0_ arg0) : + string_(CYCopyJSString(arg0)) + { } template - CYJSString(Arg0_ arg0, Arg1_ arg1) { - string_ = CYCopyJSString(arg0, arg1); + CYJSString(Arg0_ arg0, Arg1_ arg1) : + string_(CYCopyJSString(arg0, arg1)) + { + } + + CYJSString &operator =(const CYJSString &rhs) { + Clear_(); + string_ = CYCopyJSString(rhs.string_); + return *this; } ~CYJSString() { - JSStringRelease(string_); + Clear_(); + } + + void Clear() { + Clear_(); + string_ = NULL; } operator JSStringRef() const { @@ -365,50 +428,103 @@ CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef value) { return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &number); } -NSString *CYCastNSString(JSStringRef value) { - return [reinterpret_cast(CYCopyCFString(value)) autorelease]; +NSString *CYCastNSString(apr_pool_t *pool, JSStringRef value) { + return CYPoolRelease(pool, reinterpret_cast(CYCopyCFString(value))); +} + +bool CYCastBool(JSContextRef context, JSValueRef value) { + return JSValueToBoolean(context, value); } -CFTypeRef CYCopyCFType(JSContextRef context, JSValueRef value) { +CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, bool cast) { + CFTypeRef object; + bool copy; + switch (JSType type = JSValueGetType(context, value)) { case kJSTypeUndefined: - return CFRetain([WebUndefined undefined]); + object = [WebUndefined undefined]; + copy = false; + break; + case kJSTypeNull: - return nil; + return NULL; + break; + case kJSTypeBoolean: - return CFRetain(JSValueToBoolean(context, value) ? kCFBooleanTrue : kCFBooleanFalse); + object = CYCastBool(context, value) ? kCFBooleanTrue : kCFBooleanFalse; + copy = false; + break; + case kJSTypeNumber: - return CYCopyCFNumber(context, value); + object = CYCopyCFNumber(context, value); + copy = true; + break; + case kJSTypeString: - return CYCopyCFString(context, value); + object = CYCopyCFString(context, value); + copy = true; + break; + case kJSTypeObject: - return CFRetain((CFTypeRef) CYCastNSObject(context, (JSObjectRef) value)); + // XXX: this might could be more efficient + object = (CFTypeRef) CYCastNSObject(pool, context, (JSObjectRef) value); + copy = false; + break; + default: @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"JSValueGetType() == 0x%x", type] userInfo:nil]; + break; } + + if (cast != copy) + return object; + else if (copy) + return CYPoolRelease(pool, (id) object); + else + return CFRetain(object); +} + +CFTypeRef CYCastCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value) { + return CYCFType(pool, context, value, true); +} + +CFTypeRef CYCopyCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value) { + return CYCFType(pool, context, value, false); } NSArray *CYCastNSArray(JSPropertyNameArrayRef names) { + CYPool pool; size_t size(JSPropertyNameArrayGetCount(names)); NSMutableArray *array([NSMutableArray arrayWithCapacity:size]); for (size_t index(0); index != size; ++index) - [array addObject:CYCastNSString(JSPropertyNameArrayGetNameAtIndex(names, index))]; + [array addObject:CYCastNSString(pool, JSPropertyNameArrayGetNameAtIndex(names, index))]; return array; } -id CYCastNSObject(JSContextRef context, JSValueRef value) { - const NSObject *object(reinterpret_cast(CYCopyCFType(context, value))); - return object == nil ? nil : [object autorelease]; +id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value) { + return reinterpret_cast(CYCastCFType(pool, context, value)); } void CYThrow(JSContextRef context, JSValueRef value) { if (value == NULL) return; - @throw CYCastNSObject(context, value); + @throw CYCastNSObject(NULL, context, value); +} + +JSValueRef CYJSNull(JSContextRef context) { + return JSValueMakeNull(context); +} + +JSValueRef CYCastJSValue(JSContextRef context, JSStringRef value) { + return value == NULL ? CYJSNull(context) : JSValueMakeString(context, value); +} + +JSValueRef CYCastJSValue(JSContextRef context, const char *value) { + return CYCastJSValue(context, CYJSString(value)); } JSValueRef CYCastJSValue(JSContextRef context, id value) { - return value == nil ? JSValueMakeNull(context) : [value cy$JSValueInContext:context]; + return value == nil ? CYJSNull(context) : [value cy$JSValueInContext:context]; } JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value) { @@ -452,7 +568,7 @@ void CYThrow(JSContextRef context, id error, JSValueRef *exception) { } - (id) objectForKey:(id)key { - return CYCastNSObject(context_, CYGetProperty(context_, object_, CYJSString(key))); + return CYCastNSObject(NULL, context_, CYGetProperty(context_, object_, CYJSString(key))); } - (NSEnumerator *) keyEnumerator { @@ -492,14 +608,14 @@ void CYThrow(JSContextRef context, id error, JSValueRef *exception) { JSValueRef exception(NULL); JSValueRef value(JSObjectGetPropertyAtIndex(context_, object_, index, &exception)); CYThrow(context_, exception); - id object(CYCastNSObject(context_, value)); + id object(CYCastNSObject(NULL, context_, value)); return object == nil ? [NSNull null] : object; } @end CFStringRef CYCopyJSONString(JSContextRef context, JSValueRef value) { - id object(CYCastNSObject(context, value)); + id object(CYCastNSObject(NULL, context, value)); return reinterpret_cast([(object == nil ? @"null" : [object cy$toJSON]) retain]); } @@ -576,20 +692,39 @@ static void OnAccept(CFSocketRef socket, CFSocketCallBackType type, CFDataRef ad } } -static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { _pooled +static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { @try { - NSString *name(CYCastNSString(property)); - NSLog(@"%@", name); + CYPool pool; + NSString *name(CYCastNSString(pool, property)); + NSLog(@"get:%@", name); return NULL; } CYCatch } +static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { + @try { + CYPool pool; + NSString *name(CYCastNSString(pool, property)); + NSLog(@"set:%@", name); + return false; + } CYCatch +} + +static bool Instance_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { + @try { + CYPool pool; + NSString *name(CYCastNSString(pool, property)); + NSLog(@"delete:%@", name); + return false; + } CYCatch +} + typedef id jocData; -static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { _pooled +static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { @try { id data(reinterpret_cast(JSObjectGetPrivate(object))); - return CYMakeObject(context, [[data alloc] autorelease]); + return CYMakeInstance(context, [data alloc]); } CYCatch } @@ -616,7 +751,7 @@ struct ffiData : ptrData { sig::Signature signature_; ffi_cif cif_; - ffiData(void (*value)(), const char *type) : + ffiData(const char *type, void (*value)() = NULL) : ptrData(reinterpret_cast(value)) { sig::Parse(pool_, &signature_, type); @@ -629,6 +764,10 @@ struct selData : ptrData { ptrData(value) { } + + SEL GetValue() const { + return reinterpret_cast(value_); + } }; JSObjectRef CYMakeSelector(JSContextRef context, SEL sel) { @@ -646,39 +785,62 @@ static void Pointer_finalize(JSObjectRef object) { apr_pool_destroy(data->pool_); } -static void Instance_finalize(JSObjectRef object) { +/*static void Instance_finalize(JSObjectRef object) { id data(reinterpret_cast(JSObjectGetPrivate(object))); - [data release]; -} +}*/ -JSObjectRef CYMakeFunction(JSContextRef context, void (*function)(), const char *type) { - ffiData *data(new ffiData(function, type)); +JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) { + ffiData *data(new ffiData(type, function)); return JSObjectMake(context, Functor_, data); } -JSObjectRef CYMakeFunction(JSContextRef context, void *function, const char *type) { - return CYMakeFunction(context, reinterpret_cast(function), type); +void Closure_(ffi_cif *cif, void *result, void **arguments, void *arg) { +} + +JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char *type) { + // XXX: in case of exceptions this will leak + ffiData *data(new ffiData(type)); + + ffi_closure *closure; + _syscall(closure = (ffi_closure *) mmap( + NULL, sizeof(ffi_closure), + PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, + -1, 0 + )); + + ffi_status status(ffi_prep_closure(closure, &data->cif_, &Closure_, data)); + _assert(status == FFI_OK); + + _syscall(mprotect(closure, sizeof(*closure), PROT_READ | PROT_EXEC)); + + return JSObjectMake(context, Functor_, data); } char *CYPoolCString(apr_pool_t *pool, JSStringRef value) { size_t size(JSStringGetMaximumUTF8CStringSize(value)); char *string(new(pool) char[size]); JSStringGetUTF8CString(value, string, size); - JSStringRelease(value); return string; } char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value) { + if (JSValueIsNull(context, value)) + return NULL; return CYPoolCString(pool, CYJSString(context, value)); } // XXX: this macro is unhygenic #define CYCastCString(context, value) ({ \ - JSStringRef string(CYCopyJSString(context, value)); \ - size_t size(JSStringGetMaximumUTF8CStringSize(string)); \ - char *utf8(reinterpret_cast(alloca(size))); \ - JSStringGetUTF8CString(string, utf8, size); \ - JSStringRelease(string); \ + char *utf8; \ + if (value == NULL) \ + utf8 = NULL; \ + else { \ + JSStringRef string(CYCopyJSString(context, value)); \ + size_t size(JSStringGetMaximumUTF8CStringSize(string)); \ + utf8 = reinterpret_cast(alloca(size)); \ + JSStringGetUTF8CString(string, utf8, size); \ + JSStringRelease(string); \ + } \ utf8; \ }) @@ -692,7 +854,7 @@ SEL CYCastSEL(JSContextRef context, JSValueRef value) { return sel_registerName(CYCastCString(context, value)); } -void *CYCastPointer(JSContextRef context, JSValueRef value) { +void *CYCastPointer_(JSContextRef context, JSValueRef value) { switch (JSValueGetType(context, value)) { case kJSTypeNull: return NULL; @@ -708,6 +870,11 @@ void *CYCastPointer(JSContextRef context, JSValueRef value) { } } +template +_finline Type_ CYCastPointer(JSContextRef context, JSValueRef value) { + return reinterpret_cast(CYCastPointer_(context, value)); +} + void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, void *data, JSValueRef value) { switch (type->primitive) { case sig::boolean_P: @@ -734,7 +901,7 @@ void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, void *da case sig::object_P: case sig::typename_P: - *reinterpret_cast(data) = CYCastNSObject(context, value); + *reinterpret_cast(data) = CYCastNSObject(pool, context, value); break; case sig::selector_P: @@ -742,7 +909,7 @@ void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, void *da break; case sig::pointer_P: - *reinterpret_cast(data) = CYCastPointer(context, value); + *reinterpret_cast(data) = CYCastPointer(context, value); break; case sig::string_P: @@ -766,12 +933,12 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { switch (type->primitive) { case sig::boolean_P: - value = JSValueMakeBoolean(context, *reinterpret_cast(data)); + value = CYCastJSValue(context, *reinterpret_cast(data)); break; #define CYFromFFI_(primitive, native) \ case sig::primitive ## _P: \ - value = JSValueMakeNumber(context, *reinterpret_cast(data)); \ + value = CYCastJSValue(context, *reinterpret_cast(data)); \ break; CYFromFFI_(uchar, unsigned char) @@ -788,10 +955,13 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { CYFromFFI_(double, double) case sig::object_P: - case sig::typename_P: value = CYCastJSValue(context, *reinterpret_cast(data)); break; + case sig::typename_P: + value = CYMakeInstance(context, *reinterpret_cast(data)); + break; + case sig::selector_P: if (SEL sel = *reinterpret_cast(data)) value = CYMakeSelector(context, sel); @@ -806,7 +976,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { case sig::string_P: if (char *utf8 = *reinterpret_cast(data)) - value = JSValueMakeString(context, CYJSString(utf8)); + value = CYCastJSValue(context, utf8); else goto null; break; @@ -814,11 +984,11 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { goto fail; case sig::void_P: - value = JSValueMakeUndefined(context); + value = CYJSUndefined(context); break; null: - value = JSValueMakeNull(context); + value = CYJSNull(context); break; default: fail: @@ -829,7 +999,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { return value; } -static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSValueRef *arguments, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { _pooled +static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSValueRef *arguments, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { @try { if (count != signature->count - 1) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to ffi function" userInfo:nil]; @@ -851,17 +1021,18 @@ static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSVal } CYCatch } -static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { _pooled +static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { @try { - NSString *name(CYCastNSString(property)); + CYPool pool; + NSString *name(CYCastNSString(pool, property)); if (Class _class = NSClassFromString(name)) - return CYMakeObject(context, _class); + return CYMakeInstance(context, _class); if (NSMutableArray *entry = [Bridge_ objectForKey:name]) switch ([[entry objectAtIndex:0] intValue]) { case 0: return JSEvaluateScript(CYGetJSContext(), CYJSString([entry objectAtIndex:1]), NULL, NULL, 0, NULL); case 1: - return CYMakeFunction(context, [name cy$symbol], [[entry objectAtIndex:1] UTF8String]); + return CYMakeFunctor(context, reinterpret_cast([name cy$symbol]), [[entry objectAtIndex:1] UTF8String]); case 2: CYPool pool; sig::Signature signature; @@ -879,16 +1050,43 @@ bool stret(ffi_type *ffi_type) { ); } -static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { _pooled +extern "C" { + int *_NSGetArgc(void); + char ***_NSGetArgv(void); + int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName); +} + +static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + @try { + NSLog(@"%s", CYCastCString(context, arguments[0])); + return CYJSUndefined(context); + } CYCatch +} + +static JSValueRef CYApplicationMain(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + @try { + CYPool pool; + NSString *name(CYCastNSObject(pool, context, arguments[0])); + int argc(*_NSGetArgc() - 1); + char **argv(*_NSGetArgv() + 1); + for (int i(0); i != argc; ++i) + NSLog(@"argv[%i]=%s", i, argv[i]); + return CYCastJSValue(context, UIApplicationMain(argc, argv, name, name)); + } CYCatch +} + +static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { const char *type; @try { if (count < 2) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"too few arguments to objc_msgSend" userInfo:nil]; - id self(CYCastNSObject(context, arguments[0])); + CYPool pool; + + id self(CYCastNSObject(pool, context, arguments[0])); if (self == nil) - return JSValueMakeNull(context); + return CYJSNull(context); SEL _cmd(CYCastSEL(context, arguments[1])); NSMethodSignature *method([self methodSignatureForSelector:_cmd]); @@ -923,7 +1121,7 @@ static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef objec return CYCallFunction(context, count, arguments, exception, &data->signature_, &data->cif_, reinterpret_cast(data->value_)); } -JSObjectRef sel(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { +JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { @try { if (count != 1) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector constructor" userInfo:nil]; @@ -932,25 +1130,51 @@ JSObjectRef sel(JSContextRef context, JSObjectRef object, size_t count, const JS } CYCatch } -JSObjectRef ffi(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { +JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { @try { if (count != 2) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Functor constructor" userInfo:nil]; - void *function(CYCastPointer(context, arguments[0])); const char *type(CYCastCString(context, arguments[1])); - return CYMakeFunction(context, function, type); + JSValueRef exception(NULL); + if (JSValueIsInstanceOfConstructor(context, arguments[0], Function_, &exception)) { + JSObjectRef function(CYCastJSObject(context, arguments[0])); + return CYMakeFunctor(context, function, type); + } else if (exception != NULL) { + return NULL; + } else { + void (*function)()(CYCastPointer(context, arguments[0])); + return CYMakeFunctor(context, function, type); + } } CYCatch } JSValueRef Pointer_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { ptrData *data(reinterpret_cast(JSObjectGetPrivate(object))); - return JSValueMakeNumber(context, reinterpret_cast(data->value_)); + return CYCastJSValue(context, reinterpret_cast(data->value_)); } JSValueRef Selector_getProperty_prototype(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { return Function_; } +static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + @try { + if (count != 2) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector.type" userInfo:nil]; + CYPool pool; + selData *data(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)) + return CYCastJSValue(context, method_getTypeEncoding(method)); + else if (NSString *type = [Bridge_ objectForKey:[NSString stringWithFormat:@":%s", sel_getName(sel)]]) + return CYCastJSValue(context, CYJSString(type)); + else + return CYJSNull(context); + } CYCatch +} + static JSStaticValue Pointer_staticValues[2] = { {"value", &Pointer_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} @@ -961,6 +1185,11 @@ static JSStaticValue Pointer_staticValues[2] = { {NULL, NULL, NULL, 0} };*/ +static JSStaticFunction Selector_staticFunctions[2] = { + {"type", &Selector_callAsFunction_type, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, 0} +}; + CYDriver::CYDriver(const std::string &filename) : state_(CYClear), data_(NULL), @@ -982,6 +1211,17 @@ void cy::parser::error(const cy::parser::location_type &location, const std::str driver.errors_.push_back(error); } +void CYSetArgs(int argc, const char *argv[]) { + JSContextRef context(CYGetJSContext()); + JSValueRef args[argc]; + for (int i(0); i != argc; ++i) + args[i] = CYCastJSValue(context, argv[i]); + JSValueRef exception(NULL); + JSObjectRef array(JSObjectMakeArray(context, argc, args, &exception)); + CYThrow(context, exception); + CYSetProperty(context, System_, CYJSString("args"), array); +} + MSInitialize { _pooled apr_initialize(); @@ -1024,14 +1264,17 @@ MSInitialize { _pooled definition.className = "Selector"; definition.parentClass = Pointer_; //definition.staticValues = Selector_staticValues; + definition.staticFunctions = Selector_staticFunctions; definition.callAsFunction = &Selector_callAsFunction; Selector_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; - definition.className = "Instance_"; + definition.className = "Instance"; definition.getProperty = &Instance_getProperty; + definition.setProperty = &Instance_setProperty; + definition.deleteProperty = &Instance_deleteProperty; definition.callAsConstructor = &Instance_callAsConstructor; - definition.finalize = &Instance_finalize; + //definition.finalize = &Instance_finalize; Instance_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; @@ -1043,11 +1286,19 @@ MSInitialize { _pooled JSObjectRef global(JSContextGetGlobalObject(context)); - CYSetProperty(context, global, CYJSString("SEL"), JSObjectMakeConstructor(context, Selector_, &sel)); - CYSetProperty(context, global, CYJSString("ffi"), JSObjectMakeConstructor(context, Functor_, &ffi)); + CYSetProperty(context, global, CYJSString("Selector"), JSObjectMakeConstructor(context, Selector_, &Selector_new)); + CYSetProperty(context, global, CYJSString("Functor"), JSObjectMakeConstructor(context, Functor_, &Functor_new)); + CYSetProperty(context, global, CYJSString("CYApplicationMain"), JSObjectMakeFunctionWithCallback(context, CYJSString("CYApplicationMain"), &CYApplicationMain)); CYSetProperty(context, global, CYJSString("objc_msgSend"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_msgSend"), &$objc_msgSend)); + System_ = JSObjectMake(context, NULL, NULL); + CYSetProperty(context, global, CYJSString("system"), System_); + CYSetProperty(context, System_, CYJSString("args"), CYJSNull(context)); + CYSetProperty(context, System_, CYJSString("global"), global); + + CYSetProperty(context, System_, CYJSString("print"), JSObjectMakeFunctionWithCallback(context, CYJSString("print"), &System_print)); + Bridge_ = [[NSMutableDictionary dictionaryWithContentsOfFile:@"/usr/lib/libcycript.plist"] retain]; name_ = JSStringCreateWithUTF8CString("name"); diff --git a/Output.cpp b/Output.cpp index 5471620..a35ab81 100644 --- a/Output.cpp +++ b/Output.cpp @@ -3,10 +3,46 @@ #include #include +_finline CYFlags operator ~(CYFlags rhs) { + return static_cast(~static_cast(rhs)); +} + +_finline CYFlags operator &(CYFlags lhs, CYFlags rhs) { + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + +_finline CYFlags operator |(CYFlags lhs, CYFlags rhs) { + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +_finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) { + return lhs = lhs | rhs; +} + +_finline CYFlags CYLeft(CYFlags flags) { + return flags & ~CYNoTrailer; +} + +_finline CYFlags CYCenter(CYFlags flags) { + return flags & CYNoIn; +} + +_finline CYFlags CYRight(CYFlags flags) { + return flags & (CYNoIn | CYNoTrailer); +} + +bool CYFalse::Value() const { + return false; +} + +bool CYTrue::Value() const { + return true; +} + #define CYPA 16 -void CYAddressOf::Output(std::ostream &out) const { - rhs_->Output(out, 1); +void CYAddressOf::Output(std::ostream &out, CYFlags flags) const { + rhs_->Output(out, 1, CYLeft(flags)); out << ".$()"; } @@ -17,7 +53,7 @@ void CYArgument::Output(std::ostream &out) const { out << ":"; } if (value_ != NULL) - value_->Output(out, false); + value_->Output(out, CYPA, CYNoFlags); if (next_ != NULL) { if (next_->name_ == NULL) out << ','; @@ -27,21 +63,25 @@ void CYArgument::Output(std::ostream &out) const { } } -void CYArray::Output(std::ostream &out) const { +void CYArray::Output(std::ostream &out, CYFlags flags) const { out << '['; if (elements_ != NULL) elements_->Output(out); out << ']'; } -void CYAssignment::Output(std::ostream &out) const { - lhs_->Output(out, Precedence() - 1); +void CYAssignment::Output(std::ostream &out, CYFlags flags) const { + lhs_->Output(out, Precedence() - 1, CYLeft(flags)); out << Operator(); - rhs_->Output(out, Precedence()); + rhs_->Output(out, Precedence(), CYRight(flags)); } -void CYBoolean::Output(std::ostream &out) const { +void CYBoolean::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; out << (Value() ? "true" : "false"); + if ((flags & CYNoTrailer) != 0) + out << ' '; } void CYBreak::Output(std::ostream &out) const { @@ -51,8 +91,8 @@ void CYBreak::Output(std::ostream &out) const { out << ';'; } -void CYCall::Output(std::ostream &out) const { - function_->Output(out, Precedence()); +void CYCall::Output(std::ostream &out, CYFlags flags) const { + function_->Output(out, Precedence(), CYLeft(flags)); out << '('; if (arguments_ != NULL) arguments_->Output(out); @@ -64,13 +104,30 @@ void CYCatch::Output(std::ostream &out) const { code_->Output(out, true); } -void CYCondition::Output(std::ostream &out) const { - test_->Output(out, Precedence() - 1); +void CYClass::Output(std::ostream &out) const { + out << "(function($cys,$cyc,$cym,$cyn,$cyt){"; + out << "$cyc=objc_allocateClassPair($cys,\"" << *name_ << "\",0);"; + out << "$cym=object_getClass($cyc);"; + if (fields_ != NULL) + fields_->Output(out); + if (messages_ != NULL) + messages_->Output(out); + out << "objc_registerClassPair($cyc);"; + out << "})("; + if (super_ != NULL) + super_->Output(out, CYPA, CYNoFlags); + else + out << "null"; + out << ");"; +} + +void CYCondition::Output(std::ostream &out, CYFlags flags) const { + test_->Output(out, Precedence() - 1, CYLeft(flags)); out << '?'; if (true_ != NULL) - true_->Output(out, CYPA); + true_->Output(out, CYPA, CYNoFlags); out << ':'; - false_->Output(out, CYPA); + false_->Output(out, CYPA, CYRight(flags)); } void CYContinue::Output(std::ostream &out) const { @@ -83,7 +140,7 @@ void CYContinue::Output(std::ostream &out) const { void CYClause::Output(std::ostream &out) const { if (case_ != NULL) { out << "case"; - case_->Output(out); + case_->Output(out, CYNoFlags); } else out << "default"; out << ':'; @@ -92,6 +149,7 @@ void CYClause::Output(std::ostream &out) const { out << *next_; } +// XXX: deal with NoIn void CYDeclaration::Part(std::ostream &out) const { out << "var "; Output(out); @@ -101,10 +159,11 @@ void CYDeclaration::Output(std::ostream &out) const { out << *identifier_; if (initialiser_ != NULL) { out << '='; - initialiser_->Output(out, CYPA); + initialiser_->Output(out, CYPA, CYNoFlags); } } +// XXX: deal with NoIn void CYDeclarations::Part(std::ostream &out) const { out << "var "; @@ -125,16 +184,17 @@ void CYDeclarations::Output(std::ostream &out) const { } void CYDoWhile::Output(std::ostream &out) const { + // XXX: extra space character! out << "do "; code_->Output(out, false); out << "while("; - test_->Output(out); - out << ';'; + test_->Output(out, CYNoFlags); + out << ')'; } void CYElement::Output(std::ostream &out) const { if (value_ != NULL) - value_->Output(out, CYPA); + value_->Output(out, CYPA, CYNoFlags); if (next_ != NULL || value_ == NULL) out << ','; if (next_ != NULL) @@ -153,34 +213,42 @@ void CYEmpty::Output(std::ostream &out, bool block) const { } void CYExpress::Output(std::ostream &out) const { - expression_->Output(out); + expression_->Output(out, CYNoFunction | CYNoBrace); out << ';'; } void CYExpression::Part(std::ostream &out) const { - // XXX: this should notice "in" expressions // XXX: this should handle LeftHandSideExpression - Output(out); + Output(out, CYNoIn); } -void CYCompound::Output(std::ostream &out) const { +void CYCompound::Output(std::ostream &out, CYFlags flags) const { if (CYExpression *expression = expressions_) - for (;;) { - expression->Output(out); - expression = expression->next_; - if (expression == NULL) - break; - out << ','; + if (CYExpression *next = expression->next_) + expression->Output(out, flags); + else { + expression->Output(out, CYLeft(flags)); + CYFlags center(CYCenter(flags)); + while (next != NULL) { + out << ','; + next = expression->next_; + CYFlags right(next != NULL ? center : CYRight(flags)); + expression->Output(out, right); + } } } -void CYExpression::Output(std::ostream &out, unsigned precedence) const { - bool protect(precedence < Precedence()); - if (protect) +void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const { + if (precedence < Precedence()) { out << '('; - Output(out); - if (protect) + Output(out, CYNoFlags); out << ')'; + } else + Output(out, flags); +} + +void CYField::Output(std::ostream &out) const { + // XXX: implement! } void CYFor::Output(std::ostream &out) const { @@ -189,10 +257,10 @@ void CYFor::Output(std::ostream &out) const { initialiser_->Part(out); out << ';'; if (test_ != NULL) - test_->Output(out); + test_->Output(out, CYNoFlags); out << ';'; if (increment_ != NULL) - increment_->Output(out); + increment_->Output(out, CYNoFlags); out << ')'; code_->Output(out, false); } @@ -200,19 +268,29 @@ void CYFor::Output(std::ostream &out) const { void CYForIn::Output(std::ostream &out) const { out << "for("; initialiser_->Part(out); - out << " in "; - set_->Output(out); + // XXX: deal with this space character! + out << ' '; + out << "in"; + set_->Output(out, CYNoLeader); out << ')'; code_->Output(out, false); } void CYFunction::Output(std::ostream &out) const { - CYLambda::Output(out); + CYLambda::Output(out, CYNoFlags); +} + +void CYFunctionParameter::Output(std::ostream &out) const { + out << *name_; + if (next_ != NULL) { + out << ','; + out << *next_; + } } void CYIf::Output(std::ostream &out) const { out << "if("; - test_->Output(out); + test_->Output(out, CYNoFlags); out << ')'; true_->Output(out, true); if (false_ != NULL) { @@ -221,106 +299,141 @@ void CYIf::Output(std::ostream &out) const { } } -void CYIndirect::Output(std::ostream &out) const { - rhs_->Output(out, 1); +void CYIndirect::Output(std::ostream &out, CYFlags flags) const { + rhs_->Output(out, 1, CYLeft(flags)); out << "[0]"; } -void CYInfix::Output(std::ostream &out) const { - lhs_->Output(out, Precedence()); - out << Operator(); - rhs_->Output(out, Precedence() - 1); +void CYInfix::Output(std::ostream &out, CYFlags flags) const { + const char *name(Operator()); + bool protect((flags & CYNoIn) != 0 && strcmp(name, "in")); + if (protect) + out << '('; + bool alphabetic(Alphabetic()); + CYFlags left(protect ? CYNoFlags : CYLeft(flags)); + if (alphabetic) + left |= CYNoTrailer; + lhs_->Output(out, Precedence(), left); + out << name; + CYFlags right(protect ? CYNoFlags : CYRight(flags)); + if (alphabetic) + right |= CYNoLeader; + rhs_->Output(out, Precedence() - 1, right); + if (protect) + out << ')'; } -void CYLambda::Output(std::ostream &out) const { +void CYLambda::Output(std::ostream &out, CYFlags flags) const { + bool protect((flags & CYNoFunction) != 0); + if (protect) + out << '('; out << "function"; if (name_ != NULL) out << ' ' << *name_; out << '('; if (parameters_ != NULL) out << *parameters_; - out << ')'; - body_->Output(out, true); + out << "){"; + if (body_ != NULL) + body_->Show(out); + out << '}'; + if (protect) + out << ')'; } -void CYMember::Output(std::ostream &out) const { - object_->Output(out, Precedence()); +void CYMember::Output(std::ostream &out, CYFlags flags) const { + object_->Output(out, Precedence(), CYLeft(flags)); if (const char *word = property_->Word()) out << '.' << word; else { out << '['; - property_->Output(out); + property_->Output(out, CYNoFlags); out << ']'; } } void CYMessage::Output(std::ostream &out) const { - out << "objc_msgSend("; - self_->Output(out, CYPA); - out << ",\""; - for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) - if (argument->name_ != NULL) { - out << *argument->name_; - if (argument->value_ != NULL) + out << "$cyn=new Selector(\""; + for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_) + if (parameter->tag_ != NULL) { + out << *parameter->tag_; + if (parameter->name_ != NULL) out << ':'; } - out << "\""; - for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) - if (argument->value_ != NULL) { - out << ","; - argument->value_->Output(out, CYPA); + out << "\");"; + out << "$cyt=$cyn.type($cys," << (instance_ ? "true" : "false") << ");"; + out << "class_addMethod($cy" << (instance_ ? 'c' : 'm') << ",$cyn,"; + out << "new Functor(function("; + bool comma(false); + for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_) + if (parameter->name_ != NULL) { + if (comma) + out << ','; + else + comma = true; + out << *parameter->name_; } - out << ')'; + out << "){"; + if (body_ != NULL) + body_->Show(out); + out << "},$cyt),$cyt);"; } -void CYNew::Output(std::ostream &out) const { +void CYNew::Output(std::ostream &out, CYFlags flags) const { out << "new"; - // XXX: I don't /always/ need this character - out << ' '; - constructor_->Output(out, Precedence()); + constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader); out << '('; if (arguments_ != NULL) arguments_->Output(out); out << ')'; } -void CYNull::Output(std::ostream &out) const { +void CYNull::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; CYWord::Output(out); + if ((flags & CYNoTrailer) != 0) + out << ' '; } -void CYNumber::Output(std::ostream &out) const { +void CYNumber::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; // XXX: this is not a useful formatting out << Value(); + if ((flags & CYNoTrailer) != 0) + out << ' '; } -void CYObject::Output(std::ostream &out) const { +void CYObject::Output(std::ostream &out, CYFlags flags) const { + bool protect((flags & CYNoBrace) != 0); + if (protect) + out << '('; out << '{'; if (property_ != NULL) property_->Output(out); out << '}'; + if (protect) + out << ')'; } -void CYParameter::Output(std::ostream &out) const { - out << *name_; - if (next_ != NULL) { - out << ','; - out << *next_; - } -} - -void CYPostfix::Output(std::ostream &out) const { - lhs_->Output(out, Precedence()); +void CYPostfix::Output(std::ostream &out, CYFlags flags) const { + lhs_->Output(out, Precedence(), CYLeft(flags)); out << Operator(); } -void CYPrefix::Output(std::ostream &out) const { +void CYPrefix::Output(std::ostream &out, CYFlags flags) const { + bool alphabetic(Alphabetic()); out << Operator(); - rhs_->Output(out, Precedence()); + CYFlags right(CYRight(flags)); + if (alphabetic) + right |= CYNoLeader; + rhs_->Output(out, Precedence(), right); } void CYProperty::Output(std::ostream &out) const { out << *name_ << ':'; - value_->Output(out, CYPA); + value_->Output(out, CYPA, CYNoFlags); if (next_ != NULL) { out << ','; next_->Output(out); @@ -329,15 +442,13 @@ void CYProperty::Output(std::ostream &out) const { void CYReturn::Output(std::ostream &out) const { out << "return"; - if (value_ != NULL) { - out << ' '; - value_->Output(out); - } + if (value_ != NULL) + value_->Output(out, CYNoLeader); out << ';'; } -void CYSelector::Output(std::ostream &out) const { - out << "new SEL(\""; +void CYSelector::Output(std::ostream &out, CYFlags flags) const { + out << "new Selector(\""; if (name_ != NULL) name_->Output(out); out << "\")"; @@ -352,9 +463,28 @@ void CYSelectorPart::Output(std::ostream &out) const { next_->Output(out); } +void CYSend::Output(std::ostream &out, CYFlags flags) const { + out << "objc_msgSend("; + self_->Output(out, CYPA, CYNoFlags); + out << ",\""; + for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) + if (argument->name_ != NULL) { + out << *argument->name_; + if (argument->value_ != NULL) + out << ':'; + } + out << "\""; + for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) + if (argument->value_ != NULL) { + out << ","; + argument->value_->Output(out, CYPA, CYNoFlags); + } + out << ')'; +} + void CYSource::Show(std::ostream &out) const { for (const CYSource *next(this); next != NULL; next = next->next_) - next->Output(out, false); + next->Output(out); } void CYSource::Output(std::ostream &out, bool block) const { @@ -367,7 +497,7 @@ void CYSource::Output(std::ostream &out, bool block) const { } } -void CYString::Output(std::ostream &out) const { +void CYString::Output(std::ostream &out, CYFlags flags) const { out << '\"'; for (const char *value(value_), *end(value_ + size_); value != end; ++value) switch (*value) { @@ -391,23 +521,25 @@ void CYString::Output(std::ostream &out) const { void CYSwitch::Output(std::ostream &out) const { out << "switch("; - value_->Output(out); + value_->Output(out, CYNoFlags); out << "){"; if (clauses_ != NULL) out << *clauses_; out << '}'; } -void CYThis::Output(std::ostream &out) const { +void CYThis::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; CYWord::Output(out); + if ((flags & CYNoTrailer) != 0) + out << ' '; } void CYThrow::Output(std::ostream &out) const { out << "throw"; - if (value_ != NULL) { - out << ' '; - value_->Output(out); - } + if (value_ != NULL) + value_->Output(out, CYNoLeader); out << ';'; } @@ -422,20 +554,25 @@ void CYTry::Output(std::ostream &out) const { } } -void CYVariable::Output(std::ostream &out) const { +void CYVariable::Output(std::ostream &out, CYFlags flags) const { + bool protect((flags & CYNoLeader) != 0); + if (protect) + out << '('; out << *name_; + if (protect) + out << ')'; } void CYWhile::Output(std::ostream &out) const { out << "while("; - test_->Output(out); + test_->Output(out, CYNoFlags); out << ')'; code_->Output(out, false); } void CYWith::Output(std::ostream &out) const { out << "with("; - scope_->Output(out); + scope_->Output(out, CYNoFlags); out << ')'; code_->Output(out, false); } diff --git a/Parser.hpp b/Parser.hpp index 643833f..9daf63e 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -153,6 +153,15 @@ struct CYForInInitialiser : { }; +enum CYFlags { + CYNoFlags, + CYNoBrace, + CYNoFunction, + CYNoLeader, + CYNoTrailer, + CYNoIn +}; + struct CYExpression : CYNext, CYForInitialiser, @@ -160,14 +169,19 @@ struct CYExpression : { virtual unsigned Precedence() const = 0; virtual void Part(std::ostream &out) const; - virtual void Output(std::ostream &out) const = 0; - void Output(std::ostream &out, unsigned precedence) const; + virtual void Output(std::ostream &out, CYFlags flags) const = 0; + void Output(std::ostream &out, unsigned precedence, CYFlags flags) const; virtual const char *Word() const { return NULL; } }; +#define CYAlphabetic(value) \ + virtual bool Alphabetic() const { \ + return value; \ + } + #define CYPrecedence(value) \ virtual unsigned Precedence() const { \ return value; \ @@ -193,7 +207,7 @@ struct CYCompound : CYPrecedence(17) - void Output(std::ostream &out) const; + void Output(std::ostream &out, CYFlags flags) const; }; struct CYLiteral : @@ -230,7 +244,7 @@ struct CYSelector : CYPrecedence(1) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYRange { @@ -292,7 +306,11 @@ struct CYString : return Value(); } - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out) const { + return Output(out, CYNoFlags); + } + + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYNumber : @@ -314,7 +332,11 @@ struct CYNumber : throw; } - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out) const { + return Output(out, CYNoFlags); + } + + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYNull : @@ -326,7 +348,7 @@ struct CYNull : { } - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYThis : @@ -340,14 +362,14 @@ struct CYThis : CYPrecedence(0) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYBoolean : CYLiteral { virtual bool Value() const = 0; - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYFalse : @@ -359,9 +381,7 @@ struct CYFalse : { } - virtual bool Value() const { - return false; - } + virtual bool Value() const; }; struct CYTrue : @@ -373,9 +393,7 @@ struct CYTrue : { } - virtual bool Value() const { - return true; - } + virtual bool Value() const; }; struct CYVariable : @@ -390,7 +408,7 @@ struct CYVariable : CYPrecedence(0) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYPrefix : @@ -403,9 +421,10 @@ struct CYPrefix : { } + virtual bool Alphabetic() const = 0; virtual const char *Operator() const = 0; - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYInfix : @@ -420,9 +439,10 @@ struct CYInfix : { } + virtual bool Alphabetic() const = 0; virtual const char *Operator() const = 0; - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYPostfix : @@ -437,7 +457,7 @@ struct CYPostfix : virtual const char *Operator() const = 0; - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYAssignment : @@ -454,7 +474,7 @@ struct CYAssignment : virtual const char *Operator() const = 0; - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYArgument : @@ -522,7 +542,7 @@ struct CYArray : { } - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYDeclaration : @@ -559,14 +579,73 @@ struct CYDeclarations : virtual void Output(std::ostream &out) const; }; -struct CYParameter : - CYNext, +struct CYField : + CYNext +{ + virtual void Output(std::ostream &out) const; +}; + +struct CYMessageParameter : + CYNext +{ + CYWord *tag_; + CYExpression *type_; + CYIdentifier *name_; + + CYMessageParameter(CYWord *tag, CYExpression *type, CYIdentifier *name) : + tag_(tag), + type_(type), + name_(name) + { + } +}; + +struct CYMessage : + CYSource +{ + bool instance_; + CYExpression *type_; + CYMessageParameter *parameter_; + CYSource *body_; + + CYMessage(bool instance, CYExpression *type, CYMessageParameter *parameter, CYSource *body) : + instance_(instance), + type_(type), + parameter_(parameter), + body_(body) + { + } + + virtual void Output(std::ostream &out) const; +}; + +struct CYClass : + CYSource +{ + CYIdentifier *name_; + CYExpression *super_; + CYField *fields_; + CYMessage *messages_; + + CYClass(CYIdentifier *name, CYExpression *super, CYField *fields, CYMessage *messages) : + name_(name), + super_(super), + fields_(fields), + messages_(messages) + { + } + + virtual void Output(std::ostream &out) const; +}; + +struct CYFunctionParameter : + CYNext, CYThing { CYIdentifier *name_; - CYParameter(CYIdentifier *name, CYParameter *next) : - CYNext(next), + CYFunctionParameter(CYIdentifier *name, CYFunctionParameter *next) : + CYNext(next), name_(name) { } @@ -636,7 +715,7 @@ struct CYObject : { } - void Output(std::ostream &out) const; + void Output(std::ostream &out, CYFlags flags) const; }; struct CYCatch : @@ -654,13 +733,13 @@ struct CYCatch : virtual void Output(std::ostream &out) const; }; -struct CYMessage : +struct CYSend : CYExpression { CYExpression *self_; CYArgument *arguments_; - CYMessage(CYExpression *self, CYArgument *arguments) : + CYSend(CYExpression *self, CYArgument *arguments) : self_(self), arguments_(arguments) { @@ -668,7 +747,7 @@ struct CYMessage : CYPrecedence(0) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYMember : @@ -685,7 +764,7 @@ struct CYMember : CYPrecedence(1) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYNew : @@ -702,7 +781,7 @@ struct CYNew : CYPrecedence(1) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYCall : @@ -719,7 +798,7 @@ struct CYCall : CYPrecedence(2) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYIf : @@ -773,10 +852,10 @@ struct CYLambda : CYExpression { CYIdentifier *name_; - CYParameter *parameters_; + CYFunctionParameter *parameters_; CYSource *body_; - CYLambda(CYIdentifier *name, CYParameter *parameters, CYSource *body) : + CYLambda(CYIdentifier *name, CYFunctionParameter *parameters, CYSource *body) : name_(name), parameters_(parameters), body_(body) @@ -785,14 +864,14 @@ struct CYLambda : CYPrecedence(0) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYFunction : CYLambda, CYSource { - CYFunction(CYIdentifier *name, CYParameter *parameters, CYSource *body) : + CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYSource *body) : CYLambda(name, parameters, body) { } @@ -935,7 +1014,7 @@ struct CYCondition : CYPrecedence(15) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYAddressOf : @@ -950,9 +1029,10 @@ struct CYAddressOf : return "&"; } + CYAlphabetic(false) CYPrecedence(2) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYIndirect : @@ -967,9 +1047,10 @@ struct CYIndirect : return "*"; } + CYAlphabetic(false) CYPrecedence(1) - virtual void Output(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; }; #define CYPostfix_(op, name) \ @@ -988,7 +1069,7 @@ struct CYIndirect : } \ }; -#define CYPrefix_(op, name) \ +#define CYPrefix_(alphabetic, op, name) \ struct CY ## name : \ CYPrefix \ { \ @@ -997,6 +1078,7 @@ struct CYIndirect : { \ } \ \ + CYAlphabetic(alphabetic) \ CYPrecedence(4) \ \ virtual const char *Operator() const { \ @@ -1004,7 +1086,7 @@ struct CYIndirect : } \ }; -#define CYInfix_(precedence, op, name) \ +#define CYInfix_(alphabetic, precedence, op, name) \ struct CY ## name : \ CYInfix \ { \ @@ -1013,6 +1095,7 @@ struct CYIndirect : { \ } \ \ + CYAlphabetic(alphabetic) \ CYPrecedence(precedence) \ \ virtual const char *Operator() const { \ @@ -1039,38 +1122,38 @@ struct CYIndirect : CYPostfix_("++", PostIncrement) CYPostfix_("--", PostDecrement) -CYPrefix_("delete", Delete) -CYPrefix_("void", Void) -CYPrefix_("typeof", TypeOf) -CYPrefix_("++", PreIncrement) -CYPrefix_("--", PreDecrement) -CYPrefix_("-", Negate) -CYPrefix_("~", BitwiseNot) -CYPrefix_("!", LogicalNot) - -CYInfix_(5, "*", Multiply) -CYInfix_(5, "/", Divide) -CYInfix_(5, "%", Modulus) -CYInfix_(6, "+", Add) -CYInfix_(6, "-", Subtract) -CYInfix_(7, "<<", ShiftLeft) -CYInfix_(7, ">>", ShiftRightSigned) -CYInfix_(7, ">>>", ShiftRightUnsigned) -CYInfix_(8, "<", Less) -CYInfix_(8, ">", Greater) -CYInfix_(8, "<=", LessOrEqual) -CYInfix_(8, ">=", GreaterOrEqual) -CYInfix_(8, "instanceof", InstanceOf) -CYInfix_(8, "in", In) -CYInfix_(9, "==", Equal) -CYInfix_(9, "!=", NotEqual) -CYInfix_(9, "===", Identical) -CYInfix_(9, "!==", NotIdentical) -CYInfix_(10, "&", BitwiseAnd) -CYInfix_(11, "^", BitwiseXOr) -CYInfix_(12, "|", BitwiseOr) -CYInfix_(13, "&&", LogicalAnd) -CYInfix_(14, "||", LogicalOr) +CYPrefix_(true, "delete", Delete) +CYPrefix_(true, "void", Void) +CYPrefix_(true, "typeof", TypeOf) +CYPrefix_(false, "++", PreIncrement) +CYPrefix_(false, "--", PreDecrement) +CYPrefix_(false, "-", Negate) +CYPrefix_(false, "~", BitwiseNot) +CYPrefix_(false, "!", LogicalNot) + +CYInfix_(false, 5, "*", Multiply) +CYInfix_(false, 5, "/", Divide) +CYInfix_(false, 5, "%", Modulus) +CYInfix_(false, 6, "+", Add) +CYInfix_(false, 6, "-", Subtract) +CYInfix_(false, 7, "<<", ShiftLeft) +CYInfix_(false, 7, ">>", ShiftRightSigned) +CYInfix_(false, 7, ">>>", ShiftRightUnsigned) +CYInfix_(false, 8, "<", Less) +CYInfix_(false, 8, ">", Greater) +CYInfix_(false, 8, "<=", LessOrEqual) +CYInfix_(false, 8, ">=", GreaterOrEqual) +CYInfix_(true, 8, "instanceof", InstanceOf) +CYInfix_(true, 8, "in", In) +CYInfix_(false, 9, "==", Equal) +CYInfix_(false, 9, "!=", NotEqual) +CYInfix_(false, 9, "===", Identical) +CYInfix_(false, 9, "!==", NotIdentical) +CYInfix_(false, 10, "&", BitwiseAnd) +CYInfix_(false, 11, "^", BitwiseXOr) +CYInfix_(false, 12, "|", BitwiseOr) +CYInfix_(false, 13, "&&", LogicalAnd) +CYInfix_(false, 14, "||", LogicalOr) CYAssignment_("=", ) CYAssignment_("*=", Multiply) diff --git a/cycript.hpp b/cycript.hpp index 7fd159c..2edea84 100644 --- a/cycript.hpp +++ b/cycript.hpp @@ -5,15 +5,12 @@ #include #endif -#include -#include -#include -#include -#include +#include #include JSContextRef CYGetJSContext(); CFStringRef CYCopyJSONString(JSContextRef context, JSValueRef value); +void CYSetArgs(int argc, const char *argv[]); #ifdef __OBJC__ void CYThrow(JSContextRef context, id error, JSValueRef *exception); diff --git a/documents.txt b/documents.txt index 5371ac8..2d31216 100644 --- a/documents.txt +++ b/documents.txt @@ -1,3 +1,6 @@ http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html - http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html - http://www.webweavertech.com/ovidiu/Objective-C/objc-features_3.html +http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html +http://www.webweavertech.com/ovidiu/Objective-C/objc-features_3.html + +http://www.mail-archive.com/es-discuss@mozilla.org/msg00999.html +http://www.mail-archive.com/es-discuss@mozilla.org/msg01025.html diff --git a/makefile b/makefile index d178765..1eb6f99 100644 --- a/makefile +++ b/makefile @@ -15,16 +15,19 @@ clean: rm -f *.o libcycript.dylib cycript libcycript.plist Struct.hpp lex.cy.c Cycript.tab.cc Cycript.tab.hh location.hh position.hh stack.hh libcycript.plist: Bridge.def - sed -e 's/^C/0/;s/^F/1/;s/^V/2/' Bridge.def | while read -r line; do \ - if [[ $$line == '' ]]; then \ - continue; \ - fi; \ - set $$line; \ - if [[ $$1 =~ [#fl] ]]; then \ - continue; \ - fi; \ - echo "$$2 = ($$1, \"$$3\");"; \ - done >$@ + { \ + sed -e 's/^C/0/;s/^F/1/;s/^V/2/' Bridge.def | while read -r line; do \ + if [[ $$line == '' ]]; then \ + continue; \ + fi; \ + set $$line; \ + if [[ $$1 =~ [#fl:] ]]; then \ + continue; \ + fi; \ + echo "$$2 = ($$1, \"$$3\");"; \ + done; \ + grep ^: Bridge.def | sed -e 's/^: \([^ ]*\) \(.*\)/":\1" = "\2";/'; \ + } >$@ Cycript.tab.cc Cycript.tab.hh location.hh position.hh: Cycript.y bison -v --report=state $< @@ -57,7 +60,7 @@ Application.o: Application.mm Cycript.tab.hh Parser.hpp Pooling.hpp cycript.hpp $(target)g++ $(flags) -c -o $@ $< libcycript.dylib: ffi_type.o parse.o Output.o Cycript.tab.o lex.cy.o Library.o - $(target)g++ $(flags) -dynamiclib -o $@ $(filter %.o,$^) -lobjc -framework CFNetwork -framework JavaScriptCore -framework WebCore -install_name /usr/lib/libcycript.dylib -framework CoreFoundation -framework Foundation -L$(menes)/mobilesubstrate -lsubstrate -lapr-1 -lffi + $(target)g++ $(flags) -dynamiclib -o $@ $(filter %.o,$^) -lobjc -framework CFNetwork -framework JavaScriptCore -framework WebCore -install_name /usr/lib/libcycript.dylib -framework CoreFoundation -framework Foundation -L$(menes)/mobilesubstrate -lsubstrate -lapr-1 -lffi -framework UIKit ldid -S $@ cycript: Application.o libcycript.dylib @@ -85,6 +88,6 @@ package: all test: package dpkg -i $(shell grep ^Package: control | cut -d ' ' -f 2-)_$(shell grep ^Version: control | cut -d ' ' -f 2)_iphoneos-arm.deb - cycript + cycript /Applications/HelloCycript.app/HelloCycript .PHONY: all clean extra package -- 2.47.2