Add support for float variables and basic math.
Add support for float variables and basic math.
1.1 --- a/jitcraft/AST.h Tue Jun 26 00:58:55 2012 -0700
1.2 +++ b/jitcraft/AST.h Wed Jun 27 02:21:56 2012 -0700
1.3 @@ -29,7 +29,8 @@
1.4 _(VariableDeclaration) \
1.5 _(ForStatement) \
1.6 _(ReturnStatement) \
1.7 - _(IntegerLiteralExpression) \
1.8 + _(IntegerLiteral) \
1.9 + _(FloatLiteral) \
1.10 _(BinaryExpression) \
1.11 _(BlockStatement) \
1.12 _(Assignment) \
1.13 @@ -141,15 +142,20 @@
1.14 Variable *variable_;
1.15 Expression *initialization_;
1.16 ExpressionList *postDimensions_;
1.17 + Name *tag_;
1.18
1.19 public:
1.20 - VariableDeclaration(Variable *var, ExpressionList *postDimensions, Expression *initialization)
1.21 + VariableDeclaration(Variable *var, Name *tag, ExpressionList *postDimensions, Expression *initialization)
1.22 : variable_(var),
1.23 postDimensions_(postDimensions),
1.24 - initialization_(initialization)
1.25 + initialization_(initialization),
1.26 + tag_(tag)
1.27 {
1.28 }
1.29
1.30 + Name *tag() const {
1.31 + return tag_;
1.32 + }
1.33 Kind kind() const {
1.34 return kVariableDeclaration;
1.35 }
1.36 @@ -197,18 +203,18 @@
1.37 }
1.38 };
1.39
1.40 -class IntegerLiteralExpression : public Expression
1.41 +class IntegerLiteral : public Expression
1.42 {
1.43 int value_;
1.44
1.45 public:
1.46 - IntegerLiteralExpression(int value)
1.47 + IntegerLiteral(int value)
1.48 : value_(value)
1.49 {
1.50 }
1.51
1.52 Kind kind() const {
1.53 - return kIntegerLiteralExpression;
1.54 + return kIntegerLiteral;
1.55 }
1.56 int value() const {
1.57 return value_;
1.58 @@ -218,6 +224,27 @@
1.59 }
1.60 };
1.61
1.62 +class FloatLiteral : public Expression
1.63 +{
1.64 + double value_;
1.65 +
1.66 + public:
1.67 + FloatLiteral(double value)
1.68 + : value_(value)
1.69 + {
1.70 + }
1.71 +
1.72 + Kind kind() const {
1.73 + return kFloatLiteral;
1.74 + }
1.75 + double value() const {
1.76 + return value_;
1.77 + }
1.78 + void accept(AstVisitor *visitor) {
1.79 + visitor->visit(this);
1.80 + }
1.81 +};
1.82 +
1.83 class BinaryExpression : public Expression
1.84 {
1.85 Expression *left_;
2.1 --- a/jitcraft/BytecodeCompiler.cpp Tue Jun 26 00:58:55 2012 -0700
2.2 +++ b/jitcraft/BytecodeCompiler.cpp Wed Jun 27 02:21:56 2012 -0700
2.3 @@ -152,12 +152,22 @@
2.4 }
2.5
2.6 void
2.7 +BytecodeCompiler::visitForALU(Type *needed, Expression *node)
2.8 +{
2.9 + node->accept(this);
2.10 + if (needed->isFloat() && !node->type()->isFloat())
2.11 + __ cvt_i2f();
2.12 +}
2.13 +
2.14 +void
2.15 BytecodeCompiler::visit(BinaryExpression *node)
2.16 {
2.17 - node->left()->accept(this);
2.18 - node->right()->accept(this);
2.19 + visitForALU(node->type(), node->left());
2.20 + visitForALU(node->type(), node->right());
2.21
2.22 Opcode op = TokenToOpcode(node->token());
2.23 + if (node->type()->isFloat())
2.24 + op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
2.25 __ binary(op);
2.26 }
2.27
2.28 @@ -256,12 +266,18 @@
2.29 }
2.30
2.31 void
2.32 -BytecodeCompiler::visit(IntegerLiteralExpression *node)
2.33 +BytecodeCompiler::visit(IntegerLiteral *node)
2.34 {
2.35 __ int_(node->value());
2.36 }
2.37
2.38 void
2.39 +BytecodeCompiler::visit(FloatLiteral *node)
2.40 +{
2.41 + __ float_((float)node->value());
2.42 +}
2.43 +
2.44 +void
2.45 BytecodeCompiler::visit(VariableDeclaration *node)
2.46 {
2.47 Variable *var = node->variable();
3.1 --- a/jitcraft/BytecodeCompiler.h Tue Jun 26 00:58:55 2012 -0700
3.2 +++ b/jitcraft/BytecodeCompiler.h Wed Jun 27 02:21:56 2012 -0700
3.3 @@ -57,6 +57,7 @@
3.4 void leaveScope(Scope *scope);
3.5 void visitForTest(Expression *expression, BytecodeEmitter::Label *label, bool onTrue);
3.6 Code *compileFunction(Module *module, FunctionStatement *fun);
3.7 + void visitForALU(Type *needed, Expression *node);
3.8
3.9 public:
3.10 BytecodeCompiler(ParseTree *tree);
3.11 @@ -71,7 +72,8 @@
3.12 void visit(ForStatement *node);
3.13 void visit(BlockStatement *node);
3.14 void visit(VariableDeclaration *node);
3.15 - void visit(IntegerLiteralExpression *node);
3.16 + void visit(IntegerLiteral *node);
3.17 + void visit(FloatLiteral *node);
3.18 void visit(ExpressionStatement *node);
3.19 void visit(FunctionStatement *node);
3.20 void visit(CallExpression *node);
4.1 --- a/jitcraft/BytecodeEmitter.h Tue Jun 26 00:58:55 2012 -0700
4.2 +++ b/jitcraft/BytecodeEmitter.h Wed Jun 27 02:21:56 2012 -0700
4.3 @@ -54,6 +54,10 @@
4.4 assert(value >= 0 && value <= UCHAR_MAX);
4.5 *buffer_pos_++ = value;
4.6 }
4.7 + void writeFloat(float value) {
4.8 + *(float *)buffer_pos_ = value;
4.9 + buffer_pos_ += sizeof(float);
4.10 + }
4.11 void writeInt32(int value) {
4.12 *(int *)buffer_pos_ = value;
4.13 buffer_pos_ += sizeof(int);
4.14 @@ -271,6 +275,14 @@
4.15 void bounds_sta() {
4.16 singleByteOp(OP_BOUNDS_STA);
4.17 }
4.18 + void float_(float value) {
4.19 + ensure(OP_FLOAT_LENGTH);
4.20 + writeOp(OP_FLOAT);
4.21 + writeFloat(value);
4.22 + }
4.23 + void cvt_i2f() {
4.24 + singleByteOp(OP_CVT_I2F);
4.25 + }
4.26 };
4.27
4.28 }
5.1 --- a/jitcraft/Interpreter.cpp Tue Jun 26 00:58:55 2012 -0700
5.2 +++ b/jitcraft/Interpreter.cpp Wed Jun 27 02:21:56 2012 -0700
5.3 @@ -28,6 +28,12 @@
5.4 top.sp++; \
5.5 } while (0)
5.6
5.7 +#define PUSH_F(top, value) \
5.8 + do { \
5.9 + top.sp->f = value; \
5.10 + top.sp++; \
5.11 + } while (0)
5.12 +
5.13 static inline int
5.14 POP_I32(Top &top)
5.15 {
5.16 @@ -36,6 +42,14 @@
5.17 return value;
5.18 }
5.19
5.20 +static inline float
5.21 +POP_F(Top &top)
5.22 +{
5.23 + float value = top.sp[-1].f;
5.24 + top.sp--;
5.25 + return value;
5.26 +}
5.27 +
5.28 static inline bool
5.29 CheckDimensionSize(int size, unsigned width)
5.30 {
5.31 @@ -171,7 +185,7 @@
5.32 }
5.33
5.34 bool
5.35 -jc::Interpret(Frame *frame, int *result)
5.36 +jc::Interpret(Frame *frame, LocalSlot *result)
5.37 {
5.38 Top &top = *ZONE()->stack().top();
5.39 LocalSlot *locals = frame->locals();
5.40 @@ -187,17 +201,19 @@
5.41 PUSH_I32(top, READ_INT32(top.pc));
5.42 break;
5.43
5.44 +case OP_FLOAT:
5.45 + PUSH_F(top, READ_FLOAT(top.pc));
5.46 + break;
5.47 +
5.48 case OP_RETURN:
5.49 {
5.50 - int rval = POP_I32(top);
5.51 - if (!frame->prev()) {
5.52 - *result = rval;
5.53 + *result = *--top.sp;
5.54 + if (!frame->prev())
5.55 return true;
5.56 - }
5.57
5.58 frame = ZONE()->stack().popFrame(frame);
5.59 locals = frame->locals();
5.60 - PUSH_I32(top, rval);
5.61 + *top.sp++ = *result;
5.62 top.pc += OpcodeInfo[*top.pc].length;
5.63 continue;
5.64 }
5.65 @@ -312,6 +328,44 @@
5.66 break;
5.67 }
5.68
5.69 +case OP_ADD_F:
5.70 +{
5.71 + float right = POP_F(top);
5.72 + float left = POP_F(top);
5.73 + float result = left + right;
5.74 + PUSH_F(top, result);
5.75 + break;
5.76 +}
5.77 +
5.78 +case OP_SUB_F:
5.79 +{
5.80 + float right = POP_F(top);
5.81 + float left = POP_F(top);
5.82 + float result = left - right;
5.83 + PUSH_F(top, result);
5.84 + break;
5.85 +}
5.86 +
5.87 +case OP_MUL_F:
5.88 +{
5.89 + float right = POP_F(top);
5.90 + float left = POP_F(top);
5.91 + float result = left * right;
5.92 + PUSH_F(top, result);
5.93 + break;
5.94 +}
5.95 +
5.96 +case OP_DIV_F:
5.97 +{
5.98 + float right = POP_F(top);
5.99 + float left = POP_F(top);
5.100 + if (!right)
5.101 + return false;
5.102 + float result = left / right;
5.103 + PUSH_F(top, result);
5.104 + break;
5.105 +}
5.106 +
5.107 case OP_POP:
5.108 top.sp--;
5.109 break;
5.110 @@ -398,6 +452,14 @@
5.111 break;
5.112 }
5.113
5.114 +case OP_CVT_I2F:
5.115 +{
5.116 + int ival = POP_I32(top);
5.117 + float fval = (float)ival;
5.118 + PUSH_F(top, fval);
5.119 + break;
5.120 +}
5.121 +
5.122 default:
5.123 assert(false);
5.124 return false;
6.1 --- a/jitcraft/Interpreter.h Tue Jun 26 00:58:55 2012 -0700
6.2 +++ b/jitcraft/Interpreter.h Wed Jun 27 02:21:56 2012 -0700
6.3 @@ -22,7 +22,7 @@
6.4
6.5 namespace jc {
6.6
6.7 -bool Interpret(Frame *frame, int *result);
6.8 +bool Interpret(Frame *frame, LocalSlot *result);
6.9
6.10 // Virtual machine helper functions.
6.11 UnsafeArray *AllocateUnsafeArray(unsigned width, unsigned ndims, int *dims);
7.1 --- a/jitcraft/Opcodes.cpp Tue Jun 26 00:58:55 2012 -0700
7.2 +++ b/jitcraft/Opcodes.cpp Wed Jun 27 02:21:56 2012 -0700
7.3 @@ -55,6 +55,11 @@
7.4 case OP_SUB:
7.5 case OP_MUL:
7.6 case OP_DIV:
7.7 + case OP_ADD_F:
7.8 + case OP_SUB_F:
7.9 + case OP_MUL_F:
7.10 + case OP_DIV_F:
7.11 + case OP_CVT_I2F:
7.12 case OP_POP:
7.13 case OP_LD_STA_I:
7.14 case OP_LD_STA_P:
7.15 @@ -70,6 +75,10 @@
7.16 fprintf(fp, "%d", READ_INT32(pc));
7.17 break;
7.18
7.19 + case OP_FLOAT:
7.20 + fprintf(fp, "%f", READ_FLOAT(pc));
7.21 + break;
7.22 +
7.23 case OP_JL:
7.24 case OP_JLE:
7.25 case OP_JG:
8.1 --- a/jitcraft/Opcodes.h Tue Jun 26 00:58:55 2012 -0700
8.2 +++ b/jitcraft/Opcodes.h Wed Jun 27 02:21:56 2012 -0700
8.3 @@ -80,6 +80,11 @@
8.4 {
8.5 return *reinterpret_cast<unsigned *>(pc + 1);
8.6 }
8.7 +static inline float
8.8 +READ_FLOAT(bytecode *pc)
8.9 +{
8.10 + return *reinterpret_cast<float *>(pc + 1);
8.11 +}
8.12
8.13 class Code;
8.14
9.1 --- a/jitcraft/Opcodes.tbl Tue Jun 26 00:58:55 2012 -0700
9.2 +++ b/jitcraft/Opcodes.tbl Wed Jun 27 02:21:56 2012 -0700
9.3 @@ -116,3 +116,19 @@
9.4 // push(array)
9.5 // push(index)
9.6 OPDEF(OP_BOUNDS_STA, 28, "bounds.sta", 1, 2, 2)
9.7 +
9.8 +// Pushes a 32-bit IEEE-754 floating point immediate onto the stack.
9.9 +OPDEF(OP_FLOAT, 29, "float", 5, 0, 1)
9.10 +
9.11 +// Converts an integer to a 32-bit IEEE-754 floating point immediate.
9.12 +OPDEF(OP_CVT_I2F, 30, "cvt.i2f", 1, 1, 1)
9.13 +
9.14 +// Stack transitions for these binary operators:
9.15 +// rhs = pop()
9.16 +// lhs = pop()
9.17 +// push(lhs OP rhs)
9.18 +OPDEF(OP_ADD_F, 31, "add.f", 1, 2, 1)
9.19 +OPDEF(OP_SUB_F, 32, "sub.f", 1, 2, 1)
9.20 +OPDEF(OP_MUL_F, 33, "mul.f", 1, 2, 1)
9.21 +OPDEF(OP_DIV_F, 34, "div.f", 1, 2, 1)
9.22 +
10.1 --- a/jitcraft/Parser.cpp Tue Jun 26 00:58:55 2012 -0700
10.2 +++ b/jitcraft/Parser.cpp Wed Jun 27 02:21:56 2012 -0700
10.3 @@ -68,6 +68,25 @@
10.4 return proxy;
10.5 }
10.6
10.7 +bool
10.8 +Parser::matchName(Name **name, TokenKind kind)
10.9 +{
10.10 + assert(kind == TOK_NAME || kind == TOK_LABEL);
10.11 + *name = NULL;
10.12 + if (!match(kind))
10.13 + return false;
10.14 + *name = strings_.add(scanner_.literal());
10.15 + return true;
10.16 +}
10.17 +
10.18 +Name *
10.19 +Parser::expectName()
10.20 +{
10.21 + if (!expect(TOK_NAME))
10.22 + return NULL;
10.23 + return strings_.add(scanner_.literal());
10.24 +}
10.25 +
10.26 Expression *
10.27 Parser::primitive()
10.28 {
10.29 @@ -79,11 +98,18 @@
10.30 return bind(name);
10.31 }
10.32
10.33 + case TOK_FLOAT_LITERAL:
10.34 + {
10.35 + scanner_.scan();
10.36 + double value = Scanner::ParseDouble(scanner_.literal());
10.37 + return new (pool_) FloatLiteral(value);
10.38 + }
10.39 +
10.40 case TOK_INTEGER_LITERAL:
10.41 {
10.42 scanner_.scan();
10.43 int value = atoi(scanner_.literal());
10.44 - return new (pool_) IntegerLiteralExpression(value);
10.45 + return new (pool_) IntegerLiteral(value);
10.46 }
10.47
10.48 default:
10.49 @@ -326,11 +352,13 @@
10.50 if (!expect(TOK_NEW))
10.51 return NULL;
10.52
10.53 - // Get the name.
10.54 - if (!expect(TOK_NAME))
10.55 + Name *tag;
10.56 + if (matchName(&tag, TOK_LABEL) && !tag)
10.57 return NULL;
10.58 -
10.59 - Name *name = strings_.add(scanner_.literal());
10.60 +
10.61 + Name *name = expectName();
10.62 + if (!name)
10.63 + return NULL;
10.64
10.65 ExpressionList *postDimensions = NULL;
10.66 if (scanner_.peek() == TOK_LBRACKET) {
10.67 @@ -359,7 +387,7 @@
10.68 }
10.69
10.70 Variable *var = scope_->declareVariable(name);
10.71 - VariableDeclaration *decl = new (pool_) VariableDeclaration(var, postDimensions, expr);
10.72 + VariableDeclaration *decl = new (pool_) VariableDeclaration(var, tag, postDimensions, expr);
10.73
10.74 return decl;
10.75 }
10.76 @@ -549,10 +577,7 @@
10.77 if (scanner_.peek() == TOK_RBRACE)
10.78 break;
10.79
10.80 - if (!expect(TOK_NAME))
10.81 - return NULL;
10.82 -
10.83 - Name *name = strings_.add(scanner_.literal());
10.84 + Name *name = expectName();
10.85 if (!name)
10.86 return NULL;
10.87
10.88 @@ -582,9 +607,7 @@
10.89 Statement *
10.90 Parser::function()
10.91 {
10.92 - expect(TOK_NAME);
10.93 -
10.94 - Name *name = strings_.add(scanner_.literal());
10.95 + Name *name = expectName();
10.96 if (!name)
10.97 return NULL;
10.98
10.99 @@ -607,10 +630,7 @@
10.100 return NULL;
10.101 if (!match(TOK_RPAREN)) {
10.102 while (true) {
10.103 - if (!expect(TOK_NAME))
10.104 - return NULL;
10.105 -
10.106 - Name *name = strings_.add(scanner_.literal());
10.107 + Name *name = expectName();
10.108 if (!name)
10.109 return NULL;
10.110
10.111 @@ -783,9 +803,13 @@
10.112 node->initialization()->accept(this);
10.113 unindent();
10.114 }
10.115 - void visit(IntegerLiteralExpression *node) {
10.116 + void visit(IntegerLiteral *node) {
10.117 prefix();
10.118 - fprintf(fp_, "[ LiteralExpression (%d)\n", node->value());
10.119 + fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
10.120 + }
10.121 + void visit(FloatLiteral *node) {
10.122 + prefix();
10.123 + fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
10.124 }
10.125 void visit(IfStatement *node) {
10.126 prefix();
11.1 --- a/jitcraft/Parser.h Tue Jun 26 00:58:55 2012 -0700
11.2 +++ b/jitcraft/Parser.h Wed Jun 27 02:21:56 2012 -0700
11.3 @@ -45,6 +45,8 @@
11.4 Scope *enterScope(Scope::Kind kind);
11.5
11.6 VariableDeclaration *variableDeclaration();
11.7 + bool matchName(Name **name, TokenKind kind = TOK_NAME);
11.8 + Name *expectName();
11.9 NameProxy *bind(Name *name);
11.10 Expression *primitive();
11.11 Expression *call(Expression *callee);
12.1 --- a/jitcraft/Scanner.cpp Tue Jun 26 00:58:55 2012 -0700
12.2 +++ b/jitcraft/Scanner.cpp Wed Jun 27 02:21:56 2012 -0700
12.3 @@ -86,21 +86,115 @@
12.4 return false;
12.5 }
12.6
12.7 +static inline bool
12.8 +IsDigit(char c)
12.9 +{
12.10 + return c >= '0' && c <= '9';
12.11 +}
12.12 +
12.13 +// Based off the logic in sc2.c's ftoi()...
12.14 +double
12.15 +Scanner::ParseDouble(const char *string)
12.16 +{
12.17 + const char *ptr = string;
12.18 +
12.19 + double number = 0.0;
12.20 + while (IsDigit(*ptr)) {
12.21 + number = (number * 10) + (*ptr - '0');
12.22 + ptr++;
12.23 + }
12.24 +
12.25 + assert(*ptr == '.');
12.26 + ptr++;
12.27 +
12.28 + double fraction = 0.0;
12.29 + double multiplier = 1.0;
12.30 + while (IsDigit(*ptr)) {
12.31 + fraction = (fraction * 10) + (*ptr - '0');
12.32 + multiplier = multiplier / 10.0;
12.33 + ptr++;
12.34 + }
12.35 +
12.36 + number += fraction * multiplier;
12.37 +
12.38 + if (*ptr++ == 'e') {
12.39 + int sign = 1;
12.40 + if (*ptr == '-') {
12.41 + sign = -1;
12.42 + ptr++;
12.43 + }
12.44 +
12.45 + int exponent = 0;
12.46 + while (IsDigit(*ptr)) {
12.47 + exponent = (exponent * 10) + (*ptr - '0');
12.48 + ptr++;
12.49 + }
12.50 +
12.51 + multiplier = pow(10.0, exponent * sign);
12.52 + number *= multiplier;
12.53 + }
12.54 +
12.55 + return number;
12.56 +}
12.57 +
12.58 TokenKind
12.59 -Scanner::integerLiteral(char first)
12.60 +Scanner::numberLiteral(char first)
12.61 {
12.62 literal_ = first;
12.63
12.64 + char c;
12.65 for (;;) {
12.66 - char c = getChar();
12.67 - if (c < '0' || c > '9') {
12.68 - putChar(c);
12.69 + c = getChar();
12.70 + if (!IsDigit(c))
12.71 break;
12.72 - }
12.73 literal_ += c;
12.74 }
12.75
12.76 - return TOK_INTEGER_LITERAL;
12.77 + if (c != '.') {
12.78 + putChar(c);
12.79 + return TOK_INTEGER_LITERAL;
12.80 + }
12.81 + literal_ += c;
12.82 +
12.83 + c = getChar();
12.84 + if (!IsDigit(c)) {
12.85 + assert(false);
12.86 + return TOK_ERROR;
12.87 + }
12.88 + literal_ += c;
12.89 +
12.90 + for (;;) {
12.91 + c = getChar();
12.92 + if (!IsDigit(c))
12.93 + break;
12.94 + literal_ += c;
12.95 + }
12.96 +
12.97 + if (c != 'e') {
12.98 + putChar(c);
12.99 + } else {
12.100 + literal_ += c;
12.101 + c = getChar();
12.102 + if (c == '-') {
12.103 + literal_ += c;
12.104 + c = getChar();
12.105 + }
12.106 + if (!IsDigit(c)) {
12.107 + assert(false);
12.108 + return TOK_ERROR;
12.109 + }
12.110 + literal_ += c;
12.111 + for (;;) {
12.112 + c = getChar();
12.113 + if (!IsDigit(c)) {
12.114 + putChar(c);
12.115 + break;
12.116 + }
12.117 + literal_ += c;
12.118 + }
12.119 + }
12.120 +
12.121 + return TOK_FLOAT_LITERAL;
12.122 }
12.123
12.124 TokenKind
12.125 @@ -108,10 +202,12 @@
12.126 {
12.127 literal_ = first;
12.128
12.129 + char c;
12.130 for (;;) {
12.131 - char c = getChar();
12.132 + c = getChar();
12.133 if (!isascii(c) || (!isalnum(c) && c != '_')) {
12.134 - putChar(c);
12.135 + if (c != ':')
12.136 + putChar(c);
12.137 break;
12.138 }
12.139 literal_ += c;
12.140 @@ -129,7 +225,7 @@
12.141 return TOK_ELSE;
12.142 if (literal_ == "enum")
12.143 return TOK_ENUM;
12.144 - return TOK_NAME;
12.145 + return (c == ':') ? TOK_LABEL : TOK_NAME;
12.146 }
12.147
12.148 TokenKind
12.149 @@ -218,9 +314,10 @@
12.150
12.151 default:
12.152 if (c >= '0' && c <= '9')
12.153 - return integerLiteral(c);
12.154 + return numberLiteral(c);
12.155 if (c == '_' || (isascii(c) && isalpha(c)))
12.156 return identifier(c);
12.157 + assert(false);
12.158 return TOK_ERROR;
12.159 }
12.160 }
13.1 --- a/jitcraft/Scanner.h Tue Jun 26 00:58:55 2012 -0700
13.2 +++ b/jitcraft/Scanner.h Wed Jun 27 02:21:56 2012 -0700
13.3 @@ -38,7 +38,7 @@
13.4 void putChar(char c);
13.5 void eatSingleLine();
13.6 bool eatComment();
13.7 - TokenKind integerLiteral(char first);
13.8 + TokenKind numberLiteral(char first);
13.9 TokenKind identifier(char first);
13.10
13.11 TokenKind next();
13.12 @@ -46,6 +46,8 @@
13.13 public:
13.14 Scanner(const char *stream, size_t length);
13.15
13.16 + static double ParseDouble(const char *string);
13.17 +
13.18 TokenKind scan();
13.19 TokenKind peek();
13.20 TokenKind last() const {
14.1 --- a/jitcraft/SemanticAnalysis.cpp Tue Jun 26 00:58:55 2012 -0700
14.2 +++ b/jitcraft/SemanticAnalysis.cpp Wed Jun 27 02:21:56 2012 -0700
14.3 @@ -80,8 +80,8 @@
14.4 return true;
14.5 }
14.6
14.7 - case AstNode::kIntegerLiteralExpression:
14.8 - *out = BoxedPrimitive::Int(expression->toIntegerLiteralExpression()->value());
14.9 + case AstNode::kIntegerLiteral:
14.10 + *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
14.11 return true;
14.12
14.13 default:
14.14 @@ -111,15 +111,29 @@
14.15 name->setType(name->binding()->type());
14.16 }
14.17
14.18 +static inline bool
14.19 +TypeCheck(Type *left, Type *right)
14.20 +{
14.21 + if (!left || !right)
14.22 + return false;
14.23 +
14.24 + if (left->isPrimitive()) {
14.25 + if (!right->isPrimitive())
14.26 + return false;
14.27 + return left->primitive() == right->primitive();
14.28 + }
14.29 +
14.30 + return false;
14.31 +}
14.32 +
14.33 void
14.34 SemanticAnalysis::visit(Assignment *node)
14.35 {
14.36 node->expression()->accept(this);
14.37
14.38 if (node->lvalue()->isIndexExpression()) {
14.39 - node->lvalue()->accept(this);
14.40 -
14.41 - node->setType(node->lvalue()->type());
14.42 + node->lvalue()->accept(this);
14.43 + node->setType(node->lvalue()->type()->contained());
14.44 } else {
14.45 NameProxy *proxy = node->lvalue()->toNameProxy();
14.46 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
14.47 @@ -130,11 +144,37 @@
14.48 Variable *var = proxy->binding()->toVariable();
14.49 node->setType(var->type());
14.50 }
14.51 +
14.52 + assert(TypeCheck(node->type(), node->expression()->type()));
14.53 }
14.54
14.55 +
14.56 void
14.57 SemanticAnalysis::visit(BinaryExpression *node)
14.58 {
14.59 + node->left()->accept(this);
14.60 + node->right()->accept(this);
14.61 +
14.62 + if (node->token() >= TOK_PLUS && node->token() <= TOK_SLASH) {
14.63 + // Both sides must be primitive.
14.64 + Type *left = node->left()->type();
14.65 + Type *right = node->right()->type();
14.66 + if (!left || !right)
14.67 + return;
14.68 +
14.69 + // If either side is a float, the other side must be a float or int.
14.70 + if (left->isFloat() || right->isFloat()) {
14.71 + assert(left->isFloat() || left->isInt());
14.72 + assert(right->isFloat() || right->isInt());
14.73 + node->setType(left->isFloat() ? left : right);
14.74 + return;
14.75 + }
14.76 +
14.77 + // Otherwise, both sides must be integer.
14.78 + assert(left->isInt() && right->isInt());
14.79 + node->setType(left);
14.80 + return;
14.81 + }
14.82 }
14.83
14.84 void
14.85 @@ -169,9 +209,7 @@
14.86 void
14.87 SemanticAnalysis::visit(VariableDeclaration *node)
14.88 {
14.89 - Tag *tag = NULL;
14.90 -
14.91 - Type *type = Type::NewPrimitive(tag);
14.92 + Type *type = Type::NewPrimitive(node->tag());
14.93 if (!type)
14.94 return;
14.95
14.96 @@ -191,8 +229,8 @@
14.97 }
14.98
14.99 int size = -1;
14.100 - if (expr->isIntegerLiteralExpression()) {
14.101 - size = expr->toIntegerLiteralExpression()->value();
14.102 + if (expr->isIntegerLiteral()) {
14.103 + size = expr->toIntegerLiteral()->value();
14.104 if (size <= 0) {
14.105 error();
14.106 return;
14.107 @@ -211,7 +249,7 @@
14.108 }
14.109
14.110 void
14.111 -SemanticAnalysis::visit(IntegerLiteralExpression *node)
14.112 +SemanticAnalysis::visit(IntegerLiteral *node)
14.113 {
14.114 Type *type = Type::NewPrimitive(NULL);
14.115 node->setType(type);
14.116 @@ -259,12 +297,8 @@
14.117 void
14.118 SemanticAnalysis::visit(EnumStatement *node)
14.119 {
14.120 - Tag *tag = NULL;
14.121 - if (node->name()) {
14.122 - tag = new Tag(node->name());
14.123 - if (!tag)
14.124 - return;
14.125 - }
14.126 + // :TODO: test "enum Float { ..."
14.127 + Name *tag = node->name();
14.128
14.129 Type *type = Type::NewPrimitive(tag);
14.130 if (!type)
14.131 @@ -288,3 +322,13 @@
14.132 value++;
14.133 }
14.134 }
14.135 +
14.136 +void
14.137 +SemanticAnalysis::visit(FloatLiteral *node)
14.138 +{
14.139 + Type *type = Type::NewPrimitive(PrimitiveType_Float);
14.140 + if (!type)
14.141 + return;
14.142 +
14.143 + node->setType(type);
14.144 +}
15.1 --- a/jitcraft/SemanticAnalysis.h Tue Jun 26 00:58:55 2012 -0700
15.2 +++ b/jitcraft/SemanticAnalysis.h Wed Jun 27 02:21:56 2012 -0700
15.3 @@ -47,13 +47,14 @@
15.4 void visit(ForStatement *node);
15.5 void visit(BlockStatement *node);
15.6 void visit(VariableDeclaration *node);
15.7 - void visit(IntegerLiteralExpression *node);
15.8 + void visit(IntegerLiteral *node);
15.9 void visit(ExpressionStatement *node);
15.10 void visit(FunctionStatement *node);
15.11 void visit(CallExpression *node);
15.12 void visit(IfStatement *node);
15.13 void visit(IndexExpression *node);
15.14 void visit(EnumStatement *node);
15.15 + void visit(FloatLiteral *node);
15.16 };
15.17
15.18 } // namespace jc
16.1 --- a/jitcraft/Stack.h Tue Jun 26 00:58:55 2012 -0700
16.2 +++ b/jitcraft/Stack.h Wed Jun 27 02:21:56 2012 -0700
16.3 @@ -28,6 +28,7 @@
16.4 union LocalSlot
16.5 {
16.6 int i32;
16.7 + float f;
16.8 void *p;
16.9 UnsafeArray *unsafeArray;
16.10 };
17.1 --- a/jitcraft/Token.h Tue Jun 26 00:58:55 2012 -0700
17.2 +++ b/jitcraft/Token.h Wed Jun 27 02:21:56 2012 -0700
17.3 @@ -27,9 +27,11 @@
17.4 _(RETURN, "'return'") \
17.5 _(NAME, "<name>") \
17.6 _(INTEGER_LITERAL, "<integer>") \
17.7 + _(FLOAT_LITERAL, "<float>") \
17.8 _(IF, "<if>") \
17.9 _(ELSE, "<else>") \
17.10 _(ENUM, "<enum>") \
17.11 + _(LABEL, "<label>") \
17.12 _(PLUS, "+") \
17.13 _(MINUS, "-") \
17.14 _(STAR, "*") \
18.1 --- a/jitcraft/Types.cpp Tue Jun 26 00:58:55 2012 -0700
18.2 +++ b/jitcraft/Types.cpp Wed Jun 27 02:21:56 2012 -0700
18.3 @@ -19,19 +19,27 @@
18.4
18.5 using namespace jc;
18.6
18.7 -Tag::Tag(Name *name)
18.8 - : name_(name)
18.9 -{
18.10 -}
18.11 -
18.12 Type *
18.13 -Type::NewPrimitive(Tag *tag)
18.14 +Type::NewPrimitive(Name *tag)
18.15 {
18.16 Type *type = new Type;
18.17 type->kind_ = PRIMITIVE;
18.18 type->tag_ = tag;
18.19
18.20 - type->primitive_ = PrimitiveType_Int32;
18.21 + if (tag && strcmp(tag, "Float") == 0)
18.22 + type->primitive_ = PrimitiveType_Float;
18.23 + else
18.24 + type->primitive_ = PrimitiveType_Int32;
18.25 + return type;
18.26 +}
18.27 +
18.28 +Type *
18.29 +Type::NewPrimitive(PrimitiveType prim)
18.30 +{
18.31 + Type *type = new Type;
18.32 + type->kind_ = PRIMITIVE;
18.33 + type->tag_ = NULL;
18.34 + type->primitive_ = prim;
18.35 return type;
18.36 }
18.37
19.1 --- a/jitcraft/Types.h Tue Jun 26 00:58:55 2012 -0700
19.2 +++ b/jitcraft/Types.h Wed Jun 27 02:21:56 2012 -0700
19.3 @@ -22,22 +22,10 @@
19.4
19.5 namespace jc {
19.6
19.7 -// Tags are a weak form of user-created types.
19.8 -class Tag
19.9 -{
19.10 - Name *name_;
19.11 -
19.12 - public:
19.13 - Tag(Name *name);
19.14 -
19.15 - Name *name() const {
19.16 - return name_;
19.17 - }
19.18 -};
19.19 -
19.20 enum PrimitiveType
19.21 {
19.22 - PrimitiveType_Int32
19.23 + PrimitiveType_Int32,
19.24 + PrimitiveType_Float
19.25 };
19.26
19.27 class Type
19.28 @@ -51,7 +39,8 @@
19.29 static const int UNKNOWN_SIZE = -1;
19.30 static const size_t MAX_UNSAFE_ARRAY_DEPTH = 5;
19.31
19.32 - static Type *NewPrimitive(Tag *tag);
19.33 + static Type *NewPrimitive(Name *tag);
19.34 + static Type *NewPrimitive(PrimitiveType type);
19.35 static Type *NewUnsafeArray(Type *contained, int elements);
19.36
19.37 bool isPrimitive() const {
19.38 @@ -86,12 +75,18 @@
19.39 temp = temp->contained();
19.40 return temp;
19.41 }
19.42 + bool isFloat() const {
19.43 + return isPrimitive() && primitive() == PrimitiveType_Float;
19.44 + }
19.45 + bool isInt() const {
19.46 + return isPrimitive() && primitive() == PrimitiveType_Int32;
19.47 + }
19.48
19.49 private:
19.50 Kind kind_;
19.51
19.52 // If a primitive type, these tell the kind of type.
19.53 - Tag *tag_;
19.54 + Name *tag_;
19.55 PrimitiveType primitive_;
19.56
19.57 // The contained type of an array.
20.1 --- a/jitcraft/main.cpp Tue Jun 26 00:58:55 2012 -0700
20.2 +++ b/jitcraft/main.cpp Wed Jun 27 02:21:56 2012 -0700
20.3 @@ -92,11 +92,11 @@
20.4 if (!frame)
20.5 return false;
20.6
20.7 - int result;
20.8 + LocalSlot result;
20.9 if (!Interpret(frame, &result))
20.10 return false;
20.11
20.12 - printf("Result: %d\n", result);
20.13 + printf("Result: %f\n", result.f);
20.14
20.15 return true;
20.16 }