# HG changeset patch # User David Anderson # Date 1356570852 28800 # Node ID 18f3010a358c984fc73e73d677c19cb1a18a0226 # Parent e3c851a14f166a8986a7c1e919743985124fe9a0 Implement |const| keyword. diff -r e3c851a14f16 -r 18f3010a358c src/API.cpp --- a/src/API.cpp Tue Dec 25 18:13:02 2012 -0800 +++ b/src/API.cpp Wed Dec 26 17:14:12 2012 -0800 @@ -295,9 +295,10 @@ for (unsigned i = 0; i < nparams; i++) { if (!CheckInvokeType(params[i], fun->argType(i))) { + char name[255]; ke::ZONE()->reportError(Message_TypeMismatchDuringInvoke, GetInvokeTypeName(params[i].type()), - GetTypeName(fun->argType(i))); + GetTypeName(fun->argType(i), name, sizeof(name))); return false; } } @@ -308,7 +309,9 @@ !returnType->isEnum() && !returnType->isVoid()) { - ke::ZONE()->reportError(Message_CannotInvokeReturnType, GetTypeName(returnType)); + char name[255]; + ke::ZONE()->reportError(Message_CannotInvokeReturnType, + GetTypeName(returnType, name, sizeof(name))); return false; } diff -r e3c851a14f16 -r 18f3010a358c src/Messages.tbl --- a/src/Messages.tbl Tue Dec 25 18:13:02 2012 -0800 +++ b/src/Messages.tbl Wed Dec 26 17:14:12 2012 -0800 @@ -41,7 +41,6 @@ MSG(ForwardDeclareMismatches, SyntaxError, "declaration does not match original forward signature") MSG(ArrayCantBeReference, SyntaxError, "this type cannot be used with a reference") MSG(ArraySizeMustBeConstant, SyntaxError, "array size must be a constant integer") -MSG(ReferenceIsConstant, SyntaxError, "cannot assign to a constant lvalue") MSG(MultiArrayInNative, SyntaxError, "multidimensional arrays cannot be passed to natives") MSG(InvalidVarArgs, SyntaxError, "varargs cannot be const or ref") MSG(VarArgsOutsideNative, SyntaxError, "variadic arguments can only be specified on natives") @@ -80,4 +79,7 @@ MSG(ImportsMustBeFirst, SyntaxError, "import statements must come before other statements") MSG(ImportedNameAlreadyBound, TypeError, "imported name has already been bound") MSG(CannotResolveImport, TypeError, "cannot resolve import %s") -MSG(InvalidCoercion, TypeError, "cannot coerce type '%s' to type '%s'") \ No newline at end of file +MSG(InvalidCoercion, TypeError, "cannot coerce type '%s' to type '%s'") +MSG(CannotConstReference, TypeError, "constant outparams are not allowed") +MSG(CannotModifyConst, TypeError, "cannot change constant value or structure") +MSG(InvalidConstOnFormal, TypeError, "const parameters must be arrays or structs") \ No newline at end of file diff -r e3c851a14f16 -r 18f3010a358c src/Structures.cpp --- a/src/Structures.cpp Tue Dec 25 18:13:02 2012 -0800 +++ b/src/Structures.cpp Wed Dec 26 17:14:12 2012 -0800 @@ -133,14 +133,16 @@ childStructMap = StructMap::cast(StructType::cast(desc->type())->newMap()); child = Struct::New(zone, childStructMap, tenure); } else if (desc->type()->isArray()) { - assert(false); -#if 0 - childArrayMap = ArrayMap::cast(desc->type()->newMap()); - if (desc->type()->isFixedLength()) + // :TODO: don't create empty arrays for ref slots here. + // Instead, make a separate Initialize function, so we + // can avoid double-creating arrays for module globals. + // (const char:x[] = "x") + ArrayType *type = ArrayType::cast(desc->type()); + childArrayMap = ArrayMap::cast(type->newMap()); + if (type->isFixedLength()) child = Array::NewFixed(zone, childArrayMap, tenure); else child = Array::NewEmpty(zone, childArrayMap, tenure); -#endif } if (!child) return NULL; diff -r e3c851a14f16 -r 18f3010a358c src/TypeManager.cpp --- a/src/TypeManager.cpp Tue Dec 25 18:13:02 2012 -0800 +++ b/src/TypeManager.cpp Wed Dec 26 17:14:12 2012 -0800 @@ -102,9 +102,12 @@ } Type * -TypeManager::qualify(Handle type, TypeQualifiers quals) +TypeManager::qualify(Handle argType, TypeQualifiers quals) { - assert(!type->hasTypeQualifiers()); + Local type(zone_, argType->unqualified()); + + if (!quals) + return type; LookupKey key(type, quals); diff -r e3c851a14f16 -r 18f3010a358c src/Types.cpp --- a/src/Types.cpp Tue Dec 25 18:13:02 2012 -0800 +++ b/src/Types.cpp Wed Dec 26 17:14:12 2012 -0800 @@ -218,32 +218,84 @@ return type; } -// :TODO: this leaks an interior pointer. -const char * -ke::GetTypeName(Type *type) +static size_t +FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap) +{ + size_t len = vsnprintf(buffer, maxlen, text, ap); + if (len >= maxlen) { + buffer[maxlen - 1] = '\0'; + return maxlen - 1; + } + return len; +} + +static size_t +Format(char *buffer, size_t maxlen, const char *text, ...) { - if (type->isArray()) - return "array"; + va_list ap; + va_start(ap, text); + size_t len = FormatVA(buffer, maxlen, text, ap); + va_end(ap); + return len; +} + +static size_t +FormatTypeName(Type *type, char *buffer, size_t maxlen) +{ + if (type->isArray()) { + ArrayType *atype = ArrayType::cast(type); + Type *innermost = atype->innermost(); + + size_t len = FormatTypeName(innermost, buffer, maxlen); + for (;;) { + if (atype->isFixedLength()) + len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength()); + else + len += Format(buffer + len, maxlen - len, "[]"); + if (!atype->contained()->isArray()) + break; + atype = ArrayType::cast(atype->contained()); + } + return len; + } + if (type->hasTypeQualifiers()) { + size_t len = 0; + if (type->quals() & TypeQual_Const) + len += Format(buffer, maxlen, "const "); + return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len); + } if (type->isFunction()) - return "function"; + return Format(buffer, maxlen, "function"); if (type->isVoid()) - return "void"; + return Format(buffer, maxlen, "void"); + if (type->isUnchecked()) + return Format(buffer, maxlen, "unchecked"); if (type->isEnum()) - return EnumType::cast(type)->name()->chars(); + return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars()); if (type->isStruct()) - return StructType::cast(type)->name()->chars(); - if (type->isReference()) - type = ReferenceType::cast(type)->contained(); + return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars()); + if (type->isReference()) { + ReferenceType *ref = ReferenceType::cast(type); + size_t len = Format(buffer, maxlen, "&"); + return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len); + } switch (type->primitive()) { case PrimitiveType_Bool: - return "bool"; + return Format(buffer, maxlen, "bool"); case PrimitiveType_Char: - return "String"; + return Format(buffer, maxlen, "char"); case PrimitiveType_Int32: - return "int"; + return Format(buffer, maxlen, "int"); case PrimitiveType_Float: - return "Float"; + return Format(buffer, maxlen, "float"); default: - return ""; + return Format(buffer, maxlen, ""); } } + +const char * +ke::GetTypeName(Type *type, char *buffer, size_t maxlen) +{ + FormatTypeName(type, buffer, maxlen); + return buffer; +} diff -r e3c851a14f16 -r 18f3010a358c src/Types.h --- a/src/Types.h Tue Dec 25 18:13:02 2012 -0800 +++ b/src/Types.h Wed Dec 26 17:14:12 2012 -0800 @@ -64,34 +64,8 @@ { TypeQual_None = 0, - // Const qualifier that has not been determined yet. - TypeQual_UnkConst = (1 << 0), - - // For simplification, SP2 differentiates between two meanings of const. - // "StoreConst" means that the value itself may not be changed. For - // example, - // const a = 5; - // - // Specifies that the storage of "a" is immutable. - // - // In addition, "RefConst" means that the memory at a reference may not - // be changed. For example, - // - // const char:text[] = "asdfasdfasdf"; - // - // Specifies a readonly view of a character array, however, |text| itself - // may be repointed to another readonly character array. - // - // The meaning of "const" is inferred based on the scope and type: - // - // +---------+---------+-------+ - // | Array | Struct | Other | - // +---------------+---------+---------+-------+ - // | GLOBAL/STATIC | Ref|Str | Ref|Str | Str | - // | LOCAL | Ref | Ref|Str | Str | - // +---------------+---------+---------+-------+ - TypeQual_StoreConst = (1 << 1), - TypeQual_RefConst = (1 << 2) + // Values of this type cannot be modified. + TypeQual_Const = (1 << 2) }; class Type : public Object @@ -233,7 +207,7 @@ } TypeQualifiers quals() { - if (hasTypeQualifiers()) + if (!hasTypeQualifiers()) return TypeQual_None; return quals_; } @@ -544,7 +518,7 @@ } }; -const char *GetTypeName(Type *type); +const char *GetTypeName(Type *type, char *buffer, size_t maxlen); } diff -r e3c851a14f16 -r 18f3010a358c src/compiler/AST.h --- a/src/compiler/AST.h Tue Dec 25 18:13:02 2012 -0800 +++ b/src/compiler/AST.h Wed Dec 26 17:14:12 2012 -0800 @@ -193,6 +193,9 @@ ExpressionList *dims() const { return dims_; } + TypeQualifiers quals() const { + return qual_; + } }; class Parameter : public PoolObject @@ -200,23 +203,23 @@ ScopedRoot name_; Expression *type_; bool reference_; - bool const_; Expression *initializer_; VariableSymbol *sym_; SourcePosition pos_; ExpressionList *dims_; + TypeQualifiers quals_; public: - Parameter(Handle name, Expression *type, bool reference, bool isConst, + Parameter(Handle name, Expression *type, bool reference, TypeQualifiers quals, ExpressionList *dims, Expression *initializer, const SourcePosition &pos) : name_(name), type_(type), reference_(reference), - const_(isConst), initializer_(initializer), sym_(NULL), pos_(pos), - dims_(dims) + dims_(dims), + quals_(quals) { } @@ -229,8 +232,8 @@ bool reference() const { return reference_; } - bool isConst() const { - return const_; + TypeQualifiers quals() const { + return quals_; } ExpressionList *dims() const { return dims_; diff -r e3c851a14f16 -r 18f3010a358c src/compiler/NameBinding.cpp --- a/src/compiler/NameBinding.cpp Tue Dec 25 18:13:02 2012 -0800 +++ b/src/compiler/NameBinding.cpp Wed Dec 26 17:14:12 2012 -0800 @@ -543,11 +543,14 @@ if (node->initialization()) node->initialization()->accept(this); - Local type(zone_, bindType(node->type())); + Local type(zone_, bindType(node->type(), node->quals())); if (!type) return; - if (node->dims() || type->isArray()) { + // We don't allow array typedefs yet. + assert(!type->isArray()); + + if (node->dims()) { int dims[MAX_ARRAY_DEPTH]; int levels = evaluateDimensions(node->pos(), type, node->dims(), dims); if (levels < 0) @@ -568,11 +571,25 @@ // If we got extra dimensions, we need to build a new type. if (node->dims()) { - if ((type = buildArrayType(type, dims, node->dims()->length())) == NULL) + if ((type = buildArrayType(type, node->quals(), dims, node->dims()->length())) == NULL) return; } } + // If we're in global scope, and we received a |const| qualifier, then + // we extend this to array reference as well. This is to sort of mimic + // SP1 functionality, but also means that you cannot have changeable + // const pointers in global scope. + if ((node->quals() & TypeQual_Const) && + type->isArray() && + link_->scope()->kind() == Scope::GLOBAL) + { + if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL) + return; + if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL) + return; + } + // If the node already has a symbol (meaning it was a global), then // we don't have to do anything more. if (node->sym()) { @@ -817,15 +834,17 @@ return true; } - ArrayType *buildArrayType(Handle contained, int dims[MAX_ARRAY_DEPTH], size_t postlevels) { + ArrayType *buildArrayType(Handle contained, TypeQualifiers quals, int dims[MAX_ARRAY_DEPTH], size_t postlevels) { Local type(zone_, contained); + for (size_t i = postlevels - 1; i < postlevels; i--) { int size = dims[i] > 0 ? dims[i] : ArrayType::DYNAMIC_ARRAY_SIZE; - type = zone_->types()->newArray(contained, size); - if (!type) + if ((type = zone_->types()->newArray(contained, size)) == NULL) + return NULL; + if ((type = zone_->types()->qualify(type, quals)) == NULL) return NULL; } return ArrayType::cast(type); @@ -834,7 +853,7 @@ bool fillFunctionType(Handle fun, const FunctionSignature &sig) { Local type(zone_); if (!fun->returnType()) { - if ((type = bindType(sig.returnType())) == NULL) + if ((type = bindType(sig.returnType(), TypeQual_None)) == NULL) return false; fun->setReturnType(type); } @@ -845,10 +864,12 @@ for (size_t i = 0; i < sig.parameters()->length(); i++) { Parameter *param = sig.parameters()->at(i); - if ((type = bindType(param->type())) == NULL) + if ((type = bindType(param->type(), param->quals())) == NULL) return false; - if (type->isArray() || param->dims()) { + assert(!type->isArray()); + + if (param->dims()) { int dims[MAX_ARRAY_DEPTH]; int levels = evaluateDimensions(param->pos(), type, param->dims(), dims); if (levels < 0) @@ -858,7 +879,7 @@ // Unlike variables, we do not infer anything about array // sizes from its default initializer. if (param->dims()) { - if ((type = buildArrayType(type, dims, param->dims()->length())) == NULL) + if ((type = buildArrayType(type, param->quals(), dims, param->dims()->length())) == NULL) return false; } @@ -873,9 +894,19 @@ cc_.reportError(param->pos(), Message_ArrayCantBeReference); return false; } + if (param->quals() & TypeQual_Const) { + cc_.reportError(param->pos(), Message_CannotConstReference); + return false; + } if ((type = zone_->types()->getReference(type, false)) == NULL) return false; } + if (param->quals() & TypeQual_Const) { + if (!type->isArray() && !type->isStruct()) { + cc_.reportError(param->pos(), Message_InvalidConstOnFormal); + return false; + } + } if (type->isVoid()) { cc_.reportError(param->type()->pos(), Message_CannotDeclareVoid); @@ -891,27 +922,31 @@ return true; } - Type *bindType(Expression *expr) { + Type *bindType(Expression *expr, TypeQualifiers quals) { + Local type(zone_); + if (!expr) { // If no type was declared, we return int32. - return zone_->types()->getPrimitive(PrimitiveType_Int32); - } - - expr->accept(this); + type = zone_->types()->getPrimitive(PrimitiveType_Int32); + } else { + expr->accept(this); - NameProxy *proxy = expr->asNameProxy(); - assert(proxy); + NameProxy *proxy = expr->asNameProxy(); + assert(proxy); - Symbol *sym = proxy->sym(); - if (!sym) - return NULL; + Symbol *sym = proxy->sym(); + if (!sym) + return NULL; - if (!sym->isType()) { - cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars()); - return NULL; + if (!sym->isType()) { + cc_.reportError(expr->pos(), Message_IdentifierIsNotAType, sym->name()->chars()); + return NULL; + } + + type = sym->type(); } - return sym->type(); + return zone_->types()->qualify(type, quals); } private: diff -r e3c851a14f16 -r 18f3010a358c src/compiler/Parser.cpp --- a/src/compiler/Parser.cpp Tue Dec 25 18:13:02 2012 -0800 +++ b/src/compiler/Parser.cpp Wed Dec 26 17:14:12 2012 -0800 @@ -1044,7 +1044,7 @@ case TOK_NEW: { TypeQualifiers quals = (kind == TOK_CONST) - ? TypeQual_UnkConst + ? TypeQual_Const : TypeQual_None; scanner_.scan(); if ((statement = vars(quals)) == NULL) @@ -1253,7 +1253,10 @@ if (!match(TOK_RPAREN)) { while (true) { - bool isConst = match(TOK_CONST); + TypeQualifiers quals = TypeQual_None; + if (match(TOK_CONST)) + quals = TypeQualifiers(quals | TypeQual_Const); + bool ref = match(TOK_AMPERSAND); SourcePosition begin = scanner_.begin(); @@ -1263,7 +1266,7 @@ return NULL; if (!name) { - if (isConst || ref) { + if ((quals & TypeQual_Const) || ref) { cc_.reportError(begin, Message_InvalidVarArgs); return NULL; } @@ -1289,7 +1292,7 @@ return NULL; } - Parameter *parameter = new (pool_) Parameter(name, type, ref, isConst, dims, expr, begin); + Parameter *parameter = new (pool_) Parameter(name, type, ref, quals, dims, expr, begin); if (!parameters->append(parameter)) return NULL; @@ -1335,42 +1338,11 @@ return DeclareIntrinsicType(zone, scope, name, primitive); } -bool -Parser::setupIntrinsics() -{ -#if 0 - if (!DeclareIntrinsicType(zone_, scope_, "Float", PrimitiveType_Float)) - return false; - if (!DeclareIntrinsicType(zone_, scope_, "_", PrimitiveType_Int32)) - return false; - if (!DeclareIntrinsicType(zone_, scope_, "bool", PrimitiveType_Bool)) - return false; - if (!DeclareIntrinsicType(zone_, scope_, "String", PrimitiveType_Char)) - return false; - - Local unchecked(zone_, zone_->types()->getUnchecked()); - if (!DeclareIntrinsicType(zone_, scope_, "unchecked", unchecked)) - return false; - - Local voidType(zone_, zone_->types()->getVoid()); - if (!DeclareIntrinsicType(zone_, scope_, "void", voidType)) - return false; - - Local intType(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32)); - if (!DeclareIntrinsicType(zone_, scope_, "int", intType)) - return false; -#endif - return true; -} - ParseTree * Parser::parse() { StatementList *statements = new (pool_) StatementList(); - if (!setupIntrinsics()) - return NULL; - for (;;) { Statement *statement = NULL; @@ -1412,7 +1384,7 @@ if (kind != TOK_LABEL) scanner_.scan(); if (kind == TOK_PUBLIC && peek(TOK_CONST)) { - if ((statement = var(TypeQual_UnkConst)) == NULL) + if ((statement = var(TypeQual_Const)) == NULL) return NULL; if (!matchSemicolon()) return NULL; @@ -1428,7 +1400,7 @@ case TOK_CONST: case TOK_NEW: { - TypeQualifiers quals = (kind == TOK_NEW) ? TypeQual_UnkConst : TypeQual_None; + TypeQualifiers quals = (kind == TOK_CONST) ? TypeQual_Const : TypeQual_None; // Note: at global scope, we don't accept comma-delimited // declarations yet, to see if we can get away with forcing // a nicer top-level style. diff -r e3c851a14f16 -r 18f3010a358c src/compiler/Parser.h --- a/src/compiler/Parser.h Tue Dec 25 18:13:02 2012 -0800 +++ b/src/compiler/Parser.h Wed Dec 26 17:14:12 2012 -0800 @@ -95,8 +95,6 @@ Statement *returnStatement(); ImportStatement *import(); - bool setupIntrinsics(); - public: Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length); diff -r e3c851a14f16 -r 18f3010a358c src/compiler/SemanticAnalysis.cpp --- a/src/compiler/SemanticAnalysis.cpp Tue Dec 25 18:13:02 2012 -0800 +++ b/src/compiler/SemanticAnalysis.cpp Wed Dec 26 17:14:12 2012 -0800 @@ -731,6 +731,11 @@ if (!lval) return; + if (lval->type()->quals() & TypeQual_Const) { + cc_.reportError(node->pos(), Message_CannotModifyConst); + return; + } + HIR *hir = eval(node->expression()); if ((hir = coerce(hir, lval->type(), Coerce_Assign)) == NULL) return; @@ -838,7 +843,7 @@ HIR * SemanticAnalysis::typeCheckArray(const SourcePosition &pos, HIR *from, - Handle argActual, + Handle argActual, CoercionKind kind) { Local argGiven(zone_, from->type()); @@ -888,7 +893,7 @@ // We treat declaration separately from assignment, since for // declaration we can just immediately use the cloned version. bool shouldDuplicate = true; - if (0 /*actual->isConst() :TODO */ || + if ((actual->quals() & TypeQual_Const) || (actual->isFixedLength() && kind == Coerce_Assign)) { shouldDuplicate = false; @@ -959,11 +964,18 @@ actual = ArrayType::cast(actual->contained()); } + bool givenConst = !!(given->contained()->quals() & TypeQual_Const); + bool actualConst = !!(actual->contained()->quals() & TypeQual_Const); + // These arrays must contain the same innermost type. - if (given->contained() != actual->contained()) { + if (given->contained()->unqualified() != actual->contained()->unqualified() || + (givenConst && !actualConst)) + { + char aname[255]; + char gname[255]; cc_.reportError(pos, Message_TypeMismatch, - GetTypeName(actual->contained()), - GetTypeName(given->contained())); + GetTypeName(argActual, aname, sizeof(aname)), + GetTypeName(argGiven, gname, sizeof(gname))); return false; } @@ -973,9 +985,11 @@ HIR * SemanticAnalysis::typeFailure(const SourcePosition &pos, Handle from, Handle to) { + char fname[255]; + char tname[255]; cc_.reportError(pos, Message_InvalidCoercion, - GetTypeName(from), - GetTypeName(to)); + GetTypeName(from, fname, sizeof(fname)), + GetTypeName(to, tname, sizeof(tname))); return NULL; } @@ -992,8 +1006,10 @@ if (to->isEnum() && *from != to) return typeFailure(hir->node()->pos(), from, to); - if (to->isArray()) - return typeCheckArray(SourcePosition(), hir, to, kind); + if (to->isArray()) { + Local atype(zone_, ArrayType::cast(to)); + return typeCheckArray(hir->node()->pos(), hir, atype, kind); + } return hir; } diff -r e3c851a14f16 -r 18f3010a358c src/compiler/SemanticAnalysis.h --- a/src/compiler/SemanticAnalysis.h Tue Dec 25 18:13:02 2012 -0800 +++ b/src/compiler/SemanticAnalysis.h Wed Dec 26 17:14:12 2012 -0800 @@ -183,7 +183,7 @@ HIR *typeCheckArray(const SourcePosition &pos, HIR *from, - Handle argActual, + Handle argActual, CoercionKind kind); private: diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-1.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-1.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 3, col 12: cannot change constant value or structure diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-1.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-1.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,4 @@ +f(const char:text[]) +{ + text[0] = 0; +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-2.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-2.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 1, col 7: const parameters must be arrays or structs diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-2.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-2.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,3 @@ +f(const a) +{ +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-3.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-3.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 1, col 7: constant outparams are not allowed diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-3.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-3.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,3 @@ +f(const &a) +{ +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-4.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-4.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 8, col 7: type mismatch (expected 'char[]', got 'const char[]') diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-4.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-4.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,9 @@ +f(char:text[]) +{ +} + +main() +{ + const char:text[] = ""; + f(text); +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-5.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-5.out Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ +9798 diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-arg-5.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-arg-5.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,14 @@ +native PrintNum(num); + + +f(const char:text[]) +{ + PrintNum(text[0]); +} + +public main() +{ + new char:q[20] = "blub"; + f("asdf"); + f(q); +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-global-1.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-global-1.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 4, col 7: cannot change constant value or structure diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-global-1.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-global-1.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,5 @@ +const a = 5; +public main() +{ + a = 10; +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-global-2.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-global-2.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 5, col 12: cannot change constant value or structure diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-global-2.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-global-2.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,6 @@ +const char:text[] = "Adsf"; + +public main() +{ + text[0] = 0; +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-global-3.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-global-3.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 4, col 10: cannot change constant value or structure diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-global-3.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-global-3.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,5 @@ +const char:text[] = ""; +public main() +{ + text = "a"; +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-local-1.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-local-1.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 4, col 7: cannot change constant value or structure diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-local-1.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-local-1.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,6 @@ +public main() +{ + const a = 5; + a = 10; +} + diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-local-2.err --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-local-2.err Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ + line 4, col 12: cannot change constant value or structure diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-local-2.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-local-2.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,5 @@ +public main() +{ + const char:text[] = "hello, gabe newell!"; + text[5] = 10; +} diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-local-3.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-local-3.out Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,1 @@ +107 diff -r e3c851a14f16 -r 18f3010a358c tests/basic/const-local-3.sp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/basic/const-local-3.sp Wed Dec 26 17:14:12 2012 -0800 @@ -0,0 +1,9 @@ +native PrintNum(num); + +public main() +{ + const char:a[] = "what"; + const char:b[] = "k"; + a = b; + PrintNum(a[0]); +}