Scanning, parsing, and static analysis now report errors properly.
Scanning, parsing, and static analysis now report errors properly.
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