Added support for enums.
Added support for enums.
1.1 --- a/jitcraft/AST.h Mon Jun 25 21:20:01 2012 -0700
1.2 +++ b/jitcraft/AST.h Tue Jun 26 00:35:15 2012 -0700
1.3 @@ -38,7 +38,8 @@
1.4 _(FunctionStatement) \
1.5 _(CallExpression) \
1.6 _(IfStatement) \
1.7 - _(IndexExpression)
1.8 + _(IndexExpression) \
1.9 + _(EnumStatement)
1.10
1.11 // Forward declarations.
1.12 #define _(name) class name;
1.13 @@ -501,6 +502,48 @@
1.14 }
1.15 };
1.16
1.17 +class EnumStatement : public Statement
1.18 +{
1.19 + Name *name_;
1.20 +
1.21 + public:
1.22 + struct Entry {
1.23 + NamedConstant *name;
1.24 + Expression *expr;
1.25 +
1.26 + Entry(NamedConstant *name, Expression *expr)
1.27 + : name(name),
1.28 + expr(expr)
1.29 + {
1.30 + }
1.31 + };
1.32 +
1.33 + typedef std::vector<Entry> EntryList;
1.34 +
1.35 + public:
1.36 + EnumStatement(Name *name, EntryList *entries)
1.37 + : name_(name),
1.38 + entries_(entries)
1.39 + {
1.40 + }
1.41 +
1.42 + Kind kind() const {
1.43 + return kEnumStatement;
1.44 + }
1.45 + Name *name() const {
1.46 + return name_;
1.47 + }
1.48 + EntryList *entries() const {
1.49 + return entries_;
1.50 + }
1.51 + void accept(AstVisitor *visitor) {
1.52 + visitor->visit(this);
1.53 + }
1.54 +
1.55 + private:
1.56 + EntryList *entries_;
1.57 +};
1.58 +
1.59 class Scope;
1.60
1.61 typedef std::vector<NameProxy *> NameProxyList;
2.1 --- a/jitcraft/BytecodeCompiler.cpp Mon Jun 25 21:20:01 2012 -0700
2.2 +++ b/jitcraft/BytecodeCompiler.cpp Tue Jun 26 00:35:15 2012 -0700
2.3 @@ -94,13 +94,26 @@
2.4 void
2.5 BytecodeCompiler::visit(NameProxy *name)
2.6 {
2.7 - Variable *var = name->binding()->toVariable();
2.8 + switch (name->binding()->kind()) {
2.9 + case BoundName::VARIABLE:
2.10 + {
2.11 + Variable *var = name->binding()->toVariable();
2.12
2.13 - if (var->location() == Variable::STACK) {
2.14 - __ getlocal(var->slot());
2.15 - } else {
2.16 - assert(var->location() == Variable::PARAMETER);
2.17 - __ getarg(var->slot());
2.18 + if (var->location() == Variable::STACK) {
2.19 + __ getlocal(var->slot());
2.20 + } else {
2.21 + assert(var->location() == Variable::PARAMETER);
2.22 + __ getarg(var->slot());
2.23 + }
2.24 + break;
2.25 + }
2.26 +
2.27 + default:
2.28 + {
2.29 + NamedConstant *constant = name->binding()->toNamedConstant();
2.30 + __ int_(constant->value().toInt());
2.31 + break;
2.32 + }
2.33 }
2.34 }
2.35
2.36 @@ -328,6 +341,12 @@
2.37 module_->setFunction(node->fun()->slot(), code);
2.38 }
2.39
2.40 +void
2.41 +BytecodeCompiler::visit(EnumStatement *node)
2.42 +{
2.43 + // :TODO: eventually, we'll export these.
2.44 +}
2.45 +
2.46 Code *
2.47 BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
2.48 {
3.1 --- a/jitcraft/BytecodeCompiler.h Mon Jun 25 21:20:01 2012 -0700
3.2 +++ b/jitcraft/BytecodeCompiler.h Tue Jun 26 00:35:15 2012 -0700
3.3 @@ -77,6 +77,7 @@
3.4 void visit(CallExpression *node);
3.5 void visit(IfStatement *node);
3.6 void visit(IndexExpression *node);
3.7 + void visit(EnumStatement *node);
3.8 };
3.9
3.10 }
4.1 --- a/jitcraft/NameBinding.h Mon Jun 25 21:20:01 2012 -0700
4.2 +++ b/jitcraft/NameBinding.h Tue Jun 26 00:35:15 2012 -0700
4.3 @@ -20,6 +20,7 @@
4.4
4.5 #include "PoolAllocator.h"
4.6 #include "StringPool.h"
4.7 +#include "Types.h"
4.8
4.9 namespace jc {
4.10
4.11 @@ -27,6 +28,8 @@
4.12 class NamedFunction;
4.13 class Scope;
4.14 class Type;
4.15 +class NamedEnum;
4.16 +class NamedConstant;
4.17
4.18 class BoundName : public PoolObject
4.19 {
4.20 @@ -38,7 +41,8 @@
4.21 enum Kind {
4.22 VARIABLE,
4.23 FUNCTION,
4.24 - TAG
4.25 + ENUM,
4.26 + CONSTANT
4.27 };
4.28
4.29 BoundName(Scope *scope, Name *name);
4.30 @@ -59,6 +63,10 @@
4.31 assert(kind() == FUNCTION);
4.32 return reinterpret_cast<NamedFunction *>(this);
4.33 }
4.34 + NamedConstant *toNamedConstant() {
4.35 + assert(kind() == CONSTANT);
4.36 + return reinterpret_cast<NamedConstant *>(this);
4.37 + }
4.38 Type *type() const {
4.39 return type_;
4.40 }
4.41 @@ -85,22 +93,43 @@
4.42 }
4.43 };
4.44
4.45 -class NamedTag : public BoundName
4.46 +class NamedEnum : public BoundName
4.47 {
4.48 - Tag *tag_;
4.49 -
4.50 public:
4.51 - NamedTag(Scope *scope, Name *name)
4.52 - : BoundName(scope, name),
4.53 - tag_(NULL)
4.54 + NamedEnum(Scope *scope, Name *name)
4.55 + : BoundName(scope, name)
4.56 {
4.57 }
4.58
4.59 - Tag *tag() {
4.60 - return tag_;
4.61 + Kind kind() const {
4.62 + return ENUM;
4.63 }
4.64 - void setTag(Tag *tag) {
4.65 - tag_ = tag;
4.66 +};
4.67 +
4.68 +class NamedConstant : public BoundName
4.69 +{
4.70 + BoxedPrimitive value_;
4.71 + Type *type_;
4.72 +
4.73 + public:
4.74 + NamedConstant(Scope *scope, Name *name)
4.75 + : BoundName(scope, name),
4.76 + type_(NULL)
4.77 + {
4.78 + }
4.79 +
4.80 + Kind kind() const {
4.81 + return CONSTANT;
4.82 + }
4.83 + void set(Type *type, const BoxedPrimitive &value) {
4.84 + value_ = value;
4.85 + type_ = type;
4.86 + }
4.87 + Type *type() const {
4.88 + return type_;
4.89 + }
4.90 + BoxedPrimitive value() const {
4.91 + return value_;
4.92 }
4.93 };
4.94
5.1 --- a/jitcraft/Parser.cpp Mon Jun 25 21:20:01 2012 -0700
5.2 +++ b/jitcraft/Parser.cpp Tue Jun 26 00:35:15 2012 -0700
5.3 @@ -221,15 +221,31 @@
5.4 }
5.5
5.6 Expression *
5.7 +Parser::shift()
5.8 +{
5.9 + Expression *left = addition();
5.10 + while (left) {
5.11 + if (!match(TOK_SHL))
5.12 + break;
5.13 + TokenKind kind = scanner_.last();
5.14 + Expression *right = addition();
5.15 + if (!right)
5.16 + return NULL;
5.17 + left = new (pool_) BinaryExpression(kind, left, right);
5.18 + }
5.19 + return left;
5.20 +}
5.21 +
5.22 +Expression *
5.23 Parser::relational()
5.24 {
5.25 - Expression *left = addition();
5.26 + Expression *left = shift();
5.27 while (left) {
5.28 TokenKind kind = scanner_.peek();
5.29 if (kind < TOK_LT || kind > TOK_GE)
5.30 break;
5.31 scanner_.scan();
5.32 - Expression *right = addition();
5.33 + Expression *right = shift();
5.34 if (!right)
5.35 return NULL;
5.36 left = new (pool_) BinaryExpression(kind, left, right);
5.37 @@ -482,6 +498,10 @@
5.38 statement = returnStatement();
5.39 break;
5.40
5.41 + case TOK_ENUM:
5.42 + statement = enum_();
5.43 + break;
5.44 +
5.45 case TOK_IF:
5.46 return if_();
5.47
5.48 @@ -501,6 +521,65 @@
5.49 }
5.50
5.51 Statement *
5.52 +Parser::enum_()
5.53 +{
5.54 + expect(TOK_ENUM);
5.55 +
5.56 + Name *name = NULL;
5.57 + if (match(TOK_NAME)) {
5.58 + if ((name = strings_.add(scanner_.literal())) == NULL)
5.59 + return NULL;
5.60 +
5.61 + if (scope_->localLookup(name)) {
5.62 + redeclarationError();
5.63 + return NULL;
5.64 + }
5.65 +
5.66 + NamedEnum *e = scope_->declareEnum(name);
5.67 + if (!e)
5.68 + return NULL;
5.69 + }
5.70 +
5.71 + EnumStatement::EntryList *entries = new EnumStatement::EntryList();
5.72 +
5.73 + if (!expect(TOK_LBRACE))
5.74 + return NULL;
5.75 +
5.76 + do {
5.77 + if (scanner_.peek() == TOK_RBRACE)
5.78 + break;
5.79 +
5.80 + if (!expect(TOK_NAME))
5.81 + return NULL;
5.82 +
5.83 + Name *name = strings_.add(scanner_.literal());
5.84 + if (!name)
5.85 + return NULL;
5.86 +
5.87 + if (scope_->localLookup(name)) {
5.88 + redeclarationError();
5.89 + return NULL;
5.90 + }
5.91 +
5.92 + NamedConstant *constant = scope_->declareConstant(name);
5.93 + if (!constant)
5.94 + return NULL;
5.95 +
5.96 + Expression *expr = NULL;
5.97 + if (match(TOK_ASSIGN)) {
5.98 + if ((expr = expression()) == NULL)
5.99 + return NULL;
5.100 + }
5.101 +
5.102 + entries->push_back(EnumStatement::Entry(constant, expr));
5.103 + } while (match(TOK_COMMA));
5.104 + if (!expect(TOK_RBRACE))
5.105 + return NULL;
5.106 +
5.107 + return new (pool_) EnumStatement(name, entries);
5.108 +}
5.109 +
5.110 +Statement *
5.111 Parser::function()
5.112 {
5.113 expect(TOK_NAME);
5.114 @@ -580,6 +659,12 @@
5.115 return NULL;
5.116 break;
5.117
5.118 + case TOK_ENUM:
5.119 + if ((statement = enum_()) == NULL)
5.120 + return NULL;
5.121 + // :TODO: require semicolon
5.122 + break;
5.123 +
5.124 default:
5.125 fprintf(stderr, "expected function or global variable\n");
5.126 return NULL;
5.127 @@ -719,6 +804,21 @@
5.128 node->right()->accept(this);
5.129 unindent();
5.130 }
5.131 + void visit(EnumStatement *node) {
5.132 + prefix();
5.133 + fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name() : "<anonymous>");
5.134 + indent();
5.135 + for (size_t i = 0; i < node->entries()->size(); i++) {
5.136 + prefix();
5.137 + fprintf(fp_, "%s =\n", node->entries()->at(i).name->name());
5.138 + if (node->entries()->at(i).expr) {
5.139 + indent();
5.140 + node->entries()->at(i).expr->accept(this);
5.141 + unindent();
5.142 + }
5.143 + }
5.144 + unindent();
5.145 + }
5.146 };
5.147
5.148 void
6.1 --- a/jitcraft/Parser.h Mon Jun 25 21:20:01 2012 -0700
6.2 +++ b/jitcraft/Parser.h Tue Jun 26 00:35:15 2012 -0700
6.3 @@ -37,6 +37,7 @@
6.4
6.5 private:
6.6 void redeclarationError() {
6.7 + assert(false);
6.8 }
6.9 bool match(TokenKind kind);
6.10 bool expect(TokenKind kind);
6.11 @@ -52,11 +53,13 @@
6.12 Expression *primary();
6.13 Expression *unary();
6.14 Expression *multiplication();
6.15 + Expression *shift();
6.16 Expression *addition();
6.17 Expression *relational();
6.18 Expression *equals();
6.19 Expression *expression();
6.20
6.21 + Statement *enum_();
6.22 Statement *if_();
6.23 Statement *block();
6.24 Statement *function();
7.1 --- a/jitcraft/Scanner.cpp Mon Jun 25 21:20:01 2012 -0700
7.2 +++ b/jitcraft/Scanner.cpp Tue Jun 26 00:35:15 2012 -0700
7.3 @@ -127,6 +127,8 @@
7.4 return TOK_IF;
7.5 if (literal_ == "else")
7.6 return TOK_ELSE;
7.7 + if (literal_ == "enum")
7.8 + return TOK_ENUM;
7.9 return TOK_NAME;
7.10 }
7.11
7.12 @@ -161,8 +163,21 @@
7.13 case ')': return TOK_RPAREN;
7.14 case '[': return TOK_LBRACKET;
7.15 case ']': return TOK_RBRACKET;
7.16 - case '*': return TOK_STAR;
7.17 - case '+': return TOK_PLUS;
7.18 +
7.19 + case '*':
7.20 + c = getChar();
7.21 + if (c == '=')
7.22 + return TOK_ASSIGN_MUL;
7.23 + putChar(c);
7.24 + return TOK_STAR;
7.25 +
7.26 + case '+':
7.27 + c = getChar();
7.28 + if (c == '=')
7.29 + return TOK_ASSIGN_ADD;
7.30 + putChar(c);
7.31 + return TOK_PLUS;
7.32 +
7.33 case '-': return TOK_MINUS;
7.34 case ',': return TOK_COMMA;
7.35 case '\0': return TOK_EOF;
7.36 @@ -178,6 +193,12 @@
7.37 c = getChar();
7.38 if (c == '=')
7.39 return TOK_LE;
7.40 + if (c == '<') {
7.41 + c = getChar();
7.42 + if (c == '=')
7.43 + return TOK_ASSIGN_SHL;
7.44 + return TOK_SHL;
7.45 + }
7.46 putChar(c);
7.47 return TOK_LT;
7.48
8.1 --- a/jitcraft/Scopes.cpp Mon Jun 25 21:20:01 2012 -0700
8.2 +++ b/jitcraft/Scopes.cpp Tue Jun 26 00:35:15 2012 -0700
8.3 @@ -104,12 +104,29 @@
8.4 Scope::declareFunction(Name *name)
8.5 {
8.6 assert(!localLookup(name));
8.7 + assert(kind() == GLOBAL);
8.8
8.9 NamedFunction *fun = new (pool_) NamedFunction(this, name);
8.10 names_.push_back(fun);
8.11 return fun;
8.12 }
8.13
8.14 +NamedEnum *
8.15 +Scope::declareEnum(Name *name)
8.16 +{
8.17 + NamedEnum *e = new (pool_) NamedEnum(this, name);
8.18 + names_.push_back(e);
8.19 + return e;
8.20 +}
8.21 +
8.22 +NamedConstant *
8.23 +Scope::declareConstant(Name *name)
8.24 +{
8.25 + NamedConstant *constant = new (pool_) NamedConstant(this, name);
8.26 + names_.push_back(constant);
8.27 + return constant;
8.28 +}
8.29 +
8.30 void
8.31 Scope::allocateGlobals()
8.32 {
8.33 @@ -123,8 +140,10 @@
8.34 for (size_t i = 0; i < names_.size(); i++) {
8.35 BoundName *name = names_[i];
8.36
8.37 - NamedFunction *fun = name->toNamedFunction();
8.38 - fun->allocate(numFunctions_++);
8.39 + if (name->kind() == FUNCTION) {
8.40 + NamedFunction *fun = name->toNamedFunction();
8.41 + fun->allocate(numFunctions_++);
8.42 + }
8.43 }
8.44 }
8.45
8.46 @@ -144,7 +163,8 @@
8.47
8.48 locals_ = 0;
8.49 for (size_t i = 0; i < names_.size(); i++) {
8.50 - assert(names_[i]->kind() == BoundName::VARIABLE);
8.51 + if (names_[i]->kind() != BoundName::VARIABLE)
8.52 + continue;
8.53
8.54 Variable *var = names_[i]->toVariable();
8.55 if (var->unallocated()) {
8.56 @@ -162,8 +182,10 @@
8.57 for (size_t i = 0; i < tree->unbound()->size(); i++) {
8.58 NameProxy *proxy = tree->unbound()->at(i);
8.59 BoundName *name = tree->scope()->lookup(proxy->name());
8.60 - if (!name)
8.61 + if (!name) {
8.62 + assert(false);
8.63 return false;
8.64 + }
8.65
8.66 proxy->bind(name);
8.67 }
9.1 --- a/jitcraft/Scopes.h Mon Jun 25 21:20:01 2012 -0700
9.2 +++ b/jitcraft/Scopes.h Tue Jun 26 00:35:15 2012 -0700
9.3 @@ -80,6 +80,8 @@
9.4 NamedFunction *declareFunction(Name *name);
9.5 Variable *declareVariable(Name *name);
9.6 Variable *declareArgument(Name *name);
9.7 + NamedEnum *declareEnum(Name *name);
9.8 + NamedConstant *declareConstant(Name *name);
9.9 void allocate();
9.10 void allocateGlobals();
9.11
10.1 --- a/jitcraft/SemanticAnalysis.cpp Mon Jun 25 21:20:01 2012 -0700
10.2 +++ b/jitcraft/SemanticAnalysis.cpp Tue Jun 26 00:35:15 2012 -0700
10.3 @@ -20,6 +20,75 @@
10.4
10.5 using namespace jc;
10.6
10.7 +static inline bool
10.8 +IsPrimitiveType(Type *type, PrimitiveType primitive)
10.9 +{
10.10 + if (!type)
10.11 + return false;
10.12 +
10.13 + if (!type->isPrimitive())
10.14 + return false;
10.15 +
10.16 + return primitive == type->primitive();
10.17 +}
10.18 +
10.19 +static inline bool
10.20 +EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
10.21 + BoxedPrimitive *out)
10.22 +{
10.23 + switch (kind) {
10.24 + case TOK_PLUS:
10.25 + *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
10.26 + return true;
10.27 +
10.28 + case TOK_SHL:
10.29 + *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
10.30 + return true;
10.31 + }
10.32 +
10.33 + return true;
10.34 +}
10.35 +
10.36 +static bool
10.37 +EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
10.38 +{
10.39 + switch (expression->kind()) {
10.40 + case AstNode::kBinaryExpression:
10.41 + {
10.42 + BoxedPrimitive left;
10.43 + BoxedPrimitive right;
10.44 + BinaryExpression *b = expression->toBinaryExpression();
10.45 + if (!EvaluateForConstant(b->left(), &left) ||
10.46 + !EvaluateForConstant(b->right(), &right))
10.47 + {
10.48 + return false;
10.49 + }
10.50 + return EvaluateBinaryOperation(b->token(), left, right, out);
10.51 + }
10.52 +
10.53 + case AstNode::kNameProxy:
10.54 + {
10.55 + NameProxy *proxy = expression->toNameProxy();
10.56 + if (proxy->binding()->kind() != BoundName::CONSTANT)
10.57 + return false;
10.58 +
10.59 + NamedConstant *c = proxy->binding()->toNamedConstant();
10.60 + if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
10.61 + return false;
10.62 +
10.63 + *out = c->value();
10.64 + return true;
10.65 + }
10.66 +
10.67 + case AstNode::kIntegerLiteralExpression:
10.68 + *out = BoxedPrimitive::Int(expression->toIntegerLiteralExpression()->value());
10.69 + return true;
10.70 +
10.71 + default:
10.72 + return false;
10.73 + }
10.74 +}
10.75 +
10.76 SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
10.77 : tree_(tree)
10.78 {
10.79 @@ -42,18 +111,6 @@
10.80 name->setType(name->binding()->type());
10.81 }
10.82
10.83 -static inline bool
10.84 -IsPrimitiveType(Type *type, PrimitiveType primitive)
10.85 -{
10.86 - if (!type)
10.87 - return false;
10.88 -
10.89 - if (!type->isPrimitive())
10.90 - return false;
10.91 -
10.92 - return primitive == type->primitive();
10.93 -}
10.94 -
10.95 void
10.96 SemanticAnalysis::visit(Assignment *node)
10.97 {
10.98 @@ -198,3 +255,29 @@
10.99 }
10.100 node->setType(node->left()->type()->contained());
10.101 }
10.102 +
10.103 +void
10.104 +SemanticAnalysis::visit(EnumStatement *node)
10.105 +{
10.106 + Type *type = Type::NewPrimitive(NULL);
10.107 + if (!type)
10.108 + return;
10.109 +
10.110 + int value = 0;
10.111 + for (size_t i = 0; i < node->entries()->size(); i++) {
10.112 + EnumStatement::Entry &entry = node->entries()->at(i);
10.113 +
10.114 + BoxedPrimitive box = BoxedPrimitive::Int(value);
10.115 + if (entry.expr) {
10.116 + entry.expr->accept(this);
10.117 + if (!EvaluateForConstant(entry.expr, &box))
10.118 + fprintf(stderr, "expected constant expression\n");
10.119 +
10.120 + assert(box.type() == PrimitiveType_Int32);
10.121 + value = box.toInt();
10.122 + }
10.123 +
10.124 + entry.name->set(type, box);
10.125 + value++;
10.126 + }
10.127 +}
11.1 --- a/jitcraft/SemanticAnalysis.h Mon Jun 25 21:20:01 2012 -0700
11.2 +++ b/jitcraft/SemanticAnalysis.h Tue Jun 26 00:35:15 2012 -0700
11.3 @@ -53,6 +53,7 @@
11.4 void visit(CallExpression *node);
11.5 void visit(IfStatement *node);
11.6 void visit(IndexExpression *node);
11.7 + void visit(EnumStatement *node);
11.8 };
11.9
11.10 } // namespace jc
12.1 --- a/jitcraft/Token.h Mon Jun 25 21:20:01 2012 -0700
12.2 +++ b/jitcraft/Token.h Tue Jun 26 00:35:15 2012 -0700
12.3 @@ -29,10 +29,12 @@
12.4 _(INTEGER_LITERAL, "<integer>") \
12.5 _(IF, "<if>") \
12.6 _(ELSE, "<else>") \
12.7 + _(ENUM, "<enum>") \
12.8 _(PLUS, "+") \
12.9 _(MINUS, "-") \
12.10 _(STAR, "*") \
12.11 _(SLASH, "/") \
12.12 + _(SHL, "<<") \
12.13 _(ASSIGN, "=") \
12.14 _(SEMICOLON, ";") \
12.15 _(LBRACE, "{") \
12.16 @@ -41,6 +43,9 @@
12.17 _(RPAREN, ")") \
12.18 _(LBRACKET, "[") \
12.19 _(RBRACKET, "]") \
12.20 + _(ASSIGN_ADD, "+=") \
12.21 + _(ASSIGN_MUL, "*=") \
12.22 + _(ASSIGN_SHL, "<<=") \
12.23 _(EQUALS, "==") \
12.24 _(NOTEQUALS, "!=") \
12.25 _(LT, "<") \
13.1 --- a/jitcraft/Types.h Mon Jun 25 21:20:01 2012 -0700
13.2 +++ b/jitcraft/Types.h Tue Jun 26 00:35:15 2012 -0700
13.3 @@ -104,6 +104,30 @@
13.4 unsigned levels_;
13.5 };
13.6
13.7 +class BoxedPrimitive
13.8 +{
13.9 + PrimitiveType type_;
13.10 + union {
13.11 + int i_;
13.12 + };
13.13 +
13.14 + public:
13.15 + static BoxedPrimitive Int(int i) {
13.16 + BoxedPrimitive b;
13.17 + b.type_ = PrimitiveType_Int32;
13.18 + b.i_ = i;
13.19 + return b;
13.20 + }
13.21 +
13.22 + PrimitiveType type() const {
13.23 + return type_;
13.24 + }
13.25 + int toInt() const {
13.26 + assert(type() == PrimitiveType_Int32);
13.27 + return i_;
13.28 + }
13.29 +};
13.30 +
13.31 }
13.32
13.33 #endif // _include_jc_types_h_