From 367eebb166684de7a659b4e9cd34565b62b7928d Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Sun, 18 Oct 2009 10:32:51 +0000 Subject: [PATCH] Started work on array comprehensions, implemented multi-line string literals (not for console yet), and refactored @class to be an expression (with support for anonymous classes). --- Cycript.l | 3 ++- Cycript.y | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ Library.mm | 9 +++++++++ Output.cpp | 27 +++++++++++++++++++-------- Parser.hpp | 18 ++++++++++-------- todo.txt | 1 + 6 files changed, 87 insertions(+), 23 deletions(-) diff --git a/Cycript.l b/Cycript.l index 2ab8f0c..66f38ce 100644 --- a/Cycript.l +++ b/Cycript.l @@ -61,7 +61,7 @@ int H(char c) { %option reentrant Exponent [eE][+-]?[0-9]+ -Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4} +Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n %% @@ -204,6 +204,7 @@ Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4} if (yytext[i] == '\\') switch (next = yytext[++i]) { + case '\n': continue; case '\\': next = '\\'; break; case '\'': next = '\''; break; case '"': next = '"'; break; diff --git a/Cycript.y b/Cycript.y index 2572473..dd0ea51 100644 --- a/Cycript.y +++ b/Cycript.y @@ -269,10 +269,12 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type CaseClause %type CaseClausesOpt %type CatchOpt -%type ClassDeclaration +%type CategoryStatement +%type ClassExpression %type ClassMessageDeclaration %type ClassMessageDeclarationListOpt %type ClassName +%type ClassNameOpt %type ClassSuperOpt %type ClassFieldList %type ConditionalExpression @@ -1244,13 +1246,25 @@ ClassName | "(" AssignmentExpression ")" { $$ = $2; } ; -ClassDeclaration - : "@class" Identifier ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new CYClass($2, $3, $4, $5); } - | "@class" ClassName ClassMessageDeclarationListOpt "@end" { $$ = new CYCategory($2, $3); } +ClassNameOpt + : ClassName { $$ = $1; } + | { $$ = NULL; } ; -SourceElement - : ClassDeclaration { $$ = $1; } +ClassExpression + : "@class" ClassNameOpt ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new CYClass($2, $3, $4, $5); } + ; + +CategoryStatement + : "@class" ClassName ClassMessageDeclarationListOpt "@end" { $$ = new CYCategory($2, $3); } + ; + +PrimaryExpression_ + : ClassExpression { $$ = $1; } + ; + +Statement + : CategoryStatement ; VariadicCall @@ -1308,4 +1322,30 @@ MemberAccess : "->" Identifier { $$ = new(driver.pool_) CYIndirectMember(NULL, new(driver.pool_) CYString($2)); } ; +/* + +IfComprehension + : "if" "(" Expression ")" + ; + +ForComprehension + : "for" "(" ForInStatementInitialiser "in" Expression ")" + ; + +ComprehensionListOpt + : ComprehensionList + | IfComprehension + | + ; + +ComprehensionList + : ForComprehension ComprehensionListOpt + ; + +PrimaryExpression_ + : "[" AssignmentExpression ComprehensionList "]" + ; + +*/ + %% diff --git a/Library.mm b/Library.mm index 92e43ed..89ed137 100644 --- a/Library.mm +++ b/Library.mm @@ -2710,6 +2710,14 @@ JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, SEL _c return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, exception, &signature, &cif, function); } +static size_t Nonce_(0); + +static JSValueRef $cyq(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + char name[16]; + sprintf(name, "%s%zu", CYCastCString(context, arguments[0]), Nonce_++); + return CYCastJSValue(context, name); +} + static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYPool pool; @@ -3468,6 +3476,7 @@ JSGlobalContextRef CYGetJSContext() { CYSetProperty(context, global, CYJSString("objc_registerClassPair"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_registerClassPair"), &objc_registerClassPair_)); CYSetProperty(context, global, CYJSString("objc_msgSend"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_msgSend"), &$objc_msgSend)); + CYSetProperty(context, global, CYJSString("$cyq"), JSObjectMakeFunctionWithCallback(context, CYJSString("$cyq"), &$cyq)); System_ = JSObjectMake(context, NULL, NULL); CYSetProperty(context, global, CYJSString("system"), System_); diff --git a/Output.cpp b/Output.cpp index f15b90d..3fc3355 100644 --- a/Output.cpp +++ b/Output.cpp @@ -119,26 +119,33 @@ void CYCategory::Output(std::ostream &out) const { if (messages_ != NULL) messages_->Output(out, true); out << "})("; - name_->ClassName(out); + name_->ClassName(out, true); out << ");"; } -void CYClass::Output(std::ostream &out) const { +void CYClass::Output(std::ostream &out, CYFlags flags) const { + // XXX: I don't necc. need the ()s out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){"; out << "$cyp=object_getClass($cys);"; - out << "$cyc=objc_allocateClassPair($cys,\"" << *name_ << "\",0);"; + out << "$cyc=objc_allocateClassPair($cys,"; + if (name_ != NULL) + name_->ClassName(out, false); + else + out << "$cyq(\"CY$\")"; + out << ",0);"; out << "$cym=object_getClass($cyc);"; if (fields_ != NULL) fields_->Output(out); if (messages_ != NULL) messages_->Output(out, false); out << "objc_registerClassPair($cyc);"; - out << "})("; + out << "return $cyc;"; + out << "}("; if (super_ != NULL) super_->Output(out, CYPA, CYNoFlags); else out << "null"; - out << ");"; + out << "))"; } void CYCompound::Output(std::ostream &out, CYFlags flags) const { @@ -264,7 +271,7 @@ void CYExpress::Output(std::ostream &out) const { out << ';'; } -void CYExpression::ClassName(std::ostream &out) const { +void CYExpression::ClassName(std::ostream &out, bool object) const { Output(out, CYPA, CYNoFlags); } @@ -663,8 +670,12 @@ void CYWith::Output(std::ostream &out) const { code_->Output(out, false); } -void CYWord::ClassName(std::ostream &out) const { - out << "objc_getClass(\"" << Value() << "\")"; +void CYWord::ClassName(std::ostream &out, bool object) const { + if (object) + out << "objc_getClass("; + out << '"' << Value() << '"'; + if (object) + out << ')'; } void CYWord::Output(std::ostream &out) const { diff --git a/Parser.hpp b/Parser.hpp index fc5abf1..2e872a9 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -93,7 +93,7 @@ struct CYPropertyName { }; struct CYClassName { - virtual void ClassName(std::ostream &out) const = 0; + virtual void ClassName(std::ostream &out, bool object) const = 0; }; struct CYWord : @@ -114,7 +114,7 @@ struct CYWord : virtual void Output(std::ostream &out) const; - virtual void ClassName(std::ostream &out) const; + virtual void ClassName(std::ostream &out, bool object) const; virtual void PropertyName(std::ostream &out) const; }; @@ -246,7 +246,7 @@ struct CYExpression : virtual void Output(std::ostream &out, CYFlags flags) const = 0; void Output(std::ostream &out, unsigned precedence, CYFlags flags) const; - virtual void ClassName(std::ostream &out) const; + virtual void ClassName(std::ostream &out, bool object) const; virtual const char *Word() const { return NULL; @@ -703,14 +703,14 @@ struct CYMessage : }; struct CYClass : - CYSource + CYExpression { - CYIdentifier *name_; + CYClassName *name_; CYExpression *super_; CYField *fields_; CYMessage *messages_; - CYClass(CYIdentifier *name, CYExpression *super, CYField *fields, CYMessage *messages) : + CYClass(CYClassName *name, CYExpression *super, CYField *fields, CYMessage *messages) : name_(name), super_(super), fields_(fields), @@ -718,11 +718,13 @@ struct CYClass : { } - virtual void Output(std::ostream &out) const; + CYPrecedence(0) + + virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYCategory : - CYSource + CYStatement { CYClassName *name_; CYMessage *messages_; diff --git a/todo.txt b/todo.txt index d903383..e8c3584 100644 --- a/todo.txt +++ b/todo.txt @@ -3,3 +3,4 @@ blocks and empty statements are poorly factored unicode identifier support (native and \u) object literal compilation should use numerify strings support unions (right now 0-1 fields parsed as struct) +\\\n escapes in strings aren't handled in the console -- 2.47.2