]> git.saurik.com Git - cycript.git/commitdiff
Got jQuery parsing (empty finally block, function statements, carriage return) and...
authorJay Freeman (saurik) <saurik@saurik.com>
Tue, 20 Oct 2009 04:44:44 +0000 (04:44 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Tue, 20 Oct 2009 04:44:44 +0000 (04:44 +0000)
Console.cpp
Cycript.l
Cycript.y
Library.mm
Output.cpp
Parser.hpp

index 6ed69e66dce574b5dcf16d79617720bd8aa7ae05..77ee9f9c40f2171119669fb7cc53a4b19e2f78f2 100644 (file)
@@ -94,12 +94,15 @@ static void sigint(int) {
 #if YYDEBUG
 static bool bison_;
 #endif
 #if YYDEBUG
 static bool bison_;
 #endif
+static bool strict_;
 
 
-void Setup(cy::parser &parser) {
+void Setup(CYDriver &driver, cy::parser &parser) {
 #if YYDEBUG
     if (bison_)
         parser.set_debug_level(1);
 #endif
 #if YYDEBUG
     if (bison_)
         parser.set_debug_level(1);
 #endif
+    if (strict_)
+        driver.strict_ = true;
 }
 
 void Run(int socket, const char *data, size_t size, FILE *fout = NULL, bool expand = false) {
 }
 
 void Run(int socket, const char *data, size_t size, FILE *fout = NULL, bool expand = false) {
@@ -229,7 +232,7 @@ static void Console(int socket) {
         else {
             CYDriver driver("");
             cy::parser parser(driver);
         else {
             CYDriver driver("");
             cy::parser parser(driver);
-            Setup(parser);
+            Setup(driver, parser);
 
             driver.data_ = command.c_str();
             driver.size_ = command.size();
 
             driver.data_ = command.c_str();
             driver.size_ = command.size();
@@ -237,7 +240,7 @@ static void Console(int socket) {
             if (parser.parse() != 0 || !driver.errors_.empty()) {
                 for (CYDriver::Errors::const_iterator error(driver.errors_.begin()); error != driver.errors_.end(); ++error) {
                     cy::position begin(error->location_.begin);
             if (parser.parse() != 0 || !driver.errors_.empty()) {
                 for (CYDriver::Errors::const_iterator error(driver.errors_.begin()); error != driver.errors_.end(); ++error) {
                     cy::position begin(error->location_.begin);
-                    if (begin.line != lines.size() || begin.column - 1 != lines.back().size()) {
+                    if (begin.line != lines.size() || begin.column - 1 != lines.back().size() || error->warning_) {
                         cy::position end(error->location_.end);
 
                         if (begin.line != lines.size()) {
                         cy::position end(error->location_.end);
 
                         if (begin.line != lines.size()) {
@@ -269,7 +272,7 @@ static void Console(int socket) {
                 goto read;
             }
 
                 goto read;
             }
 
-            if (driver.source_ == NULL)
+            if (driver.program_ == NULL)
                 goto restart;
 
             if (socket != -1)
                 goto restart;
 
             if (socket != -1)
@@ -277,7 +280,7 @@ static void Console(int socket) {
             else {
                 std::ostringstream str;
                 CYOutput out(str);
             else {
                 std::ostringstream str;
                 CYOutput out(str);
-                driver.source_->Show(out);
+                driver.program_->Show(out);
                 code = str.str();
             }
         }
                 code = str.str();
             }
         }
@@ -316,7 +319,7 @@ int main(int argc, char *argv[]) {
     pid_t pid(_not(pid_t));
     bool compile(false);
 
     pid_t pid(_not(pid_t));
     bool compile(false);
 
-    for (;;) switch (getopt(argc, argv, "cg:p:")) {
+    for (;;) switch (getopt(argc, argv, "cg:p:s")) {
         case -1:
             goto getopt;
         case '?':
         case -1:
             goto getopt;
         case '?':
@@ -348,6 +351,10 @@ int main(int argc, char *argv[]) {
                 return 1;
             }
         } break;
                 return 1;
             }
         } break;
+
+        case 's':
+            strict_ = true;
+        break;
     } getopt:;
 
     const char *script;
     } getopt:;
 
     const char *script;
@@ -397,7 +404,7 @@ int main(int argc, char *argv[]) {
     else {
         CYDriver driver(script ?: "<stdin>");
         cy::parser parser(driver);
     else {
         CYDriver driver(script ?: "<stdin>");
         cy::parser parser(driver);
-        Setup(parser);
+        Setup(driver, parser);
 
         char *start, *end;
 
 
         char *start, *end;
 
@@ -427,13 +434,13 @@ int main(int argc, char *argv[]) {
         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;
         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)
+        } else if (driver.program_ != NULL)
             if (socket != -1)
                 Run(socket, start, end - start, stdout);
             else {
                 std::ostringstream str;
                 CYOutput out(str);
             if (socket != -1)
                 Run(socket, start, end - start, stdout);
             else {
                 std::ostringstream str;
                 CYOutput out(str);
-                driver.source_->Show(out);
+                driver.program_->Show(out);
                 std::string code(str.str());
                 if (compile)
                     std::cout << code;
                 std::string code(str.str());
                 if (compile)
                     std::cout << code;
index 115e1de6e490a70b3289efffce3addb810216195..d62a14b09f3413553c69293d337db5d43a1482ba 100644 (file)
--- a/Cycript.l
+++ b/Cycript.l
@@ -289,7 +289,7 @@ RegularExpressionStart_ {RegularExpressionBody}{RegularExpressionEnd_}
     return tk::StringLiteral;
 }
 
     return tk::StringLiteral;
 }
 
-\n yylloc->end.lines(); yylloc->step(); N
+\r?\n yylloc->end.lines(); yylloc->step(); N
 
 [ \t] L
 <<EOF>> L yyterminate();
 
 [ \t] L
 <<EOF>> L yyterminate();
index c83562c8e377aa4107fa32d5f8aa5f118a9058d0..42402f3935fa9f83a849a4224815eaae68e8babb 100644 (file)
--- a/Cycript.y
+++ b/Cycript.y
@@ -69,6 +69,7 @@ typedef struct {
         CYExpression *expression_;
         CYFalse *false_;
         CYField *field_;
         CYExpression *expression_;
         CYFalse *false_;
         CYField *field_;
+        CYFinally *finally_;
         CYForInitialiser *for_;
         CYForInInitialiser *forin_;
         CYFunctionParameter *functionParameter_;
         CYForInitialiser *for_;
         CYForInInitialiser *forin_;
         CYFunctionParameter *functionParameter_;
@@ -83,7 +84,6 @@ typedef struct {
         CYProperty *property_;
         CYPropertyName *propertyName_;
         CYSelectorPart *selector_;
         CYProperty *property_;
         CYPropertyName *propertyName_;
         CYSelectorPart *selector_;
-        CYSource *source_;
         CYStatement *statement_;
         CYString *string_;
         CYThis *this_;
         CYStatement *statement_;
         CYString *string_;
         CYThis *this_;
@@ -328,7 +328,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <compound_> ExpressionNoIn_
 %type <expression_> ExpressionNoInOpt
 %type <statement_> ExpressionStatement
 %type <compound_> ExpressionNoIn_
 %type <expression_> ExpressionNoInOpt
 %type <statement_> ExpressionStatement
-%type <statement_> FinallyOpt
+%type <finally_> FinallyOpt
 %type <comprehension_> ForComprehension
 %type <statement_> ForStatement
 %type <for_> ForStatementInitialiser
 %type <comprehension_> ForComprehension
 %type <statement_> ForStatement
 %type <for_> ForStatementInitialiser
@@ -336,8 +336,8 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <forin_> ForInStatementInitialiser
 %type <functionParameter_> FormalParameterList
 %type <functionParameter_> FormalParameterList_
 %type <forin_> ForInStatementInitialiser
 %type <functionParameter_> FormalParameterList
 %type <functionParameter_> FormalParameterList_
-%type <source_> FunctionBody
-%type <source_> FunctionDeclaration
+%type <statement_> FunctionBody
+%type <statement_> FunctionDeclaration
 %type <expression_> FunctionExpression
 %type <identifier_> Identifier
 %type <identifier_> IdentifierOpt
 %type <expression_> FunctionExpression
 %type <identifier_> Identifier
 %type <identifier_> IdentifierOpt
@@ -380,7 +380,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <expression_> PrimaryExpression
 %type <expression_> PrimaryExpression_
 %type <expression_> PrimaryExpressionNoBF
 %type <expression_> PrimaryExpression
 %type <expression_> PrimaryExpression_
 %type <expression_> PrimaryExpressionNoBF
-%type <source_> Program
+%type <statement_> Program
 %type <propertyName_> PropertyName
 %type <property_> PropertyNameAndValueList
 %type <property_> PropertyNameAndValueList_
 %type <propertyName_> PropertyName
 %type <property_> PropertyNameAndValueList
 %type <property_> PropertyNameAndValueList_
@@ -398,9 +398,10 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <selector_> SelectorExpressionOpt
 %type <expression_> ShiftExpression
 %type <expression_> ShiftExpressionNoBF
 %type <selector_> SelectorExpressionOpt
 %type <expression_> ShiftExpression
 %type <expression_> ShiftExpressionNoBF
-%type <source_> SourceElement
-%type <source_> SourceElements
+%type <statement_> SourceElement
+%type <statement_> SourceElements
 %type <statement_> Statement
 %type <statement_> Statement
+%type <statement_> Statement_
 %type <statement_> StatementList
 %type <statement_> StatementListOpt
 %type <statement_> SwitchStatement
 %type <statement_> StatementList
 %type <statement_> StatementListOpt
 %type <statement_> SwitchStatement
@@ -448,16 +449,23 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 
 %%
 
 
 %%
 
-TerminatorOpt
+StrictSemi
+    : { driver.Warning(yylloc, "warning, automatic semi-colon insertion required"); }
+    ;
+
+Terminator_
     : ";"
     : ";"
-    | "\n"
-    | error { yyerrok; driver.errors_.pop_back(); }
+    | "\n" StrictSemi
+    ;
+
+TerminatorOpt
+    : Terminator_
+    | error { yyerrok; driver.errors_.pop_back(); } StrictSemi
     ;
 
 Terminator
     ;
 
 Terminator
-    : ";"
-    | "\n"
-    | error { if (yychar != 0 && yychar != cy::parser::token::CloseBrace && !yylval.newline_) YYABORT; else { yyerrok; driver.errors_.pop_back(); } }
+    : Terminator_
+    | error { if (yychar != 0 && yychar != cy::parser::token::CloseBrace && !yylval.newline_) YYABORT; else { yyerrok; driver.errors_.pop_back(); } } StrictSemi
     ;
 
 /*CommaOpt
     ;
 
 /*CommaOpt
@@ -1040,7 +1048,7 @@ ExpressionNoBF
 /* }}} */
 
 /* 12 Statements {{{ */
 /* }}} */
 
 /* 12 Statements {{{ */
-Statement
+Statement_
     : Block { $$ = $1; }
     | VariableStatement { $$ = $1; }
     | EmptyStatement { $$ = $1; }
     : Block { $$ = $1; }
     | VariableStatement { $$ = $1; }
     | EmptyStatement { $$ = $1; }
@@ -1056,6 +1064,10 @@ Statement
     | ThrowStatement { $$ = $1; }
     | TryStatement { $$ = $1; }
     ;
     | ThrowStatement { $$ = $1; }
     | TryStatement { $$ = $1; }
     ;
+
+Statement
+    : Statement_ { $$ = $1; }
+    ;
 /* }}} */
 /* 12.1 Block {{{ */
 Block_
 /* }}} */
 /* 12.1 Block {{{ */
 Block_
@@ -1249,7 +1261,7 @@ CatchOpt
     ;
 
 FinallyOpt
     ;
 
 FinallyOpt
-    : "finally" Block_ { $$ = $2; }
+    : "finally" Block_ { $$ = new(driver.pool_) CYFinally($2); }
     | { $$ = NULL; }
     ;
 /* }}} */
     | { $$ = NULL; }
     ;
 /* }}} */
@@ -1279,7 +1291,7 @@ FunctionBody
 /* }}} */
 /* 14 Program {{{ */
 Program
 /* }}} */
 /* 14 Program {{{ */
 Program
-    : SourceElements { driver.source_ = $1; }
+    : SourceElements { driver.program_ = $1; }
     ;
 
 SourceElements
     ;
 
 SourceElements
@@ -1288,7 +1300,7 @@ SourceElements
     ;
 
 SourceElement
     ;
 
 SourceElement
-    : Statement { $$ = $1; }
+    : Statement_ { $$ = $1; }
     | FunctionDeclaration { $$ = $1; }
     ;
 /* }}} */
     | FunctionDeclaration { $$ = $1; }
     ;
 /* }}} */
@@ -1362,7 +1374,7 @@ PrimaryExpression
     : ClassDefinition { $$ = $1; }
     ;
 
     : ClassDefinition { $$ = $1; }
     ;
 
-Statement
+Statement_
     : ClassDefinition { $$ = $1; }
     | CategoryStatement { $$ = $1; }
     ;
     : ClassDefinition { $$ = $1; }
     | CategoryStatement { $$ = $1; }
     ;
@@ -1457,7 +1469,7 @@ ForInStatement
     : "for" "each" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForEachIn($4, $6, $8); }
     ;
 /* }}} */
     : "for" "each" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForEachIn($4, $6, $8); }
     ;
 /* }}} */
-/* JavaScript 1.7: Let Statements {{{ *//*
+/* JavaScript 1.7: let Statements {{{ *//*
 LetStatement
     : "let" "(" VariableDeclarationList ")" Block_ { $$ = new(driver.pool_) CYLet($3, $5); }
     ;
 LetStatement
     : "let" "(" VariableDeclarationList ")" Block_ { $$ = new(driver.pool_) CYLet($3, $5); }
     ;
@@ -1466,5 +1478,10 @@ Statement
     : LetStatement
     ;
 *//* }}} */
     : LetStatement
     ;
 *//* }}} */
+/* JavaScript FTW: Function Statements {{{ */
+Statement
+    : FunctionDeclaration { driver.Warning(yylloc, "warning, FunctionDeclaration is a SourceElement, not a Statement"); } { $$ = $1; }
+    ;
+/* }}} */
 
 %%
 
 %%
index 1b4a19820ed6fcda6ed2ba39a157242a3d0d6d16..a7da81ebe57b14208f8003836d7e6ee65b419883 100644 (file)
@@ -3300,8 +3300,9 @@ CYDriver::CYDriver(const std::string &filename) :
     data_(NULL),
     size_(0),
     file_(NULL),
     data_(NULL),
     size_(0),
     file_(NULL),
+    strict_(false),
     filename_(filename),
     filename_(filename),
-    source_(NULL)
+    program_(NULL)
 {
     ScannerInit();
 }
 {
     ScannerInit();
 }
@@ -3310,8 +3311,20 @@ CYDriver::~CYDriver() {
     ScannerDestroy();
 }
 
     ScannerDestroy();
 }
 
+void CYDriver::Warning(const cy::location &location, const char *message) {
+    if (!strict_)
+        return;
+
+    CYDriver::Error error;
+    error.warning_ = true;
+    error.location_ = location;
+    error.message_ = message;
+    errors_.push_back(error);
+}
+
 void cy::parser::error(const cy::parser::location_type &location, const std::string &message) {
     CYDriver::Error error;
 void cy::parser::error(const cy::parser::location_type &location, const std::string &message) {
     CYDriver::Error error;
+    error.warning_ = false;
     error.location_ = location;
     error.message_ = message;
     driver.errors_.push_back(error);
     error.location_ = location;
     error.message_ = message;
     driver.errors_.push_back(error);
@@ -3451,7 +3464,7 @@ struct CYClient :
             } else {
                 std::ostringstream str;
                 CYOutput out(str);
             } else {
                 std::ostringstream str;
                 CYOutput out(str);
-                driver.source_->Show(out);
+                driver.program_->Show(out);
                 std::string code(str.str());
                 CYExecute_ execute = {pool, code.c_str()};
                 [client performSelectorOnMainThread:@selector(execute:) withObject:[NSValue valueWithPointer:&execute] waitUntilDone:YES];
                 std::string code(str.str());
                 CYExecute_ execute = {pool, code.c_str()};
                 [client performSelectorOnMainThread:@selector(execute:) withObject:[NSValue valueWithPointer:&execute] waitUntilDone:YES];
index e6bedf4cec2c7dbbf285b7d4df26c51d83181c6f..09ee163a739f138b964081d9a9d0aab5e4afdefd 100644 (file)
@@ -98,7 +98,7 @@ void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYBlock::Output(CYOutput &out) const {
 }
 
 void CYBlock::Output(CYOutput &out) const {
-    for (CYSource *statement(statements_); statement != NULL; statement = statement->next_)
+    for (CYStatement *statement(statements_); statement != NULL; statement = statement->next_)
         statement->Output(out);
 }
 
         statement->Output(out);
 }
 
@@ -126,8 +126,10 @@ void CYCall::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYCatch::Output(CYOutput &out) const {
 }
 
 void CYCatch::Output(CYOutput &out) const {
-    out << "catch(" << *name_ << ')';
-    code_->Output(out, true);
+    out << "catch(" << *name_ << "){";
+    if (code_ != NULL)
+        code_->Show(out);
+    out << "}";
 }
 
 void CYCategory::Output(CYOutput &out) const {
 }
 
 void CYCategory::Output(CYOutput &out) const {
@@ -300,7 +302,7 @@ void CYEmpty::Output(CYOutput &out) const {
 
 void CYEmpty::Output(CYOutput &out, bool block) const {
     if (next_ != NULL)
 
 void CYEmpty::Output(CYOutput &out, bool block) const {
     if (next_ != NULL)
-        CYSource::Output(out, block);
+        CYStatement::Output(out, block);
     else
         out << "{}";
 }
     else
         out << "{}";
 }
@@ -345,6 +347,13 @@ void CYField::Output(CYOutput &out) const {
     // XXX: implement!
 }
 
     // XXX: implement!
 }
 
+void CYFinally::Output(CYOutput &out) const {
+    out << "finally{";
+    if (code_ != NULL)
+        code_->Show(out);
+    out << "}";
+}
+
 void CYFor::Output(CYOutput &out) const {
     out << "for(";
     if (initialiser_ != NULL)
 void CYFor::Output(CYOutput &out) const {
     out << "for(";
     if (initialiser_ != NULL)
@@ -651,12 +660,12 @@ void CYSend::Output(CYOutput &out, CYFlags flags) const {
     out << ')';
 }
 
     out << ')';
 }
 
-void CYSource::Show(CYOutput &out) const {
-    for (const CYSource *next(this); next != NULL; next = next->next_)
+void CYStatement::Show(CYOutput &out) const {
+    for (const CYStatement *next(this); next != NULL; next = next->next_)
         next->Output_(out);
 }
 
         next->Output_(out);
 }
 
-void CYSource::Output(CYOutput &out, bool block) const {
+void CYStatement::Output(CYOutput &out, bool block) const {
     if (!block && !IsBlock())
         Output(out);
     else {
     if (!block && !IsBlock())
         Output(out);
     else {
@@ -666,10 +675,6 @@ void CYSource::Output(CYOutput &out, bool block) const {
     }
 }
 
     }
 }
 
-void CYSource::Output_(CYOutput &out) const {
-    Output(out);
-}
-
 void CYStatement::Output_(CYOutput &out) const {
     for (CYLabel *label(labels_); label != NULL; label = label->next_)
         out << *label->name_ << ':';
 void CYStatement::Output_(CYOutput &out) const {
     for (CYLabel *label(labels_); label != NULL; label = label->next_)
         out << *label->name_ << ':';
@@ -750,14 +755,14 @@ void CYThrow::Output(CYOutput &out) const {
 }
 
 void CYTry::Output(CYOutput &out) const {
 }
 
 void CYTry::Output(CYOutput &out) const {
-    out << "try";
-    try_->Output(out, true);
+    out << "try{";
+    if (code_ != NULL)
+        code_->Show(out);
+    out << "}";
     if (catch_ != NULL)
         catch_->Output(out);
     if (catch_ != NULL)
         catch_->Output(out);
-    if (finally_ != NULL) {
-        out << "finally";
-        finally_->Output(out, true);
-    }
+    if (finally_ != NULL)
+        finally_->Output(out);
 }
 
 void CYVar::Output(CYOutput &out) const {
 }
 
 void CYVar::Output(CYOutput &out) const {
index f8b8b6ef0179322dd2e82dae2048fdac2db929f9..6fde458b31cc43b6504550ca050d8377b66b8070 100644 (file)
@@ -94,19 +94,6 @@ struct CYOutput {
     }
 };
 
     }
 };
 
-struct CYSource :
-    CYNext<CYSource>
-{
-    virtual bool IsBlock() const {
-        return next_ != NULL;
-    }
-
-    virtual void Show(CYOutput &out) const;
-    virtual void Output(CYOutput &out) const = 0;
-    virtual void Output(CYOutput &out, bool block) const;
-    virtual void Output_(CYOutput &out) const;
-};
-
 struct CYPropertyName {
     virtual void PropertyName(CYOutput &out) const = 0;
 };
 struct CYPropertyName {
     virtual void PropertyName(CYOutput &out) const = 0;
 };
@@ -163,7 +150,7 @@ struct CYLabel :
 };
 
 struct CYStatement :
 };
 
 struct CYStatement :
-    CYSource
+    CYNext<CYStatement>
 {
     CYLabel *labels_;
 
 {
     CYLabel *labels_;
 
@@ -176,6 +163,13 @@ struct CYStatement :
         labels_ = new CYLabel(identifier, labels_);
     }
 
         labels_ = new CYLabel(identifier, labels_);
     }
 
+    virtual bool IsBlock() const {
+        return next_ != NULL;
+    }
+
+    virtual void Show(CYOutput &out) const;
+    virtual void Output(CYOutput &out) const = 0;
+    virtual void Output(CYOutput &out, bool block) const;
     virtual void Output_(CYOutput &out) const;
 };
 
     virtual void Output_(CYOutput &out) const;
 };
 
@@ -213,6 +207,8 @@ class CYDriver {
     size_t size_;
     FILE *file_;
 
     size_t size_;
     FILE *file_;
 
+    bool strict_;
+
     enum Condition {
         RegExStart,
         RegExRest
     enum Condition {
         RegExStart,
         RegExRest
@@ -221,13 +217,14 @@ class CYDriver {
     std::string filename_;
 
     struct Error {
     std::string filename_;
 
     struct Error {
+        bool warning_;
         cy::location location_;
         std::string message_;
     };
 
     typedef std::vector<Error> Errors;
 
         cy::location location_;
         std::string message_;
     };
 
     typedef std::vector<Error> Errors;
 
-    CYSource *source_;
+    CYStatement *program_;
     Errors errors_;
 
   private:
     Errors errors_;
 
   private:
@@ -239,6 +236,8 @@ class CYDriver {
     ~CYDriver();
 
     void SetCondition(Condition condition);
     ~CYDriver();
 
     void SetCondition(Condition condition);
+
+    void Warning(const cy::location &location, const char *message);
 };
 
 enum CYFlags {
 };
 
 enum CYFlags {
@@ -854,9 +853,9 @@ struct CYMessage :
     bool instance_;
     CYExpression *type_;
     CYMessageParameter *parameter_;
     bool instance_;
     CYExpression *type_;
     CYMessageParameter *parameter_;
-    CYSource *body_;
+    CYStatement *body_;
 
 
-    CYMessage(bool instance, CYExpression *type, CYMessageParameter *parameter, CYSource *body) :
+    CYMessage(bool instance, CYExpression *type, CYMessageParameter *parameter, CYStatement *body) :
         instance_(instance),
         type_(type),
         parameter_(parameter),
         instance_(instance),
         type_(type),
         parameter_(parameter),
@@ -1163,9 +1162,9 @@ struct CYLambda :
 {
     CYIdentifier *name_;
     CYFunctionParameter *parameters_;
 {
     CYIdentifier *name_;
     CYFunctionParameter *parameters_;
-    CYSource *body_;
+    CYStatement *body_;
 
 
-    CYLambda(CYIdentifier *name, CYFunctionParameter *parameters, CYSource *body) :
+    CYLambda(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
         name_(name),
         parameters_(parameters),
         body_(body)
         name_(name),
         parameters_(parameters),
         body_(body)
@@ -1179,9 +1178,9 @@ struct CYLambda :
 
 struct CYFunction :
     CYLambda,
 
 struct CYFunction :
     CYLambda,
-    CYSource
+    CYStatement
 {
 {
-    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYSource *body) :
+    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
         CYLambda(name, parameters, body)
     {
     }
         CYLambda(name, parameters, body)
     {
     }
@@ -1248,15 +1247,26 @@ struct CYEmpty :
     virtual void Output(CYOutput &out, bool block) const;
 };
 
     virtual void Output(CYOutput &out, bool block) const;
 };
 
+struct CYFinally {
+    CYStatement *code_;
+
+    CYFinally(CYStatement *code) :
+        code_(code)
+    {
+    }
+
+    virtual void Output(CYOutput &out) const;
+};
+
 struct CYTry :
     CYStatement
 {
 struct CYTry :
     CYStatement
 {
-    CYStatement *try_;
+    CYStatement *code_;
     CYCatch *catch_;
     CYCatch *catch_;
-    CYStatement *finally_;
+    CYFinally *finally_;
 
 
-    CYTry(CYStatement *_try, CYCatch *_catch, CYStatement *finally) :
-        try_(_try),
+    CYTry(CYStatement *code, CYCatch *_catch, CYFinally *finally) :
+        code_(code),
         catch_(_catch),
         finally_(finally)
     {
         catch_(_catch),
         finally_(finally)
     {