diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cfa579247..0ca9ed26c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -78,7 +78,7 @@ jobs: build-msys2-clang: runs-on: windows-latest - #if: ${{ false }} + if: ${{ false }} strategy: # Don't abort runners if a single one fails fail-fast: false diff --git a/lib/std/array.c3 b/lib/std/array.c3 index 9ed41f25d..2b8b3fb89 100644 --- a/lib/std/array.c3 +++ b/lib/std/array.c3 @@ -9,7 +9,6 @@ import std::mem; **/ macro alloc($Type, usize elements) { - assert($Type.max / elements < $Type.sizeof); $Type* ptr = mem::alloc($Type.sizeof * elements, $alignof($Type)); return ptr[0..(elements - 1)]; } diff --git a/lib/std/builtin.c3 b/lib/std/builtin.c3 index 0e532c08e..a56543e33 100644 --- a/lib/std/builtin.c3 +++ b/lib/std/builtin.c3 @@ -14,7 +14,7 @@ fault VarCastResult * * @param variable `the variable to store and restore` **/ -macro void scope(&variable; @body) @autoimport +macro void @scope(&variable; @body) @autoimport { $typeof(variable) temp = variable; defer variable = temp; @@ -51,15 +51,15 @@ fn void panic(char* message, char *file, char *function, uint line) @autoimport if (stack) stack = stack.prev; if (stack) { - libc::fprintf(@libc::stderr(), "\nERROR: '%s'\n", message); + libc::fprintf(libc::stderr(), "\nERROR: '%s'\n", message); } else { - libc::fprintf(@libc::stderr(), "\nERROR: '%s', function %s (%s:%d)\n", message, function, file, line); + libc::fprintf(libc::stderr(), "\nERROR: '%s', function %s (%s:%d)\n", message, function, file, line); } while (stack) { - libc::fprintf(@libc::stderr(), " at function %s (%s:%u)\n", stack.function, stack.file, stack.line); + libc::fprintf(libc::stderr(), " at function %s (%s:%u)\n", stack.function, stack.file, stack.line); if (stack == stack.prev) break; stack = stack.prev; } diff --git a/lib/std/linkedlist.c3 b/lib/std/linkedlist.c3 index 88f7e77cb..82969bfd7 100644 --- a/lib/std/linkedlist.c3 +++ b/lib/std/linkedlist.c3 @@ -26,7 +26,7 @@ fn void LinkedList.push(LinkedList *list, Type value) private fn void LinkedList.linkFirst(LinkedList *list, Type value) { Node *first = list.first; - Node *new_node = @mem::malloc(Node); + Node *new_node = mem::malloc(Node); *new_node = { .next = first, .value = value }; list.first = new_node; if (!first) @@ -90,7 +90,7 @@ fn Type LinkedList.get(LinkedList* list, usize index) private fn void LinkedList.linkBefore(LinkedList *list, Node *succ, Type value) { Node* pred = succ.prev; - Node* new_node = @mem::malloc(Node); + Node* new_node = mem::malloc(Node); *new_node = { .prev = pred, .next = succ, .value = value }; succ.prev = new_node; if (!pred) diff --git a/lib/std/list.c3 b/lib/std/list.c3 index c666c1d33..ba16e71e5 100644 --- a/lib/std/list.c3 +++ b/lib/std/list.c3 @@ -117,12 +117,12 @@ fn void List.free(List *list) } -macro Type List.item_at(List &list, usize index) @operator(elementat) +macro Type List.@item_at(List &list, usize index) @operator(elementat) { return list.entries[index]; } -macro Type* List.item_ref(List &list, usize index) @operator(elementref) +macro Type* List.@item_ref(List &list, usize index) @operator(elementref) { return &list.entries[index]; } diff --git a/lib/std/mem.c3 b/lib/std/mem.c3 index 2995b9b09..6ebc0197f 100644 --- a/lib/std/mem.c3 +++ b/lib/std/mem.c3 @@ -3,18 +3,18 @@ // a copy of which can be found in the LICENSE_STDLIB file. module std::mem; -macro volatile_load(&x) +macro @volatile_load(&x) { return $$volatile_load(&x); } -macro volatile_store(&x, y) +macro @volatile_store(&x, y) { return $$volatile_store(&x, y); } /** - * @require @math::is_power_of_2(alignment) + * @require math::is_power_of_2(alignment) **/ fn usize aligned_offset(usize offset, usize alignment) { @@ -23,7 +23,7 @@ fn usize aligned_offset(usize offset, usize alignment) /** - * @require @math::is_power_of_2(alignment) + * @require math::is_power_of_2(alignment) **/ fn bool ptr_is_aligned(void* ptr, usize alignment) @inline { @@ -32,7 +32,7 @@ fn bool ptr_is_aligned(void* ptr, usize alignment) @inline fn void copy(char* dst, char* src, usize size) @inline { - @memcpy(dst, src, size); + memcpy(dst, src, size); } macro void memcpy(void* dst, void* src, usize size, bool $is_volatile = false, usize $dst_align = 0, usize $src_align = 0) @@ -42,7 +42,7 @@ macro void memcpy(void* dst, void* src, usize size, bool $is_volatile = false, u fn void set(void* dst, char val, usize bytes) @inline { - @memset(dst, val, bytes); + memset(dst, val, bytes); } macro void memset(void* dst, char val, usize bytes, bool $is_volatile = false, usize $dst_align = 0) @@ -94,7 +94,7 @@ fn char[] alloc_bytes(usize bytes) @inline } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void* alloc(usize size, usize alignment = 0) { @@ -102,7 +102,7 @@ fn void* alloc(usize size, usize alignment = 0) } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void*! alloc_checked(usize size, usize alignment = 0) { @@ -111,7 +111,7 @@ fn void*! alloc_checked(usize size, usize alignment = 0) /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void* calloc(usize size, usize alignment = 0) { @@ -119,7 +119,7 @@ fn void* calloc(usize size, usize alignment = 0) } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void*! calloc_checked(usize size, usize alignment = 0) { @@ -127,7 +127,7 @@ fn void*! calloc_checked(usize size, usize alignment = 0) } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void* realloc(void *ptr, usize new_size, usize alignment = 0) { @@ -135,7 +135,7 @@ fn void* realloc(void *ptr, usize new_size, usize alignment = 0) } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void*! realloc_checked(void *ptr, usize new_size, usize alignment = 0) { @@ -150,7 +150,7 @@ fn void free(void* ptr) /** * Run with a specific allocator inside of the macro body. **/ -macro void with_allocator(Allocator allocator; @body()) +macro void @with_allocator(Allocator allocator; @body()) { Allocator old_allocator = thread_allocator; thread_allocator = allocator; @@ -172,7 +172,7 @@ struct MemoryArena /** * @require alignment > 0 `alignment must be non zero` - * @require @math::is_power_of_2(alignment) + * @require math::is_power_of_2(alignment) * @require size > 0 * @require alignment <= MAX_MEMORY_ALIGNMENT `alignment too big` * @require this != null diff --git a/lib/std/mem_allocator.c3 b/lib/std/mem_allocator.c3 index 89b865cd9..1c827b971 100644 --- a/lib/std/mem_allocator.c3 +++ b/lib/std/mem_allocator.c3 @@ -13,7 +13,7 @@ const AllocatorFunction NULL_ALLOCATOR = &null_allocator_fn; const AllocatorFunction SYSTEM_ALLOCATOR = &libc_allocator_fn; /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void*! Allocator.alloc(Allocator *allocator, usize size, usize alignment = 0) @inline { @@ -21,7 +21,7 @@ fn void*! Allocator.alloc(Allocator *allocator, usize size, usize alignment = 0) } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void*! Allocator.realloc(Allocator *allocator, void* old_pointer, usize size, usize alignment = 0) @inline { @@ -29,7 +29,7 @@ fn void*! Allocator.realloc(Allocator *allocator, void* old_pointer, usize size, } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) */ fn void*! Allocator.calloc(Allocator *allocator, usize size, usize alignment = 0) @inline { @@ -68,7 +68,7 @@ private fn usize alignment_for_allocation(usize alignment) @inline } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) * @require data `unexpectedly missing the allocator` */ fn void*! arena_allocator_function(void* data, usize size, usize alignment, void* old_pointer, AllocationKind kind) @@ -126,7 +126,7 @@ fn void*! arena_allocator_function(void* data, usize size, usize alignment, void arena.used = 0; return null; } - @unreachable(); + unreachable(); } struct DynamicArenaAllocator @@ -148,7 +148,7 @@ private struct DynamicArenaPage /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) * @require data `unexpectedly missing the allocator` */ fn void*! dynamic_arena_allocator_function(void* data, usize size, usize alignment, void* old_pointer, AllocationKind kind) @@ -184,7 +184,7 @@ fn void*! dynamic_arena_allocator_function(void* data, usize size, usize alignme allocator.reset(); return null; } - @unreachable(); + unreachable(); } /** @@ -287,12 +287,12 @@ private fn void DynamicArenaAllocator.reset(DynamicArenaAllocator* this) } /** - * @require @math::is_power_of_2(alignment) + * @require math::is_power_of_2(alignment) * @require size > 0 */ private fn void*! DynamicArenaAllocator.alloc_new(DynamicArenaAllocator* this, usize size, usize alignment) { - usize page_size = @max(this.page_size, size + DEFAULT_SIZE_PREFIX + alignment); + usize page_size = max(this.page_size, size + DEFAULT_SIZE_PREFIX + alignment); void* mem = this.backing_allocator.alloc(page_size)?; DynamicArenaPage*! page = this.backing_allocator.alloc(DynamicArenaPage.sizeof); if (catch err = page) @@ -313,7 +313,7 @@ private fn void*! DynamicArenaAllocator.alloc_new(DynamicArenaAllocator* this, u } /** - * @require !alignment || @math::is_power_of_2(alignment) + * @require !alignment || math::is_power_of_2(alignment) * @require size > 0 * @require this */ diff --git a/lib/std/mem_allocator_fn.c3 b/lib/std/mem_allocator_fn.c3 index 3de78a2d3..d0021fbd0 100644 --- a/lib/std/mem_allocator_fn.c3 +++ b/lib/std/mem_allocator_fn.c3 @@ -16,7 +16,7 @@ private fn void*! null_allocator_fn(void *data, usize bytes, usize alignment, vo fn void*! libc_allocator_fn(void *unused, usize bytes, usize alignment, void* old_pointer, AllocationKind kind) @inline { if (!alignment) alignment = DEFAULT_MEM_ALIGNMENT; - assert(@math::is_power_of_2(alignment), "Alignment was not a power of 2"); + assert(math::is_power_of_2(alignment), "Alignment was not a power of 2"); void* data; switch (kind) @@ -60,5 +60,5 @@ fn void*! libc_allocator_fn(void *unused, usize bytes, usize alignment, void* ol libc::free(old_pointer); return null; } - @unreachable(); + unreachable(); } diff --git a/resources/examples/factorial_macro.c3 b/resources/examples/factorial_macro.c3 index d9ca66e92..33ab09593 100644 --- a/resources/examples/factorial_macro.c3 +++ b/resources/examples/factorial_macro.c3 @@ -3,7 +3,7 @@ macro int factorial($n) $if ($n == 0): return 1; $else: - return $n * @factorial($n - 1); + return $n * factorial($n - 1); $endif; } @@ -11,6 +11,6 @@ extern fn void printf(char *fmt, ...); fn void main() { - int x = @factorial(12); + int x = factorial(12); printf("12! = %d\n", x); } \ No newline at end of file diff --git a/resources/examples/fannkuch-redux.c3 b/resources/examples/fannkuch-redux.c3 index a7f2ea1a6..1c1c6e549 100644 --- a/resources/examples/fannkuch-redux.c3 +++ b/resources/examples/fannkuch-redux.c3 @@ -3,16 +3,12 @@ import std::array; import libc; import std::mem; -macro int max(int a, int b) -{ - return a > b ? a : b; -} fn int fannkuchredux(int n) { - int* perm = @array::make(int, n); - int* perm1 = @array::make(int, n); - int* count = @array::make(int, n); + int* perm = array::alloc(int, n); + int* perm1 = array::alloc(int, n); + int* count = array::alloc(int, n); int max_flips_count; int perm_count; int checksum; @@ -42,7 +38,7 @@ fn int fannkuchredux(int n) flips_count++; } - max_flips_count = @max(max_flips_count, flips_count); + max_flips_count = max(max_flips_count, flips_count); checksum += perm_count % 2 == 0 ? flips_count : -flips_count; /* Use incremental change to generate another permutation */ diff --git a/resources/examples/gameoflife.c3 b/resources/examples/gameoflife.c3 index 36bf1a750..54c54b4de 100644 --- a/resources/examples/gameoflife.c3 +++ b/resources/examples/gameoflife.c3 @@ -1,11 +1,5 @@ module game_of_life; -extern fn void printf(char *fmt, ...); -extern fn int atoi(char *val); -extern void *__stdoutp; -extern fn void fflush(void *std); -extern fn int rand(); -extern fn void* malloc(usize size); extern fn void usleep(int time); @@ -20,18 +14,18 @@ struct GameBoard fn void GameBoard.show(GameBoard *board) { - printf("\e[H"); + libc::printf("\e[H"); char* current = board.world; for (int y = 0; y < board.h; y++) { for (int x = 0; x < board.w; x++) { - printf(*current ? "\e[07m \e[m" : " "); + libc::printf(*current ? "\e[07m \e[m" : " "); current++; } - printf("\e[E"); + libc::printf("\e[E"); } - fflush(__stdoutp); + libc::fflush(libc::stdout()); } fn void GameBoard.evolve(GameBoard *board) @@ -65,20 +59,20 @@ fn int main(int c, char** v) { int w = 0; int h = 0; - if (c > 1) w = atoi(v[1]); - if (c > 2) h = atoi(v[2]); + if (c > 1) w = libc::atoi(v[1]); + if (c > 2) h = libc::atoi(v[2]); if (w <= 0) w = 30; if (h <= 0) h = 30; GameBoard board; board.w = w; board.h = h; - board.world = malloc((ulong)(h * w)); - board.temp = malloc((ulong)(h * w)); + board.world = libc::malloc((ulong)(h * w)); + board.temp = libc::malloc((ulong)(h * w)); for (int i = h * w - 1; i >= 0; i--) { - board.world[i] = rand() % 10 == 0 ? 1 : 0; + board.world[i] = libc::rand() % 10 == 0 ? 1 : 0; } for (int j = 0; j < 1000; j++) { diff --git a/resources/examples/guess_number.c3 b/resources/examples/guess_number.c3 index f48637473..ae41b0d56 100644 --- a/resources/examples/guess_number.c3 +++ b/resources/examples/guess_number.c3 @@ -3,7 +3,6 @@ import std::mem; import std::io; import libc; -extern fn void printf(char*, ...); extern fn isize getline(char** linep, usize* linecapp, CFile stream); struct Game @@ -24,7 +23,7 @@ int err_count = 0; fn int! askGuess(int high) { - printf("Guess a number between 1 and %d: ", high); + libc::printf("Guess a number between 1 and %d: ", high); char[] text = readLine()?; char* end = null; int value = (int)libc::strtol(text.ptr, &end, 10); @@ -35,7 +34,7 @@ fn int! askGuess(int high) fn char[]! readLine() { char* chars = mem::talloc(1024)?; - isize loaded = getline(&chars, &&(usize)1023, @libc::stdin()); + isize loaded = getline(&chars, &&(usize)1023, 2libc::stdin()); if (loaded < 0) return InputResult.FAILED_TO_READ!; chars[loaded] = 0; return chars[0..(loaded - 1)]; @@ -48,13 +47,13 @@ fn int! askGuessMulti(int high) int! result = askGuess(high); if (catch(result) == InputResult.NOT_AN_INT) { - printf("I didn't understand that.\n"); + libc::printf("I didn't understand that.\n"); err_count++; continue; } return result; } - @unreachable(); + unreachable(); } fn void! Game.play(Game *game) @@ -74,7 +73,7 @@ fn void Game.report(Game *game, int guess) if (guess > game.answer) return "too high"; return "the answer"; |}; - printf("%d is %.*s.\n", guess, (int)desc.len, desc.ptr); + libc::printf("%d is %.*s.\n", guess, (int)desc.len, desc.ptr); } fn void Game.update(Game *game, int guess) @@ -90,6 +89,6 @@ fn void! main() int answer = libc::rand() % high + 1; Game game = { .answer = answer, .high = high }; game.play(); - printf("Finished in %d guesses.\n", game.guesses); - printf("Total input errors: %d.\n", err_count); + libc::printf("Finished in %d guesses.\n", game.guesses); + libc::printf("Total input errors: %d.\n", err_count); } \ No newline at end of file diff --git a/resources/examples/notworking/madlibs.c3 b/resources/examples/notworking/madlibs.c3 index a78da432f..1a6dbe684 100644 --- a/resources/examples/notworking/madlibs.c3 +++ b/resources/examples/notworking/madlibs.c3 @@ -14,7 +14,7 @@ fn void main() Regex r; - r.initWithOptions("<.+?>", RegexOpt.GLOBAL) else @unreachable; + r.initWithOptions("<.+?>", RegexOpt.GLOBAL) else unreachable; defer r.destroy(); foreach (RegexMatch* match : r.match(story)) diff --git a/resources/examples/raylib/raylib_snake.c3 b/resources/examples/raylib/raylib_snake.c3 index dde0d347b..d2e4ea198 100644 --- a/resources/examples/raylib/raylib_snake.c3 +++ b/resources/examples/raylib/raylib_snake.c3 @@ -153,7 +153,7 @@ fn void update_game() snake[0].position.x += -SQUARE_SIZE; snake[0].position.y += 0; default: - @unreachable(); + unreachable(); } for (int i = 1; i < counter_tail; i++) { diff --git a/resources/examples/raylib/raylib_tetris.c3 b/resources/examples/raylib/raylib_tetris.c3 index 4ebe3db00..7da975cf8 100644 --- a/resources/examples/raylib/raylib_tetris.c3 +++ b/resources/examples/raylib/raylib_tetris.c3 @@ -462,7 +462,7 @@ fn void get_random_piece() incoming_piece[2][1] = MOVING; incoming_piece[3][1] = MOVING; //S inversa default: - @unreachable(); + unreachable(); } } diff --git a/resources/examples/spectralnorm.c3 b/resources/examples/spectralnorm.c3 index aa1b8cbc8..dc205ded2 100644 --- a/resources/examples/spectralnorm.c3 +++ b/resources/examples/spectralnorm.c3 @@ -46,9 +46,9 @@ fn void eval_AtA_times_u(double[] u, double[] atau) @noinline fn int main(int argc, char **argv) { int n = (argc == 2) ? atoi(argv[1]) : 2000; - temparr = @array::make(double, n); - double[] u = @array::make(double, n); - double[] v = @array::make(double, n); + temparr = array::alloc(double, n); + double[] u = array::alloc(double, n); + double[] v = array::alloc(double, n); foreach(&uval : u) *uval = 1; for (int i = 0; i < 10; i++) { diff --git a/resources/testfragments/boolerr.c3 b/resources/testfragments/boolerr.c3 index 24f8b59d9..289bd33eb 100644 --- a/resources/testfragments/boolerr.c3 +++ b/resources/testfragments/boolerr.c3 @@ -52,13 +52,13 @@ fn Doc! readDoc(char[] url) { if (contains(url, "fail")) return ReadError.BAD_READ!; if (contains(url, "head-missing")) return { .head = null }; - if (contains(url, "title-missing")) return { @dupe(Head { .title = null })? }; - if (contains(url, "title-empty")) return { @dupe(Head { .title = @dupe((char[])"")? })? }; + if (contains(url, "title-missing")) return { dupe(Head { .title = null })? }; + if (contains(url, "title-empty")) return { dupe(Head { .title = dupe((char[])"")? })? }; // Not particularly elegant due to missing string functions. int len = libc::snprintf(null, 0, "Title of %.*s", (int)url.len, url.ptr); char* str = mem::alloc_checked(len + 1)?; libc::snprintf(str, len + 1, "Title of %.*s", (int)url.len, url.ptr); - return { @dupe(Head { .title = @dupe(str[..len - 1])? })? }; + return { dupe(Head { .title = dupe(str[..len - 1])? })? }; } fn Summary buildSummary(Doc doc) @@ -132,13 +132,13 @@ fn void main() Allocator allocator = mem::dynamic_arena_allocator(&dynamic_arena); foreach (char[] url : URLS) { - @mem::with_allocator(allocator) + mem::@with_allocator(allocator) { // Yes, it's pretty onerous to print strings for the moment in C3 libc::printf(`Checking "https://%.*s/":` "\n", (int)url.len, url.ptr); Summary summary = readAndBuildSummary(url); libc::printf(" Summary: "); - summary.print(@libc::stdout()); + summary.print(libc::stdout()); libc::printf("\n"); char[] title_sure = summary.title ? *summary.title : ""; libc::printf(" Title: %.*s\n", (int)title_sure.len, title_sure.ptr); diff --git a/resources/testfragments/raylibtest.c3 b/resources/testfragments/raylibtest.c3 index ed3f91d1c..634a5f6a1 100644 --- a/resources/testfragments/raylibtest.c3 +++ b/resources/testfragments/raylibtest.c3 @@ -462,7 +462,7 @@ fn void get_random_piece() incoming_piece[2][1] = MOVING; incoming_piece[3][1] = MOVING; //S inversa default: - @unreachable(); + unreachable(); } } diff --git a/resources/testfragments/toposort.c3 b/resources/testfragments/toposort.c3 index afdb1f0d3..1f88d588a 100644 --- a/resources/testfragments/toposort.c3 +++ b/resources/testfragments/toposort.c3 @@ -25,15 +25,15 @@ struct TopoList fn void sort(InputPair[] pairs, uint elements) { - InputPair[] result = @array::make(InputPair, pairs.len); - TopoList* top = @array::make(TopoList, elements); + InputPair[] result = array::alloc(InputPair, pairs.len); + TopoList* top = array::alloc(TopoList, elements); for (int i = 0; i < pairs.len; i++) { InputPair pair = pairs[i]; assert(pair.value >= 0 && pair.value < elements); assert(pair.successor >= 0 && pair.successor < elements); top[pair.successor].count++; - Entry* successor_entry = @mem::malloc(Entry); + Entry* successor_entry = mem::malloc(Entry); *successor_entry = { pair.successor, null }; Entry** next_ref = &top[pair.value].next; while (*next_ref) @@ -42,7 +42,7 @@ fn void sort(InputPair[] pairs, uint elements) } *next_ref = successor_entry; } - int[] intout = @array::make(int, elements); + int[] intout = array::alloc(int, elements); int count = 0; while LOOP: (1) { diff --git a/src/compiler/ast.c b/src/compiler/ast.c index f1026a7ac..d8ea2945e 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -275,7 +275,6 @@ bool expr_is_pure(Expr *expr) case EXPR_RETHROW: case EXPR_HASH_IDENT: case EXPR_MACRO_BLOCK: - case EXPR_MACRO_EXPANSION: case EXPR_FLATPATH: case EXPR_INITIALIZER_LIST: case EXPR_DESIGNATED_INITIALIZER_LIST: @@ -490,4 +489,15 @@ bool ast_is_not_empty(Ast *ast) return ast_is_not_empty(stmt); } return false; -} \ No newline at end of file +} + +AttributeType attribute_by_name(Attr *attr) +{ + const char *attribute = attr->name; + for (unsigned i = 0; i < NUMBER_OF_ATTRIBUTES; i++) + { + if (attribute_list[i] == attribute) return (AttributeType)i; + } + return ATTRIBUTE_NONE; +} + diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index ae03c1abc..50a64a498 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -793,12 +793,6 @@ typedef struct }; } ExprCtCall; -typedef struct -{ - Expr *inner; - Decl *decl; -} ExprMacroExpansion; - typedef struct { CastKind kind : 8; @@ -955,7 +949,6 @@ struct Expr_ ExprIdentifierRaw ct_ident_expr; // 24 ExprCtCall ct_call_expr; // 24 ExprIdentifierRaw ct_macro_ident_expr; // 24 - ExprMacroExpansion macro_expansion_expr; // 16 ExprIdentifierRaw hash_ident_expr; // 24 TypeInfo *typeid_expr; // 8 ExprBodyExpansion body_expansion_expr; // 24 @@ -1614,6 +1607,13 @@ extern const char *kw_check_assign; extern const char *kw_argc; extern const char *kw_argv; extern const char *kw_mainstub; +extern const char *kw_at_ensure; +extern const char *kw_at_require; +extern const char *kw_at_pure; +extern const char *kw_at_optreturn; +extern const char *kw_at_param; +extern const char *kw_at_return; +extern const char *kw_at_checked; ARENA_DEF(chars, char) ARENA_DEF(ast, Ast) @@ -1659,6 +1659,8 @@ typedef enum CmpRes_ CMP_GT = 1, } CmpRes; +AttributeType attribute_by_name(Attr *attr); + void type_setup(PlatformTarget *target); Float float_add(Float op1, Float op2); Float float_sub(Float op1, Float op2); @@ -1941,7 +1943,7 @@ bool sema_analyse_ct_assert_stmt(SemaContext *context, Ast *statement); bool sema_analyse_statement(SemaContext *context, Ast *statement); bool sema_expr_analyse_assign_right_side(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped_var); -bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool is_macro, bool failable); +bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool failable); Decl *sema_resolve_symbol_in_current_dynamic_scope(SemaContext *context, const char *symbol); Decl *sema_find_decl_in_modules(Module **module_list, Path *path, const char *interned_name); Decl *unit_resolve_parameterized_symbol(CompilationUnit *unit, NameResolve *name_resolve); diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 748f59dd1..44e7eab9a 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -206,11 +206,6 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) return expr; case EXPR_COMPILER_CONST: return expr; - case EXPR_MACRO_EXPANSION: - SCOPE_FIXUP_START - MACRO_COPY_EXPR(expr->macro_expansion_expr.inner); - SCOPE_FIXUP_END; - return expr; case EXPR_DESIGNATOR: expr->designator_expr.path = macro_copy_designator_list(c, expr->designator_expr.path); MACRO_COPY_EXPR(expr->designator_expr.value); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 436e2ce5e..402849fb9 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -198,7 +198,6 @@ typedef enum EXPR_FORCE_UNWRAP, EXPR_HASH_IDENT, EXPR_MACRO_BLOCK, - EXPR_MACRO_EXPANSION, EXPR_IDENTIFIER, EXPR_RETVAL, EXPR_FLATPATH, @@ -411,13 +410,16 @@ typedef enum TOKEN_HASH_CONST_IDENT, // #FOOBAR TOKEN_HASH_TYPE_IDENT, // #Foobar + TOKEN_AT_IDENT, // @macro + TOKEN_AT_CONST_IDENT, // @MACRO + TOKEN_AT_TYPE_IDENT, // @Macro + TOKEN_STRING, // "Teststring" TOKEN_INTEGER, // 123 0x23 0b10010 0o327 TOKEN_CHAR_LITERAL, // 'a' 'FO' 'BARS' '\u1232' TOKEN_REAL, // 0x23.2p-2a 43.23e23 TOKEN_BYTES, // Base64 or Hex - TOKEN_DOC_DIRECTIVE, // Doc Directive TOKEN_DOC_COMMENT, // Doc Comment start // Keywords @@ -490,14 +492,7 @@ typedef enum TOKEN_DOCS_START, // /** TOKEN_DOCS_END, // */ (may start with an arbitrary number of `*` - TOKEN_DOCS_ENSURE, // @ensure - TOKEN_DOCS_REQUIRE, // @require - TOKEN_DOCS_CHECKED, // @checked - TOKEN_DOCS_PARAM, // @param - TOKEN_DOCS_RETURN, // @return - TOKEN_DOCS_OPTRETURN, // @optreturn - TOKEN_DOCS_PURE, // @pure - + TOKEN_DOC_DIRECTIVE, // Any doc directive TOKEN_EOF, // \n - SHOULD ALWAYS BE THE LAST TOKEN. @@ -669,6 +664,7 @@ typedef enum ATTRIBUTE_OVERLAP, ATTRIBUTE_AUTOIMPORT, ATTRIBUTE_OPERATOR, + ATTRIBUTE_PURE, ATTRIBUTE_NONE, NUMBER_OF_ATTRIBUTES = ATTRIBUTE_NONE, } AttributeType; diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index bafebeb35..38ad22c25 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -1160,33 +1160,23 @@ INLINE void skip_to_doc_line_end(Lexer *lexer) } -static bool parse_doc_directive(Lexer *lexer) +static bool lex_doc_directive(Lexer *lexer) { begin_new_token(lexer); next(lexer); // Then our keyword - if (!scan_ident(lexer, TOKEN_IDENT, TOKEN_CONST, TOKEN_TYPE_IDENT, '@')) + if (!scan_ident(lexer, TOKEN_AT_IDENT, TOKEN_AT_CONST_IDENT, TOKEN_AT_TYPE_IDENT, '@')) { return false; } - switch (lexer->token_type) + if (lexer->token_type != TOKEN_AT_IDENT) { - case TOKEN_DOCS_ENSURE: - case TOKEN_DOCS_CHECKED: - case TOKEN_DOCS_REQUIRE: - case TOKEN_DOCS_OPTRETURN: - case TOKEN_DOCS_PARAM: - case TOKEN_DOCS_RETURN: - case TOKEN_DOCS_PURE: - return true; - case TOKEN_IDENT: - lexer->token_type = TOKEN_DOC_DIRECTIVE; - return true; - default: - add_error_token_at_current(lexer, "A doc directive was expected."); - return false; + add_error_token_at_current(lexer, "A doc directive was expected."); + return false; } + lexer->token_type = TOKEN_DOC_DIRECTIVE; + return true; } static bool scan_doc_line(Lexer *lexer) @@ -1224,7 +1214,7 @@ RETRY:; // If we have '@' [_A-Za-z] then parse the directive if (c == '@') { - return parse_doc_directive(lexer); + return lex_doc_directive(lexer); } // Otherwise scan to the end of the line @@ -1285,6 +1275,10 @@ static bool lexer_scan_token_inner(Lexer *lexer) case '\n': return scan_doc_line(lexer); case '@': + if (char_is_letter(peek(lexer))) + { + return scan_ident(lexer, TOKEN_AT_IDENT, TOKEN_AT_CONST_IDENT, TOKEN_AT_TYPE_IDENT, '@'); + } return return_token(lexer, TOKEN_AT, "@"); case '\'': return scan_char(lexer); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 85aa9ffa8..0e15e72ed 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1347,7 +1347,6 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_ break; case CAST_ENUMLOW: llvm_value_rvalue(c, value); - value->value = value->value; break; case CAST_STST: llvm_value_addr(c, value); @@ -5546,7 +5545,6 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) { case NON_RUNTIME_EXPR: case EXPR_COND: - case EXPR_MACRO_EXPANSION: UNREACHABLE case EXPR_RETVAL: *value = c->retval; diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index b7e69830f..11b52a30c 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -345,20 +345,6 @@ bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool * } } -/** - * macro_expansion ::= '@' non_at_expression - */ -static Expr *parse_macro_expansion(ParseContext *c, Expr *left) -{ - assert(!left && "Unexpected left hand side"); - Expr *macro_expression = EXPR_NEW_TOKEN(EXPR_MACRO_EXPANSION); - advance_and_verify(c, TOKEN_AT); - ASSIGN_EXPR_OR_RET(Expr * inner, parse_precedence(c, PREC_MACRO), poisoned_expr); - macro_expression->macro_expansion_expr.inner = inner; - assert(inner); - RANGE_EXTEND_PREV(macro_expression); - return macro_expression; -} /** @@ -712,32 +698,37 @@ static Expr *parse_call_expr(ParseContext *c, Expr *left) { if (!parse_attribute(c, &attr)) return poisoned_expr; if (!attr) break; - if (attr->name == kw_pure) + + AttributeType attr_type = attribute_by_name(attr); + int new_inline = attr_type == ATTRIBUTE_INLINE; + switch (attr_type) { - if (call->call_expr.attr_pure) - { - SEMA_ERROR(attr, "Repeat of the same attribute is not allowed."); + case ATTRIBUTE_PURE: + if (call->call_expr.attr_pure) + { + SEMA_ERROR(attr, "Repeat of the same attribute is not allowed."); + return poisoned_expr; + } + call->call_expr.attr_pure = true; + continue; + case ATTRIBUTE_INLINE: + case ATTRIBUTE_NOINLINE: + if (force_inline == new_inline) + { + SEMA_ERROR(attr, "Repeat of the same attribute is not allowed."); + return poisoned_expr; + } + if (force_inline != -1) + { + SEMA_ERROR(attr, "@inline and @noinline cannot be combined"); + return poisoned_expr; + } + force_inline = new_inline; + continue; + default: + SEMA_ERROR(attr, "Only '@pure', '@inline' and '@noinline' are valid attributes for calls."); return poisoned_expr; - } - call->call_expr.attr_pure = true; - continue; } - if (attr->name != kw_inline && attr->name != kw_noinline && attr->name != kw_pure) - { - SEMA_ERROR(attr, "Only '@pure', '@inline' and '@noinline' are valid attributes for calls."); - return poisoned_expr; - } - int new_inline = attr->name == kw_inline; - if (new_inline == force_inline) - { - SEMA_ERROR(attr, "Repeat of the same attribute is not allowed."); - return poisoned_expr; - } - if (force_inline != -1) - { - SEMA_ERROR(attr, "@inline and @noinline cannot be combined"); - } - force_inline = new_inline; } if (force_inline != -1) { @@ -1029,6 +1020,7 @@ static Expr *parse_identifier_starting_expression(ParseContext *c, Expr *left) { case TOKEN_IDENT: case TOKEN_CONST_IDENT: + case TOKEN_AT_IDENT: { Expr *expr = parse_identifier(c, NULL); expr->identifier_expr.path = path; @@ -1752,7 +1744,6 @@ ParseRule rules[TOKEN_EOF + 1] = { [TOKEN_INTEGER] = { parse_integer, NULL, PREC_NONE }, [TOKEN_BUILTIN] = { parse_builtin, NULL, PREC_NONE }, [TOKEN_CHAR_LITERAL] = { parse_char_lit, NULL, PREC_NONE }, - [TOKEN_AT] = { parse_macro_expansion, NULL, PREC_NONE }, [TOKEN_STRING] = { parse_string_literal, NULL, PREC_NONE }, [TOKEN_REAL] = { parse_double, NULL, PREC_NONE }, [TOKEN_OR] = { NULL, parse_binary, PREC_OR }, @@ -1776,6 +1767,7 @@ ParseRule rules[TOKEN_EOF + 1] = { [TOKEN_CT_CONST_IDENT] = { parse_ct_ident, NULL, PREC_NONE }, [TOKEN_CT_TYPE_IDENT] = { parse_type_identifier, NULL, PREC_NONE }, [TOKEN_HASH_IDENT] = { parse_hash_ident, NULL, PREC_NONE }, + [TOKEN_AT_IDENT] = { parse_identifier, NULL, PREC_NONE }, //[TOKEN_HASH_TYPE_IDENT] = { parse_type_identifier, NULL, PREC_NONE } [TOKEN_CT_SIZEOF] = { parse_ct_sizeof, NULL, PREC_NONE }, diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index e25c60d8d..6f19d9bea 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -858,29 +858,26 @@ Decl *parse_var_decl(ParseContext *c) bool parse_attribute(ParseContext *c, Attr **attribute_ref) { - if (!try_consume(c, TOKEN_AT)) - { - *attribute_ref = NULL; - return true; - } bool had_error; Path *path = parse_path_prefix(c, &had_error); if (had_error) return false; - + if (!tok_is(c, TOKEN_AT_IDENT) && !tok_is(c, TOKEN_AT_TYPE_IDENT)) + { + if (path) + { + SEMA_ERROR_HERE("Expected an attribute name."); + return false; + } + *attribute_ref = NULL; + return true; + } Attr *attr = CALLOCS(Attr); attr->name = symstr(c); attr->span = c->span; attr->path = path; - if (tok_is(c, TOKEN_TYPE_IDENT) || tok_is(c, TOKEN_TYPE_IDENT)) - { - advance(c); - } - else - { - TRY_CONSUME_OR_RET(TOKEN_IDENT, "Expected an attribute", false); - } + advance(c); if (tok_is(c, TOKEN_LPAREN)) { @@ -897,11 +894,7 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref) * ; * * attribute - * : AT IDENT - * | AT path IDENT - * | AT IDENT '(' constant_expression ')' - * | AT path IDENT '(' constant_expression ')' - * ; + * : path AT_IDENT | AT_TYPE_IDENT ('(' constant_expression ')')? * * @return true if parsing succeeded, false if recovery is needed */ @@ -1441,10 +1434,9 @@ static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl * // Do we have trailing block parameters? if (try_consume(c, TOKEN_EOS)) { - // Consume '@' IDENT - TRY_CONSUME_OR_RET(TOKEN_AT, "Expected an ending ')' or a block parameter on the format '@block(...).", false); + // Consume AT_IDENT Decl *body_param = decl_new(DECL_BODYPARAM, symstr(c), c->span, visibility); - if (!consume_ident(c, "variable name")) return false; + TRY_CONSUME_OR_RET(TOKEN_AT_IDENT, "Expected an ending ')' or a block parameter on the format '@block(...).", false); if (try_consume(c, TOKEN_LPAREN)) { if (!parse_parameters(c, visibility, &body_param->body_params)) return false; @@ -1694,16 +1686,16 @@ static inline Decl *parse_define(ParseContext *c, Visibility visibility) } } -static inline bool parse_is_func_name(ParseContext *c) +static inline bool parse_is_macro_name(ParseContext *c) { - return tok_is(c, TOKEN_IDENT) && peek(c) != TOKEN_SCOPE; + return (tok_is(c, TOKEN_IDENT) && peek(c) != TOKEN_SCOPE) || tok_is(c, TOKEN_AT_IDENT); } /** - * func_header ::= type '!'? (type '.')? IDENT - * macro_header ::= (type '!'?)? (type '.')? IDENT + * func_header ::= type '!'? (type '.')? (IDENT | MACRO_IDENT) + * macro_header ::= (type '!'?)? (type '.')? (IDENT | MACRO_IDENT) */ -static inline bool parse_func_macro_header(ParseContext *c, bool rtype_is_optional, +static inline bool parse_func_macro_header(ParseContext *c, bool is_macro, TypeInfoId *rtype_ref, TypeInfoId *method_type_ref, const char **name_ref, SourceSpan *name_span) { @@ -1711,7 +1703,7 @@ static inline bool parse_func_macro_header(ParseContext *c, bool rtype_is_option TypeInfo *method_type = NULL; // 1. If we have a macro and see the name, we're done. - if (rtype_is_optional && parse_is_func_name(c)) + if (is_macro && parse_is_macro_name(c)) { goto RESULT; } @@ -1720,7 +1712,7 @@ static inline bool parse_func_macro_header(ParseContext *c, bool rtype_is_option ASSIGN_TYPE_OR_RET(rtype, parse_failable_type(c), false); // 4. We might have a type here, if so then we read it. - if (!tok_is(c, TOKEN_DOT) && !parse_is_func_name(c)) + if (!tok_is(c, TOKEN_DOT) && !parse_is_macro_name(c)) { ASSIGN_TYPE_OR_RET(method_type, parse_type(c), false); } @@ -1732,7 +1724,7 @@ static inline bool parse_func_macro_header(ParseContext *c, bool rtype_is_option if (!method_type) { // 5b. If the rtype is not optional or the return type was a failable, then this is an error. - if (!rtype_is_optional || rtype->failable) + if (!is_macro || rtype->failable) { SEMA_ERROR_LAST("This looks like you are declaring a method without a return type?"); return false; @@ -1750,7 +1742,17 @@ static inline bool parse_func_macro_header(ParseContext *c, bool rtype_is_option RESULT: *name_ref = symstr(c); *name_span = c->span; - TRY_CONSUME_OR_RET(TOKEN_IDENT, "Expected a name here.", false); + if (is_macro && c->tok != TOKEN_IDENT && c->tok != TOKEN_AT_IDENT) + { + sema_error_at(c->span, "Expected a macro name here, e.g. '@someName' or 'someName'."); + return false; + } + else if (!is_macro && c->tok != TOKEN_IDENT) + { + sema_error_at(c->span, "Expected a function name here, e.g. 'someName'."); + return false; + } + advance(c); *rtype_ref = rtype ? type_infoid(rtype) : 0; *method_type_ref = method_type ? type_infoid(method_type) : 0; return true; @@ -1771,12 +1773,10 @@ static inline Decl *parse_macro_declaration(ParseContext *c, Visibility visibili TypeInfoId *rtype_ref = &decl->macro_decl.rtype; TypeInfoId *method_type_ref = &decl->macro_decl.type_parent; if (!parse_func_macro_header(c, true, rtype_ref, method_type_ref, &decl->name, &decl->span)) return poisoned_decl; - const char *block_parameter = NULL; if (!parse_macro_arguments(c, visibility, &decl->macro_decl.parameters, &decl->macro_decl.body_param)) return poisoned_decl; if (!parse_attributes(c, &decl->attributes)) return poisoned_decl; - ASSIGN_ASTID_OR_RET(decl->macro_decl.body, parse_stmt(c), poisoned_decl); return decl; } @@ -1980,6 +1980,11 @@ static inline Decl *parse_func_definition(ParseContext *c, Visibility visibility TypeInfoId *rtype_id_ref = &func->func_decl.function_signature.returntype; TypeInfoId *method_type_ref = &func->func_decl.type_parent; if (!parse_func_macro_header(c, false, rtype_id_ref, method_type_ref, &func->name, &func->span)) return poisoned_decl; + if (func->name[0] == '@') + { + SEMA_ERROR(func, "Function names may not use '@'."); + return false; + } if (!parse_parameter_list(c, visibility, &(func->func_decl.function_signature), is_interface)) return poisoned_decl; if (!parse_attributes(c, &func->attributes)) return poisoned_decl; @@ -2230,38 +2235,56 @@ static bool parse_docs(ParseContext *c, AstId *docs_ref) // Spin past the lines and line ends switch (c->tok) { - case TOKEN_DOCS_PARAM: - if (!parse_doc_param(c, &last)) return false; - break; - case TOKEN_DOCS_RETURN: - advance(c); - if (!consume(c, TOKEN_STRING, "Expected a string description.")) return false; - break; - case TOKEN_DOCS_REQUIRE: - if (!parse_doc_contract(c, &docs_ref, DOC_DIRECTIVE_REQUIRE)) return false; - break; - case TOKEN_DOCS_CHECKED: - if (!parse_doc_contract(c, &docs_ref, DOC_DIRECTIVE_CHECKED)) return false; - break; - case TOKEN_DOCS_ENSURE: - if (!parse_doc_contract(c, &docs_ref, DOC_DIRECTIVE_ENSURE)) return false; - break; - case TOKEN_DOCS_OPTRETURN: - if (!parse_doc_errors(c, &docs_ref)) return false; - break; - case TOKEN_DOCS_PURE: - { - Ast *ast = ast_new_curr(c, AST_DOC_STMT); - ast->doc_stmt.kind = DOC_DIRECTIVE_PURE; - *docs_ref = astid(ast); - docs_ref = &ast->next; - advance(c); - break; - } case TOKEN_DOC_DIRECTIVE: - advance(c); - // Ignore - break; + { + const char *name = symstr(c); + if (name == kw_at_param) + { + if (!parse_doc_param(c, &last)) return false; + break; + } + else if (name == kw_at_return) + { + advance(c); + if (!consume(c, TOKEN_STRING, "Expected a string description.")) return false; + break; + } + else if (name == kw_at_require) + { + if (!parse_doc_contract(c, &docs_ref, DOC_DIRECTIVE_REQUIRE)) return false; + break; + } + else if (name == kw_at_checked) + { + if (!parse_doc_contract(c, &docs_ref, DOC_DIRECTIVE_CHECKED)) return false; + break; + } + else if (name == kw_at_ensure) + { + if (!parse_doc_contract(c, &docs_ref, DOC_DIRECTIVE_ENSURE)) return false; + break; + } + else if (name == kw_at_optreturn) + { + if (!parse_doc_errors(c, &docs_ref)) return false; + break; + } + else if (name == kw_at_pure) + { + Ast *ast = ast_new_curr(c, AST_DOC_STMT); + ast->doc_stmt.kind = DOC_DIRECTIVE_PURE; + *docs_ref = astid(ast); + docs_ref = &ast->next; + advance(c); + break; + } + else + { + advance(c); + // Ignore + break; + } + } case TOKEN_DOCS_END: advance(c); return true; diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index 9b85999f2..33eaa10dd 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -846,7 +846,10 @@ Ast *parse_stmt(ParseContext *c) case TOKEN_STATIC: // Static means declaration! case TOKEN_CONST: // Const means declaration! return parse_declaration_stmt(c); + case TOKEN_AT_TYPE_IDENT: + case TOKEN_AT_CONST_IDENT: case TOKEN_AT: + case TOKEN_AT_IDENT: return parse_expr_stmt(c); case TOKEN_RETURN: { @@ -1028,13 +1031,6 @@ Ast *parse_stmt(ParseContext *c) SEMA_ERROR_HERE("Reached the end of the file when expecting a statement."); return poisoned_ast; case TOKEN_DOC_DIRECTIVE: - case TOKEN_DOCS_ENSURE: - case TOKEN_DOCS_REQUIRE: - case TOKEN_DOCS_CHECKED: - case TOKEN_DOCS_PARAM: - case TOKEN_DOCS_RETURN: - case TOKEN_DOCS_OPTRETURN: - case TOKEN_DOCS_PURE: SEMA_ERROR_HERE("Unexpectedly encountered doc directives."); return poisoned_ast; } diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index e741d12da..fe66bce5f 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -775,7 +775,6 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type) case EXPR_DESIGNATOR: case EXPR_EXPR_BLOCK: case EXPR_MACRO_BLOCK: - case EXPR_MACRO_EXPANSION: case EXPR_IDENTIFIER: case EXPR_SLICE_ASSIGN: case EXPR_SLICE: @@ -930,7 +929,6 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type) case EXPR_DESIGNATOR: case EXPR_EXPR_BLOCK: case EXPR_MACRO_BLOCK: - case EXPR_MACRO_EXPANSION: case EXPR_IDENTIFIER: case EXPR_SLICE_ASSIGN: case EXPR_SLICE: diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index d44e4b8e2..3839dd9ce 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -269,7 +269,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl * { Attr *attribute = attributes[j]; if (!sema_analyse_attribute(context, attribute, ATTR_GLOBAL)) return false; - if (attribute->name == kw_align) + if (attribute->name == attribute_list[ATTRIBUTE_ALIGN]) { member_alignment = attribute->alignment; // Update total alignment if we have a member that has bigger alignment. @@ -1075,16 +1075,6 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl) return unit_add_method_like(context->unit, type, decl); } -static inline AttributeType attribute_by_name(Attr *attr) -{ - const char *attribute = attr->name; - for (unsigned i = 0; i < NUMBER_OF_ATTRIBUTES; i++) - { - if (attribute_list[i] == attribute) return (AttributeType)i; - } - return ATTRIBUTE_NONE; -} - static const char *attribute_domain_to_string(AttributeDomain domain) { @@ -1151,6 +1141,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute [ATTRIBUTE_OVERLAP] = ATTR_BITSTRUCT, [ATTRIBUTE_AUTOIMPORT] = ATTR_MACRO | ATTR_FUNC, [ATTRIBUTE_OPERATOR] = ATTR_MACRO | ATTR_FUNC, + [ATTRIBUTE_PURE] = ATTR_CALL, }; if ((attribute_domain[type] & domain) != domain) @@ -1669,6 +1660,7 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) decl->macro_decl.unit = context->unit; Decl **parameters = decl->macro_decl.parameters; unsigned param_count = vec_size(parameters); + bool is_function_like = true; for (unsigned i = 0; i < param_count; i++) { Decl *param = parameters[i]; @@ -1677,8 +1669,10 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) switch (param->var.kind) { case VARDECL_PARAM_EXPR: - case VARDECL_PARAM_CT: case VARDECL_PARAM_REF: + is_function_like = false; + FALLTHROUGH; + case VARDECL_PARAM_CT: if (is_generic) { SEMA_ERROR(param, "Only regular parameters and type parameters are allowed for generic functions."); @@ -1715,6 +1709,7 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) param->resolve_status = RESOLVE_DONE; } DeclId body_param = decl->macro_decl.body_param; + if (body_param) is_function_like = false; if (is_generic && body_param) { SEMA_ERROR(declptr(body_param), "Trailing block syntax is not allowed for generic functions."); @@ -1756,6 +1751,11 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) } bool pure = false; if (!sema_analyse_doc_header(decl->macro_decl.docs, decl->macro_decl.parameters, body_parameters, &pure)) return decl_poison(decl); + if (decl->name[0] != '@' && !is_function_like) + { + SEMA_ERROR(decl, "Names of non-function like macros (i.e. a macro with a trailing body, ref or expression parameters, must start with '@'."); + return false; + } if (decl->macro_decl.type_parent) { if (!sema_analyse_macro_method(context, decl)) return decl_poison(decl); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 5c011a73d..3d05207f9 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -452,7 +452,6 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) case EXPR_CT_IDENT: case EXPR_FLATPATH: case EXPR_COMPOUND_LITERAL: - case EXPR_MACRO_EXPANSION: case EXPR_COMPILER_CONST: case EXPR_POISONED: case EXPR_ARGV_TO_SUBARRAY: @@ -885,6 +884,19 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, DEBUG_LOG("Now resolving %s", expr->identifier_expr.ident); + DeclId body_param; + if (!expr->identifier_expr.path && context->current_macro && (body_param = context->current_macro->macro_decl.body_param)) + { + if (expr->identifier_expr.ident == declptr(body_param)->name) + { + expr->expr_kind = EXPR_MACRO_BODY_EXPANSION; + expr->body_expansion_expr.ast = NULL; + expr->body_expansion_expr.declarations = NULL; + expr->resolve_status = RESOLVE_NOT_DONE; + expr->type = type_void; + return true; + } + } // Just start with inference if (!expr->identifier_expr.path && to) { @@ -977,44 +989,6 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, return true; } -static inline bool sema_expr_analyse_macro_expansion(SemaContext *context, Expr *expr) -{ - Expr *inner = expr->macro_expansion_expr.inner; - if (inner->expr_kind == EXPR_IDENTIFIER) - { - DeclId body_param = context->current_macro ? context->current_macro->macro_decl.body_param : 0; - if (body_param && !inner->identifier_expr.path && inner->identifier_expr.ident == declptr(body_param)->name) - { - expr->expr_kind = EXPR_MACRO_BODY_EXPANSION; - expr->body_expansion_expr.ast = NULL; - expr->body_expansion_expr.declarations = NULL; - expr->resolve_status = RESOLVE_NOT_DONE; - expr->type = type_void; - return true; - } - } - if (!sema_analyse_expr_lvalue(context, inner)) return false; - Decl *decl; - switch (inner->expr_kind) - { - case EXPR_IDENTIFIER: - decl = inner->identifier_expr.decl; - break; - case EXPR_ACCESS: - decl = inner->access_expr.ref; - break; - default: - SEMA_ERROR(expr, "Expected a macro identifier here."); - return false; - } - if (decl->decl_kind != DECL_MACRO) - { - SEMA_ERROR(inner, "Expected a macro identifier here."); - return false; - } - expr->macro_expansion_expr.decl = decl; - return true; -} static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *expr) { @@ -2137,7 +2111,7 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) return success; } -bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool is_macro, bool failable) +bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool failable) { expr->call_expr.is_type_method = struct_var != NULL; if (decl == NULL) @@ -2147,37 +2121,17 @@ bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl switch (decl->decl_kind) { case DECL_MACRO: - if (!is_macro) - { - SEMA_ERROR(expr, "A macro neeeds to be called with a '@' prefix, please add it."); - return false; - } expr->call_expr.func_ref = declid(decl); expr->call_expr.is_func_ref = true; return sema_expr_analyse_macro_call(context, expr, struct_var, decl, failable); case DECL_VAR: - if (is_macro) - { - SEMA_ERROR(expr, "A function cannot be called with a '@' prefix, please remove it."); - return false; - } assert(struct_var == NULL); return sema_expr_analyse_var_call(context, expr, decl->type->canonical, failable || IS_FAILABLE(decl)); case DECL_FUNC: - if (is_macro) - { - SEMA_ERROR(expr, "A function cannot be called with a '@' prefix, please remove it."); - return false; - } expr->call_expr.func_ref = declid(decl); expr->call_expr.is_func_ref = true; return sema_expr_analyse_func_call(context, expr, decl, struct_var, failable); case DECL_GENERIC: - if (is_macro) - { - SEMA_ERROR(expr, "A generic function cannot be called with a '@' prefix, please remove it."); - return false; - } expr->call_expr.func_ref = declid(decl); expr->call_expr.is_func_ref = true; return sema_expr_analyse_generic_call(context, expr, struct_var, decl, failable); @@ -2432,7 +2386,6 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr) bool failable = func_expr->type && IS_FAILABLE(func_expr); Decl *decl; Expr *struct_var = NULL; - bool macro = false; switch (func_expr->expr_kind) { case EXPR_BUILTIN: @@ -2444,15 +2397,10 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr) decl = func_expr->access_expr.ref; if (decl->decl_kind == DECL_FUNC || decl->decl_kind == DECL_MACRO) { - macro = decl->decl_kind == DECL_MACRO; - if (!macro) expr_insert_addr(func_expr->access_expr.parent); + if (decl->decl_kind != DECL_MACRO) expr_insert_addr(func_expr->access_expr.parent); struct_var = func_expr->access_expr.parent; } break; - case EXPR_MACRO_EXPANSION: - decl = func_expr->macro_expansion_expr.decl; - macro = true; - break; case EXPR_TYPEINFO: if (func_expr->type_expr->resolve_status == RESOLVE_DONE) { @@ -2477,7 +2425,7 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr) } } decl = decl ? decl_flatten(decl) : NULL; - return sema_expr_analyse_general_call(context, expr, decl, struct_var, macro, failable); + return sema_expr_analyse_general_call(context, expr, decl, struct_var, failable); } static void sema_deref_array_pointers(Expr *expr) @@ -2965,18 +2913,6 @@ RETRY: // A path is not allowed. if (child->identifier_expr.path) break; return child; - case EXPR_MACRO_EXPANSION: - child = child->macro_expansion_expr.inner; - switch (child->expr_kind) - { - case EXPR_IDENTIFIER: - case EXPR_HASH_IDENT: - return sema_expr_resolve_access_child(context, child, missing); - default: - SEMA_ERROR(child, "Expected a macro name."); - return NULL; - } - break; case EXPR_HASH_IDENT: { Decl *decl = sema_resolve_symbol(context, child->hash_ident_expr.identifier, NULL, child->span); @@ -3044,7 +2980,7 @@ static inline void expr_replace_with_enum_array(Expr *enum_array_expr, Decl *enu enum_array_expr->resolve_status = RESOLVE_NOT_DONE; } -static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, TypeInfo *parent, bool was_group, bool is_macro, Expr *identifier) +static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, TypeInfo *parent, bool was_group, Expr *identifier) { assert(identifier->expr_kind == EXPR_IDENTIFIER); @@ -3153,13 +3089,6 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp } - // 12b. If the member was *not* a macro but was prefixed with `@` then that's an error. - if (member->decl_kind != DECL_MACRO && is_macro) - { - SEMA_ERROR(expr, "'@' should only be placed in front of macro names."); - return false; - } - if (member->decl_kind == DECL_VAR) { expr->expr_kind = EXPR_TYPEINFO; @@ -3178,12 +3107,6 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp return true; } - // 12a. If the member was a macro and it isn't prefixed with `@` then that's an error. - if (member->decl_kind == DECL_MACRO && !is_macro) - { - SEMA_ERROR(expr, "Expected '@' before the macro name."); - return false; - } expr->identifier_expr.ident = name; expr->expr_kind = EXPR_IDENTIFIER; @@ -3205,7 +3128,6 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr) // 2. The right hand side may be a @ident or ident Expr *child = expr->access_expr.child; - bool is_macro = child->expr_kind == EXPR_MACRO_EXPANSION; // 3. Handle xxxxxx.typeid if (child->expr_kind == EXPR_TYPEINFO) @@ -3238,7 +3160,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr) // 2. If our left-hand side is a type, e.g. MyInt.abc, handle this here. if (parent->expr_kind == EXPR_TYPEINFO) { - return sema_expr_analyse_type_access(context, expr, parent->type_expr, was_group, is_macro, identifier); + return sema_expr_analyse_type_access(context, expr, parent->type_expr, was_group, identifier); } // 6. Copy failability @@ -3263,7 +3185,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr) Type *flat_type = type_flatten(type); const char *kw = identifier->identifier_expr.ident; - if (!is_macro && kw_type == kw && flat_type->type_kind == TYPE_ANY) + if (kw_type == kw && flat_type->type_kind == TYPE_ANY) { expr->expr_kind = EXPR_TYPEOFANY; expr->inner_expr = parent; @@ -3274,7 +3196,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr) CHECK_DEEPER: // 9. Fix hard coded function `len` on subarrays and arrays - if (!is_macro && kw == kw_len) + if (kw == kw_len) { if (flat_type->type_kind == TYPE_SUBARRAY) { @@ -3292,7 +3214,7 @@ CHECK_DEEPER: } // Hard coded ptr on subarrays and variant - if (!is_macro && kw == kw_ptr) + if (kw == kw_ptr) { if (flat_type->type_kind == TYPE_SUBARRAY) { @@ -3312,7 +3234,7 @@ CHECK_DEEPER: } } - if (!is_macro && kw == kw_ordinal) + if (kw == kw_ordinal) { if (type->type_kind == TYPE_ENUM) { @@ -3366,19 +3288,6 @@ CHECK_DEEPER: return false; } - // 12a. If the member was a macro and it isn't prefixed with `@` then that's an error. - if (member->decl_kind == DECL_MACRO && !is_macro) - { - SEMA_ERROR(expr, "Expected '@' before the macro name."); - return false; - } - // 12b. If the member was *not* a macro but was prefixed with `@` then that's an error. - if (member->decl_kind != DECL_MACRO && is_macro) - { - SEMA_ERROR(expr, "'@' should only be placed in front of macro names."); - return false; - } - // Transform bitstruct access to expr_bitaccess. if (member->var.kind == VARDECL_BITMEMBER) { @@ -5565,9 +5474,6 @@ static bool sema_take_addr_of(Expr *inner) case EXPR_CT_IDENT: SEMA_ERROR(inner, "It's not possible to take the address of a compile time value."); return false; - case EXPR_MACRO_EXPANSION: - SEMA_ERROR(inner, "It's not possible to take the address of a macro."); - return false; case EXPR_IDENTIFIER: return sema_take_addr_of_ident(inner); case EXPR_UNARY: @@ -6962,8 +6868,6 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) return sema_expr_analyse_unary(context, expr); case EXPR_TYPEID: return sema_expr_analyse_typeid(context, expr); - case EXPR_MACRO_EXPANSION: - return sema_expr_analyse_macro_expansion(context, expr); case EXPR_IDENTIFIER: return sema_expr_analyse_identifier(context, NULL, expr); case EXPR_CALL: @@ -7066,9 +6970,6 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr) case EXPR_TYPEINFO: SEMA_ERROR(expr, "A type must be followed by either (...) or '.'."); return false; - case EXPR_MACRO_EXPANSION: - SEMA_ERROR(expr, "Expected macro followed by (...).", expr->ct_macro_ident_expr.identifier); - return expr_poison(expr); case EXPR_CT_IDENT: if (!sema_cast_ct_ident_rvalue(context, expr)) return false; break; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index f1a1de2f3..d586fea93 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -890,7 +890,7 @@ static Expr *sema_insert_method_macro_call(SemaContext *context, SourceSpan span { if (parent->type->type_kind != TYPE_POINTER) expr_insert_addr(parent); } - if (!sema_expr_analyse_general_call(context, len_call, method_decl, parent, is_macro, false)) return poisoned_expr; + if (!sema_expr_analyse_general_call(context, len_call, method_decl, parent, false)) return poisoned_expr; len_call->resolve_status = RESOLVE_DONE; return len_call; } @@ -1551,8 +1551,8 @@ static bool sema_analyse_continue_stmt(SemaContext *context, Ast *statement) switch (parent->ast_kind) { case AST_FOR_STMT: - // Is this plain "do"? - if (parent->for_stmt.cond || parent->flow.skip_first) break; + // Break on anything but plain "do" + if (parent->for_stmt.cond || !parent->flow.skip_first) break; FALLTHROUGH; default: SEMA_ERROR(statement, "'continue' may only be used with 'for', 'while' and 'do-while' statements."); diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 5c2d4c263..0d6a8a3ca 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -74,7 +74,13 @@ const char *kw_check_assign; const char *kw_argc; const char *kw_argv; const char *kw_mainstub;; - +const char *kw_at_ensure; +const char *kw_at_require; +const char *kw_at_pure; +const char *kw_at_optreturn; +const char *kw_at_param; +const char *kw_at_return; +const char *kw_at_checked; void symtab_destroy() { @@ -181,27 +187,36 @@ void symtab_init(uint32_t capacity) assert(builtin_list[i] && "Missing builtin"); } - attribute_list[ATTRIBUTE_INLINE] = kw_inline; - attribute_list[ATTRIBUTE_NOINLINE] = kw_noinline; - attribute_list[ATTRIBUTE_BIGENDIAN] = KW_DEF("bigendian"); - attribute_list[ATTRIBUTE_LITTLEENDIAN] = KW_DEF("littleendian"); - attribute_list[ATTRIBUTE_NORETURN] = KW_DEF("noreturn"); - attribute_list[ATTRIBUTE_SECTION] = KW_DEF("section"); - attribute_list[ATTRIBUTE_EXTNAME] = KW_DEF("extname"); - attribute_list[ATTRIBUTE_WEAK] = KW_DEF("weak"); - attribute_list[ATTRIBUTE_ALIGN] = kw_align; - attribute_list[ATTRIBUTE_PACKED] = KW_DEF("packed"); - attribute_list[ATTRIBUTE_UNUSED] = KW_DEF("unused"); - attribute_list[ATTRIBUTE_USED] = KW_DEF("used"); - attribute_list[ATTRIBUTE_NAKED] = KW_DEF("naked"); - attribute_list[ATTRIBUTE_CDECL] = KW_DEF("cdecl"); - attribute_list[ATTRIBUTE_STDCALL] = KW_DEF("stdcall"); - attribute_list[ATTRIBUTE_VECCALL] = KW_DEF("veccall"); - attribute_list[ATTRIBUTE_REGCALL] = KW_DEF("regcall"); - attribute_list[ATTRIBUTE_FASTCALL] = KW_DEF("fastcall"); - attribute_list[ATTRIBUTE_OVERLAP] = KW_DEF("overlap"); - attribute_list[ATTRIBUTE_OPERATOR] = KW_DEF("operator"); - attribute_list[ATTRIBUTE_AUTOIMPORT] = KW_DEF("autoimport"); + type = TOKEN_AT_IDENT; + kw_at_param = KW_DEF("@param"); + kw_at_ensure = KW_DEF("@ensure"); + kw_at_optreturn = KW_DEF("@optreturn"); + kw_at_pure = KW_DEF("@pure"); + kw_at_require = KW_DEF("@require"); + kw_at_checked = KW_DEF("@checked"); + kw_at_return = KW_DEF("@return"); + attribute_list[ATTRIBUTE_INLINE] = KW_DEF("@inline"); + attribute_list[ATTRIBUTE_NOINLINE] = KW_DEF("@noinline"); + attribute_list[ATTRIBUTE_BIGENDIAN] = KW_DEF("@bigendian"); + attribute_list[ATTRIBUTE_LITTLEENDIAN] = KW_DEF("@littleendian"); + attribute_list[ATTRIBUTE_NORETURN] = KW_DEF("@noreturn"); + attribute_list[ATTRIBUTE_SECTION] = KW_DEF("@section"); + attribute_list[ATTRIBUTE_EXTNAME] = KW_DEF("@extname"); + attribute_list[ATTRIBUTE_WEAK] = KW_DEF("@weak"); + attribute_list[ATTRIBUTE_ALIGN] = KW_DEF("@align"); + attribute_list[ATTRIBUTE_PACKED] = KW_DEF("@packed"); + attribute_list[ATTRIBUTE_UNUSED] = KW_DEF("@unused"); + attribute_list[ATTRIBUTE_USED] = KW_DEF("@used"); + attribute_list[ATTRIBUTE_NAKED] = KW_DEF("@naked"); + attribute_list[ATTRIBUTE_CDECL] = KW_DEF("@cdecl"); + attribute_list[ATTRIBUTE_STDCALL] = KW_DEF("@stdcall"); + attribute_list[ATTRIBUTE_VECCALL] = KW_DEF("@veccall"); + attribute_list[ATTRIBUTE_REGCALL] = KW_DEF("@regcall"); + attribute_list[ATTRIBUTE_FASTCALL] = KW_DEF("@fastcall"); + attribute_list[ATTRIBUTE_OVERLAP] = KW_DEF("@overlap"); + attribute_list[ATTRIBUTE_OPERATOR] = KW_DEF("@operator"); + attribute_list[ATTRIBUTE_PURE] = kw_at_pure; + attribute_list[ATTRIBUTE_AUTOIMPORT] = KW_DEF("@autoimport"); for (unsigned i = 0; i < NUMBER_OF_ATTRIBUTES; i++) { diff --git a/src/compiler/tokens.c b/src/compiler/tokens.c index ed00bd103..ef6763a05 100644 --- a/src/compiler/tokens.c +++ b/src/compiler/tokens.c @@ -157,6 +157,13 @@ const char *token_type_to_string(TokenType type) case TOKEN_TYPE_IDENT: return "TYPE_IDENT"; + case TOKEN_AT_IDENT: + return "MACRO_IDENT"; + case TOKEN_AT_TYPE_IDENT: + return "MACRO_TYPE_IDENT"; + case TOKEN_AT_CONST_IDENT: + return "MACRO_CONST_IDENT"; + // Asm case TOKEN_ASM_STRING: return "ASM_STRING"; @@ -318,20 +325,6 @@ const char *token_type_to_string(TokenType type) return "/**"; case TOKEN_DOCS_END: return "*/"; - case TOKEN_DOCS_OPTRETURN: - return "@optreturn"; - case TOKEN_DOCS_PARAM: - return "@param"; - case TOKEN_DOCS_RETURN: - return "@return"; - case TOKEN_DOCS_ENSURE: - return "@ensure"; - case TOKEN_DOCS_REQUIRE: - return "@require"; - case TOKEN_DOCS_CHECKED: - return "@checked"; - case TOKEN_DOCS_PURE: - return "@pure"; case TOKEN_DOC_DIRECTIVE: return "DOC_DIRECTIVE"; diff --git a/src/version.h b/src/version.h index 2e6b1dd7f..15146c785 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.2.1" \ No newline at end of file +#define COMPILER_VERSION "0.2.2" \ No newline at end of file diff --git a/test/test_suite/abi/darwinx64_2.c3t b/test/test_suite/abi/darwinx64_2.c3t index 83bf0f24f..ecb9ece8a 100644 --- a/test/test_suite/abi/darwinx64_2.c3t +++ b/test/test_suite/abi/darwinx64_2.c3t @@ -5,13 +5,13 @@ struct St12 { int a @align(16); } -fn St12 f12_0(void) { while (1) {}; @unreachable(); } +fn St12 f12_0(void) { while (1) {}; unreachable(); } fn void f12_1(St12 a0) {} struct St13_0 { long[3] f0; } struct St13_1 { long[2] f0; } fn St13_0 f13(int a, int b, int c, int d, - St13_1 e, int f) { while (1) {}; @unreachable(); } + St13_1 e, int f) { while (1) {}; unreachable(); } fn void f14(int a, int b, int c, int d, int e, int f, ichar x) {} diff --git a/test/test_suite/assert/unreachable.c3t b/test/test_suite/assert/unreachable.c3t index dcd444acb..41b7bb597 100644 --- a/test/test_suite/assert/unreachable.c3t +++ b/test/test_suite/assert/unreachable.c3t @@ -8,7 +8,7 @@ fn void test() { int x = foo(); if (x > 0) return; - @unreachable(); + unreachable(); x++; } diff --git a/test/test_suite/attributes/repeat_of_attributes.c3 b/test/test_suite/attributes/repeat_of_attributes.c3 index 2729e1ccf..f321330c0 100644 --- a/test/test_suite/attributes/repeat_of_attributes.c3 +++ b/test/test_suite/attributes/repeat_of_attributes.c3 @@ -1,6 +1,6 @@ fn void test() { - for (int a @align(16) @align(16) = 0 ; a < 10; a++) // #error: Repeat of attribute 'align' + for (int a @align(16) @align(16) = 0 ; a < 10; a++) // #error: Repeat of attribute '@align' { } } diff --git a/test/test_suite/compile_time/ct_switch.c3t b/test/test_suite/compile_time/ct_switch.c3t index 91c6d3d7e..97d4c1575 100644 --- a/test/test_suite/compile_time/ct_switch.c3t +++ b/test/test_suite/compile_time/ct_switch.c3t @@ -30,11 +30,11 @@ extern fn void printf(char*, ...); fn void main() { - printf("%s\n", @getisprime(3)); - printf("%s\n", @getisprime(12)); - printf("%s\n", @getisprime(4)); - printf("%s\n", @getisprime(100)); - printf("%s\n", @getisprime(17)); + printf("%s\n", getisprime(3)); + printf("%s\n", getisprime(12)); + printf("%s\n", getisprime(4)); + printf("%s\n", getisprime(100)); + printf("%s\n", getisprime(17)); } /* #expect: test.ll diff --git a/test/test_suite/compile_time/ct_switch_top_level.c3t b/test/test_suite/compile_time/ct_switch_top_level.c3t index 90581cf29..c5f87f0aa 100644 --- a/test/test_suite/compile_time/ct_switch_top_level.c3t +++ b/test/test_suite/compile_time/ct_switch_top_level.c3t @@ -24,8 +24,8 @@ $endswitch; fn int main() { - @tester(); - @tester(); + tester(); + tester(); int i = 1; return 1; } diff --git a/test/test_suite/compile_time/ct_switch_type_check.c3t b/test/test_suite/compile_time/ct_switch_type_check.c3t index 1fd240b46..15e5cb4ee 100644 --- a/test/test_suite/compile_time/ct_switch_type_check.c3t +++ b/test/test_suite/compile_time/ct_switch_type_check.c3t @@ -18,9 +18,9 @@ extern fn void printf(char*, ...); fn void main() { - printf("%s\n", @get_type(int)); - printf("%s\n", @get_type(double)); - printf("%s\n", @get_type(bool)); + printf("%s\n", get_type(int)); + printf("%s\n", get_type(double)); + printf("%s\n", get_type(bool)); } diff --git a/test/test_suite/compile_time/not_yet_initialized.c3 b/test/test_suite/compile_time/not_yet_initialized.c3 index eef09a7fc..018b02310 100644 --- a/test/test_suite/compile_time/not_yet_initialized.c3 +++ b/test/test_suite/compile_time/not_yet_initialized.c3 @@ -7,7 +7,7 @@ macro foo($Foo) fn void test1() { var $Bar; - @foo($Bar); // #error: '$Bar' is not defined yet + foo($Bar); // #error: '$Bar' is not defined yet } fn void test2() diff --git a/test/test_suite/compile_time/stringify.c3t b/test/test_suite/compile_time/stringify.c3t index 27aec0496..b7e3846c8 100644 --- a/test/test_suite/compile_time/stringify.c3t +++ b/test/test_suite/compile_time/stringify.c3t @@ -3,7 +3,7 @@ module test; import libc; import std::io; -macro timeit(#call) +macro @timeit(#call) { long t = (long)libc::clock(); var $Type = $typeof(#call); diff --git a/test/test_suite/compile_time/typeof_example.c3t b/test/test_suite/compile_time/typeof_example.c3t index f00a26baf..3b7491038 100644 --- a/test/test_suite/compile_time/typeof_example.c3t +++ b/test/test_suite/compile_time/typeof_example.c3t @@ -10,8 +10,8 @@ macro bitcast($Target, value) fn void main() { float f = 100; - int i = @bitcast(int, f); - float f2 = @bitcast(float, i); + int i = bitcast(int, f); + float f2 = bitcast(float, i); printf("Bitcast %f to %d to %f", f, i, f2); } diff --git a/test/test_suite/defer/defer_static_var.c3t b/test/test_suite/defer/defer_static_var.c3t index 54c178ec6..870db010f 100644 --- a/test/test_suite/defer/defer_static_var.c3t +++ b/test/test_suite/defer/defer_static_var.c3t @@ -35,9 +35,9 @@ fn void main() foo(1); foo(2); foo(-2); - @foo2(0); - @foo2(1); - @foo2(2); + foo2(0); + foo2(1); + foo2(2); } /* #expect: foo.ll diff --git a/test/test_suite/errors/error_regression_2.c3t b/test/test_suite/errors/error_regression_2.c3t index a71ff792f..2db800280 100644 --- a/test/test_suite/errors/error_regression_2.c3t +++ b/test/test_suite/errors/error_regression_2.c3t @@ -55,14 +55,14 @@ fn Doc! readDoc(char[] url) { if (contains(url, "fail")) return ReadError.BAD_READ!; if (contains(url, "head-missing")) return { .head = null }; - if (contains(url, "title-missing")) return { @dupe(Head { .title = null })? }; - if (contains(url, "title-empty")) return { @dupe(Head { .title = @dupe((char[])"")? })? }; + if (contains(url, "title-missing")) return { dupe(Head { .title = null })? }; + if (contains(url, "title-empty")) return { dupe(Head { .title = dupe((char[])"")? })? }; // Not particularly elegant due to missing string functions. int len = libc::snprintf(null, 0, "Title of %.*s", (int)url.len, url.ptr); char* str = mem::alloc(len + 1); if (!str) return ReadError.OUT_OF_MEMORY!; libc::snprintf(str, len + 1, "Title of %.*s", (int)url.len, url.ptr); - return { @dupe(Head { .title = @dupe(str[..len - 1])? })? }; + return { dupe(Head { .title = dupe(str[..len - 1])? })? }; } fn Summary buildSummary(Doc doc) @@ -137,7 +137,7 @@ fn void main() libc::printf(`Checking "https://%.*s/":` "\n", (int)url.len, url.ptr); Summary summary = readAndBuildSummary(url); libc::printf(" Summary: "); - summary.print(@libc::stdout()); + summary.print(libc::stdout()); libc::printf("\n"); char[] title_sure = summary.title ? *summary.title : ""; libc::printf(" Title: %.*s\n", (int)title_sure.len, title_sure.ptr); diff --git a/test/test_suite/errors/macro_err.c3t b/test/test_suite/errors/macro_err.c3t index 62750a224..5c76c16ad 100644 --- a/test/test_suite/errors/macro_err.c3t +++ b/test/test_suite/errors/macro_err.c3t @@ -11,7 +11,7 @@ macro test() fn void main() { - libc::printf("%d\n", @test() ?? 2); + libc::printf("%d\n", test() ?? 2); } /* #expect: test.ll diff --git a/test/test_suite/errors/macro_err2.c3t b/test/test_suite/errors/macro_err2.c3t index 3a730bcf1..3d6aab51f 100644 --- a/test/test_suite/errors/macro_err2.c3t +++ b/test/test_suite/errors/macro_err2.c3t @@ -15,7 +15,7 @@ macro test() fn void main() { defer libc::printf("Test1\n"); - libc::printf("%d\n", @test() ?? 2); + libc::printf("%d\n", test() ?? 2); } /* #expect: test.ll diff --git a/test/test_suite/errors/macro_err3.c3t b/test/test_suite/errors/macro_err3.c3t index b30243b89..041b51b07 100644 --- a/test/test_suite/errors/macro_err3.c3t +++ b/test/test_suite/errors/macro_err3.c3t @@ -12,7 +12,7 @@ macro test() fn void main() { defer libc::printf("Test1\n"); - libc::printf("%d\n", @test() ?? 2); + libc::printf("%d\n", test() ?? 2); } /* #expect: test.ll diff --git a/test/test_suite/errors/no_common.c3 b/test/test_suite/errors/no_common.c3 index b896300a3..563fdafaa 100644 --- a/test/test_suite/errors/no_common.c3 +++ b/test/test_suite/errors/no_common.c3 @@ -9,5 +9,5 @@ macro test() fn void main() { - @test() ?? 2; // #error: Cannot find a common type for 'void' and 'int' + test() ?? 2; // #error: Cannot find a common type for 'void' and 'int' } \ No newline at end of file diff --git a/test/test_suite/expressions/addr_of_fails.c3 b/test/test_suite/expressions/addr_of_fails.c3 index 0fe763de3..ec43851b4 100644 --- a/test/test_suite/expressions/addr_of_fails.c3 +++ b/test/test_suite/expressions/addr_of_fails.c3 @@ -22,7 +22,7 @@ macro int hello() fn void test3() { - int* x = &@hello(); // #error: To take the address of a temporary value, use '&&' instead of '&' + int* x = &hello(); // #error: To take the address of a temporary value, use '&&' instead of '&' } fn void test3b() diff --git a/test/test_suite/expressions/rvalues.c3 b/test/test_suite/expressions/rvalues.c3 index d7d949322..fd4d9c237 100644 --- a/test/test_suite/expressions/rvalues.c3 +++ b/test/test_suite/expressions/rvalues.c3 @@ -8,7 +8,7 @@ fn void test() var $Foo = int; var $Bar = $Foo; $Bar x; - @hello(1); + hello(1); var $foo = 1; $foo; FOO; diff --git a/test/test_suite/expressions/unsafe_comparisons.c3 b/test/test_suite/expressions/unsafe_comparisons.c3 index 632ff274f..013b889e9 100644 --- a/test/test_suite/expressions/unsafe_comparisons.c3 +++ b/test/test_suite/expressions/unsafe_comparisons.c3 @@ -37,5 +37,5 @@ macro obfuscate(x, $foo) fn bool test7(uint x) { - return @obfuscate(x, -1); + return obfuscate(x, -1); } \ No newline at end of file diff --git a/test/test_suite/failable_catch.c3t b/test/test_suite/failable_catch.c3t index 1fd0102ca..e538a8388 100644 --- a/test/test_suite/failable_catch.c3t +++ b/test/test_suite/failable_catch.c3t @@ -15,10 +15,10 @@ extern fn void printf(char*, ...); fn int main() { - int! a = @foo(1); + int! a = foo(1); - int! b = @foo((a + 3) ?? 2); - int! c = @foo(0); + int! b = foo((a + 3) ?? 2); + int! c = foo(0); printf("a = %d\n", a); printf("b = %d\n", b); printf("c = %d\n", c); diff --git a/test/test_suite/from_docs/examples_macro_function.c3t b/test/test_suite/from_docs/examples_macro_function.c3t index 7fce466d4..6f5cb46f1 100644 --- a/test/test_suite/from_docs/examples_macro_function.c3t +++ b/test/test_suite/from_docs/examples_macro_function.c3t @@ -16,12 +16,12 @@ fn int test() { int a = 2; int b = 3; - return @foo(&square, 2) + a + b; // 9 - // return @foo(square, 2) + a + b; + return foo(&square, 2) + a + b; // 9 + // return foo(square, 2) + a + b; // Error the symbol "square" cannot be used as an argument. } -// #expect: example.ll +/* #expect: example.ll define i32 @example.square(i32 %0) #0 { entry: diff --git a/test/test_suite/import/autoimport.c3 b/test/test_suite/import/autoimport.c3 index 9c089b497..afdfc74de 100644 --- a/test/test_suite/import/autoimport.c3 +++ b/test/test_suite/import/autoimport.c3 @@ -25,12 +25,12 @@ import foo; fn void main() { - @testm(); + testm(); test(); } fn void main2() { - @testm1(); // #error: Macros from other modules must be prefixed with the module nam + testm1(); // #error: Macros from other modules must be prefixed with the module nam test1(); // #error: Functions from other modules must be prefixed with the module nam } \ No newline at end of file diff --git a/test/test_suite/macro_methods/access.c3 b/test/test_suite/macro_methods/access.c3 index 07f22dc87..153445d93 100644 --- a/test/test_suite/macro_methods/access.c3 +++ b/test/test_suite/macro_methods/access.c3 @@ -15,7 +15,7 @@ struct An2 extern fn void printf(char *string); -macro void An2.helloWorld(An2 &an2) +macro void An2.@helloWorld(An2 &an2) { printf("An2 hello\n"); } diff --git a/test/test_suite/macro_methods/macro_method_fails.c3 b/test/test_suite/macro_methods/macro_method_fails.c3 index d1f10338a..780b4f24f 100644 --- a/test/test_suite/macro_methods/macro_method_fails.c3 +++ b/test/test_suite/macro_methods/macro_method_fails.c3 @@ -15,7 +15,7 @@ struct An2 extern fn void printf(char* string); -macro void An2.helloWorld(An2 &an2) +macro void An2.@helloWorld(An2 &an2) { printf("An2 hello\n"); } @@ -44,14 +44,3 @@ fn void test3() a.@helloWorld.b; // #error: There is no member or method 'b' on 'void' } -fn void test4() -{ - An1 an; - an.x.@y; // #error: '@' should only be placed in front of macro names -} - -fn void test5() -{ - An1 an; - an.x.@y(); // #error: '@' should only be placed in front of macro names -} \ No newline at end of file diff --git a/test/test_suite/macro_methods/macro_methods_defined_twice.c3 b/test/test_suite/macro_methods/macro_methods_defined_twice.c3 index 362282fff..8bb57cdd0 100644 --- a/test/test_suite/macro_methods/macro_methods_defined_twice.c3 +++ b/test/test_suite/macro_methods/macro_methods_defined_twice.c3 @@ -9,12 +9,12 @@ module baz; import foo; import std::io; -macro void foo::Bar.test(Bar &bar) +macro void foo::Bar.@test(Bar &bar) { io::println("Inside of baz::Bar.test"); } -macro void Bar.test(Bar &bar) // #error: This macro method is already defined in this module +macro void Bar.@test(Bar &bar) // #error: This macro method is already defined in this module { io::println("Inside of baz::Bar.test"); } @@ -26,6 +26,6 @@ import baz; fn void main() { Bar bar; - bar.test(); + bar.@test(); } diff --git a/test/test_suite/macros/hash_ident.c3 b/test/test_suite/macros/hash_ident.c3 index 192b00f1e..a962d6f0b 100644 --- a/test/test_suite/macros/hash_ident.c3 +++ b/test/test_suite/macros/hash_ident.c3 @@ -1,4 +1,4 @@ -macro int cofefe(#a) +macro int @cofefe(#a) { int y = 0; return #a + #a; diff --git a/test/test_suite/macros/macro_body_as_value.c3 b/test/test_suite/macros/macro_body_as_value.c3 index aea846468..b8df768a4 100644 --- a/test/test_suite/macros/macro_body_as_value.c3 +++ b/test/test_suite/macros/macro_body_as_value.c3 @@ -1,4 +1,4 @@ -macro foo4(;@body) +macro @foo4(;@body) { @body; // #error: must be followed by () } diff --git a/test/test_suite/macros/macro_body_defer.c3t b/test/test_suite/macros/macro_body_defer.c3t index 0dbac55f3..8d0d26311 100644 --- a/test/test_suite/macros/macro_body_defer.c3t +++ b/test/test_suite/macros/macro_body_defer.c3t @@ -4,7 +4,7 @@ extern fn void printf(char*,...); fn int! foo() { return 1; } -macro foo_test(int i; @body()) +macro @foo_test(int i; @body()) { defer printf("%d\n", i); @body(); @@ -19,7 +19,7 @@ macro foo_defer() } fn void! main() { - @foo_defer(); + foo_defer(); @foo_test(34) { defer printf("inside_defer\n"); }; diff --git a/test/test_suite/macros/macro_calls_prefix.c3 b/test/test_suite/macros/macro_calls_prefix.c3 new file mode 100644 index 000000000..316bdca8b --- /dev/null +++ b/test/test_suite/macros/macro_calls_prefix.c3 @@ -0,0 +1,11 @@ +macro foo(a, $b, $Type) {} + +macro @foo2(a, $b, $Type) {} + +macro bar(&x) // #error: non-function +{} + +macro baz(#y) {} // #error: non-function + +macro baz2(a; @body()) {} // #error: non-function + diff --git a/test/test_suite/macros/macro_common.c3t b/test/test_suite/macros/macro_common.c3t index 8a2b8b836..3db78222a 100644 --- a/test/test_suite/macros/macro_common.c3t +++ b/test/test_suite/macros/macro_common.c3t @@ -8,8 +8,8 @@ macro frab(x) fn void test2() { - @frab(1); - @frab(0); + frab(1); + frab(0); } /* #expect: test.ll diff --git a/test/test_suite/macros/macro_convert_literal.c3 b/test/test_suite/macros/macro_convert_literal.c3 index d8d0ee7ab..e0099270a 100644 --- a/test/test_suite/macros/macro_convert_literal.c3 +++ b/test/test_suite/macros/macro_convert_literal.c3 @@ -8,5 +8,5 @@ macro foo(y) fn void main() { - libc::printf("%d\n", @foo(10)); + libc::printf("%d\n", foo(10)); } \ No newline at end of file diff --git a/test/test_suite/macros/macro_defer_exit.c3t b/test/test_suite/macros/macro_defer_exit.c3t index 2c5d14213..17d2d7295 100644 --- a/test/test_suite/macros/macro_defer_exit.c3t +++ b/test/test_suite/macros/macro_defer_exit.c3t @@ -14,8 +14,8 @@ macro int abc(x) fn void main() { defer printf("On exit\n"); - @abc(123); - @abc(3); + abc(123); + abc(3); } /* #expect: foo.ll diff --git a/test/test_suite/macros/macro_defer_scope.c3t b/test/test_suite/macros/macro_defer_scope.c3t index fe701b01d..59b8b9302 100644 --- a/test/test_suite/macros/macro_defer_scope.c3t +++ b/test/test_suite/macros/macro_defer_scope.c3t @@ -1,6 +1,6 @@ // #target: macos-x64 module foo; -macro int cofefe(#a) +macro int @cofefe(#a) { int x = 0; defer printf("Was here\n"); diff --git a/test/test_suite/macros/macro_defer_with_body.c3t b/test/test_suite/macros/macro_defer_with_body.c3t index abec94d23..2cb71134c 100644 --- a/test/test_suite/macros/macro_defer_with_body.c3t +++ b/test/test_suite/macros/macro_defer_with_body.c3t @@ -1,5 +1,5 @@ module foo; -macro int cofefe(a; @body(x)) +macro int @cofefe(a; @body(x)) { @body(a); @body(a); diff --git a/test/test_suite/macros/macro_import_res_private.c3t b/test/test_suite/macros/macro_import_res_private.c3t index 6261ddda0..a5f6bce35 100644 --- a/test/test_suite/macros/macro_import_res_private.c3t +++ b/test/test_suite/macros/macro_import_res_private.c3t @@ -14,7 +14,7 @@ module baz; import bar; fn void test() { - @bar::bar1(); + bar::bar1(); } /* #expect: baz.ll diff --git a/test/test_suite/macros/macro_import_resolution.c3 b/test/test_suite/macros/macro_import_resolution.c3 index d375ccf3b..1772389fd 100644 --- a/test/test_suite/macros/macro_import_resolution.c3 +++ b/test/test_suite/macros/macro_import_resolution.c3 @@ -2,7 +2,7 @@ module foo; import bar; fn void run() { - @bar::test(); + bar::test(); } module bar; diff --git a/test/test_suite/macros/macro_nested_labels.c3t b/test/test_suite/macros/macro_nested_labels.c3t index f8a8b4794..094f3a6ae 100644 --- a/test/test_suite/macros/macro_nested_labels.c3t +++ b/test/test_suite/macros/macro_nested_labels.c3t @@ -12,7 +12,7 @@ macro checker(int x, $i) for (int i = 0; i < $indent; i++) printf(" "); printf("Helo %d\n", x); $if ($i > 0): - @checker(x, $i - 1); + checker(x, $i - 1); $endif; if (x % 2 == 0) break FOO; } @@ -23,7 +23,7 @@ macro checker(int x, $i) fn void main() { int ab = 7; - @checker(ab, 3); + checker(ab, 3); } /* #expect: test.ll diff --git a/test/test_suite/macros/macro_resolution.c3 b/test/test_suite/macros/macro_resolution.c3 index 3da574261..37f80b138 100644 --- a/test/test_suite/macros/macro_resolution.c3 +++ b/test/test_suite/macros/macro_resolution.c3 @@ -2,12 +2,12 @@ module foo; import bar; fn void run() { - @bar::test(); + bar::test(); } fn void run2() { - @bar::test2(); + bar::test2(); } private fn void tester() {} diff --git a/test/test_suite/macros/macro_rtype.c3 b/test/test_suite/macros/macro_rtype.c3 index e7a7aadff..8a32d3490 100644 --- a/test/test_suite/macros/macro_rtype.c3 +++ b/test/test_suite/macros/macro_rtype.c3 @@ -5,5 +5,5 @@ macro int frob() fn void test1() { - @frob(); + frob(); } \ No newline at end of file diff --git a/test/test_suite/macros/macro_with_body.c3t b/test/test_suite/macros/macro_with_body.c3t index 5cf223b6a..fbe8ce7af 100644 --- a/test/test_suite/macros/macro_with_body.c3t +++ b/test/test_suite/macros/macro_with_body.c3t @@ -14,13 +14,13 @@ fn int Foo.mutate(Foo *foo) return 10 * ++foo.x; } -macro macro_with_body(foo, &x; @body(x, y)) +macro @macro_with_body(foo, &x; @body(x, y)) { x = foo.x; @body(foo.mutate(), x); } -macro repeat(int times; @body(x)) +macro @repeat(int times; @body(x)) { for (int i = 0; i < times; i++) { diff --git a/test/test_suite/macros/no_body.c3 b/test/test_suite/macros/no_body.c3 index 14bdb5655..6a71cf27f 100644 --- a/test/test_suite/macros/no_body.c3 +++ b/test/test_suite/macros/no_body.c3 @@ -2,7 +2,7 @@ module test; extern fn int printf(char *, ...); -macro foo(x; @body(y)) +macro @foo(x; @body(y)) { @body(x); } @@ -32,7 +32,7 @@ macro foo_no(x) fn void test2() { - @foo_no(10) // #error: This macro does not support trailing statements + foo_no(10) // #error: This macro does not support trailing statements { printf("foek"); }; @@ -40,11 +40,11 @@ fn void test2() macro foo2(x) { - @body(x); // #error: 'body' could not be found, did you spell it right? + @body(x); // #error: '@body' could not be found, did you spell it right? } fn void test4() { - @foo2(10); + foo2(10); } diff --git a/test/test_suite/macros/type_params.c3t b/test/test_suite/macros/type_params.c3t index f56cbc26f..d364460be 100644 --- a/test/test_suite/macros/type_params.c3t +++ b/test/test_suite/macros/type_params.c3t @@ -8,11 +8,11 @@ macro foo($Foo) define Bar = short; fn void test() { - int x = @foo(int); + int x = foo(int); var $Foo = double; - double d = @foo($Foo); - double d2 = @foo($typeof(d)); - short z = @foo(Bar); + double d = foo($Foo); + double d2 = foo($typeof(d)); + short z = foo(Bar); } diff --git a/test/test_suite/macros/userland_bitcast.c3t b/test/test_suite/macros/userland_bitcast.c3t index d1b195b8b..16662f6c5 100644 --- a/test/test_suite/macros/userland_bitcast.c3t +++ b/test/test_suite/macros/userland_bitcast.c3t @@ -53,23 +53,23 @@ fn ulong testFoo(short x) { Foo z; z.a = x; - return @testbitcast(z, ulong); + return testbitcast(z, ulong); } fn char[4] test(float x) { - return @testbitcast(x, char[4]); + return testbitcast(x, char[4]); } fn void main() { float f = 12.353; - int i = @testbitcast(f, int); - float f2 = @testbitcast(i, float); + int i = testbitcast(f, int); + float f2 = testbitcast(i, float); printf("%f => %d => %f\n", f, i, f2); double d = 12.353e267; - ulong l = @testbitcast(d, ulong); - double d2 = @testbitcast(d, double); + ulong l = testbitcast(d, ulong); + double d2 = testbitcast(d, double); printf("%e => %llu => %e\n", d, l, d2); } diff --git a/test/test_suite/statements/custom_foreach_with_ref.c3t b/test/test_suite/statements/custom_foreach_with_ref.c3t index 5ed6eac6d..96c1f6a38 100644 --- a/test/test_suite/statements/custom_foreach_with_ref.c3t +++ b/test/test_suite/statements/custom_foreach_with_ref.c3t @@ -8,17 +8,17 @@ struct Foo extern fn void printf(char*, ...); -macro int* Foo.operator_element_at_ref(Foo &f, int a) @operator(elementref) +macro int* Foo.@operator_element_at_ref(Foo &f, int a) @operator(elementref) { return &f.a[a]; } -macro int Foo.operator_len(Foo &f) @operator(len) +macro int Foo.@operator_len(Foo &f) @operator(len) { return 3; } -macro int Foo.operator_element_at(Foo &f, int a) @operator(elementat) +macro int Foo.@operator_element_at(Foo &f, int a) @operator(elementat) { return f.a[a]; } diff --git a/test/test_suite/statements/foreach_custom.c3t b/test/test_suite/statements/foreach_custom.c3t index fd65af512..2fffde686 100644 --- a/test/test_suite/statements/foreach_custom.c3t +++ b/test/test_suite/statements/foreach_custom.c3t @@ -6,12 +6,12 @@ struct Foo int[] x; } -macro int Foo.operator_element_at(Foo &foo, usize index) @operator(elementat) +macro int Foo.@operator_element_at(Foo &foo, usize index) @operator(elementat) { return foo.x[index]; } -macro usize Foo.operator_len(Foo &foo) @operator(len) +macro usize Foo.@operator_len(Foo &foo) @operator(len) { return foo.x.len; } @@ -31,7 +31,7 @@ fn void main() extern fn int printf(char *fmt, ...); -// #expect: foo.ll +/* #expect: foo.ll ; Function Attrs: nounwind define void @foo.main() #0 { diff --git a/test/test_suite/statements/foreach_custom_macro.c3t b/test/test_suite/statements/foreach_custom_macro.c3t index 5b19bc1f8..046462d2e 100644 --- a/test/test_suite/statements/foreach_custom_macro.c3t +++ b/test/test_suite/statements/foreach_custom_macro.c3t @@ -5,12 +5,12 @@ struct Foo int[] x; } -macro int Foo.operator_element_at(Foo &foo, usize index) @operator(elementat) +macro int Foo.@operator_element_at(Foo &foo, usize index) @operator(elementat) { return foo.x[index]; } -macro usize Foo.operator_len(Foo &foo) @operator(len) +macro usize Foo.@operator_len(Foo &foo) @operator(len) { return foo.x.len; } @@ -30,7 +30,7 @@ fn void main() extern fn int printf(char *fmt, ...); -// #expect: foo.ll +/* #expect: foo.ll define void @foo.main() #0 { entry: