From c39967a72f28d747714a367d6f51127612267923 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Mon, 11 Aug 2025 14:12:25 +1000 Subject: [PATCH] Type conversion --- README.md | 2 +- docs/syntax.md | 2 +- src/main.cpp | 126 ++++++++++++++++++++++++++++++++++++++++++- tests/typeconvs.grnd | 10 ++++ 4 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 tests/typeconvs.grnd diff --git a/README.md b/README.md index a0f2dda..fc8881a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Ground is an interpreter which processes and interprets Ground instructions. It * **Simple syntax:** Ground doesn't have very many features, and that's intentional. It makes Ground easy to learn, and keeps it speedy. * **Super speed:** Ground code is faster than Python and JavaScript, and nearly as fast as C++ and Rust, while still being interpreted. (Tested using tests/to1000.grnd) -* **Tiny interpreter:** Ground contains 761 lines of code (and 233 lines of comments) at the time of writing, and compiles in seconds. +* **Tiny interpreter:** Ground contains 1154 lines of code (and 320 lines of comments) at the time of writing, and compiles in seconds. * **Portable:** Ground's code only uses features from the C++ standard library, using features from C++17 and prior. ## How do I get started? diff --git a/docs/syntax.md b/docs/syntax.md index fc8a810..aa4c20f 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -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 (ALL WORK IN PROGRESS) +### Type Conversions #### stoi diff --git a/src/main.cpp b/src/main.cpp index 98c5c55..319c312 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,7 +56,7 @@ enum class Instructions { End, Set, Empty, Setlist, Getlistat, Setlistat, Getlistsize, Listappend, Listprepend, Getstrcharat, Getstrsize, - Stoi, Stod, tostring, + Stoi, Stod, Tostring, Fun, Endfun, Pusharg, Call }; @@ -728,6 +728,127 @@ void exec(vector in) { break; } + /* + stoi instruction + This function converts a string to an int, and saves it in a variable. + If the string cannot be turned into an integer, there is an error. + */ + case Instructions::Stoi: + if (l.args.size() < 2) { + error("Could not find all arguments required for Stoi inbuilt"); + } + { + string toConv; + Direct ref; + + if (holds_alternative(l.args[0])) { + if (holds_alternative(get(l.args[0]).val)) { + toConv = get(get(l.args[0]).val); + } else { + error("First argument of stoi must be a string literal"); + } + } else { + error("First argument of stoi must be a string literal"); + } + + if (holds_alternative(l.args[1])) { + ref = get(l.args[1]); + } else { + error("Second argument of stoi must be a direct reference"); + } + + if (isInt(toConv)) { + Literal newLit; + newLit.val = stoi(toConv); + variables[ref.varName] = newLit; + } else { + error("Cannot convert the value " + toConv + " to an int"); + } + } + break; + /* + stod instruction + This function converts a string to a decimal, and saves it in a variable. + If the string cannot be turned into a decimal, there is an error. + */ + case Instructions::Stod: + if (l.args.size() < 2) { + error("Could not find all arguments required for Stod inbuilt"); + } + { + string toConv; + Direct ref; + + if (holds_alternative(l.args[0])) { + if (holds_alternative(get(l.args[0]).val)) { + toConv = get(get(l.args[0]).val); + } else { + error("First argument of stod must be a string literal"); + } + } else { + error("First argument of stod must be a string literal"); + } + + if (holds_alternative(l.args[1])) { + ref = get(l.args[1]); + } else { + error("Second argument of stod must be a direct reference"); + } + + if (isDouble(toConv) || isInt(toConv)) { + Literal newLit; + newLit.val = stod(toConv); + variables[ref.varName] = newLit; + } else { + error("Cannot convert the value " + toConv + " to a decimal"); + } + } + break; + /* + tostring instruction + This function converts any type to a string, and saves it in a variable. + */ + case Instructions::Tostring: + if (l.args.size() < 2) { + error("Could not find all arguments required for Tostring inbuilt"); + } + { + Literal toConv; + Direct ref; + + if (holds_alternative(l.args[0])) { + toConv = get(l.args[0]); + } else { + error("First argument of tostring must be a literal"); + } + + if (holds_alternative(l.args[1])) { + ref = get(l.args[1]); + } else { + error("Second argument of tostring must be a direct reference"); + } + + Literal newLit; + if (holds_alternative(toConv.val)) { + newLit.val = to_string(get(toConv.val)); + } else if (holds_alternative(toConv.val)) { + newLit.val = to_string(get(toConv.val)); + } else if (holds_alternative(toConv.val)) { + newLit.val = get(toConv.val); + } else if (holds_alternative(toConv.val)) { + newLit.val = string().append(&get(toConv.val)); + } else if (holds_alternative(toConv.val)) { + if (get(toConv.val)) { + newLit.val = "true"; + } else { + newLit.val = "false"; + } + } + + variables[ref.varName] = newLit; + + } + break; /* stdin instruction This instruction takes input from the standard character input via @@ -1362,6 +1483,9 @@ vector parser(vector> in) { 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 if (i == "stoi") newInst.inst = Instructions::Stoi; + else if (i == "stod") newInst.inst = Instructions::Stod; + else if (i == "tostring") newInst.inst = Instructions::Tostring; else error("Unexpected token: " + i); } else { Types type = getType(i); diff --git a/tests/typeconvs.grnd b/tests/typeconvs.grnd new file mode 100644 index 0000000..d6e6521 --- /dev/null +++ b/tests/typeconvs.grnd @@ -0,0 +1,10 @@ +stod "3.14" &out +stdlnout $out + +stoi "732" &out +add 1 $out &out +stdlnout $out + +tostring 3.14 &out +add $out " is a number of sorts" &out +stdlnout $out