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++) {