diff --git a/.gitignore b/.gitignore index 617d044..9dbba60 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ scripts/c3fmt_gentests test/c3tools/codefmt/test_c3fmt_corpus.c3 # exclude c3c/ used in CI/CD c3c/ +*.exe +*.lib +*.pdb \ No newline at end of file diff --git a/lib/c3lib/argparse/README.md b/lib/c3lib/argparse/README.md index f9e2eaa..32feb7f 100644 --- a/lib/c3lib/argparse/README.md +++ b/lib/c3lib/argparse/README.md @@ -69,7 +69,7 @@ fn void test_custom_type_callback_unknown_type() { char val = '\0'; - ArgParseCallbackFn cbf = fn void! (ArgOpt* opt, String value) { + ArgParseCallbackFn cbf = fn void? (ArgOpt* opt, String value) { io::printfn("flt--callback"); test::eq(value, "bar"); *anycast(opt.value, char)! = value[0]; @@ -89,7 +89,7 @@ fn void test_custom_type_callback_unknown_type() .short_name = 'o', .long_name = "other", .value = &my_app_state, - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { ArgParse* ctx = anycast(opt.value, ArgParse)!; io::printfn("other--callback"); // NOTE: pretends to update important app struct @@ -119,8 +119,8 @@ fn void test_custom_type_callback_unknown_type() fn void test_argparse_next_switch() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); ArgParse agp = { diff --git a/lib/c3lib/argparse/argparse.c3 b/lib/c3lib/argparse/argparse.c3 index dcec75d..fe5c520 100644 --- a/lib/c3lib/argparse/argparse.c3 +++ b/lib/c3lib/argparse/argparse.c3 @@ -144,8 +144,8 @@ different types. Example of parsing array of numbers: ```c3 -List() numbers; -numbers.new_init(); +List{int} numbers; +numbers.init(mem); defer numbers.free(); ArgParse agp = { @@ -155,8 +155,8 @@ ArgParse agp = { .long_name = "num", .value = &numbers, .allow_many = true, - .callback = fn void! (ArgOpt* opt, String value) { - List() * ctx = anycast(opt.value, List())!; + .callback = fn void? (ArgOpt* opt, String value) { + List{int} * ctx = anycast(opt.value, List{int})!; int val = value.to_integer(int)!; ctx.push(val); } @@ -168,19 +168,19 @@ ArgParse agp = { param opt "ArgOpt related to option parsed" param value "raw string value from command line argv" *> -def ArgParseCallbackFn = fn void! (ArgOpt* opt, String value); +alias ArgParseCallbackFn = fn void? (ArgOpt* opt, String value); <* Special template option for --help/-h - prints usage *> macro help_opt(String help_prompt = "show this help message and exit") { - return ArgOpt { + return (ArgOpt) { ._arg_type = ArgType.HELP, .short_name = 'h', .long_name = "help", .help = help_prompt, - .value = any_make(null,bool.typeid), + .value = any_make(null,bool.typeid) }; } @@ -189,10 +189,7 @@ Section separator in usage printout *> macro group_opt(String group_name) { - return ArgOpt { - ._arg_type = ArgType.GROUP, - .help = group_name, - }; + return (ArgOpt){._arg_type = ArgType.GROUP, .help = group_name }; } <* @@ -207,8 +204,8 @@ Example: ```c3 fn void test_argparse_next_all_together() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); String[] argv = { "testprog", "-n", "5", "--num", "2", "--foo=3", "--", "-fex", "-I./foo"}; @@ -225,7 +222,7 @@ fn void test_argparse_next_all_together() Switching over options: ```c3 -int! sum_args(String argv[]) +int? sum_args(String argv[]) { ArgParse agp = { .description = "Test number sum program", @@ -254,7 +251,7 @@ int! sum_args(String argv[]) } ``` *> -fn String! ArgParse.next(&self, String[] argv) +fn String? ArgParse.next(&self, String[] argv) { assert(self.arguments.len == 0, "ArgParse already initialized or double parse call"); @@ -274,7 +271,7 @@ fn String! ArgParse.next(&self, String[] argv) String arg = self._ctx.argv[0]; if (arg.len == 0) { io::printf("Error: argument too short `%s`\n", arg); - return ArgError.INVALID_ARGUMENT?; + return INVALID_ARGUMENT?; } if (self._ctx.cpidx > 0) { // we have --opt=foo, return 'foo' part @@ -287,7 +284,7 @@ fn String! ArgParse.next(&self, String[] argv) if (idx == arg.len-1) { io::printf("Error: option has no value `%s`\n", arg); - return ArgError.INVALID_ARGUMENT?; + return INVALID_ARGUMENT?; } arg = arg[..idx-1]; // return '--opt' part @@ -305,11 +302,11 @@ fn String! ArgParse.next(&self, String[] argv) <* Parses all arguments. -@param argv "arguments list from system argv or from previous argparse.arguments for subcommands" -@return! ArgError.INVALID_ARGUMENT -@return! ArgError.MISSING_ARGUMENT +@param argv: "arguments list from system argv or from previous argparse.arguments for subcommands" +@return? INVALID_ARGUMENT +@return? MISSING_ARGUMENT *> -fn void! ArgParse.parse(&self, String[] argv) +fn void? ArgParse.parse(&self, String[] argv) { assert(self.arguments.len == 0, "ArgParse already initialized or double parse call"); assert(!self._ctx.has_argument, "ArgParse.next() already used before (pick only one way)?"); @@ -330,7 +327,7 @@ fn void! ArgParse.parse(&self, String[] argv) // io::printf("arg: %s\n", arg); if (arg.len == 0) { io::printf("Error: argument too short `%s`\n", arg); - return ArgError.INVALID_ARGUMENT?; + return INVALID_ARGUMENT?; } if (arg.len == 1 || arg[0] != '-' || arg[1] == '\0') { @@ -352,7 +349,7 @@ fn void! ArgParse.parse(&self, String[] argv) if (self._ctx.has_argument) { io::printf("Error: passing options after arguments not allowed at `%s`\n", arg); - return ArgError.INVALID_ARGUMENT?; + return INVALID_ARGUMENT?; } self.parse_short_arg()!; @@ -375,7 +372,7 @@ fn void! ArgParse.parse(&self, String[] argv) if (self._ctx.has_argument) { io::printf("Error: passing options after arguments not allowed at `%s`\n", arg); - return ArgError.INVALID_ARGUMENT?; + return INVALID_ARGUMENT?; } self.parse_long_arg()!; @@ -388,14 +385,14 @@ fn void! ArgParse.parse(&self, String[] argv) self.arguments = argv[self._ctx.cpidx + 1 ..]; // excludes 1st argv[0], program_name if (self.flags.require_arguments && self.arguments.len == 0) { io::printf("Error: positional argument expected\n"); - return ArgError.MISSING_ARGUMENT?; + return MISSING_ARGUMENT?; } } <* Prints program usage based on ArgParse fields composition *> -fn void! ArgParse.print_usage(&self) +fn void? ArgParse.print_usage(&self) { assert(self.options.len > 0, "ArgParse is not properly configured, or using ArgParse.next()"); @@ -404,7 +401,7 @@ fn void! ArgParse.print_usage(&self) @pool() { // NOTE: prepending program_name to all usage line - path::Path path = path::temp_new(self.program_name)!; + path::Path path = path::temp(self.program_name)!; foreach (usage : self.usage.tsplit("\n")) { usage = usage.trim(); if (!usage) { @@ -529,14 +526,12 @@ fn void! ArgParse.print_usage(&self) * PRIVATE IMPLEMENTATION */ -fault ArgError @private -{ +faultdef MISSING_ARGUMENT, INVALID_ARGUMENT, ARGUMENT_VALUE, CONFIGURATION, - HELP_SHOW, -} + HELP_SHOW; enum ArgType : int @private { @@ -547,7 +542,7 @@ enum ArgType : int @private $assert(ArgType.USER.ordinal == 0); // USER must be first to support ZII behavior -fn void! ArgParse.options_ensure_required(&self) @local +fn void? ArgParse.options_ensure_required(&self) @local { bool has_errors = false; foreach (i, opt : self.options) { @@ -561,11 +556,11 @@ fn void! ArgParse.options_ensure_required(&self) @local } } if (has_errors) { - return ArgError.MISSING_ARGUMENT?; + return MISSING_ARGUMENT?; } } -fn void! ArgParse.options_check(&self) @local +fn void? ArgParse.options_check(&self) @local { assert(self.arguments.len == 0, "already processed?"); @@ -625,7 +620,7 @@ fn void! ArgParse.options_check(&self) @local } } -fn String! ArgParse.get_arg(&self) @local +fn String? ArgParse.get_arg(&self) @local { if (self._ctx.optvalue) { // --arg= via = @@ -641,26 +636,26 @@ fn String! ArgParse.get_arg(&self) @local "Error: getting another option instead of previous option value at `%s`\n", self._ctx.argv[0] ); - return ArgError.ARGUMENT_VALUE?; + return ARGUMENT_VALUE?; } return result; } else { io::printf("Error: missing argument value for %s\n", self._ctx.argv[0]); - return ArgError.ARGUMENT_VALUE?; + return ARGUMENT_VALUE?; } } -fn void! ArgParse.parse_arg_val(&self, ArgOpt* opt, bool flag_unset = false) @local +fn void? ArgParse.parse_arg_val(&self, ArgOpt* opt, bool flag_unset = false) @local { assert(opt); if (opt._arg_type == ArgType.HELP) { - return ArgError.HELP_SHOW?; + return HELP_SHOW?; } if (opt._is_present && !opt.allow_many) { io::printf("Error: duplicated option %s\n", self._ctx.argv[0]); - return ArgError.INVALID_ARGUMENT?; + return INVALID_ARGUMENT?; } assert(opt.value); @@ -714,41 +709,43 @@ fn void! ArgParse.parse_arg_val(&self, ArgOpt* opt, bool flag_unset = false) @lo } } -fn void! ArgParse.parse_short_arg(&self) @local +fn void? ArgParse.parse_short_arg(&self) @local { foreach (&opt : self.options) { if (opt.short_name == self._ctx.optvalue[0]) { self._ctx.optvalue = self._ctx.optvalue.len > 1 ? self._ctx.optvalue[1..] : ""; if (catch err = self.parse_arg_val(opt)) { - case ArgError.MISSING_ARGUMENT: - case ArgError.INVALID_ARGUMENT: - case ArgError.ARGUMENT_VALUE: - case ArgError.CONFIGURATION: - case ArgError.HELP_SHOW: + switch (err) { + case MISSING_ARGUMENT: + case INVALID_ARGUMENT: + case ARGUMENT_VALUE: + case CONFIGURATION: + case HELP_SHOW: return err?; default: io::printf( "Error: argument parse error -%s failed with `%s`\n", opt.short_name, err ); - return ArgError.ARGUMENT_VALUE?; + return ARGUMENT_VALUE?; + } } return; // ALL OK } } io::printf("Error: invalid argument %s\n", self._ctx.argv[0]); - return ArgError.INVALID_ARGUMENT?; + return INVALID_ARGUMENT?; } -fn String! prefix_skip(String s, String prefix) @local +fn String? prefix_skip(String s, String prefix) @local { if (s.starts_with(prefix)) { return s[prefix.len ..]; } else { - return ArgError.MISSING_ARGUMENT?; + return MISSING_ARGUMENT?; } } -fn void! ArgParse.parse_long_arg(&self) @local +fn void? ArgParse.parse_long_arg(&self) @local { foreach (&opt : self.options) { if (!opt.long_name) { @@ -757,10 +754,10 @@ fn void! ArgParse.parse_long_arg(&self) @local int opt_flags = 0; bool flag_unset = false; - String! arg = prefix_skip(self._ctx.argv[0][2..], opt.long_name); + String? arg = prefix_skip(self._ctx.argv[0][2..], opt.long_name); if (catch err = arg) { switch (err) { - case ArgError.MISSING_ARGUMENT: + case MISSING_ARGUMENT: // NOTE: for boolean flags it's possible to pass unset with '--no-' if ( opt.value.type == bool.typeid && @@ -781,21 +778,23 @@ fn void! ArgParse.parse_long_arg(&self) @local } if (catch err = self.parse_arg_val(opt, flag_unset)) { - case ArgError.MISSING_ARGUMENT: - case ArgError.INVALID_ARGUMENT: - case ArgError.ARGUMENT_VALUE: - case ArgError.CONFIGURATION: - case ArgError.HELP_SHOW: - return err?; - default: - io::printf( - "Error: argument parse error %s failed with `%s`\n", self._ctx.argv[0], err - ); - return ArgError.ARGUMENT_VALUE?; + switch (err) { + case MISSING_ARGUMENT: + case INVALID_ARGUMENT: + case ARGUMENT_VALUE: + case CONFIGURATION: + case HELP_SHOW: + return err?; + default: + io::printf( + "Error: argument parse error %s failed with `%s`\n", self._ctx.argv[0], err + ); + return ARGUMENT_VALUE?; + } } return; // ALL OK } io::printf("Error: invalid argument %s\n", self._ctx.argv[0]); - return ArgError.INVALID_ARGUMENT?; + return INVALID_ARGUMENT?; } diff --git a/lib/c3lib/codegen/codegen.c3 b/lib/c3lib/codegen/codegen.c3 index 150e8a2..d8ade20 100644 --- a/lib/c3lib/codegen/codegen.c3 +++ b/lib/c3lib/codegen/codegen.c3 @@ -40,9 +40,9 @@ struct CodeGen <* CodeGen constructor *> -fn CodeGen* CodeGen.new_init(&self) +fn CodeGen* CodeGen.init(&self) { - self.buf.new_init(); + self.buf.init(mem); return self; } diff --git a/lib/c3tools/ast/_parser.c3 b/lib/c3tools/ast/_parser.c3 index 90c78ba..2010141 100644 --- a/lib/c3tools/ast/_parser.c3 +++ b/lib/c3tools/ast/_parser.c3 @@ -5,7 +5,7 @@ import c3tools::ast::lexer @public; <* Returns TokenType of current scope - @param offset "1 - last, 2 - last-2, etc.." + @param offset: "1 - last, 2 - last-2, etc.." @return "current scope, or INVALID_TOKEN if offset if too high or no scope at all" @require offset > 0 *> @@ -330,7 +330,7 @@ fn bool Ast.parse_function(&ast, AstNode* node, Token* t, NodeParserState* state ast.@allc_add(AstNode, &node_func.name, t); case LPAREN: if (state.scope_depth == 1) { - DString fname = dstring::temp_new(); + DString fname = dstring::temp(); node_func.value = ast.@allc_str(ast.@node_join(node_func.name, fname, ".")); nextcase STATE: state.transition(VAR); } @@ -438,9 +438,43 @@ fn bool Ast.parse_docstring(&ast, AstNode* node, Token* t, NodeParserState* stat return false; } +fn bool Ast.parse_faultdef(&ast, AstNode* node, Token* t, NodeParserState* state) +{ + assert(node.type == FAULTDEF); + AstTypeDefEnumerable* node_typedef = (AstTypeDefEnumerable*)node; + + switch STATE: (state.check(t)) { + case INVALID_TOKEN: + node_typedef.value = ""; + state.transition(IDENT); + case IDENT: + switch (t.type) { + case CONST_IDENT: + ast.@allc_add(AstNode, &node_typedef.values, t); + case AT_IDENT: + ast.lexer.extend_current_attribute(); + ast.@allc_add(AstNode, &node_typedef.attributes, t); + case EOS: + nextcase STATE: state.transition(EOF); + default: + break; + } + case EOS: + nextcase STATE: state.transition(EOF); + case EOF: + ast.state_stack.remove_last(); + node_typedef.iend = t.offset + t.value.len - 1; + return true; + default: + break; + } + + return false; +} + fn bool Ast.parse_enumerable(&ast, AstNode* node, Token* t, NodeParserState* state) { - assert(node.type == ENUM || node.type == FAULT); + assert(node.type == ENUM); AstTypeDefEnumerable* node_enum = (AstTypeDefEnumerable*)node; switch STATE: (state.check(t)) { @@ -526,13 +560,15 @@ fn bool Ast.parse_interface(&ast, AstNode* node, Token* t, NodeParserState* stat case SCOPE: // regular function scope { ... } switch (t.type) { case LBRACE: // { - break; + if (state.sub_node) { nextcase default; } + else { break; } case RBRACE: // ending brace - if (state.scope_depth == 0) nextcase STATE: state.transition(EOF); + if (state.sub_node) { nextcase default; } + else if (state.scope_depth == 0) { nextcase STATE: state.transition(EOF); } case DOCS_START: if (state.scope_depth == 2 && !state.sub_node) { ast.@allc_add(AstDoc, &state.sub_node, &ast.lexer.token); - ast.state_stack.push(NodeParserState {}); + ast.state_stack.push({}); assert(state.sub_node.type == TokenType.DOCS_START); ast.parse_docstring(state.sub_node, &ast.lexer.token, &ast.state_stack[1]); assert(ast.state_stack.len() == 2); @@ -549,7 +585,7 @@ fn bool Ast.parse_interface(&ast, AstNode* node, Token* t, NodeParserState* stat f.docs = (AstDoc*)state.sub_node; if (ast.state_stack.len() > 1) ast.state_stack.remove_last()!!; - ast.state_stack.push(NodeParserState {}); + ast.state_stack.push({}); state.sub_node = f; assert(state.sub_node.type == TokenType.FN); @@ -656,7 +692,8 @@ fn bool Ast.parse_structural(&ast, AstNode* node, Token* t, NodeParserState* sta case VAR: // found individual field start parsing it switch (t.type) { case RBRACE: // ending brace - if (state.scope_depth == 0) nextcase STATE: state.transition(EOF); + if (state.scope_depth == 0) { nextcase STATE: state.transition(EOF); } + else { nextcase default; } case INLINE: case TYPE_IDENT: AstTypeDefStructural* s = (AstTypeDefStructural*)state.sub_node; @@ -673,7 +710,7 @@ fn bool Ast.parse_structural(&ast, AstNode* node, Token* t, NodeParserState* sta s.value = ""; state.sub_node = s; } else { - // Adding to existing type field (e.g. generic List() ) + // Adding to existing type field (e.g. generic List{MyType} ) ast.@allc_add(AstNode, &s.ftype, t); } case IDENT: @@ -720,7 +757,7 @@ fn bool Ast.parse_structural(&ast, AstNode* node, Token* t, NodeParserState* sta &ast.lexer.token ); s.docs = (AstDoc*)state.sub_node; - ast.state_stack.push(NodeParserState {}); + ast.state_stack.push({}); state.sub_node = s; } nextcase default; // initialize processing substructure @@ -798,7 +835,7 @@ fn bool Ast.parse_global_var(&ast, AstNode* node, Token* t, NodeParserState* sta fn bool Ast.parse_typedef(&ast, AstNode* node, Token* t, NodeParserState* state) { - assert(node.type == DEF || node.type == DISTINCT); + assert(node.type == ALIAS || node.type == TYPEDEF); AstTypeDef* node_typedef = (AstTypeDef*)node; switch STATE: (state.check(t)) { diff --git a/lib/c3tools/ast/ast.c3 b/lib/c3tools/ast/ast.c3 index 3d54775..90c4203 100644 --- a/lib/c3tools/ast/ast.c3 +++ b/lib/c3tools/ast/ast.c3 @@ -13,10 +13,10 @@ struct Ast AstModule* modules; allocator::DynamicArenaAllocator* _allocator; Lexer lexer; - List() state_stack; + List{NodeParserState} state_stack; } -def NodeParser = fn bool (Ast* ast, AstNode* node, Token* t, NodeParserState* state); +alias NodeParser = fn bool (Ast* ast, AstNode* node, Token* t, NodeParserState* state); struct NodeParserState { @@ -54,7 +54,7 @@ struct AstModule struct AstTypeDef { inline AstNode node; - AstModule* mod; // module which owns the type def + AstModule* mod; // module which owns the type alias AstNode* attributes; AstDoc* docs; AstNode* ftype; // field or function return type @@ -212,7 +212,7 @@ fn Ast parse( if (allc == null) { // typically this will be actual only for tests self._allocator = mem::alloc(DynamicArenaAllocator); - self._allocator.init(1024, allocator::temp()); + self._allocator.init(tmem, 1024); } else { self._allocator = allc; } @@ -229,7 +229,7 @@ fn Ast parse( ); current_module.file_path = self.path; - self.state_stack.new_init(); + self.state_stack.init(mem); defer self.state_stack.free(); while LOOP: (self.lexer.next_token()) { @@ -264,8 +264,13 @@ fn Ast parse( docstring = null; // reset all previous docs node_fn = &Ast.parse_docstring; node = self.@allc_add(AstDoc, &docstring, &self.lexer.token); + case FAULTDEF: + node_fn = &Ast.parse_faultdef; + node = self.@allc_add( + AstTypeDefEnumerable, ¤t_module.decls, &self.lexer.token + ); + ((AstTypeDefEnumerable*)node).docs = docstring; case ENUM: - case FAULT: node_fn = &Ast.parse_enumerable; node = self.@allc_add( AstTypeDefEnumerable, ¤t_module.decls, &self.lexer.token @@ -285,8 +290,8 @@ fn Ast parse( AstTypeDefStructural, ¤t_module.decls, &self.lexer.token ); ((AstTypeDefStructural*)node).docs = docstring; - case DEF: - case DISTINCT: + case ALIAS: + case TYPEDEF: node_fn = &Ast.parse_typedef; node = self.@allc_add(AstTypeDef, ¤t_module.decls, &self.lexer.token); ((AstTypeDef*)node).docs = docstring; @@ -304,7 +309,7 @@ fn Ast parse( } assert(self.state_stack.len() == 0); - self.state_stack.push(NodeParserState {}); + self.state_stack.push({}); } if (node_fn(&self, node, &self.lexer.token, &self.state_stack[0])) { @@ -312,7 +317,7 @@ fn Ast parse( switch (node.type) { case MODULE: assert(node == current_module); - DString mname = dstring::temp_new(); + DString mname = dstring::temp(); node.value = self.@allc_str(self.@node_join(current_module.name, mname, "::")); current_module.hash.init(); current_module.hash.update(node.value); diff --git a/lib/c3tools/ast/lexer.c3 b/lib/c3tools/ast/lexer.c3 index 31476bd..4f16490 100644 --- a/lib/c3tools/ast/lexer.c3 +++ b/lib/c3tools/ast/lexer.c3 @@ -9,7 +9,7 @@ import std::collections::list; // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -def Lexer = LexerImp; +alias Lexer = LexerImp; struct LexerImp { @@ -37,8 +37,8 @@ struct Token (Printable) fn String Token.to_string(&self, Allocator allocator) @dynamic { - @pool(allocator) { - DString builder = dstring::temp_new(); + @pool() { + DString builder = dstring::temp(); builder.appendf("{\n"); builder.appendf(" type: %s\n", self.type); builder.appendf(" value: `%s`\n", self.value); @@ -112,11 +112,11 @@ fn void Token.print(&self, bool new_line = false, int padding = 0) <* Initializes new lexer instance - @param contents `c3 source contents` + @param contents: `c3 source contents` *> fn void init(Lexer* lexer, String contents) { - *lexer = Lexer {}; + *lexer = {}; // Set the current file. // lexer.file_begin = lexer.file.contents; lexer.file_begin = contents; @@ -170,16 +170,16 @@ fn bool Lexer.next_token(&self) <* Parses lexer contents and returns new list of all available tokens - @param allocator "optional allocator for resulting list" + @param allocator: "optional allocator for resulting list" @return "list of all tokens in lexer string" *> -fn List() Lexer.new_parse_tokens(&self, Allocator allocator = allocator::heap()) +fn List{lexer::Token} Lexer.new_parse_tokens(&self, Allocator allocator = mem) { assert(self.file_begin, "not initialied"); assert(self.file_begin == self.current, "already processed"); - List() result; - result.new_init(allocator: allocator); + List{Token} result; + result.init(allocator); while (self.next_token()) { result.push(self.token); @@ -1563,17 +1563,17 @@ enum TokenType : uint USZ, FLOAT128, ANY, - ANYFAULT, + FAULT, TYPEID, // Keywords ASSERT, ASM, STRUCT, - DEF, - DISTINCT, + ALIAS, + TYPEDEF, BITSTRUCT, - FAULT, + FAULTDEF, UNION, BREAK, CASE, @@ -1881,8 +1881,8 @@ fn String token_type_to_string(TokenType type) return "DOC_COMMENT"; // Keywords - case ANYFAULT: - return "anyfault"; + case FAULT: + return "fault"; case ASM: return "asm"; case ASSERT: @@ -1899,14 +1899,14 @@ fn String token_type_to_string(TokenType type) return "const"; case CONTINUE: return "continue"; - case DEF: - return "def"; + case ALIAS: + return "alias"; case DEFAULT: return "default"; case DEFER: return "defer"; - case DISTINCT: - return "distinct"; + case TYPEDEF: + return "typedef"; case DO: return "do"; case ELSE: @@ -1917,8 +1917,8 @@ fn String token_type_to_string(TokenType type) return "extern"; case FALSE: return "false"; - case FAULT: - return "fault"; + case FAULTDEF: + return "faultdef"; case FOR: return "for"; case FOREACH: @@ -2128,14 +2128,14 @@ fn TokenType token_from_identifier(String indentifier) return CONST; case "continue": return CONTINUE; - case "def": - return DEF; + case "alias": + return ALIAS; case "default": return DEFAULT; case "defer": return DEFER; - case "distinct": - return DISTINCT; + case "typedef": + return TYPEDEF; case "do": return DO; case "else": @@ -2146,8 +2146,8 @@ fn TokenType token_from_identifier(String indentifier) return EXTERN; case "false": return FALSE; - case "fault": - return FAULT; + case "faultdef": + return FAULTDEF; case "for": return FOR; case "foreach": @@ -2195,7 +2195,7 @@ fn TokenType token_from_identifier(String indentifier) case "tlocal": return TLOCAL; // Types - case "anyfault": + case "fault": case "var": case "void": case "any": diff --git a/lib/c3tools/codefmt/_cache.c3 b/lib/c3tools/codefmt/_cache.c3 index e2fa2c9..86090c0 100644 --- a/lib/c3tools/codefmt/_cache.c3 +++ b/lib/c3tools/codefmt/_cache.c3 @@ -11,7 +11,7 @@ import std::collections::list; <* Dumps and formats collected cache_statement_ array into code *> -macro void! CodeFmt.cache_statement_dump( +macro void? CodeFmt.cache_statement_dump( &self, TokenType wrap_rule = INVALID_TOKEN, bool no_split = false ) @private { @@ -96,12 +96,40 @@ macro void! CodeFmt.cache_statement_dump( ); if (no_split || (!has_magic_comma && self._line_used + token_len <= self.max_line_width)) { + // Track generic braces. + isz brace_depth = -1; + List{bool} brace_is_generic; + brace_is_generic.init(tmem); + defer brace_is_generic.free(); + // NOTE: Fits in line no wrapping needed write as is with standard formatting. self.@cache_statement_iter(; usz i, Token* t) { if (self._print_lex) io::eprintf("%s ", t.type); switch (t.type) { case QUESTION: - if (self._resolve__next_question_is_error(i)) self.write(" "); + if (!self.is_prev_scope_generic && self._resolve__question_prespace(i)) self.write(" "); + nextcase default; + case LBRACE: + brace_is_generic.push(self._resolve__prev_token(i, 1) == TYPE_IDENT); + ++brace_depth; + nextcase default; + case RBRACE: + (void)brace_is_generic.pop(); + --brace_depth; + nextcase default; + case SPACE: + // In generic type expression, spaces immediately after '{' and before '}' are skipped. + if (brace_depth < 0) nextcase default; + if (brace_depth >= brace_is_generic.len()) nextcase default; + if (self._resolve__prev_token(i, 1) == LBRACE + && brace_is_generic[brace_depth]) + { + break; + } else if (self._resolve__next_token(i) == RBRACE + && brace_is_generic[brace_depth]) + { + break; + } nextcase default; default: self.write("%s", t.value); @@ -131,9 +159,9 @@ macro void! CodeFmt.cache_statement_dump( <* Struct initializers dump MyStruct s = {.foo = 1, .sub = {.bar = 0}} *> -macro void! CodeFmt.cache_statement_dump_struct_init(&self, bool is_multiline, TokenType wrap_rule) @private +macro void? CodeFmt.cache_statement_dump_struct_init(&self, bool is_multiline, TokenType wrap_rule) @private { - NodeParserState tmpstate = NodeParserState {}; + NodeParserState tmpstate = {}; TokenType brake_type = INVALID_TOKEN; self.@cache_statement_iter(; usz i, Token* t) { // if (self._print_lex) io::eprintf("%s ", t.type); @@ -161,7 +189,7 @@ macro void! CodeFmt.cache_statement_dump_struct_init(&self, bool is_multiline, T self.write(" %s", t.value); tmpstate.current_token = tmpstate.last_token; case QUESTION: - if (self._resolve__next_question_is_error(i)) self.write(" "); + if (self._resolve__question_prespace(i)) self.write(" "); nextcase default; case SPACE: if (is_multiline) { @@ -203,9 +231,9 @@ macro void! CodeFmt.cache_statement_dump_struct_init(&self, bool is_multiline, T <* Generic statement dumper *> -macro void! CodeFmt.cache_statement_dump_generic(&self, bool is_multiline, TokenType wrap_rule) @private +macro void? CodeFmt.cache_statement_dump_generic(&self, bool is_multiline, TokenType wrap_rule) @private { - NodeParserState tmpstate = NodeParserState {}; + NodeParserState tmpstate = {}; TokenType brake_type = INVALID_TOKEN; // This filter is used for forcing raw writing (e.g. cast vs call ambiguity) @@ -256,7 +284,7 @@ macro void! CodeFmt.cache_statement_dump_generic(&self, bool is_multiline, Token case COMMENT_MULTI_INLINE: self.write(" %s", t.value); case QUESTION: - if (self._resolve__next_question_is_error(i)) self.write(" "); + if (self._resolve__question_prespace(i)) self.write(" "); nextcase default; default: if (is_multiline) { diff --git a/lib/c3tools/codefmt/_codecorpus.c3 b/lib/c3tools/codefmt/_codecorpus.c3 index 58c2bf9..8df1e56 100644 --- a/lib/c3tools/codefmt/_codecorpus.c3 +++ b/lib/c3tools/codefmt/_codecorpus.c3 @@ -6,13 +6,11 @@ import std::collections::list; import std::collections::map; import std::io; -fault CodeCorpusError -{ +faultdef EMPTY_FILE, BAD_FORMAT, DUPLICATE_NAME, - BAD_NAME, -} + BAD_NAME; struct CodeCorpus { @@ -26,11 +24,11 @@ struct CodeCorpus fn bool compare_output(String expected, String actual) { - String[] lines_expected = expected.split("\n"); - String[] lines_actual = actual.split("\n"); + String[] lines_expected = expected.split(mem, "\n",); + String[] lines_actual = actual.split(mem, "\n"); - defer allocator::heap().release(lines_expected.ptr, true); - defer allocator::heap().release(lines_actual.ptr, true); + defer mem::free(lines_expected); + defer mem::free(lines_actual); int n_errors = 0; for (int i = 0, int j = 0; i < lines_expected.len || j < lines_actual.len; i++, j++) { @@ -75,20 +73,21 @@ fn bool check_casename(String case_name) return true; } -fn List()! new_parse(String file_name) +fn List{CodeCorpus}? new_parse(String file_name) { - String contents = (String)file::load_new(file_name)!; - List() result; + String contents = (String)file::load(mem, file_name)!; + List{CodeCorpus} result; - HashMap()* unique_names = HashMap(){}.new_init(); + HashMap{String, int} unique_names; + unique_names.init(mem); defer unique_names.free(); - result.new_init(); + result.init(mem); - String[] lines = contents.split("\n"); - defer allocator::heap().release(lines.ptr, true); + String[] lines = contents.split(mem, "\n"); + defer mem::free(lines.ptr); - if (!lines) return CodeCorpusError.EMPTY_FILE?; + if (!lines) return EMPTY_FILE?; CodeCorpus current = { .file_name = file_name, .line = 1 }; @@ -108,7 +107,7 @@ fn List()! new_parse(String file_name) i + 1, l.len ); - return CodeCorpusError.BAD_FORMAT?; + return BAD_FORMAT?; } if (current.phase > 2) { @@ -129,18 +128,18 @@ fn List()! new_parse(String file_name) io::printfn("```"); io::printf("output:\n%s", current.case_output); io::printfn("```"); - return CodeCorpusError.BAD_FORMAT?; + return BAD_FORMAT?; } result.push(current); - current = CodeCorpus { .file_name = file_name, .line = i + 1 }; + current = { .file_name = file_name, .line = i + 1 }; } current.phase++; if (current.phase > 1) { if (!current.case_name) { io::printfn("Probably missing case name (%s:%s)", file_name, i + 1); - return CodeCorpusError.BAD_FORMAT?; + return BAD_FORMAT?; } } continue; @@ -154,12 +153,12 @@ fn List()! new_parse(String file_name) i + 1, l.len ); - return CodeCorpusError.BAD_FORMAT?; + return BAD_FORMAT?; } if (current.phase != 3) { io::printfn("---- line is probably is out of order at (%s:%s)", file_name, i + 1); - return CodeCorpusError.BAD_FORMAT?; + return BAD_FORMAT?; } current.phase++; @@ -170,7 +169,7 @@ fn List()! new_parse(String file_name) current.case_name = l.trim(); if (unique_names.has_key(current.case_name)) { io::printfn("Duplicate case name: %s at line %d", current.case_name, i + 1); - return CodeCorpusError.DUPLICATE_NAME?; + return DUPLICATE_NAME?; } if (!check_casename(current.case_name)) { @@ -179,7 +178,7 @@ fn List()! new_parse(String file_name) current.case_name, i + 1 ); - return CodeCorpusError.BAD_NAME?; + return BAD_NAME?; } unique_names.set(current.case_name, 1); current.phase++; @@ -222,7 +221,7 @@ fn List()! new_parse(String file_name) } } else { io::printfn("Unexpected phase count (%s:%s)", file_name, i + 1); - return CodeCorpusError.BAD_FORMAT?; + return BAD_FORMAT?; } } diff --git a/lib/c3tools/codefmt/_formatters.c3 b/lib/c3tools/codefmt/_formatters.c3 index 64e0c2f..9fb0a75 100644 --- a/lib/c3tools/codefmt/_formatters.c3 +++ b/lib/c3tools/codefmt/_formatters.c3 @@ -10,7 +10,7 @@ import std::collections::list; <* Returns appropriate formatter function/state for global level statements *> -fn CodeFmtFn! CodeFmt.global_formatter_dispatch(CodeFmt* self, Token* t) @private +fn CodeFmtFn? CodeFmt.global_formatter_dispatch(CodeFmt* self, Token* t) @private { switch (t.type) { case FN: @@ -20,8 +20,9 @@ fn CodeFmtFn! CodeFmt.global_formatter_dispatch(CodeFmt* self, Token* t) @privat case UNION: case BITSTRUCT: return &CodeFmt.format_structural; + case FAULTDEF: + return &CodeFmt.format_faultdef; case ENUM: - case FAULT: return &CodeFmt.format_enumerable; case INTERFACE: return &CodeFmt.format_interface; @@ -32,8 +33,8 @@ fn CodeFmtFn! CodeFmt.global_formatter_dispatch(CodeFmt* self, Token* t) @privat break; case EXTERN: return &CodeFmt.format_generic_extern; - case DEF: - case DISTINCT: + case ALIAS: + case TYPEDEF: case MODULE: case CONST: case IMPORT: @@ -46,7 +47,7 @@ fn CodeFmtFn! CodeFmt.global_formatter_dispatch(CodeFmt* self, Token* t) @privat <* Returns special formatter function for in-scope token. *> -fn CodeFmtFn! CodeFmt.local_formatter_dispatch(CodeFmt* self, Token* t) @private +fn CodeFmtFn? CodeFmt.local_formatter_dispatch(CodeFmt* self, Token* t) @private { switch (t.type) { case IF: @@ -71,7 +72,7 @@ fn CodeFmtFn! CodeFmt.local_formatter_dispatch(CodeFmt* self, Token* t) @private } <* Generic comment processor if there is not cache_statement pending + fmt: off handler *> -fn bool! CodeFmt.format_comment_or_empty(&self, NodeParserState* state, Token* t) +fn bool? CodeFmt.format_comment_or_empty(&self, NodeParserState* state, Token* t) { if (t.type == COMMENT_SINGLE) { if (t.value.starts_with("// fmt: off") && !self._is_paused) { @@ -177,7 +178,7 @@ fn bool! CodeFmt.format_comment_or_empty(&self, NodeParserState* state, Token* t <* Formatter for generic file contents *> -fn bool! CodeFmt.format_global_file_scope(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_global_file_scope(CodeFmt* self, Token* t, NodeParserState* state) @private { // initialization with null token if (state.current_state == INVALID_TOKEN) { @@ -226,7 +227,7 @@ fn bool! CodeFmt.format_global_file_scope(CodeFmt* self, Token* t, NodeParserSta Format steps: format_fn_args -> format_code_scope -> foreach(format_generic_statement: statements) *> -fn bool! CodeFmt.format_fn(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_fn(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -350,7 +351,7 @@ fn bool! CodeFmt.format_fn(CodeFmt* self, Token* t, NodeParserState* state) @pri <* Formatting fn/macro arguments *> -fn bool! CodeFmt.format_fn_args(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_fn_args(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -394,7 +395,7 @@ fn bool! CodeFmt.format_fn_args(CodeFmt* self, Token* t, NodeParserState* state) <* Formatting generic code scope ({ ... } inside a function) *> -fn bool! CodeFmt.format_code_scope(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_code_scope(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -498,7 +499,7 @@ fn bool! CodeFmt.format_code_scope(CodeFmt* self, Token* t, NodeParserState* sta <* Formatting individual (generic statements) ending with ; *> -fn bool! CodeFmt.format_generic_statement(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_generic_statement(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -567,9 +568,17 @@ fn bool! CodeFmt.format_generic_statement(CodeFmt* self, Token* t, NodeParserSta self.write(" "); return self.push_run_state(&CodeFmt.format_code_scope, t); case FN: + // distinguish `foo(List{int} x) {...}` and `foo() { ... }` + if (state.last_token == TYPE_IDENT) { + self.cache_statement_dump()!; + return self.push_run_state(&CodeFmt.format_generic_type_scope, t); + } self.trace("fn foo() { inline enter"); self.cache_statement_dump()!; - self.write(" "); + if (!self.is_prev_scope_generic) { + self.write(" "); + } + self.is_prev_scope_generic = false; return self.push_run_state(&CodeFmt.format_code_scope, t); case FOR: case DO: @@ -684,7 +693,7 @@ fn bool! CodeFmt.format_generic_statement(CodeFmt* self, Token* t, NodeParserSta <* Formatting for extern ... *> -fn bool! CodeFmt.format_generic_extern(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_generic_extern(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -715,7 +724,7 @@ fn bool! CodeFmt.format_generic_extern(CodeFmt* self, Token* t, NodeParserState* <* Formatting of generic code flow statement block (for, while, if, foreach, switch, defer) *> -fn bool! CodeFmt.format_statement_code_flow(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_statement_code_flow(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(state.initial_token != INVALID_TOKEN); assert(t.type != EMPTY_LINE); @@ -916,7 +925,7 @@ fn bool CodeFmt.format_docstring_text_write(&self, Token* t) <* Formatting generic doc string with contracts *> -fn bool! CodeFmt.format_docstring(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_docstring(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -997,6 +1006,7 @@ fn bool! CodeFmt.format_docstring(CodeFmt* self, Token* t, NodeParserState* stat self.newline(); state.transition(SCOPE); case BANG: + case QUESTION: self.write("%s", t.value); case TYPE_IDENT: self.write(" %s", t.value); @@ -1035,7 +1045,7 @@ fn bool! CodeFmt.format_docstring(CodeFmt* self, Token* t, NodeParserState* stat <* Formatting $switch: $case / $default scopes *> -fn bool! CodeFmt.format_comptime_switch_body(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_comptime_switch_body(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); assert(state.initial_token != INVALID_TOKEN); @@ -1123,7 +1133,7 @@ fn bool! CodeFmt.format_comptime_switch_body(CodeFmt* self, Token* t, NodeParser <* Formatting of compile time code flow statement block ($for, $if, $foreach, $switch) *> -fn bool! CodeFmt.format_comptime_code_flow(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_comptime_code_flow(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); assert(state.initial_token != INVALID_TOKEN); @@ -1241,7 +1251,7 @@ fn bool! CodeFmt.format_comptime_code_flow(CodeFmt* self, Token* t, NodeParserSt } <* Asm block with automatically disabled formatting *> -fn bool! CodeFmt.asm_non_fmt_block(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.asm_non_fmt_block(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -1281,7 +1291,7 @@ fn bool! CodeFmt.asm_non_fmt_block(CodeFmt* self, Token* t, NodeParserState* sta <* Formatting asm() and asm { block } *> -fn bool! CodeFmt.format_asm(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_asm(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -1327,7 +1337,7 @@ fn bool! CodeFmt.format_asm(CodeFmt* self, Token* t, NodeParserState* state) @pr <* Formatter for struct / union / bitstruct contents *> -fn bool! CodeFmt.format_structural(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_structural(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -1376,7 +1386,7 @@ fn bool! CodeFmt.format_structural(CodeFmt* self, Token* t, NodeParserState* sta <* Formatter for struct / union / bitstruct contents *> -fn bool! CodeFmt.format_structural_scope(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_structural_scope(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); @@ -1391,7 +1401,23 @@ fn bool! CodeFmt.format_structural_scope(CodeFmt* self, Token* t, NodeParserStat case SCOPE: // struct scope {} self.trace("SCOPE"); switch (t.type) { + case LBRACE: + if (state.last_token == TYPE_IDENT) { + // Inside a struct scope, TYPE_IDENT followed by LBRACE starts a generic type list scope. + self.cache_statement_dump()!; + return self.push_run_state(&CodeFmt.format_generic_type_scope, t); + } else { + if (self.cache_statement_len() == 0) { + self.newline(); + } + self.cache_statement_add(state, t); + } case RBRACE: + if (self.is_prev_scope_generic) { + // Is end of generic type list, rather than end of struct scope. + self.write(" "); + break; + } self.dedent()!; self.newline(); self.write("}"); @@ -1415,9 +1441,10 @@ fn bool! CodeFmt.format_structural_scope(CodeFmt* self, Token* t, NodeParserStat case DOCS_END: break; default: - if (self.cache_statement_len() == 0) { + if (self.cache_statement_len() == 0 && !self.is_prev_scope_generic) { self.newline(); } + self.is_prev_scope_generic = false; self.cache_statement_add(state, t); } default: @@ -1427,15 +1454,96 @@ fn bool! CodeFmt.format_structural_scope(CodeFmt* self, Token* t, NodeParserStat } <* - Formatter for enums, faults + Formatter for generic type list +*> +fn bool? CodeFmt.format_generic_type_scope(CodeFmt* self, Token* t, NodeParserState* state) @private +{ + assert(t.type != EMPTY_LINE); + + switch STATE: (state.check(t)) { + case INVALID_TOKEN: // initial state + assert(t.type == LBRACE); + self.trace("ENTRY"); + self.write("{"); + state.transition(SCOPE); + case SCOPE: // generic scope {} + self.trace("SCOPE"); + switch (t.type) { + case LBRACE: + // Nested generic type list + if (state.last_token == TYPE_IDENT) { + self.cache_statement_dump()!; + return self.push_run_state(&CodeFmt.format_generic_type_scope, t); + } + case RBRACE: + if (state.scope_depth == 0) { + self.trace("EXIT"); + self.cache_statement_dump()!; + self.write("}"); + self.is_prev_scope_generic = true; + return true; + } + default: + self.cache_statement_add(state, t); + } + default: + unreachable(); + } + return false; +} + +<* + Formatter for faults +*> +fn bool? CodeFmt.format_faultdef(CodeFmt* self, Token* t, NodeParserState* state) @private +{ + assert(t.type != EMPTY_LINE); + + switch STATE: (state.check(t)) { + case INVALID_TOKEN: // initial state + assert(t.type == FAULTDEF); + self.trace("ENTRY"); + self.write("%s", t.value); + self.indent(); + state.transition(IDENT); + case IDENT: // fault names + self.trace("IDENT"); + switch (t.type) { + case CONST_IDENT: + self.newline(); + self.write("%s", t.value); + case COMMA: + self.write("%s", t.value); + case AT_IDENT: // attrs + self._lexer.extend_current_attribute(); + self.newline(); + self.write("%s", t.value); + case EOS: + self.write(";"); + state.transition(EOF); + default: + break; + } + case EOF: + self.trace("EXIT"); + self.dedent()!; + return true; + default: + unreachable(); + } + return false; +} + +<* + Formatter for enums *> -fn bool! CodeFmt.format_enumerable(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_enumerable(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); switch STATE: (state.check(t)) { case INVALID_TOKEN: // initial state - assert(t.type == ENUM || t.type == FAULT); + assert(t.type == ENUM); self.trace("ENTRY"); self.write("%s", t.value); state.transition(TYPE_IDENT); @@ -1522,7 +1630,7 @@ fn bool! CodeFmt.format_enumerable(CodeFmt* self, Token* t, NodeParserState* sta <* Formatter for interfaces *> -fn bool! CodeFmt.format_interface(CodeFmt* self, Token* t, NodeParserState* state) @private +fn bool? CodeFmt.format_interface(CodeFmt* self, Token* t, NodeParserState* state) @private { assert(t.type != EMPTY_LINE); diff --git a/lib/c3tools/codefmt/_resolvers.c3 b/lib/c3tools/codefmt/_resolvers.c3 index 09f765c..27d777b 100644 --- a/lib/c3tools/codefmt/_resolvers.c3 +++ b/lib/c3tools/codefmt/_resolvers.c3 @@ -114,6 +114,8 @@ macro bool CodeFmt._resolve_current_token(&self, NodeParserState* state, Token* switch (prev_t) { case AMP: // likely &Type.foo if (self._resolve__prev_is_binexp()) pre_space = true; + case LBRACE: + break; default: nextcase TOP: default; } @@ -149,6 +151,7 @@ macro bool CodeFmt._resolve_current_token(&self, NodeParserState* state, Token* case STAR: case LBRACKET: case RGENPAR: + case RBRACE: case RVEC: case BANG: break; @@ -200,6 +203,7 @@ macro bool CodeFmt._resolve_current_token(&self, NodeParserState* state, Token* case CT_TYPE_IDENT: case RPAREN: case RGENPAR: + case RBRACE: case RVEC: case LPAREN: break; @@ -211,22 +215,29 @@ macro bool CodeFmt._resolve_current_token(&self, NodeParserState* state, Token* case RPAREN: break; case RBRACE: + // HACK: generic type related braces are handled in dump func. + // array related brace switch (prev_t) { case LBRACE: // empty {} break; default: - pre_space = state.scope_depth == 0; + pre_space = self._resolve__rbrace_prespace(); } break; case LBRACE: switch (prev_t) { + case IDENT: + case TYPE_IDENT: + case CT_TYPE_IDENT: case RGENPAR: + case RBRACE: case RVEC: - // List(){}.init(...) + // (List{Foo}){}.init(...) break; case COMMA: + case RPAREN: pre_space = true; default: nextcase TOP: default; @@ -290,6 +301,7 @@ macro bool CodeFmt._resolve_current_token(&self, NodeParserState* state, Token* case CT_TYPE_IDENT: case RVEC: case RGENPAR: + case RBRACE: case STAR: case GREATER: // new generic syntax Foo<[bar]> case QUESTION: @@ -387,18 +399,19 @@ macro bool CodeFmt._resolve_default_space(&self, NodeParserState* state, Token* case NEXTCASE: case INLINE: case TYPEID: - case DISTINCT: + case TYPEDEF: case BREAK: case CONTINUE: case RVEC: case RGENPAR: + case RBRACE: case TRY: case FN: case IF: case FOR: case FOREACH: case DEFER: - case DEF: + case ALIAS: case CONST: case TLOCAL: case STATIC: @@ -502,6 +515,7 @@ fn bool CodeFmt._resolve__prev_bang_type(&self) @private case TYPE_IDENT: case RVEC: case RGENPAR: + case RBRACE: case STAR: case GREATER: // new generic notation ]> return true; @@ -655,6 +669,8 @@ fn bool CodeFmt._resolve__prev_is_binexp(&self) @private case RVEC: case LGENPAR: case RGENPAR: + case LBRACE: + case RBRACE: has_brackets = true; case BIT_AND_ASSIGN: case BIT_OR_ASSIGN: @@ -702,7 +718,7 @@ fn bool CodeFmt._resolve__prev_is_binexp(&self) @private do { if (has_parens) { // simple cast (void*) - // generic cast (Foo()*) / array cast (char[8]*) + // generic cast (Foo{void}*) / array cast (char[8]*) if (has_type) { if(has_typeof || !has_vars) is_cast = true; break; @@ -735,7 +751,7 @@ fn bool CodeFmt._resolve__prev_is_binexp(&self) @private *> fn usz CodeFmt._resolve__next_is_cast_and_dump(&self, usz current_idx) @private { - NodeParserState tmpstate = NodeParserState {}; + NodeParserState tmpstate = {}; bool is_cast = true; bool has_type = false; @@ -763,6 +779,8 @@ fn usz CodeFmt._resolve__next_is_cast_and_dump(&self, usz current_idx) @private case RVEC: case LGENPAR: case RGENPAR: + case LBRACE: + case RBRACE: break; default: is_cast = false; @@ -826,6 +844,8 @@ fn bool CodeFmt._resolve__prev_is_cast(&self) @private case RVEC: case LGENPAR: case RGENPAR: + case LBRACE: + case RBRACE: case LBRACKET: case RBRACKET: case QUESTION: @@ -838,6 +858,22 @@ fn bool CodeFmt._resolve__prev_is_cast(&self) @private return is_cast && has_type; } +<* + Checks previous token type in token cache +*> +fn TokenType CodeFmt._resolve__prev_token(&self, usz current_idx, usz nth) @private +{ + isz idx = (isz)current_idx; + usz count = 0; + TokenType result = INVALID_TOKEN; + while (--idx >= 0) { + result = self.__token_cache[idx].type; + if (result != SPACE) count++; + if (count >= nth) break; + } + return result; +} + <* Checks next token type in token cache *> @@ -854,13 +890,28 @@ fn TokenType CodeFmt._resolve__next_token(&self, usz current_idx) @private <* Checks if we need a white space before ? *> -fn bool CodeFmt._resolve__next_question_is_error(&self, usz current_idx) @private +fn bool CodeFmt._resolve__question_prespace(&self, usz current_idx) @private { // Resolves ambiguity // foo ? bar : baz; - // return foo?; - // foo ?? ERR?!; + // foo ?? ERR?; // a = foo ? !bar : baz; + // List{Foo}? foo_list; + // List{Foo}*? foo_list_ptr; + + // Resolve by previous token. + switch (self._resolve__prev_token(current_idx, 1)) { + case TYPE_IDENT: + case RVEC: + case STAR: + case RBRACE: + // No pre-space if previous expression is a type (array, vector, pointer, generic type). + return false; + default: + break; + } + + // Resolve by next token. switch (self._resolve__next_token(current_idx)) { case EOS: case RPAREN: @@ -869,6 +920,7 @@ fn bool CodeFmt._resolve__next_question_is_error(&self, usz current_idx) @privat case RBRACKET: case RVEC: case RGENPAR: + case RBRACE: case INVALID_TOKEN: return false; case BANG: @@ -882,3 +934,35 @@ fn bool CodeFmt._resolve__next_question_is_error(&self, usz current_idx) @privat } return true; } + +fn isz CodeFmt.__locate_matching_lbrace(&self) @private +{ + isz scope_depth = 1; + isz idx = (isz)self.__token_cache.len(); + while (--idx >= 0) { + switch (self.__token_cache[idx].type) { + case RBRACE: scope_depth++; + case LBRACE: scope_depth--; + default: break; + } + if (scope_depth == 0) return idx; + } + return -1; +} + +<* + Determine if a space should add before '}'. +*> +fn bool CodeFmt._resolve__rbrace_prespace(&self) @private +{ + if (self.state_stack.len() == 0) return false; + if (self.__token_cache.len() == 0) return false; + + isz lbrace = self.__locate_matching_lbrace(); + if (lbrace == -1) return false; + + // We take a shortcut to make thing easier. + // Since the LBRACE is properly formatted already, we just mirror the space after it. + return self.__token_cache[lbrace+1].type == SPACE + && self.__token_cache[^1].type != SPACE; +} diff --git a/lib/c3tools/codefmt/codefmt.c3 b/lib/c3tools/codefmt/codefmt.c3 index cd57c98..270f91d 100644 --- a/lib/c3tools/codefmt/codefmt.c3 +++ b/lib/c3tools/codefmt/codefmt.c3 @@ -11,8 +11,8 @@ struct CodeFmt { Lexer _lexer; DString buf; - List() state_stack; - List() __token_cache; + List{CodeFmtState} state_stack; + List{Token} __token_cache; char indent_type; usz max_line_width; usz _indent_level; @@ -23,12 +23,15 @@ struct CodeFmt bool _is_inline_comment; bool _is_cascade_call; bool _skip_next_new_line; + + // Track if the last stack is for generics type list + bool is_prev_scope_generic; } <* CodeFmt processing function signature *> -def CodeFmtFn = fn bool! (CodeFmt* self, Token* t, NodeParserState* state) @private; +alias CodeFmtFn = fn bool? (CodeFmt* self, Token* t, NodeParserState* state); <* Item for code formatting state stack @@ -41,7 +44,7 @@ struct CodeFmtState @private } <* Simple white space synthetic token *> -const Token TOKEN_SPACE @private = Token { .type = SPACE, .value = " " }; +const Token TOKEN_SPACE @private = { .type = SPACE, .value = " " }; /* * CODE FORMATTER OBJECT @@ -53,15 +56,15 @@ const Token TOKEN_SPACE @private = Token { .type = SPACE, .value = " " }; @require max_line_width >= 80 : "too short" @require max_line_width <= 120 : "too long" *> -fn CodeFmt CodeFmt.new_init(int max_line_width = 80, char indent_type = '4') @operator(construct) +fn CodeFmt new_init(int max_line_width = 80, char indent_type = '4') { CodeFmt self = { .max_line_width = max_line_width, .indent_type = indent_type, }; - self.buf.new_init(); - self.state_stack.new_init(); - self.__token_cache.new_init(); + self.buf.init(mem); + self.state_stack.init(mem); + self.__token_cache.init(mem); return self; } @@ -81,7 +84,7 @@ fn void CodeFmt.free(&self) NOTE: result will live until next CodeFmt.format() or CodeFmt.free() call *> -fn String! CodeFmt.format(&self, String contents, bool print_lex = false) +fn String? CodeFmt.format(&self, String contents, bool print_lex = false) { switch (self.indent_type) { case '2': @@ -91,7 +94,7 @@ fn String! CodeFmt.format(&self, String contents, bool print_lex = false) break; default: io::eprintfn("Invalid separator value: expected 2,4,8 or t"); - return IoError.GENERAL_ERROR?; + return io::GENERAL_ERROR?; } self._print_lex = print_lex; @@ -155,7 +158,7 @@ fn String! CodeFmt.format(&self, String contents, bool print_lex = false) <* Pushes new state handler function to stack. Allows parsing sub-structs, etc... *> -fn bool! CodeFmt.push_run_state( +fn bool? CodeFmt.push_run_state( &self, CodeFmtFn new_state, Token* t, TokenType initial_token = INVALID_TOKEN ) @private { @@ -178,7 +181,7 @@ fn bool! CodeFmt.push_run_state( <* Pops last state from state_stack *> -fn void! CodeFmt.pop_state(&self) @private +fn void? CodeFmt.pop_state(&self) @private { assert(self.cache_statement_len() == 0, "cache_statement is not empty, forgot dump?"); @@ -188,7 +191,7 @@ fn void! CodeFmt.pop_state(&self) @private <* Runs last state in the state_stack with current token *> -fn bool! CodeFmt.run_state(&self, Token* t) @private +fn bool? CodeFmt.run_state(&self, Token* t) @private { if (self.state_stack.len() == 0) return false; CodeFmtFn state_fn = self.state_stack[^1].state_fn; @@ -199,7 +202,7 @@ fn bool! CodeFmt.run_state(&self, Token* t) @private <* Emits formatting procedure error with debug message *> -macro bool! CodeFmt.@fail(&self, Token* t, String msg) @private +macro bool? CodeFmt.@fail(&self, Token* t, String msg) @private { if (t != null) { io::eprintfn("Patially formatted code:\n```\n%s```", self.buf.str_view()); @@ -215,7 +218,7 @@ macro bool! CodeFmt.@fail(&self, Token* t, String msg) @private } else { io::eprintfn("Error at line %s - %s", self._lexer.current_row, msg); } - return IoError.GENERAL_ERROR?; + return io::GENERAL_ERROR?; } <* @@ -300,7 +303,7 @@ macro void CodeFmt.indent(&self) @private <* Decreases code indent *> -macro void! CodeFmt.dedent(&self) @private +macro void? CodeFmt.dedent(&self) @private { self.trace("dedent"); if (self._indent_level == 0) { diff --git a/lib/c3tools/lsp/_common.c3 b/lib/c3tools/lsp/_common.c3 index 872d903..06bc7bd 100644 --- a/lib/c3tools/lsp/_common.c3 +++ b/lib/c3tools/lsp/_common.c3 @@ -17,7 +17,7 @@ enum SymbolKind ENUM, // MyEnum.BAR / MyFault.ANOTHER STRUCT, // struct Name TYPE, // custom TypeName - GENERIC, // generic type List() + GENERIC, // generic type List{int} ARRAY, // array or List or other collection of items BUILTIN, // represents builtin type/func/const/keyword } diff --git a/lib/c3tools/lsp/_document.c3 b/lib/c3tools/lsp/_document.c3 index 1100b67..797b6d0 100644 --- a/lib/c3tools/lsp/_document.c3 +++ b/lib/c3tools/lsp/_document.c3 @@ -34,14 +34,14 @@ struct DocumentContext { } -fn Document Document.new_open(String uri, String full_source, LspProject* proj) @operator(construct) +fn Document new_document(String uri, String full_source, LspProject* proj) { Document self = { .proj = proj, }; // TODO: estimate average source size - self._allocator.init(1024, allocator::heap()); + self._allocator.init(mem, 1024); // Allocate AST first, it will fill the arena with local metadata self.ast = ast::parse(full_source, file_path: uri, allc: &self._allocator); @@ -50,20 +50,20 @@ fn Document Document.new_open(String uri, String full_source, LspProject* proj) self.uri = uri.copy(&self._allocator); // NOTE: source is allocated in heap, not in arena + add extra space for editing - self.source.new_init(capacity: full_source.len * 2, allocator: allocator::heap()); + self.source.init(allocator: mem, capacity: full_source.len * 2); self.source.append(full_source); return self; } -fn void! Document.save(&self, String full_sourse) +fn void? Document.save(&self, String full_sourse) { // update full document structure? // trigger LspProject* document decls updates? } -fn void! Document.change(&self, List() changes) +fn void? Document.change(&self, List{DocChange} changes) { // update document scope structure diff --git a/lib/c3tools/lsp/_project.c3 b/lib/c3tools/lsp/_project.c3 index f98e5ea..eac3caa 100644 --- a/lib/c3tools/lsp/_project.c3 +++ b/lib/c3tools/lsp/_project.c3 @@ -18,7 +18,7 @@ struct LspProject allocator::DynamicArenaAllocator _allocator; } -fn LspProject LspProject.new_init(String proj_path, String stdlib_path) @operator(construct) +fn LspProject new_lsp_project(String proj_path, String stdlib_path) { LspProject self = { .proj_path = proj_path, @@ -26,20 +26,20 @@ fn LspProject LspProject.new_init(String proj_path, String stdlib_path) @operato }; // Arena allocator for storing all AST metadata (DynamicArenaAllocator backed by heap) - self._allocator.init(5 * 1024 * 1024, allocator::heap()); + self._allocator.init(mem, 5 * 1024 * 1024); // All other allocations are done on heap to isolate AST data and make it sequential - self.modules = SymbolCache.new_init(capacity: 512); + self.modules = symbols::new_symbol_cache(capacity: 512); // We will store symbols for core/std/project separately because they might have different // access or update patterns within LSP lifetime // builtin + std::core - self.sym_core = SymbolCache.new_init(capacity: 128); + self.sym_core = symbols::new_symbol_cache(capacity: 128); // all other stdlib symbols - self.sym_std = SymbolCache.new_init(capacity: 1024); + self.sym_std = symbols::new_symbol_cache(capacity: 1024); // project symbols - self.sym_proj = SymbolCache.new_init(capacity: 1024); + self.sym_proj = symbols::new_symbol_cache(capacity: 1024); return self; } @@ -54,7 +54,7 @@ fn void LspProject.free(&self) self._allocator.free(); } -fn void! LspProject.module_add(&self, AstModule* m) @private +fn void? LspProject.module_add(&self, AstModule* m) @private { assert(m.hash != 0, "module hash is zero"); SymbolItem* it = self.modules.add(m.value); @@ -63,7 +63,7 @@ fn void! LspProject.module_add(&self, AstModule* m) @private it.ptr.mod = m; } -fn void! LspProject.load_symbols(&self) +fn void? LspProject.load_symbols(&self) { assert(self.modules.len() > 0, "load modules first"); SymbolItem* items = self.modules.items(); @@ -88,7 +88,7 @@ fn void! LspProject.load_symbols(&self) // ); } -fn void! LspProject._load_module_symbols(&self, SymbolCache** dest, AstModule* src) @private +fn void? LspProject._load_module_symbols(&self, SymbolCache** dest, AstModule* src) @private { assert(src.hash, "no module hash"); // io::eprintfn("adding module symbols: %s", src.value); @@ -109,7 +109,7 @@ fn void! LspProject._load_module_symbols(&self, SymbolCache** dest, AstModule* s } } -fn void! LspProject._add_symbol(&self, SymbolCache* dest, AstModule* src, AstTypeDef* decl) @private +fn void? LspProject._add_symbol(&self, SymbolCache* dest, AstModule* src, AstTypeDef* decl) @private { bool is_private = false; bool is_conditional = false; @@ -126,7 +126,7 @@ fn void! LspProject._add_symbol(&self, SymbolCache* dest, AstModule* src, AstTyp // declarations.push(ModuleDecl {.mod = m, .decl = decl}); } -fn void! LspProject.load_source(&self, String full_source, String file_path) +fn void? LspProject.load_source(&self, String full_source, String file_path) { Ast ast = ast::parse(full_source, file_path, allc: &self._allocator); @@ -137,27 +137,27 @@ fn void! LspProject.load_source(&self, String full_source, String file_path) } } -fn void! LspProject.load_path(&self, String path) @local +fn void? LspProject.load_path(&self, String path) @local { assert(path); - path::Path p = path::temp_new(path)!; + path::Path p = path::temp(path)!; if (!path::exists(p)) { - return IoError.FILE_NOT_FOUND?; + return io::FILE_NOT_FOUND?; } if (!path::is_dir(p)) { - return IoError.FILE_NOT_DIR?; + return io::FILE_NOT_DIR?; } - path::PathWalker fnwalk = fn bool! (Path p, bool is_dir, void* ctx) { + path::PathWalker fnwalk = fn bool? (Path p, bool is_dir, void* ctx) { LspProject* self = (LspProject*)ctx; if (is_dir) return false; if (!p.has_extension("c3")) { return false; } - String contents = (String)file::load_new(p.str_view())!; - defer contents.free(); + String contents = (String)file::load(mem, p.str_view())!; + defer contents.free(mem); self.load_source(contents, p.str_view())!; @@ -166,7 +166,7 @@ fn void! LspProject.load_path(&self, String path) @local p.walk(fnwalk, self)!!; } -fn void! LspProject.load(&self) +fn void? LspProject.load(&self) { assert(self.modules.len() == 0, "double load?"); diff --git a/lib/c3tools/lsp/_symbols.c3 b/lib/c3tools/lsp/_symbols.c3 index f6907f3..972b622 100644 --- a/lib/c3tools/lsp/_symbols.c3 +++ b/lib/c3tools/lsp/_symbols.c3 @@ -56,7 +56,7 @@ struct SymbolItem @align(32) $assert(SymbolItem.sizeof == 32); -fn SymbolCache* SymbolCache.new_init(uint capacity) @operator(construct) +fn SymbolCache* new_symbol_cache(uint capacity) { // NOTE: adding extra +1 to capacity for sentinel record usz data_size = calc_data_size(capacity + 1); @@ -89,12 +89,12 @@ macro uint SymbolCache.len(&self) => self.items_len; Finds first SymbolItem* in SymbolCache with the same hash as name_or_hash, this method is expected to be used in a loop with SymbolCache.next() for checking all collisions. - @param name_or_hash "Fnv32a hash or String name" + @param name_or_hash: "Fnv32a hash or String name" *> macro SymbolItem* SymbolCache.first(&self, name_or_hash) { Fnv32a hash; - $switch ($typeof(name_or_hash)) + $switch $typeof(name_or_hash): $case String: hash.init(); hash.update(name_or_hash); @@ -114,7 +114,7 @@ macro SymbolItem* SymbolCache.first(&self, name_or_hash) <* Returns next item with hash collision (if any) - @param [in] item "Item returned by previous SymbolCache.find()" + @param [in] item: "Item returned by previous SymbolCache.find()" @return "next item or null if not exist" @require item != null *> @@ -216,7 +216,7 @@ fn SymbolCache* SymbolCache.grow(&self, uint new_capacity) // Force clean memory region which was previously allocated by names, and now it's for items for (usz i = old_items_capacity; i < self.items_capacity; i++) { - items[i] = SymbolItem {}; + items[i] = {}; } // Restoring sentinel data for after growing @@ -241,8 +241,8 @@ struct SymbolItemIterator uint next_idx; } -macro SymbolNameIterator SymbolCache.iter_names(&self) => SymbolNameIterator { .cache = self }; -macro SymbolItemIterator SymbolCache.iter_items(&self) => SymbolItemIterator { .cache = self }; +macro SymbolNameIterator SymbolCache.iter_names(&self) => { .cache = self }; +macro SymbolItemIterator SymbolCache.iter_items(&self) => { .cache = self }; macro usz SymbolNameIterator.len(self) @operator(len) => self.cache.names_cnt; macro usz SymbolItemIterator.len(self) @operator(len) => self.cache.items_len; @@ -346,7 +346,7 @@ macro SymbolItem* SymbolCache._insert_item(&self, Fnv32a hash, uint insert_at) @ for (int i = self.items_len - 1; i > insert_at; i--) { items[i] = items[i - 1]; } - items[insert_at] = SymbolItem { .hash = hash }; + items[insert_at] = { .hash = hash }; return &items[insert_at]; } diff --git a/lib/c3tools/lsp/lsp.c3 b/lib/c3tools/lsp/lsp.c3 index 1a09e21..2d44b2d 100644 --- a/lib/c3tools/lsp/lsp.c3 +++ b/lib/c3tools/lsp/lsp.c3 @@ -5,15 +5,15 @@ import std::collections::map; struct Lsp { LspProject proj; - HashMap() documents; + HashMap{String, Document} documents; } -fn void! Lsp.new_init(&self, String project_root, String stdlib_path) +fn void? Lsp.new_init(&self, String project_root, String stdlib_path) { - self.proj = LspProject.new_init(project_root, stdlib_path); + self.proj = project::new_lsp_project(project_root, stdlib_path); if (catch err = self.proj.load()) { - log::error("c3 project load failed: %s", err); + lsp::log::error("c3 project load failed: %s", err); return err?; } @@ -26,10 +26,10 @@ fn void Lsp.free(&self){ } -fn void! Lsp.document_did_open(&self, String uri, String full_source) +fn void? Lsp.document_did_open(&self, String uri, String full_source) { assert(uri.starts_with("file://")); - Document d = Document.new_open(uri, full_source, &self.proj); + Document d = lsp::new_document(uri, full_source, &self.proj); assert(!self.documents.has_key(uri), "document is already open"); self.documents[uri] = d; diff --git a/scripts/c3fmt_gentests.c3 b/scripts/c3fmt_gentests.c3 index b4b79d0..ed715c4 100644 --- a/scripts/c3fmt_gentests.c3 +++ b/scripts/c3fmt_gentests.c3 @@ -4,28 +4,28 @@ import std::collections::list; import c3lib::codegen; import c3tools::codefmt::codecorpus @public; -fn void! load_corpus(CodeGen* code, String path) @local +fn void? load_corpus(CodeGen* code, String path) @local { assert(path); - path::Path p = path::temp_new(path)!; + path::Path p = path::temp(path)!; io::printfn("Processing path: %s", p.str_view()); if (!path::exists(p)) { - return IoError.FILE_NOT_FOUND?; + return io::FILE_NOT_FOUND?; } if (!path::is_dir(p)) { - return IoError.FILE_NOT_DIR?; + return io::FILE_NOT_DIR?; } - path::PathWalker fnwalk = fn bool! (Path p, bool is_dir, void* ctx) { + path::PathWalker fnwalk = fn bool? (Path p, bool is_dir, void* ctx) { CodeGen* code = ctx; if (is_dir) return false; if (!p.has_extension("txt")) return false; io::printfn("Parsing corpus: %s", p.str_view()); - List()! corpus = codecorpus::new_parse(p.str_view()); + List{CodeCorpus}? corpus = codecorpus::new_parse(p.str_view()); defer (void)corpus.free(); if (catch err = corpus) { @@ -39,7 +39,7 @@ fn void! load_corpus(CodeGen* code, String path) @local foreach (c : corpus) { code.@fn("void test_corpus__%s__%s()", file_part, c.case_name) { - code.wn("CodeFmt fmt = CodeFmt.new_init()"); + code.wn("CodeFmt fmt = codefmt::new_init()"); code.wn("defer fmt.free()"); // NOTE: adding \n to input + input[1..] when check for visual formatting reasons code.wn("String input = `\n%s`", c.case_input); @@ -53,8 +53,8 @@ fn void! load_corpus(CodeGen* code, String path) @local code.wn( "test::@check(codecorpus::compare_output(expected[1..], formatted), `format mismatch`)" ); - code.wn("String fmt_out = formatted.copy()"); - code.wn("defer fmt_out.free()"); + code.wn("String fmt_out = formatted.copy(mem)"); + code.wn("defer fmt_out.free(mem)"); code.wn("formatted = fmt.format(fmt_out, print_lex: false)!!"); code.wn("assert(fmt_out.ptr != formatted.ptr)"); code.@if("expected[1..] != formatted") { @@ -79,7 +79,8 @@ fn void! load_corpus(CodeGen* code, String path) @local fn int main(String[] args) { - CodeGen* code = CodeGen {}.new_init(); + CodeGen code; + code.init(); defer code.free(); code.@module("test::c3tools::c3fmt_corpus @test"); @@ -87,13 +88,13 @@ fn int main(String[] args) code.@import("c3tools::codefmt::codecorpus @public"); code.@import("std::io"); - Path p = path::temp_cwd()!!; + Path p = path::tcwd()!!; io::printfn("cwd: %s", p.str_view()); String cwd = "../test/c3tools/codefmt/c3fmt_corpus"; String out_file = "../test/c3tools/codefmt/test_c3fmt_corpus.c3"; - if (catch err = load_corpus(code, cwd)) { + if (catch err = load_corpus(&code, cwd)) { return 1; } diff --git a/src/c3fmt/c3fmt.c3 b/src/c3fmt/c3fmt.c3 index b950311..8d2e0ac 100644 --- a/src/c3fmt/c3fmt.c3 +++ b/src/c3fmt/c3fmt.c3 @@ -61,35 +61,35 @@ fn int main(String[] args) return 0; } -fn void! format_file( +fn void? format_file( String file_name, int max_line_width, bool force_mode, bool dry_mode, String indent_type ) { - path::Path p = path::temp_new(file_name)!; + path::Path p = path::temp(file_name)!; if (!path::exists(p)) { io::printfn("File not exists: %s", file_name); - return IoError.FILE_NOT_FOUND?; + return io::FILE_NOT_FOUND?; } if (path::is_dir(p)) { io::printfn("Expected file, got directory: %s", file_name); - return IoError.FILE_IS_DIR?; + return io::FILE_IS_DIR?; } if (!force_mode && !p.has_extension("c3")) { io::printfn("Expected only .c3 expension (or use --force flag) %s", file_name); - return IoError.GENERAL_ERROR?; + return io::GENERAL_ERROR?; } if (indent_type.len != 1) { io::printfn("--indent= parameter must be a 2,4,8 or t, got '%s'", indent_type); - return IoError.GENERAL_ERROR?; + return io::GENERAL_ERROR?; } io::printfn("Path: %s", p.str_view()); - String contents = (String)file::load_new(p.str_view())!; - defer contents.free(); + String contents = (String)file::load(mem, p.str_view())!; + defer contents.free(mem); - CodeFmt fmt = CodeFmt.new_init(max_line_width: max_line_width, indent_type: indent_type[0]); + CodeFmt fmt = codefmt::new_init(max_line_width: max_line_width, indent_type: indent_type[0]); defer fmt.free(); String formatted = fmt.format(contents, print_lex: false)!!; diff --git a/src/c3fzf/c3fzf.c3 b/src/c3fzf/c3fzf.c3 index 0a7de16..6d49037 100644 --- a/src/c3fzf/c3fzf.c3 +++ b/src/c3fzf/c3fzf.c3 @@ -81,7 +81,7 @@ fn int main(String[] args) return 0; } -fn void! find(FzfSettings* settings) @local +fn void? find(FzfSettings* settings) @local { if (settings.preview && settings.module_filter == ".") { io::printfn("You must pass full module name in a module filter argument, got ."); @@ -96,7 +96,7 @@ fn void! find(FzfSettings* settings) @local settings.project_path = proj_abs.str_view(); defer proj_abs.free(); - Path! std_abs = path::temp_new(settings.stdlib_path).new_absolute(); + Path? std_abs = path::temp_new(settings.stdlib_path).new_absolute(); defer { if(try std_abs) std_abs.free(); } @@ -105,7 +105,7 @@ fn void! find(FzfSettings* settings) @local settings.stdlib_path = std_abs.str_view(); } - LspProject proj = LspProject.new_init(settings.project_path, settings.stdlib_path); + LspProject proj = project::new_lsp_project(settings.project_path, settings.stdlib_path); defer proj.free(); if (catch err = proj.load()) { @@ -119,7 +119,7 @@ fn void! find(FzfSettings* settings) @local return print_modules_list(settings, &proj); } - List() declarations; + List{ModuleDecl} declarations; declarations.temp_init(proj.modules.items_len); foreach (&sym : proj.modules.iter_items()) { @@ -188,9 +188,9 @@ fn int cmp_str(String a, String b) return (int)(an - bn); } -fn void! print_modules_list(FzfSettings* settings, LspProject* proj) @local +fn void? print_modules_list(FzfSettings* settings, LspProject* proj) @local { - List() modules; + List{String} modules; modules.new_init(proj.modules.len()); defer modules.free(); @@ -224,20 +224,20 @@ macro print_nodes(format, ast_nodes, String sep = "") } } -fn void print_decl_def(AstTypeDef* d, bool is_full_preview) +fn void print_decl_alias(AstTypeDef* d, bool is_full_preview) { - assert(d.type == TokenType.DEF); + assert(d.type == TokenType.ALIAS); - io::printf("def %s = ", d.value); + io::printf("alias %s = ", d.value); print_nodes("%s", d.ftype, sep: " "); io::printfn(";"); } -fn void print_decl_distinct(AstTypeDef* d, bool is_full_preview) +fn void print_decl_typedef(AstTypeDef* d, bool is_full_preview) { - assert(d.type == TokenType.DISTINCT); + assert(d.type == TokenType.TYPEDEF); - io::printf("distinct %s = ", d.value); + io::printf("typedef %s = ", d.value); print_nodes("%s", d.ftype); io::printfn(";"); } @@ -278,7 +278,7 @@ fn void print_decl_struct(AstTypeDefStructural* d, bool is_full_preview, uint in print_docs(d.docs); } - DString idt = dstring::temp_new(); + DString idt = dstring::temp(); for (uint i = 0; i < indent; i++) { idt.append(" "); } @@ -396,8 +396,8 @@ fn String strip_path(FzfSettings* settings, String path) { return result; } -fn void! print_preview( - FzfSettings* settings, LspProject* proj, List() declarations, bool is_full_preview +fn void? print_preview( + FzfSettings* settings, LspProject* proj, List{ModuleDecl} declarations, bool is_full_preview ) @local { @@ -430,10 +430,10 @@ fn void! print_preview( if (d.decl == null) continue; switch (d.decl.type) { - case DEF: - print_decl_def((AstTypeDef*)d.decl, is_full_preview); - case DISTINCT: - print_decl_distinct((AstTypeDef*)d.decl, is_full_preview); + case ALIAS: + print_decl_alias((AstTypeDef*)d.decl, is_full_preview); + case TYPEDEF: + print_decl_typedef((AstTypeDef*)d.decl, is_full_preview); case ENUM: case FAULT: print_decl_enum((AstTypeDefEnumerable*)d.decl, is_full_preview); @@ -488,12 +488,12 @@ fn int cmp_decl(ModuleDecl a, ModuleDecl b) @private break; } case STRUCT: - case DEF: - case DISTINCT: + case ALIAS: + case TYPEDEF: switch (b.decl.type) { case STRUCT: - case DEF: - case DISTINCT: + case ALIAS: + case TYPEDEF: is_comparable_type = true; default: break; diff --git a/src/examples/argparse_subcommand_example.c3 b/src/examples/argparse_subcommand_example.c3 index d37d819..4f842bd 100644 --- a/src/examples/argparse_subcommand_example.c3 +++ b/src/examples/argparse_subcommand_example.c3 @@ -20,7 +20,7 @@ struct Config } } -fn void! command_compile(Config* config, ArgParse* agp) +fn void? command_compile(Config* config, ArgParse* agp) { assert(agp.arguments[0] == "compile"); @@ -98,7 +98,7 @@ fn int main(String[] args) .short_name = 'O', .value = &config, .help = "optimization level [default: O0]", - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { Config* ctx = anycast(opt.value, Config)!; int level = value.to_integer(int)!; io::printfn("optimization level arg callback: -O%s", value); diff --git a/src/examples/c3test.c3 b/src/examples/c3test.c3 index 50001dc..2a9511d 100644 --- a/src/examples/c3test.c3 +++ b/src/examples/c3test.c3 @@ -16,7 +16,7 @@ struct Config } } -fn void! command_compile(Config* config, ArgParse* agp) +fn void? command_compile(Config* config, ArgParse* agp) { assert(agp.arguments[0] == "compile"); @@ -72,7 +72,7 @@ fn int main(String[] args) .short_name = 'O', .value = &config, .help = "optimization level [default: O0]", - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { Config* ctx = anycast(opt.value, Config)!; int level = value.to_integer(int)!; io::printfn("optimization level arg callback: -O%s", value); diff --git a/test/c3lib/test_argparse.c3 b/test/c3lib/test_argparse.c3 index cddaf73..09ec1d4 100644 --- a/test/c3lib/test_argparse.c3 +++ b/test/c3lib/test_argparse.c3 @@ -60,7 +60,7 @@ fn void test_help_show() }; String[] args = { "testprog", "-h" }; - test::@error(agp.parse(args), ArgError.HELP_SHOW); + test::@error(agp.parse(args), argparse::HELP_SHOW); } fn void test_help_show_long() @@ -76,7 +76,7 @@ fn void test_help_show_long() }; String[] args = { "testprog", "--help" }; - test::@error(agp.parse(args), ArgError.HELP_SHOW); + test::@error(agp.parse(args), argparse::HELP_SHOW); } fn void test_bool_flag() @@ -270,7 +270,7 @@ fn void test_invalid_arg_short() }; String[] args = { "testprog", "-z" }; - test::@error(agp.parse(args), ArgError.INVALID_ARGUMENT); + test::@error(agp.parse(args), argparse::INVALID_ARGUMENT); } fn void test_invalid_arg_long() @@ -289,7 +289,7 @@ fn void test_invalid_arg_long() }; String[] args = { "testprog", "--zooo" }; - test::@error(agp.parse(args), ArgError.INVALID_ARGUMENT); + test::@error(agp.parse(args), argparse::INVALID_ARGUMENT); } fn void test_missing_require_argument() @@ -309,7 +309,7 @@ fn void test_missing_require_argument() }; String[] args = { "testprog" }; - test::@error(agp.parse(args), ArgError.MISSING_ARGUMENT); + test::@error(agp.parse(args), argparse::MISSING_ARGUMENT); } fn void test_missing_require_arguments_many() @@ -336,7 +336,7 @@ fn void test_missing_require_arguments_many() }; String[] args = { "testprog" }; - test::@error(agp.parse(args), ArgError.MISSING_ARGUMENT); + test::@error(agp.parse(args), argparse::MISSING_ARGUMENT); } fn void test_passing_short_option_after_argument() @@ -355,7 +355,7 @@ fn void test_passing_short_option_after_argument() }; String[] args = { "testprog", "foo", "-f" }; - test::@error(agp.parse(args), ArgError.INVALID_ARGUMENT); + test::@error(agp.parse(args), argparse::INVALID_ARGUMENT); } fn void test_passing_long_option_after_argument() @@ -374,7 +374,7 @@ fn void test_passing_long_option_after_argument() }; String[] args = { "testprog", "foo", "--flt" }; - test::@error(agp.parse(args), ArgError.INVALID_ARGUMENT); + test::@error(agp.parse(args), argparse::INVALID_ARGUMENT); } fn void test_multiple_short_args() @@ -423,7 +423,7 @@ fn void test_str_set_next_arg_missing_value_with_eqchar() }; String[] args = { "testprog", "--flt=" }; - test::@error(agp.parse(args), ArgError.ARGUMENT_VALUE); + test::@error(agp.parse(args), argparse::ARGUMENT_VALUE); } fn void test_str_set_next_arg_missing_value() @@ -442,7 +442,7 @@ fn void test_str_set_next_arg_missing_value() }; String[] args = { "testprog", "--flt" }; - test::@error(agp.parse(args), ArgError.ARGUMENT_VALUE); + test::@error(agp.parse(args), argparse::ARGUMENT_VALUE); } fn void test_str_set_next_arg_is_another_option() @@ -466,7 +466,7 @@ fn void test_str_set_next_arg_is_another_option() }; String[] args = { "testprog", "--flt", "-a" }; - test::@error(agp.parse(args), ArgError.ARGUMENT_VALUE); + test::@error(agp.parse(args), argparse::ARGUMENT_VALUE); } fn void test_str_set_next_arg_is_another_option_long() @@ -490,7 +490,7 @@ fn void test_str_set_next_arg_is_another_option_long() }; String[] args = { "testprog", "--flt", "--all" }; - test::@error(agp.parse(args), ArgError.ARGUMENT_VALUE); + test::@error(agp.parse(args), argparse::ARGUMENT_VALUE); } fn void test_duplicated_flag() @@ -505,7 +505,7 @@ fn void test_duplicated_flag() }; String[] args = { "testprog", "--all", "--all" }; - test::@error(agp.parse(args), ArgError.INVALID_ARGUMENT); + test::@error(agp.parse(args), argparse::INVALID_ARGUMENT); } fn void test_integer_option_i32() @@ -542,7 +542,7 @@ fn void test_integer_option_parsing_error() }; String[] args = { "testprog", "--int=a" }; - test::@error(agp.parse(args), ArgError.ARGUMENT_VALUE); + test::@error(agp.parse(args), argparse::ARGUMENT_VALUE); } fn void test_integer_option_parsing_error_short() @@ -561,7 +561,7 @@ fn void test_integer_option_parsing_error_short() }; String[] args = { "testprog", "-i", "a" }; - test::@error(agp.parse(args), ArgError.ARGUMENT_VALUE); + test::@error(agp.parse(args), argparse::ARGUMENT_VALUE); } fn void test_integer_option_u32() @@ -718,7 +718,7 @@ fn void test_empty_argument() }; String[] args = { "testprog", "" }; - test::@error(agp.parse(args), ArgError.INVALID_ARGUMENT); + test::@error(agp.parse(args), argparse::INVALID_ARGUMENT); } fn void test_multi_arguments_double_dash() @@ -871,7 +871,7 @@ fn void test_custom_type_callback_unknown_type() { char val = '\0'; - ArgParseCallbackFn cbf = fn void! (ArgOpt* opt, String value) { + ArgParseCallbackFn cbf = fn void? (ArgOpt* opt, String value) { io::printfn("flt--callback"); test::eq(value, "bar"); *anycast(opt.value, char)! = value[0]; @@ -891,7 +891,7 @@ fn void test_custom_type_callback_unknown_type() .short_name = 'o', .long_name = "other", .value = &my_app_state, - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { ArgParse* ctx = anycast(opt.value, ArgParse)!; io::printfn("other--callback"); // NOTE: pretends to update important app struct @@ -916,7 +916,7 @@ fn void test_custom_type_callback_str_type() { String val = "foo"; - ArgParseCallbackFn cbf = fn void! (ArgOpt* opt, String value) { + ArgParseCallbackFn cbf = fn void? (ArgOpt* opt, String value) { *anycast(opt.value, String)! = value[0..1]; }; @@ -941,7 +941,7 @@ fn void test_custom_type_callback_str_type_bad_arg() { String val = "foo"; - ArgParseCallbackFn cbf = fn void! (ArgOpt* opt, String value) { + ArgParseCallbackFn cbf = fn void? (ArgOpt* opt, String value) { *anycast(opt.value, String)! = value[0..1]; }; @@ -953,14 +953,14 @@ fn void test_custom_type_callback_str_type_bad_arg() }; String[] args = { "testprog", "--flt=" }; - test::@error(agp.parse(args), ArgError.ARGUMENT_VALUE); + test::@error(agp.parse(args), argparse::ARGUMENT_VALUE); } fn void test_custom_type_callback_bool() { bool val = false; - ArgParseCallbackFn cbf = fn void! (ArgOpt* opt, String value) { + ArgParseCallbackFn cbf = fn void? (ArgOpt* opt, String value) { test::eq(value, "1"); if (value == "1") { *anycast(opt.value, bool)! = true; @@ -987,7 +987,7 @@ fn void test_custom_type_callback_bool_unset() { bool val = true; - ArgParseCallbackFn cbf = fn void! (ArgOpt* opt, String value) { + ArgParseCallbackFn cbf = fn void? (ArgOpt* opt, String value) { test::eq(value, "0"); if (value == "1") { *anycast(opt.value, bool)! = true; @@ -1029,7 +1029,7 @@ fn void test_bool_flag_unset_no_short() test::eq(val, true); test::eq(agp.options[0]._is_present, false); - test::@error(agp.parse(args), ArgError.INVALID_ARGUMENT); + test::@error(agp.parse(args), argparse::INVALID_ARGUMENT); } fn void test_bool_flag_unset_has_arg() @@ -1089,8 +1089,8 @@ fn void test_short_arguments() fn void test_custom_type_callback_int_array() { - List() numbers; - numbers.new_init(); + List{int} numbers; + numbers.init(mem); defer numbers.free(); argparse::ArgParse agp = { @@ -1100,9 +1100,9 @@ fn void test_custom_type_callback_int_array() .long_name = "num", .value = &numbers, .allow_many = true, - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { io::printfn("value: %s", value); - List() * ctx = anycast(opt.value, List())!; + List{int} * ctx = anycast(opt.value, List{int})!; int val = value.to_integer(int)!; ctx.push(val); } @@ -1127,8 +1127,8 @@ fn void test_custom_type_callback_int_array() fn void test_custom_type_callback_without_allowing_many() { - List() numbers; - numbers.new_init(); + List{int} numbers; + numbers.init(mem); defer numbers.free(); argparse::ArgParse agp = { @@ -1137,9 +1137,9 @@ fn void test_custom_type_callback_without_allowing_many() .short_name = 'n', .long_name = "num", .value = &numbers, - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { io::printfn("value: %s", value); - List() * ctx = anycast(opt.value, List())!; + List{int} * ctx = anycast(opt.value, List{int})!; int val = value.to_integer(int)!; ctx.push(val); } @@ -1151,14 +1151,14 @@ fn void test_custom_type_callback_without_allowing_many() test::eq(numbers.len(), 0); test::eq(agp.options[0]._is_present, false); - test::@error(agp.parse(args), ArgError.INVALID_ARGUMENT); + test::@error(agp.parse(args), argparse::INVALID_ARGUMENT); } fn void test_argparse_next_no_args() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); argparse::ArgParse agp; @@ -1177,8 +1177,8 @@ fn void test_argparse_next_no_args() fn void test_argparse_next_short_arg() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); argparse::ArgParse agp; @@ -1198,8 +1198,8 @@ fn void test_argparse_next_short_arg() fn void test_argparse_next_short_and_long_arg() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); argparse::ArgParse agp; @@ -1221,8 +1221,8 @@ fn void test_argparse_next_short_and_long_arg() fn void test_argparse_next_short_and_long_arg_eq() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); argparse::ArgParse agp; @@ -1246,7 +1246,7 @@ fn void test_argparse_next_empty_value() argparse::ArgParse agp; String[] argv = { "testprog", ""}; - test::@error(agp.next(argv), ArgError.INVALID_ARGUMENT); + test::@error(agp.next(argv), argparse::INVALID_ARGUMENT); } fn void test_argparse_next__empty_eq() @@ -1254,14 +1254,14 @@ fn void test_argparse_next__empty_eq() argparse::ArgParse agp; String[] argv = { "testprog", "--fofo="}; - test::@error(agp.next(argv), ArgError.INVALID_ARGUMENT); + test::@error(agp.next(argv), argparse::INVALID_ARGUMENT); } fn void test_argparse_next_all_together() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); @@ -1288,8 +1288,8 @@ fn void test_argparse_next_all_together() fn void test_argparse_next_usage() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); @@ -1321,8 +1321,8 @@ fn void test_argparse_next_usage() fn void test_argparse_next_switch() { - List() args; - args.new_init(); + List{String} args; + args.init(mem); defer args.free(); ArgParse agp = { @@ -1400,7 +1400,7 @@ fn void test_number_accumulator_with_callback() .long_name = "num", .value = &accum, .allow_many = true, - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { io::printfn("value: %s", value); int * val = anycast(opt.value, int)!; if (!opt._is_present) { diff --git a/test/c3lib/test_codegen.c3 b/test/c3lib/test_codegen.c3 index e929bc2..694d927 100644 --- a/test/c3lib/test_codegen.c3 +++ b/test/c3lib/test_codegen.c3 @@ -4,7 +4,7 @@ import std::io; fn void test_codegen_module() { - CodeGen* c = CodeGen {}.new_init(); + CodeGen* c = (CodeGen){}.init(); defer c.free(); c.@module("myfoo @if(%d)", c.indent); diff --git a/test/c3tools/ast/test_ast.c3 b/test/c3tools/ast/test_ast.c3 index 42af348..847e8f1 100644 --- a/test/c3tools/ast/test_ast.c3 +++ b/test/c3tools/ast/test_ast.c3 @@ -15,7 +15,7 @@ fn void test_node() { return 1; } `; - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); String path = "foo.c3"; Ast ast = ast::parse(contents.str_view(), path, print_lex: true); @@ -54,7 +54,7 @@ fn void test_node() { fn void test_module_no_attr() { String code = `module test::std::c3lang::ast;`; - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); String path = "foo.c3"; Ast ast = ast::parse(contents.str_view(), path); @@ -75,7 +75,7 @@ fn void test_module_imports() module test::std::c3lang::ast; // new module `; - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); String path = "foo.c3"; Ast ast = ast::parse(contents.str_view(), path); @@ -191,7 +191,7 @@ fn void test_node() { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -220,11 +220,11 @@ fn void test_node() { fn void test_func_generic_ret_type() { String code = `module test::std::c3lang::ast; -fn List() test_node() { +fn List{int} test_node() { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -238,7 +238,7 @@ fn List() test_node() { test::eq(func.type, TokenType.FN); test::eq(ast.@node_join(func.name, contents), "test_node"); - test::eq(ast.@node_join(func.ftype, contents), "List,(<,int,>)"); + test::eq(ast.@node_join(func.ftype, contents), "List,{,int,}"); test::eq(func.params, null); io::printf("\n\n``%s``", code[func.istart .. math::min((isz)func.iend, (isz)(code.len - 1))]); @@ -254,7 +254,7 @@ fn int[<2>] test_node() { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -284,7 +284,7 @@ fn MyType* test_node() { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -310,11 +310,11 @@ fn MyType* test_node() { fn void test_func_params() { String code = `module test::std::c3lang::ast; -fn void test_node(int a, List() b) @test @inline @if(env::LIBC) { +fn void test_node(int a, List{int} b) @test @inline @if(env::LIBC) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -342,7 +342,7 @@ fn void test_node(int a, List() b) @test @inline @if(env::LIBC) { param = (AstCallableParam*)ast.@node_at(func.params, 1); test::eq(param.type, TokenType.VAR); test::eq(param.value, "b"); - test::eq(ast.@node_join(param.param_type, contents), "List,(<,int,>)"); + test::eq(ast.@node_join(param.param_type, contents), "List,{,int,}"); test::ne(func.attributes, null); test::eq(ast.@node_len(func.attributes), 3); @@ -361,7 +361,7 @@ fn void test_import() import test::std::c3lang::ast::foo @test @if(env::FOO) ; import single_mod; `; - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); String path = "foo.c3"; Ast ast = ast::parse(contents.str_view(), path); @@ -396,7 +396,7 @@ fn void test_docstring_module() <* My module *> module test::std::c3lang::ast; `; - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); String path = "foo.c3"; Ast ast = ast::parse(contents.str_view(), path, true); @@ -427,7 +427,7 @@ fn void test_node() { return 1; } `; - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); String path = "foo.c3"; Ast ast = ast::parse(contents.str_view(), path, true); @@ -457,12 +457,12 @@ My module @test @param [&inout] foo "some info" @return "some stuff" -@return! Fault.SOME,IoError.ANOTHER +@return? Fault.SOME,IoError.ANOTHER @requre a > 0, a < d *> module test::std::c3lang::ast; `; - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); String path = "foo.c3"; Ast ast = ast::parse(contents.str_view(), path, true); @@ -504,7 +504,7 @@ module test::std::c3lang::ast; contract = ast.@node_at(m.docs.contracts, 4); test::eq(contract.value, "@return"); test::eq(contract.type, TokenType.AT_IDENT); - test::eq(ast.@node_join(contract.items, contents), `!,Fault,.,SOME,,,IoError,.,ANOTHER`); + test::eq(ast.@node_join(contract.items, contents), `?,Fault,.,SOME,,,IoError,.,ANOTHER`); contract = ast.@node_at(m.docs.contracts, 5); test::eq(contract.value, "@requre"); @@ -520,7 +520,7 @@ fn void test_node(int a, int b = 2) @test @inline @if(env::LIBC) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -567,7 +567,7 @@ fn MyType* MyFoo.test_node(&self) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -602,9 +602,9 @@ fn MyType* MyFoo.test_node(&self) { fn void test_one_linefunc() { String code = `module test::std::c3lang::ast; -fn char! String.to_uchar(s, int base = 10) @inline @test => s.@to_integer(char, base) @foo; +fn char? String.to_uchar(s, int base = 10) @inline @test => s.@to_integer(char, base) @foo; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -617,7 +617,7 @@ fn char! String.to_uchar(s, int base = 10) @inline @test => s.@to_integer(char, test::ne(func, null); test::eq(func.type, TokenType.FN); - test::eq(ast.@node_join(func.ftype, contents), "char,!"); + test::eq(ast.@node_join(func.ftype, contents), "char,?"); test::eq(ast.@node_join(func.name, contents), "String,to_uchar"); test::eq(ast.@node_join(func.attributes, contents), "@inline,@test"); test::ne(func.params, null); @@ -649,7 +649,7 @@ macro MyFoo.@test_macro(self) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -683,11 +683,11 @@ macro MyFoo.@test_macro(self) { fn void test_macro_type_with_ret_type() { String code = `module test::std::c3lang::ast; -macro MyType(<$it>) MyFoo.@test_macro(self) { +macro MyType{$it} MyFoo.@test_macro(self) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -700,7 +700,7 @@ macro MyType(<$it>) MyFoo.@test_macro(self) { test::ne(func, null); test::eq(func.type, TokenType.MACRO); - test::eq(ast.@node_join(func.ftype, contents), "MyType,(<,$it,>)"); + test::eq(ast.@node_join(func.ftype, contents), "MyType,{,$it,}"); test::eq(ast.@node_join(func.name, contents), "MyFoo,@test_macro"); test::eq(ast.@node_len(func.params), 1); @@ -725,7 +725,7 @@ macro @test_macro(self) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -764,7 +764,7 @@ macro @test_macro(Type* #self, $bar) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -808,7 +808,7 @@ macro @test_macro(double... a, ...args) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -852,7 +852,7 @@ macro @test_macro(Type* #self @unused, $bar @export("foo") @ok) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -901,7 +901,7 @@ macro @for_each(list; @body(it)) @body(x); } }//`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -949,7 +949,7 @@ enum Foo { FOO = SOME_OTHER_CONST, } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -996,7 +996,7 @@ enum Foo : int { FOO = SOME_OTHER_CONST, } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1043,7 +1043,7 @@ enum Foo : int (String desc, bool active, Position pos) @test @if(env:FOO) { FOO = SOME_OTHER_CONST, } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1082,17 +1082,17 @@ enum Foo : int (String desc, bool active, Position pos) @test @if(env:FOO) { test::eq(enum_type.iend, code.len - 4); } -fn void test_fault_type() +fn void test_faultdef_parser() { String code = `module test::std::c3lang::ast; -fault SomeFault @local @if(env::FOO) -{ +faultdef A, - RUNNING = { OtherEnum.FAILING, true, {12,22} }, - FOO = SOME_OTHER_CONST, -} + RUNNING, + FOO + @local @if(env::FOO) + ; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1101,35 +1101,34 @@ fault SomeFault @local @if(env::FOO) AstModule* m = ast.@node_at(ast.modules, 0); test::ne(m, null); - AstTypeDefEnumerable* enum_type = (AstTypeDefEnumerable*)ast.@node_at(m.decls, 0); - test::ne(enum_type, null); + AstTypeDefEnumerable* fault_type = (AstTypeDefEnumerable*)ast.@node_at(m.decls, 0); + test::ne(fault_type, null); - test::eq(enum_type.type, TokenType.FAULT); - test::eq(enum_type.value, "SomeFault"); + test::eq(fault_type.type, TokenType.FAULTDEF); - test::eq(ast.@node_join(enum_type.attributes, contents), "@local,@if(env::FOO)"); + test::eq(ast.@node_join(fault_type.attributes, contents), "@local,@if(env::FOO)"); - test::eq(ast.@node_len(enum_type.values), 3); + test::eq(ast.@node_len(fault_type.values), 3); AstNode* eval; - eval = ast.@node_at(enum_type.values, 0); + eval = ast.@node_at(fault_type.values, 0); test::eq(eval.type, TokenType.CONST_IDENT); test::eq(eval.value, "A"); - eval = ast.@node_at(enum_type.values, 1); + eval = ast.@node_at(fault_type.values, 1); test::eq(eval.type, TokenType.CONST_IDENT); test::eq(eval.value, "RUNNING"); - eval = ast.@node_at(enum_type.values, 2); + eval = ast.@node_at(fault_type.values, 2); test::eq(eval.type, TokenType.CONST_IDENT); test::eq(eval.value, "FOO"); io::printf( - "\n\n``%s``", code[enum_type.istart .. math::min((isz)enum_type.iend, (isz)(code.len - 1))] + "\n\n``%s``", code[fault_type.istart .. math::min((isz)fault_type.iend, (isz)(code.len - 1))] ); - test::eq(enum_type.istart, 31); - test::eq(code[enum_type.iend], '}'); - test::eq(enum_type.iend, code.len - 4); + test::eq(fault_type.istart, 31); + test::eq(code[fault_type.iend], ';'); + test::eq(fault_type.iend, code.len - 4); } fn void test_interface_type() @@ -1137,10 +1136,10 @@ fn void test_interface_type() String code = `module test::std::c3lang::ast; interface NodeI @local { fn bool foo(Ast* ast, AstNode* node, Token* t) @local; - fn List() bar() @local; + fn List{int} bar() @local; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1189,7 +1188,7 @@ interface NodeI @local { test::ne(func, null); test::eq(func.type, TokenType.FN); - test::eq(ast.@node_join(func.ftype, contents), `List,(<,int,>)`); + test::eq(ast.@node_join(func.ftype, contents), `List,{,int,}`); test::eq(ast.@node_join(func.name, contents), "bar"); test::eq(ast.@node_join(func.attributes, contents), "@local"); @@ -1213,10 +1212,10 @@ interface NodeI @local { *> fn bool foo(Ast* ast, AstNode* node, Token* t) @local; <* another doc string *> - fn List() bar() @local; + fn List{int} bar() @local; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1266,7 +1265,7 @@ interface NodeI @local { test::ne(func, null); test::eq(func.type, TokenType.FN); - test::eq(ast.@node_join(func.ftype, contents), `List,(<,int,>)`); + test::eq(ast.@node_join(func.ftype, contents), `List,{,int,}`); test::eq(ast.@node_join(func.name, contents), "bar"); test::eq(ast.@node_join(func.attributes, contents), "@local"); test::eq(ast.@node_join(func.docs, contents), "<* another doc string "); @@ -1290,7 +1289,7 @@ struct MyStruct @local { MyType b @test; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1345,10 +1344,10 @@ struct MyStruct @local { <* some stuff *> int a; <* another doc *> - List() b; + List{MyType} b; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1382,7 +1381,7 @@ struct MyStruct @local { test::ne(member, null); test::eq(member.type, TokenType.TYPE_IDENT); test::eq(member.value, "b"); - test::eq(ast.@node_join(member.ftype, contents), "List,(<,MyType,>)"); + test::eq(ast.@node_join(member.ftype, contents), "List,{,MyType,}"); test::eq(ast.@node_join(member.attributes, contents), ""); test::eq(ast.@node_join(member.docs, contents), "<* another doc "); @@ -1407,7 +1406,7 @@ struct MyStruct @local { int b @test; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1477,7 +1476,7 @@ struct MyStruct @local { int b @test; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1545,7 +1544,7 @@ struct MyStruct @local { int b @test; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1645,7 +1644,7 @@ struct MyStruct @local { int b @test; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1704,11 +1703,11 @@ fn void test_struct_inline() String code = `module test::std::c3lang::ast; struct MyStruct @local { <*inline doc*> - inline List() base @test; + inline List{int} base @test; int b @test; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1735,7 +1734,7 @@ struct MyStruct @local { test::ne(member, null); test::eq(member.type, TokenType.INLINE); test::eq(member.value, "base"); - test::eq(ast.@node_join(member.ftype, contents), `List,(<,int,>)`); + test::eq(ast.@node_join(member.ftype, contents), `List,{,int,}`); test::eq(ast.@node_join(member.attributes, contents), "@test"); test::eq(ast.@node_join(member.docs, contents), `<*inline doc`); @@ -1770,7 +1769,7 @@ union MyUnion @local { int b @test; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1831,7 +1830,7 @@ struct MyUnion @local { } } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1889,7 +1888,7 @@ bitstruct MyBit @local : char bool c : 7; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1948,7 +1947,7 @@ struct MyBit { } } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -1988,13 +1987,13 @@ struct MyBit { test::eq(struct_type.iend, code.len - 4); } -fn void test_def() +fn void test_alias() { String code = `module test::std::c3lang::ast; -<*def doc*> -def Int32 = int; +<*alias doc*> +alias Int32 = int; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2006,29 +2005,29 @@ def Int32 = int; AstTypeDefStructural* struct_type = (AstTypeDefStructural*)ast.@node_at(m.decls, 0); test::ne(struct_type, null); - test::eq(struct_type.type, TokenType.DEF); + test::eq(struct_type.type, TokenType.ALIAS); test::eq(struct_type.value, "Int32"); test::eq(ast.@node_join(struct_type.attributes, contents), ""); - test::eq(ast.@node_join(struct_type.docs, contents), "<*def doc"); + test::eq(ast.@node_join(struct_type.docs, contents), "<*alias doc"); test::eq(ast.@node_join(struct_type.ftype, contents), "int"); io::printf( "\n\n``%s``", code[struct_type.istart .. math::min((isz)struct_type.iend, (isz)(code.len - 1))] ); - test::eq(struct_type.istart, 43); + test::eq(struct_type.istart, 45); test::eq(code[struct_type.iend], ';'); test::eq(struct_type.iend, code.len - 4); } -fn void test_def_const() +fn void test_alias_const() { String code = `module test::std::c3lang::ast; -<*def doc*> -def MY_CONST = int; +<*alias doc*> +alias MY_CONST = int; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2040,29 +2039,29 @@ def MY_CONST = int; AstTypeDefStructural* struct_type = (AstTypeDefStructural*)ast.@node_at(m.decls, 0); test::ne(struct_type, null); - test::eq(struct_type.type, TokenType.DEF); + test::eq(struct_type.type, TokenType.ALIAS); test::eq(struct_type.value, "MY_CONST"); test::eq(ast.@node_join(struct_type.attributes, contents), ""); - test::eq(ast.@node_join(struct_type.docs, contents), "<*def doc"); + test::eq(ast.@node_join(struct_type.docs, contents), "<*alias doc"); test::eq(ast.@node_join(struct_type.ftype, contents), "int"); io::printf( "\n\n``%s``", code[struct_type.istart .. math::min((isz)struct_type.iend, (isz)(code.len - 1))] ); - test::eq(struct_type.istart, 43); + test::eq(struct_type.istart, 45); test::eq(code[struct_type.iend], ';'); test::eq(struct_type.iend, code.len - 4); } -fn void test_def_attr_type() +fn void test_alias_attr_type() { String code = `module test::std::c3lang::ast; -<*def doc*> -def @Int32 = { @foo @bar }; +<*alias doc*> +alias @Int32 = { @foo @bar }; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2074,29 +2073,29 @@ def @Int32 = { @foo @bar }; AstTypeDefStructural* struct_type = (AstTypeDefStructural*)ast.@node_at(m.decls, 0); test::ne(struct_type, null); - test::eq(struct_type.type, TokenType.DEF); + test::eq(struct_type.type, TokenType.ALIAS); test::eq(struct_type.value, "@Int32"); test::eq(ast.@node_join(struct_type.attributes, contents), ""); - test::eq(ast.@node_join(struct_type.docs, contents), "<*def doc"); + test::eq(ast.@node_join(struct_type.docs, contents), "<*alias doc"); test::eq(ast.@node_join(struct_type.ftype, contents), "{,@foo,@bar,}"); io::printf( "\n\n``%s``", code[struct_type.istart .. math::min((isz)struct_type.iend, (isz)(code.len - 1))] ); - test::eq(struct_type.istart, 43); + test::eq(struct_type.istart, 45); test::eq(code[struct_type.iend], ';'); test::eq(struct_type.iend, code.len - 4); } -fn void test_def_inline_list() +fn void test_alias_inline_list() { String code = `module test::std::c3lang::ast; -<*def doc*> -def IntList32 @test @foo = inline List(); +<*alias doc*> +alias IntList32 @test @foo = inline List{int}; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2108,30 +2107,30 @@ def IntList32 @test @foo = inline List(); AstTypeDefStructural* struct_type = (AstTypeDefStructural*)ast.@node_at(m.decls, 0); test::ne(struct_type, null); - test::eq(struct_type.type, TokenType.DEF); + test::eq(struct_type.type, TokenType.ALIAS); test::eq(struct_type.value, "IntList32"); test::eq(ast.@node_join(struct_type.attributes, contents), "@test,@foo"); - test::eq(ast.@node_join(struct_type.docs, contents), "<*def doc"); + test::eq(ast.@node_join(struct_type.docs, contents), "<*alias doc"); // NOTE: inline expected to be excluded from type fields - test::eq(ast.@node_join(struct_type.ftype, contents), "List,(<,int,>)"); + test::eq(ast.@node_join(struct_type.ftype, contents), "List,{,int,}"); io::printf( "\n\n``%s``", code[struct_type.istart .. math::min((isz)struct_type.iend, (isz)(code.len - 1))] ); - test::eq(struct_type.istart, 43); + test::eq(struct_type.istart, 45); test::eq(code[struct_type.iend], ';'); test::eq(struct_type.iend, code.len - 4); } -fn void test_distinct() +fn void test_typedef() { String code = `module test::std::c3lang::ast; -<*def doc*> -distinct Int32 = int; +<*typedef doc*> +typedef Int32 = int; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2143,18 +2142,18 @@ distinct Int32 = int; AstTypeDefStructural* struct_type = (AstTypeDefStructural*)ast.@node_at(m.decls, 0); test::ne(struct_type, null); - test::eq(struct_type.type, TokenType.DISTINCT); + test::eq(struct_type.type, TokenType.TYPEDEF); test::eq(struct_type.value, "Int32"); test::eq(ast.@node_join(struct_type.attributes, contents), ""); - test::eq(ast.@node_join(struct_type.docs, contents), "<*def doc"); + test::eq(ast.@node_join(struct_type.docs, contents), "<*typedef doc"); test::eq(ast.@node_join(struct_type.ftype, contents), "int"); io::printf( "\n\n``%s``", code[struct_type.istart .. math::min((isz)struct_type.iend, (isz)(code.len - 1))] ); - test::eq(struct_type.istart, 43); + test::eq(struct_type.istart, 47); test::eq(code[struct_type.iend], ';'); test::eq(struct_type.iend, code.len - 4); } @@ -2165,7 +2164,7 @@ fn void test_constant() <*def doc*> const Int32 A_FOO_BAR = 123; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2193,13 +2192,13 @@ const Int32 A_FOO_BAR = 123; test::eq(struct_type.iend, code.len - 4); } -fn void test_def_fn_pointer() +fn void test_alias_fn_pointer() { String code = `module test::std::c3lang::ast; -<*def doc*> -def NodeParser = fn bool (Ast* ast, AstNode* node, Token* t, NodeParserState* state); +<*alias doc*> +alias NodeParser = fn bool (Ast* ast, AstNode* node, Token* t, NodeParserState* state); //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2211,11 +2210,11 @@ def NodeParser = fn bool (Ast* ast, AstNode* node, Token* t, NodeParserState* st AstTypeDefStructural* struct_type = (AstTypeDefStructural*)ast.@node_at(m.decls, 0); test::ne(struct_type, null); - test::eq(struct_type.type, TokenType.DEF); + test::eq(struct_type.type, TokenType.ALIAS); test::eq(struct_type.value, "NodeParser"); test::eq(ast.@node_join(struct_type.attributes, contents), ""); - test::eq(ast.@node_join(struct_type.docs, contents), "<*def doc"); + test::eq(ast.@node_join(struct_type.docs, contents), "<*alias doc"); test::eq( ast.@node_join(struct_type.ftype, contents), "fn,bool,(,Ast,*,ast,,,AstNode,*,node,,,Token,*,t,,,NodeParserState,*,state,)" @@ -2225,7 +2224,7 @@ def NodeParser = fn bool (Ast* ast, AstNode* node, Token* t, NodeParserState* st "\n\n``%s``", code[struct_type.istart .. math::min((isz)struct_type.iend, (isz)(code.len - 1))] ); - test::eq(struct_type.istart, 43); + test::eq(struct_type.istart, 45); test::eq(code[struct_type.iend], ';'); test::eq(struct_type.iend, code.len - 4); } @@ -2237,7 +2236,7 @@ fn void test_module_imports_comma_sep() import std::io @test, test::math @foo; `; - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); String path = "foo.c3"; Ast ast = ast::parse(contents.str_view(), path, true); @@ -2283,7 +2282,7 @@ macro fetch_add(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $volatil return $$atomic_fetch_add(ptr, y, $volatile, $ordering.ordinal, $alignment); } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2320,7 +2319,7 @@ macro MyType.fetch_add(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $ return $$atomic_fetch_add(ptr, y, $volatile, $ordering.ordinal, $alignment); } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2357,7 +2356,7 @@ fn MyType* MyFoo.test_node(&self) { return 1; } //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2395,7 +2394,7 @@ fn void test_module_variable() <*def doc*> int global_int @local @bar("foo") = 2; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2429,7 +2428,7 @@ fn void test_module_variable_tlocal() <*def doc*> tlocal int global_int @local @bar("foo") = 2; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2463,7 +2462,7 @@ fn void test_module_variable_custom_type() <*def doc*> MyType global_int @local @bar("foo"); //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2497,7 +2496,7 @@ fn void test_module_variable_array() <*def doc*> char[10] global_int @local @bar("foo"); //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2529,9 +2528,9 @@ fn void test_module_variable_generic() { String code = `module test::std::c3lang::ast; <*def doc*> -List() global_int @local @bar("foo"); +List{MyType} global_int @local @bar("foo"); //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2548,7 +2547,7 @@ List() global_int @local @bar("foo"); test::eq(ast.@node_join(var_type.attributes, contents), `@local,@bar("foo")`); test::eq(ast.@node_join(var_type.docs, contents), "<*def doc"); - test::eq(ast.@node_join(var_type.ftype, contents), "List,(<,MyType,>)"); + test::eq(ast.@node_join(var_type.ftype, contents), "List,{,MyType,}"); io::printf( "\n\n``%s``", @@ -2576,7 +2575,7 @@ fn void test5(int a) => a * 2; fn void test6(int a) => a * 2; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: true); defer mem::free(ast._allocator); contents.clear(); @@ -2585,11 +2584,11 @@ fn void test6(int a) => a * 2; test::eq(3, ast.@node_len(ast.modules)); AstModule* m = ast.@node_at(ast.modules, 0); - test::eq(m.hash, (Fnv32a)fnv32a::encode("test::std::c3lang::ast")); + test::eq(m.hash, (Fnv32a)fnv32a::hash("test::std::c3lang::ast")); m = ast.@node_at(ast.modules, 1); - test::eq(m.hash, (Fnv32a)fnv32a::encode("test::std::c3lang::best")); + test::eq(m.hash, (Fnv32a)fnv32a::hash("test::std::c3lang::best")); m = ast.@node_at(ast.modules, 2); - test::eq(m.hash, (Fnv32a)fnv32a::encode("test::std::c3lang::cest")); + test::eq(m.hash, (Fnv32a)fnv32a::hash("test::std::c3lang::cest")); } diff --git a/test/c3tools/ast/test_lexer.c3 b/test/c3tools/ast/test_lexer.c3 index 44b9a36..e2ec753 100644 --- a/test/c3tools/ast/test_lexer.c3 +++ b/test/c3tools/ast/test_lexer.c3 @@ -26,7 +26,7 @@ fn void test_simple_module() String contents = `module foo;`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -62,7 +62,7 @@ fn void test_simple_module() fn void test_all_available_tokens() { - DString s = dstring::temp_new(); + DString s = dstring::temp(); foreach (ttype : TokenType.values) { s.clear(); String token_value = lexer::token_type_to_string(ttype); @@ -156,7 +156,7 @@ fn void test_all_available_tokens() test::eq(source.len, 8 + token_value.len); Lexer lexer; lexer::init(&lexer, s.str_view()); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); test::@check(4 == toks.len(), "\n%s", toks); @@ -202,7 +202,7 @@ fn void test_simple_comments_at_start_of_file() Lexer lexer; lexer::init(&lexer, contents); // breakpoint(); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -222,7 +222,7 @@ fn void test_simple_comments_after_ident() Lexer lexer; lexer::init(&lexer, contents); // breakpoint(); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); test::eq(3, toks.len()); @@ -242,7 +242,7 @@ fn void test_simple_comments_with_new_line() String contents = "module // foo;\n"; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -264,7 +264,7 @@ fn void test_simple_comments_with_new_line_prefix() String contents = "module \n \t // foo;"; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -283,7 +283,7 @@ fn void test_simple_comments_with_new_line_prefix_inline() String contents = " \t // foo;\n"; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -300,7 +300,7 @@ fn void test_string_no_escape_codes() String contents = `module "\n";`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -320,7 +320,7 @@ fn void test_multiline_comment() String contents = `module /* asda`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -339,7 +339,7 @@ fn void test_multiline_comment_at_start() String contents = "/* asda */\n"; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -356,7 +356,7 @@ fn void test_multiline_comment_with_end() String contents = `module /* asda */`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -375,7 +375,7 @@ fn void test_multiline_comment_with_nesting() String contents = "module /* asda /* with /* another */ */ */\n"; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -394,7 +394,7 @@ fn void test_multiline_comment_multiline_end() String contents = "module \n \t /* foo \n asda */\n"; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -413,7 +413,7 @@ fn void test_simple_module_multiline() String contents = "module \n \t foo;"; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -458,7 +458,7 @@ Some text `; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -533,7 +533,7 @@ fn void test_simple_docstring_inline() String contents = `<*some text*>`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -556,7 +556,7 @@ fn void test_simple_docstring_compound_statement() `; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -604,7 +604,7 @@ fn void test_base64_bytes() String contents = `module b64"SGVsbG8gV29ybGQh";`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -638,7 +638,7 @@ fn void test_base64_bytes_long() String contents = `b64"cW9pZgAAAVQAAACpBABV/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/cl/Jv39/f392jXBJv39/f392TXBJv39/f392TXBJv39/f392TXBJv39/f392TXBJv39/f392TXBJv39/f392DXBJv39/f392TXBJv39/f392TXBJv39/f392TXBJv39/f392TXBJu81Jv39zzXAJv390jXBJu01wyb9/cg1xib9/dA1wibsNcQm/f3GNcgm0zXAJv33NcEm6zXHJv39wzXIJtQ1xCb99DXBJus1wibANcEm/f3BNcgm1TXHJv3yNcEm6jXCJsE1wSb9/cA1xibZNSbANcQm/fE1wSbpNcImwjXBJv39NcUm4DXCJv3xNcEm6DXCJsM1wSb9/TXEJuI1wib98DXBJuc1wibENcEm/fw1wyblNcIm/e41wibmNcImxTXBJv37NcMm5zXBJv3uNcIm5jXCJsU1wSb9+jXEJuc1wib97TXCJuU1wibGNcEm/fk1xCboNcIm/e01wSbmNcImxjXBJv35NcMm6DXCJv3uNcEm5jXBJsc1wSb9+DXDJuk1wib97jXBJuU1wibGNcIm/fg1wyboNcIm/e81wSblNcEmxzXBJv34NcMm6TXCJv3vNcEm5TXBJsc1wSb9+DXCJuk1wib98DXBJuQ1wibHNcEm/fc1wyboNcMm/fA1wSbkNcEmxzXCJv33NcMm5jXEJv3xNcEm5DXBJsc1wSb9+DXCJuY1xSb98TXBJuM1wibGNcIm/fc1wybmNcQm/fI1wSbjNcEmxjXCJv34NcIm5zXGJv3wNcEm4zXBJsU1wyb9+DXCJug1xib97jXCJuI1wibENcMm/fk1wibrNcQm/e01wibiNcImwjXDJv37NcIm7DXEJv3sNcEm4zXBJsE1xCb9wDUm+TXCJu41wyb96zXBJuM1wSY1xSbKNcUm6jXDJvc1wibvNcMm/eo1wSbjNccmyzXIJuY1xSb3NcIm7zXEJv3pNcEm4jXGJsw1yibLNcUm0DXGJvc1wibwNcMm/ek1wSbiNcQmzTXLJsk1xybDNcImxjXHJvc1wibxNcIm/ek1wSbhNcMmzzXDJsA1xSbGNcomwjXDJsQ1ySb2NcIm8TXCJv3pNcEm4TXCJs81wibCNcUmxDXLJsI1xSbCNcQmNcIm9zXDJvA1wib96DXCJuI1wSbONcMmwzXEJsM1xibANcImwjXGJsA1xCY1wyb4NcIm7zXDJv3oNcIm4jXBJs41wibENcQmwTXGJsE1wybCNccmNcMmNcMm+TXCJtA1wibZNcIm/ek1wSbjNcEmzjXBJsU1wybANcYmwzXCJsI11Cb5NcMmzTXDJtk1wyb96TXBJuM1wSbNNcImxTXMJsM1wybCNcImwDXNJvs1wibMNcMm2TXDJv3qNcEm4zXBJs01wibFNcsmxDXDJsE1wybBNcsm/DXDJsk1xCbZNcQm/eo1wSbjNcEmzDXCJsc1yCbGNcImwjXCJsM1yCb9wDXEJsY1xCbaNcQm/es1wSbjNcEmyzXDJsY1xibJNcImwTXDJsQ1wib9xjXQJto1xCb97DXBJuM1wSbKNcQmxjXCJs01wibANcMmxTXCJv3HNc4m2jXEJv3tNcEm4zXBJsk1xibENcImzjXCJsA1wybENcMm/cg1yybbNcQm/e41wSbjNcImxzXCJjXCJsQ1wibNNcMmNcMmxTXDJv3JNcgm3DXEJv3vNcEm5DXBJsQ1xCbANcwmzTXIJsY1wyb98DXEJtg1wCb91DXBJuQ1wyY1xibCNcomzjXIJsc1wib96DXBJsE1xSbWNcAm/dc1wSblNckmxTXIJs81xybINcImzTXBJv3VNcMmNcUm1TXAJv3ZNcEm5jXHJsg1wibTNcYmyTXDJss1wSb91TXLJtQ1wCb92zXBJug1wSblNcYmyTXDJsk1wyb91TXJJtM1wCb93jXBJv3UNcQmzDXEJsU1xCb91TXJJtI1wCb94DXBJv3UNcMmzjXGJjXGJv3WNccm0jXAJv3iNcEm/dU1wSbPNc4m/dc1xibQNcAm/eU1wSb96zXLJv3YNcQm0DXAJv3nNcIm/ew1xyb92zXBJtA1wCb96jXBJv3uNcIm/fE1wCb97DXBJv39/eU1wCb9/f39/dc1wCb9/f39/dg1wCb9/f39/dg1wCbxNcUm/f39/dw1wCbxNcgm/f39/dk1wCbxNcom/f39/dc1wCbyNcQmwjXBJv39/f3VNcAm9DXCJsQ1wSb9/f390jXBJvY1wSbENcIm/f39/dA1wSb4NcAmxTXCJv39/f3ONcEm+zUmxTXCJs01wCb9/f35NcEm/cc1wibJNcUm1QDeJv39/DXCJv3JNcImyDXGJtUA3ib9/fo1wSb9zDXCJsU1yCbWAN4m/f33NcIm/c41wibDNckm1wDeJsdv4Cb9/co1wib9zzXCJsE1ySbaAN4mxzLgJv39yDXCJv3RNc4m3ADeJscy4Cb9/cY1wib9xTXBJsk1zCbeAN4mxzLgJv39xDXCJv3ENcYmxjXKJuEAyP8AAAC7/wAAAOr/AAAA9g4JAAn/AAAA+sAJAMomxzLJ/icAAMIy0Sb9/cI1wib9xTXIJsU1xybkAMc+yP8AAAD5AMomxzLI/o0AACrDMtAm/f3BNcEm/cY1ySbFNcUm5gDGPsoAyibHMsj+UQAAKsgyyyb9/TXBJv3INcImwDXDJsU1wyboAMY+whI+xQDKJscyyCrJMssm/fs1wSb9yjXBJsE1xCbENcEm6gDGPsIADj7DDgDKJscyyCrJMssm/fg1wib9zDXBJsE1xCbzAMUJPsEJPsUAyybHMsgqwSgqwP41AADAKBwyzCb99jXCJv3ONcImwDXEJsM1Ju0AxQ4+yQDLJscyyCrBMtMm/fQ1wib90DXCJsA1xSY1wibtAMUOPsgzCQDKJscyyCrBMtMm/fI1wib9yDXEJsI1wiY1yibuAMUJPsQJEj7DAMkmxzLIKsEy0yb98DXCJuY1wibcNcUmwTXOJu8AzQ4+wwDJJscyyCrBMtMm/e41wibpNcEm2zXHJsE1xSY1xSbvAM0JPsMAySbHMsgqwTLTJv3sNcIm6zXCJto1wSbANcMmwTXEJjXEJvAA3ibHMsgqwTLTJv3qNcIm7jXCJtA1JsE1JsA1wibCNcImwjXBJsI1wibxAN4mxzLIKsEy0yb96DXCJvA1wybONcomwzXCJv3BAN4mxzLIHMEy0yb95jXCJvM1wibPNckmwzXCJv3BAN4mxzLgJvs1wSbiNcIm9jXCJs81yCbDNcIm/cEA3ibHMuAm+zXCJt81wibxNSbENcImxTXDJsI1xCbANcImwjXCJv3qMuAm/DXCJtw1wibxNcEmxTXBJsQ1xSbBNcMmwjXBJsM1wSb96jLgJvw1wibcNcIm8DXCJsU1wibCNccmwTXCJsI1wSbENSb9/f3RNcEm3DXDJu81wSbFNcImwjXCJsA1wSbCNcEmwjXCJv39/dc1wibfNcAm7jXBJsY1wSbCNcEmwTXCJsE1wSbBNcMm/f392DXBJv3TNcImxTXBJsI1wSbCNcEmwDXCJsI1wib9/f3YNcEm/dM1wibFNcImwTXBJsE1wSY1xCbCNcIm/f392DXCJv3TNcEmxTXCJsE1wSY1wyY1xCbDNcAm/f39wjUm1TXBJv01wCbQNcEmxDXDJsE1xibANcEmNcAm/f39yDXDJtI1wSb4NckmzDXCJsE1xSbBNcUmwDXBJv39/cw1xCbRNcIm9jXPJsg1wSbANccmwDXDJsE1wib9/f3lNcIm9TXTJsU1xyY1wibANcEmwzXBJv39/eY1wib1NcUmNcsmxTXGJsA1wibANcImwTXCJv3Zftwm/es1wib1NcImwTXNJsM1xibCNcEmwDXCJsA1wib92i7cJsx73Sb9NcEm9TXCJsA1xSbDNcImwzXFJsM1wSbANcgm/dou3CbMMN0m/TXBJvQ1wyY1xibDNcMmwzXCJsU1wSbBNcYm/dsu3CbMMN0m/DXCJvQ1wibANcEmNcImxDXCJsQ1wSbFNcEmwjXEJv3cLsr+AADQ/gAAjcAlLswmzDDI/gCNAMD+ACcAwjDNJvw1wib0NcImwDXBJjXCJsM1wibFNcImxDXBJsM1wSb93i7K/gAAJ8EQLswmzDDHOMUwzSb8NcIm9DXCJsA1wSbANcImwTXDJsY1wSbENcEm/eYuygbBEC7MJswwxjjIMMsm/DXCJvQ1wibANcEmwDXCJjXEJsg1wCbENcEm/eYuygbBJS7MJswwxTjENsA4wTDLJvw1wib0NcImwDXBJsA1yCbINcEmxTXAJv3mLskQBsEuzSbMMMU4wzDA/gBRADjBMMsm/DXCJvQ1wibANcImNccmyzXAJv3uLsn+AAAQ/gAAAcEGwBAuyibMMMU4wTYwwTjCMMsm/DXCJvQ1wibBNcomzDXAJv3uLsklPMCgjAbCLskmzDDFOMSkRDjCMMsm+zXCJvU1wibCNccmzzUm/e4uySU8wCUGxC7HJswwxTjJMMsm6TXAJs41wib1NcImwzXFJv39wy7IBsElBsUuxybMMMU4yTDLJug1wCbPNcIm9TXDJv39zi7IPMEYLsEGwi7HJswwyDjB/gA1ADjCMMsm5jXBJs81wib2NcMm/f3OLsg8wSUGEP4AAFEGwi7HJswwzDjBCjDLJuU1wybONcIm9zXDJss1JjXAJv36Lsg8wQbGLscmzDDGNjjANjA2OME2MMsm5TXCJs41wyb3NcQmyTXCJv37LsgGJTwGxi7HJswwxgo4wAo2OMIwzCb5NcIm+TXFJsQ1xCb9/C7KEAbEEC7IJswwxj44wG44wzDMJvg1wib7Nc8m/f0u3CbMMMYKOMU2MMwm+DXCJvw1zSb9/cAu3CbMMMY2OMQ2MM0m9zXCJv3ANcsm/f3tMMc4wzYwzib3NcIm/cM1xib9/e8w3Sb2NcIm/f39/f3XNcMm/f397f6NjY3BJv3iNcMm/f397Tj+JycnwSb93zXFJv39/dU4/lFRUT7DJtA+wib93zXEJv39/dQ4PsYmzzg+wTQm/d81wyb9/f3UPsgmzz7COCb94DXAJv39/dU+xjgmyDg0wDgmwjg+wibCOD7GJv39/f3tPsQmyD7FJsI+wjgmwT7IJs84ND7CJsU4NMA4Jv39/f3LPsImyT7GJsE0PsImwj7IJsE4PsI4JsY+xCbEPsMmxTg0hIg0OCb9/f39PsEmyj7GJsE+wjgmwj7COMA0PsEmwTQ+yCbBPsQmxD7DJsQ+xSb9/f38PsI4JsI4wSbBPsEQOD7BJsE+wTQmwz7BOD7EJsEQPsgmwT7DJsU+wTQ4JsM+xib9/f38PsomwRA+xSbAOD7BOCbDPsgmwRA+yCbBPsUmwz7CJsQ+whA+wSb9/f38PsomwTg+xSbAND7CNMA4JsA+xzgmwRA+wBAmyT7FJsI+wibEPsI4Jv39/f3BOD7IOCbCPsUmwDQ+xSbAPsUmxBA+wBAmyz7DJsI+wzgmwj7DOCb9/f390j7COCbAOD7FJsE4NMA4JsY0PsA0Jsk+xSbCOD7DJsI4PsM4Jv39/f3bPsE0OCbNOD7AOCbJPsQ4JsE+xibBPsQ4Jv39/f39wD7EJsI+xibBPsQ4Jv39/f39yj7GJsE+wzgm/f39/f3LODT+KysrPsA4JsM+wSb9/f39/f39/f3aAAAAAAAAAAE=";`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -662,7 +662,7 @@ fn void test_hex_bytes() String contents = `module x"4865 6c6c";`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -712,7 +712,7 @@ x``ffffffffffffffffffffffffffffffff ffffffffffffffaffffbffffcfffdff0``;`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -736,7 +736,7 @@ fn void test_fn_decl() String contents = `fn void ! foo(int a)`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -754,17 +754,17 @@ fn void test_fn_decl() fn void test_fn_decl_bang_is_close() { - String contents = `fn void! foo(int a)`; + String contents = `fn void? foo(int a)`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); // foreach(i, t: toks) io::printf(",%s", t.type); - TokenType[] expected = { FN, TYPE_IDENT, BANG, IDENT, LPAREN, TYPE_IDENT, IDENT, RPAREN, EOF }; + TokenType[] expected = { FN, TYPE_IDENT, QUESTION, IDENT, LPAREN, TYPE_IDENT, IDENT, RPAREN, EOF }; // module IDENT[foo] ; EOF test::eq(expected.len, toks.len()); @@ -779,7 +779,7 @@ fn void test_simple_bultin() Lexer lexer; lexer::init(&lexer, contents); // breakpoint(); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -810,7 +810,7 @@ fn void test_simple_bultin_type() Lexer lexer; lexer::init(&lexer, contents); // breakpoint(); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -841,7 +841,7 @@ fn void test_simple_bultin_const() Lexer lexer; lexer::init(&lexer, contents); // breakpoint(); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -871,7 +871,7 @@ fn void test_empty_string_token() String contents = "module \n \t \t \n;"; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -981,7 +981,7 @@ fn void test_escape_chars() String contents = `'\n'`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -998,7 +998,7 @@ fn void test_escape_chars_single_quote() String contents = `'\''`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -1014,7 +1014,7 @@ fn void test_escape_chars_double_backslash() String contents = `'\\'`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -1030,7 +1030,7 @@ fn void test_multiline_comment_with_many_stars() String contents = `module /******** asda **********/`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -1052,7 +1052,7 @@ fn void test_multiline_comment_with_many_stars_multi_line() */;`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -1079,7 +1079,7 @@ fn void test_multiline_comment_with_many_stars_multi_line_endof_line() `; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); // foreach(i, t: toks) io::printf("%d: %s", i, t); @@ -1102,7 +1102,7 @@ fn void test_whitespace_mode() Lexer lexer; lexer::init(&lexer, contents); lexer.set_whitespace_mode(true); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); foreach (i, t : toks) io::printf("%d: %s", i, t); @@ -1142,7 +1142,7 @@ fn void test_comments_with_whitespace_mode() Lexer lexer; lexer::init(&lexer, contents); lexer.set_whitespace_mode(true); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: false); foreach (i, t : toks) io::printf("%d: %s", i, t); @@ -1163,7 +1163,7 @@ fn void test_comments_multiline_with_whitespace_mode() Lexer lexer; lexer::init(&lexer, contents); lexer.set_whitespace_mode(true); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: false); foreach (i, t : toks) io::printf("%d: %s", i, t); @@ -1194,7 +1194,7 @@ Some text `; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -1250,7 +1250,7 @@ fn void test_simple_docstring_empty() `; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); @@ -1272,7 +1272,7 @@ fn void test_unicode_chars() String contents = `'謝';`; Lexer lexer; lexer::init(&lexer, contents); - List() toks = lexer.new_parse_tokens(); + List{lexer::Token} toks = lexer.new_parse_tokens(); defer toks.free(); // foreach(t: toks) t.print(new_line: true); diff --git a/test/c3tools/codefmt/c3fmt_corpus/casting.txt b/test/c3tools/codefmt/c3fmt_corpus/casting.txt index 963ebd4..1c97255 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/casting.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/casting.txt @@ -139,7 +139,7 @@ fn void main() void*[] bcd = (void*[])abc; int[] cde = {}; Foo[] xyz = (Foo[])cde; - Foo[] xyz2 = (Foo[])(int[]) { 1, 2 }; + Foo[] xyz2 = (Foo[])(int[]){ 1, 2 }; } -------------------------------------------------------------------------------- fn void main() @@ -148,5 +148,5 @@ fn void main() void*[] bcd = (void*[])abc; int[] cde = {}; Foo[] xyz = (Foo[])cde; - Foo[] xyz2 = (Foo[])(int[]){ 1, 2 }; + Foo[] xyz2 = (Foo[])(int[]) { 1, 2 }; } diff --git a/test/c3tools/codefmt/c3fmt_corpus/comments.txt b/test/c3tools/codefmt/c3fmt_corpus/comments.txt index 9d086e1..d0a4bca 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/comments.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/comments.txt @@ -83,17 +83,17 @@ fn void main() comments_inside_func_args ================================================================================ -fn String[]! +fn String[]? Foo.main( -String[] args, int* foo, List() /* some */ +String[] args, int* foo, List{float} /* some */ bar, na , varg... ) { return 0 ;} -------------------------------------------------------------------------------- -fn String[]! Foo.main( +fn String[]? Foo.main( String[] args, int* foo, - List() /* some */ + List{float} /* some */ bar, na, varg... @@ -105,17 +105,17 @@ fn String[]! Foo.main( comments_single_line_forces_multiline ================================================================================ -fn String[]! +fn String[]? Foo.main( // coment -List() +List{float} bar, int a ) { return 0 ;} -------------------------------------------------------------------------------- -fn String[]! Foo.main( +fn String[]? Foo.main( // coment - List() bar, + List{float} bar, int a ) { diff --git a/test/c3tools/codefmt/c3fmt_corpus/comptime.txt b/test/c3tools/codefmt/c3fmt_corpus/comptime.txt index 4b07e6b..db3b39b 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/comptime.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/comptime.txt @@ -262,7 +262,7 @@ macro @foo($x, #y) ================================================================================ ct_if_hierarchical ================================================================================ -fn Path! new_get_config_dir(Allocator allocator = allocator::heap()) +fn Path? new_get_config_dir(Allocator allocator = allocator::heap()) { @pool(allocator) { @@ -281,7 +281,7 @@ fn Path! new_get_config_dir(Allocator allocator = allocator::heap()) }; } -------------------------------------------------------------------------------- -fn Path! new_get_config_dir(Allocator allocator = allocator::heap()) +fn Path? new_get_config_dir(Allocator allocator = allocator::heap()) { @pool(allocator) { $if env::WIN32: diff --git a/test/c3tools/codefmt/c3fmt_corpus/docstrings.txt b/test/c3tools/codefmt/c3fmt_corpus/docstrings.txt index 86ac1e5..c8dce62 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/docstrings.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/docstrings.txt @@ -111,7 +111,7 @@ Descr @param @ensure ignored @require foo > 1 @return IoError.FOO, EioError.BAR -@return! IoError.FOO, EioError.BAR +@return? IoError.FOO, EioError.BAR @require $defined(resource.open, resource.open()), ``Expected resource to have an "open" function`` @require resource != nil @require $assignable(resource.open(), void*) @@ -140,7 +140,7 @@ main() { return;} @require foo > 1 @return IoError.FOO, EioError.BAR - @return! IoError.FOO, EioError.BAR + @return? IoError.FOO, EioError.BAR @require $defined(resource.open, resource.open()), ``Expected resource to have an "open" function`` @require resource != nil @require $assignable(resource.open(), void*) @@ -154,6 +154,16 @@ fn void main() return; } ================================================================================ +docstr_return_optional +================================================================================ +<* + @return ? IoError.FOO, EioError.BAR +*> +-------------------------------------------------------------------------------- +<* + @return? IoError.FOO, EioError.BAR +*> +================================================================================ docstr_double_spaces ================================================================================ <* diff --git a/test/c3tools/codefmt/c3fmt_corpus/expressions.txt b/test/c3tools/codefmt/c3fmt_corpus/expressions.txt index c822120..8b3330a 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/expressions.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/expressions.txt @@ -159,16 +159,16 @@ generic_vec_expr ================================================================================ fn void main() { -List() lfoo; -List()* lfoo = List(){}.init(bar: 1); +List{Foo*} lfoo; +List{Foo*}* lfoo = List{Foo*}{}.init(bar: 1); int[<2>]* lfoo = int[<2 >]{}.init(bar: 1); } -------------------------------------------------------------------------------- fn void main() { - List() lfoo; - List()* lfoo = List(){}.init(bar: 1); + List{Foo*} lfoo; + List{Foo*}* lfoo = List{Foo*}{}.init(bar: 1); int[<2>]* lfoo = int[<2>]{}.init(bar: 1); } ================================================================================ @@ -245,22 +245,21 @@ macro bool char_is_base64(char c) bang_expressions ================================================================================ -fn List()! foo() => 0; -fn int[<2>]! foo() => 0; +fn List{int}? foo() => 0; +fn int[<2>]? foo() => 0; -def TFoo = fn List()! foo(); -def TFoo = fn int[<3>]! foo(); -def TFoo = fn int! foo(); -def TFoo = fn int*! foo(); +alias TFoo = fn List{int}? foo(); +alias TFoo = fn int[<3>]? foo(); +alias TFoo = fn int? foo(); +alias TFoo = fn int*? foo(); -fn void! main() { - char! c = call(); - char*! c = call(); +fn void? main() { + char? c = call(); + char*? c = call(); char c = call()!; char c = !call(); - int[<2>]! c = call(); - List<[2]>! c = call(); - List(<2>)! c = call(); + int[<2>]? c = call(); + List{2}? c = call(); if(!foo()) return 0; if(!foo() && (!(foo | bar) && !foo)) return 0; return !(!foo()); @@ -268,23 +267,22 @@ fn void! main() { } -------------------------------------------------------------------------------- -fn List()! foo() => 0; -fn int[<2>]! foo() => 0; +fn List{int}? foo() => 0; +fn int[<2>]? foo() => 0; -def TFoo = fn List()! foo(); -def TFoo = fn int[<3>]! foo(); -def TFoo = fn int! foo(); -def TFoo = fn int*! foo(); +alias TFoo = fn List{int}? foo(); +alias TFoo = fn int[<3>]? foo(); +alias TFoo = fn int? foo(); +alias TFoo = fn int*? foo(); -fn void! main() +fn void? main() { - char! c = call(); - char*! c = call(); + char? c = call(); + char*? c = call(); char c = call()!; char c = !call(); - int[<2>]! c = call(); - List <[2] >! c = call(); - List(<2>)! c = call(); + int[<2>]? c = call(); + List{2}? c = call(); if (!foo()) return 0; if (!foo() && (!(foo | bar) && !foo)) return 0; return !(!foo()); @@ -416,13 +414,13 @@ fn void main() { String text = io::readline() ?? InputResult.FAILED_TO_READ?!; io::fprintf(out, "%s", s.title.get() ?? "missing", s.ok)!; - return Summary { - .title = new_string_val(doc.head.get().title.get()) ?? MaybeString {}, + return (Summary){ + .title = new_string_val(doc.head.get().title.get()) ?? (MaybeString){}, .ok = true, }; long e10 = String.to_long() ?? NumberConversion.MALFORMED_FLOAT ? !; url.path = decode(allocator) ?? UrlParsingResult.INVALID_PATH ? !; - int! b = foo((a + 3) ?? 2); + int? b = foo((a + 3) ?? 2); char* data4 = $embed("fiek") ?? null; bool r = foo ? !bar : !vrr; bool r = foo ? (!bar) : !vrr; @@ -432,13 +430,13 @@ fn void main() { String text = io::readline() ?? InputResult.FAILED_TO_READ?!; io::fprintf(out, "%s", s.title.get() ?? "missing", s.ok)!; - return Summary { - .title = new_string_val(doc.head.get().title.get()) ?? MaybeString {}, + return (Summary) { + .title = new_string_val(doc.head.get().title.get()) ?? (MaybeString) {}, .ok = true, }; long e10 = String.to_long() ?? NumberConversion.MALFORMED_FLOAT?!; url.path = decode(allocator) ?? UrlParsingResult.INVALID_PATH?!; - int! b = foo((a + 3) ?? 2); + int? b = foo((a + 3) ?? 2); char* data4 = $embed("fiek") ?? null; bool r = foo ?!bar : !vrr; bool r = foo ? (!bar) : !vrr; @@ -493,31 +491,39 @@ fn void main() -------------------------------------------------------------------------------- fn void main() { - f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, (Complex){1.0, 1.0}); - blorg((Test){}); - return (Test){}; + f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, (Complex) {1.0, 1.0}); + blorg((Test) {}); + return (Test) {}; f_va_callee( 1, 2, 3, 4.0, 5.0, - (Tiny){6, 7, 8, 9}, - (Small){10, null}, - (Small_aligned){11}, - (Large){12, 13, 14, 15} + (Tiny) {6, 7, 8, 9}, + (Small) {10, null}, + (Small_aligned) {11}, + (Large) {12, 13, 14, 15} ); - int[?][?][] x = (int[2][1][]){ { {1, 2}} }; - int z = (int)(Foo){ .abc = 2, .defg = 1 }; - Foo4* f4 = &&(Foo4){ .expand = 2, .a = true, .b = true, .widget = &f }; - io::printfn("%s", $$reduce_max((double[<2>]){23.2, 23.3})); - var $b4 = x'403322' +++ (char[2]){ 1, 2 }; - IFoo foo = @clone((Ba){}); - if (contains(url, "title-missing")) return { dupe((Head){.title = null})! }; - return buildSummary(readDoc(url)) ?? (Summary){ + int[?][?][] x = (int[2][1][]) { { {1, 2} } }; + int z = (int)(Foo) { .abc = 2, .defg = 1 }; + Foo4* f4 = &&(Foo4) { .expand = 2, .a = true, .b = true, .widget = &f }; + io::printfn("%s", $$reduce_max((double[<2>]) {23.2, 23.3})); + var $b4 = x'403322' +++ (char[2]) { 1, 2 }; + IFoo foo = @clone((Ba) {}); + if (contains(url, "title-missing")) return { dupe((Head) {.title = null})! }; + return buildSummary(readDoc(url)) ?? (Summary) { .title = null, .ok = false }; - bool x = !(int[]){ 1, 2, 3 }; - int x = $typeof((int[?]){1, 2, 3}).len; - result = mem::gather(y, (bool[<2>]){true, false}, (int[<2>]){10, 20}); + bool x = !(int[]) { 1, 2, 3 }; + int x = $typeof((int[?]) {1, 2, 3}).len; + result = mem::gather(y, (bool[<2>]) {true, false}, (int[<2>]) {10, 20}); } +================================================================================ +my_test +================================================================================ +List{2}? c = call(); +List{2}? c = call(); +-------------------------------------------------------------------------------- +List{2}? c = call(); +List{2}? c = call(); diff --git a/test/c3tools/codefmt/c3fmt_corpus/fmtoff.txt b/test/c3tools/codefmt/c3fmt_corpus/fmtoff.txt index 1c4bbeb..ea6f015 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/fmtoff.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/fmtoff.txt @@ -108,7 +108,7 @@ fn void main() ================================================================================ fmt_off_inside_struct_initializer ================================================================================ -fn void! command_compile(Config* config, ArgParse* agp) +fn void? command_compile(Config* config, ArgParse* agp) { // fmt: off ArgParse sub_args = { @@ -124,7 +124,7 @@ fn void! command_compile(Config* config, ArgParse* agp) // fmt: on } -------------------------------------------------------------------------------- -fn void! command_compile(Config* config, ArgParse* agp) +fn void? command_compile(Config* config, ArgParse* agp) { // fmt: off ArgParse sub_args = { @@ -142,7 +142,7 @@ fn void! command_compile(Config* config, ArgParse* agp) ================================================================================ fmt_off_inside_long_array ================================================================================ -fn void! command_compile(Config* config, ArgParse* agp) +fn void? command_compile(Config* config, ArgParse* agp) { // fmt: off const Base64Alphabet STANDARD = { @@ -153,7 +153,7 @@ fn void! command_compile(Config* config, ArgParse* agp) // fmt: on } -------------------------------------------------------------------------------- -fn void! command_compile(Config* config, ArgParse* agp) +fn void? command_compile(Config* config, ArgParse* agp) { // fmt: off const Base64Alphabet STANDARD = { diff --git a/test/c3tools/codefmt/c3fmt_corpus/functions.txt b/test/c3tools/codefmt/c3fmt_corpus/functions.txt index e91e19a..d38e646 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/functions.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/functions.txt @@ -28,13 +28,13 @@ fn int main(String[] args) ret_generic_list ================================================================================ -fn List() +fn List{int} main( String[] args ) { return 0 ;} -------------------------------------------------------------------------------- -fn List() main(String[] args) +fn List{int} main(String[] args) { return 0; } @@ -42,13 +42,13 @@ fn List() main(String[] args) ret_generic_list_pointer_opt ================================================================================ -fn List()*! +fn List{int}*? main( String[] args ) { return 0 ;} -------------------------------------------------------------------------------- -fn List()*! main(String[] args) +fn List{int}*? main(String[] args) { return 0; } @@ -56,13 +56,13 @@ fn List()*! main(String[] args) ret_generic_method ================================================================================ -fn List()*! +fn List{int}*? Foo.main( String[] args ) { return 0 ;} -------------------------------------------------------------------------------- -fn List()*! Foo.main(String[] args) +fn List{int}*? Foo.main(String[] args) { return 0; } @@ -70,13 +70,13 @@ fn List()*! Foo.main(String[] args) ret_generic_method_attrs ================================================================================ -fn List() * ! +fn List{int} * ? Foo.main( String[] args ) @test @if("dio" || too) { return 0 ;} -------------------------------------------------------------------------------- -fn List()*! Foo.main(String[] args) @test @if("dio" || too) +fn List{int}*? Foo.main(String[] args) @test @if("dio" || too) { return 0; } @@ -84,13 +84,13 @@ fn List()*! Foo.main(String[] args) @test @if("dio" || too) returns_array_type ================================================================================ -fn String[]! +fn String[]? Foo.main( String[] args ) { return 0 ;} -------------------------------------------------------------------------------- -fn String[]! Foo.main(String[] args) +fn String[]? Foo.main(String[] args) { return 0; } @@ -98,14 +98,14 @@ fn String[]! Foo.main(String[] args) returns_multiple_arguments ================================================================================ -fn String[]! +fn String[]? Foo.main( -String[] args, int* foo, List() +String[] args, int* foo, List{float} bar, na , varg... ) { return 0 ;} -------------------------------------------------------------------------------- -fn String[]! Foo.main(String[] args, int* foo, List() bar, na, varg...) +fn String[]? Foo.main(String[] args, int* foo, List{float} bar, na, varg...) { return 0; } @@ -113,14 +113,14 @@ fn String[]! Foo.main(String[] args, int* foo, List() bar, na, varg...) typed_vargs ================================================================================ -fn String[]! +fn String[]? Foo.main(String[] args, int ...varg ) { call(i, j, ...varg); return 0 ;} -------------------------------------------------------------------------------- -fn String[]! Foo.main(String[] args, int ...varg) +fn String[]? Foo.main(String[] args, int ...varg) { call(i, j, ...varg); return 0; @@ -129,12 +129,12 @@ fn String[]! Foo.main(String[] args, int ...varg) long_arguments ================================================================================ -fn String[]! Foo.main(String[] args, int* foo, List() bar, MySuperClass[] last +fn String[]? Foo.main(String[] args, int* foo, List{float} bar, MySuperClass[] last ) { return 0 ;} -------------------------------------------------------------------------------- -fn String[]! Foo.main( - String[] args, int* foo, List() bar, MySuperClass[] last +fn String[]? Foo.main( + String[] args, int* foo, List{float} bar, MySuperClass[] last ) { return 0; @@ -143,17 +143,17 @@ fn String[]! Foo.main( long_arguments_multiline ================================================================================ -fn String[]! Foo.main(SoTypeIsHuuuuuuge ok, String[] args, int* foo, List() bar, MySuperClass[] last, List() too_be_true +fn String[]? Foo.main(SoTypeIsHuuuuuuge ok, String[] args, int* foo, List{float} bar, MySuperClass[] last, List{ThisIsTooBig} too_be_true ) { return 0 ;} -------------------------------------------------------------------------------- -fn String[]! Foo.main( +fn String[]? Foo.main( SoTypeIsHuuuuuuge ok, String[] args, int* foo, - List() bar, + List{float} bar, MySuperClass[] last, - List() too_be_true + List{ThisIsTooBig} too_be_true ) { return 0; @@ -162,17 +162,17 @@ fn String[]! Foo.main( arguments_magic_comma ================================================================================ -fn String[]! +fn String[]? Foo.main( -String[] args, int* foo, List() +String[] args, int* foo, List{float} bar, na , ) { return 0 ;} -------------------------------------------------------------------------------- -fn String[]! Foo.main( +fn String[]? Foo.main( String[] args, int* foo, - List() bar, + List{float} bar, na, ) { @@ -267,7 +267,7 @@ fn void remove_using_test() assert(removed == 3); thread.create(fn int(void* arg) { - UnbufferedChannel() c = (UnbufferedChannel())arg; + UnbufferedChannel{int} c = (UnbufferedChannel{int})arg; c.push(123)!!; if (foo) { c.push(321)!!; } @@ -286,7 +286,7 @@ fn void remove_using_test() ); assert(removed == 3); thread.create(fn int (void* arg) { - UnbufferedChannel() c = (UnbufferedChannel())arg; + UnbufferedChannel{int} c = (UnbufferedChannel{int})arg; c.push(123)!!; if (foo) { c.push(321)!!; diff --git a/test/c3tools/codefmt/c3fmt_corpus/generics.txt b/test/c3tools/codefmt/c3fmt_corpus/generics.txt new file mode 100644 index 0000000..d041580 --- /dev/null +++ b/test/c3tools/codefmt/c3fmt_corpus/generics.txt @@ -0,0 +1,90 @@ +================================================================================ +generic_in_struct_scope +================================================================================ +struct FileWatch { + Atomic { bool}is_running ; +} +-------------------------------------------------------------------------------- +struct FileWatch +{ + Atomic{bool} is_running; +} +================================================================================ +nested_generic_in_struct_scope +================================================================================ +struct FileWatch { + List{Atomic { bool} } is_running + ; +} +-------------------------------------------------------------------------------- +struct FileWatch +{ + List{Atomic{bool}} is_running; +} +================================================================================ +nested_multi_generic_type_in_struct_scope +================================================================================ +struct FileWatch { + List{Atomic { bool}, Foo {int } } whatever + ; +} +-------------------------------------------------------------------------------- +struct FileWatch +{ + List{Atomic{bool}, Foo{int}} whatever; +} +================================================================================ +generic_in_alias +================================================================================ +alias TFoo = fn List{int} ? foo(); +alias TFoo = fn List{int} ? foo(); +-------------------------------------------------------------------------------- +alias TFoo = fn List{int}? foo(); +alias TFoo = fn List{int}? foo(); +================================================================================ +generic_fn_return +================================================================================ +fn List{int} ? foo() { + return (List{int}){1, 2, 3}; +} +-------------------------------------------------------------------------------- +fn List{int}? foo() +{ + return (List{int}) { 1, 2, 3 }; +} +================================================================================ +generic_fn_call +================================================================================ +fn List{int} ? foo() +{ + return bar{int}((List{int}){1, 2, 3}); +} +-------------------------------------------------------------------------------- +fn List{int}? foo() +{ + return bar{int}((List{int}) {1, 2, 3}); +} +================================================================================ +generic_fn_params +================================================================================ +fn List{int } ? foo(Foo { bool} foo, Bar{int } bar ) +{ + return bar{int}((List{int}){1, 2, 3}) ; +} +-------------------------------------------------------------------------------- +fn List{int}? foo(Foo{bool} foo, Bar{int} bar) +{ + return bar{int}((List{int}) {1, 2, 3}); +} +================================================================================ +nested_generic_fn +================================================================================ +fn List{Foo {bool, int } } ? foo(MyGenericType { Foo{bool, int }, Bar{string } } value ) +{ + return bar{int}((List{int}){1, 2, 3}) ; +} +-------------------------------------------------------------------------------- +fn List{Foo{bool,int}}? foo(MyGenericType{Foo{bool, int}, Bar{string}} value) +{ + return bar{int}((List{int}) {1, 2, 3}); +} diff --git a/test/c3tools/codefmt/c3fmt_corpus/macros.txt b/test/c3tools/codefmt/c3fmt_corpus/macros.txt index 10659c5..438c7ab 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/macros.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/macros.txt @@ -47,7 +47,7 @@ macro size($Type) simple_macro_body_definition ================================================================================ -macro SomeType * ! +macro SomeType * ? @for_each( list ; @body( it )) { for ($typeof(list) @@ -58,7 +58,7 @@ macro SomeType * ! } } -------------------------------------------------------------------------------- -macro SomeType*! @for_each(list; @body(it)) +macro SomeType*? @for_each(list; @body(it)) { for ($typeof(list) x = list; x; x = x.next) { @body(x); @@ -166,11 +166,11 @@ matrix_component_mul macro matrix_component_mul(mat, val) @private { var $Type = Real[<$typeof(mat.m).len>]; - return $typeof(*mat) { .m = val * ($Type)mat.m }; + return ($typeof(*mat)){ .m = val * ($Type)mat.m }; } -------------------------------------------------------------------------------- macro matrix_component_mul(mat, val) @private { var $Type = Real[<$typeof(mat.m).len>]; - return $typeof(*mat){ .m = val * ($Type)mat.m }; + return ($typeof(*mat)) { .m = val * ($Type)mat.m }; } diff --git a/test/c3tools/codefmt/c3fmt_corpus/statements.txt b/test/c3tools/codefmt/c3fmt_corpus/statements.txt index 1a71a4b..bcf6f26 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/statements.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/statements.txt @@ -278,7 +278,7 @@ fn void main() { MyStruct foo = {.question = "how long it could be", .sub = {.hello=1,.world =2, .sub_sub = {.foo = bar, .zoo= bas}, - .anothe_call = io::prinf(Foo{.nowrap=true}, "hi there it's c3fmt") , + .anothe_call = io::prinf((Foo){.nowrap=true}, "hi there it's c3fmt") , .a_call_unwrappe = io::prinf_wrapped_if_struct(long_argument_name, "another", "hi there it's c3fmt") , @@ -299,7 +299,7 @@ fn void main() .foo = bar, .zoo = bas }, - .anothe_call = io::prinf(Foo { + .anothe_call = io::prinf((Foo) { .nowrap = true },"hi there it's c3fmt"), .a_call_unwrappe = io::prinf_wrapped_if_struct(long_argument_name,"another","hi there it's c3fmt"), @@ -575,6 +575,29 @@ fn void main() } } ================================================================================ +for_loop_with_generics +================================================================================ + +fn void main() +{ +for( uint i=0, Foo{uint} foo; + i<10; i++, foo.run(i) + +) { + io::printfn("i: %d", i); +} + return + 0;} + +-------------------------------------------------------------------------------- +fn void main() +{ + for (uint i = 0, Foo{uint} foo; i < 10; i++, foo.run(i)) { + io::printfn("i: %d", i); + } + return 0; +} +================================================================================ while_loop ================================================================================ @@ -901,7 +924,7 @@ fn void main() defer_catch_full_example ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { defer (catch err) @@ -918,7 +941,7 @@ fn char[ ] ! test () } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { defer (catch err) { io::printfn("Excuse found: %s", err); @@ -932,7 +955,7 @@ fn char[]! test() defer_catch_no_paren ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { defer catch io::printfn("Excuse found: %s", @@ -941,7 +964,7 @@ fn char[ ] ! test () } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { defer catch io::printfn("Excuse found: %s", err); return IoError.FILE_NOT_FOUND?; @@ -950,7 +973,7 @@ fn char[]! test() defer_catch_braces ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { defer catch {io::printfn("Excuse found: %s", @@ -959,7 +982,7 @@ fn char[ ] ! test () } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { defer catch { io::printfn("Excuse found: %s", err); @@ -970,7 +993,7 @@ fn char[]! test() if_catch_return_excuse ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { if (catch excuse = foo(call, dab)) { @@ -980,7 +1003,7 @@ if (catch excuse = foo(call, dab)) } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { if (catch excuse = foo(call, dab)) { // Return the excuse with ? operator @@ -991,7 +1014,7 @@ fn char[]! test() if_catch_switch ================================================================================ -fn void! test() +fn void? test() { if (catch excuse = optional_value) { @@ -1006,7 +1029,7 @@ case IoError.FILE_NOT_FOUND: } -------------------------------------------------------------------------------- -fn void! test() +fn void? test() { if (catch excuse = optional_value) { case NoHomework.DOG_ATE_MY_HOMEWORK: @@ -1023,7 +1046,7 @@ fn void! test() body_macro ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { c.@foo( a, b ; xyz , abcj ) { xyz[1] = 4;}; @@ -1031,7 +1054,7 @@ fn char[ ] ! test () } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { c.@foo(a, b; xyz, abcj) { xyz[1] = 4; @@ -1042,14 +1065,14 @@ fn char[]! test() expr_block ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { int foo = {| int a = 0; return a+1; |} ! ; return 0; } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { int foo = {| int a = 0; @@ -1061,14 +1084,14 @@ fn char[]! test() expr_block_bangbang ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { int foo = {| int a = 0; return a+1; |} !! ; return 0; } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { int foo = {| int a = 0; @@ -1231,13 +1254,13 @@ fn void main() int[<2>] a = { 23, 11 }; int[<2>] b = { 2, 1 }; int[<3>] a = { 11, 22, 33 }; - List() l = List.new(doo, 1); + List{int } l = List.new(doo, 1); int[<4>] b = a.xxzx; // b = { 11, 11, 33, 11 } int c = b.w; // c = 11; char[<4>] color = { 0x11, 0x22, 0x33, 0xFF }; char red = color.r; // red = 0x11 test_float(1.0, &f); - foo_test::test() ( 1.0, &g ); + foo_test::test{int, double} ( 1.0, &g ); int[<2>] c = { a[0] * b[0], a[1] * b[1] }; } @@ -1247,13 +1270,13 @@ fn void main() int[<2>] a = { 23, 11 }; int[<2>] b = { 2, 1 }; int[<3>] a = { 11, 22, 33 }; - List() l = List.new(doo, 1); + List{int} l = List.new(doo, 1); int[<4>] b = a.xxzx; // b = { 11, 11, 33, 11 } int c = b.w; // c = 11; char[<4>] color = { 0x11, 0x22, 0x33, 0xFF }; char red = color.r; // red = 0x11 test_float(1.0, &f); - foo_test::test()(1.0, &g); + foo_test::test{int, double}(1.0, &g); int[<2>] c = { a[0] * b[0], a[1] * b[1] }; } ================================================================================ @@ -1343,13 +1366,13 @@ import std::core::test @public; import std::core:: builtin; import std::io; -module math_tests::complex (< ElementType >) @test; +module math_tests::complex { ElementType } @test; -------------------------------------------------------------------------------- module test::std::core::test @test @if(FOO || BAR); import std::core::test @public; import std::core::builtin; import std::io; -module math_tests::complex() @test; +module math_tests::complex{ElementType} @test; ================================================================================ const ================================================================================ @@ -1361,10 +1384,10 @@ const Base64Alphabet URL = { .encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", .reverse = 2 }; -const bool KEY_BY_VALUE @private = NO_KEY_FN ||| $assignable(Type{}[0], $typefrom(KeyFn.paramsof[0].type)); -const bool KEY_BY_VALUE @private = $assignable(Type{}[0], $typefrom(KeyFn.paramsof[0].type)) ||| $assignable(Type{}[0], $typefrom(KeyFn.paramsof[0].type)); +const bool KEY_BY_VALUE @private = NO_KEY_FN ||| $assignable((Type){}[0], $typefrom(KeyFn.paramsof[0].type)); +const bool KEY_BY_VALUE @private = $assignable((Type){}[0], $typefrom(KeyFn.paramsof[0].type)) ||| $assignable((Type){}[0], $typefrom(KeyFn.paramsof[0].type)); const Foo F4 = (F1 | ~F2) ^ F3; -const Foo F5 = Foo { true, false } | Foo { false, true }; +const Foo F5 = (Foo){true, false } | (Foo) { false,true}; const char[?] TEST_QOI_DATA = b64"cW9pZgAAAVQAAACpBABV/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39"; -------------------------------------------------------------------------------- @@ -1377,17 +1400,17 @@ const Base64Alphabet URL = { .reverse = 2 }; const bool KEY_BY_VALUE @private = NO_KEY_FN ||| $assignable( - Type {}[0], $typefrom(KeyFn.paramsof[0].type) + (Type) {}[0], $typefrom(KeyFn.paramsof[0].type) ); const bool KEY_BY_VALUE @private = $assignable( - Type {}[0], + (Type) {}[0], $typefrom(KeyFn.paramsof[0].type) ) ||| $assignable( - Type {}[0], + (Type) {}[0], $typefrom(KeyFn.paramsof[0].type) ); const Foo F4 = (F1 | ~F2) ^ F3; -const Foo F5 = Foo { true, false } | Foo { false, true }; +const Foo F5 = (Foo) { true, false } | (Foo) { false, true }; const char[?] TEST_QOI_DATA = b64"cW9pZgAAAVQAAACpBABV/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39"; ================================================================================ extern_func @@ -1397,7 +1420,7 @@ extern fn int printf(char *str, ...); extern fn void* __asan_region_is_poisoned(void* beg, usz size); extern fn void __sanitizer_weak_hook_strcmp(void* called_pc, ZString s1, ZString s2, CInt result); extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @extern("CommandLineToArgvW"); -extern fn int! maybe(); +extern fn int? maybe(); extern fn Win32_BOOL win32_QueryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @extern("QueryPerformanceFrequency"); extern Char16* _win_command_line_to_argv_w; extern const int FOO @extern("foo1"); @@ -1412,7 +1435,7 @@ extern fn void __sanitizer_weak_hook_strcmp( void* called_pc, ZString s1, ZString s2, CInt result ); extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @extern("CommandLineToArgvW"); -extern fn int! maybe(); +extern fn int? maybe(); extern fn Win32_BOOL win32_QueryPerformanceFrequency( Win32_LARGE_INTEGER* lpFrequency ) @extern("QueryPerformanceFrequency"); @@ -1547,10 +1570,10 @@ fn void main() MyStruct foo = {1, 2,3}; MyStruct foo = {.bax = 2}; MyStruct foo_magic = {.bax = 2,}; - call(MyStruct{}, Bar {.soo = 1, }); - call(MyStruct{1, 2, 3}); - MyStruct foo = (MyStruct)call(MyStruct{1, 2, 3}); - MyStruct foo = (MyStruct)call(MyStruct{1, 2, 3, }); + call((MyStruct){}, (Bar) {.soo = 1, }); + call((MyStruct){1, 2, 3}); + MyStruct foo = (MyStruct)call((MyStruct){1, 2, 3}); + MyStruct foo = (MyStruct)call((MyStruct){1, 2, 3, }); } -------------------------------------------------------------------------------- @@ -1562,10 +1585,10 @@ fn void main() MyStruct foo_magic = { .bax = 2, }; - call(MyStruct {}, Bar {.soo = 1,}); - call(MyStruct {1, 2, 3}); - MyStruct foo = (MyStruct)call(MyStruct {1, 2, 3}); - MyStruct foo = (MyStruct)call(MyStruct {1, 2, 3,}); + call((MyStruct) {}, (Bar) {.soo = 1,}); + call((MyStruct) {1, 2, 3}); + MyStruct foo = (MyStruct)call((MyStruct) {1, 2, 3}); + MyStruct foo = (MyStruct)call((MyStruct) {1, 2, 3,}); } ================================================================================ body_macro_with_arg @@ -1621,14 +1644,14 @@ fn String Token.to_string(&self, Allocator allocator) @dynamic expr_block_standalone ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { {| int a = 0; return a+1; |} ! ; return 0; } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { {| int a = 0; @@ -1754,12 +1777,12 @@ struct_init_with_fn_pointers TestContext state @local = { .foo = 1, - .setup_fn = fn void!() { + .setup_fn = fn void?() { io::printn("new test setup"); // initialize something heavy (maybe a DB) state.n_runs = 777; }, - .teardown_fn = fn void!() { // inline + .teardown_fn = fn void?() { // inline state.n_runs = 0; io::printn("test teardown"); // inline }, @@ -1769,12 +1792,12 @@ TestContext state @local = { -------------------------------------------------------------------------------- TestContext state @local = { .foo = 1, - .setup_fn = fn void! () { + .setup_fn = fn void? () { io::printn("new test setup"); // initialize something heavy (maybe a DB) state.n_runs = 777; }, - .teardown_fn = fn void! () { // inline + .teardown_fn = fn void? () { // inline state.n_runs = 0; io::printn("test teardown"); // inline }, @@ -1788,14 +1811,14 @@ TestContext state @local = { .foo = 1, .sub_struct ={ .another = {1, 2, 3}, - .setup_fn = fn void! (int a, int b, $typeof(c) c) { + .setup_fn = fn void? (int a, int b, $typeof(c) c) { io::printn("new test setup"); // initialize something heavy (maybe a DB) state.n_runs = 777; }, .sub_field = 1 }, - .teardown_fn = fn void!() { // inline + .teardown_fn = fn void?() { // inline state.n_runs = 0; io::printn("test teardown"); // inline }, @@ -1811,14 +1834,14 @@ TestContext state @local = { 2, 3 }, - .setup_fn = fn void! (int a, int b, $typeof(c) c) { + .setup_fn = fn void? (int a, int b, $typeof(c) c) { io::printn("new test setup"); // initialize something heavy (maybe a DB) state.n_runs = 777; }, .sub_field = 1 }, - .teardown_fn = fn void! () { // inline + .teardown_fn = fn void? () { // inline state.n_runs = 0; io::printn("test teardown"); // inline }, @@ -1834,7 +1857,7 @@ TestContext state @local = { .sub_field = 1, .sub_field = 2 }, - .teardown_fn = fn void!() { // inline + .teardown_fn = fn void?() { // inline state.n_runs = 0; io::printn("test teardown"); // inline }, @@ -1848,7 +1871,7 @@ TestContext state @local = { .sub_field = 1, .sub_field = 2 }, - .teardown_fn = fn void! () { // inline + .teardown_fn = fn void? () { // inline state.n_runs = 0; io::printn("test teardown"); // inline }, @@ -1903,7 +1926,7 @@ fn void test_str_set_next_arg_missing_value_with_eqchar() expr_block_in_functions ================================================================================ -fn char[ ] ! test () +fn char[ ] ? test () { call( {| io::printfn("Send %d", a); @@ -1917,7 +1940,7 @@ fn char[ ] ! test () } -------------------------------------------------------------------------------- -fn char[]! test() +fn char[]? test() { call( {| io::printfn("Send %d", a); @@ -2059,7 +2082,7 @@ fn void test() .options = { { .short_name = 1, - .callback = fn void! (int a) { + .callback = fn void? (int a) { return 0; }, } @@ -2073,7 +2096,7 @@ fn void test() .options = { { .short_name = 1, - .callback = fn void! (int a) { + .callback = fn void? (int a) { return 0; }, } @@ -2091,7 +2114,7 @@ fn void test() .short_name = 'R', .value = &config, .help = "optimization level [default: O0]", - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { int level = value.to_integer(int)!; if (level ) { return 0; @@ -2103,7 +2126,7 @@ fn void test() .short_name = 'O', .value = &config, .help = "optimization level [default: O0]", - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { int level = value.to_integer(int)!; if (level ) { return 0; @@ -2125,7 +2148,7 @@ fn void test() .short_name = 'R', .value = &config, .help = "optimization level [default: O0]", - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { int level = value.to_integer(int)!; if (level) { return 0; @@ -2139,7 +2162,7 @@ fn void test() .short_name = 'O', .value = &config, .help = "optimization level [default: O0]", - .callback = fn void! (ArgOpt* opt, String value) { + .callback = fn void? (ArgOpt* opt, String value) { int level = value.to_integer(int)!; if (level) { return 0; diff --git a/test/c3tools/codefmt/c3fmt_corpus/typedef.txt b/test/c3tools/codefmt/c3fmt_corpus/typedef.txt index 8ac18da..5345e0d 100644 --- a/test/c3tools/codefmt/c3fmt_corpus/typedef.txt +++ b/test/c3tools/codefmt/c3fmt_corpus/typedef.txt @@ -198,42 +198,47 @@ enum State : int @if("foo") (String desc, bool active, Position pos) @test TERMINATED = { "ended", false, {0, 0} }, } ================================================================================ -fault_simple +faultdef_simple ================================================================================ -fault Err -{ - OOPS, OOPS_WITH_COMMENT, // this is an oops - LOTS_OF_OOPS -} +faultdef OOPS, OOPS_WITH_COMMENT, // this is an oops + LOTS_OF_OOPS @local @if(env::FOO); -------------------------------------------------------------------------------- -fault Err -{ +faultdef OOPS, OOPS_WITH_COMMENT, // this is an oops LOTS_OF_OOPS -} + @local + @if(env::FOO); ================================================================================ def_statement_global ================================================================================ -def EnumSetType = $typefrom(private::type_for_enum_elements(Enum.elements)) @private; -def ElementTest = fn bool(Type *type, any context); -def TestFailFn = fn void! (bool to_fail); -def FormatTzTestSpec = Triple(); -def IntList = ElasticArray(); -def BenchmarkFn = fn void!(int) @if($$OLD_TEST); -def @Align(y) = { @Align16(y / 2) }; -def @Test = { @noinline }; +alias EnumSetType = $typefrom(private::type_for_enum_elements(Enum.elements)) @private; +alias ElementTest = fn bool(Type *type, any context); +alias TestFailFn = fn void? (bool to_fail); +alias FormatTzTestSpec = Triple{TzDateTime, DateTimeFormat, String}; +alias IntList = ElasticArray{int, 10}; +alias BenchmarkFn = fn void?(int) @if($$OLD_TEST); +alias @Align(y) = { @Align16(y / 2) }; +alias @Test = { @noinline }; -------------------------------------------------------------------------------- -def EnumSetType = $typefrom( +alias EnumSetType = $typefrom( private::type_for_enum_elements(Enum.elements) ) @private; -def ElementTest = fn bool (Type* type, any context); -def TestFailFn = fn void! (bool to_fail); -def FormatTzTestSpec = Triple(); -def IntList = ElasticArray(); -def BenchmarkFn = fn void! (int) @if($$OLD_TEST); -def @Align(y) = { @Align16(y / 2) }; -def @Test = { @noinline }; +alias ElementTest = fn bool (Type* type, any context); +alias TestFailFn = fn void? (bool to_fail); +alias FormatTzTestSpec = Triple{TzDateTime, DateTimeFormat, String}; +alias IntList = ElasticArray{int, 10}; +alias BenchmarkFn = fn void? (int) @if($$OLD_TEST); +alias @Align(y) = { @Align16(y / 2) }; +alias @Test = { @noinline }; +================================================================================ +optional_return_type +================================================================================ +alias TestFailFn = fn void ? (bool to_fail); +alias BenchmarkFn = fn void?(int) @if($$OLD_TEST); +-------------------------------------------------------------------------------- +alias TestFailFn = fn void? (bool to_fail); +alias BenchmarkFn = fn void? (int) @if($$OLD_TEST); ================================================================================ def_interface ================================================================================ @@ -241,7 +246,7 @@ interface Printable @if("sasda") { fn String* to_string(Allocator allocator) @optional; fn String to_new_string(Allocator allocator) @optional @deprecated("Use to_string"); - fn usz! to_format(Formatter* formatter) @optional; + fn usz? to_format(Formatter* formatter) @optional; fn usz* to_format(Formatter* formatter, Alooong Type, Maybe can, bool wrap, please) @optional; fn usz* to_format(Formatter* formatter, Alooong Type, Maybe can, bool wrap, please, or_maybe multiline) @optional; fn usz* to_format(Formatter* magic_comma, ) @optional; @@ -251,7 +256,7 @@ interface Printable @if("sasda") { fn String* to_string(Allocator allocator) @optional; fn String to_new_string(Allocator allocator) @optional @deprecated("Use to_string"); - fn usz! to_format(Formatter* formatter) @optional; + fn usz? to_format(Formatter* formatter) @optional; fn usz* to_format( Formatter* formatter, Alooong Type, Maybe can, bool wrap, please ) @optional; @@ -268,21 +273,21 @@ interface Printable @if("sasda") ) @optional; } ================================================================================ -distinct +typedef ================================================================================ -distinct Color = float[<4>]; -distinct TypeA = char[]; -distinct Bob = inline Abc; -distinct Foo = fn void(Foo** x); // #error: cannot define a new function type -distinct Foo = inline PrivateFoo(); // #error: could not be found -distinct PriorityQueue = inline PrivatePriorityQueue <[Type,false] >; +typedef Color = float[<4>]; +typedef TypeA = char[]; +typedef Bob = inline Abc; +typedef Foo = fn void(Foo** x); // #error: cannot define a new function type +typedef Foo = inline PrivateFoo { int,bool } ; // #error: could not be found +typedef PriorityQueue = inline PrivatePriorityQueue <[Type,false] >; -------------------------------------------------------------------------------- -distinct Color = float[<4>]; -distinct TypeA = char[]; -distinct Bob = inline Abc; -distinct Foo = fn void (Foo** x); // #error: cannot define a new function type -distinct Foo = inline PrivateFoo(); // #error: could not be found -distinct PriorityQueue = inline PrivatePriorityQueue <[Type, false] >; +typedef Color = float[<4>]; +typedef TypeA = char[]; +typedef Bob = inline Abc; +typedef Foo = fn void (Foo** x); // #error: cannot define a new function type +typedef Foo = inline PrivateFoo{int, bool}; // #error: could not be found +typedef PriorityQueue = inline PrivatePriorityQueue <[Type, false] >; ================================================================================ union_with_struct ================================================================================ @@ -318,7 +323,7 @@ struct ReflectedParam (Printable) @if(!$defined(ReflectedParam)) String name; typeid type; } -def Time_t = $typefrom(env::WIN32 ? long.typeid : CLong.typeid); +alias Time_t = $typefrom(env::WIN32 ? long.typeid : CLong.typeid); macro bool @typeis(#value, $Type) @const @builtin => $typeof(#value).typeid == $Type.typeid; @@ -343,7 +348,7 @@ struct ReflectedParam (Printable) @if(!$defined(ReflectedParam)) typeid type; } -def Time_t = $typefrom(env::WIN32 ? long.typeid : CLong.typeid); +alias Time_t = $typefrom(env::WIN32 ? long.typeid : CLong.typeid); macro bool @typeis(#value, $Type) @const @builtin => $typeof(#value).typeid == $Type.typeid; @@ -360,14 +365,14 @@ fn typeid main(typeid t) return; } ================================================================================ -any_anyfault +any_fault ================================================================================ macro any main(any foo) { return;} -macro anyfault -main(anyfault foo) { return;} +macro fault +main(fault foo) { return;} -------------------------------------------------------------------------------- macro any main(any foo) @@ -375,7 +380,7 @@ macro any main(any foo) return; } -macro anyfault main(anyfault foo) +macro fault main(fault foo) { return; } @@ -460,12 +465,12 @@ user_defined_attributes ================================================================================ module test; -def @Foo = { @noreturn @weak }; +alias @Foo = { @noreturn @weak }; -def @Align(y) = { @align(y) }; -def @Align16(x) = { @Align(8 * x) @align(1024) } @private; -def @Test = { @noinline }; -def @TestZero = { }; +alias @Align(y) = { @align(y) }; +alias @Align16(x) = { @Align(8 * x) @align(1024) }@private; +alias @Test = { @noinline }; +alias @TestZero = { }; struct Foo { int z; @@ -490,12 +495,12 @@ fn void main() @TestZero -------------------------------------------------------------------------------- module test; -def @Foo = { @noreturn @weak }; +alias @Foo = { @noreturn @weak }; -def @Align(y) = { @align(y) }; -def @Align16(x) = { @Align(8 * x) @align(1024) }@private; -def @Test = { @noinline }; -def @TestZero = {}; +alias @Align(y) = { @align(y) }; +alias @Align16(x) = { @Align(8 * x) @align(1024) } @private; +alias @Test = { @noinline }; +alias @TestZero = {}; struct Foo { int z; diff --git a/test/c3tools/codefmt/test_c3fmt_base.c3 b/test/c3tools/codefmt/test_c3fmt_base.c3 index d99d693..a12f661 100644 --- a/test/c3tools/codefmt/test_c3fmt_base.c3 +++ b/test/c3tools/codefmt/test_c3fmt_base.c3 @@ -7,7 +7,7 @@ import c3tools::codefmt; fn void test_two_spaces() { - CodeFmt fmt = CodeFmt.new_init(indent_type: '2'); + CodeFmt fmt = codefmt::new_init(indent_type: '2'); defer fmt.free(); String input = ` fn void main() @@ -33,7 +33,7 @@ fn void main() fn void test_eight_spaces() { - CodeFmt fmt = CodeFmt.new_init(indent_type: '8'); + CodeFmt fmt = codefmt::new_init(indent_type: '8'); defer fmt.free(); String input = ` fn void main() @@ -59,7 +59,7 @@ fn void main() fn void test_tabs() { - CodeFmt fmt = CodeFmt.new_init(indent_type: 't'); + CodeFmt fmt = codefmt::new_init(indent_type: 't'); defer fmt.free(); String input = ` fn void main() diff --git a/test/c3tools/lsp/lsp_test_proj/mod1.c3 b/test/c3tools/lsp/lsp_test_proj/mod1.c3 index 2cb3aad..8120f59 100644 --- a/test/c3tools/lsp/lsp_test_proj/mod1.c3 +++ b/test/c3tools/lsp/lsp_test_proj/mod1.c3 @@ -1,7 +1,7 @@ module test::c3tools::lsp_test_mod1; // NOTE: this symbol will not be added to file scope symbol (only global one) -def MyInt = int; +alias MyInt = int; // should be in file scope int global_int @local = 2; diff --git a/test/c3tools/lsp/test_document.c3 b/test/c3tools/lsp/test_document.c3 index 0119ef4..b3bff92 100644 --- a/test/c3tools/lsp/test_document.c3 +++ b/test/c3tools/lsp/test_document.c3 @@ -11,7 +11,7 @@ fn Position resolve_src_pos(DString src) @private int col = -1; @pool() { - DString tmp = dstring::temp_new(); + DString tmp = dstring::temp(); foreach (c : src) { if (c == '\n') { line++; @@ -29,7 +29,7 @@ fn Position resolve_src_pos(DString src) @private src.append(tmp); }; assert(lpos >= 0 && cpos >= 0, "| cursor place was not found"); - return Position { .l = lpos, .c = cpos }; + return (Position) { .l = lpos, .c = cpos }; } module test::c3tools::lsp::document @test; @@ -62,10 +62,10 @@ fn void test_init_lsp_proj() { test::@setup(state.setup_fn, state.teardown_fn); String uri = "file://" +++ BASE_PROJ_PATH +++ "mod1.c3"; - String src = (String)file::load_new(BASE_PROJ_PATH +++ "mod1.c3")!!; - defer src.free(); + String src = (String)file::load(mem, BASE_PROJ_PATH +++ "mod1.c3")!!; + defer src.free(mem); - Document doc = Document.new_open(uri, src, &state.lsp.proj); + Document doc = lsp::new_document(uri, src, &state.lsp.proj); defer doc.close(); test::eq(uri, doc.uri); @@ -79,6 +79,7 @@ fn void test_document_cursor() test::@setup(state.setup_fn, state.teardown_fn); DString src = dstring::new( + mem, ` m|odule test::c3tools::lsp_test_mod1; int global_int @local = 2; @@ -95,7 +96,7 @@ fn int add(int a, int b) { test::eq(cur.l, 0); test::eq(cur.c, 1); - Document doc = Document.new_open("file://test.c3", src.str_view(), &state.lsp.proj); + Document doc = lsp::new_document("file://test.c3", src.str_view(), &state.lsp.proj); defer doc.close(); test::eq(doc.ast.@node_len(doc.ast.modules), 1); @@ -107,6 +108,7 @@ fn void test_document_cursor_next_line() test::@setup(state.setup_fn, state.teardown_fn); DString src = dstring::new( + mem, ` module test::c3tools::lsp_test_mod1; int g|lobal_int @local = 2; @@ -129,6 +131,7 @@ fn void test_document_context() test::@setup(state.setup_fn, state.teardown_fn); DString src = dstring::new( + mem, ` m|odule test::c3tools::lsp_test_mod1; int global_int @local = 2; @@ -140,7 +143,7 @@ fn int add(int a, int b) { defer src.free(); Position cur = resolve_src_pos(src); - Document doc = Document.new_open("file://test.c3", src.str_view(), &state.lsp.proj); + Document doc = lsp::new_document("file://test.c3", src.str_view(), &state.lsp.proj); defer doc.close(); } diff --git a/test/c3tools/lsp/test_project.c3 b/test/c3tools/lsp/test_project.c3 index 8a49b89..6c2221f 100644 --- a/test/c3tools/lsp/test_project.c3 +++ b/test/c3tools/lsp/test_project.c3 @@ -26,7 +26,7 @@ fn void test5(int a) => a * 2; fn void test6(int a) => a * 2; //`; // NOTE: // - is sanity guard comment, don't delete it! - DString contents = dstring::temp_new(code); + DString contents = dstring::temp(code); Ast ast = ast::parse(contents.str_view(), "foo.c3", print_lex: false); defer mem::free(ast._allocator); contents.clear(); @@ -50,7 +50,7 @@ fn void test6(int a) => a * 2; io::printfn("'%s' hash: %s", m.node.value, m.hash); test::ne(m.hash, (Fnv32a)0); - LspProject proj = LspProject.new_init("", ""); + LspProject proj = project::new_lsp_project("", ""); defer proj.free(); proj.load_source(code, "foo.c3")!!; @@ -79,7 +79,7 @@ fn void test6(int a) => a * 2; //`; // NOTE: // - is sanity guard comment, don't delete it! - LspProject proj = LspProject.new_init("", ""); + LspProject proj = project::new_lsp_project("", ""); defer proj.free(); proj.load_source(code, "foo.c3")!!; @@ -92,20 +92,20 @@ fn void test6(int a) => a * 2; SymbolItem* m = proj.modules.first("test::std::c3lang::ast"); test::eq(proj.modules.get_name(m), "test::std::c3lang::ast"); test::eq(m.kind, SymbolKind.MODULE); - test::eq(m.module_hash, (Fnv32a)fnv32a::encode("test::std::c3lang::ast")); - test::eq(m.hash, (Fnv32a)fnv32a::encode("test::std::c3lang::ast")); + test::eq(m.module_hash, (Fnv32a)fnv32a::hash("test::std::c3lang::ast")); + test::eq(m.hash, (Fnv32a)fnv32a::hash("test::std::c3lang::ast")); m = proj.modules.first("test::std::c3lang::best"); test::eq(proj.modules.get_name(m), "test::std::c3lang::best"); test::eq(m.kind, SymbolKind.MODULE); - test::eq(m.module_hash, (Fnv32a)fnv32a::encode("test::std::c3lang::best")); - test::eq(m.hash, (Fnv32a)fnv32a::encode("test::std::c3lang::best")); + test::eq(m.module_hash, (Fnv32a)fnv32a::hash("test::std::c3lang::best")); + test::eq(m.hash, (Fnv32a)fnv32a::hash("test::std::c3lang::best")); m = proj.modules.first("test::std::c3lang::cest"); test::eq(proj.modules.get_name(m), "test::std::c3lang::cest"); test::eq(m.kind, SymbolKind.MODULE); - test::eq(m.module_hash, (Fnv32a)fnv32a::encode("test::std::c3lang::cest")); - test::eq(m.hash, (Fnv32a)fnv32a::encode("test::std::c3lang::cest")); + test::eq(m.module_hash, (Fnv32a)fnv32a::hash("test::std::c3lang::cest")); + test::eq(m.hash, (Fnv32a)fnv32a::hash("test::std::c3lang::cest")); } fn void test_module_index_duplicates() @@ -129,7 +129,7 @@ fn void test6(int a) => a * 2; //`; // NOTE: // - is sanity guard comment, don't delete it! - LspProject proj = LspProject.new_init("", ""); + LspProject proj = project::new_lsp_project("", ""); defer proj.free(); proj.load_source(code, "foo.c3")!!; @@ -148,8 +148,8 @@ fn void test6(int a) => a * 2; ) { test::eq(proj.modules.get_name(m), "test::std::c3lang::ast"); test::eq(m.kind, SymbolKind.MODULE); - test::eq(m.module_hash, (Fnv32a)fnv32a::encode("test::std::c3lang::ast")); - test::eq(m.hash, (Fnv32a)fnv32a::encode("test::std::c3lang::ast")); + test::eq(m.module_hash, (Fnv32a)fnv32a::hash("test::std::c3lang::ast")); + test::eq(m.hash, (Fnv32a)fnv32a::hash("test::std::c3lang::ast")); n_collision++; } diff --git a/test/c3tools/lsp/test_symbol_cache.c3 b/test/c3tools/lsp/test_symbol_cache.c3 index fcf68be..91eba30 100644 --- a/test/c3tools/lsp/test_symbol_cache.c3 +++ b/test/c3tools/lsp/test_symbol_cache.c3 @@ -8,7 +8,7 @@ import std::io; fn void test_add_symbols() { - SymbolCache* cache = SymbolCache.new_init(10); + SymbolCache* cache = symbols::new_symbol_cache(10); defer cache.free(); test::eq(cache.items_len, 0); @@ -29,7 +29,7 @@ fn void test_add_symbols() fn void test_find_insert_position() { - SymbolCache* cache = SymbolCache.new_init(10); + SymbolCache* cache = symbols::new_symbol_cache(10); defer cache.free(); SymbolItem* items = cache.items(); @@ -57,7 +57,7 @@ fn void test_find_insert_position() fn void test_find_insert_at() { - SymbolCache* cache = SymbolCache.new_init(10); + SymbolCache* cache = symbols::new_symbol_cache(10); defer cache.free(); SymbolItem* items = cache.items(); @@ -101,7 +101,7 @@ fn void test_find_insert_at_random() random::seed_entropy(&random); for (int i = 0; i < 100; i++) { - SymbolCache* cache = SymbolCache.new_init(100); + SymbolCache* cache = symbols::new_symbol_cache(100); defer cache.free(); SymbolItem* items = cache.items(); @@ -140,7 +140,7 @@ fn void test_find_insert_at_random() fn void test_insert_name() { - SymbolCache* cache = SymbolCache.new_init(10); + SymbolCache* cache = symbols::new_symbol_cache(10); defer cache.free(); char* names = cache.strings(); @@ -161,7 +161,7 @@ fn void test_insert_name() fn void test_item_add() { - SymbolCache* cache = SymbolCache.new_init(10); + SymbolCache* cache = symbols::new_symbol_cache(10); defer cache.free(); char* names = cache.strings(); @@ -204,7 +204,7 @@ fn void test_item_add() fn void test_item_find() { - SymbolCache* cache = SymbolCache.new_init(10); + SymbolCache* cache = symbols::new_symbol_cache(10); defer cache.free(); SymbolItem* items = cache.items(); @@ -238,7 +238,7 @@ fn void test_item_find() fn void test_grow() { - SymbolCache* cache = SymbolCache.new_init(4); + SymbolCache* cache = symbols::new_symbol_cache(4); defer cache.free(); SymbolItem* items = cache.items(); @@ -308,7 +308,7 @@ fn void test_add_with_resize_and_validate() Lcg128Random random; random::seed_entropy(&random); - SymbolCache* cache = SymbolCache.new_init(100); + SymbolCache* cache = symbols::new_symbol_cache(100); DString buf; defer buf.free(); defer cache.free();