Added support for forwards.
Added support for forwards.
1.1 --- a/jitcraft/BytecodeCompiler.cpp Sun Jul 08 15:23:48 2012 -0700
1.2 +++ b/jitcraft/BytecodeCompiler.cpp Sun Jul 08 16:49:17 2012 -0700
1.3 @@ -654,6 +654,12 @@
1.4 void
1.5 BytecodeCompiler::visit(FunctionStatement *node)
1.6 {
1.7 + // If the function has no body, then it's just a declaration.
1.8 + if (!node->body()) {
1.9 + assert(node->fun()->isForward() || node->fun()->isPublic());
1.10 + return;
1.11 + }
1.12 +
1.13 BytecodeCompiler child(zone_, tree_, module_);
1.14 Local<Function> fun(zone_, child.compileFunction(module_, node));
1.15 if (!fun)
2.1 --- a/jitcraft/Messages.tbl Sun Jul 08 15:23:48 2012 -0700
2.2 +++ b/jitcraft/Messages.tbl Sun Jul 08 16:49:17 2012 -0700
2.3 @@ -41,3 +41,6 @@
2.4 MSG(CantOpenFile, SyntaxError, "cannot open file")
2.5 MSG(ErrorSeekingFile, SyntaxError, "error seeking file")
2.6 MSG(ErrorReadingFile, SyntaxError, "error reading file")
2.7 +MSG(ExpectedGlobal, SyntaxError, "expected global variable or function")
2.8 +MSG(ForwardNotImplemented, SyntaxError, "forward '%s' not implemented")
2.9 +MSG(ForwardDeclareMismatches, SyntaxError, "declaration does not match original forward signature")
2.10 \ No newline at end of file
3.1 --- a/jitcraft/NameBinding.cpp Sun Jul 08 15:23:48 2012 -0700
3.2 +++ b/jitcraft/NameBinding.cpp Sun Jul 08 16:49:17 2012 -0700
3.3 @@ -29,8 +29,10 @@
3.4 {
3.5 }
3.6
3.7 -NamedFunction::NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos)
3.8 - : BoundName(scope, name, pos)
3.9 +NamedFunction::NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos,
3.10 + TokenKind token)
3.11 + : BoundName(scope, name, pos),
3.12 + token_(token)
3.13 {
3.14 }
3.15
4.1 --- a/jitcraft/NameBinding.h Sun Jul 08 15:23:48 2012 -0700
4.2 +++ b/jitcraft/NameBinding.h Sun Jul 08 16:49:17 2012 -0700
4.3 @@ -37,6 +37,8 @@
4.4 Scope *scope_;
4.5 ScopedRoot<String> name_;
4.6 ScopedRoot<Type> type_;
4.7 +
4.8 + protected:
4.9 SourcePosition pos_;
4.10
4.11 public:
4.12 @@ -83,9 +85,11 @@
4.13 class NamedFunction : public BoundName
4.14 {
4.15 unsigned slot_;
4.16 + TokenKind token_;
4.17 + ScopedRoot<Type> forwardType_;
4.18
4.19 public:
4.20 - NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos);
4.21 + NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos, TokenKind token);
4.22
4.23 Kind kind() const {
4.24 return FUNCTION;
4.25 @@ -93,6 +97,22 @@
4.26 void allocate(unsigned slot) {
4.27 slot_ = slot;
4.28 }
4.29 + bool isForward() const {
4.30 + return token_ == TOK_FORWARD;
4.31 + }
4.32 + bool isPublic() const {
4.33 + return token_ == TOK_PUBLIC;
4.34 + }
4.35 + void setForwardType(Handle<Type> type) {
4.36 + forwardType_ = type;
4.37 + }
4.38 + Type *forwardType() {
4.39 + return forwardType_;
4.40 + }
4.41 + void setImplemented(const SourcePosition &at) {
4.42 + token_ = TOK_PUBLIC;
4.43 + pos_ = at;
4.44 + }
4.45 unsigned slot() const {
4.46 return slot_;
4.47 }
5.1 --- a/jitcraft/Parser.cpp Sun Jul 08 15:23:48 2012 -0700
5.2 +++ b/jitcraft/Parser.cpp Sun Jul 08 16:49:17 2012 -0700
5.3 @@ -46,6 +46,12 @@
5.4 }
5.5
5.6 bool
5.7 +Parser::matchSemicolon()
5.8 +{
5.9 + return expect(TOK_SEMICOLON);
5.10 +}
5.11 +
5.12 +bool
5.13 Parser::expect(TokenKind kind)
5.14 {
5.15 TokenKind got = scanner_.scan();
5.16 @@ -96,7 +102,8 @@
5.17 void
5.18 Parser::redeclarationError(BoundName *other)
5.19 {
5.20 - cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->pos().line, other->pos().col);
5.21 + cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->name()->chars(),
5.22 + other->pos().line, other->pos().col);
5.23 }
5.24
5.25 Expression *
5.26 @@ -842,7 +849,7 @@
5.27 }
5.28
5.29 Statement *
5.30 -Parser::function()
5.31 +Parser::function(TokenKind token)
5.32 {
5.33 Local<String> name(zone_, expectName());
5.34 if (!name)
5.35 @@ -853,13 +860,29 @@
5.36 // The function name goes into the outer (global) scope.
5.37 assert(!scope_->enclosing());
5.38
5.39 + NamedFunction *fun;
5.40 if (BoundName *other = scope_->localLookup(name)) {
5.41 - redeclarationError(other);
5.42 - return NULL;
5.43 + // We allow a redeclaration if the new type is a public, and the old
5.44 + // type was a forward. However, the forward must come first.
5.45 + if (other->kind() != BoundName::FUNCTION) {
5.46 + redeclarationError(other);
5.47 + return NULL;
5.48 + }
5.49 +
5.50 + fun = other->toNamedFunction();
5.51 + if (!fun->isForward() || token != TOK_PUBLIC) {
5.52 + redeclarationError(other);
5.53 + return NULL;
5.54 + }
5.55 +
5.56 + // We've got the same name, but the original is a forward, so let it
5.57 + // slide and re-use the original declaration.
5.58 + fun->setImplemented(scanner_.begin());
5.59 + } else {
5.60 + fun = scope_->declareFunction(name, scanner_.begin(), token);
5.61 + if (!fun)
5.62 + return NULL;
5.63 }
5.64 - NamedFunction *fun = scope_->declareFunction(name, scanner_.begin());
5.65 - if (!fun)
5.66 - return NULL;
5.67
5.68 Scope *scope = enterScope(Scope::FUNCTION);
5.69 if (!scope)
5.70 @@ -897,9 +920,12 @@
5.71 return NULL;
5.72 }
5.73
5.74 - Statement *body = block();
5.75 - if (!body)
5.76 - return NULL;
5.77 + Statement *body = NULL;
5.78 + if (token != TOK_FORWARD) {
5.79 + body = block();
5.80 + if (!body)
5.81 + return NULL;
5.82 + }
5.83
5.84 scope_ = scope_->enclosing();
5.85 return new (pool_) FunctionStatement(pos, scope, fun, body, parameters);
5.86 @@ -924,18 +950,30 @@
5.87 break;
5.88
5.89 case TOK_NAME:
5.90 - if ((statement = function()) == NULL)
5.91 + if ((statement = function(TOK_NAME)) == NULL)
5.92 return NULL;
5.93 break;
5.94
5.95 + case TOK_FORWARD:
5.96 + case TOK_PUBLIC:
5.97 + {
5.98 + TokenKind kind = scanner_.scan();
5.99 + if ((statement = function(kind)) == NULL)
5.100 + return NULL;
5.101 + if (kind == TOK_FORWARD && !matchSemicolon())
5.102 + return NULL;
5.103 + break;
5.104 + }
5.105 +
5.106 case TOK_ENUM:
5.107 if ((statement = enum_()) == NULL)
5.108 return NULL;
5.109 - // :TODO: require semicolon
5.110 + if (!matchSemicolon())
5.111 + return NULL;
5.112 break;
5.113
5.114 default:
5.115 - fprintf(stderr, "expected function or global variable\n");
5.116 + cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
5.117 return NULL;
5.118 }
5.119
5.120 @@ -991,7 +1029,8 @@
5.121 prefix();
5.122 fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
5.123 indent();
5.124 - node->body()->accept(this);
5.125 + if (node->body())
5.126 + node->body()->accept(this);
5.127 unindent();
5.128 }
5.129 void visit(ExpressionStatement *node) {
6.1 --- a/jitcraft/Parser.h Sun Jul 08 15:23:48 2012 -0700
6.2 +++ b/jitcraft/Parser.h Sun Jul 08 16:49:17 2012 -0700
6.3 @@ -39,6 +39,7 @@
6.4 void redeclarationError(BoundName *name);
6.5 bool match(TokenKind kind);
6.6 bool expect(TokenKind kind);
6.7 + bool matchSemicolon();
6.8
6.9 Scope *enterScope(Scope::Kind kind);
6.10
6.11 @@ -66,7 +67,7 @@
6.12 Statement *enum_();
6.13 Statement *if_();
6.14 Statement *block(Scope *scope = NULL);
6.15 - Statement *function();
6.16 + Statement *function(TokenKind tok);
6.17 Statement *expressionStatement();
6.18 Statement *while_();
6.19 Statement *do_();
7.1 --- a/jitcraft/Scanner.cpp Sun Jul 08 15:23:48 2012 -0700
7.2 +++ b/jitcraft/Scanner.cpp Sun Jul 08 16:49:17 2012 -0700
7.3 @@ -365,6 +365,10 @@
7.4 return TOK_BREAK;
7.5 if (literal_ == "continue")
7.6 return TOK_CONTINUE;
7.7 + if (literal_ == "forward")
7.8 + return TOK_FORWARD;
7.9 + if (literal_ == "public")
7.10 + return TOK_PUBLIC;
7.11 return (c == ':') ? TOK_LABEL : TOK_NAME;
7.12 }
7.13
8.1 --- a/jitcraft/Scopes.cpp Sun Jul 08 15:23:48 2012 -0700
8.2 +++ b/jitcraft/Scopes.cpp Sun Jul 08 16:49:17 2012 -0700
8.3 @@ -111,12 +111,12 @@
8.4 }
8.5
8.6 NamedFunction *
8.7 -Scope::declareFunction(Handle<String> name, const SourcePosition &pos)
8.8 +Scope::declareFunction(Handle<String> name, const SourcePosition &pos, TokenKind token)
8.9 {
8.10 assert(!localLookup(name));
8.11 assert(kind() == GLOBAL);
8.12
8.13 - NamedFunction *fun = new (pool_) NamedFunction(this, name, pos);
8.14 + NamedFunction *fun = new (pool_) NamedFunction(this, name, pos, token);
8.15 if (!names_.append(fun))
8.16 return NULL;
8.17 return fun;
9.1 --- a/jitcraft/Scopes.h Sun Jul 08 15:23:48 2012 -0700
9.2 +++ b/jitcraft/Scopes.h Sun Jul 08 16:49:17 2012 -0700
9.3 @@ -81,7 +81,7 @@
9.4 BoundName *localLookup(Handle<String> name);
9.5 BoundName *lookup(Handle<String> name);
9.6
9.7 - NamedFunction *declareFunction(Handle<String> name, const SourcePosition &pos);
9.8 + NamedFunction *declareFunction(Handle<String> name, const SourcePosition &pos, TokenKind token);
9.9 Variable *declareVariable(Handle<String> name, const SourcePosition &pos);
9.10 Variable *declareArgument(Handle<String> name, const SourcePosition &pos);
9.11 NamedEnum *declareEnum(Handle<String> name, const SourcePosition &pos);
10.1 --- a/jitcraft/SemanticAnalysis.cpp Sun Jul 08 15:23:48 2012 -0700
10.2 +++ b/jitcraft/SemanticAnalysis.cpp Sun Jul 08 16:49:17 2012 -0700
10.3 @@ -558,8 +558,20 @@
10.4 Local<Type> funtype(zone_, zone_->types()->newFunction(returnType, args));
10.5 if (!funtype)
10.6 return false;
10.7 +
10.8 + // If the function already has a type, it was forward declared before, and
10.9 + // now this is our chance to type check the second declaration.
10.10 + if (node->fun()->type()) {
10.11 + Local<Type> forward(zone_, node->fun()->type());
10.12 + if (!Type::Compare(funtype, forward)) {
10.13 + cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
10.14 + return false;
10.15 + }
10.16 + node->fun()->setForwardType(forward);
10.17 + }
10.18
10.19 node->fun()->setType(funtype);
10.20 +
10.21 return true;
10.22 }
10.23
10.24 @@ -568,7 +580,8 @@
10.25 {
10.26 function_ = node->fun()->type();
10.27 scope_ = node->scope();
10.28 - node->body()->accept(this);
10.29 + if (node->body())
10.30 + node->body()->accept(this);
10.31 scope_ = NULL;
10.32 function_ = NULL;
10.33 }
10.34 @@ -689,6 +702,13 @@
10.35 return;
10.36 }
10.37
10.38 + // Currently, only calls from a NameProxy are possible.
10.39 + NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
10.40 + if (fun->isForward()) {
10.41 + cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
10.42 + return;
10.43 + }
10.44 +
10.45 for (unsigned i = 0; i < node->arguments()->length(); i++) {
10.46 // Note: we don't compute references unless the callee needs a
10.47 // reference type.
11.1 --- a/jitcraft/Token.h Sun Jul 08 15:23:48 2012 -0700
11.2 +++ b/jitcraft/Token.h Sun Jul 08 16:49:17 2012 -0700
11.3 @@ -54,6 +54,8 @@
11.4 _(DO, "<do>") \
11.5 _(BREAK, "<break>") \
11.6 _(CONTINUE, "<continue>") \
11.7 + _(FORWARD, "<forward>") \
11.8 + _(PUBLIC, "<public>") \
11.9 _(PLUS, "+") \
11.10 _(MINUS, "-") \
11.11 _(STAR, "*") \
12.1 --- a/jitcraft/Types.cpp Sun Jul 08 15:23:48 2012 -0700
12.2 +++ b/jitcraft/Types.cpp Sun Jul 08 16:49:17 2012 -0700
12.3 @@ -109,3 +109,44 @@
12.4 type->parameters_ = parameters;
12.5 return type;
12.6 }
12.7 +
12.8 +bool
12.9 +Type::Compare(Type *left, Type *right)
12.10 +{
12.11 + if (left->kind() != right->kind())
12.12 + return false;
12.13 +
12.14 + switch (left->kind()) {
12.15 + case Type::PRIMITIVE:
12.16 + return (left->primitive() == right->primitive() &&
12.17 + left->tag() == right->tag());
12.18 +
12.19 + case Type::ARRAY:
12.20 + {
12.21 + if (left->levels() != right->levels())
12.22 + return false;
12.23 + if (left->elements() != right->elements())
12.24 + return false;
12.25 + return Compare(left->contained(), right->contained());
12.26 + }
12.27 +
12.28 + case Type::FUNCTION:
12.29 + {
12.30 + if (!Compare(left->returnType(), right->returnType()))
12.31 + return false;
12.32 + if (left->parameters()->length() != right->parameters()->length())
12.33 + return false;
12.34 + for (unsigned i = 0; i < left->parameters()->length(); i++) {
12.35 + Type *leftparam = left->parameterAt(i);
12.36 + Type *rightparam = right->parameterAt(i);
12.37 + if (!Compare(leftparam, rightparam))
12.38 + return false;
12.39 + }
12.40 + return true;
12.41 + }
12.42 +
12.43 + default:
12.44 + assert(left->kind() == Type::REFERENCE);
12.45 + return Compare(left->contained(), right->contained());
12.46 + }
12.47 +}
13.1 --- a/jitcraft/Types.h Sun Jul 08 15:23:48 2012 -0700
13.2 +++ b/jitcraft/Types.h Sun Jul 08 16:49:17 2012 -0700
13.3 @@ -60,6 +60,8 @@
13.4 static Type *NewReference(Zone *zone, Handle<Type> contained);
13.5 static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters);
13.6
13.7 + static bool Compare(Type *left, Type *right);
13.8 +
13.9 static Type *cast(Object *obj) {
13.10 assert(!obj || obj->is(MapKind_Type));
13.11 return (Type *)obj;