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 +}