Introduced type semantics, completely replacing tag semantics.
authorDavid Anderson <dvander@alliedmods.net>
Wed Aug 01 22:32:59 2012 -0700 (2012-08-01)
changeset 145e9d804821c48
parent 144 a8735148dcf0
child 146 dc7d3b7a918c
Introduced type semantics, completely replacing tag semantics.
src/API.cpp
src/AST.h
src/BytecodeCompiler.cpp
src/BytecodeEmitter.h
src/Messages.tbl
src/NameBinding.cpp
src/NameBinding.h
src/ObjectVisitor.h
src/Opcodes.cpp
src/Parser.cpp
src/Parser.h
src/Scopes.cpp
src/Scopes.h
src/SemanticAnalysis.cpp
src/SemanticAnalysis.h
src/TypeManager.cpp
src/TypeManager.h
src/Types.cpp
src/Types.h
     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