Scanning, parsing, and static analysis now report errors properly.
authorDavid Anderson <dvander@alliedmods.net>
Mon Jul 02 01:24:57 2012 -0700 (2012-07-02)
changeset 2523e8b3d8e4e6
parent 24 03c6a312213b
child 26 a48382113da6
Scanning, parsing, and static analysis now report errors properly.
jitcraft/AST.h
jitcraft/CompileContext.cpp
jitcraft/CompileContext.h
jitcraft/Exception.cpp
jitcraft/Messages.h
jitcraft/Messages.tbl
jitcraft/NameBinding.cpp
jitcraft/NameBinding.h
jitcraft/Parser.cpp
jitcraft/Parser.h
jitcraft/Scanner.cpp
jitcraft/Scanner.h
jitcraft/Scopes.cpp
jitcraft/Scopes.h
jitcraft/SemanticAnalysis.cpp
jitcraft/SemanticAnalysis.h
jitcraft/Types.cpp
jitcraft/Types.h
jitcraft/jitcraft.vcxproj
jitcraft/main.cpp
     1.1 --- a/jitcraft/AST.h	Sun Jul 01 18:39:11 2012 -0700
     1.2 +++ b/jitcraft/AST.h	Mon Jul 02 01:24:57 2012 -0700
     1.3 @@ -57,6 +57,8 @@
     1.4  // Interface for AST nodes.
     1.5  class AstNode : public PoolObject
     1.6  {
     1.7 +    SourcePosition pos_;
     1.8 +
     1.9    public:
    1.10      enum Kind {
    1.11  #       define _(name) k##name,
    1.12 @@ -64,6 +66,11 @@
    1.13  #       undef _
    1.14          AstKind_Invalid
    1.15      };
    1.16 +
    1.17 +    AstNode(const SourcePosition &pos)
    1.18 +      : pos_(pos)
    1.19 +    {
    1.20 +    }
    1.21      
    1.22      virtual Kind kind() const = 0;
    1.23  
    1.24 @@ -73,6 +80,10 @@
    1.25  #undef _
    1.26  
    1.27      virtual void accept(AstVisitor *visitor) = 0;
    1.28 +
    1.29 +    const SourcePosition &pos() const {
    1.30 +        return pos_;
    1.31 +    }
    1.32  };
    1.33  
    1.34  class AstVisitor
    1.35 @@ -115,6 +126,11 @@
    1.36  
    1.37  class Statement : public AstNode
    1.38  {
    1.39 +  public:
    1.40 +    Statement(const SourcePosition &pos)
    1.41 +      : AstNode(pos)
    1.42 +    {
    1.43 +    }
    1.44  };
    1.45  
    1.46  class Expression : public AstNode
    1.47 @@ -122,8 +138,9 @@
    1.48      Type *type_;
    1.49  
    1.50    public:
    1.51 -    Expression()
    1.52 -      : type_(NULL)
    1.53 +    Expression(const SourcePosition &pos)
    1.54 +      : AstNode(pos),
    1.55 +        type_(NULL)
    1.56      {
    1.57      }
    1.58  
    1.59 @@ -135,14 +152,10 @@
    1.60      }
    1.61  };
    1.62  
    1.63 -class Declaration : public Statement
    1.64 -{
    1.65 -};
    1.66 -
    1.67  typedef PoolList<Statement *> StatementList;
    1.68  typedef std::vector<Expression *> ExpressionList;
    1.69  
    1.70 -class VariableDeclaration : public Declaration
    1.71 +class VariableDeclaration : public Statement
    1.72  {
    1.73      Variable *variable_;
    1.74      Expression *initialization_;
    1.75 @@ -150,8 +163,10 @@
    1.76      Name *tag_;
    1.77  
    1.78    public:
    1.79 -    VariableDeclaration(Variable *var, Name *tag, ExpressionList *postDimensions, Expression *initialization)
    1.80 -      : variable_(var),
    1.81 +    VariableDeclaration(const SourcePosition &pos, Variable *var, Name *tag,
    1.82 +                        ExpressionList *postDimensions, Expression *initialization)
    1.83 +      : Statement(pos),
    1.84 +        variable_(var),
    1.85          postDimensions_(postDimensions),
    1.86          initialization_(initialization),
    1.87          tag_(tag)
    1.88 @@ -209,8 +224,9 @@
    1.89      BoundName *binding_;
    1.90  
    1.91    public:
    1.92 -    NameProxy(Name *name, BoundName *binding)
    1.93 -      : name_(name),
    1.94 +    NameProxy(const SourcePosition &pos, Name *name, BoundName *binding)
    1.95 +      : Expression(pos),
    1.96 +        name_(name),
    1.97          binding_(binding)
    1.98      {
    1.99      }
   1.100 @@ -238,8 +254,9 @@
   1.101      int value_;
   1.102  
   1.103    public:
   1.104 -    IntegerLiteral(int value)
   1.105 -      : value_(value)
   1.106 +    IntegerLiteral(const SourcePosition &pos, int value)
   1.107 +      : Expression(pos),
   1.108 +        value_(value)
   1.109      {
   1.110      }
   1.111  
   1.112 @@ -259,8 +276,9 @@
   1.113      double value_;
   1.114  
   1.115    public:
   1.116 -    FloatLiteral(double value)
   1.117 -      : value_(value)
   1.118 +    FloatLiteral(const SourcePosition &pos, double value)
   1.119 +      : Expression(pos),
   1.120 +        value_(value)
   1.121      {
   1.122      }
   1.123  
   1.124 @@ -280,8 +298,9 @@
   1.125      ByteArray *string_;
   1.126  
   1.127    public:
   1.128 -    StringLiteral(ByteArray *array)
   1.129 -      : string_(array)
   1.130 +    StringLiteral(const SourcePosition &pos, ByteArray *array)
   1.131 +      : Expression(pos),
   1.132 +        string_(array)
   1.133      {
   1.134      }
   1.135  
   1.136 @@ -303,8 +322,9 @@
   1.137      TokenKind token_;
   1.138  
   1.139    public:
   1.140 -    BinaryExpression(TokenKind token, Expression *left, Expression *right)
   1.141 -      : token_(token),
   1.142 +    BinaryExpression(const SourcePosition &pos, TokenKind token, Expression *left, Expression *right)
   1.143 +      : Expression(pos),
   1.144 +        token_(token),
   1.145          left_(left),
   1.146          right_(right)
   1.147      {
   1.148 @@ -333,8 +353,9 @@
   1.149      Expression *right_;
   1.150  
   1.151    public:
   1.152 -    IndexExpression(Expression *left, Expression *right)
   1.153 -      : left_(left),
   1.154 +    IndexExpression(const SourcePosition &pos, Expression *left, Expression *right)
   1.155 +      : Expression(pos),
   1.156 +        left_(left),
   1.157          right_(right)
   1.158      {
   1.159      }
   1.160 @@ -359,8 +380,9 @@
   1.161      ExpressionList *arguments_;
   1.162  
   1.163    public:
   1.164 -    CallExpression(Expression *callee, ExpressionList *arguments)
   1.165 -      : callee_(callee),
   1.166 +    CallExpression(const SourcePosition &pos, Expression *callee, ExpressionList *arguments)
   1.167 +      : Expression(pos),
   1.168 +        callee_(callee),
   1.169          arguments_(arguments)
   1.170      {
   1.171      }
   1.172 @@ -388,9 +410,10 @@
   1.173      Statement *body_;
   1.174  
   1.175    public:
   1.176 -    ForStatement(Scope *scope, Statement *initialization,
   1.177 +    ForStatement(const SourcePosition &pos, Scope *scope, Statement *initialization,
   1.178                   Expression *condition, Statement *update, Statement *body)
   1.179 -      : scope_(scope),
   1.180 +      : Statement(pos),
   1.181 +        scope_(scope),
   1.182          initialization_(initialization),
   1.183          condition_(condition),
   1.184          update_(update),
   1.185 @@ -428,8 +451,9 @@
   1.186      Statement *body_;
   1.187  
   1.188    public:
   1.189 -    WhileStatement(TokenKind kind, Expression *condition, Statement *body)
   1.190 -      : token_(kind),
   1.191 +    WhileStatement(const SourcePosition &pos, TokenKind kind, Expression *condition, Statement *body)
   1.192 +      : Statement(pos),
   1.193 +        token_(kind),
   1.194          condition_(condition),
   1.195          body_(body)
   1.196      {
   1.197 @@ -457,8 +481,9 @@
   1.198      Expression *expression_;
   1.199  
   1.200    public:
   1.201 -    ReturnStatement(Expression *expression)
   1.202 -      : expression_(expression)
   1.203 +    ReturnStatement(const SourcePosition &pos, Expression *expression)
   1.204 +      : Statement(pos),
   1.205 +        expression_(expression)
   1.206      {
   1.207      }
   1.208  
   1.209 @@ -476,7 +501,8 @@
   1.210  class BreakStatement : public Statement
   1.211  {
   1.212    public:
   1.213 -    BreakStatement()
   1.214 +    BreakStatement(const SourcePosition &pos)
   1.215 +      : Statement(pos)
   1.216      {
   1.217      }
   1.218  
   1.219 @@ -491,7 +517,8 @@
   1.220  class ContinueStatement : public Statement
   1.221  {
   1.222    public:
   1.223 -    ContinueStatement()
   1.224 +    ContinueStatement(const SourcePosition &pos)
   1.225 +      : Statement(pos)
   1.226      {
   1.227      }
   1.228  
   1.229 @@ -510,8 +537,9 @@
   1.230      Expression *expression_;
   1.231  
   1.232    public:
   1.233 -    Assignment(TokenKind token, Expression *left, Expression *right)
   1.234 -      : token_(token),
   1.235 +    Assignment(const SourcePosition &pos, TokenKind token, Expression *left, Expression *right)
   1.236 +      : Expression(pos),
   1.237 +        token_(token),
   1.238          lvalue_(left),
   1.239          expression_(right)
   1.240      {
   1.241 @@ -540,7 +568,8 @@
   1.242  
   1.243    public:
   1.244      ExpressionStatement(Expression *expression)
   1.245 -      : expression_(expression)
   1.246 +      : Statement(expression->pos()),
   1.247 +        expression_(expression)
   1.248      {
   1.249      }
   1.250  
   1.251 @@ -561,8 +590,9 @@
   1.252      StatementList *statements_;
   1.253  
   1.254    public:
   1.255 -    BlockStatement(Scope *scope, StatementList *statements)
   1.256 -      : scope_(scope),
   1.257 +    BlockStatement(const SourcePosition &pos, Scope *scope, StatementList *statements)
   1.258 +      : Statement(pos),
   1.259 +        scope_(scope),
   1.260          statements_(statements)
   1.261      {
   1.262      }
   1.263 @@ -591,8 +621,10 @@
   1.264      ParameterList *parameters_;
   1.265  
   1.266    public:
   1.267 -    FunctionStatement(Scope *scope, NamedFunction *fun, Statement *body, ParameterList *parameters)
   1.268 -      : scope_(scope),
   1.269 +    FunctionStatement(const SourcePosition &pos, Scope *scope, NamedFunction *fun, Statement *body,
   1.270 +                      ParameterList *parameters)
   1.271 +      : Statement(pos),
   1.272 +        scope_(scope),
   1.273          fun_(fun),
   1.274          body_(body),
   1.275          parameters_(parameters)
   1.276 @@ -626,8 +658,9 @@
   1.277      Statement *ifFalse_;
   1.278  
   1.279    public:
   1.280 -    IfStatement(Expression *condition, Statement *ifTrue)
   1.281 -      : condition_(condition),
   1.282 +    IfStatement(const SourcePosition &pos, Expression *condition, Statement *ifTrue)
   1.283 +      : Statement(pos),
   1.284 +        condition_(condition),
   1.285          ifTrue_(ifTrue),
   1.286          ifFalse_(NULL)
   1.287      {
   1.288 @@ -672,8 +705,9 @@
   1.289      typedef std::vector<Entry> EntryList;
   1.290  
   1.291    public:
   1.292 -    EnumStatement(Name *name, EntryList *entries)
   1.293 -      : name_(name),
   1.294 +    EnumStatement(const SourcePosition &pos, Name *name, EntryList *entries)
   1.295 +      : Statement(pos),
   1.296 +        name_(name),
   1.297          entries_(entries)
   1.298      {
   1.299      }
   1.300 @@ -702,8 +736,9 @@
   1.301      bool postfix_;
   1.302  
   1.303    public:
   1.304 -    IncDecExpression(TokenKind token, Expression *expression, bool postfix)
   1.305 -      : token_(token),
   1.306 +    IncDecExpression(const SourcePosition &pos, TokenKind token, Expression *expression, bool postfix)
   1.307 +      : Expression(pos),
   1.308 +        token_(token),
   1.309          expression_(expression),
   1.310          postfix_(postfix)
   1.311      {
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/jitcraft/CompileContext.cpp	Mon Jul 02 01:24:57 2012 -0700
     2.3 @@ -0,0 +1,47 @@
     2.4 +/*
     2.5 + * Copyright (C) 2012 David Anderson
     2.6 + *
     2.7 + * This file is part of JITCraft.
     2.8 + *
     2.9 + * JITCraft is free software: you can redistribute it and/or modify it under
    2.10 + * the terms of the GNU General Public License as published by the Free
    2.11 + * Software Foundation, either version 3 of the License, or (at your option)
    2.12 + * any later version.
    2.13 + * 
    2.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    2.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    2.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License along with
    2.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    2.20 + */
    2.21 +#include <stdio.h>
    2.22 +#include "Scanner.h"
    2.23 +#include "CompileContext.h"
    2.24 +
    2.25 +using namespace jc;
    2.26 +
    2.27 +CompileContext::CompileContext(Zone *zone)
    2.28 +  : zone_(zone),
    2.29 +    failures_(0)
    2.30 +{
    2.31 +}
    2.32 +
    2.33 +void
    2.34 +CompileContext::reportErrorVa(const SourcePosition &pos, Message msg, va_list ap)
    2.35 +{
    2.36 +    fprintf(stderr, "error on line %d, col %d: ", pos.line, pos.col);
    2.37 +    vfprintf(stderr, Messages[msg].format, ap);
    2.38 +    fprintf(stderr, "\n");
    2.39 +
    2.40 +    failures_++;
    2.41 +}
    2.42 +
    2.43 +void
    2.44 +CompileContext::reportError(const SourcePosition &pos, Message msg, ...)
    2.45 +{
    2.46 +    va_list ap;
    2.47 +    va_start(ap, msg);
    2.48 +    reportErrorVa(pos, msg, ap);
    2.49 +    va_end(ap);
    2.50 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/jitcraft/CompileContext.h	Mon Jul 02 01:24:57 2012 -0700
     3.3 @@ -0,0 +1,47 @@
     3.4 +/*
     3.5 + * Copyright (C) 2012 David Anderson
     3.6 + *
     3.7 + * This file is part of JITCraft.
     3.8 + *
     3.9 + * JITCraft is free software: you can redistribute it and/or modify it under
    3.10 + * the terms of the GNU General Public License as published by the Free
    3.11 + * Software Foundation, either version 3 of the License, or (at your option)
    3.12 + * any later version.
    3.13 + * 
    3.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    3.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    3.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    3.17 + *
    3.18 + * You should have received a copy of the GNU General Public License along with
    3.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    3.20 + */
    3.21 +#ifndef _include_jitcraft_compile_context_h_
    3.22 +#define _include_jitcraft_compile_context_h_
    3.23 +
    3.24 +#include <stdarg.h>
    3.25 +#include "Messages.h"
    3.26 +
    3.27 +namespace jc {
    3.28 +
    3.29 +class Zone;
    3.30 +struct SourcePosition;
    3.31 +
    3.32 +class CompileContext
    3.33 +{
    3.34 +    Zone *zone_;
    3.35 +    unsigned failures_;
    3.36 +
    3.37 +  public:
    3.38 +    CompileContext(Zone *zone);
    3.39 +
    3.40 +    void reportErrorVa(const SourcePosition &pos, Message msg, va_list ap);
    3.41 +    void reportError(const SourcePosition &pos, Message msg, ...);
    3.42 +
    3.43 +    unsigned failures() const {
    3.44 +        return failures_;
    3.45 +    }
    3.46 +};
    3.47 +
    3.48 +}
    3.49 +
    3.50 +#endif // _include_jitcraft_compile_context_h_
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/jitcraft/Exception.cpp	Mon Jul 02 01:24:57 2012 -0700
     4.3 @@ -0,0 +1,31 @@
     4.4 +
     4.5 +/*
     4.6 + * Copyright (C) 2012 David Anderson
     4.7 + *
     4.8 + * This file is part of JITCraft.
     4.9 + *
    4.10 + * JITCraft is free software: you can redistribute it and/or modify it under
    4.11 + * the terms of the GNU General Public License as published by the Free
    4.12 + * Software Foundation, either version 3 of the License, or (at your option)
    4.13 + * any later version.
    4.14 + * 
    4.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    4.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    4.18 + *
    4.19 + * You should have received a copy of the GNU General Public License along with
    4.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    4.21 + */
    4.22 +#include "Utility.h"
    4.23 +#include "Messages.h"
    4.24 +
    4.25 +using namespace jc;
    4.26 +
    4.27 +const MessageInfo jc::Messages[] =
    4.28 +{
    4.29 +#define MSG(Name, Type, String) \
    4.30 +    { MessageType_##Type, String },
    4.31 +# include "Messages.tbl"
    4.32 +#undef MSG
    4.33 +    { MessageType_SyntaxError, NULL }
    4.34 +};
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/jitcraft/Messages.h	Mon Jul 02 01:24:57 2012 -0700
     5.3 @@ -0,0 +1,46 @@
     5.4 +/*
     5.5 + * Copyright (C) 2012 David Anderson
     5.6 + *
     5.7 + * This file is part of JITCraft.
     5.8 + *
     5.9 + * JITCraft is free software: you can redistribute it and/or modify it under
    5.10 + * the terms of the GNU General Public License as published by the Free
    5.11 + * Software Foundation, either version 3 of the License, or (at your option)
    5.12 + * any later version.
    5.13 + * 
    5.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    5.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    5.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    5.17 + *
    5.18 + * You should have received a copy of the GNU General Public License along with
    5.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    5.20 + */
    5.21 +#ifndef _include_jitcraft_messages_h_
    5.22 +#define _include_jitcraft_messages_h_
    5.23 +
    5.24 +namespace jc {
    5.25 +
    5.26 +enum MessageType
    5.27 +{
    5.28 +    MessageType_SyntaxError
    5.29 +};
    5.30 +
    5.31 +enum Message
    5.32 +{
    5.33 +#define MSG(Name, Type, String)     Message_##Name,
    5.34 +# include "Messages.tbl"
    5.35 +#undef MSG
    5.36 +    MessageType_Total
    5.37 +};
    5.38 +
    5.39 +struct MessageInfo
    5.40 +{
    5.41 +    MessageType type;
    5.42 +    const char *format;
    5.43 +};
    5.44 +
    5.45 +extern const MessageInfo Messages[];
    5.46 +
    5.47 +}
    5.48 +
    5.49 +#endif // _include_jitcraft_messages_h_
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/jitcraft/Messages.tbl	Mon Jul 02 01:24:57 2012 -0700
     6.3 @@ -0,0 +1,40 @@
     6.4 +MSG(OutOfMemory,                    SyntaxError,            "out of memory")
     6.5 +MSG(UnterminatedComment,            SyntaxError,            "unterminated comment")
     6.6 +MSG(UnexpectedCharacter,            SyntaxError,            "unexpected character '%c' (code %02X)")
     6.7 +MSG(UnterminatedString,             SyntaxError,            "unterminated string")
     6.8 +MSG(UnknownEscapeCode,              SyntaxError,            "unknown escape code '%c'")
     6.9 +MSG(ExpectedDigitForFloat,          SyntaxError,            "expected digit in float literal, got '%c'")
    6.10 +MSG(WrongToken,                     SyntaxError,            "expected token '%s', got '%s'")
    6.11 +MSG(ExpectedExpression,             SyntaxError,            "expected expression, got '%s'")
    6.12 +MSG(RedeclaredName,                 SyntaxError,            "name '%s' was redeclared (previous at line %d, col %d)")
    6.13 +MSG(ExpectedLValue,                 SyntaxError,            "impossible assignment, expected l-value")
    6.14 +MSG(MaximumArrayDepth,              SyntaxError,            "maximum array dimension depth exceeded")
    6.15 +MSG(ArrayInitializerDepth,          SyntaxError,            "array declaration and initializer have different dimension counts")
    6.16 +MSG(BadArraySize,                   SyntaxError,            "array size must be positive")
    6.17 +MSG(ArraySizeTooBig,                SyntaxError,            "array size is too big")
    6.18 +MSG(EnumFieldNotConstant,           SyntaxError,            "enum fields must be constant integers")
    6.19 +MSG(BreakOutsideLoop,               SyntaxError,            "break occurs outside any loop")
    6.20 +MSG(ContinueOutsideLoop,            SyntaxError,            "continue occurs outside any loop")
    6.21 +MSG(InvalidEnumName,                SyntaxError,            "invalid enumeration name")
    6.22 +MSG(IndexMustBeInteger,             SyntaxError,            "array index must be integer")
    6.23 +MSG(IndexBaseMustBeArray,           SyntaxError,            "cannot index into non-array")
    6.24 +MSG(ArrayIsNotBoolean,              SyntaxError,            "cannot convert an array to boolean")
    6.25 +MSG(CalleeNotFunction,              SyntaxError,            "callee is not a function")
    6.26 +MSG(ArgumentCountMismatch,          SyntaxError,            "argument counts do not match")
    6.27 +MSG(CannotAssignArrayToScalar,      SyntaxError,            "cannot coerce an array to a scalar")
    6.28 +MSG(UnsupportedType,                SyntaxError,            "unsupported type")
    6.29 +MSG(TagMismatch,                    SyntaxError,            "tag mismatch (expected '%s', got '%s')")
    6.30 +MSG(ArrayDimensionsMismatch,        SyntaxError,            "number of array dimensions does not match")
    6.31 +MSG(ExpectedArray,                  SyntaxError,            "expected array")
    6.32 +MSG(ArrayDimensionSizeMismatch,     SyntaxError,            "array dimension sizes do not match (level %d)")
    6.33 +MSG(ArrayDimensionNotInteger,       SyntaxError,            "array dimension size must be an integer expression")
    6.34 +MSG(ArrayNotSupported,              SyntaxError,            "array declaration not yet supported")
    6.35 +MSG(ArrayInitializerUnknown,        SyntaxError,            "array initialized size is not known")
    6.36 +MSG(DynamicArrayHasInitializer,     SyntaxError,            "dynamic arrays cannot have initializers")
    6.37 +MSG(ArraySizeNotSpecified,          SyntaxError,            "array size was not specified")
    6.38 +MSG(ArraySizeCannotBeDetermined,    SyntaxError,            "array size cannot be determined from initializer")
    6.39 +MSG(ArrayAssignmentTooBig,          SyntaxError,            "destination array is too small")
    6.40 +MSG(CannotDeclareStringCell,        SyntaxError,            "cannot declare a String cell")
    6.41 +MSG(BinaryTypeError,                SyntaxError,            "operator '%s' does not support types '%s' and '%s'")
    6.42 +MSG(ArraySizeNotKnown,              SyntaxError,            "array size is not known")
    6.43 +MSG(UnaryTypeError,                 SyntaxError,            "operator '%s' does not support type '%s'")
    6.44 \ No newline at end of file
     7.1 --- a/jitcraft/NameBinding.cpp	Sun Jul 01 18:39:11 2012 -0700
     7.2 +++ b/jitcraft/NameBinding.cpp	Mon Jul 02 01:24:57 2012 -0700
     7.3 @@ -19,20 +19,21 @@
     7.4  
     7.5  using namespace jc;
     7.6  
     7.7 -BoundName::BoundName(Scope *scope, Name *name)
     7.8 +BoundName::BoundName(Scope *scope, Name *name, const SourcePosition &pos)
     7.9    : scope_(scope),
    7.10      name_(name),
    7.11 -    type_(NULL)
    7.12 +    type_(NULL),
    7.13 +    pos_(pos)
    7.14  {
    7.15  }
    7.16  
    7.17 -NamedFunction::NamedFunction(Scope *scope, Name *name)
    7.18 -  : BoundName(scope, name)
    7.19 +NamedFunction::NamedFunction(Scope *scope, Name *name, const SourcePosition &pos)
    7.20 +  : BoundName(scope, name, pos)
    7.21  {
    7.22  }
    7.23  
    7.24 -Variable::Variable(Scope *scope, Name *name)
    7.25 -  : BoundName(scope, name),
    7.26 +Variable::Variable(Scope *scope, Name *name, const SourcePosition &pos)
    7.27 +  : BoundName(scope, name, pos),
    7.28      location_(UNALLOCATED)
    7.29  {
    7.30  }
     8.1 --- a/jitcraft/NameBinding.h	Sun Jul 01 18:39:11 2012 -0700
     8.2 +++ b/jitcraft/NameBinding.h	Mon Jul 02 01:24:57 2012 -0700
     8.3 @@ -21,6 +21,7 @@
     8.4  #include "PoolAllocator.h"
     8.5  #include "StringPool.h"
     8.6  #include "Types.h"
     8.7 +#include "Scanner.h"
     8.8  
     8.9  namespace jc {
    8.10  
    8.11 @@ -36,6 +37,7 @@
    8.12      Name *name_;
    8.13      Scope *scope_;
    8.14      Type *type_;
    8.15 +    SourcePosition pos_;
    8.16  
    8.17    public:
    8.18      enum Kind {
    8.19 @@ -45,14 +47,14 @@
    8.20        CONSTANT
    8.21      };
    8.22  
    8.23 -    BoundName(Scope *scope, Name *name);
    8.24 +    BoundName(Scope *scope, Name *name, const SourcePosition &pos);
    8.25  
    8.26      virtual Kind kind() const = 0;
    8.27  
    8.28      Name *name() const {
    8.29          return name_;
    8.30      }
    8.31 -    Scope  *scope() const {
    8.32 +    Scope *scope() const {
    8.33          return scope_;
    8.34      }
    8.35      Variable *toVariable() {
    8.36 @@ -73,6 +75,9 @@
    8.37      void setType(Type *type) {
    8.38          type_ = type;
    8.39      }
    8.40 +    const SourcePosition &pos() {
    8.41 +        return pos_;
    8.42 +    }
    8.43  };
    8.44  
    8.45  class NamedFunction : public BoundName
    8.46 @@ -80,7 +85,7 @@
    8.47      unsigned slot_;
    8.48  
    8.49    public:
    8.50 -    NamedFunction(Scope *scope, Name *name);
    8.51 +    NamedFunction(Scope *scope, Name *name, const SourcePosition &pos);
    8.52  
    8.53      Kind kind() const {
    8.54          return FUNCTION;
    8.55 @@ -96,8 +101,8 @@
    8.56  class NamedEnum : public BoundName
    8.57  {
    8.58    public:
    8.59 -    NamedEnum(Scope *scope, Name *name)
    8.60 -      : BoundName(scope, name)
    8.61 +    NamedEnum(Scope *scope, Name *name, const SourcePosition &pos)
    8.62 +      : BoundName(scope, name, pos)
    8.63      {
    8.64      }
    8.65  
    8.66 @@ -112,8 +117,8 @@
    8.67      Type *type_;
    8.68  
    8.69    public:
    8.70 -    NamedConstant(Scope *scope, Name *name)
    8.71 -      : BoundName(scope, name),
    8.72 +    NamedConstant(Scope *scope, Name *name, const SourcePosition &pos)
    8.73 +      : BoundName(scope, name, pos),
    8.74          type_(NULL)
    8.75      {
    8.76      }
    8.77 @@ -142,7 +147,7 @@
    8.78          PARAMETER
    8.79      };
    8.80  
    8.81 -    Variable(Scope *scope, Name *name);
    8.82 +    Variable(Scope *scope, Name *name, const SourcePosition &pos);
    8.83  
    8.84      Kind kind() const {
    8.85          return VARIABLE;
     9.1 --- a/jitcraft/Parser.cpp	Sun Jul 01 18:39:11 2012 -0700
     9.2 +++ b/jitcraft/Parser.cpp	Mon Jul 02 01:24:57 2012 -0700
     9.3 @@ -23,10 +23,11 @@
     9.4  
     9.5  using namespace jc;
     9.6  
     9.7 -Parser::Parser(const char *stream, size_t length)
     9.8 -  : pool_(ZONE()->pool()),
     9.9 +Parser::Parser(CompileContext &cc, const char *stream, size_t length)
    9.10 +  : cc_(cc),
    9.11 +    pool_(ZONE()->pool()),
    9.12      strings_(pool_),
    9.13 -    scanner_(stream, length),
    9.14 +    scanner_(cc, stream, length),
    9.15      scope_(NULL),
    9.16      unbound_(NULL)
    9.17  {
    9.18 @@ -48,7 +49,7 @@
    9.19      TokenKind got = scanner_.scan();
    9.20      if (got == kind)
    9.21          return true;
    9.22 -    fprintf(stderr, "error: expected %s, got %s\n", TokenNames[kind], TokenNames[got]);
    9.23 +    cc_.reportError(scanner_.begin(), Message_WrongToken, TokenNames[kind], TokenNames[got]);
    9.24      return false;
    9.25  }
    9.26  
    9.27 @@ -65,7 +66,7 @@
    9.28  Parser::bind(Name *name)
    9.29  {
    9.30      BoundName *bound = scope_->lookup(name);
    9.31 -    NameProxy *proxy = new (pool_) NameProxy(name, bound);
    9.32 +    NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), name, bound);
    9.33      if (!bound)
    9.34          unbound_->push_back(proxy);
    9.35      return proxy;
    9.36 @@ -90,10 +91,17 @@
    9.37      return strings_.add(scanner_.literal());
    9.38  }
    9.39  
    9.40 +void
    9.41 +Parser::redeclarationError(BoundName *other)
    9.42 +{
    9.43 +    cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->pos().line, other->pos().col);
    9.44 +}
    9.45 +
    9.46  Expression *
    9.47  Parser::primitive()
    9.48  {
    9.49 -    switch (scanner_.peek()) {
    9.50 +    TokenKind kind = scanner_.peek();
    9.51 +    switch (kind) {
    9.52        case TOK_NAME:
    9.53        {
    9.54          scanner_.scan();
    9.55 @@ -105,14 +113,14 @@
    9.56        {
    9.57          scanner_.scan();
    9.58          double value = Scanner::ParseDouble(scanner_.literal());
    9.59 -        return new (pool_) FloatLiteral(value);
    9.60 +        return new (pool_) FloatLiteral(scanner_.begin(), value);
    9.61        }
    9.62  
    9.63        case TOK_INTEGER_LITERAL:
    9.64        {
    9.65          scanner_.scan();
    9.66          int value = atoi(scanner_.literal());
    9.67 -        return new (pool_) IntegerLiteral(value);
    9.68 +        return new (pool_) IntegerLiteral(scanner_.begin(), value);
    9.69        }
    9.70  
    9.71        case TOK_STRING_LITERAL:
    9.72 @@ -123,13 +131,13 @@
    9.73          if (!array)
    9.74              return NULL;
    9.75          memcpy(array->raw(), scanner_.literal(), scanner_.literal_length());
    9.76 -
    9.77 -        return new (pool_) StringLiteral(array);
    9.78 +        return new (pool_) StringLiteral(scanner_.begin(), array);
    9.79        }
    9.80  
    9.81        default:
    9.82        {
    9.83 -        fprintf(stderr, "error: expected expression!\n");
    9.84 +        if (kind != TOK_ERROR)
    9.85 +            cc_.reportError(scanner_.begin(), Message_ExpectedExpression, TokenNames[kind]);
    9.86          return NULL;
    9.87        }
    9.88      }
    9.89 @@ -160,6 +168,7 @@
    9.90  {
    9.91      ExpressionList *arguments = new ExpressionList();
    9.92  
    9.93 +    SourcePosition pos = scanner_.begin();
    9.94      expect(TOK_LPAREN);
    9.95      
    9.96      if (!match(TOK_RPAREN)) {
    9.97 @@ -178,7 +187,7 @@
    9.98              return NULL;
    9.99      }
   9.100  
   9.101 -    return new (pool_) CallExpression(callee, arguments);
   9.102 +    return new (pool_) CallExpression(pos, callee, arguments);
   9.103  }
   9.104  
   9.105  Expression *
   9.106 @@ -186,6 +195,7 @@
   9.107  {
   9.108      expect(TOK_LBRACKET);
   9.109      
   9.110 +    SourcePosition pos = scanner_.begin();
   9.111      Expression *expr = expression();
   9.112      if (!expr)
   9.113          return NULL;
   9.114 @@ -193,7 +203,7 @@
   9.115      if (!expect(TOK_RBRACKET))
   9.116          return NULL;
   9.117  
   9.118 -    return new (pool_) IndexExpression(left, expr);
   9.119 +    return new (pool_) IndexExpression(pos, left, expr);
   9.120  }
   9.121  
   9.122  Expression *
   9.123 @@ -228,6 +238,7 @@
   9.124  {
   9.125      TokenKind token = scanner_.peek();
   9.126  
   9.127 +    SourcePosition pos = scanner_.begin();
   9.128      switch (token) {
   9.129        case TOK_INCREMENT:
   9.130        case TOK_DECREMENT:
   9.131 @@ -237,16 +248,17 @@
   9.132          if (!expr)
   9.133              return NULL;
   9.134  
   9.135 -        return new (pool_) IncDecExpression(token, expr, false);
   9.136 +        return new (pool_) IncDecExpression(pos, token, expr, false);
   9.137        }
   9.138      }
   9.139  
   9.140 +
   9.141      Expression *expr = primary();
   9.142  
   9.143      token = scanner_.peek();
   9.144      if (token == TOK_INCREMENT || token == TOK_DECREMENT) {
   9.145          scanner_.scan();
   9.146 -        return new (pool_) IncDecExpression(token, expr, true);
   9.147 +        return new (pool_) IncDecExpression(pos, token, expr, true);
   9.148      }
   9.149  
   9.150      return expr;
   9.151 @@ -259,11 +271,12 @@
   9.152      do {
   9.153          if (!match(TOK_SLASH) && !match(TOK_STAR))
   9.154              break;
   9.155 +        SourcePosition pos = scanner_.begin();
   9.156          TokenKind kind = scanner_.last();
   9.157          Expression *right = unary();
   9.158          if (!right)
   9.159              return NULL;
   9.160 -        left = new (pool_) BinaryExpression(kind, left, right);
   9.161 +        left = new (pool_) BinaryExpression(pos, kind, left, right);
   9.162      } while (left);
   9.163      return left;
   9.164  }
   9.165 @@ -275,11 +288,12 @@
   9.166      while (left) {
   9.167          if (!match(TOK_PLUS) && !match(TOK_MINUS))
   9.168              break;
   9.169 +        SourcePosition pos = scanner_.begin();
   9.170          TokenKind kind = scanner_.last();
   9.171          Expression *right = multiplication();
   9.172          if (!right)
   9.173              return NULL;
   9.174 -        left = new (pool_) BinaryExpression(kind, left, right);
   9.175 +        left = new (pool_) BinaryExpression(pos, kind, left, right);
   9.176      }
   9.177      return left;
   9.178  }
   9.179 @@ -291,11 +305,12 @@
   9.180      while (left) {
   9.181          if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
   9.182              break;
   9.183 +        SourcePosition pos = scanner_.begin();
   9.184          TokenKind kind = scanner_.last();
   9.185          Expression *right = addition();
   9.186          if (!right)
   9.187              return NULL;
   9.188 -        left = new (pool_) BinaryExpression(kind, left, right);
   9.189 +        left = new (pool_) BinaryExpression(pos, kind, left, right);
   9.190      }
   9.191      return left;
   9.192  }
   9.193 @@ -307,10 +322,11 @@
   9.194      while (left) {
   9.195          if (!match(TOK_BITAND))
   9.196              break;
   9.197 +        SourcePosition pos = scanner_.begin();
   9.198          Expression *right = shift();
   9.199          if (!right)
   9.200              return NULL;
   9.201 -        left = new (pool_) BinaryExpression(TOK_BITAND, left, right);
   9.202 +        left = new (pool_) BinaryExpression(pos, TOK_BITAND, left, right);
   9.203      }
   9.204      return left;
   9.205  }
   9.206 @@ -322,10 +338,11 @@
   9.207      while (left) {
   9.208          if (!match(TOK_BITXOR))
   9.209              break;
   9.210 +        SourcePosition pos = scanner_.begin();
   9.211          Expression *right = shift();
   9.212          if (!right)
   9.213              return NULL;
   9.214 -        left = new (pool_) BinaryExpression(TOK_BITXOR, left, right);
   9.215 +        left = new (pool_) BinaryExpression(pos, TOK_BITXOR, left, right);
   9.216      }
   9.217      return left;
   9.218  }
   9.219 @@ -337,10 +354,11 @@
   9.220      while (left) {
   9.221          if (!match(TOK_BITOR))
   9.222              break;
   9.223 +        SourcePosition pos = scanner_.begin();
   9.224          Expression *right = shift();
   9.225          if (!right)
   9.226              return NULL;
   9.227 -        left = new (pool_) BinaryExpression(TOK_BITOR, left, right);
   9.228 +        left = new (pool_) BinaryExpression(pos, TOK_BITOR, left, right);
   9.229      }
   9.230      return left;
   9.231  }
   9.232 @@ -354,10 +372,11 @@
   9.233          if (kind < TOK_LT || kind > TOK_GE)
   9.234              break;
   9.235          scanner_.scan();
   9.236 +        SourcePosition pos = scanner_.begin();
   9.237          Expression *right = shift();
   9.238          if (!right)
   9.239              return NULL;
   9.240 -        left = new (pool_) BinaryExpression(kind, left, right);
   9.241 +        left = new (pool_) BinaryExpression(pos, kind, left, right);
   9.242      }
   9.243      return left;
   9.244  }
   9.245 @@ -370,10 +389,11 @@
   9.246          if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
   9.247              break;
   9.248          TokenKind kind = scanner_.last();
   9.249 +        SourcePosition pos = scanner_.begin();
   9.250          Expression *right = relational();
   9.251          if (!right)
   9.252              return NULL;
   9.253 -        left = new (pool_) BinaryExpression(kind, left, right);
   9.254 +        left = new (pool_) BinaryExpression(pos, kind, left, right);
   9.255      }
   9.256      return left;
   9.257  }
   9.258 @@ -387,11 +407,12 @@
   9.259          if (token != TOK_ASSIGN && (token < TOK_ASSIGN_ADD || token > TOK_ASSIGN_SHL))
   9.260              break;
   9.261          scanner_.scan();
   9.262 +        SourcePosition pos = scanner_.begin();
   9.263          Expression *expr = equals();
   9.264          if (!expr)
   9.265              return NULL;
   9.266  
   9.267 -        left = new (pool_) Assignment(token, left, expr);
   9.268 +        left = new (pool_) Assignment(pos, token, left, expr);
   9.269      }
   9.270      return left;
   9.271  }
   9.272 @@ -405,13 +426,16 @@
   9.273  Statement *
   9.274  Parser::while_()
   9.275  {
   9.276 +    SourcePosition pos = scanner_.begin();
   9.277      scanner_.scan();
   9.278  
   9.279      if (!expect(TOK_LPAREN))
   9.280          return NULL;
   9.281 +
   9.282      Expression *condition = expression();
   9.283      if (!condition)
   9.284          return NULL;
   9.285 +
   9.286      if (!expect(TOK_RPAREN))
   9.287          return NULL;
   9.288  
   9.289 @@ -419,12 +443,13 @@
   9.290      if (!body)
   9.291          return NULL;
   9.292  
   9.293 -    return new (pool_) WhileStatement(TOK_WHILE, condition, body);
   9.294 +    return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
   9.295  }
   9.296  
   9.297  Statement *
   9.298  Parser::do_()
   9.299  {
   9.300 +    SourcePosition pos = scanner_.begin();
   9.301      scanner_.scan();
   9.302  
   9.303      Statement *body = block();
   9.304 @@ -442,12 +467,13 @@
   9.305      if (!expect(TOK_RPAREN))
   9.306          return NULL;
   9.307  
   9.308 -    return new (pool_) WhileStatement(TOK_DO, condition, body);
   9.309 +    return new (pool_) WhileStatement(pos, TOK_DO, condition, body);
   9.310  }
   9.311  
   9.312  Statement *
   9.313  Parser::forStatement()
   9.314  {
   9.315 +    SourcePosition pos = scanner_.begin();
   9.316      scanner_.scan();
   9.317      if (!expect(TOK_LPAREN))
   9.318          return NULL;
   9.319 @@ -492,7 +518,7 @@
   9.320          blockScope = scope_->unlinkIfEmpty();
   9.321          scope_ = scope_->enclosing();
   9.322      }
   9.323 -    return new (pool_) ForStatement(blockScope, decl, condition, update, body);
   9.324 +    return new (pool_) ForStatement(pos, blockScope, decl, condition, update, body);
   9.325  }
   9.326  
   9.327  VariableDeclaration *
   9.328 @@ -509,6 +535,15 @@
   9.329      if (!name)
   9.330          return NULL;
   9.331  
   9.332 +    if (BoundName *other = scope_->localLookup(name)) {
   9.333 +        redeclarationError(other);
   9.334 +        return NULL;
   9.335 +    }
   9.336 +
   9.337 +    Variable *var = scope_->declareVariable(name, scanner_.begin());
   9.338 +    if (!var)
   9.339 +        return NULL;
   9.340 +
   9.341      ExpressionList *postDimensions = NULL;
   9.342      if (scanner_.peek() == TOK_LBRACKET) {
   9.343          postDimensions = new ExpressionList();
   9.344 @@ -529,21 +564,14 @@
   9.345          if ((expr = expression()) == NULL)
   9.346              return NULL;
   9.347      }
   9.348 -    
   9.349 -    if (scope_->localLookup(name)) {
   9.350 -        redeclarationError();
   9.351 -        return NULL;
   9.352 -    }
   9.353  
   9.354 -    Variable *var = scope_->declareVariable(name);
   9.355 -    VariableDeclaration *decl = new (pool_) VariableDeclaration(var, tag, postDimensions, expr);
   9.356 -
   9.357 -    return decl;
   9.358 +    return new (pool_) VariableDeclaration(var->pos(), var, tag, postDimensions, expr);
   9.359  }
   9.360  
   9.361  Statement *
   9.362  Parser::returnStatement()
   9.363  {
   9.364 +    SourcePosition pos = scanner_.begin();
   9.365      if (!expect(TOK_RETURN))
   9.366          return NULL;
   9.367  
   9.368 @@ -551,7 +579,7 @@
   9.369      if (!expr)
   9.370          return NULL;
   9.371  
   9.372 -    return new (pool_) ReturnStatement(expr);
   9.373 +    return new (pool_) ReturnStatement(pos, expr);
   9.374  }
   9.375  
   9.376  Statement *
   9.377 @@ -570,6 +598,7 @@
   9.378      if (!expect(TOK_LBRACE))
   9.379          return NULL;
   9.380  
   9.381 +    SourcePosition pos = scanner_.begin();
   9.382      if (!enterScope(Scope::BLOCK))
   9.383          return NULL;
   9.384  
   9.385 @@ -582,7 +611,7 @@
   9.386      }
   9.387  
   9.388      Scope *blockScope = scope_->unlinkIfEmpty();
   9.389 -    BlockStatement *block = new (pool_) BlockStatement(blockScope, statements);
   9.390 +    BlockStatement *block = new (pool_) BlockStatement(pos, blockScope, statements);
   9.391  
   9.392      scope_ = scope_->enclosing();
   9.393      return block;
   9.394 @@ -592,7 +621,8 @@
   9.395  Parser::if_()
   9.396  {
   9.397      expect(TOK_IF);
   9.398 -
   9.399 +    
   9.400 +    SourcePosition pos = scanner_.begin();
   9.401      if (!expect(TOK_LPAREN))
   9.402          return NULL;
   9.403  
   9.404 @@ -607,7 +637,7 @@
   9.405      if (!ifTrue)
   9.406          return NULL;
   9.407  
   9.408 -    IfStatement *outer = new (pool_) IfStatement(cond, ifTrue);
   9.409 +    IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue);
   9.410  
   9.411      IfStatement *last = outer;
   9.412      while (match(TOK_ELSE)) {
   9.413 @@ -623,6 +653,7 @@
   9.414          if (!expect(TOK_IF))
   9.415              return false;
   9.416  
   9.417 +        SourcePosition pos = scanner_.begin();
   9.418          if (!expect(TOK_LPAREN))
   9.419              return NULL;
   9.420  
   9.421 @@ -637,7 +668,7 @@
   9.422          if (!otherIfTrue)
   9.423              return NULL;
   9.424  
   9.425 -        IfStatement *inner = new (pool_) IfStatement(otherCond, otherIfTrue);
   9.426 +        IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue);
   9.427          last->setIfFalse(inner);
   9.428          last = inner;
   9.429      }
   9.430 @@ -667,12 +698,12 @@
   9.431  
   9.432          case TOK_BREAK:
   9.433            scanner_.scan();
   9.434 -          statement = new (pool_) BreakStatement();
   9.435 +          statement = new (pool_) BreakStatement(scanner_.begin());
   9.436            break;
   9.437  
   9.438          case TOK_CONTINUE:
   9.439            scanner_.scan();
   9.440 -          statement = new (pool_) ContinueStatement();
   9.441 +          statement = new (pool_) ContinueStatement(scanner_.begin());
   9.442            break;
   9.443  
   9.444          case TOK_DO:
   9.445 @@ -713,18 +744,19 @@
   9.446  {
   9.447      expect(TOK_ENUM);
   9.448  
   9.449 +    SourcePosition pos = scanner_.begin();
   9.450 +
   9.451      Name *name = NULL;
   9.452      if (match(TOK_NAME)) {
   9.453          if ((name = strings_.add(scanner_.literal())) == NULL)
   9.454              return NULL;
   9.455  
   9.456 -        if (scope_->localLookup(name)) {
   9.457 -            redeclarationError();
   9.458 +        if (BoundName *other = scope_->localLookup(name)) {
   9.459 +            redeclarationError(other);
   9.460              return NULL;
   9.461          }
   9.462  
   9.463 -        NamedEnum *e = scope_->declareEnum(name);
   9.464 -        if (!e)
   9.465 +        if (!scope_->declareEnum(name, scanner_.begin()))
   9.466              return NULL;
   9.467      }
   9.468  
   9.469 @@ -741,12 +773,12 @@
   9.470          if (!name)
   9.471              return NULL;
   9.472  
   9.473 -        if (scope_->localLookup(name)) {
   9.474 -            redeclarationError();
   9.475 +        if (BoundName *other = scope_->localLookup(name)) {
   9.476 +            redeclarationError(other);
   9.477              return NULL;
   9.478          }
   9.479  
   9.480 -        NamedConstant *constant = scope_->declareConstant(name);
   9.481 +        NamedConstant *constant = scope_->declareConstant(name, scanner_.begin());
   9.482          if (!constant)
   9.483              return NULL;
   9.484  
   9.485 @@ -761,7 +793,7 @@
   9.486      if (!expect(TOK_RBRACE))
   9.487          return NULL;
   9.488  
   9.489 -    return new (pool_) EnumStatement(name, entries);
   9.490 +    return new (pool_) EnumStatement(pos, name, entries);
   9.491  }
   9.492  
   9.493  Statement *
   9.494 @@ -771,14 +803,16 @@
   9.495      if (!name)
   9.496          return NULL;
   9.497  
   9.498 +    SourcePosition pos = scanner_.begin();
   9.499 +
   9.500      // The function name goes into the outer (global) scope.
   9.501      assert(!scope_->enclosing());
   9.502  
   9.503 -    if (scope_->localLookup(name)) {
   9.504 -        redeclarationError();
   9.505 +    if (BoundName *other = scope_->localLookup(name)) {
   9.506 +        redeclarationError(other);
   9.507          return NULL;
   9.508      }
   9.509 -    NamedFunction *fun = scope_->declareFunction(name);
   9.510 +    NamedFunction *fun = scope_->declareFunction(name, scanner_.begin());
   9.511      if (!fun)
   9.512          return NULL;
   9.513  
   9.514 @@ -798,11 +832,11 @@
   9.515              if (!name)
   9.516                  return NULL;
   9.517  
   9.518 -            if (scope_->localLookup(name)) {
   9.519 -                redeclarationError();
   9.520 +            if (BoundName *other = scope_->localLookup(name)) {
   9.521 +                redeclarationError(other);
   9.522                  return NULL;
   9.523              }
   9.524 -            Variable *arg = scope_->declareArgument(name);
   9.525 +            Variable *arg = scope_->declareArgument(name, scanner_.begin());
   9.526              if (!arg)
   9.527                  return NULL;
   9.528  
   9.529 @@ -821,7 +855,7 @@
   9.530          return NULL;
   9.531  
   9.532      scope_ = scope_->enclosing();
   9.533 -    return new (pool_) FunctionStatement(scope, fun, body, parameters);
   9.534 +    return new (pool_) FunctionStatement(pos, scope, fun, body, parameters);
   9.535  }
   9.536  
   9.537  ParseTree *
    10.1 --- a/jitcraft/Parser.h	Sun Jul 01 18:39:11 2012 -0700
    10.2 +++ b/jitcraft/Parser.h	Mon Jul 02 01:24:57 2012 -0700
    10.3 @@ -29,6 +29,7 @@
    10.4  
    10.5  class Parser
    10.6  {
    10.7 +    CompileContext &cc_;
    10.8      PoolAllocator &pool_;
    10.9      StringPool strings_;
   10.10      Scanner scanner_;
   10.11 @@ -36,9 +37,7 @@
   10.12      std::vector<NameProxy *> *unbound_;
   10.13  
   10.14    private:
   10.15 -    void redeclarationError() {
   10.16 -        assert(false);
   10.17 -    }
   10.18 +    void redeclarationError(BoundName *name);
   10.19      bool match(TokenKind kind);
   10.20      bool expect(TokenKind kind);
   10.21  
   10.22 @@ -78,7 +77,7 @@
   10.23      Statement *returnStatement();
   10.24  
   10.25    public:
   10.26 -    Parser(const char *stream, size_t length);
   10.27 +    Parser(CompileContext &cc, const char *stream, size_t length);
   10.28  
   10.29      ParseTree *parse();
   10.30  };
    11.1 --- a/jitcraft/Scanner.cpp	Sun Jul 01 18:39:11 2012 -0700
    11.2 +++ b/jitcraft/Scanner.cpp	Mon Jul 02 01:24:57 2012 -0700
    11.3 @@ -18,6 +18,7 @@
    11.4  #include <assert.h>
    11.5  #include <ctype.h>
    11.6  #include "Scanner.h"
    11.7 +#include "Utility.h"
    11.8  
    11.9  using namespace jc;
   11.10  
   11.11 @@ -29,13 +30,17 @@
   11.12      NULL
   11.13  };
   11.14  
   11.15 -Scanner::Scanner(const char *stream, size_t length)
   11.16 -  : stream_(stream),
   11.17 +Scanner::Scanner(CompileContext &cc, const char *stream, size_t length)
   11.18 +  : cc_(cc),
   11.19 +    stream_(stream),
   11.20      length_(length),
   11.21      pushed_(false),
   11.22      saved_('\0'),
   11.23      pos_(stream_)
   11.24  {
   11.25 +    cur_.line = 0;
   11.26 +    cur_.col = 0;
   11.27 +    last_ = cur_;
   11.28  }
   11.29  
   11.30  char
   11.31 @@ -48,6 +53,7 @@
   11.32      }
   11.33      if (pos_ >= stream_ + length_)
   11.34          return '\0';
   11.35 +    last_.col = cur_.col++;
   11.36      return *pos_++;
   11.37  }
   11.38  
   11.39 @@ -56,6 +62,19 @@
   11.40  {
   11.41      assert(saved_ == '\0');
   11.42      saved_ = c;
   11.43 +    cur_.col = last_.col;
   11.44 +}
   11.45 +
   11.46 +void
   11.47 +Scanner::calcNewLine(char c)
   11.48 +{
   11.49 +    cur_.line++;
   11.50 +    cur_.col = 0;
   11.51 +    last_ = cur_;
   11.52 +
   11.53 +    char o;
   11.54 +    if (c == '\r' && ((o = getChar()) != '\n'))
   11.55 +        putChar(o);
   11.56  }
   11.57  
   11.58  void
   11.59 @@ -63,8 +82,10 @@
   11.60  {
   11.61      char c;
   11.62      while ((c = getChar()) != '\0') {
   11.63 -        if (c == '\n' || c == '\r')
   11.64 +        if (c == '\n' || c == '\r') {
   11.65 +            calcNewLine(c);
   11.66              break;
   11.67 +        }
   11.68      }
   11.69  }
   11.70  
   11.71 @@ -81,6 +102,8 @@
   11.72              if (c == '/')
   11.73                  return true;
   11.74          }
   11.75 +        if (c == '\r' || c == '\n')
   11.76 +            calcNewLine(c);
   11.77      }
   11.78  
   11.79      return false;
   11.80 @@ -214,7 +237,7 @@
   11.81  
   11.82              return r;
   11.83          }
   11.84 -        assert(false);
   11.85 +        cc_.reportError(begin(), Message_UnknownEscapeCode, c);
   11.86          return INT_MAX;
   11.87        }
   11.88      }
   11.89 @@ -230,7 +253,7 @@
   11.90          if (c == '\"')
   11.91              break;
   11.92          if (c == '\r' || c == '\n' || c == '\0') {
   11.93 -            assert(false);
   11.94 +            cc_.reportError(begin(), Message_UnterminatedString);
   11.95              return TOK_ERROR;
   11.96          }
   11.97          if (c == '\\') {
   11.98 @@ -266,7 +289,7 @@
   11.99  
  11.100      c = getChar();
  11.101      if (!IsDigit(c)) {
  11.102 -        assert(false);
  11.103 +        cc_.reportError(begin(), Message_ExpectedDigitForFloat, c);
  11.104          return TOK_ERROR;
  11.105      }
  11.106      literal_ += c;
  11.107 @@ -288,7 +311,7 @@
  11.108              c = getChar();
  11.109          }
  11.110          if (!IsDigit(c)) {
  11.111 -            assert(false);
  11.112 +            cc_.reportError(begin(), Message_ExpectedDigitForFloat, c);
  11.113              return TOK_ERROR;
  11.114          }
  11.115          literal_ += c;
  11.116 @@ -350,6 +373,8 @@
  11.117      assert(!pushed_);
  11.118  
  11.119      for (;;) {
  11.120 +        begin_ = cur_;
  11.121 +
  11.122          char c = getChar();
  11.123          switch (c) {
  11.124            case '/':
  11.125 @@ -360,14 +385,21 @@
  11.126                  break;
  11.127              }
  11.128              if (c == '*') {
  11.129 -                if (!eatComment())
  11.130 +                if (!eatComment()) {
  11.131 +                    cc_.reportError(begin(), Message_UnterminatedComment);
  11.132                      return TOK_ERROR;
  11.133 +                }
  11.134                  break;
  11.135              }
  11.136              putChar(c);
  11.137              return TOK_SLASH;
  11.138            }
  11.139  
  11.140 +          case '\n':
  11.141 +          case '\r':
  11.142 +            calcNewLine(c);
  11.143 +            break;
  11.144 +
  11.145            case ';': return TOK_SEMICOLON;
  11.146            case '{': return TOK_LBRACE;
  11.147            case '}': return TOK_RBRACE;
  11.148 @@ -465,9 +497,7 @@
  11.149  
  11.150            case ' ':
  11.151            case '\t':
  11.152 -          case '\r':
  11.153            case '\f':
  11.154 -          case '\n':
  11.155              break;
  11.156  
  11.157            case '"':
  11.158 @@ -478,7 +508,7 @@
  11.159                  return numberLiteral(c);
  11.160              if (c == '_' || (isascii(c) && isalpha(c)))
  11.161                  return identifier(c);
  11.162 -            assert(false);
  11.163 +            cc_.reportError(begin_, Message_UnexpectedCharacter, c, uint8(c));
  11.164              return TOK_ERROR;
  11.165          }
  11.166      }
    12.1 --- a/jitcraft/Scanner.h	Sun Jul 01 18:39:11 2012 -0700
    12.2 +++ b/jitcraft/Scanner.h	Mon Jul 02 01:24:57 2012 -0700
    12.3 @@ -20,11 +20,25 @@
    12.4  
    12.5  #include <string>
    12.6  #include "Token.h"
    12.7 +#include "CompileContext.h"
    12.8  
    12.9  namespace jc {
   12.10  
   12.11 +struct SourcePosition
   12.12 +{
   12.13 +    int line;
   12.14 +    int col;
   12.15 +
   12.16 +    SourcePosition()
   12.17 +      : line(-1),
   12.18 +        col(-1)
   12.19 +    {
   12.20 +    }
   12.21 +};
   12.22 +
   12.23  class Scanner
   12.24  {
   12.25 +    CompileContext &cc_;
   12.26      const char *stream_;
   12.27      size_t length_;
   12.28      bool pushed_;
   12.29 @@ -32,12 +46,16 @@
   12.30      const char *pos_;
   12.31      std::string literal_;
   12.32      TokenKind lastToken_;
   12.33 +    SourcePosition last_;
   12.34 +    SourcePosition cur_;
   12.35 +    SourcePosition begin_;
   12.36  
   12.37    private:
   12.38      char getChar();
   12.39      void putChar(char c);
   12.40      void eatSingleLine();
   12.41      bool eatComment();
   12.42 +    void calcNewLine(char c);
   12.43      int readEscapeCode();
   12.44      TokenKind stringLiteral();
   12.45      TokenKind numberLiteral(char first);
   12.46 @@ -46,7 +64,7 @@
   12.47      TokenKind next();
   12.48  
   12.49    public:
   12.50 -    Scanner(const char *stream, size_t length);
   12.51 +    Scanner(CompileContext &cc, const char *stream, size_t length);
   12.52  
   12.53      static double ParseDouble(const char *string);
   12.54  
   12.55 @@ -56,6 +74,11 @@
   12.56          return lastToken_;
   12.57      }
   12.58  
   12.59 +    // Beginning source position of the last instruction.
   12.60 +    SourcePosition begin() const {
   12.61 +        return begin_;
   12.62 +    }
   12.63 +
   12.64      // Note: the literal may have embedded NUL characters.
   12.65      const char *literal() const {
   12.66          return literal_.c_str();
    13.1 --- a/jitcraft/Scopes.cpp	Sun Jul 01 18:39:11 2012 -0700
    13.2 +++ b/jitcraft/Scopes.cpp	Mon Jul 02 01:24:57 2012 -0700
    13.3 @@ -84,48 +84,48 @@
    13.4  }
    13.5  
    13.6  Variable *
    13.7 -Scope::declareVariable(Name *name)
    13.8 +Scope::declareVariable(Name *name, const SourcePosition &pos)
    13.9  {
   13.10      assert(!localLookup(name));
   13.11      
   13.12 -    Variable *var = new (pool_) Variable(this, name);
   13.13 +    Variable *var = new (pool_) Variable(this, name, pos);
   13.14      names_.push_back(var);
   13.15      return var;
   13.16  }
   13.17  
   13.18  Variable *
   13.19 -Scope::declareArgument(Name *name)
   13.20 +Scope::declareArgument(Name *name, const SourcePosition &pos)
   13.21  {
   13.22      assert(kind() == FUNCTION);
   13.23 -    Variable *var = declareVariable(name);
   13.24 +    Variable *var = declareVariable(name, pos);
   13.25      names_.push_back(var);
   13.26      parameters_.push_back(var);
   13.27      return var;
   13.28  }
   13.29  
   13.30  NamedFunction *
   13.31 -Scope::declareFunction(Name *name)
   13.32 +Scope::declareFunction(Name *name, const SourcePosition &pos)
   13.33  {
   13.34      assert(!localLookup(name));
   13.35      assert(kind() == GLOBAL);
   13.36  
   13.37 -    NamedFunction *fun = new (pool_) NamedFunction(this, name);
   13.38 +    NamedFunction *fun = new (pool_) NamedFunction(this, name, pos);
   13.39      names_.push_back(fun);
   13.40      return fun;
   13.41  }
   13.42  
   13.43  NamedEnum *
   13.44 -Scope::declareEnum(Name *name)
   13.45 +Scope::declareEnum(Name *name, const SourcePosition &pos)
   13.46  {
   13.47 -    NamedEnum *e = new (pool_) NamedEnum(this, name);
   13.48 +    NamedEnum *e = new (pool_) NamedEnum(this, name, pos);
   13.49      names_.push_back(e);
   13.50      return e;
   13.51  }
   13.52  
   13.53  NamedConstant *
   13.54 -Scope::declareConstant(Name *name)
   13.55 +Scope::declareConstant(Name *name, const SourcePosition &pos)
   13.56  {
   13.57 -    NamedConstant *constant = new (pool_) NamedConstant(this, name);
   13.58 +    NamedConstant *constant = new (pool_) NamedConstant(this, name, pos);
   13.59      names_.push_back(constant);
   13.60      return constant;
   13.61  }
   13.62 @@ -222,6 +222,6 @@
   13.63      if (kind() == FUNCTION || enclosing()->kind() == FUNCTION)
   13.64          return;
   13.65  
   13.66 -    lifoSlot_ = new (pool_) Variable(this, NULL);
   13.67 +    lifoSlot_ = new (pool_) Variable(this, NULL, SourcePosition());
   13.68      lifoSlot_->setType(ZONE()->types()->getPrimitive(PrimitiveType_Native));
   13.69  }
    14.1 --- a/jitcraft/Scopes.h	Sun Jul 01 18:39:11 2012 -0700
    14.2 +++ b/jitcraft/Scopes.h	Mon Jul 02 01:24:57 2012 -0700
    14.3 @@ -81,11 +81,13 @@
    14.4      Scope *unlinkIfEmpty();
    14.5      BoundName *localLookup(Name *name);
    14.6      BoundName *lookup(Name *name);
    14.7 -    NamedFunction *declareFunction(Name *name);
    14.8 -    Variable *declareVariable(Name *name);
    14.9 -    Variable *declareArgument(Name *name);
   14.10 -    NamedEnum *declareEnum(Name *name);
   14.11 -    NamedConstant *declareConstant(Name *name);
   14.12 +
   14.13 +    NamedFunction *declareFunction(Name *name, const SourcePosition &pos);
   14.14 +    Variable *declareVariable(Name *name, const SourcePosition &pos);
   14.15 +    Variable *declareArgument(Name *name, const SourcePosition &pos);
   14.16 +    NamedEnum *declareEnum(Name *name, const SourcePosition &pos);
   14.17 +    NamedConstant *declareConstant(Name *name, const SourcePosition &pos);
   14.18 +
   14.19      void allocate(Variable *var);
   14.20      void allocate();
   14.21      void allocateGlobals();
    15.1 --- a/jitcraft/SemanticAnalysis.cpp	Sun Jul 01 18:39:11 2012 -0700
    15.2 +++ b/jitcraft/SemanticAnalysis.cpp	Mon Jul 02 01:24:57 2012 -0700
    15.3 @@ -92,8 +92,9 @@
    15.4      }
    15.5  }
    15.6  
    15.7 -SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
    15.8 -  : tree_(tree),
    15.9 +SemanticAnalysis::SemanticAnalysis(CompileContext &cc, ParseTree *tree)
   15.10 +  : cc_(cc),
   15.11 +    tree_(tree),
   15.12      loopDepth_(0),
   15.13      scope_(NULL)
   15.14  {
   15.15 @@ -102,35 +103,48 @@
   15.16  bool
   15.17  SemanticAnalysis::analyze()
   15.18  {
   15.19 +    if (cc_.failures())
   15.20 +        return false;
   15.21 +
   15.22 +    for (size_t i = 0; i < tree_->statements()->length(); i++) {
   15.23 +        Statement *statement = tree_->statements()->at(i);
   15.24 +        if (statement->isFunctionStatement()) {
   15.25 +            FunctionStatement *funstmt = statement->toFunctionStatement();
   15.26 +            if (!preanalyze(funstmt))
   15.27 +                return false;
   15.28 +        }
   15.29 +    }
   15.30 +
   15.31      for (size_t i = 0; i < tree_->statements()->length(); i++) {
   15.32          Statement *statement = tree_->statements()->at(i);
   15.33          statement->accept(this);
   15.34      }
   15.35  
   15.36 -    return true;
   15.37 +    return !cc_.failures();
   15.38  }
   15.39  
   15.40 -void
   15.41 -SemanticAnalysis::visit(NameProxy *name)
   15.42 +Type *
   15.43 +SemanticAnalysis::visitAndApplyType(Expression *expression)
   15.44  {
   15.45 -    name->setType(name->binding()->type());
   15.46 +    expression->accept(this);
   15.47 +    return expression->type();
   15.48  }
   15.49  
   15.50  Type *
   15.51  SemanticAnalysis::visitForLoad(Expression *expression)
   15.52  {
   15.53 -    expression->accept(this);
   15.54 -    if (!expression->type())
   15.55 +    // :TODO: use Local
   15.56 +    Type *type = visitAndApplyType(expression);
   15.57 +    if (!type)
   15.58          return NULL;
   15.59  
   15.60 -    // :TODO: use Local
   15.61 -    Type *type = expression->type();
   15.62      if (type->isReference()) {
   15.63          expression->setType(type->contained());
   15.64      } else if (expression->isIndexExpression()) {
   15.65          if (type->isArray())
   15.66              expression->setType(type->contained());
   15.67      }
   15.68 +
   15.69      return expression->type();
   15.70  }
   15.71  
   15.72 @@ -141,94 +155,93 @@
   15.73      return expression->type();
   15.74  }
   15.75  
   15.76 -static inline bool
   15.77 -TypeCheck(Type *left, Type *right)
   15.78 +static inline const char *
   15.79 +GetTypeName(Type *type)
   15.80  {
   15.81 -    if (!left || !right)
   15.82 -        return false;
   15.83 -
   15.84 -    if (left->isPrimitive()) {
   15.85 -        if (!right->isPrimitive())
   15.86 -            return false;
   15.87 -        return left->primitive() == right->primitive();
   15.88 -    }
   15.89 -
   15.90 -    return false;
   15.91 +    if (type->isArray())
   15.92 +        return "array";
   15.93 +    if (type->isFunction())
   15.94 +        return "function";
   15.95 +    if (type->isReference())
   15.96 +        type = type->contained();
   15.97 +    if (type->tag())
   15.98 +        return type->tag();
   15.99 +    return "int";
  15.100  }
  15.101  
  15.102 -static inline bool
  15.103 -TypeCheckAssignment(Type *left, Type *right)
  15.104 +void
  15.105 +SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Type *type)
  15.106  {
  15.107 -    if (!left || !right)
  15.108 -        return false;
  15.109 -
  15.110 -    if (left->isPrimitive()) {
  15.111 -        if (!right->isPrimitive())
  15.112 -            return false;
  15.113 -        return left->primitive() == right->primitive();
  15.114 -    }
  15.115 -
  15.116 -    if (left->isArray() != right->isArray())
  15.117 -        return false;
  15.118 +    const char *op = TokenNames[token];
  15.119 +    const char *name = GetTypeName(type);
  15.120  
  15.121 -    if (left->levels() != 1 || right->levels() != 1)
  15.122 -        return false;
  15.123 -
  15.124 -    if (left->elements() == -1 || right->elements() == -1)
  15.125 -        return false;
  15.126 -
  15.127 -    if (!TypeCheckAssignment(left->contained(), right->contained()))
  15.128 -        return false;
  15.129 -
  15.130 -    if (left->elements() != right->elements()) {
  15.131 -        if (left->isCharArray() && (left->elements() >= right->elements()))
  15.132 -            return true;
  15.133 -        return false;
  15.134 -    }
  15.135 -
  15.136 -    return false;
  15.137 +    cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
  15.138  }
  15.139  
  15.140 -static inline Type *
  15.141 -TypeCheckBinary(TokenKind token, Type *left, Type *right)
  15.142 +void
  15.143 +SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Type *left, Type *right)
  15.144  {
  15.145 -    if (!left || !right)
  15.146 -        return NULL;
  15.147 +    const char *op = TokenNames[token];
  15.148 +    const char *leftName = GetTypeName(left);
  15.149 +    const char *rightName = GetTypeName(right);
  15.150  
  15.151 +    cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
  15.152 +}
  15.153 +
  15.154 +Type *
  15.155 +SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Type *left, Type *right)
  15.156 +{
  15.157      if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
  15.158          (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
  15.159      {
  15.160          // If either side is a float, the other side must be a float or int.
  15.161          if (left->isFloat() || right->isFloat()) {
  15.162 -            assert(left->isFloat() || left->isInt32());
  15.163 -            assert(right->isFloat() || right->isInt32());
  15.164 -            return left->isFloat() ? left : right;
  15.165 +            Type *floatType = left->isFloat() ? left : right;
  15.166 +            Type *other = left->isFloat() ? right : left;
  15.167 +            if (other->isFloat() || (other->isInt32() && !other->tag()))
  15.168 +                return other;
  15.169          }
  15.170      }
  15.171  
  15.172 -    assert(left->isInt32() && right->isInt32());
  15.173 -    assert(!left->tag() && !right->tag());
  15.174 +    if ((!left->isInt32() || left->tag()) ||
  15.175 +        (!right->isInt32() || right->tag()))
  15.176 +    {
  15.177 +        binaryTypeError(node, token, left, right);
  15.178 +        return NULL;
  15.179 +    }
  15.180 +
  15.181      return left;
  15.182  }
  15.183  
  15.184 +bool
  15.185 +SemanticAnalysis::canTest(AstNode *node, Type *type)
  15.186 +{
  15.187 +    if (type->isArray()) {
  15.188 +        cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
  15.189 +        return false;
  15.190 +    }
  15.191 +    return true;
  15.192 +}
  15.193 +
  15.194  Type *
  15.195  SemanticAnalysis::visitForLValue(Expression *expression)
  15.196  {
  15.197      if (expression->isIndexExpression()) {
  15.198 -        expression->accept(this);
  15.199 -        if (!expression->type())
  15.200 +        Type *type = visitAndApplyType(expression);
  15.201 +        if (!type)
  15.202              return NULL;
  15.203 -        return expression->type()->contained();
  15.204 +
  15.205 +        return type->contained();
  15.206      }
  15.207  
  15.208      if (!expression->isNameProxy()) {
  15.209 -        assert(false);
  15.210 +        cc_.reportError(expression->pos(), Message_ExpectedLValue);
  15.211          return NULL;
  15.212      }
  15.213  
  15.214      NameProxy *proxy = expression->toNameProxy();
  15.215      if (!proxy->binding()->kind() == BoundName::VARIABLE) {
  15.216 -        fprintf(stderr, "error\n");
  15.217 +        cc_.reportError(expression->pos(), Message_ExpectedLValue);
  15.218          return NULL;
  15.219      }
  15.220  
  15.221 @@ -242,20 +255,32 @@
  15.222  }
  15.223  
  15.224  void
  15.225 +SemanticAnalysis::visit(NameProxy *name)
  15.226 +{
  15.227 +    name->setType(name->binding()->type());
  15.228 +}
  15.229 +
  15.230 +void
  15.231  SemanticAnalysis::visit(Assignment *node)
  15.232  {
  15.233 -    visitForLoad(node->expression());
  15.234 +    Type *exprType = visitForLoad(node->expression());
  15.235 +    if (!exprType)
  15.236 +        return ;
  15.237  
  15.238      // :TODO: use Local
  15.239      Type *type = visitForLValue(node->lvalue());
  15.240      if (!type)
  15.241          return;
  15.242 -    node->setType(type);
  15.243  
  15.244 -    if (node->token() != TOK_ASSIGN)
  15.245 -        assert(TypeCheckBinary(node->token(), node->type(), node->expression()->type()));
  15.246 +    if (node->token() != TOK_ASSIGN) {
  15.247 +        if (!typeCheckBinary(node, node->token(), type, exprType))
  15.248 +            return;
  15.249 +    }
  15.250  
  15.251 -    assert(TypeCheckAssignment(node->type(), node->expression()->type()));
  15.252 +    if (!typeCheckAssignment(node, exprType, type, true))
  15.253 +        return;
  15.254 +
  15.255 +    node->setType(type);
  15.256  }
  15.257  
  15.258  void
  15.259 @@ -267,13 +292,12 @@
  15.260          return;
  15.261  
  15.262      assert(!type->isReference());
  15.263 -    if (type->isArray()) {
  15.264 -        // can't a[]++
  15.265 -        assert(false);
  15.266 +
  15.267 +    if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
  15.268 +        unaryTypeError(node, node->token(), type);
  15.269          return;
  15.270      }
  15.271  
  15.272 -    assert((type->isInt32() && !type->tag()) || type->isFloat());
  15.273      node->setType(type);
  15.274  }
  15.275  
  15.276 @@ -283,17 +307,25 @@
  15.277      // :TODO: use Local
  15.278      Type *left = visitForLoad(node->left());
  15.279      Type *right = visitForLoad(node->right());
  15.280 +    if (!left || !right)
  15.281 +        return;
  15.282  
  15.283 -    Type *result = TypeCheckBinary(node->token(), left, right);
  15.284 +    Type *result = typeCheckBinary(node, node->token(), left, right);
  15.285 +    if (!result)
  15.286 +        return;
  15.287 +
  15.288      node->setType(result);
  15.289  }
  15.290  
  15.291  void
  15.292  SemanticAnalysis::visit(ReturnStatement *node)
  15.293  {
  15.294 -    visitForLoad(node->expression());
  15.295 +    Type *type = visitForLoad(node->expression());
  15.296 +    if (!type)
  15.297 +        return;
  15.298  
  15.299 -    // :TODO: type check
  15.300 +    if (!typeCheckAssignment(node, type, function_->returnType(), true))
  15.301 +        return;
  15.302  }
  15.303  
  15.304  void
  15.305 @@ -302,13 +334,23 @@
  15.306      loopDepth_++;
  15.307      if (node->scope())
  15.308          scope_ = node->scope();
  15.309 +
  15.310      if (node->initialization())
  15.311          node->initialization()->accept(this);
  15.312 -    if (node->condition())
  15.313 -        visitForLoad(node->condition());
  15.314 +
  15.315 +    if (node->condition()) {
  15.316 +        Type *type = visitForLoad(node->condition());
  15.317 +        if (!type || !canTest(node->condition(), type)) {
  15.318 +            loopDepth_--;
  15.319 +            return;
  15.320 +        }
  15.321 +    }
  15.322 +
  15.323      if (node->update())
  15.324          node->update()->accept(this);
  15.325 +
  15.326      node->body()->accept(this);
  15.327 +
  15.328      if (node->scope())
  15.329          scope_ = scope_->enclosing();
  15.330      loopDepth_--;
  15.331 @@ -318,7 +360,13 @@
  15.332  SemanticAnalysis::visit(WhileStatement *node)
  15.333  {
  15.334      loopDepth_++;
  15.335 -    node->condition()->accept(this);
  15.336 +
  15.337 +    Type *type = visitForLoad(node->condition());
  15.338 +    if (!type || !canTest(node->condition(), type)) {
  15.339 +        loopDepth_--;
  15.340 +        return;
  15.341 +    }
  15.342 +
  15.343      node->body()->accept(this);
  15.344      loopDepth_--;
  15.345  }
  15.346 @@ -347,61 +395,90 @@
  15.347      if (node->postDimensions()) {
  15.348          Type *init = NULL;
  15.349          if (node->initialization()) {
  15.350 -            node->initialization()->accept(this);
  15.351 -            if ((init = node->initialization()->type()) == NULL)
  15.352 +            if ((init = visitAndApplyType(node->initialization())) == NULL)
  15.353                  return;
  15.354          }
  15.355  
  15.356          if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
  15.357 -            error();
  15.358 +            cc_.reportError(node->pos(), Message_MaximumArrayDepth);
  15.359              return;
  15.360          }
  15.361  
  15.362          // If we have an initializer, make sure it's the same type.
  15.363 -        if (init) {
  15.364 -            assert(init->levels() == node->postDimensions()->size());
  15.365 +        if (init && node->postDimensions()->size() != init->levels()) {
  15.366 +            cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
  15.367 +            return;
  15.368          }
  15.369  
  15.370          Type *check = init;
  15.371          for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
  15.372              Expression *expr = node->postDimensions()->at(i);
  15.373 -            visitForLoad(expr);
  15.374 +            int size = -1;
  15.375  
  15.376 -            if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
  15.377 -                typeError(expr, "integer");
  15.378 -                return;
  15.379 -            }
  15.380 +            if (expr) {
  15.381 +                Type *exprType = visitForLoad(expr);
  15.382 +                if (!exprType)
  15.383 +                    return;
  15.384  
  15.385 -            int size = -1;
  15.386 -            if (expr->isIntegerLiteral()) {
  15.387 -                size = expr->toIntegerLiteral()->value();
  15.388 -                if (size <= 0) {
  15.389 -                    error();
  15.390 +                if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
  15.391 +                    cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
  15.392                      return;
  15.393                  }
  15.394 -                if (size >= INT_MAX / sizeof(int)) {
  15.395 -                    error();
  15.396 +
  15.397 +                BoxedPrimitive box;
  15.398 +                if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
  15.399 +                    size = box.toInt();
  15.400 +                    if (size <= 0) {
  15.401 +                        cc_.reportError(expr->pos(), Message_BadArraySize);
  15.402 +                        return;
  15.403 +                    }
  15.404 +                    if (size >= INT_MAX / sizeof(int)) {
  15.405 +                        cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
  15.406 +                        return;
  15.407 +                    }
  15.408 +
  15.409 +                    if (check) {
  15.410 +                        if (check->elements() == -1) {
  15.411 +                            cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
  15.412 +                            return;
  15.413 +                        }
  15.414 +
  15.415 +                        if (check->isCharArray()) {
  15.416 +                            if (check->elements() > size) {
  15.417 +                                cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
  15.418 +                                return;
  15.419 +                            }
  15.420 +                        } else if (check->elements() != size) {
  15.421 +                            cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
  15.422 +                            return;
  15.423 +                        }
  15.424 +                    }
  15.425 +                } else {
  15.426 +                    if (init) {
  15.427 +                        cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
  15.428 +                        return;
  15.429 +                    }
  15.430 +
  15.431 +                    // here until we get dynamic array support.
  15.432 +                    cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
  15.433                      return;
  15.434                  }
  15.435              } else {
  15.436 -                assert(false);
  15.437 +                // Infer the size from the initializer.
  15.438 +                if (!init) {
  15.439 +                    cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
  15.440 +                    return;
  15.441 +                }
  15.442 +                if (init->elements() == -1) {
  15.443 +                    cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
  15.444 +                    return;
  15.445 +                }
  15.446 +                size = init->elements();
  15.447              }
  15.448  
  15.449              type = ZONE()->types()->unsafeArray(type, size);
  15.450 -
  15.451 -            if (check) {
  15.452 -                assert(check->elements() != -1);
  15.453 -                assert(size != -1);
  15.454 -                    
  15.455 -                // If we're assigning a string, we're allowed to pad with
  15.456 -                // zeroes.
  15.457 -                if (check->isCharArray()) {
  15.458 -                    assert(type->isCharArray());
  15.459 -                    assert(type->elements() >= check->elements());
  15.460 -                } else {
  15.461 -                    assert(false);
  15.462 -                }
  15.463 -            }
  15.464 +            if (!type)
  15.465 +                return;
  15.466  
  15.467              if (check)
  15.468                  check = check->contained();
  15.469 @@ -414,10 +491,13 @@
  15.470      } else {
  15.471          if (node->initialization()) {
  15.472              Type *right = visitForLoad(node->initialization());
  15.473 -            assert(TypeCheck(type, right));
  15.474 +            if (!right)
  15.475 +                return;
  15.476 +            if (!typeCheckAssignment(node, type, right, true))
  15.477 +                return;
  15.478          }
  15.479          if (type->primitive() == PrimitiveType_Char) {
  15.480 -            assert(false);
  15.481 +            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
  15.482              return;
  15.483          }
  15.484      }
  15.485 @@ -454,6 +534,11 @@
  15.486          if (!type)
  15.487              return false;
  15.488  
  15.489 +        if (type->primitive() == PrimitiveType_Char) {
  15.490 +            cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
  15.491 +            return false;
  15.492 +        }
  15.493 +
  15.494          if (parameter->reference()) {
  15.495              type = ZONE()->types()->getReference(type);
  15.496              if (!type)
  15.497 @@ -479,60 +564,137 @@
  15.498  void
  15.499  SemanticAnalysis::visit(FunctionStatement *node)
  15.500  {
  15.501 +    function_ = node->fun()->type();
  15.502      scope_ = node->scope();
  15.503 -
  15.504 -    // :TODO: call this ahead of time.
  15.505 -    if (!preanalyze(node))
  15.506 -        return;
  15.507 -
  15.508      node->body()->accept(this);
  15.509      scope_ = NULL;
  15.510 +    function_ = NULL;
  15.511  }
  15.512  
  15.513 -// :TODO: use handles
  15.514 -static inline bool
  15.515 -TypeCheckParameter(Type *given, Type *actual)
  15.516 +bool
  15.517 +SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Type *given, Type *actual, bool forAssign)
  15.518  {
  15.519 -    if (actual->isReference()) {
  15.520 -        if (given->isReference())
  15.521 -            given = given->contained();
  15.522 -        return TypeCheck(given, actual->contained());
  15.523 +    if (!given->isArray()) {
  15.524 +        cc_.reportError(node->pos(), Message_ExpectedArray);
  15.525 +        return false;
  15.526 +    }
  15.527 +    if (given->levels() != actual->levels()) {
  15.528 +        cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
  15.529 +        return false;
  15.530 +    }
  15.531 +
  15.532 +    unsigned level = 0;
  15.533 +    while (given->isArray()) {
  15.534 +        if (actual->elements() != -1) {
  15.535 +            if (forAssign) {
  15.536 +                if (given->elements() == -1 || actual->elements() == -1) {
  15.537 +                    cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
  15.538 +                    return false;
  15.539 +                }
  15.540 +
  15.541 +                if (actual->isCharArray()) {
  15.542 +                    // String assignment can have a truncated |given|.
  15.543 +                    if (given->elements() > actual->elements()) {
  15.544 +                        cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
  15.545 +                        return false;
  15.546 +                    }
  15.547 +                } else {
  15.548 +                    if (given->elements() != actual->elements()) {
  15.549 +                        cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
  15.550 +                        return false;
  15.551 +                    }
  15.552 +                }
  15.553 +            } else {
  15.554 +                if (actual->elements() != -1 && given->elements() != actual->elements()) {
  15.555 +                    cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
  15.556 +                    return false;
  15.557 +                }
  15.558 +            }
  15.559 +        }
  15.560 +        given = given->contained();
  15.561 +        actual = actual->contained();
  15.562      }
  15.563  
  15.564 -    return TypeCheck(given, actual);
  15.565 +    if (given->primitive() != actual->primitive()) {
  15.566 +        const char *givenTag = given->tag() ? given->tag() : "_";
  15.567 +        const char *actualTag = given->tag() ? given->tag() : "_";
  15.568 +        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
  15.569 +        return false;
  15.570 +    }
  15.571 +
  15.572 +    return true;
  15.573 +}
  15.574 +
  15.575 +bool
  15.576 +SemanticAnalysis::typeCheckAssignment(AstNode *node, Type *given, Type *actual, bool forAssign)
  15.577 +{
  15.578 +    if (actual->isArray())
  15.579 +        return typeCheckArrayAssignment(node, given, actual, forAssign);
  15.580 +
  15.581 +    if (given->isArray()) {
  15.582 +        cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
  15.583 +        return false;
  15.584 +    }
  15.585 +
  15.586 +    if (!given->isPrimitive() || !actual->primitive()) {
  15.587 +        cc_.reportError(node->pos(), Message_UnsupportedType);
  15.588 +        return false;
  15.589 +    }
  15.590 +    
  15.591 +    // The given type may not have been dereferenced.
  15.592 +    if (given->isReference())
  15.593 +        given = given->contained();
  15.594 +    if (actual->isReference())
  15.595 +        actual = given->contained();
  15.596 +
  15.597 +    if (given->primitive() != actual->primitive()) {
  15.598 +        const char *givenTag = given->tag() ? given->tag() : "_";
  15.599 +        const char *actualTag = given->tag() ? given->tag() : "_";
  15.600 +        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
  15.601 +        return false;
  15.602 +    }
  15.603 +
  15.604 +    return true;
  15.605 +}
  15.606 +
  15.607 +bool
  15.608 +SemanticAnalysis::typeCheckParameter(AstNode *node, Type *given, Type *actual)
  15.609 +{
  15.610 +    return typeCheckAssignment(node, given, actual, false);
  15.611  }
  15.612  
  15.613  void
  15.614  SemanticAnalysis::visit(CallExpression *node)
  15.615  {
  15.616 -    visitForLoad(node->callee());
  15.617 -
  15.618 -    // :TODO: use locals
  15.619 -    Type *type = node->callee()->type();
  15.620 +    Type *type = visitForLoad(node->callee());
  15.621      if (!type)
  15.622          return;
  15.623  
  15.624 -    assert(type->isFunction());
  15.625 -    assert(node->arguments()->size() == type->parameters()->length());
  15.626 +    if (!type->isFunction()) {
  15.627 +        cc_.reportError(node->pos(), Message_CalleeNotFunction);
  15.628 +        return;
  15.629 +    }
  15.630 +    if (node->arguments()->size() != type->parameters()->length()) {
  15.631 +        cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
  15.632 +        return;
  15.633 +    }
  15.634  
  15.635      for (unsigned i = 0; i < node->arguments()->size(); i++) {
  15.636          // Note: we don't compute references unless the callee needs a
  15.637          // reference type.
  15.638          Expression *expression = node->arguments()->at(i);
  15.639 -        expression->accept(this);
  15.640 -
  15.641 -        Type *given = expression->type();
  15.642 +        Type *given = visitAndApplyType(expression);
  15.643          if (!given)
  15.644              return;
  15.645  
  15.646          // If it's an IndexExpression, we special case the ability to compute
  15.647 -        // a reference. Maybe we should compute actual Ref types for
  15.648 -        // IndexExpression?
  15.649 +        // a reference.
  15.650          if (expression->isIndexExpression())
  15.651              given = given->contained();
  15.652  
  15.653 -        Type *actual = Type::cast(type->parameters()->at(i));
  15.654 -        assert(TypeCheckParameter(given, actual));
  15.655 +        Type *actual = type->parameterAt(i);
  15.656 +        if (!typeCheckParameter(expression, given, actual))
  15.657 +            return;
  15.658  
  15.659          // If the actual is a reference, and the given is not, we'll need to
  15.660          // compute a reference, which may be allocated on the stack.
  15.661 @@ -544,7 +706,13 @@
  15.662  void
  15.663  SemanticAnalysis::visit(IfStatement *node)
  15.664  {
  15.665 -    visitForLoad(node->condition());
  15.666 +    Type *type = visitForLoad(node->condition());
  15.667 +    if (!type)
  15.668 +        return;
  15.669 +
  15.670 +    if (!canTest(node, type))
  15.671 +        return;
  15.672 +
  15.673      node->ifTrue()->accept(this);
  15.674      if (node->ifFalse())
  15.675          node->ifFalse()->accept(this);
  15.676 @@ -557,12 +725,15 @@
  15.677      Type *left = visitForRef(node->left());
  15.678      Type *right = visitForLoad(node->right());
  15.679  
  15.680 -    if (!right || !right->isInt32()) {
  15.681 -        typeError(node->right(), "integer");
  15.682 +    if (!left || !right)
  15.683 +        return;
  15.684 +
  15.685 +    if (!right->isInt32()) {
  15.686 +        cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
  15.687          return;
  15.688      }
  15.689 -    if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
  15.690 -        typeError(node->left(), "array");
  15.691 +    if (!left->isArray()) {
  15.692 +        cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
  15.693          return;
  15.694      }
  15.695      node->setType(left);
  15.696 @@ -571,8 +742,16 @@
  15.697  void
  15.698  SemanticAnalysis::visit(EnumStatement *node)
  15.699  {
  15.700 -    // :TODO: test "enum Float { ..."
  15.701 +    // Forbid the blessed types.
  15.702      Name *tag = node->name();
  15.703 +    if (!strcmp(tag, "Float") ||
  15.704 +        !strcmp(tag, "String") ||
  15.705 +        !strcmp(tag, "any") ||
  15.706 +        !strcmp(tag, "bool"))
  15.707 +    {
  15.708 +        cc_.reportError(node->pos(), Message_InvalidEnumName);
  15.709 +        return;
  15.710 +    }
  15.711  
  15.712      Type *type = ZONE()->types()->getPrimitiveForTag(tag);
  15.713      if (!type)
  15.714 @@ -585,8 +764,10 @@
  15.715          BoxedPrimitive box = BoxedPrimitive::Int(value);
  15.716          if (entry.expr) {
  15.717              entry.expr->accept(this);
  15.718 -            if (!EvaluateForConstant(entry.expr, &box))
  15.719 -                fprintf(stderr, "expected constant integer expression\n");
  15.720 +            if (!EvaluateForConstant(entry.expr, &box)) {
  15.721 +                cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
  15.722 +                return;
  15.723 +            }
  15.724  
  15.725              assert(box.type() == PrimitiveType_Int32);
  15.726              value = box.toInt();
  15.727 @@ -624,11 +805,13 @@
  15.728  void
  15.729  SemanticAnalysis::visit(BreakStatement *node)
  15.730  {
  15.731 -    assert(loopDepth_ > 0);
  15.732 +    if (loopDepth_ == 0)
  15.733 +        cc_.reportError(node->pos(), Message_BreakOutsideLoop);
  15.734  }
  15.735  
  15.736  void
  15.737  SemanticAnalysis::visit(ContinueStatement *node)
  15.738  {
  15.739 -    assert(loopDepth_ > 0);
  15.740 +    if (loopDepth_ == 0)
  15.741 +        cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
  15.742  }
    16.1 --- a/jitcraft/SemanticAnalysis.h	Sun Jul 01 18:39:11 2012 -0700
    16.2 +++ b/jitcraft/SemanticAnalysis.h	Mon Jul 02 01:24:57 2012 -0700
    16.3 @@ -25,24 +25,37 @@
    16.4  
    16.5  class SemanticAnalysis : public AstVisitor
    16.6  {
    16.7 +    CompileContext &cc_;
    16.8      ParseTree *tree_;
    16.9      unsigned loopDepth_;
   16.10      Scope *scope_;
   16.11 +    Type *function_;
   16.12  
   16.13    private:
   16.14 -    void error() {
   16.15 -        assert(false);
   16.16 -    }
   16.17 -    void typeError(Expression *expr, const char *expected) {
   16.18 -        assert(false);
   16.19 -    }
   16.20 +    bool canTest(AstNode *node, Type *type);
   16.21 +    void unaryTypeError(AstNode *node, TokenKind token, Type *type);
   16.22 +    void binaryTypeError(AstNode *node, TokenKind token, Type *left, Type *right);
   16.23 +    Type *typeCheckBinary(AstNode *node, TokenKind token, Type *left, Type *right);
   16.24 +
   16.25 +    // These check if one type is compatible with another type, for various
   16.26 +    // purposes, like:
   16.27 +    //      return (expr) matches function return type
   16.28 +    //      call(a, b)    matches expected arg type
   16.29 +    //      a = b         matches declared type
   16.30 +    //
   16.31 +    bool typeCheckArrayAssignment(AstNode *node, Type *given, Type *actual, bool forAssign);
   16.32 +    bool typeCheckAssignment(AstNode *node, Type *given, Type *actual, bool forAssign);
   16.33 +
   16.34 +    bool typeCheckParameter(AstNode *node, Type *given, Type *actual);
   16.35 +
   16.36      Type *visitForLoad(Expression *expression);
   16.37      Type *visitForRef(Expression *expression);
   16.38      bool preanalyze(FunctionStatement *node);
   16.39      Type *visitForLValue(Expression *expression);
   16.40 +    Type *visitAndApplyType(Expression *expression);
   16.41  
   16.42    public:
   16.43 -    SemanticAnalysis(ParseTree *tree);
   16.44 +    SemanticAnalysis(CompileContext &cc, ParseTree *tree);
   16.45      bool analyze();
   16.46  
   16.47    public:
    17.1 --- a/jitcraft/Types.cpp	Sun Jul 01 18:39:11 2012 -0700
    17.2 +++ b/jitcraft/Types.cpp	Mon Jul 02 01:24:57 2012 -0700
    17.3 @@ -100,7 +100,7 @@
    17.4  
    17.5      Type *type = Type::cast(obj);
    17.6      type->kind_ = FUNCTION;
    17.7 -    type->contained_ = returnType;
    17.8 +    type->returnType_ = returnType;
    17.9      type->parameters_ = parameters;
   17.10      return type;
   17.11  }
    18.1 --- a/jitcraft/Types.h	Sun Jul 01 18:39:11 2012 -0700
    18.2 +++ b/jitcraft/Types.h	Mon Jul 02 01:24:57 2012 -0700
    18.3 @@ -126,6 +126,9 @@
    18.4          assert(isFunction());
    18.5          return parameters_;
    18.6      }
    18.7 +    Type *parameterAt(size_t i) {
    18.8 +        return Type::cast(parameters()->at(i));
    18.9 +    }
   18.10  
   18.11    private:
   18.12      Kind kind_;
    19.1 --- a/jitcraft/jitcraft.vcxproj	Sun Jul 01 18:39:11 2012 -0700
    19.2 +++ b/jitcraft/jitcraft.vcxproj	Mon Jul 02 01:24:57 2012 -0700
    19.3 @@ -77,6 +77,8 @@
    19.4      <ClCompile Include="Array.cpp" />
    19.5      <ClCompile Include="BytecodeCompiler.cpp" />
    19.6      <ClCompile Include="BytecodeEmitter.cpp" />
    19.7 +    <ClCompile Include="CompileContext.cpp" />
    19.8 +    <ClCompile Include="Exception.cpp" />
    19.9      <ClCompile Include="FixedArray.cpp" />
   19.10      <ClCompile Include="Heap.cpp" />
   19.11      <ClCompile Include="Interpreter.cpp" />
   19.12 @@ -103,11 +105,13 @@
   19.13      <ClInclude Include="Barriers.h" />
   19.14      <ClInclude Include="BytecodeEmitter.h" />
   19.15      <ClInclude Include="BytecodeCompiler.h" />
   19.16 +    <ClInclude Include="CompileContext.h" />
   19.17      <ClInclude Include="FixedArray.h" />
   19.18      <ClInclude Include="Handles-inl.h" />
   19.19      <ClInclude Include="HashTable.h" />
   19.20      <ClInclude Include="Heap-inl.h" />
   19.21      <ClInclude Include="Interpreter.h" />
   19.22 +    <ClInclude Include="Messages.h" />
   19.23      <ClInclude Include="Modules.h" />
   19.24      <ClInclude Include="NameBinding.h" />
   19.25      <ClInclude Include="Heap.h" />
   19.26 @@ -132,6 +136,7 @@
   19.27      <ClInclude Include="Utility.h" />
   19.28    </ItemGroup>
   19.29    <ItemGroup>
   19.30 +    <None Include="Messages.tbl" />
   19.31      <None Include="Opcodes.tbl" />
   19.32    </ItemGroup>
   19.33    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    20.1 --- a/jitcraft/main.cpp	Sun Jul 01 18:39:11 2012 -0700
    20.2 +++ b/jitcraft/main.cpp	Mon Jul 02 01:24:57 2012 -0700
    20.3 @@ -58,7 +58,9 @@
    20.4      if (!ZONE()->initialize())
    20.5          return false;
    20.6  
    20.7 -    Parser parser(stream, length);
    20.8 +    CompileContext cc(ZONE());
    20.9 +
   20.10 +    Parser parser(cc, stream, length);
   20.11      ParseTree *tree = parser.parse();
   20.12      if (!tree)
   20.13          return false;
   20.14 @@ -67,7 +69,7 @@
   20.15      if (!Scope::Bind(tree))
   20.16          return false;
   20.17  
   20.18 -    SemanticAnalysis semantics(tree);
   20.19 +    SemanticAnalysis semantics(cc, tree);
   20.20      if (!semantics.analyze())
   20.21          return false;
   20.22