From 09033cd43228b5b9e522d45948c66ae08bc9dd0f Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Mon, 11 Aug 2025 10:07:05 +1000 Subject: [PATCH] More stuff --- docs/syntax.md | 26 ++++++++++-- src/main.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++- tests/everything.grnd | 89 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 tests/everything.grnd diff --git a/docs/syntax.md b/docs/syntax.md index caed299..fc8a810 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -134,7 +134,7 @@ Appends an item to a list. Usage: `listappend *list $var` -### String Operations (ALL WORK IN PROGRESS) +### String Operations #### getstrsize @@ -200,7 +200,7 @@ Checks if the left value is lesser than the right value. Outputs a boolean to a Usage: `lesser $value $value &var` -### Type Conversions +### Type Conversions (ALL WORK IN PROGRESS) #### stoi @@ -248,6 +248,24 @@ Usage: `pusharg $value` #### call -Calls a function, with all the arguments in the argument list. +Calls a function, with all the arguments in the argument list. The return value will be put in the specified variable. -Usage: `call !function` \ No newline at end of file +Usage: `call !function &var + +### Interacting with Libraries (ALL WORK IN PROGRESS) + +#### use + +Attempts to import another Ground program. Gets inserted wherever the use statement is. Any code (including code outside function declarations) will be executed. + +Note: Ground will check the directory where the program is stored when trying to find imported programs. If that fails, it will check the directory set in the $GROUND_PATH environment variable set by your system. The '.grnd' extension is appended automatically. + +Usage: `use $stringvalue` + +#### extern + +Attempts to import a shared object library written for Ground. All functions in the external library will be usable with `call`. + +Note: Ground will check the directory where the program is stored when trying to find external programs. If that fails, it will check the directory set in the $GROUND_PATH environment variable set by your system. The '.so', '.dll', etc extension is appended automatically. + +Usage: `extern $stringvalue` \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 54ab8f3..98c5c55 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,7 +54,10 @@ enum class Instructions { Add, Subtract, Multiply, Divide, Equal, Inequal, Greater, Lesser, End, Set, Empty, - Setlist, Getlistat, Setlistat, Getlistsize, Listappend, Listprepend + Setlist, Getlistat, Setlistat, Getlistsize, Listappend, Listprepend, + Getstrcharat, Getstrsize, + Stoi, Stod, tostring, + Fun, Endfun, Pusharg, Call }; /* @@ -531,6 +534,55 @@ void exec(vector in) { } } break; + /* + getstrcharat instruction + This instruction gets a character from a string at an index and saves it + to a variable. + */ + case Instructions::Getstrcharat: + if (l.args.size() < 3) { + error("Could not find all arguments required for Getstrcharat inbuilt"); + } + { + string instr; + int ref; + Direct var; + + if (holds_alternative(l.args[0])) { + if (holds_alternative(get(l.args[0]).val)) { + instr = get(get(l.args[0]).val); + } else { + error("First argument of getlistat must be a string literal"); + } + } else { + error("First argument of getlistat must be a string literal"); + } + + if (holds_alternative(l.args[1])) { + if (holds_alternative(get(l.args[1]).val)) { + ref = get(get(l.args[1]).val); + } else { + error("Second argument of getlistat must be an integer literal"); + } + } else { + error("Second argument of getlistat must be an integer literal"); + } + + if (holds_alternative(l.args[2])) { + var = get(l.args[2]); + } else { + error("Third argument of getlistat must be a direct reference"); + } + + if (instr.size() > ref) { + Literal newLit; + newLit.val = instr[ref]; + variables[var.varName] = newLit; + } else { + error("Index " + to_string(ref) + " out of range of string " + instr); + } + } + break; /* setlistat instruction This instruction sets an item in a list to be a certain value. @@ -643,6 +695,40 @@ void exec(vector in) { break; } /* + getstrsize instruction + This instruction saves the size of a string in a variable. + */ + case Instructions::Getstrsize: + if (l.args.size() < 2) { + error("Could not find all arguments required for Getstrsize inbuilt"); + } + { + string ref; + Direct var; + + if (holds_alternative(l.args[0])) { + if (holds_alternative(get(l.args[0]).val)) { + ref = get(get(l.args[0]).val); + } else { + error("First argument of getlistsize must be a string value"); + } + } else { + error("First argument of getlistsize must be a string value"); + } + + if (holds_alternative(l.args[1])) { + var = get(l.args[1]); + } else { + error("Second argument of getlistsize must be a direct reference"); + } + + Literal newLit; + newLit.val = int(ref.size()); + variables[var.varName] = newLit; + + break; + } + /* stdin instruction This instruction takes input from the standard character input via the C++ getline() function, and saves it to a variable. @@ -705,6 +791,12 @@ void exec(vector in) { final.val = get(left.val) + double(get(right.val)); } else if (holds_alternative(left.val) && holds_alternative(right.val)) { final.val = get(left.val) + get(right.val); + } else if (holds_alternative(left.val) && holds_alternative(right.val)) { + final.val = get(left.val).append(&get(right.val)); + } else if (holds_alternative(left.val) && holds_alternative(right.val)) { + final.val = string().append(&get(left.val)) + get(right.val); + } else if (holds_alternative(left.val) && holds_alternative(right.val)) { + final.val = string().append(&get(left.val)).append(&get(right.val)); } else { error("Cannot add those two values"); } @@ -1267,6 +1359,9 @@ vector parser(vector> in) { else if (i == "setlistat") newInst.inst = Instructions::Setlistat; else if (i == "getlistat") newInst.inst = Instructions::Getlistat; else if (i == "getlistsize") newInst.inst = Instructions::Getlistsize; + else if (i == "listappend") newInst.inst = Instructions::Listappend; + else if (i == "getstrsize") newInst.inst = Instructions::Getstrsize; + else if (i == "getstrcharat") newInst.inst = Instructions::Getstrcharat; else error("Unexpected token: " + i); } else { Types type = getType(i); diff --git a/tests/everything.grnd b/tests/everything.grnd new file mode 100644 index 0000000..741fae1 --- /dev/null +++ b/tests/everything.grnd @@ -0,0 +1,89 @@ +# I/O + +stdlnout "Hello there!" +stdout "What is your name? " +stdin &name +add "Hello, " $name &out +stdlnout $out + +# Types +stdlnout "dingus" +stdlnout 7 +stdlnout 3.14159 +stdlnout true +stdlnout 'e' + +# Variables + +set &testVar "This is a test" +stdlnout $testVar + +# Lists + +setlist *testList "Item 1" "Another Item" "Item the Third" +getlistat *testList 2 &tmp +stdlnout $tmp + +setlistat *testList 1 "I changed this item" +getlistat *testList 1 &tmp +stdlnout $tmp + +listappend *testList "I appended this item" +getlistat *testList 3 &tmp +stdlnout $tmp + +getlistsize *testList &tmp +stdlnout $tmp + +# String Operations + +set &testStr "dingus" + +getstrsize $testStr &tmp +stdlnout $tmp + +getstrcharat $testStr 3 &tmp +stdlnout $tmp + +# Maths + +add 1 1 &tmp +stdlnout $tmp + +subtract 10 5 &tmp +stdlnout $tmp + +multiply 15 15 &tmp +stdlnout $tmp + +divide 36 4 &tmp +stdlnout $tmp + +# Comparisons + +equal 5 5 &tmp +stdlnout $tmp + +inequal 5 5 &tmp +stdlnout $tmp + +greater 10 5 &tmp +stdlnout $tmp + +lesser 10 5 &tmp +stdlnout $tmp + +# Control flow + +set &counter 0 + +@myLabel +add $counter 1 &counter +stdlnout $counter +inequal $counter 10 &case +if $case %myLabel + +# That's it! + +stdlnout "Everything ran! Check the output to see if it is what is expected." +end 0