jitcraft/SemanticAnalysis.cpp
changeset 2 46fc53b8fd2f
parent 0 c455ebb9a5dc
child 3 f43e399ab622
     1.1 --- a/jitcraft/SemanticAnalysis.cpp	Mon Jun 25 21:20:01 2012 -0700
     1.2 +++ b/jitcraft/SemanticAnalysis.cpp	Tue Jun 26 00:35:15 2012 -0700
     1.3 @@ -20,6 +20,75 @@
     1.4  
     1.5  using namespace jc;
     1.6  
     1.7 +static inline bool
     1.8 +IsPrimitiveType(Type *type, PrimitiveType primitive)
     1.9 +{
    1.10 +    if (!type)
    1.11 +        return false;
    1.12 +
    1.13 +    if (!type->isPrimitive())
    1.14 +        return false;
    1.15 +
    1.16 +    return primitive == type->primitive();
    1.17 +}
    1.18 +
    1.19 +static inline bool
    1.20 +EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
    1.21 +                        BoxedPrimitive *out)
    1.22 +{
    1.23 +    switch (kind) {
    1.24 +      case TOK_PLUS:
    1.25 +        *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
    1.26 +        return true;
    1.27 +
    1.28 +      case TOK_SHL:
    1.29 +        *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
    1.30 +        return true;
    1.31 +    }
    1.32 +
    1.33 +    return true;
    1.34 +}
    1.35 +
    1.36 +static bool
    1.37 +EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
    1.38 +{
    1.39 +    switch (expression->kind()) {
    1.40 +      case AstNode::kBinaryExpression:
    1.41 +      {
    1.42 +        BoxedPrimitive left;
    1.43 +        BoxedPrimitive right;
    1.44 +        BinaryExpression *b = expression->toBinaryExpression();
    1.45 +        if (!EvaluateForConstant(b->left(), &left) ||
    1.46 +            !EvaluateForConstant(b->right(), &right))
    1.47 +        {
    1.48 +            return false;
    1.49 +        }
    1.50 +        return EvaluateBinaryOperation(b->token(), left, right, out);
    1.51 +      }
    1.52 +
    1.53 +      case AstNode::kNameProxy:
    1.54 +      {
    1.55 +        NameProxy *proxy = expression->toNameProxy();
    1.56 +        if (proxy->binding()->kind() != BoundName::CONSTANT)
    1.57 +            return false;
    1.58 +
    1.59 +        NamedConstant *c = proxy->binding()->toNamedConstant();
    1.60 +        if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
    1.61 +            return false;
    1.62 +
    1.63 +        *out = c->value();
    1.64 +        return true;
    1.65 +      }
    1.66 +
    1.67 +      case AstNode::kIntegerLiteralExpression:
    1.68 +        *out = BoxedPrimitive::Int(expression->toIntegerLiteralExpression()->value());
    1.69 +        return true;
    1.70 +
    1.71 +      default:
    1.72 +        return false;
    1.73 +    }
    1.74 +}
    1.75 +
    1.76  SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
    1.77    : tree_(tree)
    1.78  {
    1.79 @@ -42,18 +111,6 @@
    1.80      name->setType(name->binding()->type());
    1.81  }
    1.82  
    1.83 -static inline bool
    1.84 -IsPrimitiveType(Type *type, PrimitiveType primitive)
    1.85 -{
    1.86 -    if (!type)
    1.87 -        return false;
    1.88 -
    1.89 -    if (!type->isPrimitive())
    1.90 -        return false;
    1.91 -
    1.92 -    return primitive == type->primitive();
    1.93 -}
    1.94 -
    1.95  void
    1.96  SemanticAnalysis::visit(Assignment *node)
    1.97  {
    1.98 @@ -198,3 +255,29 @@
    1.99      }
   1.100      node->setType(node->left()->type()->contained());
   1.101  }
   1.102 +
   1.103 +void
   1.104 +SemanticAnalysis::visit(EnumStatement *node)
   1.105 +{
   1.106 +    Type *type = Type::NewPrimitive(NULL);
   1.107 +    if (!type)
   1.108 +        return;
   1.109 +
   1.110 +    int value = 0;
   1.111 +    for (size_t i = 0; i < node->entries()->size(); i++) {
   1.112 +        EnumStatement::Entry &entry = node->entries()->at(i);
   1.113 +
   1.114 +        BoxedPrimitive box = BoxedPrimitive::Int(value);
   1.115 +        if (entry.expr) {
   1.116 +            entry.expr->accept(this);
   1.117 +            if (!EvaluateForConstant(entry.expr, &box))
   1.118 +                fprintf(stderr, "expected constant expression\n");
   1.119 +
   1.120 +            assert(box.type() == PrimitiveType_Int32);
   1.121 +            value = box.toInt();
   1.122 +        }
   1.123 +
   1.124 +        entry.name->set(type, box);
   1.125 +        value++;
   1.126 +    }
   1.127 +}