1.1 --- a/jitcraft/Parser.cpp Sun Jul 08 15:23:48 2012 -0700
1.2 +++ b/jitcraft/Parser.cpp Sun Jul 08 16:49:17 2012 -0700
1.3 @@ -46,6 +46,12 @@
1.4 }
1.5
1.6 bool
1.7 +Parser::matchSemicolon()
1.8 +{
1.9 + return expect(TOK_SEMICOLON);
1.10 +}
1.11 +
1.12 +bool
1.13 Parser::expect(TokenKind kind)
1.14 {
1.15 TokenKind got = scanner_.scan();
1.16 @@ -96,7 +102,8 @@
1.17 void
1.18 Parser::redeclarationError(BoundName *other)
1.19 {
1.20 - cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->pos().line, other->pos().col);
1.21 + cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->name()->chars(),
1.22 + other->pos().line, other->pos().col);
1.23 }
1.24
1.25 Expression *
1.26 @@ -842,7 +849,7 @@
1.27 }
1.28
1.29 Statement *
1.30 -Parser::function()
1.31 +Parser::function(TokenKind token)
1.32 {
1.33 Local<String> name(zone_, expectName());
1.34 if (!name)
1.35 @@ -853,13 +860,29 @@
1.36 // The function name goes into the outer (global) scope.
1.37 assert(!scope_->enclosing());
1.38
1.39 + NamedFunction *fun;
1.40 if (BoundName *other = scope_->localLookup(name)) {
1.41 - redeclarationError(other);
1.42 - return NULL;
1.43 + // We allow a redeclaration if the new type is a public, and the old
1.44 + // type was a forward. However, the forward must come first.
1.45 + if (other->kind() != BoundName::FUNCTION) {
1.46 + redeclarationError(other);
1.47 + return NULL;
1.48 + }
1.49 +
1.50 + fun = other->toNamedFunction();
1.51 + if (!fun->isForward() || token != TOK_PUBLIC) {
1.52 + redeclarationError(other);
1.53 + return NULL;
1.54 + }
1.55 +
1.56 + // We've got the same name, but the original is a forward, so let it
1.57 + // slide and re-use the original declaration.
1.58 + fun->setImplemented(scanner_.begin());
1.59 + } else {
1.60 + fun = scope_->declareFunction(name, scanner_.begin(), token);
1.61 + if (!fun)
1.62 + return NULL;
1.63 }
1.64 - NamedFunction *fun = scope_->declareFunction(name, scanner_.begin());
1.65 - if (!fun)
1.66 - return NULL;
1.67
1.68 Scope *scope = enterScope(Scope::FUNCTION);
1.69 if (!scope)
1.70 @@ -897,9 +920,12 @@
1.71 return NULL;
1.72 }
1.73
1.74 - Statement *body = block();
1.75 - if (!body)
1.76 - return NULL;
1.77 + Statement *body = NULL;
1.78 + if (token != TOK_FORWARD) {
1.79 + body = block();
1.80 + if (!body)
1.81 + return NULL;
1.82 + }
1.83
1.84 scope_ = scope_->enclosing();
1.85 return new (pool_) FunctionStatement(pos, scope, fun, body, parameters);
1.86 @@ -924,18 +950,30 @@
1.87 break;
1.88
1.89 case TOK_NAME:
1.90 - if ((statement = function()) == NULL)
1.91 + if ((statement = function(TOK_NAME)) == NULL)
1.92 return NULL;
1.93 break;
1.94
1.95 + case TOK_FORWARD:
1.96 + case TOK_PUBLIC:
1.97 + {
1.98 + TokenKind kind = scanner_.scan();
1.99 + if ((statement = function(kind)) == NULL)
1.100 + return NULL;
1.101 + if (kind == TOK_FORWARD && !matchSemicolon())
1.102 + return NULL;
1.103 + break;
1.104 + }
1.105 +
1.106 case TOK_ENUM:
1.107 if ((statement = enum_()) == NULL)
1.108 return NULL;
1.109 - // :TODO: require semicolon
1.110 + if (!matchSemicolon())
1.111 + return NULL;
1.112 break;
1.113
1.114 default:
1.115 - fprintf(stderr, "expected function or global variable\n");
1.116 + cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
1.117 return NULL;
1.118 }
1.119
1.120 @@ -991,7 +1029,8 @@
1.121 prefix();
1.122 fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
1.123 indent();
1.124 - node->body()->accept(this);
1.125 + if (node->body())
1.126 + node->body()->accept(this);
1.127 unindent();
1.128 }
1.129 void visit(ExpressionStatement *node) {