Added support for enums.
authorDavid Anderson <dvander@alliedmods.net>
Tue Jun 26 00:35:15 2012 -0700 (2012-06-26)
changeset 246fc53b8fd2f
parent 1 27f12e2fc369
child 3 f43e399ab622
Added support for enums.
jitcraft/AST.h
jitcraft/BytecodeCompiler.cpp
jitcraft/BytecodeCompiler.h
jitcraft/NameBinding.h
jitcraft/Parser.cpp
jitcraft/Parser.h
jitcraft/Scanner.cpp
jitcraft/Scopes.cpp
jitcraft/Scopes.h
jitcraft/SemanticAnalysis.cpp
jitcraft/SemanticAnalysis.h
jitcraft/Token.h
jitcraft/Types.h
     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_