Introduced type semantics, completely replacing tag semantics.
Introduced type semantics, completely replacing tag semantics.
1.1 --- a/src/API.cpp Mon Jul 30 22:30:38 2012 -0700
1.2 +++ b/src/API.cpp Wed Aug 01 22:32:59 2012 -0700
1.3 @@ -347,23 +347,6 @@
1.4 native->bind(function);
1.5 }
1.6
1.7 -// :TODO: this leaks an interior pointer.
1.8 -static const char *
1.9 -GetTypeName(Type *type)
1.10 -{
1.11 - if (type->isArray())
1.12 - return "array";
1.13 - if (type->isFunction())
1.14 - return "function";
1.15 - if (type->isVoid())
1.16 - return "void";
1.17 - if (type->isReference())
1.18 - type = type->contained();
1.19 - if (type->tag())
1.20 - return type->tag()->chars();
1.21 - return "int";
1.22 -}
1.23 -
1.24 static inline const char *
1.25 GetInvokeTypeName(Ke::Parameter::Type type)
1.26 {
1.27 @@ -392,7 +375,7 @@
1.28 case Ke::Parameter::Array:
1.29 return type->isArray() &&
1.30 type->levels() == 1 &&
1.31 - type->contained()->isPrimitive() &&
1.32 + (type->contained()->isPrimitive() || type->contained()->isEnum()) &&
1.33 (type->contained()->primitive() != PrimitiveType_Char);
1.34 case Ke::Parameter::CharArray:
1.35 return type->isCharArray();
1.36 @@ -401,9 +384,9 @@
1.37 case Ke::Parameter::FloatRef:
1.38 return type->isReference() && type->contained()->isFloat();
1.39 case Ke::Parameter::Int:
1.40 - return type->isInt32();
1.41 + return type->isInt32() || type->isEnum();
1.42 case Ke::Parameter::IntRef:
1.43 - return type->isReference() && type->contained()->isInt32();
1.44 + return type->isReference() && (type->contained()->isInt32() || type->contained()->isEnum());
1.45 default:
1.46 return false;
1.47 }
1.48 @@ -428,7 +411,10 @@
1.49
1.50 // Functions can only return tagged cells, for ISPE1-compatible Invoke().
1.51 ke::Local<ke::Type> returnType(ke::ZONE(), fun->type()->returnType());
1.52 - if (!returnType->isPrimitive() && !returnType->isVoid()) {
1.53 + if (!returnType->isPrimitive() &&
1.54 + !returnType->isEnum() &&
1.55 + !returnType->isVoid())
1.56 + {
1.57 ke::ZONE()->reportError(Message_CannotInvokeReturnType, GetTypeName(returnType));
1.58 return false;
1.59 }
2.1 --- a/src/AST.h Mon Jul 30 22:30:38 2012 -0700
2.2 +++ b/src/AST.h Wed Aug 01 22:32:59 2012 -0700
2.3 @@ -98,36 +98,6 @@
2.4 #undef _
2.5 };
2.6
2.7 -class NameLocation
2.8 -{
2.9 - public:
2.10 - enum Kind {
2.11 - LOCAL
2.12 - };
2.13 -
2.14 - static NameLocation Local(VariableDeclaration *decl) {
2.15 - NameLocation loc;
2.16 - loc.kind_ = LOCAL;
2.17 - loc.u_.decl = decl;
2.18 - return loc;
2.19 - }
2.20 -
2.21 - Kind kind() const {
2.22 - return kind_;
2.23 - }
2.24 -
2.25 - VariableDeclaration *local() const {
2.26 - assert(kind() == LOCAL);
2.27 - return u_.decl;
2.28 - }
2.29 -
2.30 - private:
2.31 - Kind kind_;
2.32 - union {
2.33 - VariableDeclaration *decl;
2.34 - } u_;
2.35 -};
2.36 -
2.37 class Statement : public AstNode
2.38 {
2.39 public:
2.40 @@ -164,23 +134,24 @@
2.41 Variable *variable_;
2.42 Expression *initialization_;
2.43 ExpressionList *postDimensions_;
2.44 - ScopedRoot<String> tag_;
2.45 + BoundName *type_;
2.46 TokenKind declarator_;
2.47
2.48 public:
2.49 VariableDeclaration(const SourcePosition &pos, TokenKind declarator, Variable *var,
2.50 - Handle<String> tag, ExpressionList *postDimensions,
2.51 + BoundName *type, ExpressionList *postDimensions,
2.52 Expression *initialization)
2.53 : Statement(pos),
2.54 variable_(var),
2.55 initialization_(initialization),
2.56 postDimensions_(postDimensions),
2.57 - tag_(tag)
2.58 + type_(type),
2.59 + declarator_(declarator)
2.60 {
2.61 }
2.62
2.63 - String *tag() const {
2.64 - return tag_;
2.65 + BoundName *type() const {
2.66 + return type_;
2.67 }
2.68 Kind kind() const {
2.69 return kVariableDeclaration;
2.70 @@ -205,17 +176,17 @@
2.71 class Parameter : public PoolObject
2.72 {
2.73 Variable *variable_;
2.74 - ScopedRoot<String> tag_;
2.75 + BoundName *type_;
2.76 bool reference_;
2.77 bool const_;
2.78 ExpressionList *dimensions_;
2.79 Expression *initializer_;
2.80
2.81 public:
2.82 - Parameter(Variable *var, Handle<String> tag, bool reference, bool isConst,
2.83 + Parameter(Variable *var, BoundName *type, bool reference, bool isConst,
2.84 ExpressionList *dimensions, Expression *initializer)
2.85 : variable_(var),
2.86 - tag_(tag),
2.87 + type_(type),
2.88 reference_(reference),
2.89 const_(isConst),
2.90 dimensions_(dimensions),
2.91 @@ -223,8 +194,8 @@
2.92 {
2.93 }
2.94
2.95 - String *tag() const {
2.96 - return tag_;
2.97 + BoundName *type() const {
2.98 + return type_;
2.99 }
2.100 Variable *variable() const {
2.101 return variable_;
2.102 @@ -366,7 +337,7 @@
2.103 {
2.104 Expression *expression_;
2.105 TokenKind token_;
2.106 - ScopedRoot<String> tag_;
2.107 + BoundName *type_;
2.108
2.109 public:
2.110 UnaryExpression(const SourcePosition &pos, TokenKind token, Expression *expr)
2.111 @@ -377,11 +348,11 @@
2.112 }
2.113
2.114 UnaryExpression(const SourcePosition &pos, TokenKind token, Expression *expr,
2.115 - Handle<String> tag)
2.116 + BoundName *type)
2.117 : Expression(pos),
2.118 expression_(expr),
2.119 token_(token),
2.120 - tag_(tag)
2.121 + type_(type)
2.122 {
2.123 }
2.124
2.125 @@ -394,8 +365,8 @@
2.126 TokenKind token() const {
2.127 return token_;
2.128 }
2.129 - String *tag() const {
2.130 - return tag_;
2.131 + BoundName *type() const {
2.132 + return type_;
2.133 }
2.134 void accept(AstVisitor *visitor) {
2.135 visitor->visit(this);
2.136 @@ -739,18 +710,18 @@
2.137 Statement *body_;
2.138 ParameterList *parameters_;
2.139 bool explicitReturn_;
2.140 - ScopedRoot<String> tag_;
2.141 + BoundName *returnType_;
2.142
2.143 public:
2.144 FunctionStatement(const SourcePosition &pos, Scope *scope, NamedFunction *fun, Statement *body,
2.145 - ParameterList *parameters, Handle<String> returnTag, bool explicitReturn)
2.146 + ParameterList *parameters, BoundName *returnType, bool explicitReturn)
2.147 : Statement(pos),
2.148 scope_(scope),
2.149 fun_(fun),
2.150 body_(body),
2.151 parameters_(parameters),
2.152 explicitReturn_(explicitReturn),
2.153 - tag_(returnTag)
2.154 + returnType_(returnType)
2.155 {
2.156 }
2.157
2.158 @@ -775,8 +746,8 @@
2.159 bool hasExplicitReturn() const {
2.160 return explicitReturn_;
2.161 }
2.162 - String *returnTag() const {
2.163 - return tag_;
2.164 + BoundName *returnType() const {
2.165 + return returnType_;
2.166 }
2.167 };
2.168
2.169 @@ -818,6 +789,7 @@
2.170 class EnumStatement : public Statement
2.171 {
2.172 ScopedRoot<String> name_;
2.173 + NamedType *type_;
2.174
2.175 public:
2.176 struct Entry {
2.177 @@ -834,9 +806,10 @@
2.178 typedef PoolList<Entry> EntryList;
2.179
2.180 public:
2.181 - EnumStatement(const SourcePosition &pos, Handle<String> name, EntryList *entries)
2.182 + EnumStatement(const SourcePosition &pos, NamedType *type, Handle<String> name, EntryList *entries)
2.183 : Statement(pos),
2.184 name_(name),
2.185 + type_(type),
2.186 entries_(entries)
2.187 {
2.188 }
2.189 @@ -850,6 +823,9 @@
2.190 EntryList *entries() const {
2.191 return entries_;
2.192 }
2.193 + NamedType *decl() const {
2.194 + return type_;
2.195 + }
2.196 void accept(AstVisitor *visitor) {
2.197 visitor->visit(this);
2.198 }
3.1 --- a/src/BytecodeCompiler.cpp Mon Jul 30 22:30:38 2012 -0700
3.2 +++ b/src/BytecodeCompiler.cpp Wed Aug 01 22:32:59 2012 -0700
3.3 @@ -166,7 +166,7 @@
3.4
3.5 // If this argument is actually a reference, dereference it now.
3.6 if (var->type()->isReference())
3.7 - __ getref(var->type()->contained()->primitive());
3.8 + __ getref(var->type()->contained());
3.9 }
3.10 break;
3.11 }
3.12 @@ -223,7 +223,7 @@
3.13
3.14 if (var->type()->isReference()) {
3.15 __ dup();
3.16 - __ getref(var->type()->contained()->primitive());
3.17 + __ getref(var->type()->contained());
3.18 } else {
3.19 __ get(var);
3.20 }
3.21 @@ -248,7 +248,7 @@
3.22 if (node->type()->isArray())
3.23 __ getarray_o();
3.24 else
3.25 - __ getarray(node->type()->primitive());
3.26 + __ getarray(node->type());
3.27 }
3.28 }
3.29
3.30 @@ -273,7 +273,7 @@
3.31 Variable *var = proxy->binding()->toVariable();
3.32
3.33 if (var->type()->isReference())
3.34 - __ setref(var->type()->contained()->primitive());
3.35 + __ setref(var->type()->contained());
3.36 else
3.37 __ set(var);
3.38 } else {
3.39 @@ -281,7 +281,7 @@
3.40 // :TODO: get rid of the BOUNDS instruction, embed it in g/setarray*?
3.41 // We can't emit it here because the stack is slightly out of position.
3.42 // __ bounds();
3.43 - __ setarray(index->left()->type()->contained()->primitive());
3.44 + __ setarray(index->left()->type()->contained());
3.45 }
3.46 }
3.47
3.48 @@ -326,7 +326,7 @@
3.49 // Dup and fetch.
3.50 if (var->type()->isReference()) {
3.51 __ dup();
3.52 - __ getref(node->type()->primitive());
3.53 + __ getref(node->type());
3.54 if (node->postfix()) {
3.55 __ swap();
3.56 __ pick2();
3.57 @@ -347,7 +347,7 @@
3.58 assert(!node->type()->isArray());
3.59 __ bounds();
3.60 __ dup2();
3.61 - __ getarray(node->type()->primitive());
3.62 + __ getarray(node->type());
3.63
3.64 if (node->postfix()) {
3.65 // The stack looks like this now:
3.66 @@ -380,11 +380,11 @@
3.67 Variable *var = proxy->binding()->toVariable();
3.68
3.69 if (var->type()->isReference())
3.70 - __ setref(node->type()->primitive());
3.71 + __ setref(node->type());
3.72 else
3.73 __ set(var);
3.74 } else {
3.75 - __ setarray(node->type()->primitive());
3.76 + __ setarray(node->type());
3.77 }
3.78
3.79 // Perform step (8).
3.80 @@ -413,13 +413,15 @@
3.81 void
3.82 BytecodeCompiler::visit(UnaryExpression *node)
3.83 {
3.84 + Local<Type> out(zone_, ((Expression *)node)->type());
3.85 +
3.86 switch (node->token()) {
3.87 case TOK_MINUS:
3.88 {
3.89 Local<Type> type(zone_, node->expression()->type());
3.90 node->expression()->accept(this);
3.91
3.92 - if (node->type()->isFloat())
3.93 + if (out->isFloat())
3.94 __ neg_f();
3.95 else
3.96 __ neg();
3.97 @@ -431,7 +433,7 @@
3.98 Local<Type> type(zone_, node->expression()->type());
3.99 node->expression()->accept(this);
3.100
3.101 - if (node->type()->isFloat())
3.102 + if (out->isFloat())
3.103 __ not_f();
3.104 else
3.105 __ not_();
3.106 @@ -441,12 +443,11 @@
3.107 case TOK_LABEL:
3.108 {
3.109 Local<Type> from(zone_, node->expression()->type());
3.110 - Local<Type> to(zone_, node->type());
3.111
3.112 node->expression()->accept(this);
3.113 - if (!from->isFloat() && to->isFloat())
3.114 + if (!from->isFloat() && out->isFloat())
3.115 __ bits_f2i();
3.116 - else if (from->isFloat() && !to->isFloat())
3.117 + else if (from->isFloat() && !out->isFloat())
3.118 __ bits_i2f();
3.119 break;
3.120 }
3.121 @@ -501,7 +502,7 @@
3.122 if (node->type()->isArray())
3.123 __ getarray_o();
3.124 else
3.125 - __ getarray(node->type()->primitive());
3.126 + __ getarray(node->type());
3.127 }
3.128
3.129 void
4.1 --- a/src/BytecodeEmitter.h Mon Jul 30 22:30:38 2012 -0700
4.2 +++ b/src/BytecodeEmitter.h Wed Aug 01 22:32:59 2012 -0700
4.3 @@ -365,8 +365,8 @@
4.4 writeUint32(argc);
4.5 }
4.6
4.7 - void getarray(PrimitiveType type) {
4.8 - switch (type) {
4.9 + void getarray(Type *type) {
4.10 + switch (type->pod()) {
4.11 case PrimitiveType_Float:
4.12 singleByteOp(OP_GETARRAY_F);
4.13 break;
4.14 @@ -374,13 +374,13 @@
4.15 singleByteOp(OP_GETARRAY_I);
4.16 break;
4.17 default:
4.18 - assert(type == PrimitiveType_Char);
4.19 + assert(type->pod() == PrimitiveType_Char);
4.20 singleByteOp(OP_GETARRAY_C);
4.21 break;
4.22 }
4.23 }
4.24 - void setarray(PrimitiveType type) {
4.25 - switch (type) {
4.26 + void setarray(Type *type) {
4.27 + switch (type->pod()) {
4.28 case PrimitiveType_Float:
4.29 singleByteOp(OP_SETARRAY_F);
4.30 break;
4.31 @@ -388,7 +388,7 @@
4.32 singleByteOp(OP_SETARRAY_I);
4.33 break;
4.34 default:
4.35 - assert(type == PrimitiveType_Char);
4.36 + assert(type->pod() == PrimitiveType_Char);
4.37 singleByteOp(OP_SETARRAY_C);
4.38 break;
4.39 }
4.40 @@ -488,19 +488,19 @@
4.41 singleByteOp(OP_ARRAYREF_LIFO);
4.42 markOop(1);
4.43 }
4.44 - void getref(PrimitiveType type) {
4.45 - if (type == PrimitiveType_Int32) {
4.46 + void getref(Type *type) {
4.47 + if (type->pod() == PrimitiveType_Int32) {
4.48 singleByteOp(OP_GETREF_I);
4.49 } else {
4.50 - assert(type == PrimitiveType_Float);
4.51 + assert(type->pod() == PrimitiveType_Float);
4.52 singleByteOp(OP_GETREF_F);
4.53 }
4.54 }
4.55 - void setref(PrimitiveType type) {
4.56 - if (type == PrimitiveType_Int32) {
4.57 + void setref(Type *type) {
4.58 + if (type->pod() == PrimitiveType_Int32) {
4.59 singleByteOp(OP_SETREF_I);
4.60 } else {
4.61 - assert(type == PrimitiveType_Float);
4.62 + assert(type->pod() == PrimitiveType_Float);
4.63 singleByteOp(OP_SETREF_F);
4.64 }
4.65 }
5.1 --- a/src/Messages.tbl Mon Jul 30 22:30:38 2012 -0700
5.2 +++ b/src/Messages.tbl Wed Aug 01 22:32:59 2012 -0700
5.3 @@ -22,7 +22,6 @@
5.4 MSG(ArgumentCountMismatch, SyntaxError, "argument counts do not match")
5.5 MSG(CannotAssignArrayToScalar, SyntaxError, "cannot coerce an array to a scalar")
5.6 MSG(UnsupportedType, SyntaxError, "unsupported type")
5.7 -MSG(TagMismatch, SyntaxError, "tag mismatch (expected '%s', got '%s')")
5.8 MSG(ArrayDimensionsMismatch, SyntaxError, "number of array dimensions does not match")
5.9 MSG(ExpectedArray, SyntaxError, "expected array")
5.10 MSG(ArrayDimensionSizeMismatch, SyntaxError, "array dimension sizes do not match (level %d)")
5.11 @@ -62,4 +61,7 @@
5.12 MSG(IdentifierNotFound, SyntaxError, "identifier '%s' could not be found")
5.13 MSG(TypeMismatchDuringInvoke, SyntaxError, "incoming type '%s' does not match signature type '%s'")
5.14 MSG(CannotInvokeReturnType, SyntaxError, "cannot invoke function with return type '%s'")
5.15 +MSG(TypeNotFound, SyntaxError, "type '%s' could not be found")
5.16 +MSG(IdentifierIsNotAType, SyntaxError, "identifier '%s' cannot be used as a type")
5.17 +MSG(TypeMismatch, SyntaxError, "type mismatch (expected '%s', got '%s')")
5.18
6.1 --- a/src/NameBinding.cpp Mon Jul 30 22:30:38 2012 -0700
6.2 +++ b/src/NameBinding.cpp Wed Aug 01 22:32:59 2012 -0700
6.3 @@ -53,3 +53,4 @@
6.4 {
6.5 return scope()->kind() == Scope::GLOBAL;
6.6 }
6.7 +
7.1 --- a/src/NameBinding.h Mon Jul 30 22:30:38 2012 -0700
7.2 +++ b/src/NameBinding.h Wed Aug 01 22:32:59 2012 -0700
7.3 @@ -29,8 +29,9 @@
7.4 class NamedFunction;
7.5 class Scope;
7.6 class Type;
7.7 -class NamedEnum;
7.8 class NamedConstant;
7.9 +class NamedType;
7.10 +class UnboundName;
7.11 class String;
7.12
7.13 class BoundName : public PoolObject
7.14 @@ -47,8 +48,9 @@
7.15 enum Kind {
7.16 VARIABLE,
7.17 FUNCTION,
7.18 - ENUM,
7.19 - CONSTANT
7.20 + CONSTANT,
7.21 + TYPE,
7.22 + UNBOUND
7.23 };
7.24
7.25 BoundName(Scope *scope, Handle<String> name, const SourcePosition &pos);
7.26 @@ -73,6 +75,10 @@
7.27 assert(kind() == CONSTANT);
7.28 return reinterpret_cast<NamedConstant *>(this);
7.29 }
7.30 + NamedType *toNamedType() {
7.31 + assert(kind() == TYPE);
7.32 + return reinterpret_cast<NamedType *>(this);
7.33 + }
7.34 Type *type() const {
7.35 return type_;
7.36 }
7.37 @@ -145,19 +151,6 @@
7.38 }
7.39 };
7.40
7.41 -class NamedEnum : public BoundName
7.42 -{
7.43 - public:
7.44 - NamedEnum(Scope *scope, Handle<String> name, const SourcePosition &pos)
7.45 - : BoundName(scope, name, pos)
7.46 - {
7.47 - }
7.48 -
7.49 - Kind kind() const {
7.50 - return ENUM;
7.51 - }
7.52 -};
7.53 -
7.54 class NamedConstant : public BoundName
7.55 {
7.56 BoxedPrimitive value_;
7.57 @@ -185,6 +178,38 @@
7.58 }
7.59 };
7.60
7.61 +class NamedType : public BoundName
7.62 +{
7.63 + public:
7.64 + NamedType(Scope *scope, Handle<String> name, Handle<Type> type)
7.65 + : BoundName(scope, name, SourcePosition())
7.66 + {
7.67 + setType(type);
7.68 + }
7.69 +
7.70 + NamedType(Scope *scope, Handle<String> name, const SourcePosition &pos)
7.71 + : BoundName(scope, name, pos)
7.72 + {
7.73 + }
7.74 +
7.75 + Kind kind() const {
7.76 + return TYPE;
7.77 + }
7.78 +};
7.79 +
7.80 +class UnboundName : public BoundName
7.81 +{
7.82 + public:
7.83 + UnboundName(Scope *scope, Handle<String> name)
7.84 + : BoundName(scope, name, SourcePosition())
7.85 + {
7.86 + }
7.87 +
7.88 + Kind kind() const {
7.89 + return UNBOUND;
7.90 + }
7.91 +};
7.92 +
7.93 class Variable : public BoundName
7.94 {
7.95 public:
8.1 --- a/src/ObjectVisitor.h Mon Jul 30 22:30:38 2012 -0700
8.2 +++ b/src/ObjectVisitor.h Wed Aug 01 22:32:59 2012 -0700
8.3 @@ -47,7 +47,7 @@
8.4 visitField(obj, Type::offsetOfContained());
8.5 visitField(obj, Type::offsetOfReturnType());
8.6 visitField(obj, Type::offsetOfParameters());
8.7 - visitField(obj, Type::offsetOfTag());
8.8 + visitField(obj, Type::offsetOfName());
8.9 return sizeof(Type);
8.10 }
8.11
9.1 --- a/src/Opcodes.cpp Mon Jul 30 22:30:38 2012 -0700
9.2 +++ b/src/Opcodes.cpp Wed Aug 01 22:32:59 2012 -0700
9.3 @@ -248,9 +248,6 @@
9.4 {
9.5 Heap::Tenure tenure = (Heap::Tenure)pc[1];
9.6 ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc + 1)));
9.7 - fprintf(fp, "%s:", map->type()->innermost()->tag()
9.8 - ? map->type()->innermost()->tag()->chars()
9.9 - : "_");
9.10 for (; map; map = map->contained()) {
9.11 Type *type = map->type();
9.12 fprintf(fp, "[%d]", type->elements());
10.1 --- a/src/Parser.cpp Mon Jul 30 22:30:38 2012 -0700
10.2 +++ b/src/Parser.cpp Wed Aug 01 22:32:59 2012 -0700
10.3 @@ -22,6 +22,7 @@
10.4 #include "FixedArray.h"
10.5 #include "Heap.h"
10.6 #include "Strings.h"
10.7 +#include "TypeManager.h"
10.8 #include "Heap-inl.h"
10.9
10.10 using namespace ke;
10.11 @@ -38,9 +39,15 @@
10.12 }
10.13
10.14 bool
10.15 +Parser::peek(TokenKind kind)
10.16 +{
10.17 + return scanner_.peek() == kind;
10.18 +}
10.19 +
10.20 +bool
10.21 Parser::match(TokenKind kind)
10.22 {
10.23 - if (scanner_.peek() != kind)
10.24 + if (!peek(kind))
10.25 return false;
10.26 scanner_.scan();
10.27 return true;
10.28 @@ -81,6 +88,15 @@
10.29 return proxy;
10.30 }
10.31
10.32 +BoundName *
10.33 +Parser::bindType(Handle<String> name)
10.34 +{
10.35 + if (BoundName *binding = scope_->lookup(name))
10.36 + return binding;
10.37 +
10.38 + return new (pool_) UnboundName(scope_, name);
10.39 +}
10.40 +
10.41 bool
10.42 Parser::matchName(String **name, TokenKind kind)
10.43 {
10.44 @@ -284,11 +300,15 @@
10.45 if (!tag)
10.46 return NULL;
10.47
10.48 + BoundName *type = NULL;
10.49 + if (tag)
10.50 + type = bindType(tag);
10.51 +
10.52 Expression *expr = unary();
10.53 if (!expr)
10.54 return NULL;
10.55
10.56 - return new (pool_) UnaryExpression(pos, TOK_LABEL, expr, tag);
10.57 + return new (pool_) UnaryExpression(pos, TOK_LABEL, expr, type);
10.58 }
10.59
10.60 default:
10.61 @@ -653,6 +673,25 @@
10.62 return new (pool_) ForStatement(pos, declScope, decl, condition, update, body);
10.63 }
10.64
10.65 +ExpressionList *
10.66 +Parser::dimensions()
10.67 +{
10.68 + ExpressionList *postDimensions = new (pool_) ExpressionList();
10.69 + while (match(TOK_LBRACKET)) {
10.70 + Expression *dim = NULL;
10.71 + if (!match(TOK_RBRACKET)) {
10.72 + if ((dim = expression()) == NULL)
10.73 + return NULL;
10.74 + if (!expect(TOK_RBRACKET))
10.75 + return NULL;
10.76 + }
10.77 +
10.78 + if (!postDimensions->append(dim))
10.79 + return NULL;
10.80 + }
10.81 + return postDimensions;
10.82 +}
10.83 +
10.84 VariableDeclaration *
10.85 Parser::variableDeclaration(TokenKind kind)
10.86 {
10.87 @@ -660,6 +699,10 @@
10.88 if (matchName(tag.ref(), TOK_LABEL) && !tag)
10.89 return NULL;
10.90
10.91 + BoundName *type = NULL;
10.92 + if (tag)
10.93 + type = bindType(tag);
10.94 +
10.95 Local<String> name(zone_, expectName());
10.96 if (!name)
10.97 return NULL;
10.98 @@ -674,20 +717,9 @@
10.99 return NULL;
10.100
10.101 ExpressionList *postDimensions = NULL;
10.102 - if (scanner_.peek() == TOK_LBRACKET) {
10.103 - postDimensions = new (pool_) ExpressionList();
10.104 - while (match(TOK_LBRACKET)) {
10.105 - Expression *dim = NULL;
10.106 - if (!match(TOK_RBRACKET)) {
10.107 - if ((dim = expression()) == NULL)
10.108 - return NULL;
10.109 - if (!expect(TOK_RBRACKET))
10.110 - return NULL;
10.111 - }
10.112 -
10.113 - if (!postDimensions->append(dim))
10.114 - return NULL;
10.115 - }
10.116 + if (peek(TOK_LBRACKET)) {
10.117 + if ((postDimensions = dimensions()) == NULL)
10.118 + return NULL;
10.119 }
10.120
10.121 Expression *expr = NULL;
10.122 @@ -696,7 +728,7 @@
10.123 return NULL;
10.124 }
10.125
10.126 - return new (pool_) VariableDeclaration(var->pos(), kind, var, tag, postDimensions, expr);
10.127 + return new (pool_) VariableDeclaration(var->pos(), kind, var, type, postDimensions, expr);
10.128 }
10.129
10.130 Statement *
10.131 @@ -886,6 +918,7 @@
10.132 {
10.133 expect(TOK_ENUM);
10.134
10.135 + NamedType *type = NULL;
10.136 SourcePosition pos = scanner_.begin();
10.137
10.138 Local<String> name(zone_);
10.139 @@ -898,7 +931,7 @@
10.140 return NULL;
10.141 }
10.142
10.143 - if (!scope_->declareEnum(name, scanner_.begin()))
10.144 + if ((type = scope_->declareType(name, scanner_.begin())) == NULL)
10.145 return NULL;
10.146 }
10.147
10.148 @@ -936,15 +969,27 @@
10.149 if (!expect(TOK_RBRACE))
10.150 return NULL;
10.151
10.152 - return new (pool_) EnumStatement(pos, name, entries);
10.153 + return new (pool_) EnumStatement(pos, type, name, entries);
10.154 }
10.155
10.156 Statement *
10.157 Parser::function(TokenKind token)
10.158 {
10.159 Local<String> returnTag(zone_);
10.160 - if (matchName(returnTag.ref(), TOK_LABEL) && !returnTag)
10.161 - return NULL;
10.162 + if (token == TOK_LABEL) {
10.163 + returnTag = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
10.164 + if (!returnTag)
10.165 + return NULL;
10.166 +
10.167 + token = TOK_STOCK;
10.168 + } else {
10.169 + if (matchName(returnTag.ref(), TOK_LABEL) && !returnTag)
10.170 + return NULL;
10.171 + }
10.172 +
10.173 + BoundName *returnType = NULL;
10.174 + if (returnTag)
10.175 + returnType = bindType(returnTag);
10.176
10.177 Local<String> name(zone_, expectName());
10.178 if (!name)
10.179 @@ -1001,6 +1046,10 @@
10.180 if (matchName(tag.ref(), TOK_LABEL) && !tag)
10.181 return NULL;
10.182
10.183 + BoundName *type = NULL;
10.184 + if (tag)
10.185 + type = bindType(tag);
10.186 +
10.187 if (match(TOK_ELLIPSES)) {
10.188 if (isConst || ref) {
10.189 cc_.reportError(begin, Message_InvalidVarArgs);
10.190 @@ -1030,19 +1079,8 @@
10.191
10.192 // Look for dimensions.
10.193 ExpressionList *postDimensions = NULL;
10.194 - while (match(TOK_LBRACKET)) {
10.195 - if (!postDimensions)
10.196 - postDimensions = new (pool_) ExpressionList();
10.197 -
10.198 - Expression *dim = NULL;
10.199 - if (!match(TOK_RBRACKET)) {
10.200 - if ((dim = expression()) == NULL)
10.201 - return NULL;
10.202 - if (!expect(TOK_RBRACKET))
10.203 - return NULL;
10.204 - }
10.205 -
10.206 - if (!postDimensions->append(dim))
10.207 + if (peek(TOK_LBRACKET)) {
10.208 + if ((postDimensions = dimensions()) == NULL)
10.209 return NULL;
10.210 }
10.211
10.212 @@ -1052,7 +1090,7 @@
10.213 return NULL;
10.214 }
10.215
10.216 - Parameter *parameter = new (pool_) Parameter(arg, tag, ref, isConst, postDimensions,
10.217 + Parameter *parameter = new (pool_) Parameter(arg, type, ref, isConst, postDimensions,
10.218 expr);
10.219 if (!parameters->append(parameter))
10.220 return NULL;
10.221 @@ -1074,10 +1112,37 @@
10.222 }
10.223
10.224 scope_ = scope_->enclosing();
10.225 - return new (pool_) FunctionStatement(pos, scope, fun, body, parameters, returnTag,
10.226 + return new (pool_) FunctionStatement(pos, scope, fun, body, parameters, returnType,
10.227 encounteredReturn_);
10.228 }
10.229
10.230 +static inline bool
10.231 +DeclareIntrinsicType(Zone *zone, Scope *scope, const char *name, PrimitiveType type)
10.232 +{
10.233 + Local<String> tag(zone, zone->makeSymbol(name));
10.234 + if (!tag)
10.235 + return false;
10.236 +
10.237 + Local<Type> primitive(zone, zone->types()->getPrimitive(type));
10.238 + assert(primitive);
10.239 +
10.240 + return !!scope->declareType(tag, primitive);
10.241 +}
10.242 +
10.243 +bool
10.244 +Parser::setupIntrinsics()
10.245 +{
10.246 + if (!DeclareIntrinsicType(zone_, scope_, "Float", PrimitiveType_Float))
10.247 + return false;
10.248 + if (!DeclareIntrinsicType(zone_, scope_, "_", PrimitiveType_Int32))
10.249 + return false;
10.250 + if (!DeclareIntrinsicType(zone_, scope_, "bool", PrimitiveType_Bool))
10.251 + return false;
10.252 + if (!DeclareIntrinsicType(zone_, scope_, "String", PrimitiveType_Char))
10.253 + return false;
10.254 + return true;
10.255 +}
10.256 +
10.257 ParseTree *
10.258 Parser::parse()
10.259 {
10.260 @@ -1086,6 +1151,9 @@
10.261 if (!enterScope(Scope::GLOBAL))
10.262 return NULL;
10.263
10.264 + if (!setupIntrinsics())
10.265 + return NULL;
10.266 +
10.267 for (;;) {
10.268 Statement *statement = NULL;
10.269
10.270 @@ -1106,6 +1174,7 @@
10.271 case TOK_PUBLIC:
10.272 case TOK_NATIVE:
10.273 case TOK_STOCK:
10.274 + case TOK_LABEL:
10.275 {
10.276 scanner_.scan();
10.277 if ((statement = function(kind)) == NULL)
11.1 --- a/src/Parser.h Mon Jul 30 22:30:38 2012 -0700
11.2 +++ b/src/Parser.h Wed Aug 01 22:32:59 2012 -0700
11.3 @@ -39,16 +39,23 @@
11.4
11.5 private:
11.6 void redeclarationError(BoundName *name);
11.7 + bool peek(TokenKind kind);
11.8 bool match(TokenKind kind);
11.9 bool expect(TokenKind kind);
11.10 bool matchSemicolon();
11.11
11.12 Scope *enterScope(Scope::Kind kind);
11.13
11.14 +
11.15 VariableDeclaration *variableDeclaration(TokenKind kind);
11.16 bool matchName(String **name, TokenKind kind = TOK_NAME);
11.17 +
11.18 + NameProxy *bind(Handle<String> name);
11.19 + BoundName *bindType(Handle<String> string);
11.20 +
11.21 + ExpressionList *dimensions();
11.22 String *expectName();
11.23 - NameProxy *bind(Handle<String> name);
11.24 +
11.25 Expression *primitive();
11.26 Expression *call(Expression *callee);
11.27 Expression *index(Expression *left);
11.28 @@ -81,6 +88,8 @@
11.29 Statement *globalStatement();
11.30 Statement *returnStatement();
11.31
11.32 + bool setupIntrinsics();
11.33 +
11.34 public:
11.35 Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length);
11.36
12.1 --- a/src/Scopes.cpp Mon Jul 30 22:30:38 2012 -0700
12.2 +++ b/src/Scopes.cpp Wed Aug 01 22:32:59 2012 -0700
12.3 @@ -127,15 +127,6 @@
12.4 return fun;
12.5 }
12.6
12.7 -NamedEnum *
12.8 -Scope::declareEnum(Handle<String> name, const SourcePosition &pos)
12.9 -{
12.10 - NamedEnum *e = new (pool_) NamedEnum(this, name, pos);
12.11 - if (!names_.append(e))
12.12 - return NULL;
12.13 - return e;
12.14 -}
12.15 -
12.16 NamedConstant *
12.17 Scope::declareConstant(Handle<String> name, const SourcePosition &pos)
12.18 {
12.19 @@ -145,6 +136,24 @@
12.20 return constant;
12.21 }
12.22
12.23 +NamedType *
12.24 +Scope::declareType(Handle<String> name, const SourcePosition &pos)
12.25 +{
12.26 + NamedType *decl = new (pool_) NamedType(this, name, pos);
12.27 + if (!names_.append(decl))
12.28 + return NULL;
12.29 + return decl;
12.30 +}
12.31 +
12.32 +NamedType *
12.33 +Scope::declareType(Handle<String> name, Handle<Type> type)
12.34 +{
12.35 + NamedType *decl = new (pool_) NamedType(this, name, type);
12.36 + if (!names_.append(decl))
12.37 + return NULL;
12.38 + return decl;
12.39 +}
12.40 +
12.41 void
12.42 Scope::allocateGlobals()
12.43 {
13.1 --- a/src/Scopes.h Mon Jul 30 22:30:38 2012 -0700
13.2 +++ b/src/Scopes.h Wed Aug 01 22:32:59 2012 -0700
13.3 @@ -96,8 +96,9 @@
13.4 NamedFunction *declareFunction(Handle<String> name, const SourcePosition &pos, TokenKind token);
13.5 Variable *declareVariable(Handle<String> name, const SourcePosition &pos);
13.6 Variable *declareArgument(Handle<String> name, const SourcePosition &pos);
13.7 - NamedEnum *declareEnum(Handle<String> name, const SourcePosition &pos);
13.8 NamedConstant *declareConstant(Handle<String> name, const SourcePosition &pos);
13.9 + NamedType *declareType(Handle<String> name, const SourcePosition &pos);
13.10 + NamedType *declareType(Handle<String> name, Handle<Type> type);
13.11
13.12 EnvironmentMap *createEnvironmentMap(Zone *zone);
13.13
14.1 --- a/src/SemanticAnalysis.cpp Mon Jul 30 22:30:38 2012 -0700
14.2 +++ b/src/SemanticAnalysis.cpp Wed Aug 01 22:32:59 2012 -0700
14.3 @@ -143,6 +143,22 @@
14.4 FunctionStatement *funstmt = statement->toFunctionStatement();
14.5 if (!preanalyze(funstmt))
14.6 return false;
14.7 + } else if (statement->isEnumStatement()) {
14.8 + EnumStatement *enumstmt = statement->toEnumStatement();
14.9 +
14.10 + // We pre-fill global enum types, since they may occur in function
14.11 + // signatures. This should probably be somewhere else...
14.12 + Local<String> name(zone_, enumstmt->name());
14.13 + Local<Type> type(zone_);
14.14 + if (name)
14.15 + type = zone_->types()->newEnum(name);
14.16 + else
14.17 + type = zone_->types()->getPrimitive(PrimitiveType_Int32);
14.18 +
14.19 + if (!type)
14.20 + return false;
14.21 +
14.22 + enumstmt->decl()->setType(type);
14.23 }
14.24 }
14.25
14.26 @@ -205,6 +221,27 @@
14.27 return true;
14.28 }
14.29
14.30 +Type *
14.31 +SemanticAnalysis::bindType(const SourcePosition &pos, BoundName *name)
14.32 +{
14.33 + if (!name)
14.34 + return zone_->types()->getPrimitive(PrimitiveType_Int32);
14.35 +
14.36 + if (name->kind() == BoundName::UNBOUND) {
14.37 + cc_.reportError(pos, Message_TypeNotFound, name->name()->chars());
14.38 + return NULL;
14.39 + }
14.40 +
14.41 + if (name->kind() != BoundName::TYPE) {
14.42 + cc_.reportError(pos, Message_IdentifierIsNotAType, name->name()->chars());
14.43 + return NULL;
14.44 + }
14.45 +
14.46 + if (!name->type())
14.47 + return NULL;
14.48 +
14.49 + return name->type();
14.50 +}
14.51
14.52 Type *
14.53 SemanticAnalysis::visitAndApplyType(Expression *expression)
14.54 @@ -237,8 +274,8 @@
14.55 }
14.56
14.57 // :TODO: this leaks an interior pointer.
14.58 -static inline const char *
14.59 -GetTypeName(Type *type)
14.60 +const char *
14.61 +ke::GetTypeName(Type *type)
14.62 {
14.63 if (type->isArray())
14.64 return "array";
14.65 @@ -246,11 +283,22 @@
14.66 return "function";
14.67 if (type->isVoid())
14.68 return "void";
14.69 + if (type->isEnum())
14.70 + return type->name()->chars();
14.71 if (type->isReference())
14.72 type = type->contained();
14.73 - if (type->tag())
14.74 - return type->tag()->chars();
14.75 - return "int";
14.76 + switch (type->primitive()) {
14.77 + case PrimitiveType_Bool:
14.78 + return "bool";
14.79 + case PrimitiveType_Char:
14.80 + return "String";
14.81 + case PrimitiveType_Int32:
14.82 + return "int";
14.83 + case PrimitiveType_Float:
14.84 + return "float";
14.85 + default:
14.86 + return "<unknown>";
14.87 + }
14.88 }
14.89
14.90 void
14.91 @@ -282,7 +330,7 @@
14.92 if (left->isFloat() || right->isFloat()) {
14.93 Type *floatType = left->isFloat() ? left : right;
14.94 Type *other = left->isFloat() ? right : left;
14.95 - if (other->isFloat() || (other->isInt32() && !other->tag()))
14.96 + if (other->isFloat() || other->isInt32())
14.97 return floatType;
14.98 }
14.99 }
14.100 @@ -290,22 +338,20 @@
14.101 if (token == TOK_OR || token == TOK_AND) {
14.102 if (!canTest(node, left) || !canTest(node, right))
14.103 return NULL;
14.104 - return zone_->types()->getPrimitive(PrimitiveType_Int32);
14.105 + return zone_->types()->getPrimitive(PrimitiveType_Bool);
14.106 }
14.107
14.108 if (token >= TOK_EQUALS && token <= TOK_GE) {
14.109 - if ((left->isFloat() || (left->isInt32() && !left->tag())) &&
14.110 - (right->isFloat() || (right->isInt32() && !right->tag())))
14.111 + if ((left->isFloat() || left->isInt32()) &&
14.112 + (right->isFloat() || right->isInt32()))
14.113 {
14.114 - return zone_->types()->getPrimitive(PrimitiveType_Int32);
14.115 + return zone_->types()->getPrimitive(PrimitiveType_Bool);
14.116 }
14.117 binaryTypeError(node, token, left, right);
14.118 return NULL;
14.119 }
14.120
14.121 - if ((!left->isInt32() || left->tag()) ||
14.122 - (!right->isInt32() || right->tag()))
14.123 - {
14.124 + if (!left->isInt32() || !right->isInt32()) {
14.125 binaryTypeError(node, token, left, right);
14.126 return NULL;
14.127 }
14.128 @@ -316,7 +362,7 @@
14.129 bool
14.130 SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
14.131 {
14.132 - if (type->isArray() || (type->isInt32() && type->tag())) {
14.133 + if (!type->isPrimitive() && !type->isEnum()) {
14.134 cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
14.135 return false;
14.136 }
14.137 @@ -429,7 +475,7 @@
14.138
14.139 assert(!type->isReference());
14.140
14.141 - if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
14.142 + if (!type->isInt32() && !type->isFloat()) {
14.143 unaryTypeError(node, node->token(), type);
14.144 return;
14.145 }
14.146 @@ -456,7 +502,7 @@
14.147 break;
14.148
14.149 case TOK_MINUS:
14.150 - if (!type->isFloat() && (!type->isInt32() || type->tag())) {
14.151 + if (!type->isFloat() && !type->isInt32()) {
14.152 unaryTypeError(node, node->token(), type);
14.153 return;
14.154 }
14.155 @@ -465,13 +511,12 @@
14.156
14.157 case TOK_LABEL:
14.158 {
14.159 - Local<String> tag(zone_, node->tag());
14.160 - Local<Type> to(zone_, zone_->types()->getPrimitiveForTag(tag));
14.161 + Local<Type> to(zone_, bindType(node->pos(), node->type()));
14.162 if (!to)
14.163 return;
14.164
14.165 - if ((!type->isFloat() && !type->isInt32()) ||
14.166 - (!to->isFloat() && !to->isInt32()))
14.167 + if ((!type->isFloat() && !type->isInt32OrEnum()) ||
14.168 + (!to->isFloat() && !to->isInt32OrEnum()))
14.169 {
14.170 unaryTypeError(node, node->token(), type);
14.171 return;
14.172 @@ -483,7 +528,7 @@
14.173
14.174 default:
14.175 assert(node->token() == TOK_TILDE);
14.176 - if (!type->isInt32() || type->tag()) {
14.177 + if (!type->isInt32()) {
14.178 unaryTypeError(node, node->token(), type);
14.179 return;
14.180 }
14.181 @@ -627,11 +672,20 @@
14.182 scope_ = scope_->enclosing();
14.183 }
14.184
14.185 +static inline bool
14.186 +IsScalarString(Type *type)
14.187 +{
14.188 + if (type->isPrimitive() && type->primitive() == PrimitiveType_Char)
14.189 + return true;
14.190 + if (type->isReference())
14.191 + return IsScalarString(type->contained());
14.192 + return false;
14.193 +}
14.194 +
14.195 void
14.196 SemanticAnalysis::visit(VariableDeclaration *node)
14.197 {
14.198 - Local<String> tag(zone_, node->tag());
14.199 - Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
14.200 + Local<Type> type(zone_, bindType(node->pos(), node->type()));
14.201 if (!type)
14.202 return;
14.203
14.204 @@ -778,8 +832,7 @@
14.205 for (size_t i = 0; i < node->parameters()->length(); i++) {
14.206 Parameter *parameter = node->parameters()->at(i);
14.207
14.208 - Local<String> tag(zone_, parameter->tag());
14.209 - Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
14.210 + Local<Type> type(zone_, bindType(parameter->variable()->pos(), parameter->type()));
14.211 if (!type)
14.212 return false;
14.213
14.214 @@ -823,9 +876,7 @@
14.215 }
14.216 }
14.217
14.218 - if ((type->isPrimitive() && type->primitive() == PrimitiveType_Char) ||
14.219 - (type->isReference() && type->contained()->primitive() == PrimitiveType_Char))
14.220 - {
14.221 + if (IsScalarString(type)) {
14.222 cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
14.223 return false;
14.224 }
14.225 @@ -835,11 +886,11 @@
14.226 }
14.227
14.228 Local<Type> returnType(zone_);
14.229 - if (node->returnTag()) {
14.230 - Local<String> tag(zone_, node->returnTag());
14.231 - returnType = zone_->types()->getPrimitiveForTag(tag);
14.232 - } else if (node->hasExplicitReturn() || node->fun()->isNative()) {
14.233 - returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
14.234 + if (node->returnType() ||
14.235 + node->hasExplicitReturn() ||
14.236 + node->fun()->isNative())
14.237 + {
14.238 + returnType = bindType(node->pos(), node->returnType());
14.239 } else {
14.240 returnType = zone_->types()->getVoid();
14.241 }
14.242 @@ -893,6 +944,14 @@
14.243 function_ = NULL;
14.244 }
14.245
14.246 +void
14.247 +SemanticAnalysis::typeMismatch(AstNode *node, Handle<Type> actual, Handle<Type> given)
14.248 +{
14.249 + cc_.reportError(node->pos(),Message_TypeMismatch,
14.250 + GetTypeName(actual),
14.251 + GetTypeName(given));
14.252 +}
14.253 +
14.254 bool
14.255 SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
14.256 {
14.257 @@ -940,15 +999,7 @@
14.258 actual = actual->contained();
14.259 }
14.260
14.261 - if (given->primitive() != actual->primitive()) {
14.262 - // :TODO: leaks an interior pointer.
14.263 - const char *givenTag = given->tag() ? given->tag()->chars() : "_";
14.264 - const char *actualTag = given->tag() ? given->tag()->chars() : "_";
14.265 - cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
14.266 - return false;
14.267 - }
14.268 -
14.269 - return true;
14.270 + return typeCheckAssignment(node, given, actual, forAssign);
14.271 }
14.272
14.273 bool
14.274 @@ -971,16 +1022,21 @@
14.275 if (actual->isReference())
14.276 actual = actual->contained();
14.277
14.278 - if (!given->isPrimitive() || !actual->isPrimitive()) {
14.279 - cc_.reportError(node->pos(), Message_UnsupportedType);
14.280 + if (actual->isEnum()) {
14.281 + if (!given->isEnum() || actual != given) {
14.282 + typeMismatch(node, actual, given);
14.283 + return false;
14.284 + }
14.285 + return true;
14.286 + }
14.287 +
14.288 + if (given->isEnum() || given->isFunction()) {
14.289 + typeMismatch(node, actual, given);
14.290 return false;
14.291 }
14.292 -
14.293 +
14.294 if (given->primitive() != actual->primitive()) {
14.295 - // :TODO: leaks an interior pointer
14.296 - const char *givenTag = given->tag() ? given->tag()->chars() : "_";
14.297 - const char *actualTag = actual->tag() ? actual->tag()->chars() : "_";
14.298 - cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
14.299 + typeMismatch(node, actual, given);
14.300 return false;
14.301 }
14.302
14.303 @@ -1112,7 +1168,7 @@
14.304 if (!left || !right)
14.305 return;
14.306
14.307 - if (!right->isInt32()) {
14.308 + if (!right->isInt32() && !right->isEnum()) {
14.309 cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
14.310 return;
14.311 }
14.312 @@ -1126,20 +1182,9 @@
14.313 void
14.314 SemanticAnalysis::visit(EnumStatement *node)
14.315 {
14.316 - // Forbid the blessed types.
14.317 - Local<String> tag(zone_, node->name());
14.318 - if (!strcmp(tag->chars(), "Float") ||
14.319 - !strcmp(tag->chars(), "String") ||
14.320 - !strcmp(tag->chars(), "any") ||
14.321 - !strcmp(tag->chars(), "bool"))
14.322 - {
14.323 - cc_.reportError(node->pos(), Message_InvalidEnumName);
14.324 - return;
14.325 - }
14.326 + Local<Type> type(zone_, node->decl()->type());
14.327
14.328 - Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
14.329 - if (!type)
14.330 - return;
14.331 + assert(type);
14.332
14.333 int value = 0;
14.334 for (size_t i = 0; i < node->entries()->length(); i++) {
15.1 --- a/src/SemanticAnalysis.h Mon Jul 30 22:30:38 2012 -0700
15.2 +++ b/src/SemanticAnalysis.h Wed Aug 01 22:32:59 2012 -0700
15.3 @@ -148,10 +148,13 @@
15.4
15.5 private:
15.6 bool canTest(AstNode *node, Handle<Type> type);
15.7 + void typeMismatch(AstNode *node, Handle<Type> actual, Handle<Type> given);
15.8 void unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type);
15.9 void binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
15.10 Type *typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
15.11
15.12 + Type *bindType(const SourcePosition &pos, BoundName *name);
15.13 +
15.14 // These check if one type is compatible with another type, for various
15.15 // purposes, like:
15.16 // return (expr) matches function return type
15.17 @@ -202,6 +205,8 @@
15.18 void visit(BooleanLiteral *node);
15.19 };
15.20
15.21 +const char *GetTypeName(Type *type);
15.22 +
15.23 } // namespace ke
15.24
15.25 #endif // _include_semantic_analysis_h_
16.1 --- a/src/TypeManager.cpp Mon Jul 30 22:30:38 2012 -0700
16.2 +++ b/src/TypeManager.cpp Wed Aug 01 22:32:59 2012 -0700
16.3 @@ -39,29 +39,15 @@
16.4 if (!voidType_)
16.5 return false;
16.6
16.7 - Local<String> floatTag(zone_, zone_->makeSymbol("Float"));
16.8 - if (!floatTag)
16.9 - return false;
16.10 -
16.11 - Local<String> stringTag(zone_, zone_->makeSymbol("String"));
16.12 - if (!stringTag)
16.13 + if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, PrimitiveType_Int32)) == NULL)
16.14 return false;
16.15 -
16.16 - Local<String> boolTag(zone_, zone_->makeSymbol("bool"));
16.17 - if (!boolTag)
16.18 - return false;
16.19 -
16.20 - Local<String> nullTag(zone_);
16.21 -
16.22 - if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, nullTag)) == NULL)
16.23 - return false;
16.24 - if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, floatTag)) == NULL)
16.25 + if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, PrimitiveType_Float)) == NULL)
16.26 return false;
16.27 if ((primitiveTypes_[PrimitiveType_Native] = Type::NewPrimitive(zone_, PrimitiveType_Native)) == NULL)
16.28 return false;
16.29 - if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, stringTag)) == NULL)
16.30 + if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, PrimitiveType_Char)) == NULL)
16.31 return false;
16.32 - if ((primitiveTypes_[PrimitiveType_Bool] = Type::NewPrimitive(zone_, boolTag)) == NULL)
16.33 + if ((primitiveTypes_[PrimitiveType_Bool] = Type::NewPrimitive(zone_, PrimitiveType_Bool)) == NULL)
16.34 return false;
16.35
16.36 Local<Type> type(zone_);
16.37 @@ -75,20 +61,6 @@
16.38 }
16.39
16.40 Type *
16.41 -TypeManager::getPrimitiveForTag(Handle<String> tag)
16.42 -{
16.43 - if (!tag || strcmp(tag->chars(), "_") == 0)
16.44 - return getPrimitive(PrimitiveType_Int32);
16.45 - if (strcmp(tag->chars(), "Float") == 0)
16.46 - return getPrimitive(PrimitiveType_Float);
16.47 - if (strcmp(tag->chars(), "String") == 0)
16.48 - return getPrimitive(PrimitiveType_Char);
16.49 -
16.50 - // :TODO: cache this.
16.51 - return Type::NewPrimitive(zone_, tag);
16.52 -}
16.53 -
16.54 -Type *
16.55 TypeManager::unsafeArray(Handle<Type> contained, int elements, bool isConst)
16.56 {
16.57 // :TODO: cache this.
16.58 @@ -98,7 +70,7 @@
16.59 Type *
16.60 TypeManager::getReference(Handle<Type> type, bool isConst)
16.61 {
16.62 - if (!isConst && (type->isFloat() || (type->isInt32() && !type->tag())))
16.63 + if (!isConst && type->isPrimitive())
16.64 return referenceTypes_[type->primitive()];
16.65
16.66 // :TODO: cache this.
16.67 @@ -119,6 +91,12 @@
16.68 return Type::NewNative(zone_, returnType, args, variadic);
16.69 }
16.70
16.71 +Type *
16.72 +TypeManager::newEnum(Handle<String> name)
16.73 +{
16.74 + return Type::NewEnum(zone_, name);
16.75 +}
16.76 +
16.77 void
16.78 TypeManager::accept(VirtualObjectVisitor *visitor)
16.79 {
17.1 --- a/src/TypeManager.h Mon Jul 30 22:30:38 2012 -0700
17.2 +++ b/src/TypeManager.h Wed Aug 01 22:32:59 2012 -0700
17.3 @@ -40,7 +40,6 @@
17.4
17.5 bool initialize();
17.6
17.7 - Type *getPrimitiveForTag(Handle<String>);
17.8 Type *getPrimitive(PrimitiveType type) {
17.9 return primitiveTypes_[type];
17.10 }
17.11 @@ -50,6 +49,7 @@
17.12 }
17.13 Type *getReference(Handle<Type> type, bool isConst);
17.14 Type *unsafeArray(Handle<Type> contained, int elements, bool isConst);
17.15 + Type *newEnum(Handle<String> name);
17.16 Type *newFunction(Handle<Type> returnType, Handle<FixedArray> args);
17.17 Type *newNative(Handle<Type> returnType, Handle<FixedArray> args, bool variadic);
17.18
18.1 --- a/src/Types.cpp Mon Jul 30 22:30:38 2012 -0700
18.2 +++ b/src/Types.cpp Wed Aug 01 22:32:59 2012 -0700
18.3 @@ -32,7 +32,6 @@
18.4 return NULL;
18.5
18.6 type->kind_ = VOID;
18.7 - type->tag_ = NULL;
18.8 type->contained_ = NULL;
18.9 type->returnType_ = NULL;
18.10 type->parameters_ = NULL;
18.11 @@ -40,32 +39,6 @@
18.12 }
18.13
18.14 Type *
18.15 -Type::NewPrimitive(Zone *zone, Handle<String> tag)
18.16 -{
18.17 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
18.18 - if (!type)
18.19 - return NULL;
18.20 -
18.21 - assert(!tag || strcmp(tag->chars(), "_"));
18.22 -
18.23 - type->kind_ = PRIMITIVE;
18.24 - type->tag_ = tag;
18.25 - type->contained_ = NULL;
18.26 - type->returnType_ = NULL;
18.27 - type->parameters_ = NULL;
18.28 -
18.29 - if (tag && strcmp(tag->chars(), "Float") == 0)
18.30 - type->primitive_ = PrimitiveType_Float;
18.31 - else if (tag && strcmp(tag->chars(), "String") == 0)
18.32 - type->primitive_ = PrimitiveType_Char;
18.33 - else if (tag && strcmp(tag->chars(), "bool") == 0)
18.34 - type->primitive_ = PrimitiveType_Bool;
18.35 - else
18.36 - type->primitive_ = PrimitiveType_Int32;
18.37 - return type;
18.38 -}
18.39 -
18.40 -Type *
18.41 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
18.42 {
18.43 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
18.44 @@ -73,7 +46,7 @@
18.45 return NULL;
18.46
18.47 type->kind_ = PRIMITIVE;
18.48 - type->tag_ = NULL;
18.49 + type->name_ = NULL;
18.50 type->contained_ = NULL;
18.51 type->returnType_ = NULL;
18.52 type->parameters_ = NULL;
18.53 @@ -89,12 +62,12 @@
18.54 return NULL;
18.55
18.56 type->kind_ = ARRAY;
18.57 - type->tag_ = NULL;
18.58 + type->name_ = NULL;
18.59 type->contained_ = contained;
18.60 type->returnType_ = NULL;
18.61 type->parameters_ = NULL;
18.62 type->elements_ = elements;
18.63 - if (contained->isPrimitive())
18.64 + if (!contained->isArray())
18.65 type->levels_ = 1;
18.66 else
18.67 type->levels_ = contained->levels() + 1;
18.68 @@ -110,7 +83,7 @@
18.69 return NULL;
18.70
18.71 type->kind_ = REFERENCE;
18.72 - type->tag_ = NULL;
18.73 + type->name_ = NULL;
18.74 type->contained_ = contained;
18.75 type->returnType_ = NULL;
18.76 type->parameters_ = NULL;
18.77 @@ -126,6 +99,7 @@
18.78 return NULL;
18.79
18.80 type->kind_ = FUNCTION;
18.81 + type->name_ = NULL;
18.82 type->contained_ = NULL;
18.83 type->returnType_ = returnType;
18.84 type->parameters_ = parameters;
18.85 @@ -133,6 +107,21 @@
18.86 }
18.87
18.88 Type *
18.89 +Type::NewEnum(Zone *zone, Handle<String> name)
18.90 +{
18.91 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
18.92 + if (!type)
18.93 + return NULL;
18.94 +
18.95 + type->kind_ = ENUM;
18.96 + type->name_ = name;
18.97 + type->contained_ = NULL;
18.98 + type->returnType_ = NULL;
18.99 + type->parameters_ = NULL;
18.100 + return type;
18.101 +}
18.102 +
18.103 +Type *
18.104 Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool variadic)
18.105 {
18.106 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
18.107 @@ -140,6 +129,7 @@
18.108 return NULL;
18.109
18.110 type->kind_ = NATIVE;
18.111 + type->name_ = NULL;
18.112 type->contained_ = NULL;
18.113 type->returnType_ = returnType;
18.114 type->parameters_ = parameters;
18.115 @@ -150,13 +140,15 @@
18.116 bool
18.117 Type::Compare(Type *left, Type *right)
18.118 {
18.119 + if (left == right)
18.120 + return true;
18.121 +
18.122 if (left->kind() != right->kind())
18.123 return false;
18.124
18.125 switch (left->kind()) {
18.126 case Type::PRIMITIVE:
18.127 - return (left->primitive() == right->primitive() &&
18.128 - left->tag() == right->tag());
18.129 + return left->primitive() == right->primitive();
18.130
18.131 case Type::ARRAY:
18.132 {
18.133 @@ -186,6 +178,9 @@
18.134 return true;
18.135 }
18.136
18.137 + case Type::ENUM:
18.138 + return false;
18.139 +
18.140 case Type::VOID:
18.141 return true;
18.142
19.1 --- a/src/Types.h Mon Jul 30 22:30:38 2012 -0700
19.2 +++ b/src/Types.h Wed Aug 01 22:32:59 2012 -0700
19.3 @@ -29,11 +29,28 @@
19.4
19.5 enum PrimitiveType
19.6 {
19.7 - PrimitiveType_Bool, // 0 or 1
19.8 + // A boolean type semantically represents 0 or 1. As an optimization, its
19.9 + // internal storage type is the same as int32, and any non-zero value
19.10 + // compares positively to "true".
19.11 + PrimitiveType_Bool,
19.12 +
19.13 + // A character is an arbitrary 8-bit value. Characters are not supported
19.14 + // as a normal storage class; they may only be used for arrays. When read
19.15 + // from an array, they are immediately sign extended to 32 bits. Integers
19.16 + // stored into an char array are truncated to 8 bits.
19.17 PrimitiveType_Char, // signed, 8-bit character
19.18 - PrimitiveType_Int32, // signed, 32-bit integer
19.19 - PrimitiveType_Float, // 32-bit IEEE-754 float
19.20 - PrimitiveType_Native, // native-sized word
19.21 +
19.22 + // Enumerations and untyped variables are stored as signed, 32-bit integers.
19.23 + PrimitiveType_Int32,
19.24 +
19.25 + // Floating point values are 32-bit IEEE-754 floats. This is required ro
19.26 + // SourcePawn 1 compatibility.
19.27 + PrimitiveType_Float,
19.28 +
19.29 + // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
19.30 + // on 64-bit systems), and does not exist in language semantics.
19.31 + PrimitiveType_Native,
19.32 +
19.33 PrimitiveTypes_Total
19.34 };
19.35
19.36 @@ -45,7 +62,8 @@
19.37 REFERENCE,
19.38 FUNCTION,
19.39 NATIVE,
19.40 - VOID
19.41 + VOID,
19.42 + ENUM
19.43 };
19.44
19.45 private:
19.46 @@ -58,12 +76,12 @@
19.47 static const size_t MAX_UNSAFE_ARRAY_DEPTH = 5;
19.48
19.49 static Type *NewVoid(Zone *zone);
19.50 - static Type *NewPrimitive(Zone *zone, Handle<String> tag);
19.51 static Type *NewPrimitive(Zone *zone, PrimitiveType type);
19.52 static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
19.53 static Type *NewReference(Zone *zone, Handle<Type> contained, bool isConst);
19.54 static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters);
19.55 static Type *NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool isVariadic);
19.56 + static Type *NewEnum(Zone *zone, Handle<String> name);
19.57
19.58 static bool Compare(Type *left, Type *right);
19.59
19.60 @@ -98,6 +116,12 @@
19.61 assert(isPrimitive());
19.62 return primitive_;
19.63 }
19.64 + PrimitiveType pod() {
19.65 + assert(isPrimitive() || isEnum());
19.66 + return isPrimitive()
19.67 + ? primitive()
19.68 + : PrimitiveType_Int32;
19.69 + }
19.70 Type *contained() {
19.71 assert(isArray() || isReference());
19.72 return Type::cast(contained_);
19.73 @@ -110,10 +134,6 @@
19.74 assert(isArray());
19.75 return levels_;
19.76 }
19.77 - String *tag() {
19.78 - assert(isPrimitive());
19.79 - return tag_;
19.80 - }
19.81 Type *innermost() {
19.82 assert(isArray());
19.83 Type *temp = contained();
19.84 @@ -127,6 +147,9 @@
19.85 bool isInt32() {
19.86 return isPrimitive() && primitive() == PrimitiveType_Int32;
19.87 }
19.88 + bool isInt32OrEnum() {
19.89 + return isInt32() || isEnum();
19.90 + }
19.91 bool isCharArray() {
19.92 return isArray() &&
19.93 contained()->isPrimitive() &&
19.94 @@ -150,6 +173,14 @@
19.95 assert(kind() == PRIMITIVE || kind() == ARRAY || kind() == REFERENCE);
19.96 return const_;
19.97 }
19.98 + bool isEnum() {
19.99 + return kind() == ENUM;
19.100 + }
19.101 +
19.102 + String *name() {
19.103 + assert(isEnum());
19.104 + return name_;
19.105 + }
19.106
19.107 // GC Descriptor.
19.108 static inline size_t offsetOfContained() {
19.109 @@ -161,15 +192,14 @@
19.110 static inline size_t offsetOfParameters() {
19.111 return OFFSETOF(Type, parameters_);
19.112 }
19.113 - static inline size_t offsetOfTag() {
19.114 - return OFFSETOF(Type, tag_);
19.115 + static inline size_t offsetOfName() {
19.116 + return OFFSETOF(Type, name_);
19.117 }
19.118 // End GC Descriptor.
19.119
19.120 private:
19.121 Kind kind_;
19.122 PrimitiveType primitive_;
19.123 - Barriered<String> tag_;
19.124
19.125 // Primitives, arrays, and references.
19.126 bool const_;
19.127 @@ -185,6 +215,9 @@
19.128 Barriered<Type> returnType_;
19.129 Barriered<FixedArray> parameters_;
19.130 bool variadicNative_;
19.131 +
19.132 + // Enums only.
19.133 + Barriered<String> name_;
19.134 };
19.135
19.136 class BoxedPrimitive