Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9fbdeb8
Uncommented for the sake of testing on my own branch
RubyTheRoobster Jan 20, 2023
d1891e3
Fix the tests failing
RubyTheRoobster Jan 20, 2023
26442b1
need to iron out detection
RubyTheRoobster Jan 30, 2023
f6217a3
Update LDC version to something that works.
RubyTheRoobster Feb 20, 2023
2670602
Scrap previous work, the originial idea is better.
RubyTheRoobster Feb 20, 2023
146e999
make some headway
RubyTheRoobster Feb 20, 2023
df92804
It still doesn't differentiate between functions and operators becaus…
RubyTheRoobster Feb 21, 2023
cfda62a
Change email address and also find where the bug is
RubyTheRoobster Feb 23, 2023
84a7571
Change email address and also find where the bug is
RubyTheRoobster Feb 23, 2023
f237386
Turns out that 'oldi' was unnecessary, and removing it fixes the bug.
RubyTheRoobster Feb 23, 2023
ec87f21
It doesn't actually subsitute it wtf
RubyTheRoobster Feb 24, 2023
f938c43
Fix a couple of off-by-one errors.
RubyTheRoobster Feb 24, 2023
e4587a8
Fix a couple of off-by-one errors.
RubyTheRoobster Feb 24, 2023
65e865c
Substitution still doesn't work, and it fails verification because th…
RubyTheRoobster Feb 24, 2023
f8f77de
It now attempts to do the substitution but crashes. At least the func…
RubyTheRoobster Feb 24, 2023
88140b3
It works! Probably buggy, but I couldn't care less. I'm going to do…
RubyTheRoobster Feb 24, 2023
cd5338b
It works! Probably buggy, but I couldn't care less. I'm going to do…
RubyTheRoobster Feb 24, 2023
18e2022
Revert "It works! Probably buggy, but I couldn't care less. I'm goi…
RubyTheRoobster Feb 24, 2023
d8cca09
It's buggy as hell still.
RubyTheRoobster Feb 24, 2023
27cbc2f
Final commit of the day.
RubyTheRoobster Feb 24, 2023
2780edf
THere is now an error with the bounds of the array, but at least we a…
RubyTheRoobster Mar 1, 2023
c05624a
It seems to work for a more complex case after I got it to work for a…
RubyTheRoobster Mar 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dubtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
285 changes: 245 additions & 40 deletions source/dutils/math/core.d
Original file line number Diff line number Diff line change
Expand Up @@ -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 <http://www.gnu.org/licenses/>.*/
/** Copyright: 2022-2023, Ruby The Roobster*/
/**Author: Ruby The Roobster, <rubytheroobster@yandex.com>*/
/**Author: Ruby The Roobster, <michaeleverestc79@gmail.com>*/
/**Date: January 16, 2023*/
/** License: GPL-3.0**/

Expand Down Expand Up @@ -47,20 +47,256 @@ else

bool registerFunction(in dstring name, in dstring func, in dstring def) @safe
{
auto ret = validateFunction(func, def) && name ~ func !in funcList.funcs;
import std.uni;
bool isOp = false;
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;
}
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;

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;

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 ...
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 = 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 ...
{
dstring tempstr3 = ""d;
++j;
do
{
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);
}
else
tempstr2 ~= tempstr[j];
if(tempstr[j] == d(')'))
break;
}
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) - 1]);
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] = 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; // Encapsulate it ...
// Substitute it into the body ...
if(tempstr2.length > i - oldi)
{
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 - oldi)
{
tempstr[oldi .. i] = tempstr2.dup;
}
else
{
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;
debug tempstr.writeln;
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;
isOp = true;
if(i == def.length)
break;
tempstr ~= def[i];
//debug tempstr.writeln;
}
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] = def;
funcList.funcs[name ~ func] = tempstr.idup;
return ret;
}

///
@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.

// Issue 12
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;
debug import std.stdio;
"bug".writeln;
assert(registerFunction(name, func, def));
}

/**************************************************
Expand Down Expand Up @@ -449,38 +685,7 @@ 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+/
currOp = tempstr.idup;
/+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;
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];


}+/
currOp = tempstr.idup;
}
}
while(i < def.length);
Expand Down Expand Up @@ -525,9 +730,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. The substitution is done at registration, it should execute fine.
//def = "x1*f(x1,x2)(Number)"d;
//assert(registerFunction(func, def));
}

/************************************
Expand Down Expand Up @@ -580,7 +785,7 @@ import std.typecons : Tuple;
/***********************************************************
* Executes a function.
*
* TODO: Actually write the function.
* TODO:
* Params:
* func =
* The function to execute.
Expand Down