jitcraft/SemanticAnalysis.cpp
changeset 21 af5d8e985502
parent 20 e020a14e21be
child 22 765ab1b672a3
     1.1 --- a/jitcraft/SemanticAnalysis.cpp	Sun Jul 01 11:25:36 2012 -0700
     1.2 +++ b/jitcraft/SemanticAnalysis.cpp	Sun Jul 01 14:52:57 2012 -0700
     1.3 @@ -120,10 +120,15 @@
     1.4  SemanticAnalysis::visitForLoad(Expression *expression)
     1.5  {
     1.6      expression->accept(this);
     1.7 -    if (expression->type()) {
     1.8 -        // :TODO: use Local
     1.9 -        Type *type = expression->type();
    1.10 -        if (type->isArray() || type->isReference())
    1.11 +    if (!expression->type())
    1.12 +        return NULL;
    1.13 +
    1.14 +    // :TODO: use Local
    1.15 +    Type *type = expression->type();
    1.16 +    if (type->isReference()) {
    1.17 +        expression->setType(type->contained());
    1.18 +    } else if (expression->isIndexExpression()) {
    1.19 +        if (type->isArray())
    1.20              expression->setType(type->contained());
    1.21      }
    1.22      return expression->type();
    1.23 @@ -151,6 +156,39 @@
    1.24      return false;
    1.25  }
    1.26  
    1.27 +static inline bool
    1.28 +TypeCheckAssignment(Type *left, Type *right)
    1.29 +{
    1.30 +    if (!left || !right)
    1.31 +        return false;
    1.32 +
    1.33 +    if (left->isPrimitive()) {
    1.34 +        if (!right->isPrimitive())
    1.35 +            return false;
    1.36 +        return left->primitive() == right->primitive();
    1.37 +    }
    1.38 +
    1.39 +    if (left->isArray() != right->isArray())
    1.40 +        return false;
    1.41 +
    1.42 +    if (left->levels() != 1 || right->levels() != 1)
    1.43 +        return false;
    1.44 +
    1.45 +    if (left->elements() == -1 || right->elements() == -1)
    1.46 +        return false;
    1.47 +
    1.48 +    if (!TypeCheckAssignment(left->contained(), right->contained()))
    1.49 +        return false;
    1.50 +
    1.51 +    if (left->elements() != right->elements()) {
    1.52 +        if (left->isCharArray() && (left->elements() >= right->elements()))
    1.53 +            return true;
    1.54 +        return false;
    1.55 +    }
    1.56 +
    1.57 +    return false;
    1.58 +}
    1.59 +
    1.60  void
    1.61  SemanticAnalysis::visit(Assignment *node)
    1.62  {
    1.63 @@ -167,13 +205,16 @@
    1.64          }
    1.65  
    1.66          Variable *var = proxy->binding()->toVariable();
    1.67 +        if (!var->type())
    1.68 +            return;
    1.69 +
    1.70          if  (var->type()->isReference())
    1.71              node->setType(var->type()->contained());
    1.72          else
    1.73              node->setType(var->type());
    1.74      }
    1.75  
    1.76 -    assert(TypeCheck(node->type(), node->expression()->type()));
    1.77 +    assert(TypeCheckAssignment(node->type(), node->expression()->type()));
    1.78  }
    1.79  
    1.80  
    1.81 @@ -260,11 +301,24 @@
    1.82          return;
    1.83  
    1.84      if (node->postDimensions()) {
    1.85 +        Type *init = NULL;
    1.86 +        if (node->initialization()) {
    1.87 +            node->initialization()->accept(this);
    1.88 +            if ((init = node->initialization()->type()) == NULL)
    1.89 +                return;
    1.90 +        }
    1.91 +
    1.92          if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
    1.93              error();
    1.94              return;
    1.95          }
    1.96  
    1.97 +        // If we have an initializer, make sure it's the same type.
    1.98 +        if (init) {
    1.99 +            assert(init->levels() == node->postDimensions()->size());
   1.100 +        }
   1.101 +
   1.102 +        Type *check = init;
   1.103          for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
   1.104              Expression *expr = node->postDimensions()->at(i);
   1.105              visitForLoad(expr);
   1.106 @@ -285,9 +339,28 @@
   1.107                      error();
   1.108                      return;
   1.109                  }
   1.110 +            } else {
   1.111 +                assert(false);
   1.112              }
   1.113  
   1.114              type = ZONE()->types()->unsafeArray(type, size);
   1.115 +
   1.116 +            if (check) {
   1.117 +                assert(check->elements() != -1);
   1.118 +                assert(size != -1);
   1.119 +                    
   1.120 +                // If we're assigning a string, we're allowed to pad with
   1.121 +                // zeroes.
   1.122 +                if (check->isCharArray()) {
   1.123 +                    assert(type->isCharArray());
   1.124 +                    assert(type->elements() >= check->elements());
   1.125 +                } else {
   1.126 +                    assert(false);
   1.127 +                }
   1.128 +            }
   1.129 +
   1.130 +            if (check)
   1.131 +                check = check->contained();
   1.132          }
   1.133  
   1.134          // Right now, any array is allowed on the LIFO heap. In case the
   1.135 @@ -299,6 +372,10 @@
   1.136              Type *right = visitForLoad(node->initialization());
   1.137              assert(TypeCheck(type, right));
   1.138          }
   1.139 +        if (type->primitive() == PrimitiveType_Char) {
   1.140 +            assert(false);
   1.141 +            return;
   1.142 +        }
   1.143      }
   1.144  
   1.145      node->variable()->setType(type);
   1.146 @@ -477,6 +554,20 @@
   1.147  }
   1.148  
   1.149  void
   1.150 +SemanticAnalysis::visit(StringLiteral *node)
   1.151 +{
   1.152 +    Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Char);
   1.153 +    if (!type)
   1.154 +        return;
   1.155 +
   1.156 +    type = Type::NewArray(ZONE(), type, node->string()->length() + 1, true);
   1.157 +    if (!type)
   1.158 +        return;
   1.159 +
   1.160 +    node->setType(type);
   1.161 +}
   1.162 +
   1.163 +void
   1.164  SemanticAnalysis::visit(FloatLiteral *node)
   1.165  {
   1.166      Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);