jitcraft/Parser.cpp
changeset 63 dd57743d220e
parent 59 b7d61ddb3c8d
child 66 cbba1997dc71
     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) {