From 9fbdeb83a97acb79b293b45c7a40e4390d61899a Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 19 Jan 2023 22:24:24 -0500 Subject: [PATCH 01/22] Uncommented for the sake of testing on my own branch --- source/dutils/math/core.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index ef53bc2..752b377 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -450,9 +450,9 @@ bool validateFunction(in dstring func, in dstring def) @trusted } while((def[i] != d('x') && def[i] != d('\\')) && (def[i] != d('(') && def[i] != d(' '))); - /+if(def[i] != d('(')) // Operators+/ + if(def[i] != d('(')) // Operators currOp = tempstr.idup; - /+else // Oh shit oh fuck a function (THIS CODE DOESN'T WROK AND WILL BE FIXED LATER) + else // Oh shit oh fuck a function (THIS CODE DOESN'T WROK AND WILL BE FIXED LATER) { // We need to get the types of its arguments tempstr = tempstr[0 .. $-1].dup; @@ -480,7 +480,7 @@ bool validateFunction(in dstring func, in dstring def) @trusted temptypes ~= paramTypeList[indice]; - }+/ + } } } while(i < def.length); From d1891e31b02455a05a725ad06653f6a22cdcd377 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 19 Jan 2023 22:30:12 -0500 Subject: [PATCH 02/22] Fix the tests failing --- source/dutils/math/core.d | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 752b377..98ed0e4 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -449,8 +449,12 @@ bool validateFunction(in dstring func, in dstring def) @trusted ++i; } while((def[i] != d('x') && def[i] != d('\\')) && (def[i] != d('(') && def[i] != d(' '))); - - if(def[i] != d('(')) // Operators + + bool b = i == def.length; + if (!b) + b = b && def[i] == d('(') && def[i+1] == d('x'); + + if (!b) // Operators currOp = tempstr.idup; else // Oh shit oh fuck a function (THIS CODE DOESN'T WROK AND WILL BE FIXED LATER) { From 26442b1e91b1921a5a175669590c4f3841d352dd Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Sun, 29 Jan 2023 20:15:46 -0500 Subject: [PATCH 03/22] need to iron out detection --- source/dutils/math/core.d | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 98ed0e4..0e04f99 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -442,24 +442,27 @@ bool validateFunction(in dstring func, in dstring def) @trusted isOp = true; isOperand = false; dchar[] tempstr = []; + size_t whyIsThis = 0; do { tempstr ~= def[i]; if(((def[i] != d('x')) && (def[i] != d('\\'))) && (def[i] != d('(') && def[i] != d(' '))) ++i; + ++whyIsThis; } while((def[i] != d('x') && def[i] != d('\\')) && (def[i] != d('(') && def[i] != d(' '))); bool b = i == def.length; if (!b) - b = b && def[i] == d('(') && def[i+1] == d('x'); + b = def[i] == d('(') && def[i+1] == d('x') && whyIsThis > 1; if (!b) // Operators currOp = tempstr.idup; else // Oh shit oh fuck a function (THIS CODE DOESN'T WROK AND WILL BE FIXED LATER) { + isOp = false; + isOperand = true; // We need to get the types of its arguments - tempstr = tempstr[0 .. $-1].dup; dchar[] tempargs = []; ++i; do @@ -483,7 +486,26 @@ bool validateFunction(in dstring func, in dstring def) @trusted foreach(indice; indices) temptypes ~= paramTypeList[indice]; - + foreach(type; temptypes) + tempstr ~= type ~ ","d; + tempstr = tempstr[0 .. $-1].dup; + tempstr ~= ")("d; + + // Get the return type: + ++i; + dstring retType = ""d; + do + { + retType ~= def[i]; + ++i; + } + while(def[i] != d(')')); + + tempstr ~= retType ~ ")"d; + + // Check if said function exists + if(tempstr !in funcList) + return false; } } } @@ -529,9 +551,9 @@ bool validateFunction(in dstring func, in dstring def) @trusted def = "x1*x2"d; func = "(Number,Number)(Number)"d; assert(registerFunction("f"d, func, def)); - //Functions within functions were too hard to implement, so we removed them. - //def = "x1* f(x1,x2)(Number)"d; - //assert(validateFunction(func, def)); + // Functions within functions + def = "x1*f(x1,x2)(Number)"d; + assert(validateFunction(func, def)); } /************************************ From f6217a399ebaacfac161cac5cedc920598d11790 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Mon, 20 Feb 2023 13:39:59 -0500 Subject: [PATCH 04/22] Update LDC version to something that works. --- .github/workflows/dubtest.yml | 2 +- source/dutils/math/core.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dubtest.yml b/.github/workflows/dubtest.yml index ca30bad..a6e5981 100644 --- a/.github/workflows/dubtest.yml +++ b/.github/workflows/dubtest.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - dc: [ldc-1.30.0] + dc: [ldc-1.31.0] runs-on: ${{ matrix.os }} steps: diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 0e04f99..c669b38 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -606,7 +606,7 @@ import std.typecons : Tuple; /*********************************************************** * Executes a function. * - * TODO: Actually write the function. + * TODO: * Params: * func = * The function to execute. From 2670602f14d9a87a5984ddd4034864c23c5fcbdf Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Mon, 20 Feb 2023 14:05:07 -0500 Subject: [PATCH 05/22] Scrap previous work, the originial idea is better. --- source/dutils/math/core.d | 63 ++------------------------------------- 1 file changed, 3 insertions(+), 60 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index c669b38..5d5dd92 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -442,71 +442,14 @@ bool validateFunction(in dstring func, in dstring def) @trusted isOp = true; isOperand = false; dchar[] tempstr = []; - size_t whyIsThis = 0; do { tempstr ~= def[i]; if(((def[i] != d('x')) && (def[i] != d('\\'))) && (def[i] != d('(') && def[i] != d(' '))) ++i; - ++whyIsThis; } while((def[i] != d('x') && def[i] != d('\\')) && (def[i] != d('(') && def[i] != d(' '))); - - bool b = i == def.length; - if (!b) - b = def[i] == d('(') && def[i+1] == d('x') && whyIsThis > 1; - - if (!b) // Operators - currOp = tempstr.idup; - else // Oh shit oh fuck a function (THIS CODE DOESN'T WROK AND WILL BE FIXED LATER) - { - isOp = false; - isOperand = true; - // We need to get the types of its arguments - dchar[] tempargs = []; - ++i; - do - { - tempargs ~= def[i]; - ++i; - } - while(def[i] != d(')')); - - import std.algorithm; - auto indexes = tempargs.splitter(d(',')); - foreach(ref index; indexes) - index = index[1 .. $].dup; - - size_t[] indices = []; - import std.conv; - foreach(index; indexes) - indices ~= index.to!size_t; - - dstring[] temptypes; - foreach(indice; indices) - temptypes ~= paramTypeList[indice]; - - foreach(type; temptypes) - tempstr ~= type ~ ","d; - tempstr = tempstr[0 .. $-1].dup; - tempstr ~= ")("d; - - // Get the return type: - ++i; - dstring retType = ""d; - do - { - retType ~= def[i]; - ++i; - } - while(def[i] != d(')')); - - tempstr ~= retType ~ ")"d; - - // Check if said function exists - if(tempstr !in funcList) - return false; - } + currOp = tempstr.idup; } } while(i < def.length); @@ -552,8 +495,8 @@ bool validateFunction(in dstring func, in dstring def) @trusted func = "(Number,Number)(Number)"d; assert(registerFunction("f"d, func, def)); // Functions within functions - def = "x1*f(x1,x2)(Number)"d; - assert(validateFunction(func, def)); + //def = "x1*f(x1,x2)(Number)"d; + //assert(validateFunction(func, def)); } /************************************ From 146e9991ccca4e887330913e850476f837acfa9a Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Mon, 20 Feb 2023 14:50:18 -0500 Subject: [PATCH 06/22] make some headway --- source/dutils/math/core.d | 46 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 5d5dd92..f7ceb62 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -47,6 +47,48 @@ else bool registerFunction(in dstring name, in dstring func, in dstring def) @safe { + import std.uni; + dchar[] def2 = def.dup; + for(size_t i = 0; i < def.length; ++i) + { + if(def[i] != d('x') && !def[i].isNumber && def2[i] != d('\\') && def[i] != d('(')) + { + dstring tempstr = ""d; + do + { + tempstr ~= def[i]; + if(i != def.length) + ++i; + if(i == def.length) + goto c; + } + while(def[i] != d('x') && !def[i].isNumber && def[i] != d('\\') && def[i] != d('(')); + + if(def[i] != d('(')) + goto c; + + auto oldi = i; + do + { + tempstr ~= def[i]; + if(i != def.length) + ++i; + if(i == def.length) + goto c; + } + while(def[i] != d(')')); + + if(i+1 == def.length) + goto c; + + if(def[i+1] != d('(')) + goto c; + + // It truely is a function. + } + c: // If it is only an operator, and not a function. + } + auto ret = validateFunction(func, def) && name ~ func !in funcList.funcs; if(ret) funcList.funcs[name ~ func] = def; @@ -494,9 +536,9 @@ bool validateFunction(in dstring func, in dstring def) @trusted def = "x1*x2"d; func = "(Number,Number)(Number)"d; assert(registerFunction("f"d, func, def)); - // Functions within functions + // Functions within functions. The substitution is done at registration, it should execute fine. //def = "x1*f(x1,x2)(Number)"d; - //assert(validateFunction(func, def)); + //assert(registerFunction(func, def)); } /************************************ From df92804ba19395a4ab8dfdc94b19265883b8dfe4 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Tue, 21 Feb 2023 15:01:13 -0500 Subject: [PATCH 07/22] It still doesn't differentiate between functions and operators because of parantheses --- source/dutils/math/core.d | 128 +++++++++++++++++++++++++++++++++++--- 1 file changed, 121 insertions(+), 7 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index f7ceb62..93d451b 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -48,12 +48,14 @@ else bool registerFunction(in dstring name, in dstring func, in dstring def) @safe { import std.uni; - dchar[] def2 = def.dup; + dchar[] tempstr = []; + size_t oldi; for(size_t i = 0; i < def.length; ++i) { - if(def[i] != d('x') && !def[i].isNumber && def2[i] != d('\\') && def[i] != d('(')) + oldi = 0; + if(def[i] != d('x') && !def[i].isNumber && def[i] != d('\\') && def[i] != d('(')) { - dstring tempstr = ""d; + auto oldi2 = i; do { tempstr ~= def[i]; @@ -67,7 +69,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe if(def[i] != d('(')) goto c; - auto oldi = i; + oldi = i; do { tempstr ~= def[i]; @@ -84,14 +86,126 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe if(def[i+1] != d('(')) goto c; - // It truely is a function. + // It truely is a function (EXTREME PAIN AND SUFFERING): + + // Get the paramaters and return type of the function in func ... + dstring[] params; + dstring[] returni; + size_t k = 0; + getParamsReturns(params, func, k); //Get the function return type. + dstring returns; + ++k; //Make sure to get out of the closing parenthesis. + getParamsReturns(returni, func, k); //Get the parameter types. + static foreach(type; typel) + { + mixin(type ~ "[] " ~ type ~ "ParamList;"); + mixin(type ~ "[] " ~ type ~ "OperandList;"); + } + returns = returni[0]; + + size_t j = 0; + dchar[] tempstr2 = []; + size_t[] tempxns = []; + for(; j < tempstr.length; ++j) + { + if(tempstr[j] == d(')')) + break; + else if(tempstr[j] == d('x')) // Get the parameter types ... + { + dstring tempstr3 = ""d; + ++j; + do + { + tempstr3 ~= tempstr[j]; + ++j; + } + while(tempstr[j].isNumber); + + import std.conv : to; + tempstr2 ~= params[to!size_t(tempstr3[1 .. $])]; + tempxns ~= to!size_t(tempstr3[1 .. $]); + } + else + tempstr2 ~= tempstr[j]; + } + tempstr2 ~= tempstr[j .. $].dup; // The return type is known, we just need to copy it. + // Verify that tempstr2 is a registered function. + if(tempstr2.idup !in funcList) + return false; + + tempstr2 = funcList[tempstr2.idup].dup; // Load the function body + for(j = 0; j < tempstr2.length; j++) // Substitue the xns + { + if(tempstr2[j] == d('x')) // Do the substitution + { + auto oldj = ++j; + dstring tempstr3 = ""d; + + do + { + tempstr3 ~= tempstr2[j]; + ++j; + if(j == tempstr2.length) + break; + } + while(tempstr2[j].isNumber); + + import std.conv : to; + auto tempstr4 = to!dstring(tempxns[to!size_t(tempstr3)]); + if(tempstr4.length > tempstr3.length) + { + tempstr2.length += tempstr4.length - tempstr3.length; + tempstr2[j + tempstr4.length - tempstr3.length .. $] = tempstr2[j .. $ + tempstr3.length - tempstr4.length].dup; // Shift it up + tempstr2[oldj .. j+1] = tempstr4.dup; + } + else if(tempstr4.length == tempstr3.length) + { + tempstr2[oldj .. j+1] = tempstr4.dup; + } + else // The string has to be shrunk. + { + tempstr2[j + tempstr4.length - tempstr3.length .. $ + tempstr4.length - tempstr3.length] = tempstr2[j .. $].dup; + tempstr2[oldj .. j + 1 + tempstr4.length - tempstr3.length] = tempstr4.dup; + tempstr2.length += tempstr4.length - tempstr3.length; + } + } + } + + tempstr2 = "("d.dup ~ tempstr2 ~ ")"d.dup; // Encapsulate it ... + + // Substitute it into the body ... + if(tempstr2.length > i - oldi2) + { + tempstr.length += tempstr2.length + oldi2 - i; + tempstr[tempstr2.length + oldi2 .. $] = tempstr[i .. $ + i - oldi2 - tempstr2.length].dup; + tempstr[oldi2 .. i + tempstr2.length + 1] = tempstr2.dup; + } + else if(tempstr2.length == i - oldi2) + { + tempstr[oldi2 .. i+1] = tempstr2.dup; + } + else + { + tempstr[tempstr2.length + oldi2 .. $ + tempstr2.length + oldi2 - i] = tempstr[i .. $].dup; + tempstr[oldi2 .. tempstr2.length + oldi2 + 1] = tempstr2.dup; + tempstr.length += tempstr2.length + oldi2 - i; + } + continue; } c: // If it is only an operator, and not a function. + debug import std.stdio; + debug "here".writeln; + debug oldi.writeln; + if(oldi != 0) + i = oldi; + if(i == def.length) + break; + tempstr ~= def[i]; } - auto ret = validateFunction(func, def) && name ~ func !in funcList.funcs; + auto ret = validateFunction(func, tempstr.idup) && name ~ func !in funcList.funcs; if(ret) - funcList.funcs[name ~ func] = def; + funcList.funcs[name ~ func] = tempstr.idup; return ret; } From cfda62ab3032e9a98dab38ac9d69fbdaf95f2dda Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Wed, 22 Feb 2023 21:59:15 -0500 Subject: [PATCH 08/22] Change email address and also find where the bug is --- source/dutils/math/core.d | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 93d451b..dfa48aa 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -11,7 +11,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see .*/ /** Copyright: 2022-2023, Ruby The Roobster*/ -/**Author: Ruby The Roobster, */ +/**Author: Ruby The Roobster, */ /**Date: January 16, 2023*/ /** License: GPL-3.0**/ @@ -201,6 +201,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe if(i == def.length) break; tempstr ~= def[i]; + debug tempstr.writeln; } auto ret = validateFunction(func, tempstr.idup) && name ~ func !in funcList.funcs; @@ -937,6 +938,8 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg // All of the above is working def = "x1*(x2*x3)"d; assert(removeFunction("ree"d, func)); + debug import std.stdio; + debug "buggy assert".writeln; assert(registerFunction("ree"d, func, def)); i = executeFunction!(Number, Number, Number, Number)("ree(Number,Number,Number)(Number)"d, a); assert(i.toDstring == "6+0i"d, cast(char[])i.toDstring.dup); From 84a7571b0364275f8dcfa4e42f0989fe45cfed6b Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Wed, 22 Feb 2023 22:00:09 -0500 Subject: [PATCH 09/22] Change email address and also find where the bug is --- source/dutils/math/core.d | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index dfa48aa..f144019 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -172,6 +172,8 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } tempstr2 = "("d.dup ~ tempstr2 ~ ")"d.dup; // Encapsulate it ... + debug import std.stdio; + debug tempstr.writeln; // Substitute it into the body ... if(tempstr2.length > i - oldi2) @@ -203,7 +205,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe tempstr ~= def[i]; debug tempstr.writeln; } - + debug tempstr.writeln; auto ret = validateFunction(func, tempstr.idup) && name ~ func !in funcList.funcs; if(ret) funcList.funcs[name ~ func] = tempstr.idup; From f23738677ebc6cd1afc843c13517123828249499 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Wed, 22 Feb 2023 22:13:29 -0500 Subject: [PATCH 10/22] Turns out that 'oldi' was unnecessary, and removing it fixes the bug. --- source/dutils/math/core.d | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index f144019..166141a 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -69,7 +69,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe if(def[i] != d('(')) goto c; - oldi = i; + //oldi = i; do { tempstr ~= def[i]; @@ -172,8 +172,8 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } tempstr2 = "("d.dup ~ tempstr2 ~ ")"d.dup; // Encapsulate it ... - debug import std.stdio; - debug tempstr.writeln; + //debug import std.stdio; + //debug tempstr.writeln; // Substitute it into the body ... if(tempstr2.length > i - oldi2) @@ -195,17 +195,18 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe continue; } c: // If it is only an operator, and not a function. - debug import std.stdio; - debug "here".writeln; - debug oldi.writeln; - if(oldi != 0) - i = oldi; + //debug import std.stdio; + //debug "here".writeln; + //debug oldi.writeln; + //if(oldi != 0) + // i = oldi; if(i == def.length) break; tempstr ~= def[i]; - debug tempstr.writeln; + //debug tempstr.writeln; } - debug tempstr.writeln; + //debug import std.stdio; + //debug tempstr.writeln; auto ret = validateFunction(func, tempstr.idup) && name ~ func !in funcList.funcs; if(ret) funcList.funcs[name ~ func] = tempstr.idup; @@ -940,8 +941,6 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg // All of the above is working def = "x1*(x2*x3)"d; assert(removeFunction("ree"d, func)); - debug import std.stdio; - debug "buggy assert".writeln; assert(registerFunction("ree"d, func, def)); i = executeFunction!(Number, Number, Number, Number)("ree(Number,Number,Number)(Number)"d, a); assert(i.toDstring == "6+0i"d, cast(char[])i.toDstring.dup); From ec87f2162388a8db744ba4fa5fe8f02b359c9e7e Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:03:04 -0500 Subject: [PATCH 11/22] It doesn't actually subsitute it wtf --- source/dutils/math/core.d | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 166141a..f58f33f 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -205,8 +205,8 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe tempstr ~= def[i]; //debug tempstr.writeln; } - //debug import std.stdio; - //debug tempstr.writeln; + debug import std.stdio; + debug tempstr.writeln; auto ret = validateFunction(func, tempstr.idup) && name ~ func !in funcList.funcs; if(ret) funcList.funcs[name ~ func] = tempstr.idup; @@ -221,6 +221,11 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe dstring name = "f"d; assert(registerFunction(name, func, def)); assert(!registerFunction(name, func, def)); //No registering an already-existing function. + + // Issue 12 + name = "g"d; + def = "f(x1)"d; + assert(registerFunction(name, func, def)); } /************************************************** From f938c4317d621665b3eb9115d933599c17410bff Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:09:08 -0500 Subject: [PATCH 12/22] Fix a couple of off-by-one errors. --- source/dutils/math/core.d | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index f58f33f..370002d 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -118,12 +118,16 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe { tempstr3 ~= tempstr[j]; ++j; + if(tempstr.length == j) + break; } while(tempstr[j].isNumber); import std.conv : to; - tempstr2 ~= params[to!size_t(tempstr3[1 .. $])]; - tempxns ~= to!size_t(tempstr3[1 .. $]); + debug import std.stdio; + debug tempstr3.writeln; + tempstr2 ~= params[to!size_t(tempstr)]; + tempxns ~= to!size_t(tempstr3); } else tempstr2 ~= tempstr[j]; @@ -172,8 +176,8 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } tempstr2 = "("d.dup ~ tempstr2 ~ ")"d.dup; // Encapsulate it ... - //debug import std.stdio; - //debug tempstr.writeln; + debug import std.stdio; + debug tempstr.writeln; // Substitute it into the body ... if(tempstr2.length > i - oldi2) @@ -224,7 +228,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe // Issue 12 name = "g"d; - def = "f(x1)"d; + def = "f(x1)(Number)"d; assert(registerFunction(name, func, def)); } From e4587a8d18fc8a711ea52387f2341780f8ec2510 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:09:33 -0500 Subject: [PATCH 13/22] Fix a couple of off-by-one errors. --- source/dutils/math/core.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 370002d..0e7df82 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -126,7 +126,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe import std.conv : to; debug import std.stdio; debug tempstr3.writeln; - tempstr2 ~= params[to!size_t(tempstr)]; + tempstr2 ~= params[to!size_t(tempstr3)]; tempxns ~= to!size_t(tempstr3); } else From 65e865c8c2cdae3a5fd7db419100ce91bee5fcbc Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:17:06 -0500 Subject: [PATCH 14/22] Substitution still doesn't work, and it fails verification because the function isn't swapped out. --- source/dutils/math/core.d | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 0e7df82..cbee46c 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -86,6 +86,16 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe if(def[i+1] != d('(')) goto c; + i += 2; + tempstr ~= ")("d; + do + { + tempstr ~= def[i]; + ++i; + } + while(def[i] != d(')')); + tempstr ~= ")"d; + // It truely is a function (EXTREME PAIN AND SUFFERING): // Get the paramaters and return type of the function in func ... @@ -126,12 +136,14 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe import std.conv : to; debug import std.stdio; debug tempstr3.writeln; - tempstr2 ~= params[to!size_t(tempstr3)]; + tempstr2 ~= params[to!size_t(tempstr3)-1]; tempxns ~= to!size_t(tempstr3); } else tempstr2 ~= tempstr[j]; } + debug import std.stdio; + debug tempstr.writeln; tempstr2 ~= tempstr[j .. $].dup; // The return type is known, we just need to copy it. // Verify that tempstr2 is a registered function. if(tempstr2.idup !in funcList) From f8f77de10d97b0ff39406e91f24ff650f0300b56 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:24:13 -0500 Subject: [PATCH 15/22] It now attempts to do the substitution but crashes. At least the function is copied correctly. --- source/dutils/math/core.d | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index cbee46c..e07cd8b 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -141,10 +141,13 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } else tempstr2 ~= tempstr[j]; + if(tempstr[j] == d(')')) + break; } debug import std.stdio; debug tempstr.writeln; tempstr2 ~= tempstr[j .. $].dup; // The return type is known, we just need to copy it. + debug tempstr2.writeln; // Verify that tempstr2 is a registered function. if(tempstr2.idup !in funcList) return false; @@ -188,8 +191,6 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } tempstr2 = "("d.dup ~ tempstr2 ~ ")"d.dup; // Encapsulate it ... - debug import std.stdio; - debug tempstr.writeln; // Substitute it into the body ... if(tempstr2.length > i - oldi2) From 88140b3949fb46dbc256bd60b2a50f23e565b3de Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:29:05 -0500 Subject: [PATCH 16/22] It works! Probably buggy, but I couldn't care less. I'm going to do some more testing of this. --- source/dutils/math/core.d | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index e07cd8b..c5f19a1 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -170,7 +170,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe while(tempstr2[j].isNumber); import std.conv : to; - auto tempstr4 = to!dstring(tempxns[to!size_t(tempstr3)]); + auto tempstr4 = to!dstring(tempxns[to!size_t(tempstr3) - 1]); if(tempstr4.length > tempstr3.length) { tempstr2.length += tempstr4.length - tempstr3.length; @@ -179,7 +179,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } else if(tempstr4.length == tempstr3.length) { - tempstr2[oldj .. j+1] = tempstr4.dup; + tempstr2[oldj .. j] = tempstr4.dup; } else // The string has to be shrunk. { @@ -190,7 +190,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } } - tempstr2 = "("d.dup ~ tempstr2 ~ ")"d.dup; // Encapsulate it ... + tempstr2 = "("d.dup ~ tempstr2; // Encapsulate it ... // Substitute it into the body ... if(tempstr2.length > i - oldi2) @@ -201,12 +201,12 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } else if(tempstr2.length == i - oldi2) { - tempstr[oldi2 .. i+1] = tempstr2.dup; + tempstr[oldi2 .. i] = tempstr2.dup; } else { tempstr[tempstr2.length + oldi2 .. $ + tempstr2.length + oldi2 - i] = tempstr[i .. $].dup; - tempstr[oldi2 .. tempstr2.length + oldi2 + 1] = tempstr2.dup; + tempstr[oldi2 .. tempstr2.length + oldi2] = tempstr2.dup; tempstr.length += tempstr2.length + oldi2 - i; } continue; From cd5338be50d4b72b628a8c208accb39341d051ba Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:31:02 -0500 Subject: [PATCH 17/22] It works! Probably buggy, but I couldn't care less. I'm going to do some more testing of this. --- source/dutils/math/core.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index c5f19a1..92700e6 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -243,6 +243,11 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe name = "g"d; def = "f(x1)(Number)"d; assert(registerFunction(name, func, def)); + + name = "h"d; + func = "(Number,Number)(Number)"d; + def = "g(x1)(Number)+f(x2)(Number)"d; + assert(registerFunction(name, func, def)); } /************************************************** From 18e20228b32d0af5295a02653e37a863dd810fbb Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:33:20 -0500 Subject: [PATCH 18/22] Revert "It works! Probably buggy, but I couldn't care less. I'm going to do some more testing of this." This reverts commit cd5338be50d4b72b628a8c208accb39341d051ba. It's still buggy as hell. --- source/dutils/math/core.d | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 92700e6..c5f19a1 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -243,11 +243,6 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe name = "g"d; def = "f(x1)(Number)"d; assert(registerFunction(name, func, def)); - - name = "h"d; - func = "(Number,Number)(Number)"d; - def = "g(x1)(Number)+f(x2)(Number)"d; - assert(registerFunction(name, func, def)); } /************************************************** From d8cca09e24966cc04966ac46d712cf792557c2f1 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 21:35:11 -0500 Subject: [PATCH 19/22] It's buggy as hell still. --- source/dutils/math/core.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index c5f19a1..92700e6 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -243,6 +243,11 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe name = "g"d; def = "f(x1)(Number)"d; assert(registerFunction(name, func, def)); + + name = "h"d; + func = "(Number,Number)(Number)"d; + def = "g(x1)(Number)+f(x2)(Number)"d; + assert(registerFunction(name, func, def)); } /************************************************** From 27cbc2fdfe2ecaeaa6c24c5b60e7e81e310dc374 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Feb 2023 22:00:48 -0500 Subject: [PATCH 20/22] Final commit of the day. --- source/dutils/math/core.d | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 92700e6..5eaa96c 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -48,13 +48,17 @@ else bool registerFunction(in dstring name, in dstring func, in dstring def) @safe { import std.uni; + bool isOp = false; dchar[] tempstr = []; size_t oldi; for(size_t i = 0; i < def.length; ++i) { oldi = 0; - if(def[i] != d('x') && !def[i].isNumber && def[i] != d('\\') && def[i] != d('(')) + if((def[i] != d('x') && !def[i].isNumber && def[i] != d('\\') && def[i] != d('(')) || isOp && def[i] == d(' ')) { + isOp = false; + if(def[i] == d(' ')) + ++i; auto oldi2 = i; do { @@ -191,7 +195,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } tempstr2 = "("d.dup ~ tempstr2; // Encapsulate it ... - + debug tempstr2.writeln; // Substitute it into the body ... if(tempstr2.length > i - oldi2) { @@ -217,6 +221,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe //debug oldi.writeln; //if(oldi != 0) // i = oldi; + isOp = true; if(i == def.length) break; tempstr ~= def[i]; @@ -246,7 +251,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe name = "h"d; func = "(Number,Number)(Number)"d; - def = "g(x1)(Number)+f(x2)(Number)"d; + def = "g(x1)(Number)+ f(x2)(Number)"d; assert(registerFunction(name, func, def)); } From 2780edf3b7a20a47ae45e6b4d24558ee17e918c3 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Tue, 28 Feb 2023 20:48:58 -0500 Subject: [PATCH 21/22] THere is now an error with the bounds of the array, but at least we actually get to that point in the code. --- source/dutils/math/core.d | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 5eaa96c..e4b445c 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -51,15 +51,21 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe bool isOp = false; dchar[] tempstr = []; size_t oldi; + size_t oldi2; for(size_t i = 0; i < def.length; ++i) { oldi = 0; if((def[i] != d('x') && !def[i].isNumber && def[i] != d('\\') && def[i] != d('(')) || isOp && def[i] == d(' ')) { isOp = false; - if(def[i] == d(' ')) + oldi = tempstr.length; + if(def[i+1] == d(' ')) + { ++i; - auto oldi2 = i; + oldi +=2; + tempstr ~= def[i-1]; + } + oldi2 = i; do { tempstr ~= def[i]; @@ -73,7 +79,6 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe if(def[i] != d('(')) goto c; - //oldi = i; do { tempstr ~= def[i]; @@ -117,11 +122,20 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } returns = returni[0]; - size_t j = 0; + size_t j = oldi; dchar[] tempstr2 = []; size_t[] tempxns = []; + debug import std.stdio; + "here".writeln; + debug oldi.writeln; + debug + { + if(oldi > 0) + debug tempstr[oldi].writeln; + } for(; j < tempstr.length; ++j) { + tempstr.writeln; if(tempstr[j] == d(')')) break; else if(tempstr[j] == d('x')) // Get the parameter types ... @@ -138,8 +152,6 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe while(tempstr[j].isNumber); import std.conv : to; - debug import std.stdio; - debug tempstr3.writeln; tempstr2 ~= params[to!size_t(tempstr3)-1]; tempxns ~= to!size_t(tempstr3); } @@ -148,10 +160,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe if(tempstr[j] == d(')')) break; } - debug import std.stdio; - debug tempstr.writeln; tempstr2 ~= tempstr[j .. $].dup; // The return type is known, we just need to copy it. - debug tempstr2.writeln; // Verify that tempstr2 is a registered function. if(tempstr2.idup !in funcList) return false; @@ -195,7 +204,6 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } tempstr2 = "("d.dup ~ tempstr2; // Encapsulate it ... - debug tempstr2.writeln; // Substitute it into the body ... if(tempstr2.length > i - oldi2) { @@ -213,6 +221,9 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe tempstr[oldi2 .. tempstr2.length + oldi2] = tempstr2.dup; tempstr.length += tempstr2.length + oldi2 - i; } + + debug import std.stdio; + debug tempstr.writeln; continue; } c: // If it is only an operator, and not a function. @@ -252,6 +263,8 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe name = "h"d; func = "(Number,Number)(Number)"d; def = "g(x1)(Number)+ f(x2)(Number)"d; + debug import std.stdio; + "bug".writeln; assert(registerFunction(name, func, def)); } From c05624a82a84eb950f9cf2153e2b54bd62c10c96 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Tue, 28 Feb 2023 22:33:15 -0500 Subject: [PATCH 22/22] It seems to work for a more complex case after I got it to work for a simpler one. I'm calling it a day at this point. --- source/dutils/math/core.d | 55 ++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index e4b445c..4adbccf 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -52,20 +52,23 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe dchar[] tempstr = []; size_t oldi; size_t oldi2; + bool bruh = false; for(size_t i = 0; i < def.length; ++i) { oldi = 0; + bruh = false; if((def[i] != d('x') && !def[i].isNumber && def[i] != d('\\') && def[i] != d('(')) || isOp && def[i] == d(' ')) { isOp = false; oldi = tempstr.length; + oldi2 = i; if(def[i+1] == d(' ')) { ++i; oldi +=2; tempstr ~= def[i-1]; + bruh = true; } - oldi2 = i; do { tempstr ~= def[i]; @@ -203,23 +206,42 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } } - tempstr2 = "("d.dup ~ tempstr2; // Encapsulate it ... + tempstr2 = "("d.dup ~ tempstr2 ~ ")"d; // Encapsulate it ... // Substitute it into the body ... - if(tempstr2.length > i - oldi2) + if(tempstr2.length > i - oldi) { - tempstr.length += tempstr2.length + oldi2 - i; - tempstr[tempstr2.length + oldi2 .. $] = tempstr[i .. $ + i - oldi2 - tempstr2.length].dup; - tempstr[oldi2 .. i + tempstr2.length + 1] = tempstr2.dup; + tempstr.length += tempstr2.length + oldi - i; + tempstr[tempstr2.length + oldi .. $] = tempstr[i .. $ + i - oldi - tempstr2.length].dup; + tempstr[oldi .. i + tempstr2.length + 1] = tempstr2.dup; } - else if(tempstr2.length == i - oldi2) + else if(tempstr2.length == i - oldi) { - tempstr[oldi2 .. i] = tempstr2.dup; + tempstr[oldi .. i] = tempstr2.dup; } else { - tempstr[tempstr2.length + oldi2 .. $ + tempstr2.length + oldi2 - i] = tempstr[i .. $].dup; - tempstr[oldi2 .. tempstr2.length + oldi2] = tempstr2.dup; - tempstr.length += tempstr2.length + oldi2 - i; + debug import std.stdio; + debug "bruh".writeln; + if(bruh) + { + debug tempstr[oldi2 + oldi .. $].writeln; + debug tempstr[oldi .. oldi+tempstr[oldi2 + oldi .. $].length].writeln; + } + if(!bruh) + tempstr[tempstr2.length + oldi .. $ + tempstr2.length + oldi - i] = tempstr[i .. $].dup; + else // THIS LINE I SWEAR + tempstr[oldi .. oldi+tempstr[oldi2 + oldi .. $].length] = tempstr[oldi2 + oldi .. $].dup; + if(bruh) + debug tempstr[oldi .. oldi + oldi2 - tempstr2.length + 1].writeln; + debug tempstr2.writeln; + if(!bruh) + tempstr[oldi .. tempstr2.length + oldi] = tempstr2.dup; + else + tempstr[oldi .. oldi + oldi2 - tempstr2.length + 1] = tempstr2.dup; + if(bruh) + tempstr.length += tempstr.length - oldi - oldi2 - tempstr2.length + 1; + else + tempstr.length += tempstr2.length + oldi - i - 1; } debug import std.stdio; @@ -240,6 +262,15 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe } debug import std.stdio; debug tempstr.writeln; + + for(size_t i = 0; i < tempstr.length; ++i) // Remove any whitespace + { + if(tempstr[i] == d(' ')) + { + tempstr[i .. $-1] = tempstr[i+1 .. $].dup; + --tempstr.length; + } + } auto ret = validateFunction(func, tempstr.idup) && name ~ func !in funcList.funcs; if(ret) funcList.funcs[name ~ func] = tempstr.idup; @@ -250,7 +281,7 @@ bool registerFunction(in dstring name, in dstring func, in dstring def) @safe @safe unittest { dstring func = "(Number)(Number)"d; - dstring def = "x1"d; + dstring def = "x1*x1"d; dstring name = "f"d; assert(registerFunction(name, func, def)); assert(!registerFunction(name, func, def)); //No registering an already-existing function.