]> git.saurik.com Git - cycript.git/commitdiff
Added cyrver to make clean, fixed GC protection for CYJS*, implemented array comprehe...
authorJay Freeman (saurik) <saurik@saurik.com>
Mon, 19 Oct 2009 01:53:13 +0000 (01:53 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Mon, 19 Oct 2009 01:53:13 +0000 (01:53 +0000)
Console.cpp
Cycript.l
Cycript.y
Library.mm
Output.cpp
Parser.hpp
makefile

index fdfc05449ec2c71f41aa71ab64975adfad488557..b3702ca386af74bd734ecf0c8e70566c735b9603 100644 (file)
@@ -218,6 +218,7 @@ static void Console(int socket) {
         else {
             CYDriver driver("");
             cy::parser parser(driver);
         else {
             CYDriver driver("");
             cy::parser parser(driver);
+            //parser.set_debug_level(1);
 
             driver.data_ = command.c_str();
             driver.size_ = command.size();
 
             driver.data_ = command.c_str();
             driver.size_ = command.size();
@@ -301,14 +302,19 @@ static void *Map(const char *path, size_t *psize) {
 int main(int argc, char *argv[]) {
     bool tty(isatty(STDIN_FILENO));
     pid_t pid(_not(pid_t));
 int main(int argc, char *argv[]) {
     bool tty(isatty(STDIN_FILENO));
     pid_t pid(_not(pid_t));
+    bool compile(false);
 
 
-    for (;;) switch (getopt(argc, argv, "p:")) {
+    for (;;) switch (getopt(argc, argv, "cp:")) {
         case -1:
             goto getopt;
         case '?':
         case -1:
             goto getopt;
         case '?':
-            fprintf(stderr, "usage: cycript [-p <pid>] [<script> [<arg>...]]\n");
+            fprintf(stderr, "usage: cycript [-c] [-p <pid>] [<script> [<arg>...]]\n");
             return 1;
 
             return 1;
 
+        case 'c':
+            compile = true;
+        break;
+
         case 'p': {
             size_t size(strlen(optarg));
             char *end;
         case 'p': {
             size_t size(strlen(optarg));
             char *end;
@@ -322,11 +328,16 @@ int main(int argc, char *argv[]) {
 
     const char *script;
 
 
     const char *script;
 
-    if (optind < argc - 1 && pid != _not(pid_t)) {
+    if (pid != _not(pid_t) && optind < argc - 1) {
         fprintf(stderr, "-p cannot set argv\n");
         return 1;
     }
 
         fprintf(stderr, "-p cannot set argv\n");
         return 1;
     }
 
+    if (pid != _not(pid_t) && compile) {
+        fprintf(stderr, "-p conflicts with -c\n");
+        return 1;
+    }
+
     if (optind == argc)
         script = NULL;
     else {
     if (optind == argc)
         script = NULL;
     else {
@@ -398,7 +409,10 @@ int main(int argc, char *argv[]) {
                 std::ostringstream str;
                 driver.source_->Show(str);
                 std::string code(str.str());
                 std::ostringstream str;
                 driver.source_->Show(str);
                 std::string code(str.str());
-                Run(socket, code);
+                if (compile)
+                    std::cout << code;
+                else
+                    Run(socket, code);
             }
     }
 
             }
     }
 
index 66f38cee04f54c703194d62ee62d4c2eb6bf6277..dd6e2042657bc815afaa56c7ac1e2d8b84344ccf 100644 (file)
--- a/Cycript.l
+++ b/Cycript.l
@@ -187,7 +187,9 @@ Escape   \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n
 "transient"    L C yylval->word_ = new CYWord("transient"); return tk::Transient;
 "volatile"     L C yylval->word_ = new CYWord("volatile"); return tk::Volatile;
 
 "transient"    L C yylval->word_ = new CYWord("transient"); return tk::Transient;
 "volatile"     L C yylval->word_ = new CYWord("volatile"); return tk::Volatile;
 
-[a-zA-Z$_][a-zA-Z$_0-9]* yylval->identifier_ = new CYIdentifier(apr_pstrmemdup(yyextra->pool_, yytext, yyleng)); L C return tk::Identifier;
+"each"         L C yylval->word_ = 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_;
 
 (\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?){Exponent}? yylval->number_ = new CYNumber(strtod(yytext, NULL)); L C return tk::NumericLiteral;
 
 
 (\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?){Exponent}? yylval->number_ = new CYNumber(strtod(yytext, NULL)); L C return tk::NumericLiteral;
 
index 1e0f0bf4953b1230f30cbae6fc4832e74288c132..6a355343f8b538d9b3fc8f3baacf2dbedaf82b06 100644 (file)
--- a/Cycript.y
+++ b/Cycript.y
@@ -59,6 +59,7 @@ typedef struct {
         CYCatch *catch_;
         CYClass *class_;
         CYClassName *className_;
         CYCatch *catch_;
         CYClass *class_;
         CYClassName *className_;
+        CYComprehension *comprehension_;
         CYCompound *compound_;
         CYDeclaration *declaration_;
         CYDeclarations *declarations_;
         CYCompound *compound_;
         CYDeclaration *declaration_;
         CYDeclarations *declarations_;
@@ -106,7 +107,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 
 %defines
 
 
 %defines
 
-%debug
+//%debug
 %error-verbose
 
 %parse-param { CYDriver &driver }
 %error-verbose
 
 %parse-param { CYDriver &driver }
@@ -234,7 +235,9 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %token <word_> Transient "transient"
 %token <word_> Volatile "volatile"
 
 %token <word_> Transient "transient"
 %token <word_> Volatile "volatile"
 
-%token <identifier_> Identifier
+%token <identifier_> Each "each"
+
+%token <identifier_> Identifier_
 %token <number_> NumericLiteral
 %token <string_> StringLiteral
 
 %token <number_> NumericLiteral
 %token <string_> StringLiteral
 
@@ -278,6 +281,8 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <className_> ClassNameOpt
 %type <expression_> ClassSuperOpt
 %type <field_> ClassFieldList
 %type <className_> ClassNameOpt
 %type <expression_> ClassSuperOpt
 %type <field_> ClassFieldList
+%type <comprehension_> ComprehensionList
+%type <comprehension_> ComprehensionListOpt
 %type <expression_> ConditionalExpression
 %type <expression_> ConditionalExpressionNoBF
 %type <expression_> ConditionalExpressionNoIn
 %type <expression_> ConditionalExpression
 %type <expression_> ConditionalExpressionNoBF
 %type <expression_> ConditionalExpressionNoIn
@@ -302,6 +307,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <expression_> ExpressionNoInOpt
 %type <statement_> ExpressionStatement
 %type <statement_> FinallyOpt
 %type <expression_> ExpressionNoInOpt
 %type <statement_> ExpressionStatement
 %type <statement_> FinallyOpt
+%type <comprehension_> ForComprehension
 %type <statement_> ForStatement
 %type <for_> ForStatementInitialiser
 %type <statement_> ForInStatement
 %type <statement_> ForStatement
 %type <for_> ForStatementInitialiser
 %type <statement_> ForInStatement
@@ -311,7 +317,9 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <source_> FunctionBody
 %type <source_> FunctionDeclaration
 %type <expression_> FunctionExpression
 %type <source_> FunctionBody
 %type <source_> FunctionDeclaration
 %type <expression_> FunctionExpression
+%type <identifier_> Identifier
 %type <identifier_> IdentifierOpt
 %type <identifier_> IdentifierOpt
+%type <comprehension_> IfComprehension
 %type <statement_> IfStatement
 %type <expression_> Initialiser
 %type <expression_> InitialiserOpt
 %type <statement_> IfStatement
 %type <expression_> Initialiser
 %type <expression_> InitialiserOpt
@@ -505,6 +513,11 @@ Word
     | "with" { $$ = $1; }
     ;
 
     | "with" { $$ = $1; }
     ;
 
+Identifier
+    : Identifier_ { $$ = $1; }
+    | "each" { $$ = $1; }
+    ;
+
 IdentifierOpt
     : Identifier { $$ = $1; }
     | { $$ = NULL; }
 IdentifierOpt
     : Identifier { $$ = $1; }
     | { $$ = NULL; }
@@ -1092,6 +1105,7 @@ ForStatementInitialiser
 
 ForInStatement
     : "for" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForIn($3, $5, $7); }
 
 ForInStatement
     : "for" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForIn($3, $5, $7); }
+    | "for" "each" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForEachIn($4, $6, $8); }
     ;
 
 ForInStatementInitialiser
     ;
 
 ForInStatementInitialiser
@@ -1216,7 +1230,7 @@ TypeOpt
     ;
 
 MessageParameter
     ;
 
 MessageParameter
-    : Word ":" TypeOpt Identifier { $$ = new CYMessageParameter($1, $3, $4); }
+    : Word ":" TypeOpt Identifier { $$ = new(driver.pool_) CYMessageParameter($1, $3, $4); }
     ;
 
 MessageParameterListOpt
     ;
 
 MessageParameterListOpt
@@ -1230,11 +1244,11 @@ MessageParameterList
 
 MessageParameters
     : MessageParameterList { $$ = $1; }
 
 MessageParameters
     : MessageParameterList { $$ = $1; }
-    | Word { $$ = new CYMessageParameter($1, NULL, NULL); }
+    | Word { $$ = new(driver.pool_) CYMessageParameter($1, NULL, NULL); }
     ;
 
 ClassMessageDeclaration
     ;
 
 ClassMessageDeclaration
-    : MessageScope TypeOpt MessageParameters "{" FunctionBody "}" { $$ = new CYMessage($1, $2, $3, $5); }
+    : MessageScope TypeOpt MessageParameters "{" FunctionBody "}" { $$ = new(driver.pool_) CYMessage($1, $2, $3, $5); }
     ;
 
 ClassMessageDeclarationListOpt
     ;
 
 ClassMessageDeclarationListOpt
@@ -1253,11 +1267,11 @@ ClassNameOpt
     ;
 
 ClassDefinition
     ;
 
 ClassDefinition
-    : "@class" ClassNameOpt ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new CYClass($2, $3, $4, $5); }
+    : "@class" ClassNameOpt ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClass($2, $3, $4, $5); }
     ;
 
 CategoryStatement
     ;
 
 CategoryStatement
-    : "@class" ClassName ClassMessageDeclarationListOpt "@end" { $$ = new CYCategory($2, $3); }
+    : "@class" ClassName ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYCategory($2, $3); }
     ;
 
 PrimaryExpression
     ;
 
 PrimaryExpression
@@ -1308,7 +1322,7 @@ SelectorExpression
 
 PrimaryExpression_
     : MessageExpression { $$ = $1; }
 
 PrimaryExpression_
     : MessageExpression { $$ = $1; }
-    | "@selector" "(" SelectorExpression ")" { $$ = new CYSelector($3); }
+    | "@selector" "(" SelectorExpression ")" { $$ = new(driver.pool_) CYSelector($3); }
     ;
 /* }}} */
 
     ;
 /* }}} */
 
@@ -1324,30 +1338,27 @@ MemberAccess
     : "->" Identifier { $$ = new(driver.pool_) CYIndirectMember(NULL, new(driver.pool_) CYString($2)); }
     ;
 
     : "->" Identifier { $$ = new(driver.pool_) CYIndirectMember(NULL, new(driver.pool_) CYString($2)); }
     ;
 
-/*
-
 IfComprehension
 IfComprehension
-    : "if" "(" Expression ")"
+    : "if" "(" Expression ")" { $$ = new(driver.pool_) CYIfComprehension($3); }
     ;
 
 ForComprehension
     ;
 
 ForComprehension
-    : "for" "(" ForInStatementInitialiser "in" Expression ")"
+    : "for" "(" Identifier "in" Expression ")" { $$ = new(driver.pool_) CYForInComprehension($3, $5); }
+    | "for" "each" "(" Identifier "in" Expression ")" { $$ = new(driver.pool_) CYForEachInComprehension($4, $6); }
     ;
 
 ComprehensionListOpt
     ;
 
 ComprehensionListOpt
-    : ComprehensionList
-    | IfComprehension
-    |
+    : ComprehensionList { $$ = $1; }
+    | IfComprehension { $$ = $1; }
+    | { $$ = NULL; }
     ;
 
 ComprehensionList
     ;
 
 ComprehensionList
-    : ForComprehension ComprehensionListOpt
+    : ForComprehension ComprehensionListOpt { $1->SetNext($2); $$ = $1; }
     ;
 
 PrimaryExpression_
     ;
 
 PrimaryExpression_
-    : "[" AssignmentExpression ComprehensionList "]"
+    : "[" AssignmentExpression ComprehensionList "]" { $$ = new(driver.pool_) CYArrayComprehension($2, $3); }
     ;
 
     ;
 
-*/
-
 %%
 %%
index 66c752341ad090c760ef1275f79243dc780a6a48..61eafe18caa5bf1e2856b2b8e34275934df3320c 100644 (file)
@@ -1475,9 +1475,15 @@ bool CYIsCallable(JSContextRef context, JSValueRef value) {
     if ((self = [super init]) != nil) {
         object_ = object;
         context_ = context;
     if ((self = [super init]) != nil) {
         object_ = object;
         context_ = context;
+        JSValueProtect(context_, object_);
     } return self;
 }
 
     } return self;
 }
 
+- (void) dealloc {
+    JSValueUnprotect(context_, object_);
+    [super dealloc];
+}
+
 - (NSObject *) cy$toJSON:(NSString *)key {
     JSValueRef toJSON(CYGetProperty(context_, object_, toJSON_));
     if (!CYIsCallable(context_, toJSON))
 - (NSObject *) cy$toJSON:(NSString *)key {
     JSValueRef toJSON(CYGetProperty(context_, object_, toJSON_));
     if (!CYIsCallable(context_, toJSON))
@@ -1538,9 +1544,15 @@ bool CYIsCallable(JSContextRef context, JSValueRef value) {
     if ((self = [super init]) != nil) {
         object_ = object;
         context_ = context;
     if ((self = [super init]) != nil) {
         object_ = object;
         context_ = context;
+        JSValueProtect(context_, object_);
     } return self;
 }
 
     } return self;
 }
 
+- (void) dealloc {
+    JSValueUnprotect(context_, object_);
+    [super dealloc];
+}
+
 - (NSUInteger) count {
     return CYCastDouble(context_, CYGetProperty(context_, object_, length_));
 }
 - (NSUInteger) count {
     return CYCastDouble(context_, CYGetProperty(context_, object_, length_));
 }
index a73b9c95866b4389f97760e39ff79027c0c1313f..1d4a510e36a4090751f39c34eed89bf361654634 100644 (file)
@@ -73,6 +73,24 @@ void CYArray::Output(std::ostream &out, CYFlags flags) const {
     out << ']';
 }
 
     out << ']';
 }
 
+void CYArrayComprehension::Output(std::ostream &out, CYFlags flags) const {
+    // XXX: I don't necc. need the ()s
+    out << "(function($cyv";
+    for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
+        if (const char *name = comprehension->Name())
+            out << ',' << name;
+    out << "){";
+    out << "$cyt=[];";
+    comprehensions_->Output(out);
+    out << "$cyt.push(";
+    expression_->Output(out, CYPA, CYNoFlags);
+    out << ");";
+    for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
+        comprehension->End_(out);
+    out << "return $cyt;";
+    out << "}())";
+}
+
 void CYAssignment::Output(std::ostream &out, CYFlags flags) const {
     lhs_->Output(out, Precedence() - 1, CYLeft(flags));
     out << Operator();
 void CYAssignment::Output(std::ostream &out, CYFlags flags) const {
     lhs_->Output(out, Precedence() - 1, CYLeft(flags));
     out << Operator();
@@ -169,6 +187,12 @@ void CYCompound::Output(std::ostream &out, CYFlags flags) const {
             expression->Output(out, flags);
 }
 
             expression->Output(out, flags);
 }
 
+void CYComprehension::Output(std::ostream &out) const {
+    Begin_(out);
+    if (next_ != NULL)
+        next_->Output(out);
+}
+
 void CYCondition::Output(std::ostream &out, CYFlags flags) const {
     test_->Output(out, Precedence() - 1, CYLeft(flags));
     out << '?';
 void CYCondition::Output(std::ostream &out, CYFlags flags) const {
     test_->Output(out, Precedence() - 1, CYLeft(flags));
     out << '?';
@@ -197,37 +221,46 @@ void CYClause::Output(std::ostream &out) const {
     out << *next_;
 }
 
     out << *next_;
 }
 
-// XXX: deal with NoIn
-void CYDeclaration::Part(std::ostream &out) const {
+void CYDeclaration::Part(std::ostream &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "var ";
     out << "var ";
-    Output(out);
+    Output(out, CYRight(flags));
+}
+
+void CYDeclaration::ForEachIn(std::ostream &out) const {
+    out << *identifier_;
 }
 
 }
 
-void CYDeclaration::Output(std::ostream &out) const {
+void CYDeclaration::Output(std::ostream &out, CYFlags flags) const {
     out << *identifier_;
     if (initialiser_ != NULL) {
         out << '=';
     out << *identifier_;
     if (initialiser_ != NULL) {
         out << '=';
-        initialiser_->Output(out, CYPA, CYNoFlags);
-    }
+        initialiser_->Output(out, CYPA, CYRight(flags));
+    } else if ((flags & CYNoTrailer) != 0)
+        out << ' ';
 }
 
 }
 
-// XXX: deal with NoIn
-void CYDeclarations::Part(std::ostream &out) const {
+void CYDeclarations::Part(std::ostream &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "var ";
 
     const CYDeclarations *declaration(this);
   output:
     out << "var ";
 
     const CYDeclarations *declaration(this);
   output:
-    out << *declaration->declaration_;
-    declaration = declaration->next_;
+    CYDeclarations *next(declaration->next_);
+    CYFlags right(next == NULL ? CYRight(flags) : CYCenter(flags));
+    declaration->declaration_->Output(out, right);
 
 
-    if (declaration != NULL) {
+    if (next != NULL) {
         out << ',';
         out << ',';
+        declaration = next;
         goto output;
     }
 }
 
 void CYDeclarations::Output(std::ostream &out) const {
         goto output;
     }
 }
 
 void CYDeclarations::Output(std::ostream &out) const {
-    Part(out);
+    Part(out, CYNoFlags);
     out << ';';
 }
 
     out << ';';
 }
 
@@ -280,9 +313,14 @@ void CYExpression::ClassName(std::ostream &out, bool object) const {
     Output(out, CYPA, CYNoFlags);
 }
 
     Output(out, CYPA, CYNoFlags);
 }
 
-void CYExpression::Part(std::ostream &out) const {
+void CYExpression::ForEachIn(std::ostream &out) const {
     // XXX: this should handle LeftHandSideExpression
     // XXX: this should handle LeftHandSideExpression
-    Output(out, CYNoIn);
+    Output(out, CYPA, CYNoFlags);
+}
+
+void CYExpression::Part(std::ostream &out, CYFlags flags) const {
+    // XXX: this should handle LeftHandSideExpression
+    Output(out, flags);
 }
 
 void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const {
 }
 
 void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const {
@@ -301,7 +339,7 @@ void CYField::Output(std::ostream &out) const {
 void CYFor::Output(std::ostream &out) const {
     out << "for(";
     if (initialiser_ != NULL)
 void CYFor::Output(std::ostream &out) const {
     out << "for(";
     if (initialiser_ != NULL)
-        initialiser_->Part(out);
+        initialiser_->Part(out, CYNoFlags);
     out << ';';
     if (test_ != NULL)
         test_->Output(out, CYNoFlags);
     out << ';';
     if (test_ != NULL)
         test_->Output(out, CYNoFlags);
@@ -312,17 +350,61 @@ void CYFor::Output(std::ostream &out) const {
     code_->Output(out, false);
 }
 
     code_->Output(out, false);
 }
 
+void CYForEachIn::Output(std::ostream &out) const {
+    const char *name(initialiser_->ForEachIn());
+
+    if (name != NULL) {
+        out << '{';
+        out << "var " << name << ';';
+    }
+
+    out << "(function($cys,$cyt){";
+    out << "$cys=";
+    set_->Output(out, CYPA, CYNoFlags);
+    out << ";";
+
+    out << "for($cyt in $cys){";
+
+    initialiser_->ForEachIn(out);
+    out << "=$cys[$cyt];";
+
+    code_->Show(out);
+
+    out << "}}());";
+
+    if (name != NULL)
+        out << '}';
+}
+
+void CYForEachInComprehension::Begin_(std::ostream &out) const {
+    out << "(function($cys){";
+    out << "$cys=";
+    set_->Output(out, CYPA, CYNoFlags);
+    out << ";";
+
+    out << "for(" << *name_ << " in $cys){";
+    out << *name_ << "=$cys[" << *name_ << "];";
+}
+
+void CYForEachInComprehension::End_(std::ostream &out) const {
+    out << "}}());";
+}
+
 void CYForIn::Output(std::ostream &out) const {
     out << "for(";
 void CYForIn::Output(std::ostream &out) const {
     out << "for(";
-    initialiser_->Part(out);
-    // XXX: deal with this space character!
-    out << ' ';
+    initialiser_->Part(out, CYNoIn | CYNoTrailer);
     out << "in";
     set_->Output(out, CYNoLeader);
     out << ')';
     code_->Output(out, false);
 }
 
     out << "in";
     set_->Output(out, CYNoLeader);
     out << ')';
     code_->Output(out, false);
 }
 
+void CYForInComprehension::Begin_(std::ostream &out) const {
+    out << "for(" << *name_ << " in";
+    set_->Output(out, CYNoLeader);
+    out << ')';
+}
+
 void CYFunction::Output(std::ostream &out) const {
     CYLambda::Output(out, CYNoFlags);
 }
 void CYFunction::Output(std::ostream &out) const {
     CYLambda::Output(out, CYNoFlags);
 }
@@ -346,6 +428,12 @@ void CYIf::Output(std::ostream &out) const {
     }
 }
 
     }
 }
 
+void CYIfComprehension::Begin_(std::ostream &out) const {
+    out << "if(";
+    test_->Output(out, CYNoFlags);
+    out << ')';
+}
+
 void CYIndirect::Output(std::ostream &out, CYFlags flags) const {
     rhs_->Output(out, 1, CYLeft(flags));
     out << ".$cyi";
 void CYIndirect::Output(std::ostream &out, CYFlags flags) const {
     rhs_->Output(out, 1, CYLeft(flags));
     out << ".$cyi";
index caddafca634d92c116b111db3c00a5b9fa12fd36..ed4037efa9f4e1231c1bcdbb2c2dfef106661fa5 100644 (file)
@@ -211,8 +211,19 @@ class CYDriver {
     ~CYDriver();
 };
 
     ~CYDriver();
 };
 
+enum CYFlags {
+    CYNoFlags =    0,
+    CYNoBrace =    (1 << 0),
+    CYNoFunction = (1 << 1),
+    CYNoLeader =   (1 << 2),
+    CYNoTrailer =  (1 << 3),
+    CYNoIn =       (1 << 4),
+    CYNoHyphen =   (1 << 5),
+    CYNoBF =       (CYNoBrace | CYNoFunction),
+};
+
 struct CYPart {
 struct CYPart {
-    virtual void Part(std::ostream &out) const = 0;
+    virtual void Part(std::ostream &out, CYFlags flags) const = 0;
 };
 
 struct CYForInitialiser :
 };
 
 struct CYForInitialiser :
@@ -223,17 +234,8 @@ struct CYForInitialiser :
 struct CYForInInitialiser :
     CYPart
 {
 struct CYForInInitialiser :
     CYPart
 {
-};
-
-enum CYFlags {
-    CYNoFlags =    0,
-    CYNoBrace =    (1 << 0),
-    CYNoFunction = (1 << 1),
-    CYNoLeader =   (1 << 2),
-    CYNoTrailer =  (1 << 3),
-    CYNoIn =       (1 << 4),
-    CYNoHyphen =   (1 << 5),
-    CYNoBF =       (CYNoBrace | CYNoFunction),
+    virtual const char *ForEachIn() const = 0;
+    virtual void ForEachIn(std::ostream &out) const = 0;
 };
 
 struct CYExpression :
 };
 
 struct CYExpression :
@@ -243,7 +245,14 @@ struct CYExpression :
     CYClassName
 {
     virtual unsigned Precedence() const = 0;
     CYClassName
 {
     virtual unsigned Precedence() const = 0;
-    virtual void Part(std::ostream &out) const;
+    virtual void Part(std::ostream &out, CYFlags flags) const;
+
+    virtual const char *ForEachIn() const {
+        return NULL;
+    }
+
+    virtual void ForEachIn(std::ostream &out) const;
+
     virtual void Output(std::ostream &out, CYFlags flags) const = 0;
     void Output(std::ostream &out, unsigned precedence, CYFlags flags) const;
 
     virtual void Output(std::ostream &out, CYFlags flags) const = 0;
     void Output(std::ostream &out, unsigned precedence, CYFlags flags) const;
 
@@ -287,6 +296,91 @@ struct CYCompound :
     void Output(std::ostream &out, CYFlags flags) const;
 };
 
     void Output(std::ostream &out, CYFlags flags) const;
 };
 
+struct CYComprehension :
+    CYNext<CYComprehension>
+{
+    void Output(std::ostream &out) const;
+    virtual const char *Name() const = 0;
+
+    virtual void Begin_(std::ostream &out) const = 0;
+
+    virtual void End_(std::ostream &out) const {
+    }
+};
+
+struct CYForInComprehension :
+    CYComprehension
+{
+    CYIdentifier *name_;
+    CYExpression *set_;
+
+    CYForInComprehension(CYIdentifier *name, CYExpression *set) :
+        name_(name),
+        set_(set)
+    {
+    }
+
+    virtual const char *Name() const {
+        return name_->Value();
+    }
+
+    virtual void Begin_(std::ostream &out) const;
+};
+
+struct CYForEachInComprehension :
+    CYComprehension
+{
+    CYIdentifier *name_;
+    CYExpression *set_;
+
+    CYForEachInComprehension(CYIdentifier *name, CYExpression *set) :
+        name_(name),
+        set_(set)
+    {
+    }
+
+    virtual const char *Name() const {
+        return name_->Value();
+    }
+
+    virtual void Begin_(std::ostream &out) const;
+    virtual void End_(std::ostream &out) const;
+};
+
+struct CYIfComprehension :
+    CYComprehension
+{
+    CYExpression *test_;
+
+    CYIfComprehension(CYExpression *test) :
+        test_(test)
+    {
+    }
+
+    virtual const char *Name() const {
+        return NULL;
+    }
+
+    virtual void Begin_(std::ostream &out) const;
+};
+
+struct CYArrayComprehension :
+    CYExpression
+{
+    CYExpression *expression_;
+    CYComprehension *comprehensions_;
+
+    CYArrayComprehension(CYExpression *expression, CYComprehension *comprehensions) :
+        expression_(expression),
+        comprehensions_(comprehensions)
+    {
+    }
+
+    CYPrecedence(0)
+
+    virtual void Output(std::ostream &out, CYFlags flags) const;
+};
+
 struct CYLiteral :
     CYExpression
 {
 struct CYLiteral :
     CYExpression
 {
@@ -630,7 +724,6 @@ struct CYArray :
 };
 
 struct CYDeclaration :
 };
 
 struct CYDeclaration :
-    CYThing,
     CYForInInitialiser
 {
     CYIdentifier *identifier_;
     CYForInInitialiser
 {
     CYIdentifier *identifier_;
@@ -642,8 +735,15 @@ struct CYDeclaration :
     {
     }
 
     {
     }
 
-    virtual void Part(std::ostream &out) const;
-    virtual void Output(std::ostream &out) const;
+    virtual void Part(std::ostream &out, CYFlags flags) const;
+
+    virtual const char *ForEachIn() const {
+        return identifier_->Value();
+    }
+
+    virtual void ForEachIn(std::ostream &out) const;
+
+    virtual void Output(std::ostream &out, CYFlags flags) const;
 };
 
 struct CYDeclarations :
 };
 
 struct CYDeclarations :
@@ -659,7 +759,7 @@ struct CYDeclarations :
     {
     }
 
     {
     }
 
-    virtual void Part(std::ostream &out) const;
+    virtual void Part(std::ostream &out, CYFlags flags) const;
     virtual void Output(std::ostream &out) const;
 };
 
     virtual void Output(std::ostream &out) const;
 };
 
@@ -792,6 +892,23 @@ struct CYForIn :
     virtual void Output(std::ostream &out) const;
 };
 
     virtual void Output(std::ostream &out) const;
 };
 
+struct CYForEachIn :
+    CYStatement
+{
+    CYForInInitialiser *initialiser_;
+    CYExpression *set_;
+    CYStatement *code_;
+
+    CYForEachIn(CYForInInitialiser *initialiser, CYExpression *set, CYStatement *code) :
+        initialiser_(initialiser),
+        set_(set),
+        code_(code)
+    {
+    }
+
+    virtual void Output(std::ostream &out) const;
+};
+
 struct CYProperty :
     CYNext<CYProperty>
 {
 struct CYProperty :
     CYNext<CYProperty>
 {
index b153d52123f32700423732b137b7879631a42be4..518cd481690a583558c8177f9893c6f67cf9f9e0 100644 (file)
--- a/makefile
+++ b/makefile
@@ -18,7 +18,7 @@ $(deb):
 all: $(all)
 
 clean:
 all: $(all)
 
 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
+       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 cyrver
 
 libcycript.plist: Bridge.def
        { \
 
 libcycript.plist: Bridge.def
        { \