Implement |const| keyword.
Implement |const| keyword.
1.1 --- a/src/API.cpp Tue Dec 25 18:13:02 2012 -0800
1.2 +++ b/src/API.cpp Wed Dec 26 17:14:12 2012 -0800
1.3 @@ -295,9 +295,10 @@
1.4
1.5 for (unsigned i = 0; i < nparams; i++) {
1.6 if (!CheckInvokeType(params[i], fun->argType(i))) {
1.7 + char name[255];
1.8 ke::ZONE()->reportError(Message_TypeMismatchDuringInvoke,
1.9 GetInvokeTypeName(params[i].type()),
1.10 - GetTypeName(fun->argType(i)));
1.11 + GetTypeName(fun->argType(i), name, sizeof(name)));
1.12 return false;
1.13 }
1.14 }
1.15 @@ -308,7 +309,9 @@
1.16 !returnType->isEnum() &&
1.17 !returnType->isVoid())
1.18 {
1.19 - ke::ZONE()->reportError(Message_CannotInvokeReturnType, GetTypeName(returnType));
1.20 + char name[255];
1.21 + ke::ZONE()->reportError(Message_CannotInvokeReturnType,
1.22 + GetTypeName(returnType, name, sizeof(name)));
1.23 return false;
1.24 }
1.25
2.1 --- a/src/Messages.tbl Tue Dec 25 18:13:02 2012 -0800
2.2 +++ b/src/Messages.tbl Wed Dec 26 17:14:12 2012 -0800
2.3 @@ -41,7 +41,6 @@
2.4 MSG(ForwardDeclareMismatches, SyntaxError, "declaration does not match original forward signature")
2.5 MSG(ArrayCantBeReference, SyntaxError, "this type cannot be used with a reference")
2.6 MSG(ArraySizeMustBeConstant, SyntaxError, "array size must be a constant integer")
2.7 -MSG(ReferenceIsConstant, SyntaxError, "cannot assign to a constant lvalue")
2.8 MSG(MultiArrayInNative, SyntaxError, "multidimensional arrays cannot be passed to natives")
2.9 MSG(InvalidVarArgs, SyntaxError, "varargs cannot be const or ref")
2.10 MSG(VarArgsOutsideNative, SyntaxError, "variadic arguments can only be specified on natives")
2.11 @@ -80,4 +79,7 @@
2.12 MSG(ImportsMustBeFirst, SyntaxError, "import statements must come before other statements")
2.13 MSG(ImportedNameAlreadyBound, TypeError, "imported name has already been bound")
2.14 MSG(CannotResolveImport, TypeError, "cannot resolve import %s")
2.15 -MSG(InvalidCoercion, TypeError, "cannot coerce type '%s' to type '%s'")
2.16 \ No newline at end of file
2.17 +MSG(InvalidCoercion, TypeError, "cannot coerce type '%s' to type '%s'")
2.18 +MSG(CannotConstReference, TypeError, "constant outparams are not allowed")
2.19 +MSG(CannotModifyConst, TypeError, "cannot change constant value or structure")
2.20 +MSG(InvalidConstOnFormal, TypeError, "const parameters must be arrays or structs")
2.21 \ No newline at end of file
3.1 --- a/src/Structures.cpp Tue Dec 25 18:13:02 2012 -0800
3.2 +++ b/src/Structures.cpp Wed Dec 26 17:14:12 2012 -0800
3.3 @@ -133,14 +133,16 @@
3.4 childStructMap = StructMap::cast(StructType::cast(desc->type())->newMap());
3.5 child = Struct::New(zone, childStructMap, tenure);
3.6 } else if (desc->type()->isArray()) {
3.7 - assert(false);
3.8 -#if 0
3.9 - childArrayMap = ArrayMap::cast(desc->type()->newMap());
3.10 - if (desc->type()->isFixedLength())
3.11 + // :TODO: don't create empty arrays for ref slots here.
3.12 + // Instead, make a separate Initialize function, so we
3.13 + // can avoid double-creating arrays for module globals.
3.14 + // (const char:x[] = "x")
3.15 + ArrayType *type = ArrayType::cast(desc->type());
3.16 + childArrayMap = ArrayMap::cast(type->newMap());
3.17 + if (type->isFixedLength())
3.18 child = Array::NewFixed(zone, childArrayMap, tenure);
3.19 else
3.20 child = Array::NewEmpty(zone, childArrayMap, tenure);
3.21 -#endif
3.22 }
3.23 if (!child)
3.24 return NULL;
4.1 --- a/src/TypeManager.cpp Tue Dec 25 18:13:02 2012 -0800
4.2 +++ b/src/TypeManager.cpp Wed Dec 26 17:14:12 2012 -0800
4.3 @@ -102,9 +102,12 @@
4.4 }
4.5
4.6 Type *
4.7 -TypeManager::qualify(Handle<Type> type, TypeQualifiers quals)
4.8 +TypeManager::qualify(Handle<Type> argType, TypeQualifiers quals)
4.9 {
4.10 - assert(!type->hasTypeQualifiers());
4.11 + Local<Type> type(zone_, argType->unqualified());
4.12 +
4.13 + if (!quals)
4.14 + return type;
4.15
4.16 LookupKey key(type, quals);
4.17
5.1 --- a/src/Types.cpp Tue Dec 25 18:13:02 2012 -0800
5.2 +++ b/src/Types.cpp Wed Dec 26 17:14:12 2012 -0800
5.3 @@ -218,32 +218,84 @@
5.4 return type;
5.5 }
5.6
5.7 -// :TODO: this leaks an interior pointer.
5.8 -const char *
5.9 -ke::GetTypeName(Type *type)
5.10 +static size_t
5.11 +FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap)
5.12 +{
5.13 + size_t len = vsnprintf(buffer, maxlen, text, ap);
5.14 + if (len >= maxlen) {
5.15 + buffer[maxlen - 1] = '\0';
5.16 + return maxlen - 1;
5.17 + }
5.18 + return len;
5.19 +}
5.20 +
5.21 +static size_t
5.22 +Format(char *buffer, size_t maxlen, const char *text, ...)
5.23 {
5.24 - if (type->isArray())
5.25 - return "array";
5.26 + va_list ap;
5.27 + va_start(ap, text);
5.28 + size_t len = FormatVA(buffer, maxlen, text, ap);
5.29 + va_end(ap);
5.30 + return len;
5.31 +}
5.32 +
5.33 +static size_t
5.34 +FormatTypeName(Type *type, char *buffer, size_t maxlen)
5.35 +{
5.36 + if (type->isArray()) {
5.37 + ArrayType *atype = ArrayType::cast(type);
5.38 + Type *innermost = atype->innermost();
5.39 +
5.40 + size_t len = FormatTypeName(innermost, buffer, maxlen);
5.41 + for (;;) {
5.42 + if (atype->isFixedLength())
5.43 + len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength());
5.44 + else
5.45 + len += Format(buffer + len, maxlen - len, "[]");
5.46 + if (!atype->contained()->isArray())
5.47 + break;
5.48 + atype = ArrayType::cast(atype->contained());
5.49 + }
5.50 + return len;
5.51 + }
5.52 + if (type->hasTypeQualifiers()) {
5.53 + size_t len = 0;
5.54 + if (type->quals() & TypeQual_Const)
5.55 + len += Format(buffer, maxlen, "const ");
5.56 + return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len);
5.57 + }
5.58 if (type->isFunction())
5.59 - return "function";
5.60 + return Format(buffer, maxlen, "function");
5.61 if (type->isVoid())
5.62 - return "void";
5.63 + return Format(buffer, maxlen, "void");
5.64 + if (type->isUnchecked())
5.65 + return Format(buffer, maxlen, "unchecked");
5.66 if (type->isEnum())
5.67 - return EnumType::cast(type)->name()->chars();
5.68 + return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars());
5.69 if (type->isStruct())
5.70 - return StructType::cast(type)->name()->chars();
5.71 - if (type->isReference())
5.72 - type = ReferenceType::cast(type)->contained();
5.73 + return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars());
5.74 + if (type->isReference()) {
5.75 + ReferenceType *ref = ReferenceType::cast(type);
5.76 + size_t len = Format(buffer, maxlen, "&");
5.77 + return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len);
5.78 + }
5.79 switch (type->primitive()) {
5.80 case PrimitiveType_Bool:
5.81 - return "bool";
5.82 + return Format(buffer, maxlen, "bool");
5.83 case PrimitiveType_Char:
5.84 - return "String";
5.85 + return Format(buffer, maxlen, "char");
5.86 case PrimitiveType_Int32:
5.87 - return "int";
5.88 + return Format(buffer, maxlen, "int");
5.89 case PrimitiveType_Float:
5.90 - return "Float";
5.91 + return Format(buffer, maxlen, "float");
5.92 default:
5.93 - return "<unknown>";
5.94 + return Format(buffer, maxlen, "<UNKNOWN>");
5.95 }
5.96 }
5.97 +
5.98 +const char *
5.99 +ke::GetTypeName(Type *type, char *buffer, size_t maxlen)
5.100 +{
5.101 + FormatTypeName(type, buffer, maxlen);
5.102 + return buffer;
5.103 +}
6.1 --- a/src/Types.h Tue Dec 25 18:13:02 2012 -0800
6.2 +++ b/src/Types.h Wed Dec 26 17:14:12 2012 -0800
6.3 @@ -64,34 +64,8 @@
6.4 {
6.5 TypeQual_None = 0,
6.6
6.7 - // Const qualifier that has not been determined yet.
6.8 - TypeQual_UnkConst = (1 << 0),
6.9 -
6.10 - // For simplification, SP2 differentiates between two meanings of const.
6.11 - // "StoreConst" means that the value itself may not be changed. For
6.12 - // example,
6.13 - // const a = 5;
6.14 - //
6.15 - // Specifies that the storage of "a" is immutable.
6.16 - //
6.17 - // In addition, "RefConst" means that the memory at a reference may not
6.18 - // be changed. For example,
6.19 - //
6.20 - // const char:text[] = "asdfasdfasdf";
6.21 - //
6.22 - // Specifies a readonly view of a character array, however, |text| itself
6.23 - // may be repointed to another readonly character array.
6.24 - //
6.25 - // The meaning of "const" is inferred based on the scope and type:
6.26 - //
6.27 - // +---------+---------+-------+
6.28 - // | Array | Struct | Other |
6.29 - // +---------------+---------+---------+-------+
6.30 - // | GLOBAL/STATIC | Ref|Str | Ref|Str | Str |
6.31 - // | LOCAL | Ref | Ref|Str | Str |
6.32 - // +---------------+---------+---------+-------+
6.33 - TypeQual_StoreConst = (1 << 1),
6.34 - TypeQual_RefConst = (1 << 2)
6.35 + // Values of this type cannot be modified.
6.36 + TypeQual_Const = (1 << 2)
6.37 };
6.38
6.39 class Type : public Object
6.40 @@ -233,7 +207,7 @@
6.41 }
6.42
6.43 TypeQualifiers quals() {
6.44 - if (hasTypeQualifiers())
6.45 + if (!hasTypeQualifiers())
6.46 return TypeQual_None;
6.47 return quals_;
6.48 }
6.49 @@ -544,7 +518,7 @@
6.50 }
6.51 };
6.52
6.53 -const char *GetTypeName(Type *type);
6.54 +const char *GetTypeName(Type *type, char *buffer, size_t maxlen);
6.55
6.56 }
6.57
7.1 --- a/src/compiler/AST.h Tue Dec 25 18:13:02 2012 -0800
7.2 +++ b/src/compiler/AST.h Wed Dec 26 17:14:12 2012 -0800
7.3 @@ -193,6 +193,9 @@
7.4 ExpressionList *dims() const {
7.5 return dims_;
7.6 }
7.7 + TypeQualifiers quals() const {
7.8 + return qual_;
7.9 + }
7.10 };
7.11
7.12 class Parameter : public PoolObject
7.13 @@ -200,23 +203,23 @@
7.14 ScopedRoot<String> name_;
7.15 Expression *type_;
7.16 bool reference_;
7.17 - bool const_;
7.18 Expression *initializer_;
7.19 VariableSymbol *sym_;
7.20 SourcePosition pos_;
7.21 ExpressionList *dims_;
7.22 + TypeQualifiers quals_;
7.23
7.24 public:
7.25 - Parameter(Handle<String> name, Expression *type, bool reference, bool isConst,
7.26 + Parameter(Handle<String> name, Expression *type, bool reference, TypeQualifiers quals,
7.27 ExpressionList *dims, Expression *initializer, const SourcePosition &pos)
7.28 : name_(name),
7.29 type_(type),
7.30 reference_(reference),
7.31 - const_(isConst),
7.32 initializer_(initializer),
7.33 sym_(NULL),
7.34 pos_(pos),
7.35 - dims_(dims)
7.36 + dims_(dims),
7.37 + quals_(quals)
7.38 {
7.39 }
7.40
7.41 @@ -229,8 +232,8 @@
7.42 bool reference() const {
7.43 return reference_;
7.44 }
7.45 - bool isConst() const {
7.46 - return const_;
7.47 + TypeQualifiers quals() const {
7.48 + return quals_;
7.49 }
7.50 ExpressionList *dims() const {
7.51 return dims_;
8.1 --- a/src/compiler/NameBinding.cpp Tue Dec 25 18:13:02 2012 -0800
8.2 +++ b/src/compiler/NameBinding.cpp Wed Dec 26 17:14:12 2012 -0800
8.3 @@ -543,11 +543,14 @@
8.4 if (node->initialization())
8.5 node->initialization()->accept(this);
8.6
8.7 - Local<Type> type(zone_, bindType(node->type()));
8.8 + Local<Type> type(zone_, bindType(node->type(), node->quals()));
8.9 if (!type)
8.10 return;
8.11
8.12 - if (node->dims() || type->isArray()) {
8.13 + // We don't allow array typedefs yet.
8.14 + assert(!type->isArray());
8.15 +
8.16 + if (node->dims()) {
8.17 int dims[MAX_ARRAY_DEPTH];
8.18 int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
8.19 if (levels < 0)
8.20 @@ -568,11 +571,25 @@
8.21
8.22 // If we got extra dimensions, we need to build a new type.
8.23 if (node->dims()) {
8.24 - if ((type = buildArrayType(type, dims, node->dims()->length())) == NULL)
8.25 + if ((type = buildArrayType(type, node->quals(), dims, node->dims()->length())) == NULL)
8.26 return;
8.27 }
8.28 }
8.29
8.30 + // If we're in global scope, and we received a |const| qualifier, then
8.31 + // we extend this to array reference as well. This is to sort of mimic
8.32 + // SP1 functionality, but also means that you cannot have changeable
8.33 + // const pointers in global scope.
8.34 + if ((node->quals() & TypeQual_Const) &&
8.35 + type->isArray() &&
8.36 + link_->scope()->kind() == Scope::GLOBAL)
8.37 + {
8.38 + if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL)
8.39 + return;
8.40 + if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL)
8.41 + return;
8.42 + }
8.43 +
8.44 // If the node already has a symbol (meaning it was a global), then
8.45 // we don't have to do anything more.
8.46 if (node->sym()) {
8.47 @@ -817,15 +834,17 @@
8.48 return true;
8.49 }
8.50
8.51 - ArrayType *buildArrayType(Handle<Type> contained, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
8.52 + ArrayType *buildArrayType(Handle<Type> contained, TypeQualifiers quals, int dims[MAX_ARRAY_DEPTH], size_t postlevels) {
8.53 Local<Type> type(zone_, contained);
8.54 +
8.55 for (size_t i = postlevels - 1; i < postlevels; i--) {
8.56 int size = dims[i] > 0
8.57 ? dims[i]
8.58 : ArrayType::DYNAMIC_ARRAY_SIZE;
8.59
8.60 - type = zone_->types()->newArray(contained, size);
8.61 - if (!type)
8.62 + if ((type = zone_->types()->newArray(contained, size)) == NULL)
8.63 + return NULL;
8.64 + if ((type = zone_->types()->qualify(type, quals)) == NULL)
8.65 return NULL;
8.66 }
8.67 return ArrayType::cast(type);
8.68 @@ -834,7 +853,7 @@
8.69 bool fillFunctionType(Handle<FunctionType> fun, const FunctionSignature &sig) {
8.70 Local<Type> type(zone_);
8.71 if (!fun->returnType()) {
8.72 - if ((type = bindType(sig.returnType())) == NULL)
8.73 + if ((type = bindType(sig.returnType(), TypeQual_None)) == NULL)
8.74 return false;
8.75 fun->setReturnType(type);
8.76 }
8.77 @@ -845,10 +864,12 @@
8.78
8.79 for (size_t i = 0; i < sig.parameters()->length(); i++) {
8.80 Parameter *param = sig.parameters()->at(i);
8.81 - if ((type = bindType(param->type())) == NULL)
8.82 + if ((type = bindType(param->type(), param->quals())) == NULL)
8.83 return false;
8.84
8.85 - if (type->isArray() || param->dims()) {
8.86 + assert(!type->isArray());
8.87 +
8.88 + if (param->dims()) {
8.89 int dims[MAX_ARRAY_DEPTH];
8.90 int levels = evaluateDimensions(param->pos(), type, param->dims(), dims);
8.91 if (levels < 0)
8.92 @@ -858,7 +879,7 @@
8.93 // Unlike variables, we do not infer anything about array
8.94 // sizes from its default initializer.
8.95 if (param->dims()) {
8.96 - if ((type = buildArrayType(type, dims, param->dims()->length())) == NULL)
8.97 + if ((type = buildArrayType(type, param->quals(), dims, param->dims()->length())) == NULL)
8.98 return false;
8.99 }
8.100
8.101 @@ -873,9 +894,19 @@
8.102 cc_.reportError(param->pos(), Message_ArrayCantBeReference);
8.103 return false;
8.104 }
8.105 + if (param->quals() & TypeQual_Const) {
8.106 + cc_.reportError(param->pos(), Message_CannotConstReference);
8.107 + return false;
8.108 + }
8.109 if ((type = zone_->types()->getReference(type, false)) == NULL)
8.110 return false;
8.111 }
8.112 + if (param->quals() & TypeQual_Const) {
8.113 + if (!type->isArray() && !type->isStruct()) {
8.114 + cc_.reportError(param->pos(), Message_InvalidConstOnFormal);
8.115 + return false;
8.116 + }
8.117 + }
8.118
8.119 if (type->isVoid()) {
8.120 cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid);
8.121 @@ -891,27 +922,31 @@
8.122 return true;
8.123 }
8.124
8.125 - Type *bindType(Expression *expr) {
8.126 + Type *bindType(Expression *expr, TypeQualifiers quals) {
8.127 + Local<Type> type(zone_);
8.128 +
8.129 if (!expr) {
8.130 // If no type was declared, we return int32.
8.131 - return zone_->types()->getPrimitive(PrimitiveType_Int32);
8.132 - }
8.133 -
8.134 - expr->accept(this);
8.135 + type = zone_->types()->getPrimitive(PrimitiveType_Int32);
8.136 + } else {
8.137 + expr->accept(this);
8.138
8.139 - NameProxy *proxy = expr->asNameProxy();
8.140 - assert(proxy);
8.141 + NameProxy *proxy = expr->asNameProxy();
8.142 + assert(proxy);
8.143
8.144 - Symbol *sym = proxy->sym();
8.145 - if (!sym)
8.146 - return NULL;
8.147 + Symbol *sym = proxy->sym();
8.148 + if (!sym)
8.149 + return NULL;
8.150
8.151 - if (!sym->isType()) {
8.152 - cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
8.153 - return NULL;
8.154 + if (!sym->isType()) {
8.155 + cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars());
8.156 + return NULL;
8.157 + }
8.158 +
8.159 + type = sym->type();
8.160 }
8.161
8.162 - return sym->type();
8.163 + return zone_->types()->qualify(type, quals);
8.164 }
8.165
8.166 private:
9.1 --- a/src/compiler/Parser.cpp Tue Dec 25 18:13:02 2012 -0800
9.2 +++ b/src/compiler/Parser.cpp Wed Dec 26 17:14:12 2012 -0800
9.3 @@ -1044,7 +1044,7 @@
9.4 case TOK_NEW:
9.5 {
9.6 TypeQualifiers quals = (kind == TOK_CONST)
9.7 - ? TypeQual_UnkConst
9.8 + ? TypeQual_Const
9.9 : TypeQual_None;
9.10 scanner_.scan();
9.11 if ((statement = vars(quals)) == NULL)
9.12 @@ -1253,7 +1253,10 @@
9.13
9.14 if (!match(TOK_RPAREN)) {
9.15 while (true) {
9.16 - bool isConst = match(TOK_CONST);
9.17 + TypeQualifiers quals = TypeQual_None;
9.18 + if (match(TOK_CONST))
9.19 + quals = TypeQualifiers(quals | TypeQual_Const);
9.20 +
9.21 bool ref = match(TOK_AMPERSAND);
9.22
9.23 SourcePosition begin = scanner_.begin();
9.24 @@ -1263,7 +1266,7 @@
9.25 return NULL;
9.26
9.27 if (!name) {
9.28 - if (isConst || ref) {
9.29 + if ((quals & TypeQual_Const) || ref) {
9.30 cc_.reportError(begin, Message_InvalidVarArgs);
9.31 return NULL;
9.32 }
9.33 @@ -1289,7 +1292,7 @@
9.34 return NULL;
9.35 }
9.36
9.37 - Parameter *parameter = new (pool_) Parameter(name, type, ref, isConst, dims, expr, begin);
9.38 + Parameter *parameter = new (pool_) Parameter(name, type, ref, quals, dims, expr, begin);
9.39 if (!parameters->append(parameter))
9.40 return NULL;
9.41
9.42 @@ -1335,42 +1338,11 @@
9.43 return DeclareIntrinsicType(zone, scope, name, primitive);
9.44 }
9.45
9.46 -bool
9.47 -Parser::setupIntrinsics()
9.48 -{
9.49 -#if 0
9.50 - if (!DeclareIntrinsicType(zone_, scope_, "Float", PrimitiveType_Float))
9.51 - return false;
9.52 - if (!DeclareIntrinsicType(zone_, scope_, "_", PrimitiveType_Int32))
9.53 - return false;
9.54 - if (!DeclareIntrinsicType(zone_, scope_, "bool", PrimitiveType_Bool))
9.55 - return false;
9.56 - if (!DeclareIntrinsicType(zone_, scope_, "String", PrimitiveType_Char))
9.57 - return false;
9.58 -
9.59 - Local<Type> unchecked(zone_, zone_->types()->getUnchecked());
9.60 - if (!DeclareIntrinsicType(zone_, scope_, "unchecked", unchecked))
9.61 - return false;
9.62 -
9.63 - Local<Type> voidType(zone_, zone_->types()->getVoid());
9.64 - if (!DeclareIntrinsicType(zone_, scope_, "void", voidType))
9.65 - return false;
9.66 -
9.67 - Local<Type> intType(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
9.68 - if (!DeclareIntrinsicType(zone_, scope_, "int", intType))
9.69 - return false;
9.70 -#endif
9.71 - return true;
9.72 -}
9.73 -
9.74 ParseTree *
9.75 Parser::parse()
9.76 {
9.77 StatementList *statements = new (pool_) StatementList();
9.78
9.79 - if (!setupIntrinsics())
9.80 - return NULL;
9.81 -
9.82 for (;;) {
9.83 Statement *statement = NULL;
9.84
9.85 @@ -1412,7 +1384,7 @@
9.86 if (kind != TOK_LABEL)
9.87 scanner_.scan();
9.88 if (kind == TOK_PUBLIC && peek(TOK_CONST)) {
9.89 - if ((statement = var(TypeQual_UnkConst)) == NULL)
9.90 + if ((statement = var(TypeQual_Const)) == NULL)
9.91 return NULL;
9.92 if (!matchSemicolon())
9.93 return NULL;
9.94 @@ -1428,7 +1400,7 @@
9.95 case TOK_CONST:
9.96 case TOK_NEW:
9.97 {
9.98 - TypeQualifiers quals = (kind == TOK_NEW) ? TypeQual_UnkConst : TypeQual_None;
9.99 + TypeQualifiers quals = (kind == TOK_CONST) ? TypeQual_Const : TypeQual_None;
9.100 // Note: at global scope, we don't accept comma-delimited
9.101 // declarations yet, to see if we can get away with forcing
9.102 // a nicer top-level style.
10.1 --- a/src/compiler/Parser.h Tue Dec 25 18:13:02 2012 -0800
10.2 +++ b/src/compiler/Parser.h Wed Dec 26 17:14:12 2012 -0800
10.3 @@ -95,8 +95,6 @@
10.4 Statement *returnStatement();
10.5 ImportStatement *import();
10.6
10.7 - bool setupIntrinsics();
10.8 -
10.9 public:
10.10 Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length);
10.11
11.1 --- a/src/compiler/SemanticAnalysis.cpp Tue Dec 25 18:13:02 2012 -0800
11.2 +++ b/src/compiler/SemanticAnalysis.cpp Wed Dec 26 17:14:12 2012 -0800
11.3 @@ -731,6 +731,11 @@
11.4 if (!lval)
11.5 return;
11.6
11.7 + if (lval->type()->quals() & TypeQual_Const) {
11.8 + cc_.reportError(node->pos(), Message_CannotModifyConst);
11.9 + return;
11.10 + }
11.11 +
11.12 HIR *hir = eval(node->expression());
11.13 if ((hir = coerce(hir, lval->type(), Coerce_Assign)) == NULL)
11.14 return;
11.15 @@ -838,7 +843,7 @@
11.16 HIR *
11.17 SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
11.18 HIR *from,
11.19 - Handle<Type> argActual,
11.20 + Handle<ArrayType> argActual,
11.21 CoercionKind kind)
11.22 {
11.23 Local<Type> argGiven(zone_, from->type());
11.24 @@ -888,7 +893,7 @@
11.25 // We treat declaration separately from assignment, since for
11.26 // declaration we can just immediately use the cloned version.
11.27 bool shouldDuplicate = true;
11.28 - if (0 /*actual->isConst() :TODO */ ||
11.29 + if ((actual->quals() & TypeQual_Const) ||
11.30 (actual->isFixedLength() && kind == Coerce_Assign))
11.31 {
11.32 shouldDuplicate = false;
11.33 @@ -959,11 +964,18 @@
11.34 actual = ArrayType::cast(actual->contained());
11.35 }
11.36
11.37 + bool givenConst = !!(given->contained()->quals() & TypeQual_Const);
11.38 + bool actualConst = !!(actual->contained()->quals() & TypeQual_Const);
11.39 +
11.40 // These arrays must contain the same innermost type.
11.41 - if (given->contained() != actual->contained()) {
11.42 + if (given->contained()->unqualified() != actual->contained()->unqualified() ||
11.43 + (givenConst && !actualConst))
11.44 + {
11.45 + char aname[255];
11.46 + char gname[255];
11.47 cc_.reportError(pos, Message_TypeMismatch,
11.48 - GetTypeName(actual->contained()),
11.49 - GetTypeName(given->contained()));
11.50 + GetTypeName(argActual, aname, sizeof(aname)),
11.51 + GetTypeName(argGiven, gname, sizeof(gname)));
11.52 return false;
11.53 }
11.54
11.55 @@ -973,9 +985,11 @@
11.56 HIR *
11.57 SemanticAnalysis::typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to)
11.58 {
11.59 + char fname[255];
11.60 + char tname[255];
11.61 cc_.reportError(pos, Message_InvalidCoercion,
11.62 - GetTypeName(from),
11.63 - GetTypeName(to));
11.64 + GetTypeName(from, fname, sizeof(fname)),
11.65 + GetTypeName(to, tname, sizeof(tname)));
11.66 return NULL;
11.67 }
11.68
11.69 @@ -992,8 +1006,10 @@
11.70 if (to->isEnum() && *from != to)
11.71 return typeFailure(hir->node()->pos(), from, to);
11.72
11.73 - if (to->isArray())
11.74 - return typeCheckArray(SourcePosition(), hir, to, kind);
11.75 + if (to->isArray()) {
11.76 + Local<ArrayType> atype(zone_, ArrayType::cast(to));
11.77 + return typeCheckArray(hir->node()->pos(), hir, atype, kind);
11.78 + }
11.79
11.80 return hir;
11.81 }
12.1 --- a/src/compiler/SemanticAnalysis.h Tue Dec 25 18:13:02 2012 -0800
12.2 +++ b/src/compiler/SemanticAnalysis.h Wed Dec 26 17:14:12 2012 -0800
12.3 @@ -183,7 +183,7 @@
12.4
12.5 HIR *typeCheckArray(const SourcePosition &pos,
12.6 HIR *from,
12.7 - Handle<Type> argActual,
12.8 + Handle<ArrayType> argActual,
12.9 CoercionKind kind);
12.10
12.11 private:
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/tests/basic/const-arg-1.err Wed Dec 26 17:14:12 2012 -0800
13.3 @@ -0,0 +1,1 @@
13.4 + line 3, col 12: cannot change constant value or structure
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/tests/basic/const-arg-1.sp Wed Dec 26 17:14:12 2012 -0800
14.3 @@ -0,0 +1,4 @@
14.4 +f(const char:text[])
14.5 +{
14.6 + text[0] = 0;
14.7 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/tests/basic/const-arg-2.err Wed Dec 26 17:14:12 2012 -0800
15.3 @@ -0,0 +1,1 @@
15.4 + line 1, col 7: const parameters must be arrays or structs
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/tests/basic/const-arg-2.sp Wed Dec 26 17:14:12 2012 -0800
16.3 @@ -0,0 +1,3 @@
16.4 +f(const a)
16.5 +{
16.6 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/tests/basic/const-arg-3.err Wed Dec 26 17:14:12 2012 -0800
17.3 @@ -0,0 +1,1 @@
17.4 + line 1, col 7: constant outparams are not allowed
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/tests/basic/const-arg-3.sp Wed Dec 26 17:14:12 2012 -0800
18.3 @@ -0,0 +1,3 @@
18.4 +f(const &a)
18.5 +{
18.6 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/tests/basic/const-arg-4.err Wed Dec 26 17:14:12 2012 -0800
19.3 @@ -0,0 +1,1 @@
19.4 + line 8, col 7: type mismatch (expected 'char[]', got 'const char[]')
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/tests/basic/const-arg-4.sp Wed Dec 26 17:14:12 2012 -0800
20.3 @@ -0,0 +1,9 @@
20.4 +f(char:text[])
20.5 +{
20.6 +}
20.7 +
20.8 +main()
20.9 +{
20.10 + const char:text[] = "";
20.11 + f(text);
20.12 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/tests/basic/const-arg-5.out Wed Dec 26 17:14:12 2012 -0800
21.3 @@ -0,0 +1,1 @@
21.4 +9798
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/tests/basic/const-arg-5.sp Wed Dec 26 17:14:12 2012 -0800
22.3 @@ -0,0 +1,14 @@
22.4 +native PrintNum(num);
22.5 +
22.6 +
22.7 +f(const char:text[])
22.8 +{
22.9 + PrintNum(text[0]);
22.10 +}
22.11 +
22.12 +public main()
22.13 +{
22.14 + new char:q[20] = "blub";
22.15 + f("asdf");
22.16 + f(q);
22.17 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/tests/basic/const-global-1.err Wed Dec 26 17:14:12 2012 -0800
23.3 @@ -0,0 +1,1 @@
23.4 + line 4, col 7: cannot change constant value or structure
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/tests/basic/const-global-1.sp Wed Dec 26 17:14:12 2012 -0800
24.3 @@ -0,0 +1,5 @@
24.4 +const a = 5;
24.5 +public main()
24.6 +{
24.7 + a = 10;
24.8 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/tests/basic/const-global-2.err Wed Dec 26 17:14:12 2012 -0800
25.3 @@ -0,0 +1,1 @@
25.4 + line 5, col 12: cannot change constant value or structure
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/tests/basic/const-global-2.sp Wed Dec 26 17:14:12 2012 -0800
26.3 @@ -0,0 +1,6 @@
26.4 +const char:text[] = "Adsf";
26.5 +
26.6 +public main()
26.7 +{
26.8 + text[0] = 0;
26.9 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/tests/basic/const-global-3.err Wed Dec 26 17:14:12 2012 -0800
27.3 @@ -0,0 +1,1 @@
27.4 + line 4, col 10: cannot change constant value or structure
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/tests/basic/const-global-3.sp Wed Dec 26 17:14:12 2012 -0800
28.3 @@ -0,0 +1,5 @@
28.4 +const char:text[] = "";
28.5 +public main()
28.6 +{
28.7 + text = "a";
28.8 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/tests/basic/const-local-1.err Wed Dec 26 17:14:12 2012 -0800
29.3 @@ -0,0 +1,1 @@
29.4 + line 4, col 7: cannot change constant value or structure
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/tests/basic/const-local-1.sp Wed Dec 26 17:14:12 2012 -0800
30.3 @@ -0,0 +1,6 @@
30.4 +public main()
30.5 +{
30.6 + const a = 5;
30.7 + a = 10;
30.8 +}
30.9 +
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/tests/basic/const-local-2.err Wed Dec 26 17:14:12 2012 -0800
31.3 @@ -0,0 +1,1 @@
31.4 + line 4, col 12: cannot change constant value or structure
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/tests/basic/const-local-2.sp Wed Dec 26 17:14:12 2012 -0800
32.3 @@ -0,0 +1,5 @@
32.4 +public main()
32.5 +{
32.6 + const char:text[] = "hello, gabe newell!";
32.7 + text[5] = 10;
32.8 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/tests/basic/const-local-3.out Wed Dec 26 17:14:12 2012 -0800
33.3 @@ -0,0 +1,1 @@
33.4 +107
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/tests/basic/const-local-3.sp Wed Dec 26 17:14:12 2012 -0800
34.3 @@ -0,0 +1,9 @@
34.4 +native PrintNum(num);
34.5 +
34.6 +public main()
34.7 +{
34.8 + const char:a[] = "what";
34.9 + const char:b[] = "k";
34.10 + a = b;
34.11 + PrintNum(a[0]);
34.12 +}