src/SemanticAnalysis.cpp
changeset 145 e9d804821c48
parent 144 a8735148dcf0
child 146 dc7d3b7a918c
     1.1 --- a/src/SemanticAnalysis.cpp	Mon Jul 30 22:30:38 2012 -0700
     1.2 +++ b/src/SemanticAnalysis.cpp	Wed Aug 01 22:32:59 2012 -0700
     1.3 @@ -143,6 +143,22 @@
     1.4              FunctionStatement *funstmt = statement->toFunctionStatement();
     1.5              if (!preanalyze(funstmt))
     1.6                  return false;
     1.7 +        } else if (statement->isEnumStatement()) {
     1.8 +            EnumStatement *enumstmt = statement->toEnumStatement();
     1.9 +
    1.10 +            // We pre-fill global enum types, since they may occur in function
    1.11 +            // signatures. This should probably be somewhere else...
    1.12 +            Local<String> name(zone_, enumstmt->name());
    1.13 +            Local<Type> type(zone_);
    1.14 +            if (name)
    1.15 +                type = zone_->types()->newEnum(name);
    1.16 +            else
    1.17 +                type = zone_->types()->getPrimitive(PrimitiveType_Int32);
    1.18 +
    1.19 +            if (!type)
    1.20 +                return false;
    1.21 +
    1.22 +            enumstmt->decl()->setType(type);
    1.23          }
    1.24      }
    1.25  
    1.26 @@ -205,6 +221,27 @@
    1.27      return true;
    1.28  }
    1.29  
    1.30 +Type *
    1.31 +SemanticAnalysis::bindType(const SourcePosition &pos, BoundName *name)
    1.32 +{
    1.33 +    if (!name)
    1.34 +        return zone_->types()->getPrimitive(PrimitiveType_Int32);
    1.35 +
    1.36 +    if (name->kind() == BoundName::UNBOUND) {
    1.37 +        cc_.reportError(pos, Message_TypeNotFound, name->name()->chars());
    1.38 +        return NULL;
    1.39 +    }
    1.40 +
    1.41 +    if (name->kind() != BoundName::TYPE) {
    1.42 +        cc_.reportError(pos, Message_IdentifierIsNotAType, name->name()->chars());
    1.43 +        return NULL;
    1.44 +    }
    1.45 +
    1.46 +    if (!name->type())
    1.47 +        return NULL;
    1.48 +
    1.49 +    return name->type();
    1.50 +}
    1.51  
    1.52  Type *
    1.53  SemanticAnalysis::visitAndApplyType(Expression *expression)
    1.54 @@ -237,8 +274,8 @@
    1.55  }
    1.56  
    1.57  // :TODO: this leaks an interior pointer.
    1.58 -static inline const char *
    1.59 -GetTypeName(Type *type)
    1.60 +const char *
    1.61 +ke::GetTypeName(Type *type)
    1.62  {
    1.63      if (type->isArray())
    1.64          return "array";
    1.65 @@ -246,11 +283,22 @@
    1.66          return "function";
    1.67      if (type->isVoid())
    1.68          return "void";
    1.69 +    if (type->isEnum())
    1.70 +        return type->name()->chars();
    1.71      if (type->isReference())
    1.72          type = type->contained();
    1.73 -    if (type->tag())
    1.74 -        return type->tag()->chars();
    1.75 -    return "int";
    1.76 +    switch (type->primitive()) {
    1.77 +      case PrimitiveType_Bool:
    1.78 +        return "bool";
    1.79 +      case PrimitiveType_Char:
    1.80 +        return "String";
    1.81 +      case PrimitiveType_Int32:
    1.82 +        return "int";
    1.83 +      case PrimitiveType_Float:
    1.84 +        return "float";
    1.85 +      default:
    1.86 +        return "<unknown>";
    1.87 +    }
    1.88  }
    1.89  
    1.90  void
    1.91 @@ -282,7 +330,7 @@
    1.92          if (left->isFloat() || right->isFloat()) {
    1.93              Type *floatType = left->isFloat() ? left : right;
    1.94              Type *other = left->isFloat() ? right : left;
    1.95 -            if (other->isFloat() || (other->isInt32() && !other->tag()))
    1.96 +            if (other->isFloat() || other->isInt32())
    1.97                  return floatType;
    1.98          }
    1.99      }
   1.100 @@ -290,22 +338,20 @@
   1.101      if (token == TOK_OR || token == TOK_AND) {
   1.102          if (!canTest(node, left) || !canTest(node, right))
   1.103              return NULL;
   1.104 -        return zone_->types()->getPrimitive(PrimitiveType_Int32);
   1.105 +        return zone_->types()->getPrimitive(PrimitiveType_Bool);
   1.106      }
   1.107  
   1.108      if (token >= TOK_EQUALS && token <= TOK_GE) {
   1.109 -        if ((left->isFloat() || (left->isInt32() && !left->tag())) &&
   1.110 -            (right->isFloat() || (right->isInt32() && !right->tag())))
   1.111 +        if ((left->isFloat() || left->isInt32()) &&
   1.112 +            (right->isFloat() || right->isInt32()))
   1.113          {
   1.114 -            return zone_->types()->getPrimitive(PrimitiveType_Int32);
   1.115 +            return zone_->types()->getPrimitive(PrimitiveType_Bool);
   1.116          }
   1.117          binaryTypeError(node, token, left, right);
   1.118          return NULL;
   1.119      }
   1.120  
   1.121 -    if ((!left->isInt32() || left->tag()) ||
   1.122 -        (!right->isInt32() || right->tag()))
   1.123 -    {
   1.124 +    if (!left->isInt32() || !right->isInt32()) {
   1.125          binaryTypeError(node, token, left, right);
   1.126          return NULL;
   1.127      }
   1.128 @@ -316,7 +362,7 @@
   1.129  bool
   1.130  SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
   1.131  {
   1.132 -    if (type->isArray() || (type->isInt32() && type->tag())) {
   1.133 +    if (!type->isPrimitive() && !type->isEnum()) {
   1.134          cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
   1.135          return false;
   1.136      }
   1.137 @@ -429,7 +475,7 @@
   1.138  
   1.139      assert(!type->isReference());
   1.140  
   1.141 -    if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
   1.142 +    if (!type->isInt32() && !type->isFloat()) {
   1.143          unaryTypeError(node, node->token(), type);
   1.144          return;
   1.145      }
   1.146 @@ -456,7 +502,7 @@
   1.147          break;
   1.148  
   1.149        case TOK_MINUS:
   1.150 -        if (!type->isFloat() && (!type->isInt32() || type->tag())) {
   1.151 +        if (!type->isFloat() && !type->isInt32()) {
   1.152              unaryTypeError(node, node->token(), type);
   1.153              return;
   1.154          }
   1.155 @@ -465,13 +511,12 @@
   1.156  
   1.157        case TOK_LABEL:
   1.158        {
   1.159 -        Local<String> tag(zone_, node->tag());
   1.160 -        Local<Type> to(zone_, zone_->types()->getPrimitiveForTag(tag));
   1.161 +        Local<Type> to(zone_, bindType(node->pos(), node->type()));
   1.162          if (!to)
   1.163              return;
   1.164  
   1.165 -        if ((!type->isFloat() && !type->isInt32()) ||
   1.166 -            (!to->isFloat() && !to->isInt32()))
   1.167 +        if ((!type->isFloat() && !type->isInt32OrEnum()) ||
   1.168 +            (!to->isFloat() && !to->isInt32OrEnum()))
   1.169          {
   1.170              unaryTypeError(node, node->token(), type);
   1.171              return;
   1.172 @@ -483,7 +528,7 @@
   1.173  
   1.174        default:
   1.175          assert(node->token() == TOK_TILDE);
   1.176 -        if (!type->isInt32() || type->tag()) {
   1.177 +        if (!type->isInt32()) {
   1.178              unaryTypeError(node, node->token(), type);
   1.179              return;
   1.180          }
   1.181 @@ -627,11 +672,20 @@
   1.182          scope_ = scope_->enclosing();
   1.183  }
   1.184  
   1.185 +static inline bool
   1.186 +IsScalarString(Type *type)
   1.187 +{
   1.188 +    if (type->isPrimitive() && type->primitive() == PrimitiveType_Char)
   1.189 +        return true;
   1.190 +    if (type->isReference())
   1.191 +        return IsScalarString(type->contained());
   1.192 +    return false;
   1.193 +}
   1.194 +
   1.195  void
   1.196  SemanticAnalysis::visit(VariableDeclaration *node)
   1.197  {
   1.198 -    Local<String> tag(zone_, node->tag());
   1.199 -    Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   1.200 +    Local<Type> type(zone_, bindType(node->pos(), node->type()));
   1.201      if (!type)
   1.202          return;
   1.203  
   1.204 @@ -778,8 +832,7 @@
   1.205      for (size_t i = 0; i < node->parameters()->length(); i++) {
   1.206          Parameter *parameter = node->parameters()->at(i);
   1.207          
   1.208 -        Local<String> tag(zone_, parameter->tag());
   1.209 -        Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   1.210 +        Local<Type> type(zone_, bindType(parameter->variable()->pos(), parameter->type()));
   1.211          if (!type)
   1.212              return false;
   1.213  
   1.214 @@ -823,9 +876,7 @@
   1.215              }
   1.216          }
   1.217  
   1.218 -        if ((type->isPrimitive() && type->primitive() == PrimitiveType_Char) ||
   1.219 -            (type->isReference() && type->contained()->primitive() == PrimitiveType_Char))
   1.220 -        {
   1.221 +        if (IsScalarString(type)) {
   1.222              cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   1.223              return false;
   1.224          }
   1.225 @@ -835,11 +886,11 @@
   1.226      }
   1.227  
   1.228      Local<Type> returnType(zone_);
   1.229 -    if (node->returnTag()) {
   1.230 -        Local<String> tag(zone_, node->returnTag());
   1.231 -        returnType = zone_->types()->getPrimitiveForTag(tag);
   1.232 -    } else if (node->hasExplicitReturn() || node->fun()->isNative()) {
   1.233 -        returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
   1.234 +    if (node->returnType() ||
   1.235 +        node->hasExplicitReturn() ||
   1.236 +        node->fun()->isNative())
   1.237 +    {
   1.238 +        returnType = bindType(node->pos(), node->returnType());
   1.239      } else {
   1.240          returnType = zone_->types()->getVoid();
   1.241      }
   1.242 @@ -893,6 +944,14 @@
   1.243      function_ = NULL;
   1.244  }
   1.245  
   1.246 +void
   1.247 +SemanticAnalysis::typeMismatch(AstNode *node, Handle<Type> actual, Handle<Type> given)
   1.248 +{
   1.249 +    cc_.reportError(node->pos(),Message_TypeMismatch,
   1.250 +                    GetTypeName(actual),
   1.251 +                    GetTypeName(given));
   1.252 +}
   1.253 +
   1.254  bool
   1.255  SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
   1.256  {
   1.257 @@ -940,15 +999,7 @@
   1.258          actual = actual->contained();
   1.259      }
   1.260  
   1.261 -    if (given->primitive() != actual->primitive()) {
   1.262 -        // :TODO: leaks an interior pointer.
   1.263 -        const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   1.264 -        const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   1.265 -        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   1.266 -        return false;
   1.267 -    }
   1.268 -
   1.269 -    return true;
   1.270 +    return typeCheckAssignment(node, given, actual, forAssign);
   1.271  }
   1.272  
   1.273  bool
   1.274 @@ -971,16 +1022,21 @@
   1.275      if (actual->isReference())
   1.276          actual = actual->contained();
   1.277  
   1.278 -    if (!given->isPrimitive() || !actual->isPrimitive()) {
   1.279 -        cc_.reportError(node->pos(), Message_UnsupportedType);
   1.280 +    if (actual->isEnum()) {
   1.281 +        if (!given->isEnum() || actual != given) {
   1.282 +            typeMismatch(node, actual, given);
   1.283 +            return false;
   1.284 +        }
   1.285 +        return true;
   1.286 +    }
   1.287 +
   1.288 +    if (given->isEnum() || given->isFunction()) {
   1.289 +        typeMismatch(node, actual, given);
   1.290          return false;
   1.291      }
   1.292 -    
   1.293 +
   1.294      if (given->primitive() != actual->primitive()) {
   1.295 -        // :TODO: leaks an interior pointer
   1.296 -        const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   1.297 -        const char *actualTag = actual->tag() ? actual->tag()->chars() : "_";
   1.298 -        cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   1.299 +        typeMismatch(node, actual, given);
   1.300          return false;
   1.301      }
   1.302  
   1.303 @@ -1112,7 +1168,7 @@
   1.304      if (!left || !right)
   1.305          return;
   1.306  
   1.307 -    if (!right->isInt32()) {
   1.308 +    if (!right->isInt32() && !right->isEnum()) {
   1.309          cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
   1.310          return;
   1.311      }
   1.312 @@ -1126,20 +1182,9 @@
   1.313  void
   1.314  SemanticAnalysis::visit(EnumStatement *node)
   1.315  {
   1.316 -    // Forbid the blessed types.
   1.317 -    Local<String> tag(zone_, node->name());
   1.318 -    if (!strcmp(tag->chars(), "Float") ||
   1.319 -        !strcmp(tag->chars(), "String") ||
   1.320 -        !strcmp(tag->chars(), "any") ||
   1.321 -        !strcmp(tag->chars(), "bool"))
   1.322 -    {
   1.323 -        cc_.reportError(node->pos(), Message_InvalidEnumName);
   1.324 -        return;
   1.325 -    }
   1.326 +    Local<Type> type(zone_, node->decl()->type());
   1.327  
   1.328 -    Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   1.329 -    if (!type)
   1.330 -        return;
   1.331 +    assert(type);
   1.332  
   1.333      int value = 0;
   1.334      for (size_t i = 0; i < node->entries()->length(); i++) {