From 29b936fee974aa5053eb8edc3a67d5d695c1998f Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 6 Jan 2022 11:48:37 +0100 Subject: [PATCH 01/20] Add a wrapper over memset/memcpy for object initialization to conditionally silence the compiler warnings --- NULLC/Array.h | 4 ++-- NULLC/CodeGenRegVm_X86.cpp | 10 +++++----- NULLC/DenseMap.h | 14 +++++++------- NULLC/Executor_X86.cpp | 4 ++-- NULLC/Instruction_X86.h | 2 +- NULLC/Translator_X86.cpp | 2 +- NULLC/stdafx.h | 9 +++++++++ 7 files changed, 27 insertions(+), 18 deletions(-) diff --git a/NULLC/Array.h b/NULLC/Array.h index ac38d49b1..c4854737f 100644 --- a/NULLC/Array.h +++ b/NULLC/Array.h @@ -169,10 +169,10 @@ class FastVector assert(newData); if(zeroNewMemory) - memset(newData, 0, newSize * sizeof(T)); + NULLC_no_warning_memset(newData, 0, newSize * sizeof(T)); if(data) - memcpy(newData, data, max * sizeof(T)); + NULLC_no_warning_memcpy(newData, data, max * sizeof(T)); data = newData; max = newSize; diff --git a/NULLC/CodeGenRegVm_X86.cpp b/NULLC/CodeGenRegVm_X86.cpp index c74fce757..7fb81c6a8 100644 --- a/NULLC/CodeGenRegVm_X86.cpp +++ b/NULLC/CodeGenRegVm_X86.cpp @@ -1263,7 +1263,7 @@ void x86DtolWrap(CodeGenRegVmStateContext *vmState, unsigned cmdValueA, unsigned unsigned cmdValue[2] = { cmdValueA, cmdValueB }; RegVmCmd cmd; - memcpy(&cmd, &cmdValue, sizeof(cmd)); + NULLC_no_warning_memcpy(&cmd, &cmdValue, sizeof(cmd)); regFilePtr[cmd.rA].longValue = (long long)(regFilePtr[cmd.rC].doubleValue); } @@ -1309,7 +1309,7 @@ void x86LtodWrap(CodeGenRegVmStateContext *vmState, unsigned cmdValueA, unsigned unsigned cmdValue[2] = { cmdValueA, cmdValueB }; RegVmCmd cmd; - memcpy(&cmd, &cmdValue, sizeof(cmd)); + NULLC_no_warning_memcpy(&cmd, &cmdValue, sizeof(cmd)); regFilePtr[cmd.rA].doubleValue = double(regFilePtr[cmd.rC].longValue); } @@ -2728,7 +2728,7 @@ void x86PowWrap(CodeGenRegVmStateContext *vmState, unsigned cmdValueA, unsigned unsigned cmdValue[2] = { cmdValueA, cmdValueB }; RegVmCmd cmd; - memcpy(&cmd, &cmdValue, sizeof(cmd)); + NULLC_no_warning_memcpy(&cmd, &cmdValue, sizeof(cmd)); regFilePtr[cmd.rA].intValue = VmIntPow(*(int*)(uintptr_t)(regFilePtr[cmd.rC].ptrValue + cmd.argument), regFilePtr[cmd.rB].intValue); } @@ -3998,7 +3998,7 @@ void x86PowdWrap(CodeGenRegVmStateContext *vmState, unsigned cmdValueA, unsigned unsigned cmdValue[2] = { cmdValueA, cmdValueB }; RegVmCmd cmd; - memcpy(&cmd, &cmdValue, sizeof(cmd)); + NULLC_no_warning_memcpy(&cmd, &cmdValue, sizeof(cmd)); regFilePtr[cmd.rA].doubleValue = pow(regFilePtr[cmd.rB].doubleValue, *(double*)(uintptr_t)(regFilePtr[cmd.rC].ptrValue + cmd.argument)); } @@ -4038,7 +4038,7 @@ void x86ModdWrap(CodeGenRegVmStateContext *vmState, unsigned cmdValueA, unsigned unsigned cmdValue[2] = { cmdValueA, cmdValueB }; RegVmCmd cmd; - memcpy(&cmd, &cmdValue, sizeof(cmd)); + NULLC_no_warning_memcpy(&cmd, &cmdValue, sizeof(cmd)); regFilePtr[cmd.rA].doubleValue = fmod(regFilePtr[cmd.rB].doubleValue, *(double*)(uintptr_t)(regFilePtr[cmd.rC].ptrValue + cmd.argument)); } diff --git a/NULLC/DenseMap.h b/NULLC/DenseMap.h index 844640456..0d44767fd 100644 --- a/NULLC/DenseMap.h +++ b/NULLC/DenseMap.h @@ -24,7 +24,7 @@ class SmallDenseMap data = storage; - memset(data, 0, sizeof(Node) * bucketCount); + NULLC_no_warning_memset(data, 0, sizeof(Node) * bucketCount); } ~SmallDenseMap() @@ -125,7 +125,7 @@ class SmallDenseMap else data = (Node*)NULLC::alloc(sizeof(Node) * bucketCount); - memset(data, 0, sizeof(Node) * bucketCount); + NULLC_no_warning_memset(data, 0, sizeof(Node) * bucketCount); count = 0; @@ -182,7 +182,7 @@ class SmallDenseSet data = storage; - memset(data, 0, sizeof(Key) * bucketCount); + NULLC_no_warning_memset(data, 0, sizeof(Key) * bucketCount); } ~SmallDenseSet() @@ -208,7 +208,7 @@ class SmallDenseSet { count = 0; - memset(data, 0, sizeof(Key) * bucketCount); + NULLC_no_warning_memset(data, 0, sizeof(Key) * bucketCount); } void insert(const Key& key) @@ -279,7 +279,7 @@ class SmallDenseSet else data = (Key*)NULLC::alloc(sizeof(Key) * bucketCount); - memset(data, 0, sizeof(Key) * bucketCount); + NULLC_no_warning_memset(data, 0, sizeof(Key) * bucketCount); count = 0; @@ -377,7 +377,7 @@ class DirectChainedMap count = 0; data = (Node*)allocator->alloc(sizeof(Node) * bucketCount); - memset(data, 0, sizeof(Node) * bucketCount); + NULLC_no_warning_memset(data, 0, sizeof(Node) * bucketCount); } ~DirectChainedMap() @@ -569,7 +569,7 @@ class DirectChainedMap count = 0; data = (Node*)allocator->alloc(sizeof(Node) * bucketCount); - memset(data, 0, sizeof(Node) * bucketCount); + NULLC_no_warning_memset(data, 0, sizeof(Node) * bucketCount); for(unsigned i = 0; i < oldBucketCount; i++) { diff --git a/NULLC/Executor_X86.cpp b/NULLC/Executor_X86.cpp index bce64827e..0731514ca 100644 --- a/NULLC/Executor_X86.cpp +++ b/NULLC/Executor_X86.cpp @@ -1214,7 +1214,7 @@ void ExecutorX86::ClearNative() TRACE_SCOPE("x86", "ClearNative"); if (instList.size()) - memset(instList.data, 0, sizeof(x86Instruction) * instList.size()); + NULLC_no_warning_memset(instList.data, 0, sizeof(x86Instruction) * instList.size()); instList.clear(); binCodeSize = 0; @@ -1279,7 +1279,7 @@ bool ExecutorX86::TranslateToNative(bool enableLogFiles, OutputContext &output) TRACE_SCOPE("x86", "TranslateToNative"); if(instList.size()) - memset(instList.data, 0, sizeof(x86Instruction) * instList.size()); + NULLC_no_warning_memset(instList.data, 0, sizeof(x86Instruction) * instList.size()); instList.clear(); instList.reserve(64); diff --git a/NULLC/Instruction_X86.h b/NULLC/Instruction_X86.h index 3277c23b0..ccf461d03 100644 --- a/NULLC/Instruction_X86.h +++ b/NULLC/Instruction_X86.h @@ -275,7 +275,7 @@ struct x86Argument void Empty() { - memset(this, 0, sizeof(x86Argument)); + NULLC_no_warning_memset(this, 0, sizeof(x86Argument)); } bool operator==(const x86Argument& r) diff --git a/NULLC/Translator_X86.cpp b/NULLC/Translator_X86.cpp index 1e9d7d08e..8bc64a0fa 100644 --- a/NULLC/Translator_X86.cpp +++ b/NULLC/Translator_X86.cpp @@ -3963,7 +3963,7 @@ void x86TestEncoding(unsigned char *codeLaunchHeader) unsigned instSize = 256 * 1024; x86Instruction *instList = new x86Instruction[instSize]; - memset(instList, 0, instSize * sizeof(x86Instruction)); + NULLC_no_warning_memset(instList, 0, instSize * sizeof(x86Instruction)); ctx.SetLastInstruction(instList, instList); stream += TestRptrXmmEncoding(ctx, stream, o_movss, x86MOVSS, testSizeDword); diff --git a/NULLC/stdafx.h b/NULLC/stdafx.h index d2ebc0641..72443c096 100644 --- a/NULLC/stdafx.h +++ b/NULLC/stdafx.h @@ -35,8 +35,17 @@ #define assert(expr) ((void)sizeof(!(expr))) #endif +#ifdef NO_MEMSET_WRAPPER +#define NULLC_no_warning_memset(dest, ch, sz) memset(dest, ch, sz) +#define NULLC_no_warning_memcpy(dest, src, sz) memcpy(dest, src, sz) +#else +inline void NULLC_no_warning_memset(void *dest, int ch, size_t sz) {memset(dest, ch, sz);} +inline void NULLC_no_warning_memcpy(void *dest, void *src, size_t sz) {memcpy(dest, src, sz);} +#endif + namespace NULLC { + void* defaultAlloc(int size); void defaultDealloc(void* ptr); From adc672aeff799f4916975e7a26a438af1795d0fa Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 6 Jan 2022 12:25:41 +0100 Subject: [PATCH 02/20] Fix strcmp tests assuming we want return value like in C --- tests/TestSglString.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/TestSglString.cpp b/tests/TestSglString.cpp index 7dbb45ee0..5b47b648b 100644 --- a/tests/TestSglString.cpp +++ b/tests/TestSglString.cpp @@ -335,10 +335,10 @@ assert(strchr(\"test\", '\\0') == 4);\r\n\ assert(strchr(\"\", '\\0') == 0);\r\n\ assert(strchr(\"te\\0st\", 's') == -1);\r\n\ \r\n\ -assert(strcmp(\"test\", \"none\") == 1);\r\n\ -assert(strcmp(\"none\", \"test\") == -1);\r\n\ -assert(strcmp(\"test\", \"zz\") == -1);\r\n\ -assert(strcmp(\"zz\", \"test\") == 1);\r\n\ +assert(strcmp(\"test\", \"none\") > 0);\r\n\ +assert(strcmp(\"none\", \"test\") < 0);\r\n\ +assert(strcmp(\"test\", \"zz\") < 0);\r\n\ +assert(strcmp(\"zz\", \"test\") > 1);\r\n\ assert(strcmp(\"test\", \"test\") == 0);\r\n\ assert(strcmp(\"\", \"\") == 0);\r\n\ assert(strcmp(\"te\\0st\", \"te\") == 0);\r\n\ From ccf6eb4779ca36d340b2bc4bc4d9abe594f36823 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 6 Jan 2022 12:27:05 +0100 Subject: [PATCH 03/20] Replace lex_string by lex_identifier because it seems that is the intended meaning for it's usage --- NULLC/Lexer.cpp | 2 +- NULLC/Lexer.h | 2 +- NULLC/ParseTree.cpp | 64 +++++++++++++++---------------- external/pugixml/pugixml.cpp | 24 ++++++------ tests/nullc_in_nullc/lexer.nc | 12 +++--- tests/nullc_in_nullc/parser.nc | 70 +++++++++++++++++----------------- 6 files changed, 87 insertions(+), 87 deletions(-) diff --git a/NULLC/Lexer.cpp b/NULLC/Lexer.cpp index 8d5eff509..376dbd9dc 100644 --- a/NULLC/Lexer.cpp +++ b/NULLC/Lexer.cpp @@ -512,7 +512,7 @@ void Lexer::Lexify(const char* code) } if(lType == lex_none) - lType = lex_string; + lType = lex_identifier; } } Lexeme lex; diff --git a/NULLC/Lexer.h b/NULLC/Lexer.h index 9079488ba..f0b7d8627 100644 --- a/NULLC/Lexer.h +++ b/NULLC/Lexer.h @@ -36,7 +36,7 @@ static inline bool isDigit(char data) enum LexemeType { lex_none, - lex_number, lex_string, lex_quotedstring, // *(0-9) *(a-z,A-Z,_) "*any" + lex_number, lex_identifier, lex_quotedstring, // *(0-9) *(a-z,A-Z,_) "*any" lex_semiquotedchar, lex_point, lex_comma, // ' . lex_inc, lex_dec, // ++ -- lex_add, lex_sub, lex_mul, lex_div, lex_mod, lex_pow, lex_less, lex_lequal, lex_shl, lex_greater, lex_gequal, lex_shr, lex_equal, lex_nequal, // + - * / % ** < <= << > >= >> == != diff --git a/NULLC/ParseTree.cpp b/NULLC/ParseTree.cpp index 8372461ad..cbe2d8acb 100644 --- a/NULLC/ParseTree.cpp +++ b/NULLC/ParseTree.cpp @@ -526,7 +526,7 @@ SynBase* ParseTerminalType(ParseContext &ctx, bool &shrBorrow) { Lexeme *start = ctx.currentLexeme; - if(ctx.At(lex_string)) + if(ctx.At(lex_identifier)) { InplaceStr name = ctx.Consume(); @@ -538,7 +538,7 @@ SynBase* ParseTerminalType(ParseContext &ctx, bool &shrBorrow) { ctx.Skip(); - if(!CheckAt(ctx, lex_string, "ERROR: namespace member is expected after '.'")) + if(!CheckAt(ctx, lex_identifier, "ERROR: namespace member is expected after '.'")) { namespacePath.push_back(new (ctx.get()) SynIdentifier(start, ctx.Previous(), name)); @@ -644,7 +644,7 @@ SynBase* ParseTerminalType(ParseContext &ctx, bool &shrBorrow) if(ctx.Consume(lex_at)) { - if(!ctx.At(lex_string)) + if(!ctx.At(lex_identifier)) { // Backtrack ctx.currentLexeme = start; @@ -887,7 +887,7 @@ SynNumber* ParseNumber(ParseContext &ctx) InplaceStr suffix; - if(ctx.At(lex_string)) + if(ctx.At(lex_identifier)) suffix = ctx.Consume(); return new (ctx.get()) SynNumber(start, ctx.Previous(), value, suffix); @@ -1027,7 +1027,7 @@ SynCallArgument* ParseCallArgument(ParseContext &ctx) { Lexeme *start = ctx.currentLexeme; - if(ctx.At(lex_string)) + if(ctx.At(lex_identifier)) { InplaceStr name = ctx.Consume(); SynIdentifier *nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -1106,7 +1106,7 @@ SynBase* ParsePostExpressions(ParseContext &ctx, SynBase *node) if(ctx.Consume(lex_point)) { - if(ctx.At(lex_return) || CheckAt(ctx, lex_string, "ERROR: member name expected after '.'")) + if(ctx.At(lex_return) || CheckAt(ctx, lex_identifier, "ERROR: member name expected after '.'")) { InplaceStr member = ctx.Consume(); SynIdentifier *memberIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), member); @@ -1239,7 +1239,7 @@ SynBase* ParseComplexTerminal(ParseContext &ctx) if(!node) node = ParseType(ctx); - if(!node && ctx.At(lex_string)) + if(!node && ctx.At(lex_identifier)) { InplaceStr value = ctx.Consume(); @@ -1558,7 +1558,7 @@ SynBase* ParseClassDefinition(ParseContext &ctx) { SynIdentifier *nameIdentifier = NULL; - if(CheckAt(ctx, lex_string, "ERROR: class name expected")) + if(CheckAt(ctx, lex_identifier, "ERROR: class name expected")) { InplaceStr name = ctx.Consume(); nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -1580,7 +1580,7 @@ SynBase* ParseClassDefinition(ParseContext &ctx) if(ctx.Consume(lex_less)) { - if(CheckAt(ctx, lex_string, "ERROR: generic type alias required after '<'")) + if(CheckAt(ctx, lex_identifier, "ERROR: generic type alias required after '<'")) { InplaceStr alias = ctx.Consume(); @@ -1588,7 +1588,7 @@ SynBase* ParseClassDefinition(ParseContext &ctx) while(ctx.Consume(lex_comma)) { - if(!CheckAt(ctx, lex_string, "ERROR: generic type alias required after ','")) + if(!CheckAt(ctx, lex_identifier, "ERROR: generic type alias required after ','")) break; alias = ctx.Consume(); @@ -1640,7 +1640,7 @@ SynEnumDefinition* ParseEnumDefinition(ParseContext &ctx) { SynIdentifier *nameIdentifier = NULL; - if(CheckAt(ctx, lex_string, "ERROR: enum name expected")) + if(CheckAt(ctx, lex_identifier, "ERROR: enum name expected")) { InplaceStr name = ctx.Consume(); nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -1658,12 +1658,12 @@ SynEnumDefinition* ParseEnumDefinition(ParseContext &ctx) { if(values.empty()) { - if(!CheckAt(ctx, lex_string, "ERROR: enumeration name expected after '{'")) + if(!CheckAt(ctx, lex_identifier, "ERROR: enumeration name expected after '{'")) break; } else { - if(!CheckAt(ctx, lex_string, "ERROR: enumeration name expected after ','")) + if(!CheckAt(ctx, lex_identifier, "ERROR: enumeration name expected after ','")) break; } @@ -1706,7 +1706,7 @@ SynNamespaceDefinition* ParseNamespaceDefinition(ParseContext &ctx) { IntrusiveList path; - if(CheckAt(ctx, lex_string, "ERROR: namespace name required")) + if(CheckAt(ctx, lex_identifier, "ERROR: namespace name required")) { InplaceStr value = ctx.Consume(); path.push_back(new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), value)); @@ -1714,7 +1714,7 @@ SynNamespaceDefinition* ParseNamespaceDefinition(ParseContext &ctx) while(ctx.Consume(lex_point)) { - if(!CheckAt(ctx, lex_string, "ERROR: namespace name required after '.'")) + if(!CheckAt(ctx, lex_identifier, "ERROR: namespace name required after '.'")) break; InplaceStr value = ctx.Consume(); @@ -1825,7 +1825,7 @@ SynTypedef* ParseTypedef(ParseContext &ctx) SynIdentifier *aliasIdentifier = NULL; - if(CheckAt(ctx, lex_string, "ERROR: alias name expected after typename in typedef expression")) + if(CheckAt(ctx, lex_identifier, "ERROR: alias name expected after typename in typedef expression")) { InplaceStr alias = ctx.Consume(); aliasIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), alias); @@ -1965,7 +1965,7 @@ SynForEachIterator* ParseForEachIterator(ParseContext &ctx, bool isFirst) SynBase *type = ParseType(ctx); // Must be followed by a type - if(!ctx.At(lex_string)) + if(!ctx.At(lex_identifier)) { // Backtrack ctx.currentLexeme = start; @@ -1973,7 +1973,7 @@ SynForEachIterator* ParseForEachIterator(ParseContext &ctx, bool isFirst) type = NULL; } - if(ctx.At(lex_string)) + if(ctx.At(lex_identifier)) { InplaceStr name = ctx.Consume(); SynIdentifier *nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2274,7 +2274,7 @@ SynVariableDefinition* ParseVariableDefinition(ParseContext &ctx) { Lexeme *start = ctx.currentLexeme; - if(ctx.At(lex_string)) + if(ctx.At(lex_identifier)) { InplaceStr name = ctx.Consume(); SynIdentifier *nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2371,7 +2371,7 @@ SynAccessor* ParseAccessorDefinition(ParseContext &ctx) if(SynBase *type = ParseType(ctx)) { - if(!CheckAt(ctx, lex_string, "ERROR: class member name expected after type")) + if(!CheckAt(ctx, lex_identifier, "ERROR: class member name expected after type")) { // Backtrack ctx.currentLexeme = start; @@ -2408,7 +2408,7 @@ SynAccessor* ParseAccessorDefinition(ParseContext &ctx) { if(ctx.Consume(lex_oparen)) { - if(CheckAt(ctx, lex_string, "ERROR: r-value name not found after '('")) + if(CheckAt(ctx, lex_identifier, "ERROR: r-value name not found after '('")) { InplaceStr setName = ctx.Consume(); setNameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), setName); @@ -2458,7 +2458,7 @@ SynConstantSet* ParseConstantSet(ParseContext &ctx) SynIdentifier *nameIdentifier = NULL; - if(CheckAt(ctx, lex_string, "ERROR: constant name expected after type")) + if(CheckAt(ctx, lex_identifier, "ERROR: constant name expected after type")) { InplaceStr name = ctx.Consume(); nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2487,7 +2487,7 @@ SynConstantSet* ParseConstantSet(ParseContext &ctx) { pos = ctx.currentLexeme; - if(CheckAt(ctx, lex_string, "ERROR: constant name expected after ','")) + if(CheckAt(ctx, lex_identifier, "ERROR: constant name expected after ','")) { InplaceStr name = ctx.Consume(); nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2597,7 +2597,7 @@ SynFunctionArgument* ParseFunctionArgument(ParseContext &ctx, bool lastExplicit, if(SynBase *type = ParseType(ctx)) { - if(!ctx.At(lex_string) && lastType) + if(!ctx.At(lex_identifier) && lastType) { if(isExplicit) Stop(ctx, ctx.Current(), "ERROR: variable name not found after type in function variable list"); @@ -2611,7 +2611,7 @@ SynFunctionArgument* ParseFunctionArgument(ParseContext &ctx, bool lastExplicit, SynIdentifier *nameIdentifier = NULL; - if(CheckAt(ctx, lex_string, "ERROR: variable name not found after type in function variable list")) + if(CheckAt(ctx, lex_identifier, "ERROR: variable name not found after type in function variable list")) { InplaceStr name = ctx.Consume(); nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2738,7 +2738,7 @@ SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) Stop(ctx, ctx.Current(), "ERROR: invalid operator name"); } } - else if(ctx.At(lex_string)) + else if(ctx.At(lex_identifier)) { InplaceStr name = ctx.Consume(); nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2763,7 +2763,7 @@ SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) else CheckConsume(ctx, lex_at, "ERROR: '@' is expected after ',' in explicit generic type alias list"); - if(CheckAt(ctx, lex_string, "ERROR: explicit generic type alias is expected after '@'")) + if(CheckAt(ctx, lex_identifier, "ERROR: explicit generic type alias is expected after '@'")) { InplaceStr name = ctx.Consume(); aliases.push_back(new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name)); @@ -2842,7 +2842,7 @@ SynShortFunctionDefinition* ParseShortFunctionDefinition(ParseContext &ctx) SynBase *type = ParseType(ctx); - if(!ctx.At(lex_string)) + if(!ctx.At(lex_identifier)) { // Backtrack ctx.currentLexeme = lexeme; @@ -2853,9 +2853,9 @@ SynShortFunctionDefinition* ParseShortFunctionDefinition(ParseContext &ctx) bool hasName = false; if(arguments.empty()) - hasName = CheckAt(ctx, lex_string, "ERROR: function argument name not found after '<'"); + hasName = CheckAt(ctx, lex_identifier, "ERROR: function argument name not found after '<'"); else - hasName = CheckAt(ctx, lex_string, "ERROR: function argument name not found after ','"); + hasName = CheckAt(ctx, lex_identifier, "ERROR: function argument name not found after ','"); SynIdentifier *nameIdentifier = NULL; @@ -3108,7 +3108,7 @@ SynModuleImport* ParseImport(ParseContext &ctx) { IntrusiveList path; - if(CheckAt(ctx, lex_string, "ERROR: name expected after import")) + if(CheckAt(ctx, lex_identifier, "ERROR: name expected after import")) { InplaceStr value = ctx.Consume(); path.push_back(new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), value)); @@ -3116,7 +3116,7 @@ SynModuleImport* ParseImport(ParseContext &ctx) while(ctx.Consume(lex_point)) { - if(CheckAt(ctx, lex_string, "ERROR: name expected after '.'")) + if(CheckAt(ctx, lex_identifier, "ERROR: name expected after '.'")) { InplaceStr value = ctx.Consume(); path.push_back(new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), value)); diff --git a/external/pugixml/pugixml.cpp b/external/pugixml/pugixml.cpp index b916e5ec2..f634ac692 100644 --- a/external/pugixml/pugixml.cpp +++ b/external/pugixml/pugixml.cpp @@ -6328,7 +6328,7 @@ namespace lex_double_slash, lex_open_square_brace, lex_close_square_brace, - lex_string, + lex_identifier, lex_comma, lex_axis_attribute, lex_dot, @@ -6631,7 +6631,7 @@ namespace _cur_lexeme_contents.end = cur; - _cur_lexeme = lex_string; + _cur_lexeme = lex_identifier; } else { @@ -6654,7 +6654,7 @@ namespace const xpath_lexer_string& contents() const { - assert(_cur_lexeme == lex_var_ref || _cur_lexeme == lex_number || _cur_lexeme == lex_string || _cur_lexeme == lex_quoted_string); + assert(_cur_lexeme == lex_var_ref || _cur_lexeme == lex_number || _cur_lexeme == lex_identifier || _cur_lexeme == lex_quoted_string); return _cur_lexeme_contents; } @@ -8431,7 +8431,7 @@ namespace return n; } - case lex_string: + case lex_identifier: { xpath_ast_node* args[2] = {0}; size_t argc = 0; @@ -8539,7 +8539,7 @@ namespace nodetest_t nt_type = nodetest_none; xpath_lexer_string nt_name; - if (_lexer.current() == lex_string) + if (_lexer.current() == lex_identifier) { // node name test nt_name = _lexer.contents(); @@ -8564,7 +8564,7 @@ namespace nt_name = xpath_lexer_string(); _lexer.next(); } - else if (_lexer.current() == lex_string) + else if (_lexer.current() == lex_identifier) { nt_name = _lexer.contents(); _lexer.next(); @@ -8683,7 +8683,7 @@ namespace // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path lexeme_t l = _lexer.current(); - if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply) + if (l == lex_identifier || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply) return parse_relative_location_path(n); else return n; @@ -8717,9 +8717,9 @@ namespace if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || _lexer.current() == lex_quoted_string || _lexer.current() == lex_number || - _lexer.current() == lex_string) + _lexer.current() == lex_identifier) { - if (_lexer.current() == lex_string) + if (_lexer.current() == lex_identifier) { // This is either a function call, or not - if not, we shall proceed with location path const char_t* state = _lexer.state(); @@ -8797,7 +8797,7 @@ namespace { xpath_ast_node* n = parse_unary_expression(); - while (_lexer.current() == lex_multiply || (_lexer.current() == lex_string && + while (_lexer.current() == lex_multiply || (_lexer.current() == lex_identifier && (_lexer.contents() == PUGIXML_TEXT("mod") || _lexer.contents() == PUGIXML_TEXT("div")))) { ast_type_t op = _lexer.current() == lex_multiply ? ast_op_multiply : @@ -8883,7 +8883,7 @@ namespace { xpath_ast_node* n = parse_equality_expression(); - while (_lexer.current() == lex_string && _lexer.contents() == PUGIXML_TEXT("and")) + while (_lexer.current() == lex_identifier && _lexer.contents() == PUGIXML_TEXT("and")) { _lexer.next(); @@ -8900,7 +8900,7 @@ namespace { xpath_ast_node* n = parse_and_expression(); - while (_lexer.current() == lex_string && _lexer.contents() == PUGIXML_TEXT("or")) + while (_lexer.current() == lex_identifier && _lexer.contents() == PUGIXML_TEXT("or")) { _lexer.next(); diff --git a/tests/nullc_in_nullc/lexer.nc b/tests/nullc_in_nullc/lexer.nc index f1fec0a21..c59c00a26 100644 --- a/tests/nullc_in_nullc/lexer.nc +++ b/tests/nullc_in_nullc/lexer.nc @@ -27,7 +27,7 @@ short[256] chartype_table = 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192 }; -/* +/* block comment */ @@ -39,7 +39,7 @@ bool isDigit(char data) enum LexemeType { lex_none, - lex_number, lex_string, lex_quotedstring, // *(0-9) *(a-z,A-Z,_) "*any" + lex_number, lex_identifier, lex_quotedstring, // *(0-9) *(a-z,A-Z,_) "*any" lex_semiquotedchar, lex_point, lex_comma, // ' . lex_inc, lex_dec, // ++ -- lex_add, lex_sub, lex_mul, lex_div, lex_mod, lex_pow, lex_less, lex_lequal, lex_shl, lex_greater, lex_gequal, lex_shr, lex_equal, lex_nequal, // + - * / % ** < <= << > >= >> == != @@ -68,7 +68,7 @@ class Lexeme class Lexer { char[] code; - + vector lexems; } @@ -149,14 +149,14 @@ void Lexer:Clear(int count) void Lexer:Lexify(char[] code) { this.code = code; - + lexems.reserve(2048); LexemeType lType = LexemeType.lex_none; int lLength = 1; int curr = 0; - + while(curr < code.size) { switch(code[curr]) @@ -536,7 +536,7 @@ void Lexer:Lexify(char[] code) } if(lType == LexemeType.lex_none) - lType = LexemeType.lex_string; + lType = LexemeType.lex_identifier; } } Lexeme lex; diff --git a/tests/nullc_in_nullc/parser.nc b/tests/nullc_in_nullc/parser.nc index 7fcb32564..89707647d 100644 --- a/tests/nullc_in_nullc/parser.nc +++ b/tests/nullc_in_nullc/parser.nc @@ -397,7 +397,7 @@ SynBase ref ParseTerminalType(ParseContext ref ctx, bool ref shrBorrow) { LexemeRef start = ctx.currentLexeme; - if(ctx.At(LexemeType.lex_string)) + if(ctx.At(LexemeType.lex_identifier)) { InplaceStr name = ctx.Consume(); @@ -409,7 +409,7 @@ SynBase ref ParseTerminalType(ParseContext ref ctx, bool ref shrBorrow) { ctx.Skip(); - if(!CheckAt(ctx, LexemeType.lex_string, "ERROR: namespace member is expected after '.'")) + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: namespace member is expected after '.'")) { namespacePath.push_back(new SynIdentifier(start, ctx.Previous(), name)); @@ -515,7 +515,7 @@ SynBase ref ParseTerminalType(ParseContext ref ctx, bool ref shrBorrow) if(ctx.Consume(LexemeType.lex_at)) { - if(!ctx.At(LexemeType.lex_string)) + if(!ctx.At(LexemeType.lex_identifier)) { // Backtrack ctx.currentLexeme = start; @@ -542,7 +542,7 @@ SynBase ref ParseType(ParseContext ref ctx, bool ref shrBorrow = nullptr, bool o bool shrBorrowTerminal = shrBorrow ? *shrBorrow : false; SynBase ref base = ParseTerminalType(ctx, shrBorrowTerminal); - + if(!base) return nullptr; @@ -758,7 +758,7 @@ SynNumber ref ParseNumber(ParseContext ref ctx) InplaceStr suffix; - if(ctx.At(LexemeType.lex_string)) + if(ctx.At(LexemeType.lex_identifier)) suffix = ctx.Consume(); return new SynNumber(start, ctx.Previous(), value, suffix); @@ -898,7 +898,7 @@ SynCallArgument ref ParseCallArgument(ParseContext ref ctx) { LexemeRef start = ctx.currentLexeme; - if(ctx.At(LexemeType.lex_string)) + if(ctx.At(LexemeType.lex_identifier)) { InplaceStr name = ctx.Consume(); SynIdentifier ref nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -977,7 +977,7 @@ SynBase ref ParsePostExpressions(ParseContext ref ctx, SynBase ref node) if(ctx.Consume(LexemeType.lex_point)) { - if(ctx.At(LexemeType.lex_return) || CheckAt(ctx, LexemeType.lex_string, "ERROR: member name expected after '.'")) + if(ctx.At(LexemeType.lex_return) || CheckAt(ctx, LexemeType.lex_identifier, "ERROR: member name expected after '.'")) { InplaceStr member = ctx.Consume(); SynIdentifier ref memberIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), member); @@ -1110,7 +1110,7 @@ SynBase ref ParseComplexTerminal(ParseContext ref ctx) if(!node) node = ParseType(ctx); - if(!node && ctx.At(LexemeType.lex_string)) + if(!node && ctx.At(LexemeType.lex_identifier)) { InplaceStr value = ctx.Consume(); @@ -1135,7 +1135,7 @@ SynBase ref ParseComplexTerminal(ParseContext ref ctx) if(!node) return nullptr; - + return ParsePostExpressions(ctx, node); } @@ -1433,7 +1433,7 @@ SynBase ref ParseClassDefinition(ParseContext ref ctx) { SynIdentifier ref nameIdentifier = nullptr; - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: class name expected")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: class name expected")) { InplaceStr name = ctx.Consume(); nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -1455,7 +1455,7 @@ SynBase ref ParseClassDefinition(ParseContext ref ctx) if(ctx.Consume(LexemeType.lex_less)) { - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: generic type alias required after '<'")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: generic type alias required after '<'")) { InplaceStr alias = ctx.Consume(); @@ -1463,7 +1463,7 @@ SynBase ref ParseClassDefinition(ParseContext ref ctx) while(ctx.Consume(LexemeType.lex_comma)) { - if(!CheckAt(ctx, LexemeType.lex_string, "ERROR: generic type alias required after ','")) + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: generic type alias required after ','")) break; alias = ctx.Consume(); @@ -1515,7 +1515,7 @@ SynEnumDefinition ref ParseEnumDefinition(ParseContext ref ctx) { SynIdentifier ref nameIdentifier = nullptr; - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: enum name expected")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: enum name expected")) { InplaceStr name = ctx.Consume(); nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -1533,12 +1533,12 @@ SynEnumDefinition ref ParseEnumDefinition(ParseContext ref ctx) { if(values.empty()) { - if(!CheckAt(ctx, LexemeType.lex_string, "ERROR: enumeration name expected after '{'")) + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: enumeration name expected after '{'")) break; } else { - if(!CheckAt(ctx, LexemeType.lex_string, "ERROR: enumeration name expected after ','")) + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: enumeration name expected after ','")) break; } @@ -1581,7 +1581,7 @@ SynNamespaceDefinition ref ParseNamespaceDefinition(ParseContext ref ctx) { RefList path; - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: namespace name required")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: namespace name required")) { InplaceStr value = ctx.Consume(); path.push_back(new SynIdentifier(ctx.Previous(), ctx.Previous(), value)); @@ -1589,7 +1589,7 @@ SynNamespaceDefinition ref ParseNamespaceDefinition(ParseContext ref ctx) while(ctx.Consume(LexemeType.lex_point)) { - if(!CheckAt(ctx, LexemeType.lex_string, "ERROR: namespace name required after '.'")) + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: namespace name required after '.'")) break; InplaceStr value = ctx.Consume(); @@ -1700,7 +1700,7 @@ SynTypedef ref ParseTypedef(ParseContext ref ctx) SynIdentifier ref aliasIdentifier = nullptr; - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: alias name expected after typename in typedef expression")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: alias name expected after typename in typedef expression")) { InplaceStr alias = ctx.Consume(); aliasIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), alias); @@ -1840,7 +1840,7 @@ SynForEachIterator ref ParseForEachIterator(ParseContext ref ctx, bool isFirst) SynBase ref type = ParseType(ctx); // Must be followed by a type - if(!ctx.At(LexemeType.lex_string)) + if(!ctx.At(LexemeType.lex_identifier)) { // Backtrack ctx.currentLexeme = start; @@ -1848,7 +1848,7 @@ SynForEachIterator ref ParseForEachIterator(ParseContext ref ctx, bool isFirst) type = nullptr; } - if(ctx.At(LexemeType.lex_string)) + if(ctx.At(LexemeType.lex_identifier)) { InplaceStr name = ctx.Consume(); SynIdentifier ref nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2149,7 +2149,7 @@ SynVariableDefinition ref ParseVariableDefinition(ParseContext ref ctx) { LexemeRef start = ctx.currentLexeme; - if(ctx.At(LexemeType.lex_string)) + if(ctx.At(LexemeType.lex_identifier)) { InplaceStr name = ctx.Consume(); SynIdentifier ref nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2233,7 +2233,7 @@ SynVariableDefinitions ref ParseVariableDefinitions(ParseContext ref ctx, bool c return new SynVariableDefinitions(start, ctx.Previous(), alignment, type, definitions); } - + // Backtrack ctx.currentLexeme = start; @@ -2246,7 +2246,7 @@ SynAccessor ref ParseAccessorDefinition(ParseContext ref ctx) if(SynBase ref type = ParseType(ctx)) { - if(!CheckAt(ctx, LexemeType.lex_string, "ERROR: class member name expected after type")) + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: class member name expected after type")) { // Backtrack ctx.currentLexeme = start; @@ -2283,7 +2283,7 @@ SynAccessor ref ParseAccessorDefinition(ParseContext ref ctx) { if(ctx.Consume(LexemeType.lex_oparen)) { - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: r-value name not found after '('")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: r-value name not found after '('")) { InplaceStr setName = ctx.Consume(); setNameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), setName); @@ -2333,7 +2333,7 @@ SynConstantSet ref ParseConstantSet(ParseContext ref ctx) SynIdentifier ref nameIdentifier = nullptr; - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: constant name expected after type")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: constant name expected after type")) { InplaceStr name = ctx.Consume(); nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2362,7 +2362,7 @@ SynConstantSet ref ParseConstantSet(ParseContext ref ctx) { pos = ctx.currentLexeme; - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: constant name expected after ','")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: constant name expected after ','")) { InplaceStr name = ctx.Consume(); nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2472,7 +2472,7 @@ SynFunctionArgument ref ParseFunctionArgument(ParseContext ref ctx, bool lastExp if(SynBase ref type = ParseType(ctx)) { - if(!ctx.At(LexemeType.lex_string) && lastType) + if(!ctx.At(LexemeType.lex_identifier) && lastType) { if(isExplicit) Stop(ctx, ctx.Current(), "ERROR: variable name not found after type in function variable list"); @@ -2486,7 +2486,7 @@ SynFunctionArgument ref ParseFunctionArgument(ParseContext ref ctx, bool lastExp SynIdentifier ref nameIdentifier = nullptr; - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: variable name not found after type in function variable list")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: variable name not found after type in function variable list")) { InplaceStr name = ctx.Consume(); nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2613,7 +2613,7 @@ SynFunctionDefinition ref ParseFunctionDefinition(ParseContext ref ctx) Stop(ctx, ctx.Current(), "ERROR: invalid operator name"); } } - else if(ctx.At(LexemeType.lex_string)) + else if(ctx.At(LexemeType.lex_identifier)) { InplaceStr name = ctx.Consume(); nameIdentifier = new SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -2638,7 +2638,7 @@ SynFunctionDefinition ref ParseFunctionDefinition(ParseContext ref ctx) else CheckConsume(ctx, LexemeType.lex_at, "ERROR: '@' is expected after ',' in explicit generic type alias list"); - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: explicit generic type alias is expected after '@'")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: explicit generic type alias is expected after '@'")) { InplaceStr name = ctx.Consume(); aliases.push_back(new SynIdentifier(ctx.Previous(), ctx.Previous(), name)); @@ -2717,7 +2717,7 @@ SynShortFunctionDefinition ref ParseShortFunctionDefinition(ParseContext ref ctx SynBase ref type = ParseType(ctx); - if(!ctx.At(LexemeType.lex_string)) + if(!ctx.At(LexemeType.lex_identifier)) { // Backtrack ctx.currentLexeme = lexeme; @@ -2728,9 +2728,9 @@ SynShortFunctionDefinition ref ParseShortFunctionDefinition(ParseContext ref ctx bool hasName = false; if(arguments.empty()) - hasName = CheckAt(ctx, LexemeType.lex_string, "ERROR: function argument name not found after '<'"); + hasName = CheckAt(ctx, LexemeType.lex_identifier, "ERROR: function argument name not found after '<'"); else - hasName = CheckAt(ctx, LexemeType.lex_string, "ERROR: function argument name not found after ','"); + hasName = CheckAt(ctx, LexemeType.lex_identifier, "ERROR: function argument name not found after ','"); SynIdentifier ref nameIdentifier = nullptr; @@ -2948,7 +2948,7 @@ SynModuleImport ref ParseImport(ParseContext ref ctx) { RefList path; - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: name expected after import")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: name expected after import")) { InplaceStr value = ctx.Consume(); path.push_back(new SynIdentifier(ctx.Previous(), ctx.Previous(), value)); @@ -2956,7 +2956,7 @@ SynModuleImport ref ParseImport(ParseContext ref ctx) while(ctx.Consume(LexemeType.lex_point)) { - if(CheckAt(ctx, LexemeType.lex_string, "ERROR: name expected after '.'")) + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: name expected after '.'")) { InplaceStr value = ctx.Consume(); path.push_back(new SynIdentifier(ctx.Previous(), ctx.Previous(), value)); From c461e7f696bb0d6e084a6f4ccf6ec4a732fde793 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 6 Jan 2022 12:31:22 +0100 Subject: [PATCH 04/20] Small modification of REGISTER_FUNC macro to simplify it's usage here --- NULLC/includes/string.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/NULLC/includes/string.cpp b/NULLC/includes/string.cpp index 849ac1976..09c5fedc4 100644 --- a/NULLC/includes/string.cpp +++ b/NULLC/includes/string.cpp @@ -145,14 +145,14 @@ namespace NULLCString } } -#define REGISTER_FUNC(funcPtr, name, index) if(!nullcBindModuleFunctionHelper("std.string", NULLCString::funcPtr, name, index)) return false; +#define REGISTER_FUNC(name, index) if(!nullcBindModuleFunctionHelper("std.string", NULLCString::name, #name, index)) return false; bool nullcInitStringModule() { - REGISTER_FUNC(strlen, "strlen", 0); - REGISTER_FUNC(strstr, "strstr", 0); - REGISTER_FUNC(strchr, "strchr", 0); - REGISTER_FUNC(strcmp, "strcmp", 0); - REGISTER_FUNC(strcpy, "strcpy", 0); + REGISTER_FUNC(strlen, 0); + REGISTER_FUNC(strstr, 0); + REGISTER_FUNC(strchr, 0); + REGISTER_FUNC(strcmp, 0); + REGISTER_FUNC(strcpy, 0); return true; } From abdd0217564e573325bdd6603a97de46a0bef6da Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 27 Sep 2022 18:12:25 +0200 Subject: [PATCH 05/20] Allow to build without link to libstdc++ --- Makefile | 15 ++++++++++---- NULLC/stdafx.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index bc2ade907..d2f936793 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,13 @@ config=debug check=none -REG_CFLAGS=-g -Wall -Wextra -COMP_CFLAGS=-g -Wall -Wextra -D NULLC_NO_EXECUTOR -DYNCALL_FLAGS=-g -Wall -Wextra -STDLIB_FLAGS=-lstdc++ -lm +CXXFLAGS=-fno-exceptions -fno-rtti -fno-threadsafe-statics + +REG_CFLAGS=-g -Wall -Wextra $(CXXFLAGS) +COMP_CFLAGS=-g -Wall -Wextra $(CXXFLAGS) -D NULLC_NO_EXECUTOR +DYNCALL_FLAGS=-g -Wall -Wextra $(CXXFLAGS) +#STDLIB_FLAGS=-lstdc++ -lm +STDLIB_FLAGS=-lm FUZZ_FLAGS= ALIGN_FLAGS= @@ -129,6 +132,7 @@ STDLIB_TARGETS = \ temp/lib/pugi.o \ temp/lib/random.o \ temp/lib/string.o \ + temp/lib/lua-regex.o \ temp/lib/time.o \ temp/lib/typeinfo.o \ temp/lib/vector.o \ @@ -163,6 +167,9 @@ endif temp/lib/%.o: NULLC/includes/%.cpp $(CXX) $(REG_CFLAGS) -c $< -o $@ +temp/lib/lua-regex.o: NULLC/includes/lua-regex.c + $(CXX) $(REG_CFLAGS) -c $< -o $@ + ${LIB_TARGETS}: ${LIB_SOURCES} $(CXX) $(REG_CFLAGS) -c $(@:temp/%.o=NULLC/%.cpp) -o $@ diff --git a/NULLC/stdafx.cpp b/NULLC/stdafx.cpp index aa1dad488..87040e735 100644 --- a/NULLC/stdafx.cpp +++ b/NULLC/stdafx.cpp @@ -2,7 +2,7 @@ void* NULLC::defaultAlloc(int size) { - return ::new(std::nothrow) char[size]; + return ::new/*(std::nothrow)*/ char[size]; } void NULLC::defaultDealloc(void* ptr) { @@ -78,3 +78,54 @@ void NULLC::defaultFileFree(const char* data) const char* (*NULLC::fileLoad)(const char*, unsigned*) = NULLC::defaultFileLoad; void (*NULLC::fileFree)(const char*) = NULLC::defaultFileFree; + +#ifndef WITH_STDCPP_LIB +/* +This code is to have an executable without libstd++ library dependency +g++ -g -Wall -fno-rtti -fno-exceptions *.cpp -o YourParser + */ + +// MSVC uses __cdecl calling convention for new/delete :-O +#ifdef _MSC_VER +# define NEWDECL_CALL __cdecl +#else +# define NEWDECL_CALL +#endif + +extern "C" void __cxa_pure_virtual () +{ + puts("__cxa_pure_virtual called\n"); + abort (); +} + +void * NEWDECL_CALL operator new (size_t size) +{ + void *p = malloc (size); + if(!p) + { + puts("not enough memory\n"); + abort (); + } + return p; +} + +void * NEWDECL_CALL operator new [] (size_t size) +{ + return ::operator new(size); +} + +void NEWDECL_CALL operator delete (void *p) +{ + if (p) free (p); +} + +void NEWDECL_CALL operator delete [] (void *p) +{ + if (p) free (p); +} + +void NEWDECL_CALL operator delete (void *p, size_t) +{ + if (p) free (p); +} +#endif //WITH_STDCPP_LIB From 5373cb0a0df52df048ae4c79aa56f4b201a8bac3 Mon Sep 17 00:00:00 2001 From: mingodad Date: Wed, 28 Sep 2022 14:46:18 +0200 Subject: [PATCH 06/20] Add a wrapper to allow silency warnings --- external/rapidjson/document.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/external/rapidjson/document.h b/external/rapidjson/document.h index e3e20dfbd..66a07b5c0 100644 --- a/external/rapidjson/document.h +++ b/external/rapidjson/document.h @@ -52,6 +52,14 @@ RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_N #include // std::move #endif +#ifdef NO_MEMSET_WRAPPER +#define RAPIDJSON_no_warning_memset(dest, ch, sz) memset(dest, ch, sz) +#define RAPIDJSON_no_warning_memcpy(dest, src, sz) memcpy(dest, src, sz) +#else +inline void RAPIDJSON_no_warning_memset(void *dest, int ch, size_t sz) {memset(dest, ch, sz);} +inline void RAPIDJSON_no_warning_memcpy(void *dest, void *src, size_t sz) {memcpy(dest, src, sz);} +#endif + RAPIDJSON_NAMESPACE_BEGIN // Forward declaration. @@ -1936,7 +1944,7 @@ class GenericValue { if (count) { GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); SetElementsPointer(e); - std::memcpy(e, values, count * sizeof(GenericValue)); + RAPIDJSON_no_warning_memcpy(e, values, count * sizeof(GenericValue)); } else SetElementsPointer(0); @@ -1949,7 +1957,7 @@ class GenericValue { if (count) { Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); SetMembersPointer(m); - std::memcpy(m, members, count * sizeof(Member)); + RAPIDJSON_no_warning_memcpy(m, members, count * sizeof(Member)); } else SetMembersPointer(0); From 86a9e81bccddc6f2d5528d9ac6be384eaeb95280 Mon Sep 17 00:00:00 2001 From: mingodad Date: Wed, 28 Sep 2022 14:46:44 +0200 Subject: [PATCH 07/20] Add the missing math lib command line --- nullcl/main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nullcl/main.cpp b/nullcl/main.cpp index cf9da0d17..8c78c855b 100644 --- a/nullcl/main.cpp +++ b/nullcl/main.cpp @@ -195,7 +195,10 @@ int main(int argc, char** argv) printf("Failed to find '%s' input file", tmp); } } - + + strcpy(pos, " -lm"); + pos += strlen(pos); + if (verbose) printf("Command line: %s\n", cmdLine); @@ -324,5 +327,5 @@ int main(int argc, char** argv) nullcTerminate(); - return argIndex != argc; + return argIndex != argc; } From ea465c20bf6c6e07ae333e3f75793fa2c3c0829e Mon Sep 17 00:00:00 2001 From: mingodad Date: Wed, 28 Sep 2022 14:47:57 +0200 Subject: [PATCH 08/20] Add a conditional wrapper for msvc compiler pragmas --- vscode/nullc_lang_debugger/handler.cpp | 2 ++ vscode/nullc_lang_debugger/main.cpp | 2 ++ vscode/nullc_lang_server/main.cpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/vscode/nullc_lang_debugger/handler.cpp b/vscode/nullc_lang_debugger/handler.cpp index 644272314..b778ad035 100644 --- a/vscode/nullc_lang_debugger/handler.cpp +++ b/vscode/nullc_lang_debugger/handler.cpp @@ -1,6 +1,8 @@ #include "handler.h" +#ifdef _MSC_VER #pragma warning(disable: 4996) +#endif #include diff --git a/vscode/nullc_lang_debugger/main.cpp b/vscode/nullc_lang_debugger/main.cpp index 06a58a319..240d6fe3b 100644 --- a/vscode/nullc_lang_debugger/main.cpp +++ b/vscode/nullc_lang_debugger/main.cpp @@ -15,7 +15,9 @@ #include "context.h" #include "handler.h" +#ifdef _MSC_VER #pragma warning(disable: 4996) +#endif int main(int argc, char **argv) { diff --git a/vscode/nullc_lang_server/main.cpp b/vscode/nullc_lang_server/main.cpp index f4c7f71a5..3e22abce9 100644 --- a/vscode/nullc_lang_server/main.cpp +++ b/vscode/nullc_lang_server/main.cpp @@ -15,7 +15,9 @@ #include "context.h" #include "handler.h" +#ifdef _MSC_VER #pragma warning(disable: 4996) +#endif int main(int argc, char **argv) { From c55283546b724a7d0d26012806c04688d54f7a1e Mon Sep 17 00:00:00 2001 From: mingodad Date: Wed, 28 Sep 2022 19:00:45 +0200 Subject: [PATCH 09/20] Change class member declarator separator from ':' to '::' --- Makefile | 8 +- Modules/img/canvas.nc | 20 +- Modules/old/list.nc | 28 +- Modules/old/vector.nc | 28 +- Modules/std/error.nc | 2 +- Modules/std/event.nc | 6 +- Modules/std/file.nc | 48 +- Modules/std/hashmap.nc | 10 +- Modules/std/list.nc | 56 +- Modules/std/math.nc | 12 +- Modules/std/range.nc | 6 +- Modules/std/string.nc | 76 +-- Modules/std/typeinfo.nc | 40 +- Modules/std/vector.nc | 68 +-- Modules/win/window.nc | 16 +- NULLC/Compiler.cpp | 26 +- NULLC/Lexer.cpp | 7 +- NULLC/Lexer.h | 2 +- NULLC/ParseTree.cpp | 2 +- NULLC/includes/lua-regex.c | 619 ++++++++++++++++++++++ NULLC/includes/lua-regex.h | 89 ++++ NULLC/includes/string.cpp | 46 ++ NULLC/stdafx.cpp | 5 + tests/TestAccessors.cpp | 2 +- tests/TestAutoRefCall.cpp | 18 +- tests/TestClasses.cpp | 38 +- tests/TestClosures.cpp | 2 +- tests/TestCompileFail.cpp | 68 +-- tests/TestConversions.cpp | 2 +- tests/TestCoroutine.cpp | 2 +- tests/TestDefault.cpp | 4 +- tests/TestExternalCallInt.h | 2 +- tests/TestExtra.cpp | 4 +- tests/TestFinalizer.cpp | 22 +- tests/TestForEach.cpp | 12 +- tests/TestFromReference.cpp | 6 +- tests/TestGC.cpp | 2 +- tests/TestGeneric.cpp | 6 +- tests/TestGenericType.cpp | 154 +++--- tests/TestIndirectCall.cpp | 4 +- tests/TestInference.cpp | 16 +- tests/TestInheritance.cpp | 4 +- tests/TestListComprehension.cpp | 2 +- tests/TestLocalClass.cpp | 8 +- tests/TestMembers.cpp | 6 +- tests/TestMisc.cpp | 4 +- tests/TestNamespace.cpp | 6 +- tests/TestNew.cpp | 6 +- tests/TestPostExpr.cpp | 2 +- tests/TestRuntimeFail.cpp | 2 +- tests/TestScope.cpp | 4 +- tests/TestSglList.cpp | 34 +- tests/TestSpecial.cpp | 12 +- tests/TestSpeed.cpp | 4 +- tests/nullc_in_nullc/analyzer.nc | 10 +- tests/nullc_in_nullc/arrayview.nc | 4 +- tests/nullc_in_nullc/common.nc | 18 +- tests/nullc_in_nullc/compiler.nc | 26 +- tests/nullc_in_nullc/expressioncontext.nc | 86 +-- tests/nullc_in_nullc/lexer.nc | 14 +- tests/nullc_in_nullc/parser.nc | 44 +- tests/nullc_in_nullc/reflist.nc | 2 +- tests/nullc_in_nullc/stringutil.nc | 2 +- tests/run-it | 2 + 64 files changed, 1330 insertions(+), 556 deletions(-) create mode 100644 NULLC/includes/lua-regex.c create mode 100644 NULLC/includes/lua-regex.h create mode 100755 tests/run-it diff --git a/Makefile b/Makefile index d2f936793..ba88378f8 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,8 @@ config=debug check=none CXXFLAGS=-fno-exceptions -fno-rtti -fno-threadsafe-statics +OPTFLAGS=-O2 -pipe +#OPTFLAGS=-Os -pipe REG_CFLAGS=-g -Wall -Wextra $(CXXFLAGS) COMP_CFLAGS=-g -Wall -Wextra $(CXXFLAGS) -D NULLC_NO_EXECUTOR @@ -16,9 +18,9 @@ FUZZ_FLAGS= ALIGN_FLAGS= ifeq ($(config),release) - REG_CFLAGS += -O2 -fno-omit-frame-pointer -DNDEBUG - COMP_CFLAGS += -O2 -fno-omit-frame-pointer -DNDEBUG - DYNCALL_FLAGS += -O2 -fno-omit-frame-pointer -DNDEBUG + REG_CFLAGS += $(OPTFLAGS) -fno-omit-frame-pointer -DNDEBUG + COMP_CFLAGS += $(OPTFLAGS) -fno-omit-frame-pointer -DNDEBUG + DYNCALL_FLAGS += $(OPTFLAGS) -fno-omit-frame-pointer -DNDEBUG endif ifeq ($(config),coverage) diff --git a/Modules/img/canvas.nc b/Modules/img/canvas.nc index c681dd668..1dbfdf271 100644 --- a/Modules/img/canvas.nc +++ b/Modules/img/canvas.nc @@ -22,19 +22,19 @@ Canvas Canvas(int width, height) return ret; } -void Canvas:Clear(float red, green, blue); -void Canvas:Clear(float red, green, blue, alpha); +void Canvas::Clear(float red, green, blue); +void Canvas::Clear(float red, green, blue, alpha); -void Canvas:SetColor(char red, green, blue); -void Canvas:SetAA(bool enable); +void Canvas::SetColor(char red, green, blue); +void Canvas::SetAA(bool enable); -void Canvas:DrawLine(double x1, y1, x2, y2); -void Canvas:DrawRect(int x1, y1, x2, y2); -void Canvas:DrawRect(int x1, y1, x2, y2, double alpha); -void Canvas:DrawPoint(double x, y); -void Canvas:DrawPoint(double x, y, alpha); +void Canvas::DrawLine(double x1, y1, x2, y2); +void Canvas::DrawRect(int x1, y1, x2, y2); +void Canvas::DrawRect(int x1, y1, x2, y2, double alpha); +void Canvas::DrawPoint(double x, y); +void Canvas::DrawPoint(double x, y, alpha); -float[] Canvas:GetData() +float[] Canvas::GetData() { return data; } diff --git a/Modules/old/list.nc b/Modules/old/list.nc index 50166eb5a..d194c634d 100644 --- a/Modules/old/list.nc +++ b/Modules/old/list.nc @@ -29,7 +29,7 @@ auto ref list_node.value(auto ref val) return elem = duplicate(val); } -void list:list(typeid type = auto ref) +void list::list(typeid type = auto ref) { anyType = type == auto ref; elemType = type; @@ -43,7 +43,7 @@ list list(typeid type = auto ref) return ret; } -void list:push_back(auto ref elem) +void list::push_back(auto ref elem) { if(!anyType && typeid(elem) != (isPointer(elemType) ? elemType.subType() : elemType)) assert(0, "list::push_back argument type (" + typeid(elem).name + ") differs from list element type (" + elemType.name + ")"); @@ -61,7 +61,7 @@ void list:push_back(auto ref elem) } last.parent = this; } -void list:push_front(auto ref elem) +void list::push_front(auto ref elem) { if(!anyType && typeid(elem) != elemType) assert(0, "list::push_front argument type (" + typeid(elem).name + ") differs from list element type (" + elemType.name + ")"); @@ -79,7 +79,7 @@ void list:push_front(auto ref elem) } last.parent = this; } -void list:insert(list_node ref it, auto ref elem) +void list::insert(list_node ref it, auto ref elem) { if(!anyType && typeid(elem) != elemType) assert(0, "list::insert argument type (" + typeid(elem).name + ") differs from list element type (" + elemType.name + ")"); @@ -94,7 +94,7 @@ void list:insert(list_node ref it, auto ref elem) if(next) next.prev = it.next; } -void list:erase(list_node ref it) +void list::erase(list_node ref it) { if(list ref(it.parent) != this) assert(0, "list::insert iterator is from a different list"); @@ -108,29 +108,29 @@ void list:erase(list_node ref it) if(it == last) last = last.prev; } -void list:clear() +void list::clear() { first = last = nullptr; } -auto ref list:back() +auto ref list::back() { assert(first != nullptr, "list::back called on empty list"); return last.elem; } -auto ref list:front() +auto ref list::front() { assert(first != nullptr, "list::front called on empty list"); return first.elem; } -auto list:begin() +auto list::begin() { return first; } -auto list:end() +auto list::end() { return last; } -int list:empty() +int list::empty() { return first == nullptr; } @@ -146,17 +146,17 @@ auto list_iterator(list_node ref start) ret.curr = start; return ret; } -auto list:start() +auto list::start() { return list_iterator(this.first); } -auto list_iterator:next() +auto list_iterator::next() { auto ref ret = curr.elem; curr = curr.next; return ret; } -auto list_iterator:hasnext() +auto list_iterator::hasnext() { return curr ? 1 : 0; } diff --git a/Modules/old/vector.nc b/Modules/old/vector.nc index 546209709..42271f583 100644 --- a/Modules/old/vector.nc +++ b/Modules/old/vector.nc @@ -18,7 +18,7 @@ vector vector(typeid type, int reserved = 0) cConstructVector(ret, type, reserved); return ret; } -void vector:vector(typeid type, int reserved = 0) +void vector::vector(typeid type, int reserved = 0) { cConstructVector(this, type, reserved); } @@ -28,24 +28,24 @@ class vector_iterator vector ref arr; int pos; } -auto vector:start() +auto vector::start() { vector_iterator iter; iter.arr = this; iter.pos = 0; return iter; } -auto ref vector_iterator:next(); -int vector_iterator:hasnext(); +auto ref vector_iterator::next(); +int vector_iterator::hasnext(); -void vector:push_back(auto ref val); -void vector:pop_back(); -auto ref vector:front(); -auto ref vector:back(); +void vector::push_back(auto ref val); +void vector::pop_back(); +auto ref vector::front(); +auto ref vector::back(); auto ref operator[](vector ref v, int index); -void vector:reserve(int size); -void vector:resize(int size); -void vector:clear(); -void vector:destroy(); -int vector:size(); -int vector:capacity(); +void vector::reserve(int size); +void vector::resize(int size); +void vector::clear(); +void vector::destroy(); +int vector::size(); +int vector::capacity(); diff --git a/Modules/std/error.nc b/Modules/std/error.nc index ff3ef8d5c..dd06c86ac 100644 --- a/Modules/std/error.nc +++ b/Modules/std/error.nc @@ -34,7 +34,7 @@ bool try_result.has_error() return message != nullptr; } -void try_result:rethrow() +void try_result::rethrow() { if(exception) throw(exception); diff --git a/Modules/std/event.nc b/Modules/std/event.nc index 7774e5260..1e43f12a6 100644 --- a/Modules/std/event.nc +++ b/Modules/std/event.nc @@ -117,7 +117,7 @@ bool bool(event<@T> ref e) } // Attach the callback to the event (a single callback can be attached only once) -void event:attach(T callback) +void event::attach(T callback) { if(callback in callbacks) return; @@ -130,7 +130,7 @@ void operator+=(event<@T> ref e, @T callback) } // Detach the callback from the event -void event:detach(T callback) +void event::detach(T callback) { auto it = callbacks.find(callback); if(it) @@ -143,7 +143,7 @@ void operator-=(event<@T> ref e, @T callback) } // Detach all callbacks -void event:detach_all() +void event::detach_all() { callbacks.clear(); } diff --git a/Modules/std/file.nc b/Modules/std/file.nc index 4fe8be95f..e3c9506da 100644 --- a/Modules/std/file.nc +++ b/Modules/std/file.nc @@ -19,67 +19,67 @@ File File(char[] name, char[] access); // Open a file with the specified access. Previous file will be closed. // Use Opened function to tell if the operation was successful -void File:Open(char[] name, char[] access); +void File::Open(char[] name, char[] access); // Close the file -void File:Close(); +void File::Close(); // Check if the file is opened -bool File:Opened(); +bool File::Opened(); // Check if the file has ended -bool File:Eof(); +bool File::Eof(); // Seek inside the file from the 3 available origin points -void File:Seek(Seek origin, int shift = 0); +void File::Seek(Seek origin, int shift = 0); // Receive the current position inside the file -long File:Tell(); +long File::Tell(); // Get the file size -long File:Size(); +long File::Size(); // Write a basic type value to the file (binary) // functions returns true on success // if the file was not opened or was closed, these functions will throw an error -bool File:Write(char data); -bool File:Write(short data); -bool File:Write(int data); -bool File:Write(long data); -bool File:Write(float data); -bool File:Write(double data); +bool File::Write(char data); +bool File::Write(short data); +bool File::Write(int data); +bool File::Write(long data); +bool File::Write(float data); +bool File::Write(double data); // Read a basic type value from the file (binary) // functions returns true on success // if the file was not opened or was closed, these functions will throw an error -bool File:Read(char ref data); -bool File:Read(short ref data); -bool File:Read(int ref data); -bool File:Read(long ref data); -bool File:Read(float ref data); -bool File:Read(double ref data); +bool File::Read(char ref data); +bool File::Read(short ref data); +bool File::Read(int ref data); +bool File::Read(long ref data); +bool File::Read(float ref data); +bool File::Read(double ref data); // Read an array of bytes from the file (array size wil tell how many bytes are read) // function returns the number of bytes successfully read // if the file was not opened or was closed, this function will throw an error -int File:Read(char[] arr); +int File::Read(char[] arr); // Write an array of bytes to the file (array size wil tell how many bytes are written) // function returns the number of bytes successfully written // if the file was not opened or was closed, this function will throw an error -int File:Write(char[] arr); +int File::Write(char[] arr); // Print a sequence on bytes to the file, stopping at the zero-termination symbol or at the end of the array // function returns true if the sequence was fully written // if the file was not opened or was closed, this function will throw an error -bool File:Print(char[] arr); +bool File::Print(char[] arr); // Read the specified number of bytes into the array at a specified offset // function returns the number of bytes successfully read // if the array size is not enough to fit the number of bytes from the file at the specified offset, the function will throw an error // if the file was not opened or was closed, this function will throw an error -int File:Read(char[] arr, int offset, int bytes); +int File::Read(char[] arr, int offset, int bytes); // Write the specified number of bytes from the array at a specified offset // function returns the number of bytes successfully written // if the array size is not enough to get the number of bytes from the it at the specified offset, the function will throw an error // if the file was not opened or was closed, this function will throw an error -int File:Write(char[] arr, int offset, int bytes); +int File::Write(char[] arr, int offset, int bytes); diff --git a/Modules/std/hashmap.nc b/Modules/std/hashmap.nc index 74e6ee919..648d493a4 100644 --- a/Modules/std/hashmap.nc +++ b/Modules/std/hashmap.nc @@ -19,18 +19,18 @@ class hashmap int hash_value_default(@Key key){ return hash_value(key); } -void hashmap:hashmap() +void hashmap::hashmap() { entries = new hashmap_node ref[bucketCount]; this.compute_hash = hash_value_default; } -void hashmap:hashmap(int ref(Key) compute_hash) +void hashmap::hashmap(int ref(Key) compute_hash) { entries = new hashmap_node ref[bucketCount]; this.compute_hash = compute_hash; } -void hashmap:clear() +void hashmap::clear() { for(i in entries) i = nullptr; @@ -62,7 +62,7 @@ auto operator[](hashmap<@K, @V> ref m, typeof(m).target.Key key) m.entries[bucket] = n; return &n.value; } -void hashmap:remove(Key key) +void hashmap::remove(Key key) { int hash = compute_hash(key); int bucket = hash & bucketMask; @@ -81,7 +81,7 @@ void hashmap:remove(Key key) entries[bucket] = curr.next; } -auto hashmap:find(Key key) +auto hashmap::find(Key key) { int hash = compute_hash(key); int bucket = hash & bucketMask; diff --git a/Modules/std/list.nc b/Modules/std/list.nc index 626f653dd..586b08a26 100644 --- a/Modules/std/list.nc +++ b/Modules/std/list.nc @@ -21,12 +21,12 @@ auto list_node.value(T val) return elem = val; } -void list:list() +void list::list() { first = last = nullptr; } -void list:push_back(T elem) +void list::push_back(T elem) { if(!first) { @@ -41,7 +41,7 @@ void list:push_back(T elem) last.elem = elem; last.parent = this; } -void list:push_front(T elem) +void list::push_front(T elem) { if(!first) { @@ -56,19 +56,19 @@ void list:push_front(T elem) first.elem = elem; first.parent = this; } -void list:pop_back() +void list::pop_back() { if(!last) assert(0, "list::pop_back list is empty"); last = last.prev; } -void list:pop_front() +void list::pop_front() { if(!first) assert(0, "list::pop_back list is empty"); first = first.next; } -void list:insert(list_node ref it, T elem) +void list::insert(list_node ref it, T elem) { if(it.parent != this) assert(0, "list::insert iterator is from a different list"); @@ -81,7 +81,7 @@ void list:insert(list_node ref it, T elem) if(next) next.prev = it.next; } -void list:erase(list_node ref it) +void list::erase(list_node ref it) { if(it.parent != this) assert(0, "list::insert iterator is from a different list"); @@ -95,33 +95,33 @@ void list:erase(list_node ref it) if(it == last) last = last.prev; } -void list:clear() +void list::clear() { first = last = nullptr; } -auto list:back() +auto list::back() { assert(first != nullptr, "list::back called on empty list"); return &last.elem; } -auto list:front() +auto list::front() { assert(first != nullptr, "list::front called on empty list"); return &first.elem; } -auto list:begin() +auto list::begin() { return first; } -auto list:end() +auto list::end() { return last; } -int list:empty() +int list::empty() { return first == nullptr; } -auto list:find(T elem) +auto list::find(T elem) { auto curr = first; @@ -140,32 +140,32 @@ class list_iterator { list_node ref curr; } -auto list_iterator:list_iterator(list_node ref start) +auto list_iterator::list_iterator(list_node ref start) { curr = start; } -auto list_iterator:start() +auto list_iterator::start() { return *this; } -auto list_iterator:next() +auto list_iterator::next() { auto ret = &curr.elem; curr = curr.next; return ret; } -auto list_iterator:hasnext() +auto list_iterator::hasnext() { return curr ? 1 : 0; } -auto list:start() +auto list::start() { return list_iterator(this.first); } // aggregate function and other features on sequences -auto list:sum(generic ref(T) f) +auto list::sum(generic ref(T) f) { typeof(f).return sum; for(i in list_iterator(first)) @@ -173,7 +173,7 @@ auto list:sum(generic ref(T) f) return sum; } -auto list:average(generic ref(T) f) +auto list::average(generic ref(T) f) { typeof(f).return sum; int count = 0; @@ -185,7 +185,7 @@ auto list:average(generic ref(T) f) return sum / count; } -auto list:min_element() +auto list::min_element() { auto min = first.elem; for(i in list_iterator(first.next)) @@ -193,7 +193,7 @@ auto list:min_element() return min; } -auto list:max_element() +auto list::max_element() { auto max = first.elem; for(i in list_iterator(first.next)) @@ -201,7 +201,7 @@ auto list:max_element() return max; } -auto list:min_element(generic ref(T) f) +auto list::min_element(generic ref(T) f) { typeof(f).return min = f(first.elem), tmp; for(i in list_iterator(first.next)) @@ -212,7 +212,7 @@ auto list:min_element(generic ref(T) f) return min; } -auto list:max_element(generic ref(T) f) +auto list::max_element(generic ref(T) f) { typeof(f).return max = f(first.elem), tmp; for(i in list_iterator(first.next)) @@ -223,7 +223,7 @@ auto list:max_element(generic ref(T) f) return max; } -auto list:count_if(generic ref(T) f) +auto list::count_if(generic ref(T) f) { int c = 0; for(i in list_iterator(first)) @@ -232,7 +232,7 @@ auto list:count_if(generic ref(T) f) return c; } -auto list:all(generic ref(T) f) +auto list::all(generic ref(T) f) { int c = first ? 1 : 0; for(i in list_iterator(first)) @@ -244,7 +244,7 @@ auto list:all(generic ref(T) f) return c; } -auto list:any(generic ref(T) f) +auto list::any(generic ref(T) f) { int c = 0; for(i in list_iterator(first)) diff --git a/Modules/std/math.nc b/Modules/std/math.nc index 560517b2c..a31202faf 100644 --- a/Modules/std/math.nc +++ b/Modules/std/math.nc @@ -308,14 +308,14 @@ float ref operator[](float2 ref a, int index); float ref operator[](float3 ref a, int index); float ref operator[](float4 ref a, int index); -float float2:length(); -float float2:normalize(); +float float2::length(); +float float2::normalize(); -float float3:length(); -float float3:normalize(); +float float3::length(); +float float3::normalize(); -float float4:length(); -float float4:normalize(); +float float4::length(); +float float4::normalize(); float dot(float2 ref a, float2 ref b); float dot(float3 ref a, float3 ref b); diff --git a/Modules/std/range.nc b/Modules/std/range.nc index 131c4d3a2..e31f815c5 100644 --- a/Modules/std/range.nc +++ b/Modules/std/range.nc @@ -6,16 +6,16 @@ class range_iterator int max; int step; } -auto range_iterator:start() +auto range_iterator::start() { return *this; } -int range_iterator:next() +int range_iterator::next() { pos += step; return pos - step; } -int range_iterator:hasnext() +int range_iterator::hasnext() { return pos < max; } diff --git a/Modules/std/string.nc b/Modules/std/string.nc index c351e9720..8e648f1fc 100644 --- a/Modules/std/string.nc +++ b/Modules/std/string.nc @@ -30,6 +30,8 @@ int strcmp(char[] a, b); // Error is generated if either array is empty of not null-terminated int strcpy(char[] dst, src); +int luamatch(char[] str, pattern, int offset = 0, int max_size=0); + // String class to use instead of error-prone raw character arrays class string { @@ -37,12 +39,12 @@ class string } // Empty constructor -void string:string() +void string::string() { } // Basic constructor -void string:string(char[] right) +void string::string(char[] right) { if(right.size == 0) return; @@ -68,7 +70,7 @@ void string:string(char[] right) } // Fill constructor -void string:string(int count, char ch) +void string::string(int count, char ch) { assert(count >= 0); @@ -81,7 +83,7 @@ void string:string(int count, char ch) } // Copy constructor -void string:string(string ref right) +void string::string(string ref right) { if(right.data) this.data = duplicate(right.data); @@ -144,19 +146,19 @@ int string.size() } // Length of the string excluding the terminating null-character -int string:length() +int string::length() { return data.size ? data.size - 1 : 0; } // Clears the string -void string:clear() +void string::clear() { data = nullptr; } // Checks that the string is empty -bool string:empty() +bool string::empty() { return data.size <= 1; } @@ -185,13 +187,13 @@ string operator[](string ref left, int start, int end) } // First character -char ref string:front() +char ref string::front() { return &data[0]; } // Last character not counting the null-character -char ref string:back() +char ref string::back() { return &data[data.size - 2]; } @@ -210,7 +212,7 @@ string ref operator+=(string ref left, char[] right) } // Inserts a string before the specified character -string ref string:insert(int offset, string ref str) +string ref string::insert(int offset, string ref str) { // No change on attempt to insert empty string if(str.size == 0) @@ -238,19 +240,19 @@ string ref string:insert(int offset, string ref str) return this; } -string ref string:insert(int offset, char[] str) +string ref string::insert(int offset, char[] str) { return this.insert(offset, string(str)); } -string ref string:insert(int offset, int count, char ch) +string ref string::insert(int offset, int count, char ch) { return this.insert(offset, string(count, ch)); } // If the length is specified, erases the selected number of characters starting from the specified character // If the length is not specified, erases all the characters starting from the specified character -string ref string:erase(int offset, int length = -1) +string ref string::erase(int offset, int length = -1) { if(length < 0 || length > data.size - offset) length = data.size - offset - 1; @@ -275,7 +277,7 @@ string ref string:erase(int offset, int length = -1) } // Erases the selected number of characters starting from the specified character and replaces them with a specified string -string ref string:replace(int offset, int length, string ref str) +string ref string::replace(int offset, int length, string ref str) { assert(offset == 0 || (offset > 0 && offset < data.size)); @@ -297,32 +299,32 @@ string ref string:replace(int offset, int length, string ref str) return this; } -string ref string:replace(int offset, int length, char[] str) +string ref string::replace(int offset, int length, char[] str) { return replace(offset, length, string(str)); } -string ref string:replace(int offset, int length, int count, char ch) +string ref string::replace(int offset, int length, int count, char ch) { return this.replace(offset, length, string(count, ch)); } // Swap string data with another string -void string:swap(string ref right) +void string::swap(string ref right) { char[] tmp = data; data = right.data; right.data = tmp; } -void string:swap(char[] right) +void string::swap(char[] right) { data = right; } // Returns the position of the first occurance of the specified string or -1 if it is not found // Optional offset specifies how many characters to skip from the start of the string during the search -int string:find(string ref str, int offset = 0) +int string::find(string ref str, int offset = 0) { int last = data.size - str.data.size + 1; @@ -341,12 +343,12 @@ int string:find(string ref str, int offset = 0) return -1; } -int string:find(char[] str, int offset = 0) +int string::find(char[] str, int offset = 0) { return find(string(str), offset); } -int string:find(char ch, int offset = 0) +int string::find(char ch, int offset = 0) { for(int i = offset; i < data.size - 1; i++) { @@ -359,7 +361,7 @@ int string:find(char ch, int offset = 0) // Returns the position of the last occurance of the specified string or -1 if it is not found // Optional offset specifies how many characters to consider in the search counting from the beginning of the string including the character at the specified offset -int string:rfind(string ref str, int offset = -1) +int string::rfind(string ref str, int offset = -1) { if(str.data.size == 0) return offset >= 0 && offset < data.size ? offset : size; @@ -382,12 +384,12 @@ int string:rfind(string ref str, int offset = -1) return -1; } -int string:rfind(char[] str, int offset = -1) +int string::rfind(char[] str, int offset = -1) { return rfind(string(str), offset); } -int string:rfind(char ch, int offset = -1) +int string::rfind(char ch, int offset = -1) { if(offset < 0 || offset >= data.size - 1) offset = data.size - 2; @@ -403,7 +405,7 @@ int string:rfind(char ch, int offset = -1) // Returns the position of the first occurance of any of the specified characters in a string or -1 if not a single match is found // Optional offset specifies how many characters to skip from the start of the string during the search -int string:find_first_of(string ref str, int offset = 0) +int string::find_first_of(string ref str, int offset = 0) { for(int i = offset; i < data.size - 1; i++) { @@ -417,19 +419,19 @@ int string:find_first_of(string ref str, int offset = 0) return -1; } -int string:find_first_of(char[] str, int offset = 0) +int string::find_first_of(char[] str, int offset = 0) { return find_first_of(string(str), offset); } -int string:find_first_of(char ch, int offset = 0) +int string::find_first_of(char ch, int offset = 0) { return find(ch, offset); } // Returns the position of the last occurance of any of the specified characters in a string or -1 if not a single match is found // Optional offset specifies how many characters to consider in the search counting from the beginning of the string including the character at the specified offset -int string:find_last_of(string ref str, int offset = -1) +int string::find_last_of(string ref str, int offset = -1) { if(offset < 0 || offset >= data.size - 1) offset = data.size - 2; @@ -446,19 +448,19 @@ int string:find_last_of(string ref str, int offset = -1) return -1; } -int string:find_last_of(char[] str, int offset = -1) +int string::find_last_of(char[] str, int offset = -1) { return find_last_of(string(str), offset); } -int string:find_last_of(char ch, int offset = -1) +int string::find_last_of(char ch, int offset = -1) { return rfind(ch, offset); } // Returns the position of the first occurance of a character that doesn't match any of the specified characters in a string or -1 if a match is found // Optional offset specifies how many characters to skip from the start of the string during the search -int string:find_first_not_of(string ref str, int offset = 0) +int string::find_first_not_of(string ref str, int offset = 0) { for(int i = offset; i < data.size - 1; i++) { @@ -475,12 +477,12 @@ int string:find_first_not_of(string ref str, int offset = 0) return -1; } -int string:find_first_not_of(char[] str, int offset = 0) +int string::find_first_not_of(char[] str, int offset = 0) { return find_first_not_of(string(str), offset); } -int string:find_first_not_of(char ch, int offset = 0) +int string::find_first_not_of(char ch, int offset = 0) { for(int i = offset; i < data.size - 1; i++) { @@ -493,7 +495,7 @@ int string:find_first_not_of(char ch, int offset = 0) // Returns the position of the last occurance of a character that doesn't match any of the specified characters in a string or -1 if a match is found // Optional offset specifies how many characters to consider in the search counting from the beginning of the string including the character at the specified offset -int string:find_last_not_of(string ref str, int offset = -1) +int string::find_last_not_of(string ref str, int offset = -1) { if(offset < 0 || offset >= data.size - 1) offset = data.size - 2; @@ -513,12 +515,12 @@ int string:find_last_not_of(string ref str, int offset = -1) return -1; } -int string:find_last_not_of(char[] str, int offset = -1) +int string::find_last_not_of(char[] str, int offset = -1) { return find_last_not_of(string(str), offset); } -int string:find_last_not_of(char ch, int offset = -1) +int string::find_last_not_of(char ch, int offset = -1) { if(offset < 0 || offset >= data.size - 1) offset = data.size - 2; @@ -539,7 +541,7 @@ bool operator in(char ch, string ref str) } // Returns a substring of [start, start + length) array elements -string string:substr(int start, int length = -1) +string string::substr(int start, int length = -1) { if(length < 0 || start + length >= data.size) length = data.size - start - 1; diff --git a/Modules/std/typeinfo.nc b/Modules/std/typeinfo.nc index 4305c7a85..98e751ace 100644 --- a/Modules/std/typeinfo.nc +++ b/Modules/std/typeinfo.nc @@ -15,20 +15,20 @@ int isPointer(auto ref type); char[] typeid.name(); // For class types -int typeid:memberCount(); -typeid typeid:memberType(int member); -char[] typeid:memberName(int member); +int typeid::memberCount(); +typeid typeid::memberType(int member); +char[] typeid::memberName(int member); // For array and pointer types -typeid typeid:subType(); +typeid typeid::subType(); // for array types -int typeid:arraySize(); +int typeid::arraySize(); // for function type -typeid typeid:returnType(); -int typeid:argumentCount(); -typeid typeid:argumentType(int argument); +typeid typeid::returnType(); +int typeid::argumentCount(); +typeid typeid::argumentType(int argument); // iteration over members of a type class member_iterator @@ -41,22 +41,22 @@ class member_info typeid type; char[] name; } -auto typeid:members() +auto typeid::members() { member_iterator ret; ret.classID = *this; ret.pos = 0; return ret; } -auto member_iterator:start() +auto member_iterator::start() { return this; } -auto member_iterator:hasnext() +auto member_iterator::hasnext() { return pos < classID.memberCount(); } -auto member_iterator:next() +auto member_iterator::next() { member_info ret; ret.type = classID.memberType(pos); @@ -85,7 +85,7 @@ class member_info_obj char[] name; auto ref value; } -auto typeid:members(auto ref obj) +auto typeid::members(auto ref obj) { member_iterator_obj ret; ret.classID = *this; @@ -93,15 +93,15 @@ auto typeid:members(auto ref obj) ret.pos = 0; return ret; } -auto member_iterator_obj:start() +auto member_iterator_obj::start() { return this; } -auto member_iterator_obj:hasnext() +auto member_iterator_obj::hasnext() { return pos < classID.memberCount(); } -auto member_iterator_obj:next() +auto member_iterator_obj::next() { member_info_obj ret; ret.type = classID.memberType(pos); @@ -117,22 +117,22 @@ class argument_iterator typeid funcID; int pos; } -auto typeid:arguments() +auto typeid::arguments() { argument_iterator ret; ret.funcID = *this; ret.pos = 0; return ret; } -auto argument_iterator:start() +auto argument_iterator::start() { return this; } -auto argument_iterator:hasnext() +auto argument_iterator::hasnext() { return pos < funcID.argumentCount(); } -auto argument_iterator:next() +auto argument_iterator::next() { return funcID.argumentType(pos++); } diff --git a/Modules/std/vector.nc b/Modules/std/vector.nc index f66d2a787..eac10f1d1 100644 --- a/Modules/std/vector.nc +++ b/Modules/std/vector.nc @@ -7,20 +7,20 @@ class vector int count; } -void vector:vector(int reserved) +void vector::vector(int reserved) { assert(reserved >= 0); if(reserved) data = new T[reserved]; count = 0; } -void vector:vector() +void vector::vector() { data = nullptr; count = 0; } -void vector:push_back(T val) +void vector::push_back(T val) { if(count == data.size) this.grow(count); @@ -28,19 +28,19 @@ void vector:push_back(T val) data[count++] = val; } -void vector:pop_back() +void vector::pop_back() { assert(count); count--; } -auto vector:back() +auto vector::back() { assert(count); return &data[count - 1]; } -auto vector:front() +auto vector::front() { assert(count); return &data[0]; @@ -52,7 +52,7 @@ auto operator[](vector ref v, int index) return &v.data[index]; } -void vector:grow(int targetSize) +void vector::grow(int targetSize) { int nReserved = data.size + (data.size >> 1) + 1; @@ -64,17 +64,17 @@ void vector:grow(int targetSize) data = nArr; } -auto vector:size() +auto vector::size() { return count; } -auto vector:capacity() +auto vector::capacity() { return data.size; } -void vector:reserve(int size) +void vector::reserve(int size) { assert(size >= 0); @@ -84,7 +84,7 @@ void vector:reserve(int size) grow(size); } -void vector:resize(int size) +void vector::resize(int size) { assert(size >= 0); @@ -95,12 +95,12 @@ void vector:resize(int size) count = size; } -void vector:clear() +void vector::clear() { count = 0; } -void vector:destroy() +void vector::destroy() { count = 0; data = nullptr; @@ -112,18 +112,18 @@ class vector_iterator vector ref arr; int pos; } -auto vector:start() +auto vector::start() { vector_iterator iter; iter.arr = this; iter.pos = 0; return iter; } -auto vector_iterator:next() +auto vector_iterator::next() { return &arr.data[pos++]; } -int vector_iterator:hasnext() +int vector_iterator::hasnext() { return arr != nullptr && pos < arr.count; } @@ -151,7 +151,7 @@ auto operator[](vector_splice<@T> ref a, int index) // aggregate function and other features on sequences -auto vector:sum(generic ref(T) f) +auto vector::sum(generic ref(T) f) { typeof(f).return sum; for(int i = 0; i < count; i++) @@ -159,12 +159,12 @@ auto vector:sum(generic ref(T) f) return sum; } -auto vector:average(generic ref(T) f) +auto vector::average(generic ref(T) f) { return sum(f) / count; } -auto vector:min_element() +auto vector::min_element() { int min = 0; for(int i = 1; i < count; i++) @@ -172,7 +172,7 @@ auto vector:min_element() return data[min]; } -auto vector:max_element() +auto vector::max_element() { int max = 0; for(int i = 1; i < count; i++) @@ -180,7 +180,7 @@ auto vector:max_element() return data[max]; } -auto vector:min_element(generic ref(T) f) +auto vector::min_element(generic ref(T) f) { typeof(f).return min = f(data[0]), tmp; for(int i = 1; i < count; i++) @@ -191,7 +191,7 @@ auto vector:min_element(generic ref(T) f) return min; } -auto vector:max_element(generic ref(T) f) +auto vector::max_element(generic ref(T) f) { typeof(f).return max = f(data[0]), tmp; for(int i = 1; i < count; i++) @@ -202,7 +202,7 @@ auto vector:max_element(generic ref(T) f) return max; } -auto vector:count_if(generic ref(T) f) +auto vector::count_if(generic ref(T) f) { int c = 0; for(int i = 0; i < count; i++) @@ -211,7 +211,7 @@ auto vector:count_if(generic ref(T) f) return c; } -auto vector:all(generic ref(T) f) +auto vector::all(generic ref(T) f) { int c = count ? 1 : 0; for(int i = 0; i < count && c; i++) // exit immediately if one of elements doesn't pass the test @@ -219,7 +219,7 @@ auto vector:all(generic ref(T) f) return c; } -auto vector:any(generic ref(T) f) +auto vector::any(generic ref(T) f) { int c = 0; for(int i = 0; i < count && !c; i++) // exit immediately if one of elements passed the test @@ -232,7 +232,7 @@ void vector_sort_impl(generic arr, generic pred) sort(arr.data, 0, arr.count, pred); } -auto vector:sort(generic ref(T, T) pred) +auto vector::sort(generic ref(T, T) pred) { vector_sort_impl(this, pred); } @@ -245,33 +245,33 @@ bool operator in(generic x, vector ref arr) return false; } -auto vector:push_back_mult(generic ref() f) +auto vector::push_back_mult(generic ref() f) { for(i in f) push_back(i); } -auto vector:push_back_mult(generic[] arr) +auto vector::push_back_mult(generic[] arr) { for(i in arr) push_back(i); } -auto vector:fill(generic ref() f) +auto vector::fill(generic ref() f) { clear(); for(i in f) push_back(i); } -auto vector:fill(generic[] arr) +auto vector::fill(generic[] arr) { clear(); for(i in arr) push_back(i); } -auto vector:foldl(generic ref(T, T) f) +auto vector::foldl(generic ref(T, T) f) { auto tmp = data[0]; for(int i = 1; i < count; i++) @@ -279,7 +279,7 @@ auto vector:foldl(generic ref(T, T) f) return tmp; } -auto vector:foldr(generic ref(T, T) f) +auto vector::foldr(generic ref(T, T) f) { auto tmp = data[count - 1]; for(int i = count - 2; i >= 0; i--) @@ -292,7 +292,7 @@ auto operator=(vector ref v, generic[] arr) v.fill(arr); } -auto vector:map(generic ref(T) f) +auto vector::map(generic ref(T) f) { vector res; res.reserve(count); @@ -301,7 +301,7 @@ auto vector:map(generic ref(T) f) return res; } -auto vector:filter(generic ref(T) f) +auto vector::filter(generic ref(T) f) { vector res; res.reserve(count); diff --git a/Modules/win/window.nc b/Modules/win/window.nc index 751a12930..27c3a1143 100644 --- a/Modules/win/window.nc +++ b/Modules/win/window.nc @@ -8,15 +8,15 @@ Window Window(char[] title, int x, y, width, height) return ret; } -void Window:SetTitle(char[] title); -void Window:SetPosition(int x, y); -void Window:SetSize(int width, height); +void Window::SetTitle(char[] title); +void Window::SetPosition(int x, y); +void Window::SetSize(int width, height); -int Window:GetPosX(){ return x; } -int Window:GetPosY(){ return y; } +int Window::GetPosX(){ return x; } +int Window::GetPosY(){ return y; } -void Window:DrawCanvas(Canvas ref c, int x, y); +void Window::DrawCanvas(Canvas ref c, int x, y); -void Window:Update(); +void Window::Update(); -void Window:Close(); +void Window::Close(); diff --git a/NULLC/Compiler.cpp b/NULLC/Compiler.cpp index 3c4f9cd43..c57ce0a97 100644 --- a/NULLC/Compiler.cpp +++ b/NULLC/Compiler.cpp @@ -24,28 +24,28 @@ int int(int a);\r\n\ long long(long a);\r\n\ float float(float a);\r\n\ double double(double a);\r\n\ -void bool:bool(bool a){ *this = a; }\r\n\ -void char:char(char a){ *this = a; }\r\n\ -void short:short(short a){ *this = a; }\r\n\ -void int:int(int a){ *this = a; }\r\n\ -void long:long(long a){ *this = a; }\r\n\ -void float:float(float a){ *this = a; }\r\n\ -void double:double(double a){ *this = a; }\r\n\ +void bool::bool(bool a){ *this = a; }\r\n\ +void char::char(char a){ *this = a; }\r\n\ +void short::short(short a){ *this = a; }\r\n\ +void int::int(int a){ *this = a; }\r\n\ +void long::long(long a){ *this = a; }\r\n\ +void float::float(float a){ *this = a; }\r\n\ +void double::double(double a){ *this = a; }\r\n\ \r\n\ int as_unsigned(char a);\r\n\ int as_unsigned(short a);\r\n\ long as_unsigned(int a);\r\n\ \r\n\ short short(char[] str);\r\n\ -char[] short:str();\r\n\ +char[] short::str();\r\n\ int int(char[] str);\r\n\ -char[] int:str();\r\n\ +char[] int::str();\r\n\ long long(char[] str);\r\n\ -char[] long:str();\r\n\ +char[] long::str();\r\n\ float float(char[] str);\r\n\ -char[] float:str(int precision = 6, bool showExponent = false);\r\n\ +char[] float::str(int precision = 6, bool showExponent = false);\r\n\ double double(char[] str);\r\n\ -char[] double:str(int precision = 6, bool showExponent = false);\r\n\ +char[] double::str(int precision = 6, bool showExponent = false);\r\n\ \r\n\ void ref __newS(int size, int type);\r\n\ int[] __newA(int size, int count, int type);\r\n\ @@ -133,7 +133,7 @@ auto[] auto_array(typeid type, int count)\r\n\ }\r\n\ typedef auto[] auto_array;\r\n\ // function will set auto[] element to the specified one, with data reallocation if neccessary\r\n\ -void auto_array:set(auto ref x, int pos);\r\n\ +void auto_array::set(auto ref x, int pos);\r\n\ void __force_size(auto[] ref s, int size);\r\n\ \r\n\ int isCoroutineReset(auto ref f);\r\n\ diff --git a/NULLC/Lexer.cpp b/NULLC/Lexer.cpp index 376dbd9dc..6ce9c8de3 100644 --- a/NULLC/Lexer.cpp +++ b/NULLC/Lexer.cpp @@ -379,7 +379,12 @@ void Lexer::Lexify(const char* code) lType = lex_questionmark; break; case ':': - lType = lex_colon; + if(code[1] == ':') + { + lType = lex_dblcolon; + lLength = 2; + } + else lType = lex_colon; break; case ';': lType = lex_semicolon; diff --git a/NULLC/Lexer.h b/NULLC/Lexer.h index f0b7d8627..f16c1bc0f 100644 --- a/NULLC/Lexer.h +++ b/NULLC/Lexer.h @@ -45,7 +45,7 @@ enum LexemeType lex_set, lex_addset, lex_subset, lex_mulset, lex_divset, lex_powset, lex_modset, lex_shlset, lex_shrset, lex_andset, lex_orset, lex_xorset, // = += -= *= /= **= %= <<= >>= &= |= ^= lex_bitnot, lex_lognot, // ~ ! lex_oparen, lex_cparen, lex_obracket, lex_cbracket, lex_ofigure, lex_cfigure, // ( ) [ ] { } - lex_questionmark, lex_colon, lex_semicolon, // ? : ; + lex_questionmark, lex_colon, lex_semicolon, lex_dblcolon,// ? : ; :: lex_if, lex_else, lex_for, lex_while, lex_do, lex_switch, lex_case, lex_default, // if else for while switch case default lex_break, lex_continue, lex_return, // break continue return lex_ref, lex_auto, lex_class, lex_noalign, lex_align, // ref auto class noalign align diff --git a/NULLC/ParseTree.cpp b/NULLC/ParseTree.cpp index cbe2d8acb..ba418dab4 100644 --- a/NULLC/ParseTree.cpp +++ b/NULLC/ParseTree.cpp @@ -2689,7 +2689,7 @@ SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) if(parentType) { - if(ctx.Consume(lex_colon)) + if(ctx.Consume(lex_dblcolon)) { accessor = false; } diff --git a/NULLC/includes/lua-regex.c b/NULLC/includes/lua-regex.c new file mode 100644 index 000000000..562797ab3 --- /dev/null +++ b/NULLC/includes/lua-regex.c @@ -0,0 +1,619 @@ +/****************************************************************************** +* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ +/* +Adapted by Domingo Alvarez Duarte 2012 +http://code.google.com/p/lua-regex-standalone/ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "lua-regex.h" + +/* macro to `unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + +#define L_ESC '%' +#define SPECIALS "^$*+?.([%-" + +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + +static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { + /* relative string position: negative means back from end */ + if (pos < 0) pos += (ptrdiff_t)len; + return (pos >= 0) ? pos : 0; +} + +static int check_capture_all_closed (LuaMatchState *ms) { + int i; + for(i=0; ilevel; ++i){ + if(ms->capture[i].len == CAP_UNFINISHED){ + ms->error = "unfinished capture"; + return 0; + } + } + return 1; +} + +static int check_capture_is_closed (LuaMatchState *ms, int l) { + if (l < 0 || l >= ms->level){ + ms->error = "invalid capture index"; + return 0; + } + if (ms->capture[l].len == CAP_UNFINISHED){ + ms->error = "unfinished capture"; + return 0; + } + return 1; +} + +static int check_capture (LuaMatchState *ms, int *l_out) { + int l; + *l_out -= '1'; + l = *l_out; + return check_capture_is_closed(ms, l); +} + +static int capture_to_close (LuaMatchState *ms, int *level_out) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) { + *level_out = level; + return 1; + } + ms->error = "invalid pattern capture"; + return 0; +} + + +static int classend (LuaMatchState *ms, const char *p, const char **result) { + switch (*p++) { + case L_ESC: { + if (p == ms->p_end){ + ms->error = "malformed pattern (ends with " LUA_QL("%%") ")"; + return 0; + } + *result = p+1; + return 1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (p == ms->p_end){ + ms->error = "malformed pattern (missing " LUA_QL("]") ")"; + return 0; + } + if (*(p++) == L_ESC && p < ms->p_end) + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + *result = p+1; + return 1; + } + default: { + *result = p; + return 1; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'g' : res = isgraph(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; /* deprecated option */ + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == L_ESC) { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } +} + + +static const char *match (LuaMatchState *ms, const char *s, const char *p); + +//add escape char extension from https://github.com/jcgoble3/lua-matchext +static const char *matchbalance (LuaMatchState *ms, const char *s, + const char *p) { + int escaped = (*(p-1) == 'B'); /* EXT */ + if (p >= ms->p_end - 1 - escaped){ + ms->error = "malformed pattern " + "(missing arguments to " LUA_QL("%%b") ")"; + return NULL; + } + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p + (escaped ? 2 : 1)); /* EXT */ + int esc = escaped ? *(p + 1) : INT_MAX; /* EXT */ + int cont = 1; + while (++s < ms->src_end) { + if (*s == esc) s++; /* EXT */ + else if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (LuaMatchState *ms, const char *s, + const char *p, const char *ep) { + ptrdiff_t i = 0; /* counts maximum expand for item */ + while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (LuaMatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (ssrc_end && singlematch(uchar(*s), p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (LuaMatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= LUA_REGEX_MAXCAPTURES) { + ms->error = "too many captures"; + return NULL; + } + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (LuaMatchState *ms, const char *s, + const char *p) { + int l; + const char *res; + if(!capture_to_close(ms, &l)) return NULL; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (LuaMatchState *ms, const char *s, int l) { + size_t len; + if(check_capture(ms, &l)){ + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + } + return NULL; +} + + +static const char *match (LuaMatchState *ms, const char *s, const char *p) { + init: /* using goto's to optimize tail recursion */ + if (p == ms->p_end) /* end of pattern? */ + return s; /* match succeeded */ + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case '$': { + if ((p+1) == ms->p_end) /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ + switch (*(p+1)) { + case 'b': case 'B': { /* balanced string? */ /* EXT */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p += (*(p + 1) == 'b') ? 4 : 5; /* EXT */ goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '['){ + ms->error = "missing " LUA_QL("[") " after " + LUA_QL("%%f") " in pattern"; + return NULL; + } + if(!classend(ms, p, &ep)) return NULL; /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p+1))); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ + } + default: goto dflt; + } + } + default: dflt: { /* pattern class plus optional suffix */ + const char *ep; + int m; + if(!classend(ms, p, &ep)) return NULL; /* points to what is next */ + m = s < ms->src_end && singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ + } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + } + } + } + } +} + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +/* check whether pattern has no special characters */ +static int nospecials (const char *p, size_t l) { + size_t upto = 0; + do { + if (strpbrk(p + upto, SPECIALS)) + return 0; /* pattern has a special character */ + upto += strlen(p + upto) + 1; /* may have more after \0 */ + } while (upto <= l); + return 1; /* no special chars found */ +} + + +static ptrdiff_t str_find_aux (LuaMatchState *ms, int find, const char *s, ptrdiff_t ls, + const char *p, ptrdiff_t lp, ptrdiff_t init, int raw_find, + luaregex_func_param fp, void *udata) { + ptrdiff_t result; + ms->error = NULL; + if(ls < 0) ls = strlen(s); + assert(ls >= 0); + if(lp < 0) lp = strlen(p); + assert(lp >= 0); + init = posrelat(init, ls); + if (init < 0) init = 0; + else if (init > ls + 1) { /* start after string's end? */ + return 0; /* cannot find anything */ + } + ms->src_init = s; + ms->src_end = s + ls; + +do_again: + result = -1; /* not found */ + /* explicit request or no special characters? */ + if (find && (raw_find || nospecials(p, lp))) { + /* do a plain search */ + const char *s2 = lmemfind(s + init, ls - init, p, lp); + if (s2) { + ms->start_pos = ((int)(s2 - s)); + result = ms->end_pos = ms->start_pos+lp; + ms->level = 0; + } + } + else { + const char *s1 = s + init; + int anchor = (*p == '^'); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + ms->p_end = p + lp; + do { + const char *res; + ms->level = 0; + if ((res=match(ms, s1, p)) != NULL) { + ms->start_pos = s1-s; + result = ms->end_pos = res-s; + goto eofunc; + } + } while (s1++ < ms->src_end && !anchor); + } + +eofunc: + + if(result >= 0){ + if(!check_capture_all_closed(ms)) return 0; + if(fp && (*fp)(ms, udata, 0)) { + init = result; + if (init == ms->start_pos) ++init; /* empty match? go at least one position */ + if (init < ls) goto do_again; + } + } + return result > 0 ? ms->start_pos : result; //returning the start position +} + + +ptrdiff_t lua_str_find (LuaMatchState *ms, const char *s, ptrdiff_t ls, + const char *p, ptrdiff_t lp, ptrdiff_t init, int raw_find, + luaregex_func_param fp, void *udata) { + return str_find_aux(ms, 1, s, ls, p, lp, init, raw_find, fp, udata); +} + + +ptrdiff_t lua_str_match (LuaMatchState *ms, const char *s, ptrdiff_t ls, + const char *p, ptrdiff_t lp, ptrdiff_t init, int raw_find, + luaregex_func_param fp, void *udata) { + return str_find_aux(ms, 0, s, ls, p, lp, init, raw_find, fp, udata); +} + +#define MIN_ALLOC_SIZE 2048 +#define NEW_SIZE(sz) (((sz/MIN_ALLOC_SIZE)+1)*MIN_ALLOC_SIZE) + +int char_buffer_add_char(LuaMatchState *ms, lua_char_buffer_st **b, char c){ + lua_char_buffer_st *tmp = *b; + if(tmp->used+1 >= tmp->size){ + int new_size = tmp->size+MIN_ALLOC_SIZE; + tmp = (lua_char_buffer_st*)realloc(tmp, sizeof(lua_char_buffer_st) + new_size); + if(!tmp){ + ms->error = "not enough memory when reallocating"; + return 0; + } + *b = tmp; + tmp->size = new_size; + } + tmp->buf[tmp->used++] = c; + return 1; +} + + +int char_buffer_add_str(LuaMatchState *ms, lua_char_buffer_st **b, const char *str, ptrdiff_t len){ + lua_char_buffer_st *tmp = *b; + if(len < 0) len = strlen(str); + assert(len >= 0); + if(tmp->used+len >= tmp->size){ + size_t new_size = tmp->size + NEW_SIZE(len); + tmp = (lua_char_buffer_st*)realloc(tmp, sizeof(lua_char_buffer_st) + new_size); + if(!tmp){ + ms->error = "not enough memory when reallocating"; + return 0; + } + *b = tmp; + tmp->size = new_size; + } + memcpy(&tmp->buf[tmp->used], str, len); + tmp->used += len; + return 1; +} + + +static int add_value (LuaMatchState *ms, lua_char_buffer_st **b, const char *s, + const char *e, const char *news, size_t lnews) { + size_t i; + for (i = 0; i < lnews; i++) { + if (news[i] != L_ESC){ + if(!char_buffer_add_char(ms, b, news[i])) return 0; + } + else { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) { + if (news[i] != L_ESC){ + ms->error = "invalid use of replacement string"; + return 0; + } + if(!char_buffer_add_char(ms, b, news[i])) return 0; + } + else if (news[i] == '0'){ + if(!char_buffer_add_str(ms, b, s, e - s)) return 0; + } + else { + int il = news[i] - '1'; + if (il >= ms->level) { + if (il == 0){ /* ms->level == 0, too */ + if(!char_buffer_add_str(ms, b, s, e - s)) return 0; /* add whole match */ + } + else{ + ms->error = "invalid capture index"; + return 0; + } + } + else { + ptrdiff_t cl = ms->capture[il].len; + if (cl == CAP_UNFINISHED) { + ms->error = "unfinished capture"; + return 0; + } + if (cl == CAP_POSITION){ + char buf[32]; + snprintf(buf, sizeof(buf), "%" PRIdPTR, ms->capture[il].init - ms->src_init + 1); + if(!char_buffer_add_str(ms, b, buf, strlen(buf))) return 0; + } + else + if(!char_buffer_add_str(ms, b, ms->capture[il].init, cl)) return 0; + } + } + } + } + return 1; +} + +lua_char_buffer_st *lua_str_gsub (const char *src, ptrdiff_t srcl, const char *p, ptrdiff_t lp, + const char *tr, ptrdiff_t ltr, size_t max_s, const char **error_ptr, + luaregex_func_param fp, void *udata) { + int anchor; + size_t n; + LuaMatchState ms; + lua_char_buffer_st *b; + if(srcl < 0) srcl = strlen(src); + assert(srcl >= 0); + if(lp < 0) lp = strlen(p); + assert(lp >= 0); + if(ltr < 0) ltr = strlen(tr); + assert(ltr >= 0); + if(max_s == 0) max_s = srcl+1; + anchor = (*p == '^'); + n = NEW_SIZE(srcl); + b = (lua_char_buffer_st*)malloc(sizeof(lua_char_buffer_st) + n); + if(!b) return NULL; + b->size = n; + b->used = 0; + + n = 0; + if (anchor) { + p++; lp--; /* skip anchor character */ + } + ms.error = 0; + ms.start_pos = ms.end_pos = 0; + ms.src_init = src; + ms.src_end = src+srcl; + ms.p_end = p + lp; + while (n < max_s) { + const char *e; + ms.level = 0; + e = match(&ms, src, p); + if(ms.error || !check_capture_all_closed(&ms)) goto free_and_null; + if (e) { + n++; + if(fp){ + ms.end_pos = e-ms.src_init; + if(!(*fp)(&ms, udata, &b)) goto free_and_null; + } + else if(!add_value(&ms, &b, src, e, tr, ltr)) goto free_and_null; + } + if (e && e>src){ /* non empty match? */ + ms.start_pos = e-ms.src_init; + src = e; /* skip it */ + } + else if (src < ms.src_end){ + if(!char_buffer_add_char(&ms, &b, *src++)) goto free_and_null; + ++ms.start_pos; + } + else break; + if (anchor) break; + } + if(!char_buffer_add_str(&ms, &b, src, ms.src_end-src)) goto free_and_null; + b->buf[b->used] = '\0'; + return b; + +free_and_null: + if(b) free(b); + if(error_ptr) *error_ptr = ms.error; + return NULL; +} + diff --git a/NULLC/includes/lua-regex.h b/NULLC/includes/lua-regex.h new file mode 100644 index 000000000..6529c633d --- /dev/null +++ b/NULLC/includes/lua-regex.h @@ -0,0 +1,89 @@ +#ifndef LUA_REGEX_H +#define LUA_REGEX_H + +/****************************************************************************** +* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ +/* +Adapted by Domingo Alvarez Duarte 2012 +http://code.google.com/p/lua-regex-standalone/ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* +** maximum number of captures that a pattern can do during +** pattern-matching. This limit is arbitrary. +*/ +#define LUA_REGEX_MAXCAPTURES 32 + +#define CAP_UNFINISHED (-1) +#define CAP_POSITION (-2) + +typedef struct lua_char_buffer_st { + size_t size, used; + char buf[1]; // Not taking in account compiler padding +} lua_char_buffer_st; + +typedef struct LuaCapture { + const char *init; + ptrdiff_t len; +} LuaCapture; + +typedef struct LuaMatchState { + const char *src_init; /* init of source string */ + const char *src_end; /* end ('\0') of source string */ + const char *p_end; /* end ('\0') of pattern */ + size_t start_pos; /* pattern match start position */ + size_t end_pos; /* pattern match end position */ + const char *error; + int level; /* total number of captures (finished or unfinished) */ + LuaCapture capture[LUA_REGEX_MAXCAPTURES]; +} LuaMatchState; + +typedef int (*luaregex_func_param)(LuaMatchState *ms, void *udata, lua_char_buffer_st **b); + +ptrdiff_t lua_str_find (LuaMatchState *ms, const char *s, ptrdiff_t ls, + const char *p, ptrdiff_t lp, ptrdiff_t init, int raw_find, + luaregex_func_param fp, void *udata); + +ptrdiff_t lua_str_match (LuaMatchState *ms, const char *s, ptrdiff_t ls, + const char *p, ptrdiff_t lp, ptrdiff_t init, int raw_find, + luaregex_func_param fp, void *udata); + +lua_char_buffer_st *lua_str_gsub (const char *src, ptrdiff_t srcl, const char *p, ptrdiff_t lp, + const char *tr, ptrdiff_t ltr, size_t max_s, const char **error_ptr, + luaregex_func_param fp, void *udata); + +int char_buffer_add_char(LuaMatchState *ms, lua_char_buffer_st **b, char c); +int char_buffer_add_str(LuaMatchState *ms, lua_char_buffer_st **b, const char *str, ptrdiff_t len); + +#ifdef __cplusplus +} +#endif + +#endif //LUA_REGEX_H diff --git a/NULLC/includes/string.cpp b/NULLC/includes/string.cpp index 09c5fedc4..d42f2d49f 100644 --- a/NULLC/includes/string.cpp +++ b/NULLC/includes/string.cpp @@ -5,6 +5,25 @@ #include +#include "lua-regex.h" + +static int calc_new_size_by_max_len(int start_pos, int max_len, int curr_size) +{ + int new_size; + if(start_pos < 0) + { + new_size = curr_size + start_pos; + start_pos = new_size < 0 ? 0 : new_size; + } + if(max_len > 0) new_size = start_pos + max_len; + else new_size = curr_size + max_len; + if( (new_size < curr_size) && (new_size > start_pos) ) + { + return new_size; + } + return curr_size; +} + namespace NULLCString { int strlen(NULLCArray string) @@ -143,6 +162,32 @@ namespace NULLCString nullcThrowError("string is not null-terminated"); return -1; } + + int luamatch(NULLCArray a, NULLCArray b, int offset, int max_size) + { + if(!a.ptr) + { + nullcThrowError("first string is null"); + return -1; + } + + if(!b.ptr) + { + nullcThrowError("second string is null"); + return -1; + } + + LuaMatchState ms; + memset(&ms, 0, sizeof(ms)); + int src_size = a.len; + if(max_size) + { + src_size = calc_new_size_by_max_len(offset, max_size, src_size); + } + ptrdiff_t rc = lua_str_match (&ms, a.ptr, max_size ? offset + max_size : src_size, b.ptr, b.len, offset, 0, NULL, NULL); + return rc; + } + } #define REGISTER_FUNC(name, index) if(!nullcBindModuleFunctionHelper("std.string", NULLCString::name, #name, index)) return false; @@ -153,6 +198,7 @@ bool nullcInitStringModule() REGISTER_FUNC(strchr, 0); REGISTER_FUNC(strcmp, 0); REGISTER_FUNC(strcpy, 0); + REGISTER_FUNC(luamatch, 0); return true; } diff --git a/NULLC/stdafx.cpp b/NULLC/stdafx.cpp index 87040e735..f60e467c6 100644 --- a/NULLC/stdafx.cpp +++ b/NULLC/stdafx.cpp @@ -124,6 +124,11 @@ void NEWDECL_CALL operator delete [] (void *p) if (p) free (p); } +void NEWDECL_CALL operator delete [] (void *p, size_t) +{ + if (p) free (p); +} + void NEWDECL_CALL operator delete (void *p, size_t) { if (p) free (p); diff --git a/tests/TestAccessors.cpp b/tests/TestAccessors.cpp index c9f9fa29f..641accca8 100644 --- a/tests/TestAccessors.cpp +++ b/tests/TestAccessors.cpp @@ -36,7 +36,7 @@ const char *testAccessorAccessInsideAMemberFunction = int _x;\r\n\ int x{ get { return _x; } set{ _x = r / 2; } };\r\n\ }\r\n\ -void Foo:Foo(){ x = 4; }\r\n\ +void Foo::Foo(){ x = 4; }\r\n\ Foo a;\r\n\ return a.x;"; TEST_RESULT("Accessor access inside a member function", testAccessorAccessInsideAMemberFunction, "2"); diff --git a/tests/TestAutoRefCall.cpp b/tests/TestAutoRefCall.cpp index 1ff4724c5..c258ecb32 100644 --- a/tests/TestAutoRefCall.cpp +++ b/tests/TestAutoRefCall.cpp @@ -3,20 +3,20 @@ const char *testAutoRefCall1 = "int sum = 0;\r\n\ class Foo{ int i; float u; }\r\n\ -void Foo:add(int u)\r\n\ +void Foo::add(int u)\r\n\ {\r\n\ sum += i * u;\r\n\ }\r\n\ -void int:add(int u)\r\n\ +void int::add(int u)\r\n\ {\r\n\ sum += *this + u;\r\n\ }\r\n\ \r\n\ -void Foo:add()\r\n\ +void Foo::add()\r\n\ {\r\n\ sum -= i;\r\n\ }\r\n\ -void int:add()\r\n\ +void int::add()\r\n\ {\r\n\ sum *= *this;\r\n\ }\r\n\ @@ -41,7 +41,7 @@ TEST_RESULT_SIMPLE("auto ref type function call 1", testAutoRefCall1, "32"); const char *testAutoRefCall2 = "import std.list;\r\n\ import std.math;\r\n\ -void int:rgba(int r, g, b, a)\r\n\ +void int::rgba(int r, g, b, a)\r\n\ {\r\n\ *this = (a << 24) | (r << 16) | (g << 8) | b;\r\n\ }\r\n\ @@ -130,7 +130,7 @@ return mp;"; TEST_RESULT("auto ref type function call 2", testAutoRefCall2, "2760"); const char *testFunctionCallThroughAutoRefInMemberFunction = -"int int:foo(){ return -*this; }\r\n\ +"int int::foo(){ return -*this; }\r\n\ class Foo\r\n\ {\r\n\ auto()\r\n\ @@ -159,7 +159,7 @@ LOAD_MODULE(test_autorefcall, "test.autorefcall", "class Proxy{ int foo(int x){ const char *testIndirectCallModules = "import test.autorefcall;\r\n\ class Bar{ int u; }\r\n\ -int Bar:foo(int x){ return x + u; }\r\n\ +int Bar::foo(int x){ return x + u; }\r\n\ Bar m; m.u = 10;\r\n\ return rc(m);"; TEST_RESULT("Function call through 'auto ref', more types defined later", testIndirectCallModules, "15"); @@ -222,13 +222,13 @@ const char *testAutorefCallIssue3 = "void foo()\r\n\ {\r\n\ class Foo{}\r\n\ - int Foo:F(){ return 1; }\r\n\ + int Foo::F(){ return 1; }\r\n\ }\r\n\ \r\n\ auto bar()\r\n\ {\r\n\ class Foo{}\r\n\ - auto Foo:F(){ return 123; }\r\n\ + auto Foo::F(){ return 123; }\r\n\ \r\n\ Foo x;\r\n\ auto ref y = x;\r\n\ diff --git a/tests/TestClasses.cpp b/tests/TestClasses.cpp index 86087c66a..8a57977ef 100644 --- a/tests/TestClasses.cpp +++ b/tests/TestClasses.cpp @@ -251,7 +251,7 @@ LOAD_MODULE(test_class_typedef, "test.class_typedef", }"); const char *testClassTypeAliasImport1 = "import test.class_typedef;\r\n\ -void Foo:foo(){ T y; }\r\n\ +void Foo::foo(){ T y; }\r\n\ return 1;"; TEST_RESULT("Import of class local aliases", testClassTypeAliasImport1, "1"); @@ -347,7 +347,7 @@ const char *testImplicitConstructorCallForGenericType2 = {\r\n\ T x;\r\n\ }\r\n\ -void Foo:Foo(){ x = 42; }\r\n\ +void Foo::Foo(){ x = 42; }\r\n\ auto x = new Foo;\r\n\ return x.x;"; TEST_RESULT("implicit constructor call for generic types 2", testImplicitConstructorCallForGenericType2, "42"); @@ -357,8 +357,8 @@ const char *testImplicitConstructorCallForGenericType3 = {\r\n\ T x;\r\n\ }\r\n\ -void Foo:Foo(){ x = 10; }\r\n\ -void Foo:Foo(){ x = 42; }\r\n\ +void Foo::Foo(){ x = 10; }\r\n\ +void Foo::Foo(){ x = 42; }\r\n\ auto x = new Foo;\r\n\ return x.x;"; TEST_RESULT("implicit constructor call for generic types 3", testImplicitConstructorCallForGenericType3, "42"); @@ -378,7 +378,7 @@ const char *testImplicitConstructorCallForGenericType5 = {\r\n\ T x;\r\n\ }\r\n\ -void Foo:Foo(){ x = 42; }\r\n\ +void Foo::Foo(){ x = 42; }\r\n\ auto x = new Foo();\r\n\ return x.x;"; TEST_RESULT("implicit constructor call for generic types 5", testImplicitConstructorCallForGenericType5, "42"); @@ -388,8 +388,8 @@ const char *testImplicitConstructorCallForGenericType6 = {\r\n\ T x;\r\n\ }\r\n\ -void Foo:Foo(){ x = 10; }\r\n\ -void Foo:Foo(){ x = 42; }\r\n\ +void Foo::Foo(){ x = 10; }\r\n\ +void Foo::Foo(){ x = 42; }\r\n\ auto x = new Foo();\r\n\ return x.x;"; TEST_RESULT("implicit constructor call for generic types 6", testImplicitConstructorCallForGenericType6, "42"); @@ -411,7 +411,7 @@ class Foo\r\n\ {\r\n\ T x;\r\n\ }\r\n\ -void Foo:Foo(){ x = m++; }\r\n\ +void Foo::Foo(){ x = m++; }\r\n\ auto x = new Foo[32];\r\n\ return x[19].x;"; TEST_RESULT_SIMPLE("constructor call for every array element 4", testConstructorForArrayElements4, "29"); @@ -422,15 +422,15 @@ class Foo\r\n\ {\r\n\ T x;\r\n\ }\r\n\ -void Foo:Foo(){ x = 10; }\r\n\ -void Foo:Foo(){ x = m++; }\r\n\ +void Foo::Foo(){ x = 10; }\r\n\ +void Foo::Foo(){ x = m++; }\r\n\ auto x = new Foo[32];\r\n\ return x[19].x;"; TEST_RESULT_SIMPLE("constructor call for every array element 5", testConstructorForArrayElements5, "29"); const char *testConstructorCallOnStaticConstructionOfGenericType1 = "class Foo{ T curr; }\r\n\ -auto Foo:Foo(int start)\r\n\ +auto Foo::Foo(int start)\r\n\ {\r\n\ curr = start;\r\n\ }\r\n\ @@ -441,7 +441,7 @@ TEST_RESULT("member constructor call on external static construction of a generi const char *testCorrectTypeAliasesInAGenericTypeConstructor = "class Bar{ Bar ref x; }\r\n\ class Foo{ T curr; }\r\n\ -auto Foo:Foo(Bar ref start){ curr = 5; }\r\n\ +auto Foo::Foo(Bar ref start){ curr = 5; }\r\n\ auto a = Foo(new Bar);\r\n\ return a.curr;"; TEST_RESULT("correct type alias in a generic type constructor", testCorrectTypeAliasesInAGenericTypeConstructor, "5"); @@ -616,7 +616,7 @@ const char *testClassConstants3 = {\r\n\ const int a = 5;\r\n\ }\r\n\ -int Foo:foo(){ return a; }\r\n\ +int Foo::foo(){ return a; }\r\n\ Foo m;\r\n\ return m.foo();"; TEST_RESULT("Class constants 3", testClassConstants3, "5"); @@ -627,7 +627,7 @@ const char *testClassConstants4 = const int a = 5;\r\n\ const int b = a + 5;\r\n\ }\r\n\ -int Foo:foo(){ return a * b; }\r\n\ +int Foo::foo(){ return a * b; }\r\n\ Foo m;\r\n\ return m.foo();"; TEST_RESULT("Class constants 4", testClassConstants4, "50"); @@ -688,7 +688,7 @@ TEST_RESULT("Class forward declaration 3", testClassForwardDeclaration3, "10"); const char *testClassForwardDeclaration4 = "class Node;\r\n\ \r\n\ -int Node:foo(){ return 12; }\r\n\ +int Node::foo(){ return 12; }\r\n\ \r\n\ class Node\r\n\ {\r\n\ @@ -1145,7 +1145,7 @@ TEST_RESULT("Usage of class value inside if, for, while, do while and switch sta const char *testClassConstructorInMemberFunction = "class Foo{ int x; void Foo(int y){ x = y; } }\r\n\ -int Foo:xx()\r\n\ +int Foo::xx()\r\n\ {\r\n\ Foo a = Foo(5);\r\n\ return 12;\r\n\ @@ -1176,7 +1176,7 @@ class Bar\r\n\ {\r\n\ Foo ref x;\r\n\ }\r\n\ -void Bar:Bar(){ x = new Foo{ x = 5; }; }\r\n\ +void Bar::Bar(){ x = new Foo{ x = 5; }; }\r\n\ return (new Bar()).x.x;"; TEST_RESULT("Class custom construction inside a member function", testClassCustomConstructorInsideAMemberFunction2, "5"); @@ -1217,8 +1217,8 @@ TEST_RESULT("Enumeration test 8", testEnumeration8, "20"); const char *testMemberFunctionCallFromLocalFunctionInsideMemberFunction = "class Foo{}\r\n\ -auto Foo:foo(){ return 1; }\r\n\ -auto Foo:bar(){ return coroutine auto(){ return foo(); }; }\r\n\ +auto Foo::foo(){ return 1; }\r\n\ +auto Foo::bar(){ return coroutine auto(){ return foo(); }; }\r\n\ Foo x; return x.bar()();"; TEST_RESULT("Member function call from local function inside a member function", testMemberFunctionCallFromLocalFunctionInsideMemberFunction, "1"); diff --git a/tests/TestClosures.cpp b/tests/TestClosures.cpp index 6b641e7bc..8df20eb4c 100644 --- a/tests/TestClosures.cpp +++ b/tests/TestClosures.cpp @@ -880,7 +880,7 @@ class Holder\r\n\ void ref() c;\r\n\ }\r\n\ \r\n\ -auto Holder:a()\r\n\ +auto Holder::a()\r\n\ {\r\n\ if(auto z = this.x)\r\n\ {\r\n\ diff --git a/tests/TestCompileFail.cpp b/tests/TestCompileFail.cpp index 63c7fd68a..a661dea79 100644 --- a/tests/TestCompileFail.cpp +++ b/tests/TestCompileFail.cpp @@ -145,8 +145,8 @@ void RunCompileFailTests() TEST_FOR_FAIL("Class function return unclear 1", "class Test{int i;int foo(){ return i; }int foo(int k){ return i; }auto bar(){ return foo; }}return 1;", "ERROR: ambiguity, there is more than one overloaded function available:"); - TEST_FOR_FAIL("Class externally defined method 1", "int dontexist:don(){ return 0; } return 1;", "ERROR: 'dontexist' is not a known type name"); - TEST_FOR_FAIL("Class externally defined method 2", "int int:(){ return *this; } return 1;", "ERROR: function name expected after ':' or '.'"); + TEST_FOR_FAIL("Class externally defined method 1", "int dontexist::don(){ return 0; } return 1;", "ERROR: 'dontexist' is not a known type name"); + TEST_FOR_FAIL("Class externally defined method 2", "int int::(){ return *this; } return 1;", "ERROR: function name expected after ':' or '.'"); TEST_FOR_FAIL("Member variable or function is not found", "int a; a.b; return 1;", "ERROR: member variable or function 'b' is not defined in class 'int'"); @@ -184,7 +184,7 @@ void RunCompileFailTests() TEST_FOR_FAIL("Invalid array index type B", "import std.math; float2 a; int[100] arr; arr[a] = 7;", "ERROR: cannot convert 'float2' to 'int'"); TEST_FOR_FAIL("None of the types implement method", "int i = 0; auto ref u = &i; return u.value();", "ERROR: function 'value' is undefined in any of existing classes"); - TEST_FOR_FAIL("None of the types implement correct method", "int i = 0; int int:value(){ return *this; } auto ref u = &i; return u.value(15);", "ERROR: can't find function 'int::value' with following arguments:"); + TEST_FOR_FAIL("None of the types implement correct method", "int i = 0; int int::value(){ return *this; } auto ref u = &i; return u.value(15);", "ERROR: can't find function 'int::value' with following arguments:"); TEST_FOR_FAIL("Operator overload with no arguments", "int operator+(){ return 5; }", "ERROR: operator '+' definition must accept one or two arguments"); @@ -208,7 +208,7 @@ void RunCompileFailTests() TEST_FOR_FAIL("Operation unsupported on reference 3", "int x; int ref y = &x; return *(y--);", "ERROR: decrement is not supported on 'int ref'"); TEST_FOR_FAIL("Operation unsupported on reference 4", "int x; int ref y = &x; return *--y;", "ERROR: decrement is not supported on 'int ref'"); - TEST_FOR_FAIL("Constructor returns a value", "auto int:int(int x, y){ *this = x; return this; } return *new int(4, 8);", "ERROR: type constructor return type must be 'void'"); + TEST_FOR_FAIL("Constructor returns a value", "auto int::int(int x, y){ *this = x; return this; } return *new int(4, 8);", "ERROR: type constructor return type must be 'void'"); const char *testCompileTimeNoReturn = "int foo(int m)\r\n\ @@ -233,8 +233,8 @@ int[foo(3)] arr;"; TEST_FOR_FAIL("Read-only member", "auto[] x = new int[2]; (&x.size)++; return x.size;", "ERROR: cannot get address of the expression"); TEST_FOR_FAIL("Read-only member", "auto[] x = new int[2]; (&x.size)--; return x.size;", "ERROR: cannot get address of the expression"); TEST_FOR_FAIL("Read-only member", "int[] x = new int[2]; (auto(int ref x){ return x; })(&x.size) = 56; return x.size;", "ERROR: cannot get address of the expression"); - TEST_FOR_FAIL("Read-only member", "int[] x = { 1, 2 }; typedef int[] wrap; void wrap:rewrite(int x){ size = x; } x.rewrite(2048); return x[1000];", "ERROR: cannot change immutable value of type int"); - TEST_FOR_FAIL("Read-only member", "auto[] x = { 1, 2 }; typedef auto[] wrap; void wrap:rewrite(){ type = long; } x.rewrite(); return long(x[0]);", "ERROR: cannot change immutable value of type typeid"); + TEST_FOR_FAIL("Read-only member", "int[] x = { 1, 2 }; typedef int[] wrap; void wrap::rewrite(int x){ size = x; } x.rewrite(2048); return x[1000];", "ERROR: cannot change immutable value of type int"); + TEST_FOR_FAIL("Read-only member", "auto[] x = { 1, 2 }; typedef auto[] wrap; void wrap::rewrite(){ type = long; } x.rewrite(); return long(x[0]);", "ERROR: cannot change immutable value of type typeid"); nullcLoadModuleBySource("test.redefinitionPartA", "int foo(int x){ return -x; }"); nullcLoadModuleBySource("test.redefinitionPartB", "int foo(int x){ return ~x; }"); @@ -274,7 +274,7 @@ return bar(<>{ return -x; }, 5);", "ERROR: cannot find function which accepts a TEST_FOR_FAIL("typeof from a combination of generic arguments", "auto sum(generic a, b, typeof(a*b) c){ return a + b; } return sum(3, 4.5, double);", "ERROR: can't find function 'sum' with following arguments:"); - TEST_FOR_FAIL("coroutine cannot be a member function", "class Foo{} coroutine int Foo:bar(){ yield 1; return 0; } return 1;", "ERROR: coroutine cannot be a member function"); + TEST_FOR_FAIL("coroutine cannot be a member function", "class Foo{} coroutine int Foo::bar(){ yield 1; return 0; } return 1;", "ERROR: coroutine cannot be a member function"); TEST_FOR_FAIL("error in generic function body", "auto sum(generic a, b, c){ return a + b + ; } return sum(3, 4.5, 5l);", "ERROR: expression not found after binary operation"); TEST_FOR_FAIL_GENERIC("genric function accessing variable that is defined later", "int y = 4; auto foo(generic a){ return i + y; } int i = 2; return foo(4);", "ERROR: unknown identifier 'i'", "while instantiating generic function foo(generic)"); @@ -343,10 +343,10 @@ return bar(foo);", TEST_FOR_FAIL("cannot select function overload", "int foo(int x){ return -x; } int foo(float x){ return x * 2; } int x = foo;", "ERROR: ambiguity, there is more than one overloaded function available:"); TEST_FOR_FAIL("Instanced inline function is wrong", "class X{} X x; int foo(int ref(int, X) f){ return f(5, x); } return foo(auto(generic y, double z){ return -y; });", "ERROR: can't find function 'foo' with following arguments:"); - TEST_FOR_FAIL("no finalizable objects on stack", "class Foo{int a;} void Foo:finalize(){} Foo x;", "ERROR: cannot create 'Foo' that implements 'finalize' on stack"); - TEST_FOR_FAIL("no finalizable objects on stack 2", "class Foo{int a;} void Foo:finalize(){} auto x = *(new Foo);", "ERROR: cannot create 'Foo' that implements 'finalize' on stack"); - TEST_FOR_FAIL("no finalizable objects on stack 3", "class Foo{int a;} void Foo:finalize(){} Foo[10] arr;", "ERROR: class 'Foo' implements 'finalize' so only an unsized array type can be created"); - TEST_FOR_FAIL("no finalizable objects on stack 4", "class Foo{int a;} void Foo:finalize(){} class Bar{ Foo z; }", "ERROR: cannot create 'Foo' that implements 'finalize' on stack"); + TEST_FOR_FAIL("no finalizable objects on stack", "class Foo{int a;} void Foo::finalize(){} Foo x;", "ERROR: cannot create 'Foo' that implements 'finalize' on stack"); + TEST_FOR_FAIL("no finalizable objects on stack 2", "class Foo{int a;} void Foo::finalize(){} auto x = *(new Foo);", "ERROR: cannot create 'Foo' that implements 'finalize' on stack"); + TEST_FOR_FAIL("no finalizable objects on stack 3", "class Foo{int a;} void Foo::finalize(){} Foo[10] arr;", "ERROR: class 'Foo' implements 'finalize' so only an unsized array type can be created"); + TEST_FOR_FAIL("no finalizable objects on stack 4", "class Foo{int a;} void Foo::finalize(){} class Bar{ Foo z; }", "ERROR: cannot create 'Foo' that implements 'finalize' on stack"); if(!nullcLoadModuleBySource("test.import_typedef1a", "class Foo{ int bar; }")) printf("Failed to create module test.import_typedef1a\n"); @@ -406,7 +406,7 @@ return bar();", "ERROR: unknown identifier 'c'", "while instantiating generic ty {\r\n\ T x, y, z;\r\n\ }\r\n\ -int Foo:foo()\r\n\ +int Foo::foo()\r\n\ {\r\n\ return c;\r\n\ }\r\n\ @@ -458,8 +458,8 @@ return int(foo(b) + foo(c));", TEST_FOR_FAIL("generic function specialization fail 6", "class Foo{ T x; } Foo a; a.x = 5; auto foo(Foo m){ return -m.x; } return foo(&a);", "ERROR: can't find function 'foo' with following arguments:"); - TEST_FOR_FAIL("external function definition syntax inside a type 1", "class Foo{ void Foo:foo(){} }", "ERROR: class name repeated inside the definition of class"); - TEST_FOR_FAIL("external function definition syntax inside a type 2", "class Bar{} class Foo{ void Bar:foo(){} }", "ERROR: cannot define class 'Bar' function inside the scope of class 'Foo'"); + TEST_FOR_FAIL("external function definition syntax inside a type 1", "class Foo{ void Foo::foo(){} }", "ERROR: class name repeated inside the definition of class"); + TEST_FOR_FAIL("external function definition syntax inside a type 2", "class Bar{} class Foo{ void Bar::foo(){} }", "ERROR: cannot define class 'Bar' function inside the scope of class 'Foo'"); TEST_FOR_FAIL_FULL("function pointer selection fail", "void foo(int a){} void foo(double a){}\r\nauto a = foo;\r\nreturn 1;", "ERROR: ambiguity, there is more than one overloaded function available:\n\ @@ -472,7 +472,7 @@ return int(foo(b) + foo(c));", TEST_FOR_FAIL_FULL("function pointer selection fail 2", "class Foo{ T a; auto foo(){ return -a; } }\r\n\ -int Foo:foo(){ return -a; }\r\n\ +int Foo::foo(){ return -a; }\r\n\ Foo x; x.a = 4; Foo s; s.a = 40;\r\n\ auto y = x.foo; auto z = s.foo;\r\n\ return int(y() + z());", @@ -509,17 +509,17 @@ return int(y() + z());", TEST_FOR_FAIL("wrong function type passed for generic function specialization", "auto average(generic ref(int, float) f){ return f(8, 3); } auto f1(int x){ return x; } return average(f1);", "ERROR: can't find function 'average' with following arguments:"); TEST_FOR_FAIL("wrong function type passed for generic function specialization", "auto average(generic ref(int) f){ return f(8, 3); } auto f1(int x, int z){ return x + z; } return average(f1);", "ERROR: can't find function 'average' with following arguments:"); - TEST_FOR_FAIL("cannot find suitable function", "class Foo{} auto Foo:average(generic ref(int, T) f){ return f(5, 4); } Foo m; return m.average({ 5+x+y; }, 4);", "ERROR: can't find function 'Foo::average' with following arguments:"); + TEST_FOR_FAIL("cannot find suitable function", "class Foo{} auto Foo::average(generic ref(int, T) f){ return f(5, 4); } Foo m; return m.average({ 5+x+y; }, 4);", "ERROR: can't find function 'Foo::average' with following arguments:"); TEST_FOR_FAIL("wrong function type passed for generic function specialization", "auto average(generic ref(generic, int) f){ return f(4.0, 2); } auto f2(float x, y){ return x * 2.5; } return average(f2);", "ERROR: can't find function 'average' with following arguments:"); TEST_FOR_FAIL("wrong function type passed for generic function specialization", "auto average(int ref(generic, int) f){ return f(2, 4); } auto f2(float x, y){ return x * 2.5; } return average(f2);", "ERROR: can't find function 'average' with following arguments:"); - TEST_FOR_FAIL("generic type constructor call without generic arguments", "class Foo{ T curr; } auto Foo:Foo(int start){ curr = start; } Foo a = Foo(5);", "ERROR: generic type arguments in <> are not found after constructor name"); - TEST_FOR_FAIL_GENERIC("generic type constructor call without generic arguments 2", "class list{} class list_iterator{} auto list_iterator:list_iterator(){} auto list:sum(){for(i in list_iterator()){}} list arr; arr.sum();", "ERROR: generic type arguments in <> are not found after constructor name", "while instantiating generic function list::sum()"); + TEST_FOR_FAIL("generic type constructor call without generic arguments", "class Foo{ T curr; } auto Foo::Foo(int start){ curr = start; } Foo a = Foo(5);", "ERROR: generic type arguments in <> are not found after constructor name"); + TEST_FOR_FAIL_GENERIC("generic type constructor call without generic arguments 2", "class list{} class list_iterator{} auto list_iterator::list_iterator(){} auto list::sum(){for(i in list_iterator()){}} list arr; arr.sum();", "ERROR: generic type arguments in <> are not found after constructor name", "while instantiating generic function list::sum()"); - TEST_FOR_FAIL_GENERIC("generic type member function local function is local", "class Foo{ T x; } auto Foo:foo(){ auto bar(){ return x; } return this.bar(); } Foo m; return m.foo();", "ERROR: member variable or function 'bar' is not defined in class 'Foo'", "while instantiating generic function Foo::foo()"); + TEST_FOR_FAIL_GENERIC("generic type member function local function is local", "class Foo{ T x; } auto Foo::foo(){ auto bar(){ return x; } return this.bar(); } Foo m; return m.foo();", "ERROR: member variable or function 'bar' is not defined in class 'Foo'", "while instantiating generic function Foo::foo()"); - TEST_FOR_FAIL_GENERIC("type aliases are taken from instance", "class Foo{} auto Foo:foo(T key){ bar(10); } auto Foo:bar(T key){} Foo map; map.foo(\"foo\"); return 1;", "ERROR: can't find function 'Foo::bar' with following arguments:", "while instantiating generic function Foo::foo(@T)"); + TEST_FOR_FAIL_GENERIC("type aliases are taken from instance", "class Foo{} auto Foo::foo(T key){ bar(10); } auto Foo::bar(T key){} Foo map; map.foo(\"foo\"); return 1;", "ERROR: can't find function 'Foo::bar' with following arguments:", "while instantiating generic function Foo::foo(@T)"); TEST_FOR_FAIL("wrong function return type", "int foo(int ref(generic) f){ return f(4); } auto f2(float x){ return x * 2.5; } return foo(f2);", "ERROR: can't find function 'foo' with following arguments:"); @@ -538,8 +538,8 @@ return int(y() + z());", TEST_FOR_FAIL("typedef dies after a generic function instance 2", "class Foo{ T x; } auto foo(Foo<@T> x, int ref(int, int) y){ return x.x * y(1, 2); } Foo a; a.x = 2; assert(6 == foo(a, { i+j; })); T x; return x;", "ERROR: 'T' is not a known type name"); - TEST_FOR_FAIL("generic in an illegal context", "auto foo(generic x){} class Bar{ T x; } auto Bar:bar(generic y = foo(Bar())){} return 1;", "ERROR: can't cast to a generic type"); - TEST_FOR_FAIL("generic in an illegal context", "auto foo(generic x){} class Bar{ T x; } auto Bar:bar(generic y = foo(T())){} return 1;", "ERROR: can't cast to a generic type"); + TEST_FOR_FAIL("generic in an illegal context", "auto foo(generic x){} class Bar{ T x; } auto Bar::bar(generic y = foo(Bar())){} return 1;", "ERROR: can't cast to a generic type"); + TEST_FOR_FAIL("generic in an illegal context", "auto foo(generic x){} class Bar{ T x; } auto Bar::bar(generic y = foo(T())){} return 1;", "ERROR: can't cast to a generic type"); TEST_FOR_FAIL("operator with short-circuit requirement", "int operator||(int a, b){ return 0; }", "ERROR: operator '||' definition must accept a function returning desired type as the second argument"); @@ -622,7 +622,7 @@ return int(y() + z());", TEST_FOR_FAIL("unresolved type", "auto foo(){ foo.a(); }", "ERROR: function 'foo' type is unresolved at this point"); TEST_FOR_FAIL("unresolved type", "auto foo(){ foo.a; }", "ERROR: function 'foo' type is unresolved at this point"); TEST_FOR_FAIL("unresolved type", "auto foo(){ &foo; }", "ERROR: function 'foo' type is unresolved at this point"); - TEST_FOR_FAIL("unresolved type", "class Foo{ } auto Foo:foo(){ auto m = this.foo; return m(); }", "ERROR: function 'Foo::foo' type is unresolved at this point"); + TEST_FOR_FAIL("unresolved type", "class Foo{ } auto Foo::foo(){ auto m = this.foo; return m(); }", "ERROR: function 'Foo::foo' type is unresolved at this point"); TEST_FOR_FAIL("no function", "int foo(@T[] arr){ return 1; } return foo(new int);", "ERROR: can't find function 'foo' with following arguments:"); TEST_FOR_FAIL("no function", "class Bar{} int foo(Bar<@T>[] arr){ return 1; } Bar ref x; return foo(x);", "ERROR: can't find function 'foo' with following arguments:"); @@ -689,7 +689,7 @@ return 0;", TEST_FOR_FAIL("?: exploit", "int foo = 0xdeadbeef; void ref bar = !foo ? nullptr : foo; int ref error = bar; *error;", "ERROR: cannot convert '__nullptr' to 'int'"); - TEST_FOR_FAIL("this exploit", "class X{ int a; } auto X:foo(){ auto bar(){ int this; return a; } return bar(); } X x; x.a = 4; return x.foo();", "ERROR: 'this' is a reserved keyword"); + TEST_FOR_FAIL("this exploit", "class X{ int a; } auto X::foo(){ auto bar(){ int this; return a; } return bar(); } X x; x.a = 4; return x.foo();", "ERROR: 'this' is a reserved keyword"); TEST_FOR_FAIL("error with a generic function returning auto printout", "int foo(generic ref(generic, int) x){ return x(4, 5); } auto bar(int a, generic b){ return a + b; } return foo(bar, bar);", "ERROR: can't find function 'foo' with following arguments:"); TEST_FOR_FAIL("function selection error printout failure", "auto x = duplicate;", "ERROR: ambiguity, there is more than one overloaded function available:"); @@ -848,7 +848,7 @@ auto m = bar;", TEST_FOR_FAIL("invalid cast", "int ref(bool ref) x = int f(bool ref x){ return *x; }; return x(2);", "ERROR: cannot convert 'int' to 'bool ref'"); - TEST_FOR_FAIL("scope switch restore", "auto bar(generic x){ retprn x; } class Foo{} int Foo:foo(typeof(bar(1)) e){ return 1; } Foo test2; return test2.foo(1);", "ERROR: can't find function 'Foo::foo' with following arguments:"); + TEST_FOR_FAIL("scope switch restore", "auto bar(generic x){ retprn x; } class Foo{} int Foo::foo(typeof(bar(1)) e){ return 1; } Foo test2; return test2.foo(1);", "ERROR: can't find function 'Foo::foo' with following arguments:"); TEST_FOR_FAIL("invalid array element size 1", "int[2][100000] a;", "ERROR: array element size cannot exceed 65535 bytes"); TEST_FOR_FAIL("invalid array element size 2", "int[][100000] a;", "ERROR: array element size cannot exceed 65535 bytes"); @@ -859,9 +859,9 @@ auto m = bar;", TEST_FOR_FAIL("generic function instantiation creates a conflict", "auto foo(generic a, int f = 1){ return -a; } foo(1, 2); auto foo(generic a = 1, int f = 2){ return a; } return foo();", "ERROR: function 'foo' is being defined with the same set of arguments"); - TEST_FOR_FAIL("direct member function call 1", "class Foo{ int x; } (void Foo:reset(){ x = 0; })();", "ERROR: member function can't be called without a class instance"); - TEST_FOR_FAIL("direct member function call 2", "class Foo{ int x; } (void Foo:reset(generic a){ x = 0; })(4);", "ERROR: member function can't be called without a class instance"); - TEST_FOR_FAIL("direct member function call 3", "class Foo{ int x; } auto foo(void ref() f){ f(); } foo(void Foo:reset(){ x = 0; });", "ERROR: member function can't be called without a class instance"); + TEST_FOR_FAIL("direct member function call 1", "class Foo{ int x; } (void Foo::reset(){ x = 0; })();", "ERROR: member function can't be called without a class instance"); + TEST_FOR_FAIL("direct member function call 2", "class Foo{ int x; } (void Foo::reset(generic a){ x = 0; })(4);", "ERROR: member function can't be called without a class instance"); + TEST_FOR_FAIL("direct member function call 3", "class Foo{ int x; } auto foo(void ref() f){ f(); } foo(void Foo::reset(){ x = 0; });", "ERROR: member function can't be called without a class instance"); TEST_FOR_FAIL("early recursive call", "auto foo(){ return foo(); }", "ERROR: function type is unresolved at this point"); @@ -900,16 +900,16 @@ auto m = bar;", TEST_FOR_FAIL("fuzzing test crash", "coroutine auto __runner(){nt i = 1; return i.str() == \"0\" &else& int(i.str()) == i;}return __runner();", "ERROR: expression not found after binary operation"); TEST_FOR_FAIL("fuzzing test crash", "auto bar(auto ref x){ if(o tydefotypeoo ", "ERROR: closing ')' not found after 'if' condition"); TEST_FOR_FAIL("fuzzing test crash", "auto average(generic ref(int) f){ return f(5); }return int(average({ i += 8; i * aaaaaaaaaaa5; }));", "ERROR: unknown identifier 'aaaaaaaaaaa5'"); - TEST_FOR_FAIL("fuzzing test crash", "void int:rgba(int r, g, b, a){r(){ return (*this >> 16) & 0xff; }int ift.g() bm(b.y", "ERROR: ';' not found after expression"); + TEST_FOR_FAIL("fuzzing test crash", "void int::rgba(int r, g, b, a){r(){ return (*this >> 16) & 0xff; }int ift.g() bm(b.y", "ERROR: ';' not found after expression"); TEST_FOR_FAIL("fuzzing test crash", "auto __runner(){class Foo{ T t; }Foo> b; b.t.t Foo> b; b.t.t = 0;>> z)turn z.t.t; }returFoo> z){ return z.tuern __runner();", "ERROR: ';' not found after expression"); TEST_FOR_FAIL("fuzzing test crash", "class vec2 extendable{ float x, y; int foo(int i, j){ return i / j; } } class vec2 : vec2{ float z; int foo(int j, i){ return i / j; } }", "ERROR: 'vec2' is being redefined"); TEST_FOR_FAIL("fuzzing test crash", "coroutine int gen3from(int x){kint ref() m;for(int i = 0; i < 3; i++){int help(){return x + i;}help();m = help;}return m();i = gen3from2(2);t2 = t2 * 10 + i;}return (t1 == 567756) + (t2 == 442344);", "ERROR: 'kint' is not a known type name"); TEST_FOR_FAIL("fuzzing test crash", "import std.algorithm;coroutine auto __runner(){int[] arr = { 2, 6 };sort(arr, { a > b; });map(arr, { *x = *x * 2; })==arr = filter(arr, { x < 8; });int sum = 0;for(i in arr) sum += i;return sum;}return __runner();", "ERROR: 'ynt' is not a known type name"); - TEST_FOR_FAIL("fuzzing test crash", "Auto int:toString(){}", "ERROR: 'Auto' is not a known type name"); + TEST_FOR_FAIL("fuzzing test crash", "Auto int::toString(){}", "ERROR: 'Auto' is not a known type name"); TEST_FOR_FAIL("fuzzing test crash", "int a = 4;@if(typeof(a) !=)tn i{f;}ora;", "ERROR: expression not found after binary operation"); TEST_FOR_FAIL("fuzzing test crash", "class Foo{ T x; }Foo a = Foo((;a.x = 6;int foo(Foo a){return a.x;}foo(a);", "ERROR: expression not found after '('"); TEST_FOR_FAIL("fuzzing test crash", "int auto.c(){ return 0; }", "ERROR: cannot add accessor to type 'auto'"); - TEST_FOR_FAIL("fuzzing test crash", "int auto:c(){ return 0; }", "ERROR: cannot add member function to type 'auto'"); + TEST_FOR_FAIL("fuzzing test crash", "int auto::c(){ return 0; }", "ERROR: cannot add member function to type 'auto'"); TEST_FOR_FAIL("fuzzing test crash", "coroutine auto foo(){ int bar(); int bar(int x); yield bar; }", "ERROR: ambiguity, there is more than one overloaded function available:"); TEST_FOR_FAIL("fuzzing test crash", "coroutine auto foo(){ auto a = 2; class T{ int b = a; } }", "ERROR: member function 'T::T$' cannot access external variable 'a'"); TEST_FOR_FAIL("fuzzing test crash", "auto(@e x=){}", "ERROR: default argument value not found after '='"); @@ -923,8 +923,8 @@ auto m = bar;", TEST_FOR_FAIL("fuzzing test crash", "(.size", "ERROR: expression not found after '('"); TEST_FOR_FAIL("fuzzing test crash", "(.arraySize", "ERROR: expression not found after '('"); TEST_FOR_FAIL("fuzzing test crash", "auto bar<@T,@U>(){ return 1; } return bar with() + bar with<>();", "ERROR: type name is expected after 'with'"); - TEST_FOR_FAIL("fuzzing test crash", "class Fooo(", "ERROR: '>' expected after generic type alias list"); - TEST_FOR_FAIL("fuzzing test crash", "class Footest3; test3.foo(4", "ERROR: '>' expected after generic type alias list"); + TEST_FOR_FAIL("fuzzing test crash", "class Fooo(", "ERROR: '>' expected after generic type alias list"); + TEST_FOR_FAIL("fuzzing test crash", "class Footest3; test3.foo(4", "ERROR: '>' expected after generic type alias list"); TEST_FOR_FAIL("fuzzing test crash", "auto foo(generic x){}coroutine auto f(){auto x = foo;}", "ERROR: cannot instantiate generic function, because target type is not known"); TEST_FOR_FAIL("fuzzing test crash", "@if{", "ERROR: '(' not found after 'if'"); TEST_FOR_FAIL("fuzzing test crash", "@\"", "ERROR: unclosed string constant"); @@ -949,7 +949,7 @@ auto m = bar;", TEST_FOR_FAIL("fuzzing test crash", "auto foo(generic i, j){}foo(i:2);", "ERROR: can't find function 'foo' with following arguments:"); TEST_FOR_FAIL("fuzzing test crash", "class j{ @if(j o(){class j{}}){}}", "ERROR: 'j' is being redefined"); TEST_FOR_FAIL("fuzzing test crash", "double fo(do typeof(fo).argument[.", "ERROR: ')' not found after function variable list"); - TEST_FOR_FAIL("fuzzing test crash", "class X{} int X:foo(){ return 1; } auto ref y; int ref() z = y.foo;", "ERROR: can't convert dynamic function set to 'int ref()'"); + TEST_FOR_FAIL("fuzzing test crash", "class X{} int X::foo(){ return 1; } auto ref y; int ref() z = y.foo;", "ERROR: can't convert dynamic function set to 'int ref()'"); TEST_FOR_FAIL("fuzzing test crash", "auto ref x; *x = assert;", "ERROR: ambiguity, there is more than one overloaded function available:"); TEST_FOR_FAIL("fuzzing test crash", "int(new{ class auto ref x = Foo; void Foo(", "ERROR: type name expected after 'new'"); TEST_FOR_FAIL("fuzzing test crash", "class a; a(); class a{}", "ERROR: type 'a' is not fully defined"); diff --git a/tests/TestConversions.cpp b/tests/TestConversions.cpp index 1232b8c91..0689f2f05 100644 --- a/tests/TestConversions.cpp +++ b/tests/TestConversions.cpp @@ -46,7 +46,7 @@ TEST_RESULT("Auto ref to value conversion", testAutoRefToValue, "14"); const char *testImplicitConversionOnReturn = "class array{ int[10] arr; int size; }\r\n\ -void array:push_back(auto ref a){ arr[size++] = int(a); }\r\n\ +void array::push_back(auto ref a){ arr[size++] = int(a); }\r\n\ auto ref operator[](array ref arr, int index){ assert(index{ T x; U y; } int Pair:prod(){ return x * y; }"); +LOAD_MODULE(test_generic_type3, "test.generic_type3", "class Pair{ T x; U y; } int Pair::prod(){ return x * y; }"); const char *testGenericType19 = "import test.generic_type2;\r\n\ Pair z; z.x = 4; z.y = 2.5;\r\n\ @@ -351,7 +351,7 @@ TEST_RESULT("Function that accepts generic type 2", testGenericType24, "-6"); const char *testGenericType25 = "class Foo{ T x; }\r\n\ -auto Foo:foo(){ T y = 7; return x + y; }\r\n\ +auto Foo::foo(){ T y = 7; return x + y; }\r\n\ Foo a; a.x = 4;\r\n\ return a.foo();"; TEST_RESULT("Generic type external member function aliases restore", testGenericType25, "11"); @@ -448,7 +448,7 @@ TEST_RESULT("Generic type specialization to reference type 2", testGenericType35 const char *testGenericType36 = "class Foo{ T a; }\r\n\ -auto Foo:foo(){ return 2*a; }\r\n\ +auto Foo::foo(){ return 2*a; }\r\n\ Foo x; x.a = 4; Foo s; s.a = 40;\r\n\ auto y = x.foo;\r\n\ auto z = s.foo;\r\n\ @@ -457,8 +457,8 @@ TEST_RESULT("Taking pointer to a generic type member function", testGenericType3 const char *testGenericType37 = "class Foo{ T a; }\r\n\ -auto Foo:foo(){ return 2*a; }\r\n\ -int Foo:foo(){ return -a; }\r\n\ +auto Foo::foo(){ return 2*a; }\r\n\ +int Foo::foo(){ return -a; }\r\n\ Foo x; x.a = 4; Foo s; s.a = 40;\r\n\ auto y = x.foo;\r\n\ auto z = s.foo;\r\n\ @@ -471,7 +471,7 @@ const char *testGenericType38 = T a;\r\n\ auto foo(){ return -a; }\r\n\ }\r\n\ -int Foo:foo(){ return 2*a; }\r\n\ +int Foo::foo(){ return 2*a; }\r\n\ \r\n\ Foo x; x.a = 4; Foo s; s.a = 40;\r\n\ auto y = x.foo;\r\n\ @@ -487,7 +487,7 @@ const char *testGenericType39 = auto bar(int x){ return -x; }\r\n\ auto bar(float x){ return 2*x; }\r\n\ }\r\n\ -int Foo:foo()\r\n\ +int Foo::foo()\r\n\ {\r\n\ int ref(int) m = bar;\r\n\ return m(a);\r\n\ @@ -501,7 +501,7 @@ TEST_RESULT("Function call by pointer in a member function", testGenericType39, const char *testGenericType40 = "class Foo{ T x; }\r\n\ -void Foo:set(T x){ assert(typeof(x) == double); this.x = x; }\r\n\ +void Foo::set(T x){ assert(typeof(x) == double); this.x = x; }\r\n\ Foo m;\r\n\ m.set(4);\r\n\ return int(m.x * 1.5);"; @@ -509,8 +509,8 @@ TEST_RESULT("Generic type aliases are available in external unspecialized member const char *testGenericType41 = "class Factorial{}\r\n\ -auto Factorial:get(){ T arr; return arr; }\r\n\ -auto Factorial:get()\r\n\ +auto Factorial::get(){ T arr; return arr; }\r\n\ +auto Factorial::get()\r\n\ {\r\n\ Factorial x;\r\n\ int[typeof(x.get()).target.arraySize] ref m; // arraysize > 1 ? arraysize - 1 : 1;\r\n\ @@ -736,14 +736,14 @@ const char *testGenericType50 = {\r\n\ T x;\r\n\ }\r\n\ -void Foo:Foo(){ x = 4; }\r\n\ +void Foo::Foo(){ x = 4; }\r\n\ Foo a;\r\n\ return a.x;"; TEST_RESULT("automatic constructor call for generic class instance on stack", testGenericType50, "4"); const char *testGenericType51 = "class Foo{ T x; }\r\n\ -auto Foo:bar(generic z){ return x - z; }\r\n\ +auto Foo::bar(generic z){ return x - z; }\r\n\ Foo h;\r\n\ h.x = 3;\r\n\ h.bar(3);\r\n\ @@ -755,16 +755,16 @@ const char *testGenericType52 = "class Foo{ T x; }\r\n\ Foo h;\r\n\ h.x = 3;\r\n\ -int Foo:bar(){ return 5; }\r\n\ +int Foo::bar(){ return 5; }\r\n\ h.bar();\r\n\ -int Foo:bar(int z){ return x - z; }\r\n\ +int Foo::bar(int z){ return x - z; }\r\n\ return h.bar(2);"; TEST_RESULT("generic type member function overload defined after first overload instantion is instanced", testGenericType52, "1"); const char *testGenericType53 = "class Foo{ T x; }\r\n\ -int Foo:bar(){ return 5; }\r\n\ -int Foo:bar(int z){ return x - z; }\r\n\ +int Foo::bar(){ return 5; }\r\n\ +int Foo::bar(int z){ return x - z; }\r\n\ Foo h;\r\n\ h.x = 3;\r\n\ return h.bar() + h.bar(1);"; @@ -793,14 +793,14 @@ TEST_RESULT("generic type accessor is instanced 2", testGenericType55, "0"); const char *testGenericType56 = "class Foo{ typedef int T; T x; }\r\n\ -auto Foo:bar(T z, generic y){ return x - z + y; }\r\n\ +auto Foo::bar(T z, generic y){ return x - z + y; }\r\n\ Foo h; h.x = 3;\r\n\ return h.bar(5, 3);"; TEST_RESULT("class typedef in a generic member function", testGenericType56, "1"); const char *testGenericType57 = "class Foo{ typedef int T; T x; }\r\n\ -auto Foo:bar(generic z, T y){ return x - z + y; }\r\n\ +auto Foo::bar(generic z, T y){ return x - z + y; }\r\n\ Foo h; h.x = 3;\r\n\ return h.bar(5, 3);"; TEST_RESULT("class typedef in a generic member function 2", testGenericType57, "1"); @@ -828,8 +828,8 @@ const char *testGenericType58b = {\r\n\ T y;\r\n\ }\r\n\ -int Foo:boo(int x){ return x * y; }\r\n\ -void Foo:Foo(T n){ y = n; }\r\n\ +int Foo::boo(int x){ return x * y; }\r\n\ +void Foo::Foo(T n){ y = n; }\r\n\ auto ref[2] arr;\r\n\ arr[0] = new Foo(3);\r\n\ arr[1] = new Foo(1.5);\r\n\ @@ -907,7 +907,7 @@ const char *testGenericType62b = "class Foo\r\n\ {\r\n\ }\r\n\ -int Foo:boo(auto ref[] x){ return x.size; }\r\n\ +int Foo::boo(auto ref[] x){ return x.size; }\r\n\ auto ref x = new Foo;\r\n\ return x.boo(1, 2, 3) + x.boo(1, 2);"; TEST_RESULT("Function call through 'auto ref' for generic type, selection of a variable argument function 2", testGenericType62b, "5"); @@ -1145,7 +1145,7 @@ LOAD_MODULE(test_generic_type73, "test.generic_type73", "class Foo{ T x; }"); const char *testGenericType73 = "import test.generic_type73;\r\n\ -int Foo:foo(){ return -x; }\r\n\ +int Foo::foo(){ return -x; }\r\n\ Foo x;\r\n\ x.x = 10;\r\n\ return x.foo();"; @@ -1153,7 +1153,7 @@ TEST_RESULT("Generic type specialized external function definition", testGeneric const char *testGenericType74 = "import test.generic_type73;\r\n\ -int Foo:foo(){ @if(typeof(this.x) == int) return x; else return -x; }\r\n\ +int Foo::foo(){ @if(typeof(this.x) == int) return x; else return -x; }\r\n\ Foo x;\r\n\ Foo z;\r\n\ x.x = 10;\r\n\ @@ -1163,12 +1163,12 @@ TEST_RESULT("Generic type external member function definition", testGenericType7 const char *testGenericType75 = "import test.generic_type73;\r\n\ -int Foo:foo(){ return -x; }\r\n\ -int Foo:foo(){ return 2*x; }\r\n\ +int Foo::foo(){ return -x; }\r\n\ +int Foo::foo(){ return 2*x; }\r\n\ \r\n\ Foo x;\r\n\ \r\n\ -int Foo:bar(){ return 9; }\r\n\ +int Foo::bar(){ return 9; }\r\n\ \r\n\ Foo z;\r\n\ x.x = 10;\r\n\ @@ -1178,12 +1178,12 @@ TEST_RESULT("Generic type external member function definition after instancing", const char *testGenericType76 = "import test.generic_type73;\r\n\ -int Foo:foo(){ return -x; }\r\n\ -int Foo:foo(){ return 2*x; }\r\n\ +int Foo::foo(){ return -x; }\r\n\ +int Foo::foo(){ return 2*x; }\r\n\ \r\n\ Foo x;\r\n\ \r\n\ -int Foo:bar(){ return 9; }\r\n\ +int Foo::bar(){ return 9; }\r\n\ \r\n\ Foo z;\r\n\ x.x = 10;\r\n\ @@ -1235,7 +1235,7 @@ TEST_RESULT("Function that accepts generic type 2", testGenericType80, "-6"); const char *testGenericType81 = "import test.generic_type73;\r\n\ \r\n\ -auto Foo:foo(){ T y = 7; return x + y; }\r\n\ +auto Foo::foo(){ T y = 7; return x + y; }\r\n\ Foo a; a.x = 4;\r\n\ return a.foo();"; TEST_RESULT("Generic type external member function aliases restore", testGenericType81, "11"); @@ -1351,7 +1351,7 @@ LOAD_MODULE(test_generic_type92, "test.generic_type92", const char *testGenericType92 = "import test.generic_type92;\r\n\ \r\n\ -auto Foo:foo(){ return 2*a; }\r\n\ +auto Foo::foo(){ return 2*a; }\r\n\ Foo x; x.a = 4; Foo s; s.a = 40;\r\n\ auto y = x.foo;\r\n\ auto z = s.foo;\r\n\ @@ -1363,8 +1363,8 @@ LOAD_MODULE(test_generic_type93, "test.generic_type93", const char *testGenericType93 = "import test.generic_type93;\r\n\ \r\n\ -auto Foo:foo(){ return 2*a; }\r\n\ -int Foo:foo(){ return -a; }\r\n\ +auto Foo::foo(){ return 2*a; }\r\n\ +int Foo::foo(){ return -a; }\r\n\ Foo x; x.a = 4; Foo s; s.a = 40;\r\n\ auto y = x.foo;\r\n\ auto z = s.foo;\r\n\ @@ -1380,7 +1380,7 @@ LOAD_MODULE(test_generic_type94, "test.generic_type94", const char *testGenericType94 = "import test.generic_type94;\r\n\ \r\n\ -int Foo:foo(){ return 2*a; }\r\n\ +int Foo::foo(){ return 2*a; }\r\n\ \r\n\ Foo x; x.a = 4; Foo s; s.a = 40;\r\n\ auto y = x.foo;\r\n\ @@ -1399,7 +1399,7 @@ LOAD_MODULE(test_generic_type95, "test.generic_type95", const char *testGenericType95 = "import test.generic_type95;\r\n\ \r\n\ -int Foo:foo()\r\n\ +int Foo::foo()\r\n\ {\r\n\ int ref(int) m = bar;\r\n\ return m(a);\r\n\ @@ -1414,7 +1414,7 @@ TEST_RESULT("Function call by pointer in a member function", testGenericType95, const char *testGenericType96 = "import test.generic_type73;\r\n\ \r\n\ -void Foo:set(T x){ assert(typeof(x) == double); this.x = x; }\r\n\ +void Foo::set(T x){ assert(typeof(x) == double); this.x = x; }\r\n\ Foo m;\r\n\ m.set(4);\r\n\ return int(m.x * 1.5);"; @@ -1425,8 +1425,8 @@ LOAD_MODULE(test_generic_type97, "test.generic_type97", const char *testGenericType97 = "import test.generic_type97;\r\n\ \r\n\ -auto Factorial:get(){ T arr; return arr; }\r\n\ -auto Factorial:get()\r\n\ +auto Factorial::get(){ T arr; return arr; }\r\n\ +auto Factorial::get()\r\n\ {\r\n\ Factorial x;\r\n\ int[typeof(x.get()).target.arraySize] ref m; // arraysize > 1 ? arraysize - 1 : 1;\r\n\ @@ -1670,7 +1670,7 @@ TEST_RESULT("Generic function is specialized for reference type but a non-refere const char *testGenericType106 = "import test.generic_type73;\r\n\ \r\n\ -void Foo:Foo(){ x = 4; }\r\n\ +void Foo::Foo(){ x = 4; }\r\n\ Foo a;\r\n\ return a.x;"; TEST_RESULT("automatic constructor call for generic class instance on stack", testGenericType106, "4"); @@ -1678,7 +1678,7 @@ TEST_RESULT("automatic constructor call for generic class instance on stack", te const char *testGenericType107 = "import test.generic_type73;\r\n\ \r\n\ -auto Foo:bar(generic z){ return x - z; }\r\n\ +auto Foo::bar(generic z){ return x - z; }\r\n\ Foo h;\r\n\ h.x = 3;\r\n\ h.bar(3);\r\n\ @@ -1691,17 +1691,17 @@ const char *testGenericType108 = \r\n\ Foo h;\r\n\ h.x = 3;\r\n\ -int Foo:bar(){ return 5; }\r\n\ +int Foo::bar(){ return 5; }\r\n\ h.bar();\r\n\ -int Foo:bar(int z){ return x - z; }\r\n\ +int Foo::bar(int z){ return x - z; }\r\n\ return h.bar(2);"; TEST_RESULT("generic type member function overload defined after first overload instantion is instanced", testGenericType108, "1"); const char *testGenericType109 = "import test.generic_type73;\r\n\ \r\n\ -int Foo:bar(){ return 5; }\r\n\ -int Foo:bar(int z){ return x - z; }\r\n\ +int Foo::bar(){ return 5; }\r\n\ +int Foo::bar(int z){ return x - z; }\r\n\ Foo h;\r\n\ h.x = 3;\r\n\ return h.bar() + h.bar(1);"; @@ -1755,8 +1755,8 @@ TEST_RESULT("generic type member function call through 'auto ref'", testGenericT LOAD_MODULE(test_generic_type114b, "test.generic_type114b", "class Foo{ T y; }\r\n\ -int Foo:boo(int x){ return x * y; }\r\n\ -void Foo:Foo(T n){ y = n; }"); +int Foo::boo(int x){ return x * y; }\r\n\ +void Foo::Foo(T n){ y = n; }"); const char *testGenericType114b = "import test.generic_type114b;\r\n\ \r\n\ @@ -1844,7 +1844,7 @@ TEST_RESULT("Function call through 'auto ref' for generic type, selection of a v LOAD_MODULE(test_generic_type118b, "test.generic_type118b", "class Foo{}\r\n\ -int Foo:boo(auto ref[] x){ return x.size; }"); +int Foo::boo(auto ref[] x){ return x.size; }"); const char *testGenericType118b = "import test.generic_type118b;\r\n\ \r\n\ @@ -1854,24 +1854,24 @@ TEST_RESULT("Function call through 'auto ref' for generic type, selection of a v const char *testGenericType119 = "class Foo{ T x; }\r\n\ -auto Foo:sum(generic ref(T) f){ return f(10); }\r\n\ -auto Foo:average(generic ref(T) f){ return sum(f) / 2; }\r\n\ +auto Foo::sum(generic ref(T) f){ return f(10); }\r\n\ +auto Foo::average(generic ref(T) f){ return sum(f) / 2; }\r\n\ Foo m;\r\n\ return m.average({ -i; });"; TEST_RESULT("generic member function instancing in a generic member function", testGenericType119, "-5"); const char *testGenericType120 = "import test.generic_type73;\r\n\ -auto Foo:sum(generic ref(T) f){ auto o = x; return f(10); }\r\n\ -auto Foo:average(generic ref(T) f){ return sum(f) / x; }\r\n\ +auto Foo::sum(generic ref(T) f){ auto o = x; return f(10); }\r\n\ +auto Foo::average(generic ref(T) f){ return sum(f) / x; }\r\n\ Foo m; m.x = 2;\r\n\ return m.average({ -i; });"; TEST_RESULT("generic member function instancing in a generic member function (imported class)", testGenericType120, "-5"); LOAD_MODULE(test_generic_type121, "test.generic_type121", "class Foo{ T x; }\r\n\ -auto Foo:sum(generic ref(T) f){ auto o = x; return f(10); }\r\n\ -auto Foo:average(generic ref(T) f){ return sum(f) / x; }"); +auto Foo::sum(generic ref(T) f){ auto o = x; return f(10); }\r\n\ +auto Foo::average(generic ref(T) f){ return sum(f) / x; }"); const char *testGenericType121 = "import test.generic_type121;\r\n\ Foo m; m.x = 2;\r\n\ @@ -1908,7 +1908,7 @@ TEST_RESULT("short inline function in argument with function with generic type d const char *testGenericType124 = "class Foo{}\r\n\ -int Foo:foo(T ref x){ return *x; }\r\n\ +int Foo::foo(T ref x){ return *x; }\r\n\ Foo x;\r\n\ return x.foo(1) + x.foo(2);"; TEST_RESULT("when generic type member function is instanced, aliases are from instanced type", testGenericType124, "3"); @@ -1916,7 +1916,7 @@ TEST_RESULT("when generic type member function is instanced, aliases are from in const char *testGenericType125 = "class Node{}\r\n\ class Foo{}\r\n\ -auto Node:first(int hash)\r\n\ +auto Node::first(int hash)\r\n\ {\r\n\ Foo ref curr;\r\n\ return coroutine auto generator()\r\n\ @@ -2091,7 +2091,7 @@ auto bar(generic x){ @if(typeof(x).isReference) return x; else return &x; }\r\n\ \r\n\ class Foo{}\r\n\ \r\n\ -typeid Foo:foo(typeof(bar(T())) e){ return typeof(e); }\r\n\ +typeid Foo::foo(typeof(bar(T())) e){ return typeof(e); }\r\n\ \r\n\ Foo test1;\r\n\ assert(test1.foo(4) == int ref);\r\n\ @@ -2249,7 +2249,7 @@ const char *testAccessorAccessInsideAMemberFunctionGeneric = auto Foo.x(){ return _x; }\r\n\ void Foo.x(T r){ _x = r / 2; }\r\n\ \r\n\ -void Foo:Foo(){ x = 4; }\r\n\ +void Foo::Foo(){ x = 4; }\r\n\ \r\n\ Foo a;\r\n\ return a.x;"; @@ -2288,11 +2288,11 @@ class hashmap\r\n\ Node ref entry;\r\n\ int x;\r\n\ }\r\n\ -void hashmap:hashmap()\r\n\ +void hashmap::hashmap()\r\n\ {\r\n\ x = 5;\r\n\ }\r\n\ -void hashmap:foo()\r\n\ +void hashmap::foo()\r\n\ {\r\n\ entry = new Node;\r\n\ }\r\n\ @@ -2429,7 +2429,7 @@ TEST_RESULT("Generic class name can be used if the generic arguments can be dedu const char *testGenericType148 = "class F{}\r\n\ -int F:f(){ return 2; }\r\n\ +int F::f(){ return 2; }\r\n\ F a;\r\n\ int operator+(int a, int ref() b){ return a + b(); }\r\n\ return 1 + a.f;"; @@ -2437,9 +2437,9 @@ TEST_RESULT("Generic class function pointer access performs instantiation", test const char *testGenericType149 = "class F{}\r\n\ -int F:f(){ return 2; }\r\n\ -float F:f(){ return 2; }\r\n\ -double F:f(){ return 2; }\r\n\ +int F::f(){ return 2; }\r\n\ +float F::f(){ return 2; }\r\n\ +double F::f(){ return 2; }\r\n\ F a;\r\n\ int operator+(int a, int ref() b){ return a + b(); }\r\n\ return 1 + a.f;"; @@ -2447,7 +2447,7 @@ TEST_RESULT("Generic class function pointer access performs instantiation", test const char *testGenericType150 = "class Foo{}\r\n\ -auto Foo:foo(){ return sizeof(T); }\r\n\ +auto Foo::foo(){ return sizeof(T); }\r\n\ \r\n\ Foo a;\r\n\ Foo b;\r\n\ @@ -2460,8 +2460,8 @@ TEST_RESULT("Generic class external function definition and auto ref calls", tes const char *testGenericType151 = "class Foo{}\r\n\ -auto Foo:foo(){ return sizeof(T); }\r\n\ -auto Foo:foo(int x){ return sizeof(T) + x; }\r\n\ +auto Foo::foo(){ return sizeof(T); }\r\n\ +auto Foo::foo(int x){ return sizeof(T) + x; }\r\n\ \r\n\ Foo a;\r\n\ Foo b;\r\n\ @@ -2474,7 +2474,7 @@ TEST_RESULT("Generic class external function definition and auto ref calls (over const char *testGenericType152 = "class Foo{}\r\n\ -auto Foo:foo(generic x){ return sizeof(T) * 10 + sizeof(x); }\r\n\ +auto Foo::foo(generic x){ return sizeof(T) * 10 + sizeof(x); }\r\n\ \r\n\ Foo a;\r\n\ Foo b;\r\n\ @@ -2487,10 +2487,10 @@ TEST_RESULT("Generic class external function definition and auto ref calls (gene const char *testGenericType153 = "class Foo{}\r\n\ -auto Foo:foo(generic x){ return sizeof(T) * 10 + sizeof(x); }\r\n\ +auto Foo::foo(generic x){ return sizeof(T) * 10 + sizeof(x); }\r\n\ \r\n\ class Bar{}\r\n\ -auto Bar:foo(generic x){ return 100; }\r\n\ +auto Bar::foo(generic x){ return 100; }\r\n\ \r\n\ Foo a;\r\n\ Bar b;\r\n\ diff --git a/tests/TestIndirectCall.cpp b/tests/TestIndirectCall.cpp index 2a5af8091..b0cccf9e3 100644 --- a/tests/TestIndirectCall.cpp +++ b/tests/TestIndirectCall.cpp @@ -99,7 +99,7 @@ TEST("Class function return", testClassFuncReturn, "1") const char *testMemberFuncCallRef = "typedef char[] string;\r\n\ \r\n\ -void string:set(int a)\r\n\ +void string::set(int a)\r\n\ {\r\n\ this[0] = a;\r\n\ }\r\n\ @@ -121,7 +121,7 @@ TEST_RESULT("Indirect function call in member function 2", testIndirectCallInMem const char *testFunctionTypeMemberSelfcall = "int foo(int x){ return -x; }\r\n\ typedef int ref(int) omg;\r\n\ -int omg:call(int x){ return (*this)(x); }\r\n\ +int omg::call(int x){ return (*this)(x); }\r\n\ auto ref x = duplicate(foo);\r\n\ return x.call(5);"; TEST_RESULT("Function type member function that calls itself", testFunctionTypeMemberSelfcall, "-5"); diff --git a/tests/TestInference.cpp b/tests/TestInference.cpp index 0b5ac051f..22dfac548 100644 --- a/tests/TestInference.cpp +++ b/tests/TestInference.cpp @@ -424,28 +424,28 @@ const char *testSizeofInExternalFunction = {\r\n\ int k;\r\n\ }\r\n\ -auto Foo:s(){ return sizeof(Foo); }\r\n\ +auto Foo::s(){ return sizeof(Foo); }\r\n\ Foo m;\r\n\ return m.s();"; TEST_RESULT("sizeof in external member function", testSizeofInExternalFunction, "4"); const char *testShortFunctionInMemberFunctionCall = "class Foo{}\r\n\ -auto Foo:average(generic ref(int) f){ return f(5); }\r\n\ +auto Foo::average(generic ref(int) f){ return f(5); }\r\n\ Foo m;\r\n\ return m.average({ 5+x; });"; TEST_RESULT("short function in a member function call", testShortFunctionInMemberFunctionCall, "10"); const char *testShortFunctionInMemberFunctionCall2 = "class Foo{}\r\n\ -auto Foo:average(generic ref(int) f){ return f(5); }\r\n\ +auto Foo::average(generic ref(int) f){ return f(5); }\r\n\ Foo m;\r\n\ return m.average({ 5+x; });"; TEST_RESULT("short function in a generic type member function call", testShortFunctionInMemberFunctionCall2, "10"); const char *testShortFunctionInMemberFunctionCall3 = "class Foo{}\r\n\ -auto Foo:average(generic ref(int, T) f){ return f(5, 4); }\r\n\ +auto Foo::average(generic ref(int, T) f){ return f(5, 4); }\r\n\ Foo m;\r\n\ return m.average({ 5+x+y; });"; TEST_RESULT("short function in a generic type member function call with generic type aliases", testShortFunctionInMemberFunctionCall3, "14"); @@ -477,7 +477,7 @@ const char *testShortFunctionInMemberFunctionCall6 = typedef int T;\r\n\ auto average(generic ref(T) f){ return f(5); }\r\n\ }\r\n\ -auto Foo:foo(){ return average({ -i; }); }\r\n\ +auto Foo::foo(){ return average({ -i; }); }\r\n\ Foo k;\r\n\ return k.foo();"; TEST_RESULT("short function in a member function call in a member function with aliases", testShortFunctionInMemberFunctionCall6, "-5"); @@ -489,7 +489,7 @@ class Foo\r\n\ typedef int T;\r\n\ auto average(int ref(T) f){ return f(5); }\r\n\ }\r\n\ -auto Foo:foo(){ return average({ -i; }); }\r\n\ +auto Foo::foo(){ return average({ -i; }); }\r\n\ Foo k;\r\n\ return k.foo();"; TEST_RESULT("short function in a member function call in a member function correct selection", testShortFunctionInMemberFunctionCall7, "-5"); @@ -545,7 +545,7 @@ const char *testGenericTypePointerResolve3 = int boo(int x){ return x * y; }\r\n\ }\r\n\ Foo x; x.y = 6;\r\n\ -auto Foo:foo()\r\n\ +auto Foo::foo()\r\n\ {\r\n\ int ref(double) m = x.boo;\r\n\ return m(2.5);\r\n\ @@ -560,7 +560,7 @@ const char *testGenericTypePointerResolve4 = int boo(generic x){ return x * y; }\r\n\ }\r\n\ Foo x; x.y = 6;\r\n\ -auto Foo:foo()\r\n\ +auto Foo::foo()\r\n\ {\r\n\ int ref(double) m = x.boo;\r\n\ return m(2.5);\r\n\ diff --git a/tests/TestInheritance.cpp b/tests/TestInheritance.cpp index 572a50a35..edac0bd95 100644 --- a/tests/TestInheritance.cpp +++ b/tests/TestInheritance.cpp @@ -540,7 +540,7 @@ const char *testInheritance46 = int c;\r\n\ }\r\n\ \r\n\ -void Test:Test()\r\n\ +void Test::Test()\r\n\ {\r\n\ a = 1;\r\n\ b = 2;\r\n\ @@ -552,7 +552,7 @@ class Test2 : Test\r\n\ int d;\r\n\ }\r\n\ \r\n\ -void Test2 : Test2()\r\n\ +void Test2 :: Test2()\r\n\ {\r\n\ d = 10;\r\n\ }\r\n\ diff --git a/tests/TestListComprehension.cpp b/tests/TestListComprehension.cpp index 6d0481d9e..a420d37a2 100644 --- a/tests/TestListComprehension.cpp +++ b/tests/TestListComprehension.cpp @@ -68,7 +68,7 @@ TEST_RESULT("List comprehension with explicit return", testListComprehensionRetu const char *testListComprehensionRef = "class Foo{ int a; }\r\n\ -void Foo:Foo(int x){ a = x; }\r\n\ +void Foo::Foo(int x){ a = x; }\r\n\ auto x = { for(int i=0;i<4;i++) yield new Foo(10+i); };\r\n\ int z = 0; for(i in x) z += i.a;\r\n\ return z;"; diff --git a/tests/TestLocalClass.cpp b/tests/TestLocalClass.cpp index cf505a28a..c9c39b645 100644 --- a/tests/TestLocalClass.cpp +++ b/tests/TestLocalClass.cpp @@ -24,7 +24,7 @@ const char *testLocalClass3 = "int foo(int x)\r\n\ {\r\n\ class X{ int i; int bar(){ return -i; } }\r\n\ - int X:foo(){ return this.i * 2; }\r\n\ + int X::foo(){ return this.i * 2; }\r\n\ X a;\r\n\ a.i = x;\r\n\ return a.foo();\r\n\ @@ -36,7 +36,7 @@ const char *testLocalClass4 = "class X{ int i; int bar(){ return -i; } }\r\n\ int foo(int x)\r\n\ {\r\n\ - int X:foo(){ return i * 2; }\r\n\ + int X::foo(){ return i * 2; }\r\n\ X a;\r\n\ a.i = x;\r\n\ return a.foo();\r\n\ @@ -48,7 +48,7 @@ const char *testLocalClass5 = "int foo(int x)\r\n\ {\r\n\ class X{ int i; int bar(){ return -i; } }\r\n\ - int X:foo(){ return i * 2; }\r\n\ + int X::foo(){ return i * 2; }\r\n\ X a;\r\n\ a.i = x;\r\n\ return a.bar();\r\n\ @@ -60,7 +60,7 @@ const char *testLocalClass6 = "int foo(int x)\r\n\ {\r\n\ class X{ int i; int bar(){ return -i; } }\r\n\ - int X:foo(){ return i * 2; }\r\n\ + int X::foo(){ return i * 2; }\r\n\ X a;\r\n\ a.i = x;\r\n\ return a.foo();\r\n\ diff --git a/tests/TestMembers.cpp b/tests/TestMembers.cpp index fdae8918c..0f5aa5ee4 100644 --- a/tests/TestMembers.cpp +++ b/tests/TestMembers.cpp @@ -18,7 +18,7 @@ return 1;"; TEST_RESULT("Class method test", testClassMethod, "1"); const char *testClassExternalMethodInt = -"auto int:toString()\r\n\ +"auto int::toString()\r\n\ {\r\n\ int copy = *this, len = 0;\r\n\ while(copy)\r\n\ @@ -42,7 +42,7 @@ TEST_RESULT("Class externally defined method (int)", testClassExternalMethodInt, const char *testClassMethodString = "typedef char[] string;\r\n\ -string string:reverse()\r\n\ +string string::reverse()\r\n\ {\r\n\ for(int i = 0; i < (this.size-1) / 2; i++)\r\n\ {\r\n\ @@ -63,7 +63,7 @@ const char *testClassExternalMethod = int bar;\r\n\ }\r\n\ \r\n\ -int Foo:GetBar(){ return bar; }\r\n\ +int Foo::GetBar(){ return bar; }\r\n\ Foo a;\r\n\ a.bar = 14;\r\n\ \r\n\ diff --git a/tests/TestMisc.cpp b/tests/TestMisc.cpp index 009fb6f51..f51539fb8 100644 --- a/tests/TestMisc.cpp +++ b/tests/TestMisc.cpp @@ -165,13 +165,13 @@ TEST_RESULT("Function prototype is implemented at a correct time", testFunctionP const char *testFunctionPrototypes4 = "class Test{ int f(); }\r\n\ -int Test:f(){ return 2; }\r\n\ +int Test::f(){ return 2; }\r\n\ return Test().f();"; TEST_RESULT("Member function prototype implementation in a different scope 1", testFunctionPrototypes4, "2"); const char *testFunctionPrototypes5 = "class Test{ int f(int a); }\r\n\ -int Test:f(int a){ if(a) return f(0); return 10; }\r\n\ +int Test::f(int a){ if(a) return f(0); return 10; }\r\n\ return Test().f(1);"; TEST_RESULT("Member function prototype implementation in a different scope 2", testFunctionPrototypes5, "10"); diff --git a/tests/TestNamespace.cpp b/tests/TestNamespace.cpp index 2a3bf0fd9..1355ea1df 100644 --- a/tests/TestNamespace.cpp +++ b/tests/TestNamespace.cpp @@ -600,7 +600,7 @@ const char *testNamespace50 = {\r\n\ class Foo{ T x; }\r\n\ int bar(int x){ return x * 2; }\r\n\ - int Foo:foo(){ return bar(5); }\r\n\ + int Foo::foo(){ return bar(5); }\r\n\ }\r\n\ namespace Bar\r\n\ {\r\n\ @@ -690,7 +690,7 @@ const char *testNamespace56 = namespace Test\r\n\ {\r\n\ class Device{ Canvas ref canvas; }\r\n\ - void Device:Device( Canvas ref canvas )\r\n\ + void Device::Device( Canvas ref canvas )\r\n\ {\r\n\ this.canvas = canvas;\r\n\ }\r\n\ @@ -749,7 +749,7 @@ TEST_RESULT("namespace test 61", testNamespace61, "-10"); const char *testNamespace62 = "class X{}\r\n\ -int X:pos(){ return 10; }\r\n\ +int X::pos(){ return 10; }\r\n\ \r\n\ namespace B\r\n\ {\r\n\ diff --git a/tests/TestNew.cpp b/tests/TestNew.cpp index a46b163e1..d4fb3e45a 100644 --- a/tests/TestNew.cpp +++ b/tests/TestNew.cpp @@ -23,16 +23,16 @@ return b[0]() + b[1]() + b[4]();"; TEST_RESULT("new call with typeof", testTypeOfNew, "8"); const char *testConstructorAfterNew = -"void int:int(int x, y){ *this = x; }\r\n\ +"void int::int(int x, y){ *this = x; }\r\n\ int ref a = new int(5, 0);\r\n\ int foo(int ref x){ return *x; }\r\n\ return *a + foo(new int(30, 0));"; TEST_RESULT("Type constructor after new.", testConstructorAfterNew, "35"); -const char *testConstructorAfterNew2 = "class Test{ int x; } void Test:Test(int x){ this.x = x; } return (new Test(4)).x;"; +const char *testConstructorAfterNew2 = "class Test{ int x; } void Test::Test(int x){ this.x = x; } return (new Test(4)).x;"; TEST_RESULT("Type constructor after new 2.", testConstructorAfterNew2, "4"); -const char *testConstructorAfterNew3 = "class Test{ int x; } void Test:Test(){ } return (new Test()).x;"; +const char *testConstructorAfterNew3 = "class Test{ int x; } void Test::Test(){ } return (new Test()).x;"; TEST_RESULT("Type constructor after new 3.", testConstructorAfterNew3, "0"); const char *testTypeChangeInArrayExpression = "int[] arr = new int[(int f(){ return 5; })()]; return arr.size;"; diff --git a/tests/TestPostExpr.cpp b/tests/TestPostExpr.cpp index 1fb446f1f..77a5cf3fc 100644 --- a/tests/TestPostExpr.cpp +++ b/tests/TestPostExpr.cpp @@ -3,7 +3,7 @@ const char *testPostExpressions = "typedef char[] string;\r\n\ \r\n\ -int string:find(char a)\r\n\ +int string::find(char a)\r\n\ {\r\n\ int i = 0;\r\n\ while(i < this.size && this[i] != a)\r\n\ diff --git a/tests/TestRuntimeFail.cpp b/tests/TestRuntimeFail.cpp index a8993b45f..0c84e3d9c 100644 --- a/tests/TestRuntimeFail.cpp +++ b/tests/TestRuntimeFail.cpp @@ -91,7 +91,7 @@ TEST_RUNTIME_FAIL("Iteration over a a function that is not a coroutine [failure const char *testTypeDoesntImplementMethod = "class Foo{ int i; }\r\n\ -void Foo:test(){ assert(i); }\r\n\ +void Foo::test(){ assert(i); }\r\n\ Foo test; test.i = 5;\r\n\ auto ref[2] objs;\r\n\ objs[0] = &test;\r\n\ diff --git a/tests/TestScope.cpp b/tests/TestScope.cpp index a14ef1a25..902f80d3e 100644 --- a/tests/TestScope.cpp +++ b/tests/TestScope.cpp @@ -105,7 +105,7 @@ const char *testTypedefScopeTypeReturn = typedef int[2] data;\r\n\ data x;\r\n\ }\r\n\ -int TypeA:func(){ data y = x; return y[0] * y[1]; }\r\n\ +int TypeA::func(){ data y = x; return y[0] * y[1]; }\r\n\ TypeA a;\r\n\ a.x[0] = 5; a.x[1] = 4;\r\n\ class TypeB\r\n\ @@ -113,7 +113,7 @@ class TypeB\r\n\ typedef float[2] data;\r\n\ data x;\r\n\ }\r\n\ -int TypeB:func(){ data y = x; return y[0] / y[1]; }\r\n\ +int TypeB::func(){ data y = x; return y[0] / y[1]; }\r\n\ TypeB b;\r\n\ b.x[0] = 3.6; b.x[1] = 0.5;\r\n\ typedef int data;\r\n\ diff --git a/tests/TestSglList.cpp b/tests/TestSglList.cpp index 43ba8b429..356723c2d 100644 --- a/tests/TestSglList.cpp +++ b/tests/TestSglList.cpp @@ -5,25 +5,25 @@ auto list_node.value(); auto list_node.value(T ref val); -void list:list(); +void list::list(); -void list:push_back(T ref elem);! -void list:push_front(T ref elem);! -void list:pop_back();! -void list:pop_front();! -void list:insert(list_node ref it, T ref elem); -void list:erase(list_node ref it); -void list:clear();! -auto list:back();! -auto list:front();! -auto list:begin(); -auto list:end(); -int list:empty();! +void list::push_back(T ref elem);! +void list::push_front(T ref elem);! +void list::pop_back();! +void list::pop_front();! +void list::insert(list_node ref it, T ref elem); +void list::erase(list_node ref it); +void list::clear();! +auto list::back();! +auto list::front();! +auto list::begin(); +auto list::end(); +int list::empty();! -auto list_iterator:list_iterator(list_node ref start); -auto list:start();! -auto list_iterator:next();! -auto list_iterator:hasnext();! +auto list_iterator::list_iterator(list_node ref start); +auto list::start();! +auto list_iterator::next();! +auto list_iterator::hasnext();! */ const char *testSglList1 = diff --git a/tests/TestSpecial.cpp b/tests/TestSpecial.cpp index 945e27e78..3ced402c0 100644 --- a/tests/TestSpecial.cpp +++ b/tests/TestSpecial.cpp @@ -486,23 +486,23 @@ const char *testVectorSplice = T[] data;\r\n\ int count;\r\n\ }\r\n\ -void vector:push_back(generic val)\r\n\ +void vector::push_back(generic val)\r\n\ {\r\n\ if(count == data.size)\r\n\ this.grow();\r\n\ data[count++] = val;\r\n\ }\r\n\ -void vector:pop_back()\r\n\ +void vector::pop_back()\r\n\ {\r\n\ assert(count);\r\n\ count--;\r\n\ }\r\n\ -auto vector:back()\r\n\ +auto vector::back()\r\n\ {\r\n\ assert(count);\r\n\ return &data[count - 1];\r\n\ }\r\n\ -auto vector:front()\r\n\ +auto vector::front()\r\n\ {\r\n\ assert(count);\r\n\ return &data[0];\r\n\ @@ -512,7 +512,7 @@ auto operator[](vector ref v, int index)\r\n\ assert(index < v.count);\r\n\ return &v.data[index];\r\n\ }\r\n\ -void vector:grow()\r\n\ +void vector::grow()\r\n\ {\r\n\ int nReserved = data.size + (data.size >> 1) + 1;\r\n\ T[] nArr = new T[nReserved];\r\n\ @@ -520,7 +520,7 @@ void vector:grow()\r\n\ j = i;\r\n\ data = nArr;\r\n\ }\r\n\ -auto vector:size()\r\n\ +auto vector::size()\r\n\ {\r\n\ return count;\r\n\ }\r\n\ diff --git a/tests/TestSpeed.cpp b/tests/TestSpeed.cpp index 3114654ee..9c11c995d 100644 --- a/tests/TestSpeed.cpp +++ b/tests/TestSpeed.cpp @@ -579,12 +579,12 @@ class SphereNode\r\n\ Sphere ref sphere;\r\n\ SphereNode ref next;\r\n\ }\r\n\ -auto SphereNode:init(Sphere ref sphere)\r\n\ +auto SphereNode::init(Sphere ref sphere)\r\n\ {\r\n\ this.sphere = sphere;\r\n\ return this;\r\n\ }\r\n\ -auto SphereNode:add(Sphere ref sphere)\r\n\ +auto SphereNode::add(Sphere ref sphere)\r\n\ {\r\n\ next = new SphereNode;\r\n\ next.init(sphere);\r\n\ diff --git a/tests/nullc_in_nullc/analyzer.nc b/tests/nullc_in_nullc/analyzer.nc index 57ee4fd5f..f0997e062 100644 --- a/tests/nullc_in_nullc/analyzer.nc +++ b/tests/nullc_in_nullc/analyzer.nc @@ -9,7 +9,7 @@ import binarycache; import std.error; import std.string; -void string:string(char[] right, int start, int end) +void string::string(char[] right, int start, int end) { assert(start <= end); assert(start >= 0 && start < right.size); @@ -21,7 +21,7 @@ void string:string(char[] right, int start, int end) data[i] = right[start + i]; } -void string:string(StringRef right) +void string::string(StringRef right) { int length; @@ -34,7 +34,7 @@ void string:string(StringRef right) data[i] = right.string[right.pos + i]; } -void string:string(char[] right, int pos) +void string::string(char[] right, int pos) { int length; @@ -47,7 +47,7 @@ void string:string(char[] right, int pos) data[i] = right[pos + i]; } -void string:string(InplaceStr right) +void string::string(InplaceStr right) { data = new char[right.end - right.begin + 1]; @@ -55,7 +55,7 @@ void string:string(InplaceStr right) data[i] = right[i]; } -void InplaceStr:InplaceStr(StringRef str) +void InplaceStr::InplaceStr(StringRef str) { data = str.string; begin = str.pos; diff --git a/tests/nullc_in_nullc/arrayview.nc b/tests/nullc_in_nullc/arrayview.nc index 4e6ffee85..8cbf0eb39 100644 --- a/tests/nullc_in_nullc/arrayview.nc +++ b/tests/nullc_in_nullc/arrayview.nc @@ -52,13 +52,13 @@ auto operator=(ArrayView<@T> ref lhs, vector<@T> ref rhs) return lhs; } -auto ArrayView:ArrayView(vector<@T> ref src) +auto ArrayView::ArrayView(vector<@T> ref src) { this.data = src.data; this.count = src.size(); } -auto ArrayView:ArrayView(vector<@T> ref src, int size) +auto ArrayView::ArrayView(vector<@T> ref src, int size) { assert(size <= src.size()); diff --git a/tests/nullc_in_nullc/common.nc b/tests/nullc_in_nullc/common.nc index 567eb7270..5220aab93 100644 --- a/tests/nullc_in_nullc/common.nc +++ b/tests/nullc_in_nullc/common.nc @@ -6,7 +6,7 @@ int hash_value(int key) return key * 2654435761l; } -auto hashmap:insert(Key key, Value value) +auto hashmap::insert(Key key, Value value) { int hash = compute_hash(key); int bucket = hash & bucketMask; @@ -30,12 +30,12 @@ auto hashmap:insert(Key key, Value value) return &n.value; } -bool vector:empty() +bool vector::empty() { return size() == 0; } -auto hashmap:first(Key key) +auto hashmap::first(Key key) { int hash = compute_hash(key); int bucket = hash & bucketMask; @@ -50,12 +50,12 @@ auto hashmap:first(Key key) return nullptr; } -bool hashmap:contains(Key key) +bool hashmap::contains(Key key) { return find(key) != nullptr; } -auto hashmap:next(hashmap_node ref node) +auto hashmap::next(hashmap_node ref node) { Node ref curr = node.next; @@ -70,7 +70,7 @@ auto hashmap:next(hashmap_node ref node) return nullptr; } -auto hashmap:find(Key key, Value value) +auto hashmap::find(Key key, Value value) { int hash = compute_hash(key); int bucket = hash & bucketMask; @@ -84,7 +84,7 @@ auto hashmap:find(Key key, Value value) return nullptr; } -void hashmap:remove(Key key, Value value) +void hashmap::remove(Key key, Value value) { int hash = compute_hash(key); int bucket = hash & bucketMask; @@ -103,13 +103,13 @@ void hashmap:remove(Key key, Value value) entries[bucket] = curr.next; } -void vector:push_back(T[] val, int size) +void vector::push_back(T[] val, int size) { for(int i = 0; i < size; i++) push_back(val[i]); } -void vector:shrink(int size) +void vector::shrink(int size) { assert(size <= count); diff --git a/tests/nullc_in_nullc/compiler.nc b/tests/nullc_in_nullc/compiler.nc index cefe97dab..19fc03245 100644 --- a/tests/nullc_in_nullc/compiler.nc +++ b/tests/nullc_in_nullc/compiler.nc @@ -28,28 +28,28 @@ int int(int a); long long(long a); float float(float a); double double(double a); -void bool:bool(bool a){ *this = a; } -void char:char(char a){ *this = a; } -void short:short(short a){ *this = a; } -void int:int(int a){ *this = a; } -void long:long(long a){ *this = a; } -void float:float(float a){ *this = a; } -void double:double(double a){ *this = a; } +void bool::bool(bool a){ *this = a; } +void char::char(char a){ *this = a; } +void short::short(short a){ *this = a; } +void int::int(int a){ *this = a; } +void long::long(long a){ *this = a; } +void float::float(float a){ *this = a; } +void double::double(double a){ *this = a; } int as_unsigned(char a); int as_unsigned(short a); long as_unsigned(int a); short short(char[] str); -char[] short:str(); +char[] short::str(); int int(char[] str); -char[] int:str(); +char[] int::str(); long long(char[] str); -char[] long:str(); +char[] long::str(); float float(char[] str); -char[] float:str(int precision = 6, bool showExponent = false); +char[] float::str(int precision = 6, bool showExponent = false); double double(char[] str); -char[] double:str(int precision = 6, bool showExponent = false); +char[] double::str(int precision = 6, bool showExponent = false); void ref __newS(int size, int type); int[] __newA(int size, int count, int type); @@ -137,7 +137,7 @@ auto[] auto_array(typeid type, int count) } typedef auto[] auto_array; // function will set auto[] element to the specified one, with data reallocation if neccessary -void auto_array:set(auto ref x, int pos); +void auto_array::set(auto ref x, int pos); void __force_size(auto[] ref s, int size); int isCoroutineReset(auto ref f); diff --git a/tests/nullc_in_nullc/expressioncontext.nc b/tests/nullc_in_nullc/expressioncontext.nc index 97ed7c9f9..0896278b7 100644 --- a/tests/nullc_in_nullc/expressioncontext.nc +++ b/tests/nullc_in_nullc/expressioncontext.nc @@ -161,7 +161,7 @@ class ExpressionContext int unnamedVariableCount; } -void ExpressionContext:ExpressionContext(int optimizationLevel) +void ExpressionContext::ExpressionContext(int optimizationLevel) { this.optimizationLevel = optimizationLevel; @@ -215,17 +215,17 @@ void ExpressionContext:ExpressionContext(int optimizationLevel) unnamedVariableCount = 0; } -void ExpressionContext:StopAt(SynBase ref source, StringRef pos, char[] msg, auto ref[] args) +void ExpressionContext::StopAt(SynBase ref source, StringRef pos, char[] msg, auto ref[] args) { //StopAt(*this, source, pos, msg, args); } -void ExpressionContext:Stop(SynBase ref source, char[] msg, auto ref[] args) +void ExpressionContext::Stop(SynBase ref source, char[] msg, auto ref[] args) { //StopAt(*this, source, source.pos.begin, msg, args); } -void ExpressionContext:PushScope(ScopeType type) +void ExpressionContext::PushScope(ScopeType type) { ScopeData ref next = new ScopeData(scope, uniqueScopeId++, type); @@ -239,7 +239,7 @@ void ExpressionContext:PushScope(ScopeType type) scope = next; } -void ExpressionContext:PushScope(NamespaceData ref nameSpace) +void ExpressionContext::PushScope(NamespaceData ref nameSpace) { ScopeData ref next = new ScopeData(scope, uniqueScopeId++, nameSpace); @@ -253,7 +253,7 @@ void ExpressionContext:PushScope(NamespaceData ref nameSpace) scope = next; } -void ExpressionContext:PushScope(FunctionData ref function) +void ExpressionContext::PushScope(FunctionData ref function) { ScopeData ref next = new ScopeData(scope, uniqueScopeId++, function); @@ -263,7 +263,7 @@ void ExpressionContext:PushScope(FunctionData ref function) scope = next; } -void ExpressionContext:PushScope(TypeBase ref type) +void ExpressionContext::PushScope(TypeBase ref type) { ScopeData ref next = new ScopeData(scope, uniqueScopeId++, type); @@ -273,7 +273,7 @@ void ExpressionContext:PushScope(TypeBase ref type) scope = next; } -void ExpressionContext:PushLoopScope(bool allowBreak, bool allowContinue) +void ExpressionContext::PushLoopScope(bool allowBreak, bool allowContinue) { ScopeData ref next = new ScopeData(scope, uniqueScopeId++, ScopeType.SCOPE_LOOP); @@ -293,12 +293,12 @@ void ExpressionContext:PushLoopScope(bool allowBreak, bool allowContinue) scope = next; } -void ExpressionContext:PushTemporaryScope() +void ExpressionContext::PushTemporaryScope() { scope = new ScopeData(scope, 0, ScopeType.SCOPE_TEMPORARY); } -void ExpressionContext:PopScope(ScopeType scopeType, bool ejectContents, bool keepFunctions) +void ExpressionContext::PopScope(ScopeType scopeType, bool ejectContents, bool keepFunctions) { assert(scope.type == scopeType); @@ -421,12 +421,12 @@ void ExpressionContext:PopScope(ScopeType scopeType, bool ejectContents, bool ke scope = scope.scope; } -void ExpressionContext:PopScope(ScopeType type) +void ExpressionContext::PopScope(ScopeType type) { PopScope(type, true, false); } -void ExpressionContext:RestoreScopesAtPoint(ScopeData ref target, SynBase ref location) +void ExpressionContext::RestoreScopesAtPoint(ScopeData ref target, SynBase ref location) { // Restore parent first, up to the current scope if(target.scope != scope) @@ -495,7 +495,7 @@ void ExpressionContext:RestoreScopesAtPoint(ScopeData ref target, SynBase ref lo scope = target; } -void ExpressionContext:SwitchToScopeAtPoint(ScopeData ref target, SynBase ref targetLocation) +void ExpressionContext::SwitchToScopeAtPoint(ScopeData ref target, SynBase ref targetLocation) { // Reach the same depth while(scope.scopeDepth > target.scopeDepth) @@ -525,7 +525,7 @@ void ExpressionContext:SwitchToScopeAtPoint(ScopeData ref target, SynBase ref ta RestoreScopesAtPoint(target, targetLocation); } -NamespaceData ref ExpressionContext:GetCurrentNamespace(ScopeData ref scopeData) +NamespaceData ref ExpressionContext::GetCurrentNamespace(ScopeData ref scopeData) { // Simply walk up the scopes and find the current one for(ScopeData ref curr = scopeData; curr; curr = curr.scope) @@ -537,7 +537,7 @@ NamespaceData ref ExpressionContext:GetCurrentNamespace(ScopeData ref scopeData) return nullptr; } -FunctionData ref ExpressionContext:GetCurrentFunction(ScopeData ref scopeData) +FunctionData ref ExpressionContext::GetCurrentFunction(ScopeData ref scopeData) { // Walk up, but if we reach a type owner, stop - we're not in a context of a function for(ScopeData ref curr = scopeData; curr; curr = curr.scope) @@ -552,7 +552,7 @@ FunctionData ref ExpressionContext:GetCurrentFunction(ScopeData ref scopeData) return nullptr; } -TypeBase ref ExpressionContext:GetCurrentType(ScopeData ref scopeData) +TypeBase ref ExpressionContext::GetCurrentType(ScopeData ref scopeData) { // Simply walk up the scopes and find the current one for(ScopeData ref curr = scopeData; curr; curr = curr.scope) @@ -564,7 +564,7 @@ TypeBase ref ExpressionContext:GetCurrentType(ScopeData ref scopeData) return nullptr; } -FunctionData ref ExpressionContext:GetFunctionOwner(ScopeData ref scopeData) +FunctionData ref ExpressionContext::GetFunctionOwner(ScopeData ref scopeData) { // Temporary scopes have no owner if(scopeData.type == ScopeType.SCOPE_TEMPORARY) @@ -586,7 +586,7 @@ FunctionData ref ExpressionContext:GetFunctionOwner(ScopeData ref scopeData) return nullptr; } -ScopeData ref ExpressionContext:NamespaceScopeFrom(ScopeData ref scopeData) +ScopeData ref ExpressionContext::NamespaceScopeFrom(ScopeData ref scopeData) { if(!scopeData || scopeData.ownerNamespace) return scopeData; @@ -594,7 +594,7 @@ ScopeData ref ExpressionContext:NamespaceScopeFrom(ScopeData ref scopeData) return NamespaceScopeFrom(scopeData.scope); } -ScopeData ref ExpressionContext:GlobalScopeFrom(ScopeData ref scopeData) +ScopeData ref ExpressionContext::GlobalScopeFrom(ScopeData ref scopeData) { if(!scopeData) return nullptr; @@ -614,7 +614,7 @@ ScopeData ref ExpressionContext:GlobalScopeFrom(ScopeData ref scopeData) return scopeData; } -bool ExpressionContext:IsGenericInstance(FunctionData ref function) +bool ExpressionContext::IsGenericInstance(FunctionData ref function) { if(function.isGenericInstance) return true; @@ -634,7 +634,7 @@ bool ExpressionContext:IsGenericInstance(FunctionData ref function) return false; } -void ExpressionContext:AddType(TypeBase ref type) +void ExpressionContext::AddType(TypeBase ref type) { scope.types.push_back(type); @@ -651,7 +651,7 @@ void ExpressionContext:AddType(TypeBase ref type) } } -void ExpressionContext:AddFunction(FunctionData ref function) +void ExpressionContext::AddFunction(FunctionData ref function) { scope.functions.push_back(function); @@ -680,7 +680,7 @@ void ExpressionContext:AddFunction(FunctionData ref function) } } -void ExpressionContext:AddVariable(VariableData ref variable, bool visible) +void ExpressionContext::AddVariable(VariableData ref variable, bool visible) { scope.variables.push_back(variable); scope.allVariables.push_back(variable); @@ -695,14 +695,14 @@ void ExpressionContext:AddVariable(VariableData ref variable, bool visible) } } -void ExpressionContext:AddAlias(AliasData ref alias) +void ExpressionContext::AddAlias(AliasData ref alias) { scope.aliases.push_back(alias); typeMap.insert(alias.nameHash, alias.type); } -int ExpressionContext:GetTypeIndex(TypeBase ref type) +int ExpressionContext::GetTypeIndex(TypeBase ref type) { int index = -1; @@ -720,12 +720,12 @@ int ExpressionContext:GetTypeIndex(TypeBase ref type) return index; } -int ExpressionContext:GetFunctionIndex(FunctionData ref data) +int ExpressionContext::GetFunctionIndex(FunctionData ref data) { return data.functionIndex; } -void ExpressionContext:HideFunction(FunctionData ref function) +void ExpressionContext::HideFunction(FunctionData ref function) { // Don't have to remove internal functions since they are never added to lookup if(function.name.name && function.name.name[0] != '$') @@ -760,7 +760,7 @@ void ExpressionContext:HideFunction(FunctionData ref function) } } -bool ExpressionContext:IsGenericFunction(FunctionData ref function) +bool ExpressionContext::IsGenericFunction(FunctionData ref function) { if(function.type.isGeneric) return true; @@ -777,7 +777,7 @@ bool ExpressionContext:IsGenericFunction(FunctionData ref function) return false; } -bool ExpressionContext:IsIntegerType(TypeBase ref type) +bool ExpressionContext::IsIntegerType(TypeBase ref type) { if(type == typeBool) return true; @@ -797,7 +797,7 @@ bool ExpressionContext:IsIntegerType(TypeBase ref type) return false; } -bool ExpressionContext:IsFloatingPointType(TypeBase ref type) +bool ExpressionContext::IsFloatingPointType(TypeBase ref type) { if(type == typeFloat) return true; @@ -808,12 +808,12 @@ bool ExpressionContext:IsFloatingPointType(TypeBase ref type) return false; } -bool ExpressionContext:IsNumericType(TypeBase ref type) +bool ExpressionContext::IsNumericType(TypeBase ref type) { return IsIntegerType(type) || IsFloatingPointType(type); } -TypeBase ref ExpressionContext:GetBinaryOpResultType(TypeBase ref a, TypeBase ref b) +TypeBase ref ExpressionContext::GetBinaryOpResultType(TypeBase ref a, TypeBase ref b) { if(a == typeDouble || b == typeDouble) return typeDouble; @@ -839,12 +839,12 @@ TypeBase ref ExpressionContext:GetBinaryOpResultType(TypeBase ref a, TypeBase re return nullptr; } -TypeError ref ExpressionContext:GetErrorType() +TypeError ref ExpressionContext::GetErrorType() { return new TypeError(); } -TypeRef ref ExpressionContext:GetReferenceType(TypeBase ref type) +TypeRef ref ExpressionContext::GetReferenceType(TypeBase ref type) { // Can't derive from pseudo types assert(!isType with(type) && !isType with(type) && !isType with(type)); @@ -867,7 +867,7 @@ TypeRef ref ExpressionContext:GetReferenceType(TypeBase ref type) return result; } -TypeArray ref ExpressionContext:GetArrayType(TypeBase ref type, long length) +TypeArray ref ExpressionContext::GetArrayType(TypeBase ref type, long length) { // Can't have array of void assert(type != typeVoid); @@ -916,7 +916,7 @@ TypeArray ref ExpressionContext:GetArrayType(TypeBase ref type, long length) return result; } -TypeUnsizedArray ref ExpressionContext:GetUnsizedArrayType(TypeBase ref type) +TypeUnsizedArray ref ExpressionContext::GetUnsizedArrayType(TypeBase ref type) { // Can't have array of void assert(type != typeVoid); @@ -956,7 +956,7 @@ TypeUnsizedArray ref ExpressionContext:GetUnsizedArrayType(TypeBase ref type) return result; } -TypeFunction ref ExpressionContext:GetFunctionType(SynBase ref source, TypeBase ref returnType, RefList arguments) +TypeFunction ref ExpressionContext::GetFunctionType(SynBase ref source, TypeBase ref returnType, RefList arguments) { // Can't derive from pseudo types assert(!isType with(returnType) && !isType with(returnType) && !isType with(returnType)); @@ -1008,7 +1008,7 @@ TypeFunction ref ExpressionContext:GetFunctionType(SynBase ref source, TypeBase return result; } -TypeFunction ref ExpressionContext:GetFunctionType(SynBase ref source, TypeBase ref returnType, ArrayView arguments) +TypeFunction ref ExpressionContext::GetFunctionType(SynBase ref source, TypeBase ref returnType, ArrayView arguments) { // Can't derive from pseudo types assert(!isType with(returnType) && !isType with(returnType) && !isType with(returnType)); @@ -1065,7 +1065,7 @@ TypeFunction ref ExpressionContext:GetFunctionType(SynBase ref source, TypeBase return GetFunctionType(source, returnType, argumentTypes); } -TypeFunctionSet ref ExpressionContext:GetFunctionSetType(ArrayView setTypes) +TypeFunctionSet ref ExpressionContext::GetFunctionSetType(ArrayView setTypes) { for(int i = 0, e = functionSetTypes.count; i < e; i++) { @@ -1111,7 +1111,7 @@ TypeFunctionSet ref ExpressionContext:GetFunctionSetType(ArrayView return result; } -TypeGenericAlias ref ExpressionContext:GetGenericAliasType(SynIdentifier ref baseName) +TypeGenericAlias ref ExpressionContext::GetGenericAliasType(SynIdentifier ref baseName) { for(int i = 0, e = genericAliasTypes.count; i < e; i++) { @@ -1131,7 +1131,7 @@ TypeGenericAlias ref ExpressionContext:GetGenericAliasType(SynIdentifier ref bas return result; } -TypeGenericClass ref ExpressionContext:GetGenericClassType(SynBase ref source, TypeGenericClassProto ref proto, RefList generics) +TypeGenericClass ref ExpressionContext::GetGenericClassType(SynBase ref source, TypeGenericClassProto ref proto, RefList generics) { for(int i = 0, e = genericClassTypes.count; i < e; i++) { @@ -1168,7 +1168,7 @@ TypeGenericClass ref ExpressionContext:GetGenericClassType(SynBase ref source, T return result; } -ModuleData ref ExpressionContext:GetSourceOwner(LexemeRef lexeme) +ModuleData ref ExpressionContext::GetSourceOwner(LexemeRef lexeme) { // Fast check for current module /*if(lexeme.pos >= code && lexeme.pos <= codeEnd) @@ -1186,7 +1186,7 @@ ModuleData ref ExpressionContext:GetSourceOwner(LexemeRef lexeme) return nullptr; } -SynInternal ref ExpressionContext:MakeInternal(SynBase ref source) +SynInternal ref ExpressionContext::MakeInternal(SynBase ref source) { if(SynInternal ref synInternal = getType with(source)) return synInternal; diff --git a/tests/nullc_in_nullc/lexer.nc b/tests/nullc_in_nullc/lexer.nc index c59c00a26..5c7c02472 100644 --- a/tests/nullc_in_nullc/lexer.nc +++ b/tests/nullc_in_nullc/lexer.nc @@ -48,7 +48,7 @@ enum LexemeType lex_set, lex_addset, lex_subset, lex_mulset, lex_divset, lex_powset, lex_modset, lex_shlset, lex_shrset, lex_andset, lex_orset, lex_xorset, // = += -= *= /= **= %= <<= >>= &= |= ^= lex_bitnot, lex_lognot, // ~ ! lex_oparen, lex_cparen, lex_obracket, lex_cbracket, lex_ofigure, lex_cfigure, // ( ) [ ] { } - lex_questionmark, lex_colon, lex_semicolon, // ? : ; + lex_questionmark, lex_colon, lex_semicolon, lex_dblcolon, // ? : ; :: lex_if, lex_else, lex_for, lex_while, lex_do, lex_switch, lex_case, lex_default, // if else for while switch case default lex_break, lex_continue, lex_return, // break continue return lex_ref, lex_auto, lex_class, lex_noalign, lex_align, // ref auto class noalign align @@ -141,12 +141,12 @@ bool bool(LexemeRef lexeme) return lexeme.owner != nullptr; } -void Lexer:Clear(int count) +void Lexer::Clear(int count) { lexems.resize(count); } -void Lexer:Lexify(char[] code) +void Lexer::Lexify(char[] code) { this.code = code; @@ -403,7 +403,11 @@ void Lexer:Lexify(char[] code) lType = LexemeType.lex_questionmark; break; case ':': - lType = LexemeType.lex_colon; + if(code[curr + 1] == ':') + { + lType = LexemeType.lex_dblcolon; + lLength = 2; + } else lType = LexemeType.lex_colon; break; case ';': lType = LexemeType.lex_semicolon; @@ -556,7 +560,7 @@ void Lexer:Lexify(char[] code) lexems.push_back(lex); } -void Lexer:Append(Lexeme[] stream) +void Lexer::Append(Lexeme[] stream) { for(i in stream) lexems.push_back(i); diff --git a/tests/nullc_in_nullc/parser.nc b/tests/nullc_in_nullc/parser.nc index 89707647d..63684c9fa 100644 --- a/tests/nullc_in_nullc/parser.nc +++ b/tests/nullc_in_nullc/parser.nc @@ -67,7 +67,7 @@ class ParseContext hashmap nonFunctionDefinitionLocations; } -void ParseContext:ParseContext(int optimizationLevel, ArrayView activeImports) +void ParseContext::ParseContext(int optimizationLevel, ArrayView activeImports) { this.optimizationLevel = optimizationLevel; @@ -89,22 +89,22 @@ void ParseContext:ParseContext(int optimizationLevel, ArrayView acti this.activeImports.push_back(activeImports[i]); } -LexemeType ParseContext:Peek() +LexemeType ParseContext::Peek() { return currentLexeme.type; } -InplaceStr ParseContext:Value() +InplaceStr ParseContext::Value() { return InplaceStr(currentLexeme.pos, currentLexeme.length); } -bool ParseContext:At(LexemeType type) +bool ParseContext::At(LexemeType type) { return currentLexeme.type == type; } -bool ParseContext:Consume(LexemeType type) +bool ParseContext::Consume(LexemeType type) { if(currentLexeme.type == type) { @@ -115,7 +115,7 @@ bool ParseContext:Consume(LexemeType type) return false; } -bool ParseContext:Consume(char[] str) +bool ParseContext::Consume(char[] str) { if(InplaceStr(currentLexeme.pos, currentLexeme.length) == InplaceStr(str)) { @@ -126,7 +126,7 @@ bool ParseContext:Consume(char[] str) return false; } -InplaceStr ParseContext:Consume() +InplaceStr ParseContext::Consume() { InplaceStr str = InplaceStr(currentLexeme.pos, currentLexeme.length); @@ -135,47 +135,47 @@ InplaceStr ParseContext:Consume() return str; } -void ParseContext:Skip() +void ParseContext::Skip() { if(currentLexeme.type != LexemeType.lex_none) currentLexeme.advance(); } -LexemeRef ParseContext:First() +LexemeRef ParseContext::First() { return firstLexeme; } -LexemeRef ParseContext:Current() +LexemeRef ParseContext::Current() { return currentLexeme; } -LexemeRef ParseContext:Previous() +LexemeRef ParseContext::Previous() { assert(currentLexeme > firstLexeme); return currentLexeme - 1; } -LexemeRef ParseContext:Last() +LexemeRef ParseContext::Last() { return lastLexeme; } -StringRef ParseContext:Position() +StringRef ParseContext::Position() { return currentLexeme.pos; } -StringRef ParseContext:LastEnding() +StringRef ParseContext::LastEnding() { assert(currentLexeme > firstLexeme); return (currentLexeme - 1).pos + (currentLexeme - 1).length; } -SynNamespaceElement ref ParseContext:IsNamespace(SynNamespaceElement ref parent, InplaceStr name) +SynNamespaceElement ref ParseContext::IsNamespace(SynNamespaceElement ref parent, InplaceStr name) { // In the context of a parent namespace, we only look for immediate children if(parent) @@ -218,7 +218,7 @@ SynNamespaceElement ref ParseContext:IsNamespace(SynNamespaceElement ref parent, return nullptr; } -SynNamespaceElement ref ParseContext:PushNamespace(SynIdentifier ref name) +SynNamespaceElement ref ParseContext::PushNamespace(SynIdentifier ref name) { SynNamespaceElement ref current = currentNamespace; @@ -240,7 +240,7 @@ SynNamespaceElement ref ParseContext:PushNamespace(SynIdentifier ref name) return ns; } -void ParseContext:PopNamespace() +void ParseContext::PopNamespace() { assert(currentNamespace != nullptr); @@ -2564,7 +2564,7 @@ SynFunctionDefinition ref ParseFunctionDefinition(ParseContext ref ctx) if(parentType) { - if(ctx.Consume(LexemeType.lex_colon)) + if(ctx.Consume(LexemeType.lex_dblcolon)) { accessor = false; } @@ -2855,10 +2855,10 @@ ByteCode ref GetBytecodeFromPath(ParseContext ref ctx, LexemeRef start, RefList< //TRACE_SCOPE("parser", "GetBytecodeFromPath"); //TRACE_LABEL2(moduleName.begin, moduleName.end); - /*ByteCode ref bytecode = BinaryCache:FindBytecode(moduleName.begin, false); + /*ByteCode ref bytecode = BinaryCache::FindBytecode(moduleName.begin, false); lexCount = 0; - lexStream = BinaryCache:FindLexems(moduleName.begin, false, lexCount); + lexStream = BinaryCache::FindLexems(moduleName.begin, false, lexCount); if(!bytecode) { @@ -3037,7 +3037,7 @@ SynModule ref Parse(ParseContext ref ctx, char[] code) ctx.lexer.Lexify(code); - //int traceDepth = NULLC:TraceGetDepth(); + //int traceDepth = NULLC::TraceGetDepth(); //if(!setjmp(ctx.errorHandler)) { @@ -3058,7 +3058,7 @@ SynModule ref Parse(ParseContext ref ctx, char[] code) return module; } - //NULLC:TraceLeaveTo(traceDepth); + //NULLC::TraceLeaveTo(traceDepth); //assert(ctx.errorPos); diff --git a/tests/nullc_in_nullc/reflist.nc b/tests/nullc_in_nullc/reflist.nc index 96f91f8cb..caec8b17c 100644 --- a/tests/nullc_in_nullc/reflist.nc +++ b/tests/nullc_in_nullc/reflist.nc @@ -59,7 +59,7 @@ auto operator[](RefList<@T> ref lhs, int index) return curr; } -auto RefList:start() +auto RefList::start() { return coroutine auto() { diff --git a/tests/nullc_in_nullc/stringutil.nc b/tests/nullc_in_nullc/stringutil.nc index 3a903252d..1c410ee18 100644 --- a/tests/nullc_in_nullc/stringutil.nc +++ b/tests/nullc_in_nullc/stringutil.nc @@ -231,7 +231,7 @@ bool operator!=(InplaceStr a, InplaceStr b) return !(a== b); } -void StringRef:StringRef(InplaceStr str) +void StringRef::StringRef(InplaceStr str) { this.string = str.data; this.pos = str.begin; diff --git a/tests/run-it b/tests/run-it new file mode 100755 index 000000000..0a708d586 --- /dev/null +++ b/tests/run-it @@ -0,0 +1,2 @@ +/usr/bin/time ../bin/TestRun $* + From c4383463a617b84ad6157b717171f84802e7c9c3 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 29 Sep 2022 17:41:05 +0200 Subject: [PATCH 10/20] Fix for preserve double precision --- NULLC/ExpressionTranslate.cpp | 4 ++-- NULLC/ExpressionTree.cpp | 10 +++++++--- NULLC/InstructionTreeRegVmLower.cpp | 4 ++-- NULLC/Lexer.cpp | 6 ++++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/NULLC/ExpressionTranslate.cpp b/NULLC/ExpressionTranslate.cpp index 67bc11f5e..38ecf7ed9 100644 --- a/NULLC/ExpressionTranslate.cpp +++ b/NULLC/ExpressionTranslate.cpp @@ -512,9 +512,9 @@ void TranslateIntegerLiteral(ExpressionTranslateContext &ctx, ExprIntegerLiteral void TranslateRationalLiteral(ExpressionTranslateContext &ctx, ExprRationalLiteral *expression) { if(expression->type == ctx.ctx.typeFloat) - Print(ctx, "((float)%e)", expression->value); + Print(ctx, "((float)%.9g)", expression->value); else if(expression->type == ctx.ctx.typeDouble) - Print(ctx, "%e", expression->value); + Print(ctx, "%.17g", expression->value); else assert(!"unknown type"); } diff --git a/NULLC/ExpressionTree.cpp b/NULLC/ExpressionTree.cpp index 40da93561..f0cf393f3 100644 --- a/NULLC/ExpressionTree.cpp +++ b/NULLC/ExpressionTree.cpp @@ -256,6 +256,9 @@ namespace double ParseDouble(ExpressionContext &ctx, const char *str) { + char *sTemp; + return strtod(str,&sTemp); +/* unsigned digit; double integer = 0.0; @@ -269,7 +272,7 @@ namespace if(*str == '.') { - double power = 0.1f; + double power = 0.1; str++; while((digit = *str - '0') < 10) @@ -280,7 +283,7 @@ namespace } } - if(*str == 'e') + if(*str == 'e' || *str == 'E') { str++; @@ -291,6 +294,7 @@ namespace } return integer + fractional; + */ } bool IsBinaryOp(SynUnaryOpType type) @@ -3792,7 +3796,7 @@ ExprBase* AnalyzeNumber(ExpressionContext &ctx, SynNumber *syntax) for(unsigned i = 0; i < value.length(); i++) { - if(value.begin[i] == '.' || value.begin[i] == 'e') + if(value.begin[i] == '.' || value.begin[i] == 'e' || value.begin[i] == 'E') isFP = true; } diff --git a/NULLC/InstructionTreeRegVmLower.cpp b/NULLC/InstructionTreeRegVmLower.cpp index 264843376..63b6d1ccd 100644 --- a/NULLC/InstructionTreeRegVmLower.cpp +++ b/NULLC/InstructionTreeRegVmLower.cpp @@ -283,7 +283,7 @@ bool RegVmLoweredFunction::TransferRegisterTo(VmValue *value, unsigned char reg) unsigned RegVmLoweredModule::FindConstant(unsigned value) { - for(unsigned i = 0; i < constants.size(); i++) + for(unsigned i = 0, imax = constants.size(); i < imax; i++) { if(constants[i] == value) return i + 1; @@ -294,7 +294,7 @@ unsigned RegVmLoweredModule::FindConstant(unsigned value) unsigned RegVmLoweredModule::FindConstant(unsigned value1, unsigned value2) { - for(unsigned i = 0; i + 1 < constants.size(); i += 2) + for(unsigned i = 0, imax = constants.size(); i + 1 < imax; i += 2) { if(constants[i] == value1 && constants[i + 1] == value2) return i + 1; diff --git a/NULLC/Lexer.cpp b/NULLC/Lexer.cpp index 6ce9c8de3..1f4ffa286 100644 --- a/NULLC/Lexer.cpp +++ b/NULLC/Lexer.cpp @@ -132,7 +132,8 @@ void Lexer::Lexify(const char* code) } break; case '.': - lType = lex_point; + if(isDigit(code[1])) goto do_lex_number; + else lType = lex_point; break; case ',': lType = lex_comma; @@ -392,6 +393,7 @@ void Lexer::Lexify(const char* code) default: if(isDigit(*code)) { +do_lex_number: lType = lex_number; const char *pos = code; @@ -408,7 +410,7 @@ void Lexer::Lexify(const char* code) pos++; while(isDigit(*pos)) pos++; - if(*pos == 'e') + if(*pos == 'e' || *pos == 'E') { pos++; if(*pos == '-') From 75fcded9962ff89b04aea6cba0865c31a4c162d7 Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 30 Sep 2022 14:40:42 +0200 Subject: [PATCH 11/20] Fix lexer numbers like '-.34' --- tests/nullc_in_nullc/analyzer.nc | 4 +-- tests/nullc_in_nullc/lexer.nc | 57 +++++++++++++++++--------------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/tests/nullc_in_nullc/analyzer.nc b/tests/nullc_in_nullc/analyzer.nc index f0997e062..47f20ad81 100644 --- a/tests/nullc_in_nullc/analyzer.nc +++ b/tests/nullc_in_nullc/analyzer.nc @@ -354,7 +354,7 @@ double ParseDouble(ExpressionContext ref ctx, StringRef str) if(str.curr() == '.') { - double power = 0.1f; + double power = 0.1; str.advance(); digit = str.curr() - '0'; @@ -368,7 +368,7 @@ double ParseDouble(ExpressionContext ref ctx, StringRef str) } } - if(str.curr() == 'e') + if(str.curr() == 'e' || str.curr() == 'E') { str.advance(); diff --git a/tests/nullc_in_nullc/lexer.nc b/tests/nullc_in_nullc/lexer.nc index 5c7c02472..bcd00de14 100644 --- a/tests/nullc_in_nullc/lexer.nc +++ b/tests/nullc_in_nullc/lexer.nc @@ -157,6 +157,34 @@ void Lexer::Lexify(char[] code) int curr = 0; + void parserNumber() { + lType = LexemeType.lex_number; + + int pos = curr; + if(code[pos] == '0' && code[pos + 1] == 'x') + { + pos += 2; + while(isDigit(code[pos]) || ((code[pos] & ~0x20) >= 'A' && (code[pos] & ~0x20) <= 'F')) + pos++; + }else{ + while(isDigit(code[pos])) + pos++; + } + if(code[pos] == '.') + pos++; + while(isDigit(code[pos])) + pos++; + if(code[pos] == 'e' || code[pos] == 'E') + { + pos++; + if(code[pos] == '-') + pos++; + } + while(isDigit(code[pos])) + pos++; + lLength = (pos - curr); + } + while(curr < code.size) { switch(code[curr]) @@ -194,7 +222,8 @@ void Lexer::Lexify(char[] code) } break; case '.': - lType = LexemeType.lex_point; + if(isDigit(code[1])) parserNumber(); + else lType = LexemeType.lex_point; break; case ',': lType = LexemeType.lex_comma; @@ -415,31 +444,7 @@ void Lexer::Lexify(char[] code) default: if(isDigit(code[curr])) { - lType = LexemeType.lex_number; - - int pos = curr; - if(code[pos] == '0' && code[pos + 1] == 'x') - { - pos += 2; - while(isDigit(code[pos]) || ((code[pos] & ~0x20) >= 'A' && (code[pos] & ~0x20) <= 'F')) - pos++; - }else{ - while(isDigit(code[pos])) - pos++; - } - if(code[pos] == '.') - pos++; - while(isDigit(code[pos])) - pos++; - if(code[pos] == 'e') - { - pos++; - if(code[pos] == '-') - pos++; - } - while(isDigit(code[pos])) - pos++; - lLength = (pos - curr); + parserNumber(); }else if(chartype_table[as_unsigned(code[curr])] & int(chartype.ct_start_symbol)){ int pos = curr; while(chartype_table[as_unsigned(code[pos])] & int(chartype.ct_symbol)) From 8abdad923cf9860ff3b41d167f8f0a01645d061b Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 30 Sep 2022 20:44:54 +0200 Subject: [PATCH 12/20] Add lua-regex to CMakeKists.txt --- NULLC/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/NULLC/CMakeLists.txt b/NULLC/CMakeLists.txt index 4fdceec03..f70fa60ff 100644 --- a/NULLC/CMakeLists.txt +++ b/NULLC/CMakeLists.txt @@ -67,6 +67,7 @@ add_library (NULLC "includes/window.cpp" "includes/window.h" "includes/memory.cpp" "includes/memory.h" "includes/error.cpp" "includes/error.h" +"includes/lua-regex.c" "includes/lua-regex.h" "../external/pugixml/pugixml.cpp" ) From 8b6467fbc0840bef9c995617cd4a54a2bdf190f4 Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 30 Sep 2022 20:45:20 +0200 Subject: [PATCH 13/20] Show error message when it fails --- NULLC/Compiler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/NULLC/Compiler.cpp b/NULLC/Compiler.cpp index c57ce0a97..5adfd5749 100644 --- a/NULLC/Compiler.cpp +++ b/NULLC/Compiler.cpp @@ -185,6 +185,7 @@ bool BuildBaseModule(Allocator *allocator, int optimizationLevel) if(!BuildModuleFromSource(allocator, "$base$.nc", NULL, nullcBaseCode, unsigned(strlen(nullcBaseCode)), &errorPos, errorBuf, 256, optimizationLevel, ArrayView(), NULL)) { + fprintf(stderr, "%s\n", errorBuf); assert(!"Failed to compile base NULLC module"); return false; } From 56497752766ba3ff408ff73215b386b3a66d5bfa Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 30 Sep 2022 20:46:35 +0200 Subject: [PATCH 14/20] More code added to implement "goto" and accept "struct" --- NULLC/ExpressionTree.cpp | 38 ++++++++ NULLC/ExpressionTree.h | 30 ++++++ NULLC/Lexer.cpp | 4 + NULLC/Lexer.h | 5 +- NULLC/ParseGraph.cpp | 16 ++++ NULLC/ParseTree.cpp | 150 +++++++++++++++++++----------- NULLC/ParseTree.h | 29 +++++- tests/TestExtra.cpp | 10 +- tests/nullc_in_nullc/lexer.nc | 11 ++- tests/nullc_in_nullc/parser.nc | 58 +++++++++++- tests/nullc_in_nullc/parsetree.nc | 36 ++++++- 11 files changed, 319 insertions(+), 68 deletions(-) diff --git a/NULLC/ExpressionTree.cpp b/NULLC/ExpressionTree.cpp index f0cf393f3..4b0a8a1fc 100644 --- a/NULLC/ExpressionTree.cpp +++ b/NULLC/ExpressionTree.cpp @@ -11656,6 +11656,34 @@ ExprContinue* AnalyzeContinue(ExpressionContext &ctx, SynContinue *syntax) return new (ctx.get()) ExprContinue(syntax, ctx.typeVoid, depth, CreateContinueUpvalueClose(ctx, syntax, ctx.GetCurrentFunction(ctx.scope), ctx.scope, depth)); } +ExprLabel* AnalyzeLabel(ExpressionContext &ctx, SynLabel *syntax) +{ + unsigned depth = 1; + + if(syntax->labeIdentifier) + { + } + + if(ctx.scope->contiueDepth < depth) + Stop(ctx, syntax, "ERROR: label level is greater that loop depth"); + + return new (ctx.get()) ExprLabel(syntax, ctx.typeVoid, depth, NULL /*CreateLabelUpvalueClose(ctx, syntax, ctx.GetCurrentFunction(ctx.scope), ctx.scope, depth)*/); +} + +ExprGoto* AnalyzeGoto(ExpressionContext &ctx, SynGoto *syntax) +{ + unsigned depth = 1; + + if(syntax->labeIdentifier) + { + } + + if(ctx.scope->contiueDepth < depth) + Stop(ctx, syntax, "ERROR: goto level is greater that loop depth"); + + return new (ctx.get()) ExprGoto(syntax, ctx.typeVoid, depth, NULL /*CreateGotoUpvalueClose(ctx, syntax, ctx.GetCurrentFunction(ctx.scope), ctx.scope, depth)*/); +} + ExprBlock* AnalyzeBlock(ExpressionContext &ctx, SynBlock *syntax, bool createScope) { if(createScope) @@ -12116,6 +12144,16 @@ ExprBase* AnalyzeStatement(ExpressionContext &ctx, SynBase *syntax) return AnalyzeContinue(ctx, node); } + if(SynLabel *node = getType(syntax)) + { + return AnalyzeLabel(ctx, node); + } + + if(SynGoto *node = getType(syntax)) + { + return AnalyzeGoto(ctx, node); + } + if(SynBlock *node = getType(syntax)) { return AnalyzeBlock(ctx, node, true); diff --git a/NULLC/ExpressionTree.h b/NULLC/ExpressionTree.h index e7c612fea..eb8e78b20 100644 --- a/NULLC/ExpressionTree.h +++ b/NULLC/ExpressionTree.h @@ -475,6 +475,10 @@ namespace ExprNode ExprBlock, ExprSequence, ExprModule, + // the order above this line seem to be important + // do not change, insert,remove above it + ExprLabel, + ExprGoto, }; } @@ -1204,6 +1208,32 @@ struct ExprContinue: ExprBase static const unsigned myTypeID = ExprNode::ExprContinue; }; +struct ExprLabel: ExprBase +{ + ExprLabel(SynBase *source, TypeBase *type, unsigned depth, ExprBase *closures): ExprBase(myTypeID, source, type), depth(depth), closures(closures) + { + } + + unsigned depth; + + ExprBase *closures; + + static const unsigned myTypeID = ExprNode::ExprLabel; +}; + +struct ExprGoto: ExprBase +{ + ExprGoto(SynBase *source, TypeBase *type, unsigned depth, ExprBase *closures): ExprBase(myTypeID, source, type), depth(depth), closures(closures) + { + } + + unsigned depth; + + ExprBase *closures; + + static const unsigned myTypeID = ExprNode::ExprGoto; +}; + struct ExprBlock: ExprBase { ExprBlock(SynBase *source, TypeBase *type, IntrusiveList expressions, ExprBase *closures): ExprBase(myTypeID, source, type), expressions(expressions), closures(closures) diff --git a/NULLC/Lexer.cpp b/NULLC/Lexer.cpp index 1f4ffa286..dd99669cd 100644 --- a/NULLC/Lexer.cpp +++ b/NULLC/Lexer.cpp @@ -458,6 +458,8 @@ void Lexer::Lexify(const char* code) lType = lex_enum; else if(memcmp(code, "with", 4) == 0) lType = lex_with; + else if(memcmp(code, "goto", 4) == 0) + lType = lex_goto; break; case 5: if(memcmp(code, "while", 5) == 0) @@ -486,6 +488,8 @@ void Lexer::Lexify(const char* code) lType = lex_sizeof; else if(memcmp(code, "import", 6) == 0) lType = lex_import; + else if(memcmp(code, "struct", 6) == 0) + lType = lex_struct; break; case 7: if(memcmp(code, "noalign", 7) == 0) diff --git a/NULLC/Lexer.h b/NULLC/Lexer.h index f16c1bc0f..9622a1f32 100644 --- a/NULLC/Lexer.h +++ b/NULLC/Lexer.h @@ -52,7 +52,10 @@ enum LexemeType lex_typeof, lex_sizeof, lex_new, lex_operator, lex_typedef, lex_import, lex_nullptr, // typeof sizeof new operator typedef import in nullptr lex_coroutine, lex_yield, // coroutine yield lex_at, // @ - lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with // generic const true false enum namespace extendable with + lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with, // generic const true false enum namespace extendable with + // it seems that there is a place where the position of the above tokes is significant + // do not change, add, remove anything above this line unless you find it ! + lex_goto, lex_struct // goto struct }; struct Lexeme diff --git a/NULLC/ParseGraph.cpp b/NULLC/ParseGraph.cpp index f071a0581..5ed62ee6c 100644 --- a/NULLC/ParseGraph.cpp +++ b/NULLC/ParseGraph.cpp @@ -399,6 +399,22 @@ void PrintGraph(ParseGraphContext &ctx, SynBase *syntax, const char *name) PrintLeaveBlock(ctx); } + else if(SynLabel *node = getType(syntax)) + { + PrintEnterBlock(ctx, name, "SynLabel()"); + + PrintGraph(ctx, node->labeIdentifier, "labeIdentifier"); + + PrintLeaveBlock(ctx); + } + else if(SynGoto *node = getType(syntax)) + { + PrintEnterBlock(ctx, name, "SynGoto()"); + + PrintGraph(ctx, node->labeIdentifier, "labeIdentifier"); + + PrintLeaveBlock(ctx); + } else if(SynBlock *node = getType(syntax)) { PrintEnterBlock(ctx, name, "SynBlock()"); diff --git a/NULLC/ParseTree.cpp b/NULLC/ParseTree.cpp index ba418dab4..5fa0659ca 100644 --- a/NULLC/ParseTree.cpp +++ b/NULLC/ParseTree.cpp @@ -1553,12 +1553,15 @@ SynBase* ParseClassDefinition(ParseContext &ctx) Lexeme *start = ctx.currentLexeme; SynAlign *align = ParseAlign(ctx); + + bool isStruct = ctx.Consume(lex_struct); - if(ctx.Consume(lex_class)) + if(isStruct || ctx.Consume(lex_class)) { SynIdentifier *nameIdentifier = NULL; + const char *classOrStruct = isStruct ? "struct" : "class"; - if(CheckAt(ctx, lex_identifier, "ERROR: class name expected")) + if(CheckAt(ctx, lex_identifier, "ERROR: %s name expected", classOrStruct)) { InplaceStr name = ctx.Consume(); nameIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); @@ -1571,7 +1574,7 @@ SynBase* ParseClassDefinition(ParseContext &ctx) if(ctx.Consume(lex_semicolon)) { if(align) - Report(ctx, ctx.Current(), "ERROR: can't specify alignment of a class prototype"); + Report(ctx, ctx.Current(), "ERROR: can't specify alignment of a %s prototype", classOrStruct); return new (ctx.get()) SynClassPrototype(start, ctx.Previous(), nameIdentifier); } @@ -1612,7 +1615,7 @@ SynBase* ParseClassDefinition(ParseContext &ctx) Report(ctx, ctx.Current(), "ERROR: base type name is expected at this point"); } - CheckConsume(ctx, lex_ofigure, "ERROR: '{' not found after class name"); + CheckConsume(ctx, lex_ofigure, "ERROR: '{' not found after %s name", classOrStruct); TRACE_SCOPE("parse", "ParseClassBody"); @@ -1621,9 +1624,9 @@ SynBase* ParseClassDefinition(ParseContext &ctx) SynClassElements *elements = ParseClassElements(ctx); - CheckConsume(ctx, lex_cfigure, "ERROR: '}' not found after class definition"); + CheckConsume(ctx, lex_cfigure, "ERROR: '}' not found after %s definition", classOrStruct); - return new (ctx.get()) SynClassDefinition(start, ctx.Previous(), align, nameIdentifier, aliases, extendable, baseClass, elements); + return new (ctx.get()) SynClassDefinition(start, ctx.Previous(), align, nameIdentifier, aliases, extendable, isStruct, baseClass, elements); } // Backtrack @@ -1808,6 +1811,47 @@ SynContinue* ParseContinue(ParseContext &ctx) return NULL; } +SynLabel* ParseLabel(ParseContext &ctx) +{ + Lexeme *start = ctx.currentLexeme; + + if(ctx.At(lex_identifier)) + { + InplaceStr name = ctx.Consume(); + SynIdentifier *labeIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); + if(ctx.Consume(lex_colon)) { + return new (ctx.get()) SynLabel(start, ctx.Previous(), labeIdentifier); + } + } + + // Backtrack + ctx.currentLexeme = start; + + return NULL; +} + +SynGoto* ParseGoto(ParseContext &ctx) +{ + Lexeme *start = ctx.currentLexeme; + + if(ctx.Consume(lex_goto)) + { + SynIdentifier *labeIdentifier = NULL; + + if(CheckAt(ctx, lex_identifier, "ERROR: label name expected")) + { + InplaceStr name = ctx.Consume(); + labeIdentifier = new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), name); + } + + CheckConsume(ctx, lex_semicolon, "ERROR: ';' not found after goto"); + + return new (ctx.get()) SynGoto(start, ctx.Previous(), labeIdentifier); + } + + return NULL; +} + SynTypedef* ParseTypedef(ParseContext &ctx) { Lexeme *start = ctx.currentLexeme; @@ -2906,56 +2950,42 @@ SynShortFunctionDefinition* ParseShortFunctionDefinition(ParseContext &ctx) SynBase* ParseStatement(ParseContext &ctx) { - if(SynBase *node = ParseClassDefinition(ctx)) - return node; - - if(SynBase *node = ParseEnumDefinition(ctx)) - return node; - - if(SynBase *node = ParseNamespaceDefinition(ctx)) - return node; - - if(SynBase *node = ParseReturn(ctx)) - return node; - - if(SynBase *node = ParseYield(ctx)) - return node; - - if(SynBase *node = ParseBreak(ctx)) - return node; - - if(SynBase *node = ParseContinue(ctx)) - return node; - - if(SynBase *node = ParseTypedef(ctx)) - return node; - - if(SynBase *node = ParseBlock(ctx)) - return node; - - if(SynBase *node = ParseIfElse(ctx, false)) - return node; - - if(SynBase *node = ParseForEach(ctx)) - return node; - - if(SynBase *node = ParseFor(ctx)) - return node; - - if(SynBase *node = ParseWhile(ctx)) - return node; - - if(SynBase *node = ParseDoWhile(ctx)) - return node; - - if(SynBase *node = ParseSwitch(ctx)) - return node; - - if(SynBase *node = ParseFunctionDefinition(ctx)) - return node; - - if(SynBase *node = ParseVariableDefinitions(ctx, false)) - return node; + SynBase *node; + switch(ctx.Peek()) { + case lex_enum: return ParseEnumDefinition(ctx); + case lex_namespace: return ParseNamespaceDefinition(ctx); + case lex_return: return ParseReturn(ctx); + case lex_yield: return ParseYield(ctx); + case lex_break: return ParseBreak(ctx); + case lex_continue: return ParseContinue(ctx); + case lex_goto: return ParseGoto(ctx); + case lex_typedef: return ParseTypedef(ctx); + case lex_ofigure: return ParseBlock(ctx); + case lex_for: + if((node = ParseForEach(ctx))) + return node; + return ParseFor(ctx); + case lex_while: return ParseWhile(ctx); + case lex_do: return ParseDoWhile(ctx); + case lex_switch: return ParseSwitch(ctx); + + default: + + if((node = ParseClassDefinition(ctx))) + return node; + + if((node = ParseFunctionDefinition(ctx))) + return node; + + if((node = ParseVariableDefinitions(ctx, false))) + return node; + + if((node = ParseIfElse(ctx, false))) + return node; + + if((node = ParseLabel(ctx))) + return node; + } return NULL; } @@ -3374,6 +3404,14 @@ void VisitParseTreeNodes(SynBase *syntax, void *context, void(*accept)(void *con { VisitParseTreeNodes(node->number, context, accept); } + else if(SynLabel *node = getType(syntax)) + { + VisitParseTreeNodes(node->labeIdentifier, context, accept); + } + else if(SynGoto *node = getType(syntax)) + { + VisitParseTreeNodes(node->labeIdentifier, context, accept); + } else if(SynBlock *node = getType(syntax)) { for(SynBase *expr = node->expressions.head; expr; expr = expr->next) diff --git a/NULLC/ParseTree.h b/NULLC/ParseTree.h index 014c461ae..0bc01129f 100644 --- a/NULLC/ParseTree.h +++ b/NULLC/ParseTree.h @@ -301,6 +301,10 @@ namespace SynNode SynNamespaceDefinition, SynModuleImport, SynModule, + // the order above this line seem to be important + // don't change, insert, delete above this line ! + SynGoto, + SynLabel, }; } @@ -740,6 +744,28 @@ struct SynContinue: SynBase static const unsigned myTypeID = SynNode::SynContinue; }; +struct SynLabel: SynBase +{ + SynLabel(Lexeme *begin, Lexeme *end, SynIdentifier *labeIdentifier): SynBase(myTypeID, begin, end), labeIdentifier(labeIdentifier) + { + } + + SynIdentifier *labeIdentifier; + + static const unsigned myTypeID = SynNode::SynLabel; +}; + +struct SynGoto: SynBase +{ + SynGoto(Lexeme *begin, Lexeme *end, SynIdentifier *labeIdentifier): SynBase(myTypeID, begin, end), labeIdentifier(labeIdentifier) + { + } + + SynIdentifier *labeIdentifier; + + static const unsigned myTypeID = SynNode::SynGoto; +}; + struct SynBlock: SynBase { SynBlock(Lexeme *begin, Lexeme *end, IntrusiveList expressions): SynBase(myTypeID, begin, end), expressions(expressions) @@ -1069,7 +1095,7 @@ struct SynClassElements: SynBase struct SynClassDefinition: SynBase { - SynClassDefinition(Lexeme *begin, Lexeme *end, SynAlign* align, SynIdentifier* name, IntrusiveList aliases, bool extendable, SynBase *baseClass, SynClassElements *elements): SynBase(myTypeID, begin, end), align(align), name(name), aliases(aliases), extendable(extendable), baseClass(baseClass), elements(elements) + SynClassDefinition(Lexeme *begin, Lexeme *end, SynAlign* align, SynIdentifier* name, IntrusiveList aliases, bool extendable, bool isStruct, SynBase *baseClass, SynClassElements *elements): SynBase(myTypeID, begin, end), align(align), name(name), aliases(aliases), extendable(extendable), isStruct(isStruct), baseClass(baseClass), elements(elements) { imported = false; } @@ -1079,6 +1105,7 @@ struct SynClassDefinition: SynBase SynIdentifier* name; IntrusiveList aliases; bool extendable; + bool isStruct; SynBase *baseClass; SynClassElements *elements; diff --git a/tests/TestExtra.cpp b/tests/TestExtra.cpp index eafd943cb..806f5c6f3 100644 --- a/tests/TestExtra.cpp +++ b/tests/TestExtra.cpp @@ -2,7 +2,7 @@ #include -const char *testMissingTests = +const char *testMissingTests = "long a1 = 01, a2 = 0377, a3 = 01777777, a4 = 017777777777777777;\r\n\ long b1 = 0b, b2 = 1b, b3 = 1111111111100001010100101b, b4 = 101010101101010101011010101010011101011010010101110101010101001b;\r\n\ \r\n\ @@ -431,13 +431,13 @@ int CheckAlignmentStruct(NULLCRef ptr) return obj->x == 0x34 && obj->y == 32.0 && obj->z == 0x45; } -LOAD_MODULE_BIND(test_alignment_struct, "test.alignment.struct", "int CheckAlignmentStruct(auto ref ptr);") +LOAD_MODULE_BIND(test_alignment_struct, "test.alignment.xstruct", "int CheckAlignmentStruct(auto ref ptr);") { - nullcBindModuleFunctionHelper("test.alignment.struct", CheckAlignmentStruct, "CheckAlignmentStruct", 0); + nullcBindModuleFunctionHelper("test.alignment.xstruct", CheckAlignmentStruct, "CheckAlignmentStruct", 0); } const char *testAlignmentPadding4 = -"import test.alignment.struct;\r\n\ +"import test.alignment.xstruct;\r\n\ class X{ char x; double v; char z; }\r\n\ X x;\r\n\ x.x = 0x34;\r\n\ @@ -1180,7 +1180,7 @@ total += -arr11[0] + -arr11[8];\r\n\ return total;"; TEST_RESULT("Array lowering check 6", testArrayLowering6, "10"); -const char *testArrayLowering7 = +const char *testArrayLowering7 = "int a(auto ref[] args){ return args.size; }\r\n\ int b(bool ctx){ return a(ctx ? char[](\"a, \") : char[](\"\"), ctx ? char[](\"b, \") : char[](\"\"), ctx ? char[](\"c, \") : char[](\"\")); }\r\n\ return b(true);"; diff --git a/tests/nullc_in_nullc/lexer.nc b/tests/nullc_in_nullc/lexer.nc index bcd00de14..65b0fffad 100644 --- a/tests/nullc_in_nullc/lexer.nc +++ b/tests/nullc_in_nullc/lexer.nc @@ -55,7 +55,10 @@ enum LexemeType lex_typeof, lex_sizeof, lex_new, lex_operator, lex_typedef, lex_import, lex_nullptr, // typeof sizeof new operator typedef import in nullptr lex_coroutine, lex_yield, // coroutine yield lex_at, // @ - lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with // generic const true false enum namespace extendable with + lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with, // generic const true false enum namespace extendable with + // it seems that there is a place where the position of the above tokes is significant + // do not change, add, remove anything above this line unless you find it ! + lex_goto, lex_struct // goto struct } class Lexeme @@ -484,6 +487,8 @@ void Lexer::Lexify(char[] code) lType = LexemeType.lex_enum; else if(memcmp(code, curr, "with", 4) == 0) lType = LexemeType.lex_with; + else if(memcmp(code, curr, "goto", 4) == 0) + lType = LexemeType.lex_goto; break; case 5: if(memcmp(code, curr, "while", 5) == 0) @@ -512,6 +517,8 @@ void Lexer::Lexify(char[] code) lType = LexemeType.lex_sizeof; else if(memcmp(code, curr, "import", 6) == 0) lType = LexemeType.lex_import; + else if(memcmp(code, curr, "struct", 6) == 0) + lType = LexemeType.lex_struct; break; case 7: if(memcmp(code, curr, "noalign", 7) == 0) @@ -608,4 +615,4 @@ test.Clear(0); test.Lexify("return 2 * 3"); return k; -*/ \ No newline at end of file +*/ diff --git a/tests/nullc_in_nullc/parser.nc b/tests/nullc_in_nullc/parser.nc index 63684c9fa..40854531e 100644 --- a/tests/nullc_in_nullc/parser.nc +++ b/tests/nullc_in_nullc/parser.nc @@ -1429,7 +1429,9 @@ SynBase ref ParseClassDefinition(ParseContext ref ctx) SynAlign ref alignment = ParseAlign(ctx); - if(ctx.Consume(LexemeType.lex_class)) + bool isStruct = ctx.Consume(LexemeType.lex_struct); + + if(isStruct || ctx.Consume(LexemeType.lex_class)) { SynIdentifier ref nameIdentifier = nullptr; @@ -1498,7 +1500,7 @@ SynBase ref ParseClassDefinition(ParseContext ref ctx) CheckConsume(ctx, LexemeType.lex_cfigure, "ERROR: '}' not found after class definition"); - return new SynClassDefinition(start, ctx.Previous(), alignment, nameIdentifier, aliases, isExtendable, baseClass, elements); + return new SynClassDefinition(start, ctx.Previous(), alignment, nameIdentifier, aliases, isExtendable, isStruct, baseClass, elements); } // Backtrack @@ -1683,6 +1685,40 @@ SynContinue ref ParseContinue(ParseContext ref ctx) return nullptr; } +SynLabel ref ParseLabel(ParseContext ref ctx) +{ + LexemeRef start = ctx.currentLexeme; + + if(ctx.Consume(LexemeType.lex_continue)) + { + // Optional + SynNumber ref node = ParseNumber(ctx); + + CheckConsume(ctx, LexemeType.lex_semicolon, "ERROR: continue statement must be followed by ';' or a constant"); + + return new SynLabel(start, ctx.Previous(), node); + } + + return nullptr; +} + +SynGoto ref ParseGoto(ParseContext ref ctx) +{ + LexemeRef start = ctx.currentLexeme; + + if(ctx.Consume(LexemeType.lex_continue)) + { + // Optional + SynNumber ref node = ParseNumber(ctx); + + CheckConsume(ctx, LexemeType.lex_semicolon, "ERROR: continue statement must be followed by ';' or a constant"); + + return new SynGoto(start, ctx.Previous(), node); + } + + return nullptr; +} + SynTypedef ref ParseTypedef(ParseContext ref ctx) { LexemeRef start = ctx.currentLexeme; @@ -2787,6 +2823,12 @@ SynBase ref ParseExpression(ParseContext ref ctx) if(SynBase ref node = ParseContinue(ctx)) return node; + if(SynBase ref node = ParseGoto(ctx)) + return node; + + if(SynBase ref node = ParseLabel(ctx)) + return node; + if(SynBase ref node = ParseTypedef(ctx)) return node; @@ -3205,6 +3247,14 @@ void VisitParseTreeNodes(SynBase ref syntax, void ref(SynBase ref) accept) { VisitParseTreeNodes(node.number, accept); } + else if(SynLabel ref node = getType with(syntax)) + { + VisitParseTreeNodes(node.number, accept); + } + else if(SynGoto ref node = getType with(syntax)) + { + VisitParseTreeNodes(node.number, accept); + } else if(SynBlock ref node = getType with(syntax)) { for(SynBase ref expr = node.expressions.head; expr; expr = expr.next) @@ -3479,6 +3529,10 @@ char[] GetParseTreeNodeName(SynBase ref syntax) return "SynBreak"; case SynContinue: return "SynContinue"; + case SynLabel: + return "SynLabel"; + case SynGoto: + return "SynGoto"; case SynBlock: return "SynBlock"; case SynIfElse: diff --git a/tests/nullc_in_nullc/parsetree.nc b/tests/nullc_in_nullc/parsetree.nc index 069fc485d..8cc51df43 100644 --- a/tests/nullc_in_nullc/parsetree.nc +++ b/tests/nullc_in_nullc/parsetree.nc @@ -889,6 +889,38 @@ class SynContinue: SynBase SynNumber ref number; } +class SynLabel: SynBase +{ + void SynLabel(LexemeRef begin, LexemeRef end, SynNumber ref number) + { + this.begin = begin; + this.end = end; + + if(begin.owner && end.owner) + this.pos = InplaceStr(begin.owner.code, begin.pos.pos, end.pos.pos + end.length); + + this.number = number; + } + + SynNumber ref number; +} + +class SynGoto: SynBase +{ + void SynGoto(LexemeRef begin, LexemeRef end, SynNumber ref number) + { + this.begin = begin; + this.end = end; + + if(begin.owner && end.owner) + this.pos = InplaceStr(begin.owner.code, begin.pos.pos, end.pos.pos + end.length); + + this.number = number; + } + + SynNumber ref number; +} + class SynBlock: SynBase { void SynBlock(LexemeRef begin, LexemeRef end, RefList expressions) @@ -1393,7 +1425,7 @@ class SynClassElements: SynBase class SynClassDefinition: SynBase { - void SynClassDefinition(LexemeRef begin, LexemeRef end, SynAlign ref alignment, SynIdentifier ref name, RefList aliases, bool isExtendable, SynBase ref baseClass, SynClassElements ref elements) + void SynClassDefinition(LexemeRef begin, LexemeRef end, SynAlign ref alignment, SynIdentifier ref name, RefList aliases, bool isExtendable, bool isStruct, SynBase ref baseClass, SynClassElements ref elements) { this.begin = begin; this.end = end; @@ -1405,6 +1437,7 @@ class SynClassDefinition: SynBase this.name = name; this.aliases = aliases; this.isExtendable = isExtendable; + this.isStruct = isStruct; this.baseClass = baseClass; this.elements = elements; @@ -1416,6 +1449,7 @@ class SynClassDefinition: SynBase SynIdentifier ref name; RefList aliases; bool isExtendable; + bool isStruct; SynBase ref baseClass; SynClassElements ref elements; } From 62b869b6771090426969a4817fe8389db6897f34 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sat, 1 Oct 2022 10:34:16 +0200 Subject: [PATCH 15/20] Somehow it seems that the problem was related to source dependencies after a "make clean" build succeeded. --- NULLC/Lexer.h | 11 ++++------- NULLC/ParseTree.h | 6 ++---- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/NULLC/Lexer.h b/NULLC/Lexer.h index 9622a1f32..5bfb71324 100644 --- a/NULLC/Lexer.h +++ b/NULLC/Lexer.h @@ -45,17 +45,14 @@ enum LexemeType lex_set, lex_addset, lex_subset, lex_mulset, lex_divset, lex_powset, lex_modset, lex_shlset, lex_shrset, lex_andset, lex_orset, lex_xorset, // = += -= *= /= **= %= <<= >>= &= |= ^= lex_bitnot, lex_lognot, // ~ ! lex_oparen, lex_cparen, lex_obracket, lex_cbracket, lex_ofigure, lex_cfigure, // ( ) [ ] { } - lex_questionmark, lex_colon, lex_semicolon, lex_dblcolon,// ? : ; :: + lex_questionmark, lex_colon, lex_dblcolon, lex_semicolon, // ? : :: ; lex_if, lex_else, lex_for, lex_while, lex_do, lex_switch, lex_case, lex_default, // if else for while switch case default - lex_break, lex_continue, lex_return, // break continue return - lex_ref, lex_auto, lex_class, lex_noalign, lex_align, // ref auto class noalign align + lex_break, lex_continue, lex_goto, lex_return, // break continue goto return + lex_ref, lex_auto, lex_class, lex_struct, lex_noalign, lex_align, // ref auto class struct noalign align lex_typeof, lex_sizeof, lex_new, lex_operator, lex_typedef, lex_import, lex_nullptr, // typeof sizeof new operator typedef import in nullptr lex_coroutine, lex_yield, // coroutine yield lex_at, // @ - lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with, // generic const true false enum namespace extendable with - // it seems that there is a place where the position of the above tokes is significant - // do not change, add, remove anything above this line unless you find it ! - lex_goto, lex_struct // goto struct + lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with // generic const true false enum namespace extendable with }; struct Lexeme diff --git a/NULLC/ParseTree.h b/NULLC/ParseTree.h index 0bc01129f..c1647d220 100644 --- a/NULLC/ParseTree.h +++ b/NULLC/ParseTree.h @@ -271,6 +271,8 @@ namespace SynNode SynYield, SynBreak, SynContinue, + SynGoto, + SynLabel, SynBlock, SynIfElse, SynFor, @@ -301,10 +303,6 @@ namespace SynNode SynNamespaceDefinition, SynModuleImport, SynModule, - // the order above this line seem to be important - // don't change, insert, delete above this line ! - SynGoto, - SynLabel, }; } From 8a34423d4be3d8cd59af1bb19aa6d47c305a6cf2 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sat, 1 Oct 2022 14:43:44 +0200 Subject: [PATCH 16/20] Almost working the conversion of namespace separator from '.' by '::' --- NULLC/ParseTree.cpp | 10 +- tests/TestClasses.cpp | 10 +- tests/TestCompileFail.cpp | 6 +- tests/TestGeneric.cpp | 2 +- tests/TestModules.cpp | 4 +- tests/TestNamespace.cpp | 228 ++++++++++++------------ tests/TestParseFail.cpp | 2 +- tests/TestSpecial.cpp | 44 ++--- tests/nullc_in_nullc/analyzer.nc | 18 +- tests/nullc_in_nullc/compiler.nc | 10 +- tests/nullc_in_nullc/expressioneval.nc | 38 ++-- tests/nullc_in_nullc/expressiongraph.nc | 2 +- tests/nullc_in_nullc/parser.nc | 10 +- tests/nullc_in_nullc/stringutil.nc | 2 +- tests/nullc_in_nullc/typetreehelpers.nc | 14 +- 15 files changed, 200 insertions(+), 200 deletions(-) diff --git a/NULLC/ParseTree.cpp b/NULLC/ParseTree.cpp index 5fa0659ca..527fafca3 100644 --- a/NULLC/ParseTree.cpp +++ b/NULLC/ParseTree.cpp @@ -534,11 +534,11 @@ SynBase* ParseTerminalType(ParseContext &ctx, bool &shrBorrow) SynNamespaceElement *ns = NULL; - while(ctx.At(lex_point) && (ns = ctx.IsNamespace(ns, name)) != NULL) + while(ctx.At(lex_dblcolon) && (ns = ctx.IsNamespace(ns, name)) != NULL) { ctx.Skip(); - if(!CheckAt(ctx, lex_identifier, "ERROR: namespace member is expected after '.'")) + if(!CheckAt(ctx, lex_identifier, "ERROR: namespace member is expected after '::'")) { namespacePath.push_back(new (ctx.get()) SynIdentifier(start, ctx.Previous(), name)); @@ -1715,9 +1715,9 @@ SynNamespaceDefinition* ParseNamespaceDefinition(ParseContext &ctx) path.push_back(new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), value)); } - while(ctx.Consume(lex_point)) + while(ctx.Consume(lex_dblcolon)) { - if(!CheckAt(ctx, lex_identifier, "ERROR: namespace name required after '.'")) + if(!CheckAt(ctx, lex_identifier, "ERROR: namespace name required after '::'")) break; InplaceStr value = ctx.Consume(); @@ -2789,7 +2789,7 @@ SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) } else if(parentType) { - Stop(ctx, ctx.Current(), "ERROR: function name expected after ':' or '.'"); + Stop(ctx, ctx.Current(), "ERROR: function name expected after '::' or '.'"); } else if(coroutine && !allowEmptyName) { diff --git a/tests/TestClasses.cpp b/tests/TestClasses.cpp index 8a57977ef..f658ba01b 100644 --- a/tests/TestClasses.cpp +++ b/tests/TestClasses.cpp @@ -821,16 +821,16 @@ const char *testClassAssignmentOperator2 = }\r\n\ }\r\n\ \r\n\ -A.Foo a;\r\n\ +A::Foo a;\r\n\ a.a = new int(4);\r\n\ -A.Foo b = a;\r\n\ +A::Foo b = a;\r\n\ *b.a = 10;\r\n\ \r\n\ assert(a.a != b.a);\r\n\ assert(*a.a == 4);\r\n\ assert(*b.a == 10);\r\n\ \r\n\ -A.Bar1 m1, n1;\r\n\ +A::Bar1 m1, n1;\r\n\ m1.x = 7;\r\n\ m1.y.a = &m1.x;\r\n\ \r\n\ @@ -1182,13 +1182,13 @@ TEST_RESULT("Class custom construction inside a member function", testClassCusto const char *testEnumeration3 = "namespace Foo{ enum Bar{ C, D } }\r\n\ -Foo.Bar y = Foo.Bar(1);\r\n\ +Foo::Bar y = Foo::Bar(1);\r\n\ return y;"; TEST_RESULT("Enumeration test 3", testEnumeration3, "1"); const char *testEnumeration4 = "namespace Foo{ enum Bar{ C, D } }\r\n\ -Foo.Bar y = Foo.Bar(1);\r\n\ +Foo::Bar y = Foo::Bar(1);\r\n\ return int(y);"; TEST_RESULT("Enumeration test 4", testEnumeration4, "1"); diff --git a/tests/TestCompileFail.cpp b/tests/TestCompileFail.cpp index a661dea79..66bdd5dc9 100644 --- a/tests/TestCompileFail.cpp +++ b/tests/TestCompileFail.cpp @@ -146,7 +146,7 @@ void RunCompileFailTests() TEST_FOR_FAIL("Class function return unclear 1", "class Test{int i;int foo(){ return i; }int foo(int k){ return i; }auto bar(){ return foo; }}return 1;", "ERROR: ambiguity, there is more than one overloaded function available:"); TEST_FOR_FAIL("Class externally defined method 1", "int dontexist::don(){ return 0; } return 1;", "ERROR: 'dontexist' is not a known type name"); - TEST_FOR_FAIL("Class externally defined method 2", "int int::(){ return *this; } return 1;", "ERROR: function name expected after ':' or '.'"); + TEST_FOR_FAIL("Class externally defined method 2", "int int::(){ return *this; } return 1;", "ERROR: function name expected after '::' or '.'"); TEST_FOR_FAIL("Member variable or function is not found", "int a; a.b; return 1;", "ERROR: member variable or function 'b' is not defined in class 'int'"); @@ -598,7 +598,7 @@ return int(y() + z());", TEST_FOR_FAIL("namespace error", "namespace Test{} int Test;", "ERROR: name 'Test' is already taken for a namespace"); TEST_FOR_FAIL("namespace error", "int Test; namespace Test{}", "ERROR: name 'Test' is already taken for a variable in current scope"); TEST_FOR_FAIL("namespace error", "namespace Test{ int foo(){ return 12; } } return foo();", "ERROR: unknown identifier 'foo'"); - TEST_FOR_FAIL("namespace error", "namespace Test{ namespace Nested{ int x; } } return Nested.x;", "ERROR: unknown identifier 'Nested'"); + TEST_FOR_FAIL("namespace error", "namespace Test{ namespace Nested{ int x; } } return Nested::x;", "ERROR: unknown identifier 'Nested'"); TEST_FOR_FAIL("enum error", "namespace Test{} enum Test{ A }", "ERROR: name 'Test' is already taken for a namespace"); TEST_FOR_FAIL("enum error", "enum Test{ A } namespace Test{}", "ERROR: name 'Test' is already taken for a type"); @@ -606,7 +606,7 @@ return int(y() + z());", TEST_FOR_FAIL("no biggy", "int[1024 * 1024 * 1024] f; f[3] = 0;", "ERROR: variable size limit exceeded"); - TEST_FOR_FAIL("namespace error", "int foo(){ namespace Test{ int x; } return Test.x; }", "ERROR: a namespace definition must appear either at file scope or immediately within another namespace definition"); + TEST_FOR_FAIL("namespace error", "int foo(){ namespace Test{ int x; } return Test::x; }", "ERROR: a namespace definition must appear either at file scope or immediately within another namespace definition"); TEST_FOR_FAIL("reserved function", "int __newS(){ return 4; }", "ERROR: function '__newS' is reserved"); TEST_FOR_FAIL("reserved function", "int __newA(){ return 4; }", "ERROR: function '__newA' is reserved"); diff --git a/tests/TestGeneric.cpp b/tests/TestGeneric.cpp index 6a9ade0aa..b20c3e7ef 100644 --- a/tests/TestGeneric.cpp +++ b/tests/TestGeneric.cpp @@ -1899,7 +1899,7 @@ const char *testGenericClassOperatorInANamespace = \r\n\ int operator+(Foo a, generic b){return a.a + b.a; }\r\n\ }\r\n\ -auto x = Test.Foo(1), y = Test.Foo(20);\r\n\ +auto x = Test::Foo(1), y = Test::Foo(20);\r\n\ return x + y;"; TEST_RESULT("Generic operator of a class defined in a namespace", testGenericClassOperatorInANamespace, "21"); diff --git a/tests/TestModules.cpp b/tests/TestModules.cpp index 004b8c9a3..05f7c66b2 100644 --- a/tests/TestModules.cpp +++ b/tests/TestModules.cpp @@ -114,14 +114,14 @@ TEST_RESULT("Enum import 3", testImportEnum3, "1"); LOAD_MODULE(test_importnamespacecoroutine, "test.importnamespacecoroutine", "namespace Foo{coroutine int foo(){return 0;}}"); const char *testImportNamespaceCoroutine = "import test.importnamespacecoroutine;\r\n\ -for(i in Foo.foo){}\r\n\ +for(i in Foo::foo){}\r\n\ return 1;"; TEST_RESULT("Import coroutine from a namespace", testImportNamespaceCoroutine, "1"); LOAD_MODULE(test_importnamespacecoroutine2, "test.importnamespacecoroutine2", "import std.range; namespace Foo{coroutine int foo(){return 5;}}"); const char *testImportNamespaceCoroutine2 = "import test.importnamespacecoroutine2;\r\n\ -auto y = Foo.foo;\r\n\ +auto y = Foo::foo;\r\n\ return y();"; TEST_RESULT("Import coroutine from a namespace 2", testImportNamespaceCoroutine2, "5"); diff --git a/tests/TestNamespace.cpp b/tests/TestNamespace.cpp index 1355ea1df..1f6148aec 100644 --- a/tests/TestNamespace.cpp +++ b/tests/TestNamespace.cpp @@ -10,7 +10,7 @@ const char *testNamespace1 = {\r\n\ int foo(){ return 12; }\r\n\ }\r\n\ -return Test.foo();"; +return Test::foo();"; TEST_RESULT("namespace test 1", testNamespace1, "12"); const char *testNamespace2 = @@ -19,7 +19,7 @@ const char *testNamespace2 = int foo(){ return 12; }\r\n\ int bar(){ return foo(); }\r\n\ }\r\n\ -return Test.bar();"; +return Test::bar();"; TEST_RESULT("namespace test 2", testNamespace2, "12"); const char *testNamespace3 = @@ -32,7 +32,7 @@ const char *testNamespace3 = }\r\n\ int bar(){ return foo(); }\r\n\ }\r\n\ -return Test.bar() + Test.Nested.bar();"; +return Test::bar() + Test::Nested::bar();"; TEST_RESULT("namespace test 3", testNamespace3, "24"); const char *testNamespace4 = @@ -46,7 +46,7 @@ const char *testNamespace4 = }\r\n\ int bar(){ return foo(); }\r\n\ }\r\n\ -return Test.bar() + Test.Nested.bar();"; +return Test::bar() + Test::Nested::bar();"; TEST_RESULT("namespace test 4", testNamespace4, "15"); const char *testNamespace5 = @@ -58,7 +58,7 @@ namespace Test\r\n\ {\r\n\ int bar(){ return 5 + foo(); }\r\n\ }\r\n\ -return Test.foo() + Test.bar();"; +return Test::foo() + Test::bar();"; TEST_RESULT("namespace test 5", testNamespace5, "29"); const char *testNamespace6 = @@ -73,7 +73,7 @@ namespace Test\r\n\ int bar(){ return foo(); }\r\n\ }\r\n\ }\r\n\ -return Test.Nested.bar();"; +return Test::Nested::bar();"; TEST_RESULT("namespace test 6", testNamespace6, "12"); const char *testNamespace7 = @@ -86,10 +86,10 @@ namespace Test\r\n\ namespace Nested\r\n\ {\r\n\ int foo(){ return 0; }\r\n\ - int bar(){ return Test.foo(); }\r\n\ + int bar(){ return Test::foo(); }\r\n\ }\r\n\ }\r\n\ -return Test.Nested.bar();"; +return Test::Nested::bar();"; TEST_RESULT("namespace test 7", testNamespace7, "12"); const char *testNamespace8 = @@ -100,9 +100,9 @@ const char *testNamespace8 = int a;\r\n\ }\r\n\ }\r\n\ -Test.Foo x;\r\n\ +Test::Foo x;\r\n\ x.a = 10;\r\n\ -return x.a + sizeof(Test.Foo);"; +return x.a + sizeof(Test::Foo);"; TEST_RESULT("namespace test 8", testNamespace8, "14"); const char *testNamespace9 = @@ -120,8 +120,8 @@ const char *testNamespace9 = }\r\n\ }\r\n\ }\r\n\ -Test.Foo x;\r\n\ -Test.Nested.Foo y;\r\n\ +Test::Foo x;\r\n\ +Test::Nested::Foo y;\r\n\ return sizeof(x) + sizeof(y);"; TEST_RESULT("namespace test 9", testNamespace9, "12"); @@ -145,8 +145,8 @@ class Foo\r\n\ int[25] xx;\r\n\ }\r\n\ Foo x;\r\n\ -Test.Foo y;\r\n\ -Test.Nested.Foo z;\r\n\ +Test::Foo y;\r\n\ +Test::Nested::Foo z;\r\n\ return sizeof(x) + sizeof(y) + sizeof(z);"; TEST_RESULT("namespace test 10", testNamespace10, "112"); @@ -162,7 +162,7 @@ namespace Bar\r\n\ int foo(){ return 12; }\r\n\ }\r\n\ }\r\n\ -return Test.foo();"; +return Test::foo();"; TEST_RESULT("namespace test 11", testNamespace11, "24"); const char *testNamespace12 = @@ -174,8 +174,8 @@ const char *testNamespace12 = class Foo{ int y, z; }\r\n\ }\r\n\ }\r\n\ -typeid a = Test.Foo;\r\n\ -return a != Test.Nested.Foo;"; +typeid a = Test::Foo;\r\n\ +return a != Test::Nested::Foo;"; TEST_RESULT("namespace test 12", testNamespace12, "1"); const char *testNamespace13 = @@ -185,9 +185,9 @@ const char *testNamespace13 = \r\n\ Foo x;\r\n\ }\r\n\ -Test.x.z = 5;\r\n\ +Test::x.z = 5;\r\n\ \r\n\ -return Test.x.z;"; +return Test::x.z;"; TEST_RESULT("namespace test 13", testNamespace13, "5"); const char *testNamespace14 = @@ -198,7 +198,7 @@ const char *testNamespace14 = Foo x;\r\n\ x.z = 5;\r\n\ }\r\n\ -return Test.x.z;"; +return Test::x.z;"; TEST_RESULT("namespace test 14", testNamespace14, "5"); const char *testNamespace15 = @@ -208,7 +208,7 @@ const char *testNamespace15 = \r\n\ Foo x;\r\n\ }\r\n\ -return Test.x.z;"; +return Test::x.z;"; TEST_RESULT("namespace test 15", testNamespace15, "14"); const char *testNamespace16 = @@ -216,7 +216,7 @@ const char *testNamespace16 = {\r\n\ class Foo{ int z; void Foo(){ z = 14; } }\r\n\ }\r\n\ -Test.Foo x;\r\n\ +Test::Foo x;\r\n\ return x.z;"; TEST_RESULT("namespace test 16", testNamespace16, "14"); @@ -232,8 +232,8 @@ const char *testNamespace17 = z.a = 300;\r\n\ w.a = 7;\r\n\ }\r\n\ -Test.Foo x, y; x.a = 10; y.a = 20;\r\n\ -return (x + y) + (Test.z + Test.w);"; +Test::Foo x, y; x.a = 10; y.a = 20;\r\n\ +return (x + y) + (Test::z + Test::w);"; TEST_RESULT("namespace test 17", testNamespace17, "337"); const char *testNamespace18 = @@ -243,7 +243,7 @@ const char *testNamespace18 = \r\n\ Foo x;\r\n\ }\r\n\ -Test.Foo a = Test.Foo(4);\r\n\ +Test::Foo a = Test::Foo(4);\r\n\ return a.z;"; TEST_RESULT("namespace test 18", testNamespace18, "4"); @@ -257,7 +257,7 @@ const char *testNamespace19 = int bar(int y){ return x + y; }\r\n\ }\r\n\ }\r\n\ -Test.Foo a;\r\n\ +Test::Foo a;\r\n\ return a.bar(3);"; TEST_RESULT("namespace test 19", testNamespace19, "6"); @@ -272,7 +272,7 @@ const char *testNamespace20 = int bar(int y){ return x + y; }\r\n\ }\r\n\ }\r\n\ -Test.Foo a, b = Test.Foo(6);\r\n\ +Test::Foo a, b = Test::Foo(6);\r\n\ return a.bar(3) + b.bar(30);"; TEST_RESULT("namespace test 20", testNamespace20, "42"); @@ -287,7 +287,7 @@ const char *testNamespace21 = int bar(int y){ return x + y; }\r\n\ }\r\n\ }\r\n\ -Test.Foo ref a = new Test.Foo, b = new Test.Foo(), c = new Test.Foo(100);\r\n\ +Test::Foo ref a = new Test::Foo, b = new Test::Foo(), c = new Test::Foo(100);\r\n\ return a.bar(3) + b.bar(30) + c.bar(400);"; TEST_RESULT("namespace test 21", testNamespace21, "539"); @@ -303,7 +303,7 @@ const char *testNamespace22 = }\r\n\ Foo ref a = new Foo, b = new Foo(), c = new Foo(100);\r\n\ }\r\n\ -return Test.a.bar(3) + Test.b.bar(30) + Test.c.bar(400);"; +return Test::a.bar(3) + Test::b.bar(30) + Test::c.bar(400);"; TEST_RESULT("namespace test 22", testNamespace22, "539"); const char *testNamespace23 = @@ -318,7 +318,7 @@ const char *testNamespace23 = }\r\n\ Foo a, b = Foo(), c = Foo(100);\r\n\ }\r\n\ -return Test.a.bar(3) + Test.b.bar(30) + Test.c.bar(400);"; +return Test::a.bar(3) + Test::b.bar(30) + Test::c.bar(400);"; TEST_RESULT("namespace test 23", testNamespace23, "539"); const char *testNamespace24 = @@ -329,7 +329,7 @@ const char *testNamespace24 = int y = foo(5);\r\n\ auto z = foo(4.5);\r\n\ }\r\n\ -return int(Test.y * Test.z);"; +return int(Test::y * Test::z);"; TEST_RESULT("namespace test 24", testNamespace24, "22"); const char *testNamespace25 = @@ -337,7 +337,7 @@ const char *testNamespace25 = {\r\n\ auto foo(generic x){ return -x; }\r\n\ }\r\n\ -return Test.foo(5);"; +return Test::foo(5);"; TEST_RESULT("namespace test 25", testNamespace25, "-5"); const char *testNamespace26 = @@ -348,7 +348,7 @@ const char *testNamespace26 = a = foo(a, 0, 1023);\r\n\ b = foo(b, 0, 1023);\r\n\ }\r\n\ -return Test.a + Test.b;"; +return Test::a + Test::b;"; TEST_RESULT("namespace test 26", testNamespace26, "2046"); const char *testNamespace27 = @@ -358,17 +358,17 @@ const char *testNamespace27 = class Bar\r\n\ {\r\n\ int foo(){ return 10; }\r\n\ - int bar(){ return Test.foo(); }\r\n\ + int bar(){ return Test::foo(); }\r\n\ }\r\n\ }\r\n\ -Test.Bar x;\r\n\ +Test::Bar x;\r\n\ return x.bar();"; TEST_RESULT("namespace test 27", testNamespace27, "5"); LOAD_MODULE(test_namespace, "test.namespace1", "namespace Test{ int foo(int a){ return 3 * a; } }"); const char *testNamespace28 = "import test.namespace1;\r\n\ -return Test.foo(5);"; +return Test::foo(5);"; TEST_RESULT("namespace test 28", testNamespace28, "15"); const char *testNamespace29 = @@ -382,8 +382,8 @@ const char *testNamespace29 = Foo x;\r\n\ int a = x.bar();\r\n\ }\r\n\ -Test.Foo y;\r\n\ -return Test.a + y.bar();"; +Test::Foo y;\r\n\ +return Test::a + y.bar();"; TEST_RESULT("namespace test 29", testNamespace29, "24"); const char *testNamespace30 = @@ -391,7 +391,7 @@ const char *testNamespace30 = {\r\n\ int foo(){ return 5; }\r\n\ }\r\n\ -auto x = Test.foo;\r\n\ +auto x = Test::foo;\r\n\ return x();"; TEST_RESULT("namespace test 30", testNamespace30, "5"); @@ -401,7 +401,7 @@ const char *testNamespace31 = int foo(){ return 5; }\r\n\ auto x = foo;\r\n\ }\r\n\ -return Test.x();"; +return Test::x();"; TEST_RESULT("namespace test 31", testNamespace31, "5"); const char *testNamespace32 = @@ -411,7 +411,7 @@ const char *testNamespace32 = auto x = foo;\r\n\ auto y = x();\r\n\ }\r\n\ -return Test.y;"; +return Test::y;"; TEST_RESULT("namespace test 32", testNamespace32, "5"); const char *testNamespace33 = @@ -420,7 +420,7 @@ const char *testNamespace33 = int foo(){ return 5; }\r\n\ int foo(int x){ return 5 + x; }\r\n\ }\r\n\ -int ref(int) x = Test.foo;\r\n\ +int ref(int) x = Test::foo;\r\n\ return x(2);"; TEST_RESULT("namespace test 33", testNamespace33, "7"); @@ -431,7 +431,7 @@ const char *testNamespace34 = int foo(int x){ return 5 + x; }\r\n\ int ref(int) x = foo;\r\n\ }\r\n\ -return Test.x(2);"; +return Test::x(2);"; TEST_RESULT("namespace test 34", testNamespace34, "7"); const char *testNamespace35 = @@ -442,7 +442,7 @@ const char *testNamespace35 = int ref(int) x = foo;\r\n\ auto y = x(2);\r\n\ }\r\n\ -return Test.y;"; +return Test::y;"; TEST_RESULT("namespace test 35", testNamespace35, "7"); const char *testNamespace36 = @@ -450,7 +450,7 @@ const char *testNamespace36 = {\r\n\ int foo(int ref(int, int) f){ return f(2, 3); }\r\n\ }\r\n\ -return Test.foo({ i + j; });"; +return Test::foo({ i + j; });"; TEST_RESULT("namespace test 36", testNamespace36, "5"); const char *testNamespace37 = @@ -459,7 +459,7 @@ const char *testNamespace37 = int foo(int ref(int, int) f){ return f(2, 3); }\r\n\ auto x = foo({ i + j; });\r\n\ }\r\n\ -return Test.x;"; +return Test::x;"; TEST_RESULT("namespace test 37", testNamespace37, "5"); const char *testNamespace38 = @@ -468,7 +468,7 @@ const char *testNamespace38 = int foo(int ref(int, int) f){ return f(2, 3); }\r\n\ auto x = foo;\r\n\ }\r\n\ -return Test.x({ i + j; });"; +return Test::x({ i + j; });"; TEST_RESULT("namespace test 38", testNamespace38, "5"); const char *testNamespace39 = @@ -477,7 +477,7 @@ const char *testNamespace39 = auto ref x = 5;\r\n\ int y = int(x);\r\n\ }\r\n\ -return Test.y;"; +return Test::y;"; TEST_RESULT("namespace test 39", testNamespace39, "5"); const char *testNamespace40 = @@ -487,7 +487,7 @@ const char *testNamespace40 = auto ref x = Foo(5);\r\n\ int y = Foo(x).x;\r\n\ }\r\n\ -return Test.y;"; +return Test::y;"; TEST_RESULT("namespace test 40", testNamespace40, "5"); const char *testNamespace41 = @@ -496,7 +496,7 @@ const char *testNamespace41 = class Foo{ int x; void Foo(int y){ x = y; } }\r\n\ auto ref x = Foo(5);\r\n\ }\r\n\ -return Test.Foo(Test.x).x;"; +return Test::Foo(Test::x).x;"; TEST_RESULT("namespace test 41", testNamespace41, "5"); const char *testNamespace42 = @@ -505,7 +505,7 @@ const char *testNamespace42 = class Foo{ int x; }\r\n\ int foo(typeid x){ return x == Foo; }\r\n\ }\r\n\ -return Test.foo(Test.Foo);"; +return Test::foo(Test::Foo);"; TEST_RESULT("namespace test 42", testNamespace42, "1"); const char *testNamespace43 = @@ -513,7 +513,7 @@ const char *testNamespace43 = {\r\n\ int foo(int x){ return 3 * x; }\r\n\ }\r\n\ -return Test.foo(Test.foo(5));"; +return Test::foo(Test::foo(5));"; TEST_RESULT("namespace test 43", testNamespace43, "45"); const char *testNamespace44 = @@ -537,7 +537,7 @@ namespace Test\r\n\ Foo> h;\r\n\ h[5][4] = true;\r\n\ }\r\n\ -return Test.h[5][4];"; +return Test::h[5][4];"; TEST_RESULT("namespace test 45 (global generic operator instance inside a namespace)", testNamespace45, "1"); const char *testNamespace46 = @@ -547,7 +547,7 @@ namespace Test\r\n\ int ref(int) a = foo;\r\n\ }\r\n\ int ref(int) a = foo;\r\n\ -return Test.a == a;"; +return Test::a == a;"; TEST_RESULT("namespace test 46 (generic function should be instanced in a correct namespace)", testNamespace46, "1"); const char *testNamespace47 = @@ -557,10 +557,10 @@ const char *testNamespace47 = }\r\n\ namespace Test\r\n\ {\r\n\ - int ref(int) a = Foo.foo;\r\n\ + int ref(int) a = Foo::foo;\r\n\ }\r\n\ -int ref(int) a = Foo.foo;\r\n\ -return Test.a == a;"; +int ref(int) a = Foo::foo;\r\n\ +return Test::a == a;"; TEST_RESULT("namespace test 47 (generic function should be instanced in a correct namespace)", testNamespace47, "1"); const char *testNamespace48 = @@ -572,9 +572,9 @@ const char *testNamespace48 = namespace Test\r\n\ {\r\n\ int bar(int x){ return 1; }\r\n\ - int ref(int) a = Foo.foo;\r\n\ + int ref(int) a = Foo::foo;\r\n\ }\r\n\ -return Test.a(2);"; +return Test::a(2);"; TEST_RESULT("namespace test 48", testNamespace48, "-2"); const char *testNamespace49 = @@ -588,11 +588,11 @@ namespace Test\r\n\ int bar(int x){ return 1; }\r\n\ int ref(int) a;\r\n\ {\r\n\ - int ref(int) b = Foo.foo;\r\n\ + int ref(int) b = Foo::foo;\r\n\ a = b;\r\n\ }\r\n\ }\r\n\ -return Test.a(2);"; +return Test::a(2);"; TEST_RESULT("namespace test 49", testNamespace49, "-2"); const char *testNamespace50 = @@ -604,9 +604,9 @@ const char *testNamespace50 = }\r\n\ namespace Bar\r\n\ {\r\n\ - Test.Foo a;\r\n\ + Test::Foo a;\r\n\ }\r\n\ -return Bar.a.foo();"; +return Bar::a.foo();"; TEST_RESULT("namespace test 50", testNamespace50, "10"); const char *testNamespace51 = @@ -621,9 +621,9 @@ const char *testNamespace51 = }\r\n\ namespace Bar\r\n\ {\r\n\ - Test.Foo a;\r\n\ + Test::Foo a;\r\n\ }\r\n\ -return Bar.a.foo();"; +return Bar::a.foo();"; TEST_RESULT("namespace test 51", testNamespace51, "10"); LOAD_MODULE(test_namespace2, "test.namespace2", "namespace Foo{ auto foo(generic x){ return -x; } }"); @@ -631,10 +631,10 @@ const char *testNamespace52 = "import test.namespace2;\r\n\ namespace Test\r\n\ {\r\n\ - int ref(int) a = Foo.foo;\r\n\ + int ref(int) a = Foo::foo;\r\n\ }\r\n\ -int ref(int) a = Foo.foo;\r\n\ -return Test.a == a;"; +int ref(int) a = Foo::foo;\r\n\ +return Test::a == a;"; TEST_RESULT("namespace test 52", testNamespace52, "1"); LOAD_MODULE(test_namespace3, "test.namespace3", "namespace Test{ int bar(int x){ return x * 2; } class Foo{ T x; int foo(){ return bar(5); } } }"); @@ -642,9 +642,9 @@ const char *testNamespace53 = "import test.namespace3;\r\n\ namespace Bar\r\n\ {\r\n\ - Test.Foo a;\r\n\ + Test::Foo a;\r\n\ }\r\n\ -return Bar.a.foo();"; +return Bar::a.foo();"; TEST_RESULT("namespace test 53", testNamespace53, "10"); const char *testNamespace54 = @@ -673,16 +673,16 @@ const char *testNamespace54 = }\r\n\ glob();\r\n\ }\r\n\ -return Test.r;"; +return Test::r;"; TEST_RESULT("namespace test 54", testNamespace54, "990579"); const char *testNamespace55 = -"namespace A.B.C\r\n\ +"namespace A::B::C\r\n\ {\r\n\ int x = 10;\r\n\ }\r\n\ int y = 5;\r\n\ -return A.B.C.x + y;"; +return A::B::C::x + y;"; TEST_RESULT("namespace test 55 (short-hand nested namespace definition)", testNamespace55, "15"); const char *testNamespace56 = @@ -696,7 +696,7 @@ namespace Test\r\n\ }\r\n\ }\r\n\ Canvas c;\r\n\ -Test.Device d = Test.Device(c);\r\n\ +Test::Device d = Test::Device(c);\r\n\ return d.canvas != nullptr;"; TEST_RESULT("namespace test 56", testNamespace56, "1"); @@ -705,7 +705,7 @@ const char *testNamespace57 = {\r\n\ int foo(int x){ return x * 5; }\r\n\ }\r\n\ -return Test.foo(-1);"; +return Test::foo(-1);"; TEST_RESULT("namespace test 57", testNamespace57, "-5"); const char *testNamespace58 = @@ -713,7 +713,7 @@ const char *testNamespace58 = {\r\n\ int foo(int ref(int, int) x, y){ return x(2, 3) + y(20, 30); }\r\n\ }\r\n\ -return Test.foo({ i + j; }, { i + j; });"; +return Test::foo({ i + j; }, { i + j; });"; TEST_RESULT("namespace test 58", testNamespace58, "55"); const char *testNamespace59 = @@ -724,14 +724,14 @@ const char *testNamespace59 = return 10;\r\n\ }\r\n\ }\r\n\ -auto x = Foo.foo;\r\n\ +auto x = Foo::foo;\r\n\ return x();"; TEST_RESULT("namespace test 59 (coroutine)", testNamespace59, "10"); -LOAD_MODULE(test_namespace60, "test.namespace60", "namespace A.B{ void foo(){} }"); +LOAD_MODULE(test_namespace60, "test.namespace60", "namespace A::B{ void foo(){} }"); const char *testNamespace60 = "import test.namespace60;\r\n\ -A.B.foo();\r\n\ +A::B::foo();\r\n\ return 1;"; TEST_RESULT("namespace test 60", testNamespace60, "1"); @@ -744,7 +744,7 @@ namespace B\r\n\ int bar(int ref x){ return -*x; }\r\n\ }\r\n\ X c;\r\n\ -return B.bar(c.pos);"; +return B::bar(c.pos);"; TEST_RESULT("namespace test 61", testNamespace61, "-10"); const char *testNamespace62 = @@ -756,7 +756,7 @@ namespace B\r\n\ int bar(int ref x){ return -*x; }\r\n\ }\r\n\ X c;\r\n\ -return B.bar(c.pos());"; +return B::bar(c.pos());"; TEST_RESULT("namespace test 62", testNamespace62, "-10"); const char *testNamespace63 = @@ -767,24 +767,24 @@ namespace X\r\n\ int foo(int x){ return -x; }\r\n\ }\r\n\ Bar a, b;\r\n\ -return X.foo(a + b);"; +return X::foo(a + b);"; TEST_RESULT("namespace test 63", testNamespace63, "-12"); const char *testNamespace64 = "namespace X{ void foo(char[] x){} }\r\n\ -X.foo({\"brgrg\", \"brgrg_\"}[0]);\r\n\ +X::foo({\"brgrg\", \"brgrg_\"}[0]);\r\n\ return 1;"; TEST_RESULT("namespace test 64", testNamespace64, "1"); const char *testNamespace65 = -"namespace Bar.Test\r\n\ +"namespace Bar::Test\r\n\ {\r\n\ auto foo(generic x){ return -x; }\r\n\ \r\n\ int y = foo(5);\r\n\ auto z = foo(4.5);\r\n\ }\r\n\ -return int(Bar.Test.y * Bar.Test.z);"; +return int(Bar::Test::y * Bar::Test::z);"; TEST_RESULT("namespace test 65", testNamespace65, "22"); const char *testNamespace66 = @@ -792,9 +792,9 @@ const char *testNamespace66 = {\r\n\ namespace A{ int x = 1; }\r\n\ int x = 2;\r\n\ - int a = A.A.x;\r\n\ + int a = A::A::x;\r\n\ }\r\n\ -return A.a;"; +return A::a;"; TEST_RESULT("namespace test 66", testNamespace66, "1"); const char *testNamespace67 = @@ -805,20 +805,20 @@ const char *testNamespace67 = int x = 2;\r\n\ \r\n\ int u1 = x;\r\n\ - int u2 = A.x;\r\n\ - int u3 = A.A.x;\r\n\ + int u2 = A::x;\r\n\ + int u3 = A::A::x;\r\n\ \r\n\ x += 4;\r\n\ - A.x += 20;\r\n\ - A.A.x += 500;\r\n\ + A::x += 20;\r\n\ + A::A::x += 500;\r\n\ }\r\n\ \r\n\ - A.x += 3000;\r\n\ - A.A.x += 60000;\r\n\ + A::x += 3000;\r\n\ + A::A::x += 60000;\r\n\ }\r\n\ \r\n\ -A.A.x += 10000;\r\n\ -return A.A.x;"; +A::A::x += 10000;\r\n\ +return A::A::x;"; TEST_RESULT("namespace test 67", testNamespace67, "73526"); const char *testNamespace68 = @@ -831,27 +831,27 @@ const char *testNamespace68 = int x = 2;\r\n\ \r\n\ int u1 = x;\r\n\ - int u2 = C.x;\r\n\ - int u3 = B.C.x;\r\n\ - int u4 = A.B.C.x;\r\n\ + int u2 = C::x;\r\n\ + int u3 = B::C::x;\r\n\ + int u4 = A::B::C::x;\r\n\ \r\n\ x += 1;\r\n\ - C.x += 30;\r\n\ - B.C.x += 200;\r\n\ - A.B.C.x += 1000;\r\n\ + C::x += 30;\r\n\ + B::C::x += 200;\r\n\ + A::B::C::x += 1000;\r\n\ }\r\n\ \r\n\ - C.x += 4;\r\n\ - B.C.x += 20;\r\n\ - A.B.C.x += 500;\r\n\ + C::x += 4;\r\n\ + B::C::x += 20;\r\n\ + A::B::C::x += 500;\r\n\ }\r\n\ \r\n\ - B.C.x += 3000;\r\n\ - A.B.C.x += 60000;\r\n\ + B::C::x += 3000;\r\n\ + A::B::C::x += 60000;\r\n\ }\r\n\ \r\n\ -A.B.C.x += 10000;\r\n\ -return A.B.C.x;"; +A::B::C::x += 10000;\r\n\ +return A::B::C::x;"; TEST_RESULT("namespace test 68", testNamespace68, "74757"); const char *testNamespace69 = @@ -899,7 +899,7 @@ namespace A\r\n\ }"; TEST_RESULT("namespace test 71 (local scope priority 2)", testNamespace71, "2"); -LOAD_MODULE(test_namespace72, "test.namespace72", "namespace detail{ int get(){ return 5; } } class Test{ int test(){ return detail.get(); } }"); +LOAD_MODULE(test_namespace72, "test.namespace72", "namespace detail{ int get(){ return 5; } } class Test{ int test(){ return detail::get(); } }"); const char *testNamespace72 = "import test.namespace72;\r\n\ class Foo{ int x; }\r\n\ @@ -907,7 +907,7 @@ Test f;\r\n\ return f.test();"; TEST_RESULT("namespace test 72 (generic type import parse in correct namespace)", testNamespace72, "5"); -LOAD_MODULE(test_namespace73, "test.namespace73", "namespace detail{ int get(){ return 5; } } auto gen(generic a){ return a + detail.get(); }"); +LOAD_MODULE(test_namespace73, "test.namespace73", "namespace detail{ int get(){ return 5; } } auto gen(generic a){ return a + detail::get(); }"); const char *testNamespace73 = "import test.namespace73;\r\n\ return gen(5);"; @@ -916,20 +916,20 @@ TEST_RESULT("namespace test 73 (generic function import parse in correct namespa const char *testNamespace74 = "namespace Test{ typedef int X; X a = 100; }\r\n\ \r\n\ -Test.X b = 20;\r\n\ +Test::X b = 20;\r\n\ \r\n\ namespace Test{ X c = 3; }\r\n\ \r\n\ -return Test.a + b + Test.c;"; +return Test::a + b + Test::c;"; TEST_RESULT("namespace test 74 (alias definition in a namespace)", testNamespace74, "123"); LOAD_MODULE(test_namespace75, "test.namespace75", "namespace Test{ typedef int X; X a = 100; }"); const char *testNamespace75 = "import test.namespace75;\r\n\ \r\n\ -Test.X b = 20;\r\n\ +Test::X b = 20;\r\n\ \r\n\ namespace Test{ X c = 3; }\r\n\ \r\n\ -return Test.a + b + Test.c;"; +return Test::a + b + Test::c;"; TEST_RESULT("namespace test 75 (alias definition in a namespace with import)", testNamespace75, "123"); diff --git a/tests/TestParseFail.cpp b/tests/TestParseFail.cpp index 6a41cad61..bef969fc2 100644 --- a/tests/TestParseFail.cpp +++ b/tests/TestParseFail.cpp @@ -272,7 +272,7 @@ void RunParseFailTests() TEST_FOR_FAIL("parsing", "int y; auto x = coroutine y;", "ERROR: function name not found after return type"); TEST_FOR_FAIL("parsing", "int y; auto x = coroutine int y;", "ERROR: '(' expected after function name"); - TEST_FOR_FAIL("parsing", "namespace Test{} return Test.+(5);", "ERROR: namespace member is expected after '.'"); + TEST_FOR_FAIL("parsing", "namespace Test{} return Test::+(5);", "ERROR: namespace member is expected after '::'"); TEST_FOR_FAIL("parsing", "int x = ( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((1)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) );", "ERROR: reached nested '(' limit of 256"); TEST_FOR_FAIL("parsing", "auto x = { {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} };", "ERROR: reached nested array limit of 256"); TEST_FOR_FAIL("parsing", "{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{int x;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} }", "ERROR: reached nested '{' limit of 256"); diff --git a/tests/TestSpecial.cpp b/tests/TestSpecial.cpp index 3ced402c0..6ef886140 100644 --- a/tests/TestSpecial.cpp +++ b/tests/TestSpecial.cpp @@ -1100,10 +1100,10 @@ long[2] sal = 0x1234567898765432l;\r\n\ float[2] saf = 2.5f;\r\n\ double[2] sad = 1.13;\r\n\ \r\n\ -void write(@T ref value){ memory.write(buffer, offset, *value); offset += sizeof(T); }\r\n\ -void write(@T[] value){ memory.write(buffer, offset, value); offset += sizeof(T) * value.size; }\r\n\ -void read(@T ref value){ memory.read(buffer, offset, value); offset += sizeof(T); }\r\n\ -void read(@T[] value){ memory.read(buffer, offset, value); offset += sizeof(T) * value.size; }\r\n\ +void write(@T ref value){ memory::write(buffer, offset, *value); offset += sizeof(T); }\r\n\ +void write(@T[] value){ memory::write(buffer, offset, value); offset += sizeof(T) * value.size; }\r\n\ +void read(@T ref value){ memory::read(buffer, offset, value); offset += sizeof(T); }\r\n\ +void read(@T[] value){ memory::read(buffer, offset, value); offset += sizeof(T) * value.size; }\r\n\ bool compare(@T[] a, @T[] b){ if(a.size != b.size) return false; for(i in a, j in b) if(i != j) return false; return true; }\r\n\ \r\n\ write(sb);\r\n\ @@ -1188,20 +1188,20 @@ bool[] dab2;\r\n\ \r\n\ offset = 0;\r\n\ \r\n\ -db2 = memory.read_bool(buffer, offset); offset += sizeof(db2);\r\n\ -dc2 = memory.read_char(buffer, offset); offset += sizeof(dc2);\r\n\ -ds2 = memory.read_short(buffer, offset); offset += sizeof(ds2);\r\n\ -di2 = memory.read_int(buffer, offset); offset += sizeof(di2);\r\n\ -dl2 = memory.read_long(buffer, offset); offset += sizeof(dl2);\r\n\ -df2 = memory.read_float(buffer, offset); offset += sizeof(df2);\r\n\ -dd2 = memory.read_double(buffer, offset); offset += sizeof(dd2);\r\n\ -dab2 = memory.read_bool_array(buffer, offset, 2); offset += sizeof(db2) * 2;\r\n\ -dac2 = memory.read_char_array(buffer, offset, 2); offset += sizeof(dc2) * 2;\r\n\ -das2 = memory.read_short_array(buffer, offset, 2); offset += sizeof(ds2) * 2;\r\n\ -dai2 = memory.read_int_array(buffer, offset, 2); offset += sizeof(di2) * 2;\r\n\ -dal2 = memory.read_long_array(buffer, offset, 2); offset += sizeof(dl2) * 2;\r\n\ -daf2 = memory.read_float_array(buffer, offset, 2); offset += sizeof(df2) * 2;\r\n\ -dad2 = memory.read_double_array(buffer, offset, 2); offset += sizeof(dd2) * 2;\r\n\ +db2 = memory::read_bool(buffer, offset); offset += sizeof(db2);\r\n\ +dc2 = memory::read_char(buffer, offset); offset += sizeof(dc2);\r\n\ +ds2 = memory::read_short(buffer, offset); offset += sizeof(ds2);\r\n\ +di2 = memory::read_int(buffer, offset); offset += sizeof(di2);\r\n\ +dl2 = memory::read_long(buffer, offset); offset += sizeof(dl2);\r\n\ +df2 = memory::read_float(buffer, offset); offset += sizeof(df2);\r\n\ +dd2 = memory::read_double(buffer, offset); offset += sizeof(dd2);\r\n\ +dab2 = memory::read_bool_array(buffer, offset, 2); offset += sizeof(db2) * 2;\r\n\ +dac2 = memory::read_char_array(buffer, offset, 2); offset += sizeof(dc2) * 2;\r\n\ +das2 = memory::read_short_array(buffer, offset, 2); offset += sizeof(ds2) * 2;\r\n\ +dai2 = memory::read_int_array(buffer, offset, 2); offset += sizeof(di2) * 2;\r\n\ +dal2 = memory::read_long_array(buffer, offset, 2); offset += sizeof(dl2) * 2;\r\n\ +daf2 = memory::read_float_array(buffer, offset, 2); offset += sizeof(df2) * 2;\r\n\ +dad2 = memory::read_double_array(buffer, offset, 2); offset += sizeof(dd2) * 2;\r\n\ \r\n\ assert(sb == db2);\r\n\ assert(sc == dc2);\r\n\ @@ -1219,13 +1219,13 @@ assert(compare(sal, dal2));\r\n\ assert(compare(saf, daf2));\r\n\ assert(compare(sad, dad2));\r\n\ \r\n\ -assert(memory.as_float(memory.as_int(34.7f)) == 34.7f);\r\n\ -assert(memory.as_double(memory.as_long(34.7)) == 34.7);\r\n\ +assert(memory::as_float(memory::as_int(34.7f)) == 34.7f);\r\n\ +assert(memory::as_double(memory::as_long(34.7)) == 34.7);\r\n\ \r\n\ char[256] buffer2;\r\n\ -memory.copy(buffer2, 128, buffer, 0, 128);\r\n\ +memory::copy(buffer2, 128, buffer, 0, 128);\r\n\ \r\n\ -return memory.compare(buffer2, 128, buffer, 0, 128) == 0;"; +return memory::compare(buffer2, 128, buffer, 0, 128) == 0;"; TEST_RESULT("std.memory test", testMemoryLib, "1"); const char *testNullcInNullc = diff --git a/tests/nullc_in_nullc/analyzer.nc b/tests/nullc_in_nullc/analyzer.nc index 47f20ad81..49d4ad3cc 100644 --- a/tests/nullc_in_nullc/analyzer.nc +++ b/tests/nullc_in_nullc/analyzer.nc @@ -10723,9 +10723,9 @@ void ImportModuleDependencies(ExpressionContext ref ctx, SynBase ref source, Mod StringRef moduleFileName = StringRef(symbols, moduleInfo.nameOffset); - ByteCode ref bytecode = BinaryCache.FindBytecode(string(moduleFileName), false); + ByteCode ref bytecode = BinaryCache::FindBytecode(string(moduleFileName), false); - Lexeme[] lexStream = BinaryCache.FindLexems(string(moduleFileName), false); + Lexeme[] lexStream = BinaryCache::FindLexems(string(moduleFileName), false); if(!bytecode) Stop(ctx, source, "ERROR: module dependency import is not implemented"); @@ -10750,7 +10750,7 @@ void ImportModuleDependencies(ExpressionContext ref ctx, SynBase ref source, Mod moduleData.lexer.Lexify(FindSource(moduleData.bytecode)); lexStream = moduleData.lexer.lexems.data; - BinaryCache.PutLexemes(string(moduleFileName), lexStream); + BinaryCache::PutLexemes(string(moduleFileName), lexStream); } moduleData.lexStream = lexStream; @@ -11248,7 +11248,7 @@ void ImportModuleTypes(ExpressionContext ref ctx, SynBase ref source, ModuleCont } else if(ctx.IsFloatingPointType(constantType)) { - double data = memory.as_double(constantInfo.value); + double data = memory::as_double(constantInfo.value); value = new ExprRationalLiteral(source, constantType, data); } @@ -11720,7 +11720,7 @@ void ImportModule(ExpressionContext ref ctx, SynBase ref source, ByteCode ref by /*assert(!*name.end);*/ - BinaryCache.PutLexemes(string(name), lexStream); + BinaryCache::PutLexemes(string(name), lexStream); } else { @@ -11763,9 +11763,9 @@ void AnalyzeModuleImport(ExpressionContext ref ctx, SynModuleImport ref syntax) //TRACE_SCOPE("analyze", "AnalyzeModuleImport"); //TRACE_LABEL2(moduleName.begin, moduleName.end); - ByteCode ref bytecode = BinaryCache.FindBytecode(string(moduleName), false); + ByteCode ref bytecode = BinaryCache::FindBytecode(string(moduleName), false); - Lexeme[] lexStream = BinaryCache.FindLexems(string(moduleName), false); + Lexeme[] lexStream = BinaryCache::FindLexems(string(moduleName), false); if(!bytecode) Stop(ctx, syntax, "ERROR: module import is not implemented"); @@ -11980,9 +11980,9 @@ ExprModule ref AnalyzeModule(ExpressionContext ref ctx, SynModule ref syntax) //TRACE_SCOPE("analyze", "AnalyzeModule"); // Import base module - if(ByteCode ref bytecode = BinaryCache.GetBytecode(string("$base$.nc"))) + if(ByteCode ref bytecode = BinaryCache::GetBytecode(string("$base$.nc"))) { - Lexeme[] lexStream = BinaryCache.GetLexems(string("$base$.nc")); + Lexeme[] lexStream = BinaryCache::GetLexems(string("$base$.nc")); if(bytecode) ImportModule(ctx, syntax, bytecode, lexStream, InplaceStr("$base$.nc")); diff --git a/tests/nullc_in_nullc/compiler.nc b/tests/nullc_in_nullc/compiler.nc index 19fc03245..9a037c4c9 100644 --- a/tests/nullc_in_nullc/compiler.nc +++ b/tests/nullc_in_nullc/compiler.nc @@ -1242,7 +1242,7 @@ ByteCode ref GetBytecode(CompilerContext ref ctx) } else if(ExprRationalLiteral ref node = getType with(curr.value)) { - constant.value = memory.as_long(node.value); + constant.value = memory::as_long(node.value); } debugSymbols.push_back(curr.name.name.data, curr.name.name.begin, curr.name.name.length()); @@ -2008,7 +2008,7 @@ ByteCode ref BuildModuleFromSource(string modulePath, string moduleRoot, string c.pos = newStart + (c.pos - code); }*/ - BinaryCache.PutBytecode(modulePath, bytecode, lexer.lexems.data); + BinaryCache::PutBytecode(modulePath, bytecode, lexer.lexems.data); return bytecode; } @@ -2018,7 +2018,7 @@ char[] FindFileContentInImportPaths(string moduleName, string moduleRoot, bool a char[] fileContent = nullptr; int modulePathPos = 0; - string ref modulePath = BinaryCache.EnumImportPath(modulePathPos++); + string ref modulePath = BinaryCache::EnumImportPath(modulePathPos++); while(modulePath) { string path = modulePath + moduleRoot + (moduleRoot.empty() ? "" : "/") + moduleName; @@ -2039,7 +2039,7 @@ char[] FindFileContentInImportPaths(string moduleName, string moduleRoot, bool a if(fileContent) break; - modulePath = BinaryCache.EnumImportPath(modulePathPos++); + modulePath = BinaryCache::EnumImportPath(modulePathPos++); } return fileContent; @@ -2119,7 +2119,7 @@ ByteCode ref BuildModuleFromPath(string moduleName, string moduleRoot, bool addE /* bool AddModuleFunction(const char* module, void (*ptrRaw)(), void *funcWrap, void (*ptrWrap)(void *func, char* retBuf, char* argBuf), const char* name, int index, const char **errorPos, char *errorBuf, int errorBufSize, int optimizationLevel) { - const char *bytecode = BinaryCache.FindBytecode(module, true); + const char *bytecode = BinaryCache::FindBytecode(module, true); // Create module if not found if(!bytecode) diff --git a/tests/nullc_in_nullc/expressioneval.nc b/tests/nullc_in_nullc/expressioneval.nc index 580f378f6..bb601245f 100644 --- a/tests/nullc_in_nullc/expressioneval.nc +++ b/tests/nullc_in_nullc/expressioneval.nc @@ -9,19 +9,19 @@ void memcpy(char[] dst, int offset, @T ref value, int size) assert(sizeof(T) == size); if(T == bool) - memory.write(dst, offset, *value); + memory::write(dst, offset, *value); else if(T == char) - memory.write(dst, offset, *value); + memory::write(dst, offset, *value); else if(T == short) - memory.write(dst, offset, *value); + memory::write(dst, offset, *value); else if(T == int) - memory.write(dst, offset, *value); + memory::write(dst, offset, *value); else if(T == long) - memory.write(dst, offset, *value); + memory::write(dst, offset, *value); else if(T == float) - memory.write(dst, offset, *value); + memory::write(dst, offset, *value); else if(T == double) - memory.write(dst, offset, *value); + memory::write(dst, offset, *value); else assert(false, "unknown type"); } @@ -36,19 +36,19 @@ void memcpy(@T ref value, char[] src, int offset, int size) assert(sizeof(T) == size); if(T == bool) - *value = memory.read_char(src, offset) != 0; + *value = memory::read_char(src, offset) != 0; else if(T == char) - *value = memory.read_char(src, offset); + *value = memory::read_char(src, offset); else if(T == short) - *value = memory.read_short(src, offset); + *value = memory::read_short(src, offset); else if(T == int) - *value = memory.read_int(src, offset); + *value = memory::read_int(src, offset); else if(T == long) - *value = memory.read_long(src, offset); + *value = memory::read_long(src, offset); else if(T == float) - *value = memory.read_float(src, offset); + *value = memory::read_float(src, offset); else if(T == double) - *value = memory.read_double(src, offset); + *value = memory::read_double(src, offset); else assert(false, "unknown type"); } @@ -60,14 +60,14 @@ void memcpy(@T ref value, char[] src, int size) void memcpy(char[] dst, char[] src, int size) { - memory.copy(dst, 0, src, 0, size); + memory::copy(dst, 0, src, 0, size); } void memset(char[] dst, int offset, int value, int size) { assert(value == 0); - memory.set(dst, offset, value, size); + memory::set(dst, offset, value, size); } void memset(char[] dst, int value, int size) @@ -77,7 +77,7 @@ void memset(char[] dst, int value, int size) int memcmp(char[] a, char[] b, int size) { - return memory.compare(a, 0, b, 0, size); + return memory::compare(a, 0, b, 0, size); } class StackVariable @@ -441,7 +441,7 @@ bool CreateStore(ExpressionEvalContext ref ctx, ExprBase ref target, ExprBase re if(ExprMemoryLiteral ref expr = getType with(value)) { - memory.copy(ptr.ptr.buffer, ptr.start, expr.ptr.ptr.buffer, expr.ptr.start, int(value.type.size)); + memory::copy(ptr.ptr.buffer, ptr.start, expr.ptr.ptr.buffer, expr.ptr.start, int(value.type.size)); return true; } @@ -620,7 +620,7 @@ ExprBase ref CreateLoad(ExpressionEvalContext ref ctx, ExprBase ref target) if(!storage) return nullptr; - memory.copy(storage.ptr.buffer, storage.start, ptr.ptr.buffer, ptr.start, int(type.size)); + memory::copy(storage.ptr.buffer, storage.start, ptr.ptr.buffer, ptr.start, int(type.size)); return new ExprMemoryLiteral(target.source, type, storage); } diff --git a/tests/nullc_in_nullc/expressiongraph.nc b/tests/nullc_in_nullc/expressiongraph.nc index 77ada8ef9..ca7addc32 100644 --- a/tests/nullc_in_nullc/expressiongraph.nc +++ b/tests/nullc_in_nullc/expressiongraph.nc @@ -138,7 +138,7 @@ void Print(ExpressionGraphContext ref ctx, char[] format, auto ref[] args) tmp[tmp.size - 1] = 0; } - memory.copy(tmp, tmp.size - intStr.size, intStr, 0, intStr.size - 1); + memory::copy(tmp, tmp.size - intStr.size, intStr, 0, intStr.size - 1); intStr = tmp; } diff --git a/tests/nullc_in_nullc/parser.nc b/tests/nullc_in_nullc/parser.nc index 40854531e..2018e558e 100644 --- a/tests/nullc_in_nullc/parser.nc +++ b/tests/nullc_in_nullc/parser.nc @@ -405,11 +405,11 @@ SynBase ref ParseTerminalType(ParseContext ref ctx, bool ref shrBorrow) SynNamespaceElement ref ns = nullptr; - while(ctx.At(LexemeType.lex_point) && (ns = ctx.IsNamespace(ns, name)) != nullptr) + while(ctx.At(LexemeType.lex_dblcolon) && (ns = ctx.IsNamespace(ns, name)) != nullptr) { ctx.Skip(); - if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: namespace member is expected after '.'")) + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: namespace member is expected after '::'")) { namespacePath.push_back(new SynIdentifier(start, ctx.Previous(), name)); @@ -1589,9 +1589,9 @@ SynNamespaceDefinition ref ParseNamespaceDefinition(ParseContext ref ctx) path.push_back(new SynIdentifier(ctx.Previous(), ctx.Previous(), value)); } - while(ctx.Consume(LexemeType.lex_point)) + while(ctx.Consume(LexemeType.lex_dblcolon)) { - if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: namespace name required after '.'")) + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: namespace name required after '::'")) break; InplaceStr value = ctx.Consume(); @@ -2656,7 +2656,7 @@ SynFunctionDefinition ref ParseFunctionDefinition(ParseContext ref ctx) } else if(parentType) { - Stop(ctx, ctx.Current(), "ERROR: function name expected after ':' or '.'"); + Stop(ctx, ctx.Current(), "ERROR: function name expected after '::' or '.'"); } else if(isCoroutine && !allowEmptyName) { diff --git a/tests/nullc_in_nullc/stringutil.nc b/tests/nullc_in_nullc/stringutil.nc index 1c410ee18..04b425837 100644 --- a/tests/nullc_in_nullc/stringutil.nc +++ b/tests/nullc_in_nullc/stringutil.nc @@ -250,6 +250,6 @@ StringRef InplaceStr.end_ref() char[] FMT_ISTR(InplaceStr str) { auto result = new char[str.length() + 1]; - memory.copy(result, 0, str.data, str.begin, str.length()); + memory::copy(result, 0, str.data, str.begin, str.length()); return result; } diff --git a/tests/nullc_in_nullc/typetreehelpers.nc b/tests/nullc_in_nullc/typetreehelpers.nc index 3747d9b76..f38c475b5 100644 --- a/tests/nullc_in_nullc/typetreehelpers.nc +++ b/tests/nullc_in_nullc/typetreehelpers.nc @@ -4,18 +4,18 @@ import typetree; void memcpy(StringRef dst, InplaceStr src) { - memory.copy(dst.string, dst.pos, src.data, src.begin, src.end - src.begin); + memory::copy(dst.string, dst.pos, src.data, src.begin, src.end - src.begin); } void memcpy(StringRef dst, char[] src, int length) { - memory.copy(dst.string, dst.pos, src, 0, length); + memory::copy(dst.string, dst.pos, src, 0, length); } void strcpy(StringRef dst, char[] src) { if(src.size > 0) - memory.copy(dst.string, dst.pos, src, 0, src.size - 1); + memory::copy(dst.string, dst.pos, src, 0, src.size - 1); } StringRef strstr(StringRef haystack, char[] needle) @@ -258,7 +258,7 @@ void sprintf(char[] buffer, char[] format, auto ref[] args) if(str.size > 0) { - memory.copy(buffer, pos, str, 0, str.size - 1); + memory::copy(buffer, pos, str, 0, str.size - 1); pos += str.size - 1; } } @@ -318,12 +318,12 @@ void sprintf(char[] buffer, char[] format, auto ref[] args) tmp[tmp.size - 1] = 0; } - memory.copy(tmp, tmp.size - str.size, str, 0, str.size - 1); + memory::copy(tmp, tmp.size - str.size, str, 0, str.size - 1); str = tmp; } - memory.copy(buffer, pos, str, 0, str.size - 1); + memory::copy(buffer, pos, str, 0, str.size - 1); pos += str.size - 1; } } @@ -335,7 +335,7 @@ void sprintf(char[] buffer, char[] format, auto ref[] args) if(str.size > 0) { - memory.copy(buffer, pos, str, 0, str.size - 1); + memory::copy(buffer, pos, str, 0, str.size - 1); pos += str.size - 1; } } From ca9d6a9fe30395fb081bc3088ea06b92b802d85c Mon Sep 17 00:00:00 2001 From: mingodad Date: Sat, 1 Oct 2022 15:11:30 +0200 Subject: [PATCH 17/20] Allow optional semicolon after class/enum definition --- NULLC/ParseTree.cpp | 2 ++ tests/nullc_in_nullc/parser.nc | 2 ++ 2 files changed, 4 insertions(+) diff --git a/NULLC/ParseTree.cpp b/NULLC/ParseTree.cpp index 527fafca3..cb1b12fd2 100644 --- a/NULLC/ParseTree.cpp +++ b/NULLC/ParseTree.cpp @@ -1625,6 +1625,7 @@ SynBase* ParseClassDefinition(ParseContext &ctx) SynClassElements *elements = ParseClassElements(ctx); CheckConsume(ctx, lex_cfigure, "ERROR: '}' not found after %s definition", classOrStruct); + ctx.Consume(lex_semicolon); //Optional return new (ctx.get()) SynClassDefinition(start, ctx.Previous(), align, nameIdentifier, aliases, extendable, isStruct, baseClass, elements); } @@ -1694,6 +1695,7 @@ SynEnumDefinition* ParseEnumDefinition(ParseContext &ctx) while(ctx.Consume(lex_comma)); CheckConsume(ctx, lex_cfigure, "ERROR: '}' not found after enum definition"); + ctx.Consume(lex_semicolon); //Optional return new (ctx.get()) SynEnumDefinition(start, ctx.Previous(), nameIdentifier, values); } diff --git a/tests/nullc_in_nullc/parser.nc b/tests/nullc_in_nullc/parser.nc index 2018e558e..1bef4d584 100644 --- a/tests/nullc_in_nullc/parser.nc +++ b/tests/nullc_in_nullc/parser.nc @@ -1499,6 +1499,7 @@ SynBase ref ParseClassDefinition(ParseContext ref ctx) SynClassElements ref elements = ParseClassElements(ctx); CheckConsume(ctx, LexemeType.lex_cfigure, "ERROR: '}' not found after class definition"); + ctx.Consume(LexemeType.lex_semicolon); //Optional return new SynClassDefinition(start, ctx.Previous(), alignment, nameIdentifier, aliases, isExtendable, isStruct, baseClass, elements); } @@ -1568,6 +1569,7 @@ SynEnumDefinition ref ParseEnumDefinition(ParseContext ref ctx) while(ctx.Consume(LexemeType.lex_comma)); CheckConsume(ctx, LexemeType.lex_cfigure, "ERROR: '}' not found after enum definition"); + ctx.Consume(LexemeType.lex_semicolon); //Optional return new SynEnumDefinition(start, ctx.Previous(), nameIdentifier, values); } From 5bf4e9ab8e941d110f6bc69ea5524a8e1d827722 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sat, 1 Oct 2022 18:53:02 +0200 Subject: [PATCH 18/20] Added a few more C++ keywords "template, static, public, private, protected" and parse some of then and ignore for the moment --- NULLC/Lexer.cpp | 196 +++++++++++++++++---------------- NULLC/Lexer.h | 3 +- NULLC/ParseTree.cpp | 45 ++++++++ NULLC/ParseTree.h | 12 ++ tests/nullc_in_nullc/lexer.nc | 9 ++ tests/nullc_in_nullc/parser.nc | 9 ++ 6 files changed, 180 insertions(+), 94 deletions(-) diff --git a/NULLC/Lexer.cpp b/NULLC/Lexer.cpp index dd99669cd..0d953a840 100644 --- a/NULLC/Lexer.cpp +++ b/NULLC/Lexer.cpp @@ -19,7 +19,7 @@ void Lexer::Lexify(const char* code) const char *lineStart = code; line = 0; - LexemeType lType = lex_none; + LexemeType lType = LexemeType::lex_none; int lLength = 1; while(*code) @@ -50,7 +50,7 @@ void Lexer::Lexify(const char* code) code++; continue; case '\"': - lType = lex_quotedstring; + lType = LexemeType::lex_quotedstring; { const char *pos = code; pos++; @@ -91,7 +91,7 @@ void Lexer::Lexify(const char* code) } break; case '\'': - lType = lex_semiquotedchar; + lType = LexemeType::lex_semiquotedchar; { const char *pos = code; pos++; @@ -133,45 +133,45 @@ void Lexer::Lexify(const char* code) break; case '.': if(isDigit(code[1])) goto do_lex_number; - else lType = lex_point; + else lType = LexemeType::lex_point; break; case ',': - lType = lex_comma; + lType = LexemeType::lex_comma; break; case '+': - lType = lex_add; + lType = LexemeType::lex_add; if(code[1] == '=') { - lType = lex_addset; + lType = LexemeType::lex_addset; lLength = 2; }else if(code[1] == '+'){ - lType = lex_inc; + lType = LexemeType::lex_inc; lLength = 2; } break; case '-': - lType = lex_sub; + lType = LexemeType::lex_sub; if(code[1] == '=') { - lType = lex_subset; + lType = LexemeType::lex_subset; lLength = 2; }else if(code[1] == '-'){ - lType = lex_dec; + lType = LexemeType::lex_dec; lLength = 2; } break; case '*': - lType = lex_mul; + lType = LexemeType::lex_mul; if(code[1] == '=') { - lType = lex_mulset; + lType = LexemeType::lex_mulset; lLength = 2; }else if(code[1] == '*'){ - lType = lex_pow; + lType = LexemeType::lex_pow; lLength = 2; if(code[2] == '=') { - lType = lex_powset; + lType = LexemeType::lex_powset; lLength = 3; } } @@ -179,7 +179,7 @@ void Lexer::Lexify(const char* code) case '/': if(code[1] == '=') { - lType = lex_divset; + lType = LexemeType::lex_divset; lLength = 2; }else if(code[1] == '/'){ while(code[0] != '\n' && code[0] != '\0') @@ -260,141 +260,141 @@ void Lexer::Lexify(const char* code) } continue; }else{ - lType = lex_div; + lType = LexemeType::lex_div; } break; case '%': - lType = lex_mod; + lType = LexemeType::lex_mod; if(code[1] == '=') { - lType = lex_modset; + lType = LexemeType::lex_modset; lLength = 2; } break; case '<': - lType = lex_less; + lType = LexemeType::lex_less; if(code[1] == '=') { - lType = lex_lequal; + lType = LexemeType::lex_lequal; lLength = 2; }else if(code[1] == '<'){ - lType = lex_shl; + lType = LexemeType::lex_shl; lLength = 2; if(code[2] == '=') { - lType = lex_shlset; + lType = LexemeType::lex_shlset; lLength = 3; } } break; case '>': - lType = lex_greater; + lType = LexemeType::lex_greater; if(code[1] == '=') { - lType = lex_gequal; + lType = LexemeType::lex_gequal; lLength = 2; }else if(code[1] == '>'){ - lType = lex_shr; + lType = LexemeType::lex_shr; lLength = 2; if(code[2] == '=') { - lType = lex_shrset; + lType = LexemeType::lex_shrset; lLength = 3; } } break; case '=': - lType = lex_set; + lType = LexemeType::lex_set; if(code[1] == '=') { - lType = lex_equal; + lType = LexemeType::lex_equal; lLength = 2; } break; case '!': - lType = lex_lognot; + lType = LexemeType::lex_lognot; if(code[1] == '=') { - lType = lex_nequal; + lType = LexemeType::lex_nequal; lLength = 2; } break; case '@': - lType = lex_at; + lType = LexemeType::lex_at; break; case '~': - lType = lex_bitnot; + lType = LexemeType::lex_bitnot; break; case '&': - lType = lex_bitand; + lType = LexemeType::lex_bitand; if(code[1] == '&') { - lType = lex_logand; + lType = LexemeType::lex_logand; lLength = 2; }else if(code[1] == '='){ - lType = lex_andset; + lType = LexemeType::lex_andset; lLength = 2; } break; case '|': - lType = lex_bitor; + lType = LexemeType::lex_bitor; if(code[1] == '|') { - lType = lex_logor; + lType = LexemeType::lex_logor; lLength = 2; }else if(code[1] == '='){ - lType = lex_orset; + lType = LexemeType::lex_orset; lLength = 2; } break; case '^': - lType = lex_bitxor; + lType = LexemeType::lex_bitxor; if(code[1] == '^') { - lType = lex_logxor; + lType = LexemeType::lex_logxor; lLength = 2; }else if(code[1] == '='){ - lType = lex_xorset; + lType = LexemeType::lex_xorset; lLength = 2; } break; case '(': - lType = lex_oparen; + lType = LexemeType::lex_oparen; break; case ')': - lType = lex_cparen; + lType = LexemeType::lex_cparen; break; case '[': - lType = lex_obracket; + lType = LexemeType::lex_obracket; break; case ']': - lType = lex_cbracket; + lType = LexemeType::lex_cbracket; break; case '{': - lType = lex_ofigure; + lType = LexemeType::lex_ofigure; break; case '}': - lType = lex_cfigure; + lType = LexemeType::lex_cfigure; break; case '?': - lType = lex_questionmark; + lType = LexemeType::lex_questionmark; break; case ':': if(code[1] == ':') { - lType = lex_dblcolon; + lType = LexemeType::lex_dblcolon; lLength = 2; } - else lType = lex_colon; + else lType = LexemeType::lex_colon; break; case ';': - lType = lex_semicolon; + lType = LexemeType::lex_semicolon; break; default: if(isDigit(*code)) { do_lex_number: - lType = lex_number; + lType = LexemeType::lex_number; const char *pos = code; if(pos[0] == '0' && pos[1] == 'x') @@ -431,99 +431,109 @@ void Lexer::Lexify(const char* code) { case 2: if(memcmp(code, "if", 2) == 0) - lType = lex_if; + lType = LexemeType::lex_if; else if(memcmp(code, "in", 2) == 0) - lType = lex_in; + lType = LexemeType::lex_in; else if(memcmp(code, "do", 2) == 0) - lType = lex_do; + lType = LexemeType::lex_do; break; case 3: if(memcmp(code, "for", 3) == 0) - lType = lex_for; + lType = LexemeType::lex_for; else if(memcmp(code, "ref", 3) == 0) - lType = lex_ref; + lType = LexemeType::lex_ref; else if(memcmp(code, "new", 3) == 0) - lType = lex_new; + lType = LexemeType::lex_new; break; case 4: if(memcmp(code, "case", 4) == 0) - lType = lex_case; + lType = LexemeType::lex_case; else if(memcmp(code, "else", 4) == 0) - lType = lex_else; + lType = LexemeType::lex_else; else if(memcmp(code, "auto", 4) == 0) - lType = lex_auto; + lType = LexemeType::lex_auto; else if(memcmp(code, "true", 4) == 0) - lType = lex_true; + lType = LexemeType::lex_true; else if(memcmp(code, "enum", 4) == 0) - lType = lex_enum; + lType = LexemeType::lex_enum; else if(memcmp(code, "with", 4) == 0) - lType = lex_with; + lType = LexemeType::lex_with; else if(memcmp(code, "goto", 4) == 0) - lType = lex_goto; + lType = LexemeType::lex_goto; break; case 5: if(memcmp(code, "while", 5) == 0) - lType = lex_while; + lType = LexemeType::lex_while; else if(memcmp(code, "break", 5) == 0) - lType = lex_break; + lType = LexemeType::lex_break; else if(memcmp(code, "class", 5) == 0) - lType = lex_class; + lType = LexemeType::lex_class; else if(memcmp(code, "align", 5) == 0) - lType = lex_align; + lType = LexemeType::lex_align; else if(memcmp(code, "yield", 5) == 0) - lType = lex_yield; + lType = LexemeType::lex_yield; else if(memcmp(code, "const", 5) == 0) - lType = lex_const; + lType = LexemeType::lex_const; else if(memcmp(code, "false", 5) == 0) - lType = lex_false; + lType = LexemeType::lex_false; break; case 6: if(memcmp(code, "switch", 6) == 0) - lType = lex_switch; + lType = LexemeType::lex_switch; else if(memcmp(code, "return", 6) == 0) - lType = lex_return; + lType = LexemeType::lex_return; else if(memcmp(code, "typeof", 6) == 0) - lType = lex_typeof; + lType = LexemeType::lex_typeof; else if(memcmp(code, "sizeof", 6) == 0) - lType = lex_sizeof; + lType = LexemeType::lex_sizeof; else if(memcmp(code, "import", 6) == 0) - lType = lex_import; + lType = LexemeType::lex_import; else if(memcmp(code, "struct", 6) == 0) - lType = lex_struct; + lType = LexemeType::lex_struct; + else if(memcmp(code, "static", 6) == 0) + lType = LexemeType::lex_static; + else if(memcmp(code, "public", 6) == 0) + lType = LexemeType::lex_public; break; case 7: if(memcmp(code, "noalign", 7) == 0) - lType = lex_noalign; + lType = LexemeType::lex_noalign; else if(memcmp(code, "default", 7) == 0) - lType = lex_default; + lType = LexemeType::lex_default; else if(memcmp(code, "typedef", 7) == 0) - lType = lex_typedef; + lType = LexemeType::lex_typedef; else if(memcmp(code, "nullptr", 7) == 0) - lType = lex_nullptr; + lType = LexemeType::lex_nullptr; else if(memcmp(code, "generic", 7) == 0) - lType = lex_generic; + lType = LexemeType::lex_generic; + else if(memcmp(code, "private", 7) == 0) + lType = LexemeType::lex_private; break; case 8: if(memcmp(code, "continue", 8) == 0) - lType = lex_continue; + lType = LexemeType::lex_continue; else if(memcmp(code, "operator", 8) == 0) - lType = lex_operator; + lType = LexemeType::lex_operator; + else if(memcmp(code, "template", 8) == 0) + lType = LexemeType::lex_template; break; case 9: if(memcmp(code, "coroutine", 9) == 0) - lType = lex_coroutine; + lType = LexemeType::lex_coroutine; else if(memcmp(code, "namespace", 9) == 0) - lType = lex_namespace; + lType = LexemeType::lex_namespace; + else if(memcmp(code, "protected", 9) == 0) + lType = LexemeType::lex_protected; break; case 10: if(memcmp(code, "extendable", 10) == 0) - lType = lex_extendable; + lType = LexemeType::lex_extendable; break; } } - if(lType == lex_none) - lType = lex_identifier; + if(lType == LexemeType::lex_none) + lType = LexemeType::lex_identifier; } } Lexeme lex; @@ -539,13 +549,13 @@ void Lexer::Lexify(const char* code) lexems.push_back(lex); code += lLength; - lType = lex_none; + lType = LexemeType::lex_none; lLength = 1; } Lexeme lex; - lex.type = lex_none; + lex.type = LexemeType::lex_none; lex.length = 1; lex.pos = code; diff --git a/NULLC/Lexer.h b/NULLC/Lexer.h index 5bfb71324..0674eafb1 100644 --- a/NULLC/Lexer.h +++ b/NULLC/Lexer.h @@ -48,7 +48,8 @@ enum LexemeType lex_questionmark, lex_colon, lex_dblcolon, lex_semicolon, // ? : :: ; lex_if, lex_else, lex_for, lex_while, lex_do, lex_switch, lex_case, lex_default, // if else for while switch case default lex_break, lex_continue, lex_goto, lex_return, // break continue goto return - lex_ref, lex_auto, lex_class, lex_struct, lex_noalign, lex_align, // ref auto class struct noalign align + lex_ref, lex_auto, lex_class, lex_struct, lex_template, lex_noalign, lex_align, // ref auto class struct template noalign align + lex_private, lex_public, lex_protected, lex_static, // private public protected static lex_typeof, lex_sizeof, lex_new, lex_operator, lex_typedef, lex_import, lex_nullptr, // typeof sizeof new operator typedef import in nullptr lex_coroutine, lex_yield, // coroutine yield lex_at, // @ diff --git a/NULLC/ParseTree.cpp b/NULLC/ParseTree.cpp index cb1b12fd2..f72f7ca5c 100644 --- a/NULLC/ParseTree.cpp +++ b/NULLC/ParseTree.cpp @@ -923,6 +923,42 @@ SynAlign* ParseAlign(ParseContext &ctx) return NULL; } +SynTemplate* ParseTemplate(ParseContext &ctx) +{ + Lexeme *start = ctx.currentLexeme; + + if(ctx.Consume(lex_template)) + { + if(ctx.Consume(lex_less)) + { + IntrusiveList aliases; + + if(CheckAt(ctx, lex_identifier, "ERROR: template type alias required after '<'")) + { + InplaceStr alias = ctx.Consume(); + + aliases.push_back(new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), alias)); + + while(ctx.Consume(lex_comma)) + { + if(!CheckAt(ctx, lex_identifier, "ERROR: template type alias required after ','")) + break; + + alias = ctx.Consume(); + + aliases.push_back(new (ctx.get()) SynIdentifier(ctx.Previous(), ctx.Previous(), alias)); + } + } + + CheckConsume(ctx, lex_greater, "ERROR: '>' expected after template type alias list"); + + return new (ctx.get()) SynTemplate(start, ctx.Previous(), aliases); + } + } + + return NULL; +} + SynNew* ParseNew(ParseContext &ctx) { Lexeme *start = ctx.currentLexeme; @@ -1539,6 +1575,15 @@ SynClassElements* ParseClassElements(ParseContext &ctx) } else { + switch(ctx.Peek()) { + case lex_public: + case lex_private: + case lex_protected: + // for now only consume then and do nothing + ctx.Skip(); + CheckConsume(ctx, lex_colon, "ERROR: ':' public/private"); + continue; + } break; } } diff --git a/NULLC/ParseTree.h b/NULLC/ParseTree.h index c1647d220..0f4b571c9 100644 --- a/NULLC/ParseTree.h +++ b/NULLC/ParseTree.h @@ -255,6 +255,7 @@ namespace SynNode SynArray, SynGenerator, SynAlign, + SynTemplate, SynTypedef, SynMemberAccess, SynCallArgument, @@ -542,6 +543,17 @@ struct SynGenerator: SynBase static const unsigned myTypeID = SynNode::SynGenerator; }; +struct SynTemplate: SynBase +{ + SynTemplate(Lexeme *begin, Lexeme *end, IntrusiveList aliases): SynBase(myTypeID, begin, end), aliases(aliases) + { + } + + IntrusiveList aliases; + + static const unsigned myTypeID = SynNode::SynTemplate; +}; + struct SynAlign: SynBase { SynAlign(Lexeme *begin, Lexeme *end, SynBase* value): SynBase(myTypeID, begin, end), value(value) diff --git a/tests/nullc_in_nullc/lexer.nc b/tests/nullc_in_nullc/lexer.nc index 65b0fffad..b016ee3f2 100644 --- a/tests/nullc_in_nullc/lexer.nc +++ b/tests/nullc_in_nullc/lexer.nc @@ -52,6 +52,7 @@ enum LexemeType lex_if, lex_else, lex_for, lex_while, lex_do, lex_switch, lex_case, lex_default, // if else for while switch case default lex_break, lex_continue, lex_return, // break continue return lex_ref, lex_auto, lex_class, lex_noalign, lex_align, // ref auto class noalign align + lex_private, lex_public, lex_protected, lex_static, // private public protected static lex_typeof, lex_sizeof, lex_new, lex_operator, lex_typedef, lex_import, lex_nullptr, // typeof sizeof new operator typedef import in nullptr lex_coroutine, lex_yield, // coroutine yield lex_at, // @ @@ -519,6 +520,10 @@ void Lexer::Lexify(char[] code) lType = LexemeType.lex_import; else if(memcmp(code, curr, "struct", 6) == 0) lType = LexemeType.lex_struct; + else if(memcmp(code, curr, "static", 6) == 0) + lType = LexemeType.lex_static; + else if(memcmp(code, curr, "public", 6) == 0) + lType = LexemeType.lex_public; break; case 7: if(memcmp(code, curr, "noalign", 7) == 0) @@ -531,6 +536,8 @@ void Lexer::Lexify(char[] code) lType = LexemeType.lex_nullptr; else if(memcmp(code, curr, "generic", 7) == 0) lType = LexemeType.lex_generic; + else if(memcmp(code, curr, "private", 7) == 0) + lType = LexemeType.lex_private; break; case 8: if(memcmp(code, curr, "continue", 8) == 0) @@ -543,6 +550,8 @@ void Lexer::Lexify(char[] code) lType = LexemeType.lex_coroutine; else if(memcmp(code, curr, "namespace", 9) == 0) lType = LexemeType.lex_namespace; + else if(memcmp(code, curr, "protected", 9) == 0) + lType = LexemeType.lex_protected; break; case 10: if(memcmp(code, curr, "extendable", 10) == 0) diff --git a/tests/nullc_in_nullc/parser.nc b/tests/nullc_in_nullc/parser.nc index 1bef4d584..4dce663ac 100644 --- a/tests/nullc_in_nullc/parser.nc +++ b/tests/nullc_in_nullc/parser.nc @@ -1414,6 +1414,15 @@ SynClassElements ref ParseClassElements(ParseContext ref ctx) } else { + switch(ctx.Peek()) { + case LexemeType.lex_public: + case LexemeType.lex_private: + case LexemeType.lex_protected: + // for now only consume then and do nothing + ctx.Skip(); + CheckConsume(ctx, LexemeType.lex_colon, "ERROR: ':' public/private/protected"); + continue; + } break; } } From 26ebfeb6f6cc2ce87c228ceb1ec1386c11e339ed Mon Sep 17 00:00:00 2001 From: mingodad Date: Sat, 1 Oct 2022 19:29:06 +0200 Subject: [PATCH 19/20] Add the "inline" keyword and parse and ignore it for now --- NULLC/Lexer.cpp | 2 ++ NULLC/Lexer.h | 2 +- NULLC/ParseTree.cpp | 4 ++++ tests/nullc_in_nullc/lexer.nc | 4 +++- tests/nullc_in_nullc/parser.nc | 3 +++ 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/NULLC/Lexer.cpp b/NULLC/Lexer.cpp index 0d953a840..c0d815e21 100644 --- a/NULLC/Lexer.cpp +++ b/NULLC/Lexer.cpp @@ -494,6 +494,8 @@ void Lexer::Lexify(const char* code) lType = LexemeType::lex_static; else if(memcmp(code, "public", 6) == 0) lType = LexemeType::lex_public; + else if(memcmp(code, "inline", 6) == 0) + lType = LexemeType::lex_inline; break; case 7: if(memcmp(code, "noalign", 7) == 0) diff --git a/NULLC/Lexer.h b/NULLC/Lexer.h index 0674eafb1..6bd89a32e 100644 --- a/NULLC/Lexer.h +++ b/NULLC/Lexer.h @@ -52,7 +52,7 @@ enum LexemeType lex_private, lex_public, lex_protected, lex_static, // private public protected static lex_typeof, lex_sizeof, lex_new, lex_operator, lex_typedef, lex_import, lex_nullptr, // typeof sizeof new operator typedef import in nullptr lex_coroutine, lex_yield, // coroutine yield - lex_at, // @ + lex_at, lex_inline, // @ inline lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with // generic const true false enum namespace extendable with }; diff --git a/NULLC/ParseTree.cpp b/NULLC/ParseTree.cpp index f72f7ca5c..eaba98a34 100644 --- a/NULLC/ParseTree.cpp +++ b/NULLC/ParseTree.cpp @@ -2398,6 +2398,7 @@ SynVariableDefinitions* ParseVariableDefinitions(ParseContext &ctx, bool classMe Lexeme *start = ctx.currentLexeme; SynAlign *align = ParseAlign(ctx); + bool isStatic = ctx.Consume(lex_static); if(SynBase *type = ParseType(ctx)) { @@ -2768,6 +2769,8 @@ SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) if(ctx.nonFunctionDefinitionLocations.find(unsigned(start - ctx.firstLexeme) + 1)) return NULL; + bool isStatic = ctx.Consume(lex_static); + bool isInline = ctx.Consume(lex_inline); bool coroutine = ctx.Consume(lex_coroutine); if(SynBase *returnType = ParseType(ctx)) @@ -2906,6 +2909,7 @@ SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) { Stop(ctx, ctx.Current(), "ERROR: function return type not found after 'coroutine'"); } + else if(isStatic) ctx.currentLexeme = start; //backtrack return NULL; } diff --git a/tests/nullc_in_nullc/lexer.nc b/tests/nullc_in_nullc/lexer.nc index b016ee3f2..07dab6310 100644 --- a/tests/nullc_in_nullc/lexer.nc +++ b/tests/nullc_in_nullc/lexer.nc @@ -55,7 +55,7 @@ enum LexemeType lex_private, lex_public, lex_protected, lex_static, // private public protected static lex_typeof, lex_sizeof, lex_new, lex_operator, lex_typedef, lex_import, lex_nullptr, // typeof sizeof new operator typedef import in nullptr lex_coroutine, lex_yield, // coroutine yield - lex_at, // @ + lex_at, lex_inline, // @ inline lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with, // generic const true false enum namespace extendable with // it seems that there is a place where the position of the above tokes is significant // do not change, add, remove anything above this line unless you find it ! @@ -524,6 +524,8 @@ void Lexer::Lexify(char[] code) lType = LexemeType.lex_static; else if(memcmp(code, curr, "public", 6) == 0) lType = LexemeType.lex_public; + else if(memcmp(code, curr, "inline", 6) == 0) + lType = LexemeType.lex_inline; break; case 7: if(memcmp(code, curr, "noalign", 7) == 0) diff --git a/tests/nullc_in_nullc/parser.nc b/tests/nullc_in_nullc/parser.nc index 4dce663ac..b11974a0d 100644 --- a/tests/nullc_in_nullc/parser.nc +++ b/tests/nullc_in_nullc/parser.nc @@ -2227,6 +2227,7 @@ SynVariableDefinition ref ParseVariableDefinition(ParseContext ref ctx) SynVariableDefinitions ref ParseVariableDefinitions(ParseContext ref ctx, bool classMembers) { LexemeRef start = ctx.currentLexeme; + bool isStatic = ctx.Consume(LexemeType.lex_static); SynAlign ref alignment = ParseAlign(ctx); @@ -2599,6 +2600,8 @@ SynFunctionDefinition ref ParseFunctionDefinition(ParseContext ref ctx) if(ctx.nonFunctionDefinitionLocations.find(int(start - ctx.firstLexeme) + 1)) return nullptr; + bool isStatic = ctx.Consume(LexemeType.lex_static); + bool isInline = ctx.Consume(LexemeType.lex_inline); bool isCoroutine = ctx.Consume(LexemeType.lex_coroutine); if(SynBase ref returnType = ParseType(ctx)) From a2db7962723040bdca581aabf9a92f1da652eacc Mon Sep 17 00:00:00 2001 From: mingodad Date: Sun, 2 Oct 2022 14:53:29 +0200 Subject: [PATCH 20/20] It's accepting simple template syntax for class/struct but for functions more work need to be done --- NULLC/ParseTree.cpp | 52 ++++++++++++++++++--------- NULLC/ParseTree.h | 4 +-- tests/nullc_in_nullc/lexer.nc | 11 +++--- tests/nullc_in_nullc/parser.nc | 64 +++++++++++++++++++++++++++++++--- 4 files changed, 103 insertions(+), 28 deletions(-) diff --git a/NULLC/ParseTree.cpp b/NULLC/ParseTree.cpp index eaba98a34..930bcd6bc 100644 --- a/NULLC/ParseTree.cpp +++ b/NULLC/ParseTree.cpp @@ -923,7 +923,16 @@ SynAlign* ParseAlign(ParseContext &ctx) return NULL; } -SynTemplate* ParseTemplate(ParseContext &ctx) +static bool CheckClassOrTypeNameLiteral(ParseContext &ctx) +{ + if(!(ctx.Consume("typename") || ctx.Consume("classname"))) { + Report(ctx, ctx.currentLexeme, "ERROR: template typename or classname expected"); + return false; + } + return true; +} + +bool ParseTemplate(ParseContext &ctx, IntrusiveList &aliases) { Lexeme *start = ctx.currentLexeme; @@ -931,7 +940,7 @@ SynTemplate* ParseTemplate(ParseContext &ctx) { if(ctx.Consume(lex_less)) { - IntrusiveList aliases; + CheckClassOrTypeNameLiteral(ctx); if(CheckAt(ctx, lex_identifier, "ERROR: template type alias required after '<'")) { @@ -941,6 +950,7 @@ SynTemplate* ParseTemplate(ParseContext &ctx) while(ctx.Consume(lex_comma)) { + CheckClassOrTypeNameLiteral(ctx); if(!CheckAt(ctx, lex_identifier, "ERROR: template type alias required after ','")) break; @@ -951,12 +961,11 @@ SynTemplate* ParseTemplate(ParseContext &ctx) } CheckConsume(ctx, lex_greater, "ERROR: '>' expected after template type alias list"); - - return new (ctx.get()) SynTemplate(start, ctx.Previous(), aliases); + return true; } } - return NULL; + return false; } SynNew* ParseNew(ParseContext &ctx) @@ -1576,13 +1585,15 @@ SynClassElements* ParseClassElements(ParseContext &ctx) else { switch(ctx.Peek()) { - case lex_public: - case lex_private: - case lex_protected: - // for now only consume then and do nothing - ctx.Skip(); - CheckConsume(ctx, lex_colon, "ERROR: ':' public/private"); - continue; + case lex_public: + case lex_private: + case lex_protected: + // for now only consume then and do nothing + ctx.Skip(); + CheckConsume(ctx, lex_colon, "ERROR: ':' public/private"); + continue; + default: + break; } break; } @@ -1595,9 +1606,11 @@ SynClassElements* ParseClassElements(ParseContext &ctx) SynBase* ParseClassDefinition(ParseContext &ctx) { + IntrusiveList aliases; Lexeme *start = ctx.currentLexeme; SynAlign *align = ParseAlign(ctx); + ParseTemplate(ctx, aliases); bool isStruct = ctx.Consume(lex_struct); @@ -1624,8 +1637,6 @@ SynBase* ParseClassDefinition(ParseContext &ctx) return new (ctx.get()) SynClassPrototype(start, ctx.Previous(), nameIdentifier); } - IntrusiveList aliases; - if(ctx.Consume(lex_less)) { if(CheckAt(ctx, lex_identifier, "ERROR: generic type alias required after '<'")) @@ -1654,6 +1665,13 @@ SynBase* ParseClassDefinition(ParseContext &ctx) if(ctx.Consume(lex_colon)) { + switch(ctx.Peek()) { + case lex_public: + case lex_private: + ctx.Skip(); + default: + break; + } baseClass = ParseType(ctx); if(!baseClass) @@ -2764,11 +2782,13 @@ IntrusiveList ParseFunctionArguments(ParseContext &ctx) SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) { + IntrusiveList aliases; Lexeme *start = ctx.currentLexeme; if(ctx.nonFunctionDefinitionLocations.find(unsigned(start - ctx.firstLexeme) + 1)) return NULL; + ParseTemplate(ctx, aliases); bool isStatic = ctx.Consume(lex_static); bool isInline = ctx.Consume(lex_inline); bool coroutine = ctx.Consume(lex_coroutine); @@ -2846,8 +2866,6 @@ SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) Stop(ctx, ctx.Current(), "ERROR: function name not found after return type"); } - IntrusiveList aliases; - if(nameIdentifier && ctx.Consume(lex_less)) { do @@ -2884,6 +2902,8 @@ SynFunctionDefinition* ParseFunctionDefinition(ParseContext &ctx) CheckConsume(ctx, lex_cparen, "ERROR: ')' not found after function variable list"); + ctx.Consume("override"); + if(!nameIdentifier) nameIdentifier = new (ctx.get()) SynIdentifier(InplaceStr()); diff --git a/NULLC/ParseTree.h b/NULLC/ParseTree.h index 0f4b571c9..90dd488f2 100644 --- a/NULLC/ParseTree.h +++ b/NULLC/ParseTree.h @@ -545,11 +545,11 @@ struct SynGenerator: SynBase struct SynTemplate: SynBase { - SynTemplate(Lexeme *begin, Lexeme *end, IntrusiveList aliases): SynBase(myTypeID, begin, end), aliases(aliases) + SynTemplate(Lexeme *begin, Lexeme *end, IntrusiveList typeAliases): SynBase(myTypeID, begin, end), typeAliases(typeAliases) { } - IntrusiveList aliases; + IntrusiveList typeAliases; static const unsigned myTypeID = SynNode::SynTemplate; }; diff --git a/tests/nullc_in_nullc/lexer.nc b/tests/nullc_in_nullc/lexer.nc index 07dab6310..75474ef5b 100644 --- a/tests/nullc_in_nullc/lexer.nc +++ b/tests/nullc_in_nullc/lexer.nc @@ -50,16 +50,13 @@ enum LexemeType lex_oparen, lex_cparen, lex_obracket, lex_cbracket, lex_ofigure, lex_cfigure, // ( ) [ ] { } lex_questionmark, lex_colon, lex_semicolon, lex_dblcolon, // ? : ; :: lex_if, lex_else, lex_for, lex_while, lex_do, lex_switch, lex_case, lex_default, // if else for while switch case default - lex_break, lex_continue, lex_return, // break continue return - lex_ref, lex_auto, lex_class, lex_noalign, lex_align, // ref auto class noalign align + lex_break, lex_continue, lex_goto, lex_return, // break continue goto return + lex_ref, lex_auto, lex_class, lex_struct, lex_template, lex_noalign, lex_align, // ref auto class struct template noalign align lex_private, lex_public, lex_protected, lex_static, // private public protected static lex_typeof, lex_sizeof, lex_new, lex_operator, lex_typedef, lex_import, lex_nullptr, // typeof sizeof new operator typedef import in nullptr lex_coroutine, lex_yield, // coroutine yield lex_at, lex_inline, // @ inline - lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with, // generic const true false enum namespace extendable with - // it seems that there is a place where the position of the above tokes is significant - // do not change, add, remove anything above this line unless you find it ! - lex_goto, lex_struct // goto struct + lex_generic, lex_const, lex_true, lex_false, lex_enum, lex_namespace, lex_extendable, lex_with // generic const true false enum namespace extendable with } class Lexeme @@ -546,6 +543,8 @@ void Lexer::Lexify(char[] code) lType = LexemeType.lex_continue; else if(memcmp(code, curr, "operator", 8) == 0) lType = LexemeType.lex_operator; + else if(memcmp(code, curr, "template", 8) == 0) + lType = LexemeType.lex_template; break; case 9: if(memcmp(code, curr, "coroutine", 9) == 0) diff --git a/tests/nullc_in_nullc/parser.nc b/tests/nullc_in_nullc/parser.nc index b11974a0d..f99615d88 100644 --- a/tests/nullc_in_nullc/parser.nc +++ b/tests/nullc_in_nullc/parser.nc @@ -794,6 +794,51 @@ SynAlign ref ParseAlign(ParseContext ref ctx) return nullptr; } +bool CheckClassOrTypeNameLiteral(ParseContext ref ctx) +{ + if(!(ctx.Consume("typename") || ctx.Consume("classname"))) { + Report(ctx, ctx.currentLexeme, "ERROR: template typename or classname expected"); + return false; + } + return true; +} + +bool ParseTemplate(ParseContext ref ctx, RefList ref aliases) +{ + LexemeRef start = ctx.currentLexeme; + + if(ctx.Consume(LexemeType.lex_template)) + { + if(ctx.Consume(LexemeType.lex_less)) + { + CheckClassOrTypeNameLiteral(ctx); + + if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: template type alias required after '<'")) + { + InplaceStr alias = ctx.Consume(); + + aliases.push_back(new SynIdentifier(ctx.Previous(), ctx.Previous(), alias)); + + while(ctx.Consume(LexemeType.lex_comma)) + { + CheckClassOrTypeNameLiteral(ctx); + if(!CheckAt(ctx, LexemeType.lex_identifier, "ERROR: template type alias required after ','")) + break; + + alias = ctx.Consume(); + + aliases.push_back(new SynIdentifier(ctx.Previous(), ctx.Previous(), alias)); + } + } + + CheckConsume(ctx, LexemeType.lex_greater, "ERROR: '>' expected after template type alias list"); + return true; + } + } + + return false; +} + SynNew ref ParseNew(ParseContext ref ctx) { LexemeRef start = ctx.currentLexeme; @@ -1434,9 +1479,12 @@ SynClassElements ref ParseClassElements(ParseContext ref ctx) SynBase ref ParseClassDefinition(ParseContext ref ctx) { + RefList aliases; + LexemeRef start = ctx.currentLexeme; SynAlign ref alignment = ParseAlign(ctx); + ParseTemplate(ctx, aliases); bool isStruct = ctx.Consume(LexemeType.lex_struct); @@ -1462,8 +1510,6 @@ SynBase ref ParseClassDefinition(ParseContext ref ctx) return new SynClassPrototype(start, ctx.Previous(), nameIdentifier); } - RefList aliases; - if(ctx.Consume(LexemeType.lex_less)) { if(CheckAt(ctx, LexemeType.lex_identifier, "ERROR: generic type alias required after '<'")) @@ -1492,6 +1538,13 @@ SynBase ref ParseClassDefinition(ParseContext ref ctx) if(ctx.Consume(LexemeType.lex_colon)) { + switch(ctx.Peek()) { + case LexemeType.lex_public: + case LexemeType.lex_private: + ctx.Skip(); + default: + break; + } baseClass = ParseType(ctx); if(!baseClass) @@ -2595,11 +2648,14 @@ RefList ParseFunctionArguments(ParseContext ref ctx) SynFunctionDefinition ref ParseFunctionDefinition(ParseContext ref ctx) { + RefList aliases; + LexemeRef start = ctx.currentLexeme; if(ctx.nonFunctionDefinitionLocations.find(int(start - ctx.firstLexeme) + 1)) return nullptr; + ParseTemplate(ctx, aliases); bool isStatic = ctx.Consume(LexemeType.lex_static); bool isInline = ctx.Consume(LexemeType.lex_inline); bool isCoroutine = ctx.Consume(LexemeType.lex_coroutine); @@ -2677,8 +2733,6 @@ SynFunctionDefinition ref ParseFunctionDefinition(ParseContext ref ctx) Stop(ctx, ctx.Current(), "ERROR: function name not found after return type"); } - RefList aliases; - if(nameIdentifier && ctx.Consume(LexemeType.lex_less)) { do @@ -2715,6 +2769,8 @@ SynFunctionDefinition ref ParseFunctionDefinition(ParseContext ref ctx) CheckConsume(ctx, LexemeType.lex_cparen, "ERROR: ')' not found after function variable list"); + ctx.Consume("override"); + if(!nameIdentifier) nameIdentifier = new SynIdentifier(InplaceStr());