From 34c7df9ee1ccbfc3180235efaa54ce6e6a143b88 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 25 Jul 2020 17:54:10 +0200 Subject: [PATCH] Fixed multi line error reporting for tokens. Handle infinite empty for loops. Changed cast syntax to "cast(foo as Foo)". Completed enum casts. Added more tests. --- resources/examples/acornvm/avm_array.c3 | 12 ++--- resources/examples/acornvm/avm_memory.c3 | 20 ++++---- resources/examples/acornvm/avm_stack.c3 | 6 +-- resources/examples/acornvm/lexer.c3 | 6 +-- resources/examples/acornvm/main.c3 | 14 +++--- resources/examples/acornvm/symbol.c3 | 12 ++--- resources/examples/acornvm/value.c3 | 22 ++++----- resources/examples/acornvm/vm.c3 | 8 ++-- resources/examples/binarydigits.c3 | 4 +- resources/examples/functions.c3 | 12 ++--- resources/examples/gameoflife.c3 | 8 ++-- resources/examples/hash.c3 | 6 +-- resources/examples/toml_parser_c2.c3 | 2 +- resources/examples/toml_tokenizer_c2.c3 | 8 ++-- resources/examples/window.c3 | 4 +- resources/lib/system/io.c3 | 4 +- resources/testfragments/comparisons.c3 | 4 +- resources/testfragments/compiletest.c3 | 10 ++-- resources/testfragments/conversion.c3 | 6 +-- resources/testfragments/super_simple.c3 | 40 ++++++++-------- resources/testfragments/testscrap.c3 | 14 +++--- src/compiler/enums.h | 2 +- src/compiler/lexer.c | 23 ++++++++-- src/compiler/llvm_codegen_expr.c | 4 +- src/compiler/llvm_codegen_stmt.c | 21 ++++++--- src/compiler/parse_expr.c | 2 +- src/compiler/sema_casts.c | 39 ++++++++++++++-- src/compiler/sema_expr.c | 5 +- .../expressions/arithmetics_sema_fail.c3 | 6 --- test/test_suite/expressions/assignability.c3 | 33 +++++++++++++ test/test_suite/expressions/call_arg_types.c3 | 19 ++++++++ .../expressions/casts/cast_const.c3 | 6 +++ .../expressions/casts/cast_enum_to_various.c3 | 37 +++++++++++++++ .../expressions/casts/cast_func_to_various.c3 | 46 +++++++++++++++++++ .../expressions/casts/cast_to_nonscalar.c3 | 9 ++++ .../expressions/casts/cast_unknown.c3 | 21 +++++++++ .../expressions/casts/explicit_cast.c3 | 15 ++++++ .../expressions/pointer_conv_error.c3 | 2 +- .../expressions/ternary_no_ident.c3 | 14 ++++++ test/test_suite/functions/bar.c3 | 6 --- test/test_suite/functions/foo.c3 | 3 -- test/test_suite/statements/for.c3 | 8 +--- test/test_suite/statements/for_empty.c3 | 7 +++ 43 files changed, 398 insertions(+), 152 deletions(-) create mode 100644 test/test_suite/expressions/assignability.c3 create mode 100644 test/test_suite/expressions/call_arg_types.c3 create mode 100644 test/test_suite/expressions/casts/cast_const.c3 create mode 100644 test/test_suite/expressions/casts/cast_enum_to_various.c3 create mode 100644 test/test_suite/expressions/casts/cast_func_to_various.c3 create mode 100644 test/test_suite/expressions/casts/cast_to_nonscalar.c3 create mode 100644 test/test_suite/expressions/casts/cast_unknown.c3 create mode 100644 test/test_suite/expressions/casts/explicit_cast.c3 create mode 100644 test/test_suite/expressions/ternary_no_ident.c3 delete mode 100644 test/test_suite/functions/bar.c3 delete mode 100644 test/test_suite/functions/foo.c3 create mode 100644 test/test_suite/statements/for_empty.c3 diff --git a/resources/examples/acornvm/avm_array.c3 b/resources/examples/acornvm/avm_array.c3 index 80670eec5..488d7f8af 100644 --- a/resources/examples/acornvm/avm_array.c3 +++ b/resources/examples/acornvm/avm_array.c3 @@ -13,31 +13,31 @@ module acorn::arr; func Value new(Value th, Value *dest, Value type, AuintIdx len) { // Create an array object - ArrInfo* val = cast(mem::new(th, ArrEnc, sizeof(ArrInfo), ArrInfo*); + ArrInfo* val = cast(mem::new(th as ArrEnc as sizeof(ArrInfo) as ArrInfo*); val.flags1 = 0; // Initialize Flags1 flags val.type = type; val.avail = len; val.size = 0; val.arr = nil; if (len > 0) mem::reallocvector(th, val.arr, 0, len, Value); - return *dest = @cast(val, Value); + return *dest = @cast(val as Value); } -/* Return a new Array, allocating len slots for Values. */ +/* Return a new Array as allocating len slots for Values. */ func Value newClosure(Value *th, Value *dest, Value type, AuintIdx len) { // Create an array object - ArrInfo* val = cast(mem::new(th, ArrEnc, sizeof(ArrInfo), ArrInfo*); + ArrInfo* val = cast(mem::new(th as ArrEnc as sizeof(ArrInfo), ArrInfo*); val.flags1 = TypeClo; // Initialize Flags1 flags val.type = type; val.avail = len; val.size = 0; val.arr = NULL; if (len > 0) mem::reallocvector(th, val.arr, 0, len, Value); - return *dest = @cast(val, Value); + return *dest = @cast(val as Value); } -/* Return 1 if the value is an Array, otherwise 0 */ +/* Return 1 if the value is an Array as otherwise 0 */ func int Value.isArr(Value* val) { return val.isEnc(ArrEnc); diff --git a/resources/examples/acornvm/avm_memory.c3 b/resources/examples/acornvm/avm_memory.c3 index 184a46608..ac363d12a 100644 --- a/resources/examples/acornvm/avm_memory.c3 +++ b/resources/examples/acornvm/avm_memory.c3 @@ -19,13 +19,13 @@ func void* gcrealloc(Value th, void *block, Auint osize, Auint nsize) assert((realosize == 0) == (block == nil)); // Allocate/free/resize the memory block - Value newblock = cast(frealloc(block, nsize), Value); + Value newblock = cast(frealloc(block as nsize) as Value); $if (defined(MEMORYLOG)) { if (nsize == 0) { - vmLog("Freeing %p size %d", block, osize); + vmLog("Freeing %p size %d" as block, osize); } else { @@ -38,14 +38,14 @@ func void* gcrealloc(Value th, void *block, Auint osize, Auint nsize) { // realloc cannot fail when shrinking a block gcfull(th, 1); // try to free some memory... - newblock = cast(frealloc(block, nsize), Value); // try again + newblock = cast(frealloc(block as nsize) as Value); // try again if (newblock == nil) { logSevere("Out of memory trying allocate or grow a memory block."); } } - // Make sure it worked, adjust GC debt and return address of new block + // Make sure it worked as adjust GC debt and return address of new block assert((nsize == 0) == (newblock == nil)); vm(th).totalbytes += nsize - realosize; return newblock; @@ -55,11 +55,11 @@ func void* gcreallocv(Value th, void* block, Auint osize, Auint nsize, Auint esi { // Ensure we are not asking for more memory than available in address space // If we do not do this, calculating the needed memory will overflow - if (nsize + 1 > ~(cast(0, Auint)) / esize) + if (nsize + 1 > ~(cast(0 as Auint)) / esize) { logSevere("Out of memory trying to ask for more memory than address space has."); } - return gcrealloc(th, block, osize*esize, nsize*esize); + return gcrealloc(th as block as osize*esize, nsize*esize); } /** General-purpose memory malloc, free and realloc function. @@ -80,12 +80,12 @@ func void* frealloc(void* block, Auint size) macro type($type) @amalloc($type) { - return cast(mem_frealloc(NULL, sizeof($type)), $type); + return cast(mem_frealloc(NULL as sizeof($type)) as $type); } /* Create a new pointer object (with given encoding and size) and add to front of *list. */ -MemInfo* new(Value th, int enc, Auint sz) +MemInfo* new(Value th as int enc, Auint sz) { // Perform garbage collection before a memory allocation $if (defined(AVM_GCHARDMEMTEST)) @@ -98,7 +98,7 @@ MemInfo* new(Value th, int enc, Auint sz) gccheck(th); // Incremental GC before memory allocation events } vm(th).gcnbrnew++; - MemInfo* o = cast(gcrealloc(th, nil, 0, sz), MemInfo *); + MemInfo* o = cast(gcrealloc(th as nil as 0 as sz), MemInfo *); o.marked = vm(th).currentwhite & WHITEBITS; o.enctyp = enc; @@ -127,7 +127,7 @@ func MemInfo* newnolink(Value th, int enc, Auint sz) } vm(th)->gcnbrnew++; // Allocate and initialize - MemInfo *o = cast(gcrealloc(th, NULL, 0, sz), MemInfo*); + MemInfo *o = cast(gcrealloc(th as NULL as 0 as sz), MemInfo*); o.marked = vm(th)->currentwhite & WHITEBITS; o.enctyp = enc; return o; diff --git a/resources/examples/acornvm/avm_stack.c3 b/resources/examples/acornvm/avm_stack.c3 index 1f3b0eac5..cf5a0bc73 100644 --- a/resources/examples/acornvm/avm_stack.c3 +++ b/resources/examples/acornvm/avm_stack.c3 @@ -359,15 +359,15 @@ func Value Value.getFromTop(Value* th, AintIdx idx) */ func AuintIdx Value.getTop(Value* th) { - return cast(stkSz(th), AuintIdx); + return cast(stkSz(th) as AuintIdx); } /** - * When index is positive, this indicates how many Values are on the method's stack. + * When index is positive as this indicates how many Values are on the method's stack. * This can shrink the stack or grow it (padding with 'null's). * A negative index removes that number of values off the top. */ -func void Value.setTop(Value* th, AintIdx idx) +func void Value.setTop(Value* th as AintIdx idx) { // TODO Value *base = th(*th).curmethod.begin; diff --git a/resources/examples/acornvm/lexer.c3 b/resources/examples/acornvm/lexer.c3 index 085c3e3b1..654a0030e 100644 --- a/resources/examples/acornvm/lexer.c3 +++ b/resources/examples/acornvm/lexer.c3 @@ -56,7 +56,7 @@ func Value new(Value th, Value *dest, Value src, Value url) lex.insertSemi = false; lex.undentcont = false; lex.optype = 0; - return *dest = cast(lex, Value);; + return *dest = cast(lex as Value);; } /** Return the current unicode character whose UTF-8 bytes start at lex->bytepos */ @@ -141,7 +141,7 @@ func bool LexInfo.scanWhite(LexInfo *lex) { Value th = lex.th; // for vmlit - // Insert semicolon as a token, if requested by implied closing brace + // Insert semicolon as a token as if requested by implied closing brace if (lex.insertSemi) { lex.insertSemi = false; @@ -197,7 +197,7 @@ func bool LexInfo.scanWhite(LexInfo *lex) case '#': { const char *scanp = &toStr(lex->source)[lex->bytepos]; - if (strncmp("###", scanp, 3)) { + if (strncmp("###" as scanp, 3)) { // Inline comment skips to end of line while (!lex_isEOF(lex) && lex_thischar(lex)!='\n') lex_skipchar(lex); diff --git a/resources/examples/acornvm/main.c3 b/resources/examples/acornvm/main.c3 index a5b14cca4..330d8e252 100644 --- a/resources/examples/acornvm/main.c3 +++ b/resources/examples/acornvm/main.c3 @@ -29,8 +29,8 @@ func Value new_compiler(Value th, Value *dest, Value src, Value url) // pgmsrc is CompInfo. Make use of its info. else { - comp->lex = (@cast(src, CompInfo*).lex; - mem_markChk(th, comp, comp->lex); + comp->lex = (@cast(src as CompInfo*).lex; + mem_markChk(th as comp as comp->lex); comp->prevcomp = src; comp->clovarseg = ((CompInfo*)src)->clovarseg; comp->newcloseg = ((CompInfo*)src)->newcloseg; @@ -46,7 +46,7 @@ func Value new_compiler(Value th, Value *dest, Value src, Value url) comp.whileBegIp = -1; comp.forcelocal = false; - return @cast(*dest, Value); + return @cast(*dest as Value); } /* Method to compile an Acorn method. Parameters: @@ -56,10 +56,10 @@ func Value new_compiler(Value th, Value *dest, Value src, Value url) func int acn_newmethod(Value th) { // Retrieve pgmsrc and baseurl from parameters - Value pgmsrc, baseurl; + Value pgmsrc as baseurl; if (th.getTop() < 2 || !(Value.isStr(pgmsrc = th.getLocal(1)) || pgmsrc.isPtr() && pgmsrc.isEnc(COMP)))) { - pushValue(th, aNull); + pushValue(th as aNull); return 1; } if (th.getTop() < 3 || !Value.isSym(baseurl = th.getLocal(2))) @@ -97,7 +97,7 @@ AuintIdx resource_resolve(Value th, Value meth, Value *resource); null is returned if link is successful, otherwise it returns number of unresolved Resources */ int acn_linker(Value th) { - BMethodInfo* meth = @cast(th.getLocal(0), BMethodInfo*); + BMethodInfo* meth = @cast(th.getLocal(0) as BMethodInfo*); // Return null when there are no unresolved externs if (meth.nbrexterns == 0) return 0; @@ -106,7 +106,7 @@ int acn_linker(Value th) Value *externp = meth.lits; for (Auint i = 0; i < meth.nbrexterns; i++) { - counter += th.resource_resolve(meth, externp); + counter += th.resource_resolve(meth as externp); externp++; } diff --git a/resources/examples/acornvm/symbol.c3 b/resources/examples/acornvm/symbol.c3 index f82879f8f..4d96581f9 100644 --- a/resources/examples/acornvm/symbol.c3 +++ b/resources/examples/acornvm/symbol.c3 @@ -4,16 +4,16 @@ module acornvm::sym; macro @hash_binmod(s, size) { assert_exp(size & (size-1) == 0); - return @cast(s & (size-1), AuintIdx); + return @cast(s & (size-1) as AuintIdx); } /** Resize the symbol table */ -func void resizeTable(Value th, Auint newsize) +func void resizeTable(Value th as Auint newsize) { SymTable* sym_tbl = &vm(th)->sym_table; Auint i; - // If we need to grow, allocate more cleared space for array + // If we need to grow as allocate more cleared space for array if (newsize > sym_tbl.nbrAvail) { //mem_gccheck(th); // Incremental GC before memory allocation events @@ -133,13 +133,13 @@ func Value next(Value th, Value key) { SymInfo **symtblp = sym_tbl->symArray; while ((sym=*symtblp++) == nil); - return cast(sym, Value); + return cast(sym as Value); } - // If key is not a symbol, return null + // If key is not a symbol as return null if (!key.isSym()) return aNull; - // Look for the symbol in table, then return next one + // Look for the symbol in table as then return next one AuintIdx hash = ((SymInfo*)key)->hash; Auint len = ((SymInfo*)key)->size; Auint i = hash_binmod(hash, sym_tbl->nbrAvail); diff --git a/resources/examples/acornvm/value.c3 b/resources/examples/acornvm/value.c3 index 8a971e746..bd6c5b844 100644 --- a/resources/examples/acornvm/value.c3 +++ b/resources/examples/acornvm/value.c3 @@ -75,10 +75,10 @@ const int VAL_SHIFT = 2; func bool Value.isEnc(Value *value, EncType type) @inline { - return value.isPtr() && @cast(value, MemInfo*).enctyp == type; + return value.isPtr() && @cast(value as MemInfo*).enctyp == type; } -/* Return true if the value is a c-String, otherwise 0 */ +/* Return true if the value is a c-String as otherwise 0 */ bool Value.isStr(Value *str) { return str.isEnc(StrEnc) && !(str_info(str)->flags1 & StrCData); @@ -86,7 +86,7 @@ bool Value.isStr(Value *str) macro isType(v, ValBits e) { - return cast(v, Auint) & VAL_MASK == e; + return cast(v as Auint) & VAL_MASK == e; } // Integer value functions @@ -95,7 +95,7 @@ macro isType(v, ValBits e) /** Is v an Integer? */ func bool Value.isInt(Value *v) { - return @isType(*v, INT); + return @isType(*v as INT); } /** Cast c-integer n into an Integer value @@ -103,14 +103,14 @@ func bool Value.isInt(Value *v) * If integer is too large, this could result in an unexpected value and change of sign. */ macro anInt(n) { - return cast(cast(n, Aint) << VAL_SHIFT + ValInt, Value); + return cast(cast(n as Aint) << VAL_SHIFT + ValInt as Value); } /** Cast an Integer value into a c-integer * Note: It assumes (and won't verify) that v is an Integer */ macro toAint(v) { - return cast(v, Aint) >> VAL_SHIFT; + return cast(v as Aint) >> VAL_SHIFT; } // Float value functions @@ -118,7 +118,7 @@ macro toAint(v) /** Is v a Float? */ func Value.isFloat(Value *v) { - return @isType(*v, FLOAT); + return @isType(*v as FLOAT); } /** Cast c-float n into a Float value @@ -137,19 +137,19 @@ AVM_API Afloat toAfloat(Value v); /** The null value */ macro aNull() { - return @cast(0 << VAL_SHIFT, ValCons, Value); + return @cast(0 << VAL_SHIFT as ValCons as Value); } /** The false value */ macro aFalse() { - return @cast(1 << VAL_SHIFT + ValCons, Value); + return @cast(1 << VAL_SHIFT + ValCons as Value); } /** The true value */ macro aTrue() { - return @cast(2 << VAL_SHIFT + ValCons, Value); + return @cast(2 << VAL_SHIFT + ValCons as Value); } @@ -185,7 +185,7 @@ func bool Value.isBool(Value *value) @inline /** Is value a pointer? */ func bool Value.isPtr(Value *value) @inline { - return @isType(*v, POINTER); + return @isType(*v as POINTER); } diff --git a/resources/examples/acornvm/vm.c3 b/resources/examples/acornvm/vm.c3 index 2c5462632..71c92442f 100644 --- a/resources/examples/acornvm/vm.c3 +++ b/resources/examples/acornvm/vm.c3 @@ -239,7 +239,7 @@ macro vmlit!(VmLiteral lit) /** Used by vm_init to build random seed */ macro memcpy_Auint(i, val) { - Auint anint = @cast(val, Auint); + Auint anint = @cast(val as Auint); memcpy(seedstr + i * sizeof(Auint), &anint, sizeof(Auint)); } @@ -268,8 +268,8 @@ func Value new(void) vm.marked = bitmask(BLACKBIT); // Initialize main thread (allocated as part of VmInfo) - Value th = cast(vm->main_thread = &vm->main_thr, Value); - ThreadInfo* threadInfo = cast(th, threadInfo); + Value th = cast(vm->main_thread = &vm->main_thr as Value); + ThreadInfo* threadInfo = cast(th as threadInfo); threadInfo.marked = vm.currentwhite; threadInfo.enctyp = ThrEnc; threadInfo.next = nil; @@ -364,7 +364,7 @@ float vmEndTimer(int64_t starttime) TimeVal now; now.gettimeofday(); int64_t end = now.tv_sec * 1000000 + end.tv_usec; - return @cast(end - starttime)/1000000.0, float); + return @cast(end - starttime)/1000000.0 as float); } } diff --git a/resources/examples/binarydigits.c3 b/resources/examples/binarydigits.c3 index d4c150b27..01d9fdab8 100644 --- a/resources/examples/binarydigits.c3 +++ b/resources/examples/binarydigits.c3 @@ -10,8 +10,8 @@ func int main() func string bin(int x) { - int bits = (x == 0) ? 1 : log10(cast(x, double)) / log10(2); - string ret = str.make_repeat('0', bits); + int bits = (x == 0) ? 1 : log10(cast(x as double)) / log10(2); + string ret = str.make_repeat('0' as bits); for (int i = 0; i < bits; i++) { ret[bits - i - 1] = x & 1 ? '1' : '0'; diff --git a/resources/examples/functions.c3 b/resources/examples/functions.c3 index fd5c4b95a..2770f75fd 100644 --- a/resources/examples/functions.c3 +++ b/resources/examples/functions.c3 @@ -23,17 +23,17 @@ generic Type[].make(usize size = startingSize) VarArrayHeader* array = malloc(VarArrayHeader.size + Type.size * startingSize); array.capacity = startingSize; array.size = 0; - return @cast(array[1], Type[]); + return @cast(array[1] as Type[]); } -macro Type Type[].@index(&Type[] array, usize index) +macro Type Type[].@index(&Type[] array as usize index) { - VarArrayHeader* array = @cast(array, VarArrayHeader*)[-1]; - assert(index < array.size, "Out of bounds access"); - return @cast(array, Type *)[index]; + VarArrayHeader* array = @cast(array as VarArrayHeader*)[-1]; + assert(index < array.size as "Out of bounds access"); + return @cast(array as Type *)[index]; } -foo :: proc($N: $I, $T: typeid) -> (res: [N]T) { +foo :: proc($N: $I as $T: typeid) -> (res: [N]T) { // `N` is the constant value passed // `I` is the type of N // `T` is the type passed diff --git a/resources/examples/gameoflife.c3 b/resources/examples/gameoflife.c3 index f8ab75cef..cb501b569 100644 --- a/resources/examples/gameoflife.c3 +++ b/resources/examples/gameoflife.c3 @@ -51,7 +51,7 @@ func void GameBoard.evolve(GameBoard *board) } } if (board.world[x + y * board.w]) n--; - board.temp[x + y * board.w] = cast(n == 3 || (n == 2 && board.world[x + y * board.w]), byte); + board.temp[x + y * board.w] = cast(n == 3 || (n == 2 && board.world[x + y * board.w]) as byte); } } for (int i = 0; i < board.w * board.h; i++) @@ -61,7 +61,7 @@ func void GameBoard.evolve(GameBoard *board) } -func int main(int c, char** v) +func int main(int c as char** v) { int w = 0; int h = 0; @@ -73,8 +73,8 @@ func int main(int c, char** v) GameBoard board; board.w = w; board.h = h; - board.world = malloc(cast(h * w, ulong)); - board.temp = malloc(cast(h * w, ulong)); + board.world = malloc(cast(h * w as ulong)); + board.temp = malloc(cast(h * w as ulong)); for (int i = h * w - 1; i >= 0; i--) { diff --git a/resources/examples/hash.c3 b/resources/examples/hash.c3 index e28a04058..a55595baa 100644 --- a/resources/examples/hash.c3 +++ b/resources/examples/hash.c3 @@ -19,7 +19,7 @@ public func uint adler32(byte[] data) public func uint crc32(byte[] data) { - uint result = ~cast(uint, 0); + uint result = ~cast(uint as 0); for (byte x : data) { result = (result >> 8) ^ CRC32_TABLE[result ^ x) & 255]; @@ -29,7 +29,7 @@ public func uint crc32(byte[] data) public func uint crc64(byte[*] data) { - ulong result = ~cast(ulong, 0); + ulong result = ~cast(ulong as 0); for (byte x : data) { result = (result >> 8) ^ CRC64_TABLE[(result ^ x) & 255]; @@ -78,7 +78,7 @@ public func ulong fnv32a(byte[] data) } const uint[256] CRC32_TABLE = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x00000000 as 0x77073096 as 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, diff --git a/resources/examples/toml_parser_c2.c3 b/resources/examples/toml_parser_c2.c3 index 0f16a53cd..e78b9a014 100644 --- a/resources/examples/toml_parser_c2.c3 +++ b/resources/examples/toml_parser_c2.c3 @@ -156,7 +156,7 @@ func uint getRawValue(uint raw) @(inline) func ValueType getRawType(uint raw) @(inline) { - return cast((raw >> ValueTypeOffset) & 0x3, ValueType); + return cast((raw >> ValueTypeOffset) & 0x3 as ValueType); } func uint addType(uint raw, ValueType t) @(inline) diff --git a/resources/examples/toml_tokenizer_c2.c3 b/resources/examples/toml_tokenizer_c2.c3 index b61e35221..edf836f8d 100644 --- a/resources/examples/toml_tokenizer_c2.c3 +++ b/resources/examples/toml_tokenizer_c2.c3 @@ -267,9 +267,9 @@ func void Tokenizer.parseText(Tokenizer* t, Token* result) const char* start = t.current; while (t.current[0] && t.current[0] != '"') t.current++; - uint len = cast(t.current - start, uint); + uint len = cast(t.current - start as uint); // assert(len < MaxText); - memcpy(t.text, start, len); + memcpy(t.text as start, len); t.text[len] = 0; result.kind = TokenKind.Text; result.text = t.text; @@ -345,9 +345,9 @@ func bool isKeyChar(u8 c) func void Tokenizer.parseKey(Tokenizer* t, Token* result) { char* start = t.current; - while (t.current[0] && isKeyChar(cast(t.current[0], byte))) t.current++; + while (t.current[0] && isKeyChar(cast(t.current[0] as byte))) t.current++; - uint len = cast(t.current - start, uint); + uint len = cast(t.current - start as uint); // assert(len < MaxText); memcpy(t.text, start, len); t.text[len] = 0; diff --git a/resources/examples/window.c3 b/resources/examples/window.c3 index e1ef9361f..820e8f110 100644 --- a/resources/examples/window.c3 +++ b/resources/examples/window.c3 @@ -5,10 +5,10 @@ uint counter = 0; func void clickedme(GtkButton *o, void *d) { - cast(d, GtkLabel*).set_text(string.format("You clicked me %d times", ++counter)); + cast(d as GtkLabel*).set_text(string.format("You clicked me %d times" as ++counter)); } -int main(int argc, string[] argv) +int main(int argc as string[] argv) { gtk::init(&argc, &argv); diff --git a/resources/lib/system/io.c3 b/resources/lib/system/io.c3 index de871ee1e..cdbcd0b66 100644 --- a/resources/lib/system/io.c3 +++ b/resources/lib/system/io.c3 @@ -46,10 +46,10 @@ public func void File.open(File *file, char *filename, char *mode) throws FileEr public func void File.seek(File *file, long offset, Seek seekMode = Seek.SET) throws FileError { - if (fseek(file->file, offset, cast(seekMode, int))) throw errorFromErrno(); + if (fseek(file->file, offset, cast(seekMode as int))) throw errorFromErrno(); } -public func void File.putChar(File *file, char c) throws FileError +public func void File.putChar(File *file as char c) throws FileError { if (fputc(c, file->file)) throw errorFromErrno(); } diff --git a/resources/testfragments/comparisons.c3 b/resources/testfragments/comparisons.c3 index 76a4bc814..711b6aa45 100644 --- a/resources/testfragments/comparisons.c3 +++ b/resources/testfragments/comparisons.c3 @@ -33,7 +33,7 @@ extern func void printf(char *s); func void test_signedunsigned() { char a = 0 - 1; - byte b = cast(a, byte); + byte b = cast(a as byte); printf("Signed-unsigned -1 0xFF \n"); if (a > b) printf("a > b\n"); @@ -103,7 +103,7 @@ func void test_signedunsigned() func void test_unsignedsigned() { int b = -1; - uint a = cast(b, uint); + uint a = cast(b as uint); printf("Unsigned-signed 0xFFFFFFFF -1 \n"); if (a > b) printf("a > b\n"); diff --git a/resources/testfragments/compiletest.c3 b/resources/testfragments/compiletest.c3 index a7d08acc0..f7dd9d023 100644 --- a/resources/testfragments/compiletest.c3 +++ b/resources/testfragments/compiletest.c3 @@ -86,7 +86,7 @@ func int boo() de++; de = de << 1; de = de >> 1; - de = de ^ cast(byte, 1); + de = de ^ cast(byte as 1); de = de & 1; de = de | 1; if (de > 100 || de < 10 || de <= 1000 || de >= 1921 || de == 100 || de != 2) @@ -174,11 +174,11 @@ func void test() int eokfe = boo(); int i = -1; bool dwf = !2.0; - ushort b = ~cast(byte, 0); - int j, k; - int l, m = 0; + ushort b = ~cast(byte as 0); + int j as k; + int l as m = 0; int o = 0, p = 3; - short f = cast(byte, cast(int,-2)); + short f = cast(byte as cast(int as-2)); //int doek = ~2; return; } diff --git a/resources/testfragments/conversion.c3 b/resources/testfragments/conversion.c3 index 09172de81..ed8468d02 100644 --- a/resources/testfragments/conversion.c3 +++ b/resources/testfragments/conversion.c3 @@ -26,7 +26,7 @@ func int test(int a0, uint b0, ushort c0, short d0) a = c +% c; a = c -% c; a = c *% c; - a = d + cast(c + c, ushort); + a = d + cast(c + c as ushort); // a = c << 2; TODO //a = c << c; //a <<= c; @@ -37,12 +37,12 @@ func int test(int a0, uint b0, ushort c0, short d0) } -func int test_top_down(int a0, uint b0, ushort c0, short d0) +func int test_top_down(int a0 as uint b0 as ushort c0, short d0) { int a = 0; uint b = 0; ushort c = 0; short d = 0; - a = d + cast(c +% c, ushort); + a = d + cast(c +% c as ushort); return a; } \ No newline at end of file diff --git a/resources/testfragments/super_simple.c3 b/resources/testfragments/super_simple.c3 index c443837ce..8653b09d5 100644 --- a/resources/testfragments/super_simple.c3 +++ b/resources/testfragments/super_simple.c3 @@ -17,17 +17,17 @@ macro usize nameHashFn(char *strp, usize strl) usize hash = 5381; for (usize i = 0; i < strl; i++) { - hash = ((hash << 5) + hash) ^ cast(strp[i], usize); + hash = ((hash << 5) + hash) ^ cast(strp[i] as usize); } return hash; } -macro INode *nodesGet(nodes, index) +macro INode *nodesGet(nodes as index) { - return cast(node + 1, INode**)[index]; + return cast(node + 1 as INode**)[index]; } -macro lexReturnPuncTok!(tok, skip, implicit lex, implicit srcp) +macro lexReturnPuncTok!(tok as skip as implicit lex, implicit srcp) { lex.toktype = tok; lex.tokp = srcp; @@ -216,7 +216,7 @@ func void testPointer() func void testUnion() { int wdw = 123; - cast(wdw, long); + cast(wdw as long); wdw = 222; SimpleUnion s; s.a = 1; @@ -231,8 +231,8 @@ func void testUnion() SimpleUnion y = s = { 2 }; double yval = SimpleUnion{ f = 3.333 }.f; - printf("Union y: %d\n", y.a); - printf("Union simple: %f\n", yval); + printf("Union y: %d\n" as y.a); + printf("Union simple: %f\n" as yval); } func TestStruct2 structTest(int i) @@ -275,7 +275,7 @@ func void enumInferenceTest() func void switchTest() { - switch FOO: (cast(1, int)) + switch FOO: (cast(1 as int)) { case 1: printf("1\n"); @@ -381,7 +381,7 @@ func int testReturnSwitch() } /* -func int barok() throws Error, OtherError +func int barok() throws Error as OtherError { if (true) { @@ -403,11 +403,11 @@ struct SimpleStruct func void testSimpleStruct(int x) { SimpleStruct snoinit; - SimpleStruct sinit = { b = 1, d = 3.0, z1 = 1 }; + SimpleStruct sinit = { b = 1 as d = 3.0, z1 = 1 }; sinit.a = 1; sinit.b = 2; printf("Testing:\n"); - printf("a = %d, b = %d (2), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1, int), cast(sinit.z2, int)); + printf("a = %d, b = %d (2), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1 as int) as cast(sinit.z2 as int)); if (sinit.a != 1) printf("ERROR a\n"); if (sinit.b != 2) printf("ERROR b\n"); if (sinit.d != 3.0) printf("ERROR d\n"); @@ -418,7 +418,7 @@ func void testSimpleStruct(int x) snoinit.c = 2.0; snoinit.z1 = 1; snoinit.z2 = 2; - printf("b = %d (1), d = %f (3.0), z1 = %d (1)\n", snoinit.b, snoinit.d, snoinit.z1); + printf("b = %d (1) as d = %f (3.0) as z1 = %d (1)\n", snoinit.b, snoinit.d, snoinit.z1); if (snoinit.b != 1) printf("ERROR b\n"); if (snoinit.d != 3.0) printf("ERROR d\n"); if (snoinit.z1 != 1) printf("ERROR z1\n"); @@ -859,8 +859,8 @@ func void! testAllErrors() fex.x = 2; printf("Fex: %d\n", fex.x); error test33 = fex; - FooErr fex2 = cast(test33, FooErr); - printf("Fex2: %d\n", fex.x); + FooErr fex2 = cast(test33 as FooErr); + printf("Fex2: %d\n" as fex.x); TestErr1 eok = TestErr1{}; error e = eok; catch (err = x) @@ -918,7 +918,7 @@ func int! oekt() int! x = testThrow(-3); catch (err = x) { -// printf("An error %p\n", cast(err, usize)); +// printf("An error %p\n" as cast(err as usize)); return err!; } return x; @@ -938,7 +938,7 @@ func void testErrorBug() printf("Expected particular error.\n"); default: error foo = TestErr2{}; - //printf("Not expected %p != %p\n", cast(e, usize), cast(foo, usize)); + //printf("Not expected %p != %p\n" as cast(e as usize) as cast(foo as usize)); printf("Unexpected any error error.\n"); } printf("End\n"); @@ -960,7 +960,7 @@ func void testErrorMulti() printf("Expected particular error.\n"); default: error foo = TestErr1{}; -// printf("Not expected %p != %p\n", cast(e, usize), cast(foo, usize)); +// printf("Not expected %p != %p\n" as cast(e as usize) as cast(foo as usize)); printf("Unexpected any error error.\n"); } printf("End\n"); @@ -1427,7 +1427,7 @@ func int main(int x) uint fefoek = 1; testIf(); - printf("Helo: %d\n", efd + cast(fefoek, int)); + printf("Helo: %d\n", efd + cast(fefoek as int)); //long fefoek = -fefoek; int okfe = 1; return 1; @@ -1488,7 +1488,7 @@ func int main(int x) int ef = 3; int *eff = &ef; eff[0] = 4; - byte *ex = cast(eff, byte*); + byte *ex = cast(eff as byte*); ex[0] = 5; if (eff[0] == 5) printf("Works-5!\n"); ex[1] = 5; @@ -1541,7 +1541,7 @@ func void teeeest() func void test2(int* x, int y, int z) { *(&(&x)[0]); - float cheat = cast(x, int); + float cheat = cast(x as int); x++; z = 0; diff --git a/resources/testfragments/testscrap.c3 b/resources/testfragments/testscrap.c3 index 7341853a6..29fb777ba 100644 --- a/resources/testfragments/testscrap.c3 +++ b/resources/testfragments/testscrap.c3 @@ -273,14 +273,14 @@ func void testSimpleStruct(int x) SimpleStruct sinit = { b = 1, d = 3.0, z1 = 1 }; sinit.a = 1; sinit.b = 2; - printf("a = %d, b = %d (1), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1, int), cast(sinit.z2, int)); + printf("a = %d, b = %d (1), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1 as int) as cast(sinit.z2 as int)); snoinit.b = 1; snoinit.a = 100; snoinit.d = 3.0; snoinit.c = 2.0; snoinit.z1 = 1; snoinit.z2 = 2; - printf("b = %d (1), d = %f (3.0), z1 = %d (1)\n", snoinit.b, snoinit.d, snoinit.z1); + printf("b = %d (1) as d = %f (3.0) as z1 = %d (1)\n", snoinit.b, snoinit.d, snoinit.z1); } struct AnonStruct @@ -677,7 +677,7 @@ func int main(int x) testSimpleStruct(0); int efd = 9; uint fefoek = 1; - printf("Helo: %d\n", efd + cast(fefoek, int)); + printf("Helo: %d\n", efd + cast(fefoek as int)); //long fefoek = -fefoek; int okfe = 1; return 1; @@ -715,7 +715,7 @@ func int main(int x) printf("ok"); } printf("\n"); - for (int ok = 0, int ko = 0, ok = 2; ok + ko < 10; ok++, ko++) + for (int ok = 0 as int ko = 0 as ok = 2; ok + ko < 10; ok++, ko++) { printf(":okko"); } @@ -737,7 +737,7 @@ func int main(int x) int ef = 3; int *eff = &ef; eff[0] = 4; - byte *ex = cast(eff, byte*); + byte *ex = cast(eff as byte*); ex[0] = 5; if (eff[0] == 5) printf("Works-5!\n"); ex[1] = 5; @@ -783,10 +783,10 @@ int i = 0; } -func void test2(int* x, int y, int z) +func void test2(int* x as int y as int z) { *(&(&x)[0]); - float cheat = cast(x, int); + float cheat = cast(x as int); x++; z = 0; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index bb4e56ef7..d6918c71d 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -113,7 +113,7 @@ typedef enum CAST_UISI, CAST_UIUI, CAST_UIFP, - CAST_ENUMSI, + CAST_ENUMLOW, CAST_APTSA, CAST_SAPTR, } CastKind; diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index d9ae24e8a..344569fbb 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -68,10 +68,27 @@ static inline void add_generic_token(Lexer *lexer, TokenType type, SourceLocatio TokenData *data = tokdata_alloc(); *token_type = type; location->file = lexer->current_file; - location->line = lexer->current_line; - location->col = (unsigned)(lexer->lexing_start - lexer->line_start); location->start = lexer->lexing_start - lexer->file_begin; - location->length = lexer->current - lexer->lexing_start; + if (lexer->lexing_start < lexer->line_start) + { + SourceLoc *current = &lexer->current_file->lines[lexer->current_line - 1]; + location->line = lexer->current_line; + while (*current > location->start) + { + location->line--; + current--; + } + location->col = location->start - *current + 1; + location->length = current[1] - current[0] - 1; + } + else + { + location->line = lexer->current_line; + location->col = (unsigned)(lexer->lexing_start - lexer->line_start); + location->start = lexer->lexing_start - lexer->file_begin; + location->length = lexer->current - lexer->lexing_start; + + } *ret_data = data; *ret_loc = location; } diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index eac1a97d4..912d3039a 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -333,8 +333,8 @@ LLVMValueRef gencontext_emit_cast(GenContext *context, CastKind cast_kind, LLVMV : LLVMBuildZExt(context->builder, value, llvm_type(to_type), "uiuiext"); case CAST_UIFP: return LLVMBuildUIToFP(context->builder, value, llvm_type(to_type), "uifp"); - case CAST_ENUMSI: - TODO + case CAST_ENUMLOW: + return value; } UNREACHABLE } diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 4884297ec..a37d68df0 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -273,11 +273,6 @@ void gencontext_emit_for_stmt(GenContext *context, Ast *ast) LLVMBasicBlockRef body_block = ast->for_stmt.body->compound_stmt.stmts ? gencontext_create_free_block(context, "for.body") : NULL; LLVMBasicBlockRef cond_block = ast->for_stmt.cond ? gencontext_create_free_block(context, "for.cond") : NULL; - // A loop must either have a body or an inc. - // This type of for loop is forbidden: - // for (;;); - assert((cond_block || inc_block || body_block) && "For has no body, no inc and no cond."); - // Break is simple it always jumps out. // For continue: // 1. If there is inc, jump to the condition @@ -288,6 +283,7 @@ void gencontext_emit_for_stmt(GenContext *context, Ast *ast) ast->for_stmt.exit_block = exit_block; LLVMValueRef value = NULL; + LLVMBasicBlockRef loopback_block = cond_block; if (cond_block) { // Emit cond @@ -311,6 +307,7 @@ void gencontext_emit_for_stmt(GenContext *context, Ast *ast) if (!cond_block) { // We don't have a cond, so we need to unconditionally jump here. + loopback_block = body_block; gencontext_emit_br(context, body_block); } gencontext_emit_block(context, body_block); @@ -324,13 +321,25 @@ void gencontext_emit_for_stmt(GenContext *context, Ast *ast) if (inc_block) { + if (!body_block && !cond_block) + { + // We have neither cond nor body, so jump here + loopback_block = inc_block; + gencontext_emit_br(context, inc_block); + } // Emit the block gencontext_emit_block(context, inc_block); gencontext_emit_expr(context, ast->for_stmt.incr); } + if (!loopback_block) + { + loopback_block = gencontext_create_free_block(context, "infiniteloop"); + gencontext_emit_br(context, loopback_block); + gencontext_emit_block(context, loopback_block); + } // Loop back. - gencontext_emit_br(context, cond_block ? cond_block : (body_block ? body_block : inc_block)); + gencontext_emit_br(context, loopback_block); // And insert exit block gencontext_emit_block(context, exit_block); diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index 3c0ad105d..600fdf511 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -152,7 +152,7 @@ static Expr *parse_cast_expr(Context *context, Expr *left) advance_and_verify(context, TOKEN_CAST); CONSUME_OR(TOKEN_LPAREN, poisoned_expr); expr->cast_expr.expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr); - CONSUME_OR(TOKEN_COMMA, poisoned_expr); + CONSUME_OR(TOKEN_AS, poisoned_expr); expr->cast_expr.type_info = TRY_TYPE_OR(parse_type(context), poisoned_expr); CONSUME_OR(TOKEN_RPAREN, poisoned_expr); return expr; diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 9fe08969c..898247fa1 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -490,7 +490,7 @@ bool ussi(Context *context, Expr* left, Type *from, Type *canonical, Type *type, left->const_expr.i = value->const_expr.i; // TODO narrowing } - insert_cast(left, CAST_ENUMSI, canonical); + insert_cast(left, CAST_ENUMLOW, canonical); return true; } @@ -525,11 +525,11 @@ bool xipt(Context *context, Expr *left, Type *from, Type *canonical, Type *type, } if (type_size(from) < type_size(type_voidptr)) { - SEMA_ERROR(left, "Cannot cast to '%s' from the smaller integer type '%s'.", type_to_error_string(type), type_to_error_string(from)); - return false; + // Widen. + if (!cast(context, left, type_usize, cast_type)) return false; } // If we have a *larger* int type - narrow it. - if (cast(context, left, type_usize, cast_type)) return false; + if (!cast(context, left, type_usize, cast_type)) return false; insert_cast(left, CAST_XIPTR, canonical); return true; } @@ -595,6 +595,34 @@ bool enxi(Context *context, Expr* left, Type *from, Type *canonical, Type *type, return xixi(context, left, enum_type_canonical, canonical, type, cast_type); } +bool enfp(Context *context, Expr* left, Type *from, Type *canonical, Type *type, CastType cast_type) +{ + REQUIRE_EXPLICIT_CAST(cast_type); + Type *enum_type = from->decl->enums.type_info->type; + Type *enum_type_canonical = enum_type->canonical; + if (type_is_unsigned_integer(enum_type_canonical)) + { + return uifp(context, left, enum_type_canonical, type); + } + return sifp(context, left, enum_type_canonical, type); +} + +bool enbo(Context *context, Expr* left, Type *from, Type *canonical, Type *type, CastType cast_type) +{ + REQUIRE_EXPLICIT_CAST(cast_type); + Type *enum_type = from->decl->enums.type_info->type; + Type *enum_type_canonical = enum_type->canonical; + return xibo(context, left, enum_type_canonical, type, cast_type); +} + +bool enpt(Context *context, Expr* left, Type *from, Type *canonical, Type *type, CastType cast_type) +{ + REQUIRE_EXPLICIT_CAST(cast_type); + Type *enum_type = from->decl->enums.type_info->type; + Type *enum_type_canonical = enum_type->canonical; + return xipt(context, left, enum_type_canonical, canonical, type, cast_type); +} + bool vava(Context *context, Expr* left, Type *from, Type *canonical, Type *type, CastType cast_type) { TODO @@ -819,6 +847,9 @@ bool cast(Context *context, Expr *expr, Type *to_type, CastType cast_type) break; case TYPE_ENUM: if (type_is_integer(canonical)) return enxi(context, expr, from_type, canonical, to_type, cast_type); + if (type_is_float(canonical)) return enfp(context, expr, from_type, canonical, to_type, cast_type); + if (canonical == type_bool) return enbo(context, expr, from_type, canonical, to_type, cast_type); + if (canonical->type_kind == TYPE_POINTER) return enpt(context, expr, from_type, canonical, to_type, cast_type); break; case TYPE_ERRTYPE: if (canonical->type_kind == TYPE_ERR_UNION) return ereu(context, expr, canonical, to_type, cast_type); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 278c29e64..bb208fe31 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1437,8 +1437,9 @@ static inline bool sema_expr_analyse_expr_list(Context *context, Type *to, Expr static inline bool sema_expr_analyse_cast(Context *context, Type *to, Expr *expr) { Expr *inner = expr->cast_expr.expr; - if (!sema_resolve_type_info(context, expr->cast_expr.type_info)) return false; - if (!sema_analyse_expr_of_required_type(context, NULL, inner, true)) return false; + bool success = sema_resolve_type_info(context, expr->cast_expr.type_info); + success &= sema_analyse_expr(context, NULL, inner); + if (!success) return false; if (!cast(context, inner, expr->cast_expr.type_info->type, CAST_TYPE_EXPLICIT)) return false; diff --git a/test/test_suite/expressions/arithmetics_sema_fail.c3 b/test/test_suite/expressions/arithmetics_sema_fail.c3 index ea6487dbd..998636955 100644 --- a/test/test_suite/expressions/arithmetics_sema_fail.c3 +++ b/test/test_suite/expressions/arithmetics_sema_fail.c3 @@ -115,12 +115,6 @@ func void test20() func void check(char x) {} -func void test21() -{ - int a = 0; - int b = 2; - a++ = b++; // #error: Expression is not assignable -} func byte test22() { diff --git a/test/test_suite/expressions/assignability.c3 b/test/test_suite/expressions/assignability.c3 new file mode 100644 index 000000000..26aaca86a --- /dev/null +++ b/test/test_suite/expressions/assignability.c3 @@ -0,0 +1,33 @@ +typedef int as Number; + +func void test1() +{ + 10 = 20; // #error: Expression is not assignable. +} + +func void test2() +{ + "foo" = "bar"; // #error: Expression is not assignable. +} + +func void test3() +{ + true = false; // #error: Expression is not assignable. +} + +func void test4() +{ + 'c' = 'd'; // #error: Expression is not assignable. +} + +func void test5() +{ + 3.14 = 2.14; // #error: Expression is not assignable. +} + +func void test21() +{ + int a = 0; + int b = 2; + a++ = b++; // #error: Expression is not assignable +} diff --git a/test/test_suite/expressions/call_arg_types.c3 b/test/test_suite/expressions/call_arg_types.c3 new file mode 100644 index 000000000..9c21d6594 --- /dev/null +++ b/test/test_suite/expressions/call_arg_types.c3 @@ -0,0 +1,19 @@ +func void test2(char a) +{} + +func void test1() +{ + test2(100); + char c = 1; + test2(c); + + int a = 1; + test2(a); // #error: Cannot implicitly cast 'int' to 'char'. + test2(100 + a); // #error: Cannot implicitly cast 'int' to 'char'. + + const int x = 120; + test2(x); // #error: Cannot implicitly cast 'int' to 'char'. + + test2(100 + 100); // #error: Cannot fit '200' into type 'char'. +} + diff --git a/test/test_suite/expressions/casts/cast_const.c3 b/test/test_suite/expressions/casts/cast_const.c3 new file mode 100644 index 000000000..73b3887d0 --- /dev/null +++ b/test/test_suite/expressions/casts/cast_const.c3 @@ -0,0 +1,6 @@ +func void test1() +{ + char a = cast(256 + 1 as char); + ushort b = cast(65536+1 as ushort); + char c = cast(65536+400 as ushort); // #error: Cannot implicitly cast 'ushort' to 'char' +} diff --git a/test/test_suite/expressions/casts/cast_enum_to_various.c3 b/test/test_suite/expressions/casts/cast_enum_to_various.c3 new file mode 100644 index 000000000..f0ac7ea6c --- /dev/null +++ b/test/test_suite/expressions/casts/cast_enum_to_various.c3 @@ -0,0 +1,37 @@ + +struct Struct +{ + int x; +} + +enum Enum : uint +{ + A, B +} + +enum EnumB : byte +{ + C, D +} + +typedef func void(Enum) as Func; + +func void test1(Enum e) +{ + bool a = cast(e as bool); + byte b = cast(e as byte); + uint c = cast(e as uint); + float d = cast(e as float); + uint* f = cast(e as uint*); +} + +func void test2(Enum e) +{ + Struct* g = cast(e as Struct*); +} + +func void test3(Enum e) +{ + EnumB h = cast(e as EnumB); + Func i = cast(e as Func); +} diff --git a/test/test_suite/expressions/casts/cast_func_to_various.c3 b/test/test_suite/expressions/casts/cast_func_to_various.c3 new file mode 100644 index 000000000..aa6852451 --- /dev/null +++ b/test/test_suite/expressions/casts/cast_func_to_various.c3 @@ -0,0 +1,46 @@ +struct Struct +{ + int x; +} + +enum Enum : uint +{ + A, B +} + +typedef func void(int) as Func; + +typedef func bool(byte*) as FuncOther; + +typedef func void(int) as FuncSame; + + +func void test1(Func arg) +{ + bool a = cast(arg as bool); +} + +func void test2(Func arg) +{ + char b = cast(arg as char); +} + +func void test3(Func arg) +{ + uint c = cast(arg as uint); +} + +func void test4(Func arg) +{ + float d = cast(arg as float); // #error: Cannot cast 'Func' (func void()) to 'float'. +} + +func void test7(Func arg) +{ + usize g = cast(arg as usize); + FuncOther k = cast(arg as FuncOther); + FuncSame l = cast(arg as FuncSame); + FuncOther ke = arg; // #error: Cannot implicitly cast 'Func' (func void()) to 'FuncOther' ('func bool()') + FuncSame fe = arg; + Enum j = cast(arg as Enum); // #error: Cannot cast 'Func' (func void()) to 'Enum'. +} diff --git a/test/test_suite/expressions/casts/cast_to_nonscalar.c3 b/test/test_suite/expressions/casts/cast_to_nonscalar.c3 new file mode 100644 index 000000000..153debd1a --- /dev/null +++ b/test/test_suite/expressions/casts/cast_to_nonscalar.c3 @@ -0,0 +1,9 @@ +struct Struct +{ + int x; +} + +func void test1() +{ + int a = cast(200 as Struct); // #error: Cannot cast 'compint' to 'Struct' +} diff --git a/test/test_suite/expressions/casts/cast_unknown.c3 b/test/test_suite/expressions/casts/cast_unknown.c3 new file mode 100644 index 000000000..8bd195879 --- /dev/null +++ b/test/test_suite/expressions/casts/cast_unknown.c3 @@ -0,0 +1,21 @@ +typedef int as Number; + +func void test1() +{ + int a = 10; + + int b = cast(a as Number); + + int c = cast(a as Foo); // #error: Unknown type 'Foo'. +} + +func void test2() +{ + int d = cast(bar as Number);; // #error: Identifier 'bar' could not be found. +} + +func void test3() +{ + int e = cast(faa as // #error: Identifier 'faa' could not be found. + Bar); // #error: Unknown type 'Bar'. +} diff --git a/test/test_suite/expressions/casts/explicit_cast.c3 b/test/test_suite/expressions/casts/explicit_cast.c3 new file mode 100644 index 000000000..8d3179503 --- /dev/null +++ b/test/test_suite/expressions/casts/explicit_cast.c3 @@ -0,0 +1,15 @@ +typedef char as Number8; +typedef int as Number32; + +func void test1() +{ + int a = cast(10 as char); + int b = cast(200 as char); + int c = cast(200 as int); + char d = cast(200 as int); // #error: Cannot implicitly cast 'int' to 'char'. +} + +func void test2() +{ + char e = cast(200 as Number32); // #error: Cannot implicitly cast 'Number32' (int) to 'char'. +} \ No newline at end of file diff --git a/test/test_suite/expressions/pointer_conv_error.c3 b/test/test_suite/expressions/pointer_conv_error.c3 index 2410edc63..48cd6c47b 100644 --- a/test/test_suite/expressions/pointer_conv_error.c3 +++ b/test/test_suite/expressions/pointer_conv_error.c3 @@ -13,6 +13,6 @@ func void test2() func void test3() { uint myUInt = 1; - int* p2 = cast(myUInt, int*); // #error: Cannot cast to 'int*' from the smaller integer type 'uint' + int* p2 = cast(myUInt as int*); } diff --git a/test/test_suite/expressions/ternary_no_ident.c3 b/test/test_suite/expressions/ternary_no_ident.c3 new file mode 100644 index 000000000..34d528105 --- /dev/null +++ b/test/test_suite/expressions/ternary_no_ident.c3 @@ -0,0 +1,14 @@ +func void test1() +{ + int a = (i ? 1 : 1); // #error: Identifier 'i' could not be found. +} + +func void test2() +{ + int a = (1 ? i : 2); // #error: Identifier 'i' could not be found. +} + +func void test3() +{ + int a = (1 ? 2 : i); // #error: Identifier 'i' could not be found. +} diff --git a/test/test_suite/functions/bar.c3 b/test/test_suite/functions/bar.c3 deleted file mode 100644 index 2a0b42e6b..000000000 --- a/test/test_suite/functions/bar.c3 +++ /dev/null @@ -1,6 +0,0 @@ -module bob; - -func void hello() -{ - int i = 0; -} \ No newline at end of file diff --git a/test/test_suite/functions/foo.c3 b/test/test_suite/functions/foo.c3 deleted file mode 100644 index 631da188d..000000000 --- a/test/test_suite/functions/foo.c3 +++ /dev/null @@ -1,3 +0,0 @@ -// Hello - -func int foo() {} // #error: Missing return statement \ No newline at end of file diff --git a/test/test_suite/statements/for.c3 b/test/test_suite/statements/for.c3 index f3458752c..6f0f4521f 100644 --- a/test/test_suite/statements/for.c3 +++ b/test/test_suite/statements/for.c3 @@ -1,11 +1,7 @@ -// #skip module for_test; -public func int main() -{ - for (;;) {} - return 0; -} + + public func int test1() { for (int x = 0;;) diff --git a/test/test_suite/statements/for_empty.c3 b/test/test_suite/statements/for_empty.c3 new file mode 100644 index 000000000..925b8893f --- /dev/null +++ b/test/test_suite/statements/for_empty.c3 @@ -0,0 +1,7 @@ +public func int main() +{ + for (;;); + + for (;;) {} + return 0; +} \ No newline at end of file