From b3950dcd62f9888f1d5b5fe0f71a44632876e71c Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Sat, 4 Oct 2025 14:54:32 +1000 Subject: [PATCH] file library --- docs/syntax.md | 38 +++++++++++++++- src/defs/defs.cpp | 1 + src/defs/defs.h | 2 +- src/executor/executor.cpp | 6 +++ src/modules/file/file.cpp | 90 +++++++++++++++++++++++++++++++++++++ src/modules/file/file.h | 8 ++++ src/modules/print/print.cpp | 3 +- 7 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 src/modules/file/file.cpp create mode 100644 src/modules/file/file.h diff --git a/docs/syntax.md b/docs/syntax.md index 61149b8..fcaf14c 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -179,4 +179,40 @@ fun myFunc { let result = (myFunc) println $result # Prints "doing stuff..." and then "done" -``` \ No newline at end of file +``` + +## File I/O + +### file + +The `file` module contains many submodules for reading from and writing to files. + +#### file read + +Reads an entire file. Returns a string. + +Example: `file read "myFile.txt"` + +#### file readlines + +Reads an entire file. Returns a list of strings, split by the line. + +Example: `file readlines "myFile.txt"` + +#### file exists + +Determines whether or not a file exists on the system. If yes, returns "true". If not, returns "false". + +Example: `file exists "myFile.txt"` + +#### file write + +Overwrites a file with content provided. This is destructive, be careful! + +Example: `file write "myFile.txt" "Hello from the file!"` + +#### file append + +Appends text to the end of a file. + +Example: `file append "myFile.txt" "Hello from the end of the file!"` diff --git a/src/defs/defs.cpp b/src/defs/defs.cpp index 186dce7..20be709 100644 --- a/src/defs/defs.cpp +++ b/src/defs/defs.cpp @@ -20,6 +20,7 @@ InstructionType strToInstructionType(std::string in) { else if (in == "return") return InstructionType::Return; else if (in == "concat") return InstructionType::Concat; else if (in == "split") return InstructionType::Split; + else if (in == "file") return InstructionType::File; else return InstructionType::Variable; } diff --git a/src/defs/defs.h b/src/defs/defs.h index 90e3cff..4e81cd2 100644 --- a/src/defs/defs.h +++ b/src/defs/defs.h @@ -6,7 +6,7 @@ enum class InstructionType { - None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Return, Concat, Split + None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Return, Concat, Split, File }; enum class ValueType { diff --git a/src/executor/executor.cpp b/src/executor/executor.cpp index 1b43b3a..0d59e6e 100644 --- a/src/executor/executor.cpp +++ b/src/executor/executor.cpp @@ -15,6 +15,8 @@ #include "../modules/input/input.h" #include "../modules/function/function.h" #include "../modules/split/split.h" +#include "../modules/concat/concat.h" +#include "../modules/file/file.h" // Forward declaration for mutual recursion Value evaluate(Value val); @@ -146,6 +148,10 @@ Value execute(Instruction inst) { return modules::input(inst.args); case InstructionType::Split: return modules::split(inst.args); + case InstructionType::Concat: + return modules::concat(inst.args); + case InstructionType::File: + return modules::file(inst.args); case InstructionType::Exit: return modules::exit(inst.args); case InstructionType::Return: { diff --git a/src/modules/file/file.cpp b/src/modules/file/file.cpp new file mode 100644 index 0000000..d8bac8c --- /dev/null +++ b/src/modules/file/file.cpp @@ -0,0 +1,90 @@ +#include "file.h" +#include "../../defs/defs.h" +#include "../../error/error.h" +#include +#include + +Value modules::file(std::vector args) { + if (args.size() < 2) { + error("Not enough args for file module"); + return Value("Error"); + } + if (args[1].valtype != ValueType::String) { + error("Expecting a string to identify file to open"); + return Value("Error"); + } + if (args[0].valtype == ValueType::Identifier) { + if (args[0].string_val == "read") { + std::ifstream file(args[1].string_val); + if (!file) { + error("File " + args[1].string_val + " does not exist (in file module)"); + return Value("Error"); + } + std::string buf; + std::string retval; + bool notfirst = false; + while (getline(file, buf)) { + if (notfirst) { + buf += "\n"; + } else { + notfirst = true; + } + retval += buf; + } + file.close(); + return Value(retval); + } else if (args[0].string_val == "readlines") { + std::ifstream file(args[1].string_val); + if (!file) { + error("File " + args[1].string_val + " does not exist (in file module)"); + return Value("Error"); + } + std::string buf; + std::vector retval; + while (getline(file, buf)) { + retval.push_back(Value(buf)); + } + file.close(); + return Value(retval); + } else if (args[0].string_val == "exists") { + if (std::ifstream(args[1].string_val)) { + return Value("true"); + } else { + return Value("false"); + } + } else if (args[0].string_val == "write") { + if (args.size() < 3) { + error("Not enough args for write submodule of file module"); + return Value("Error"); + } + if (args[2].valtype != ValueType::String) { + error("Expecting a string of content to write to file"); + return Value("Error"); + } + std::ofstream file(args[1].string_val, std::ofstream::trunc); + file << args[2].string_val; + file.close(); + return Value("true"); + } else if (args[0].string_val == "append") { + if (args.size() < 3) { + error("Not enough args for write submodule of file module"); + return Value("Error"); + } + if (args[2].valtype != ValueType::String) { + error("Expecting a string of content to write to file"); + return Value("Error"); + } + std::ofstream file(args[1].string_val, std::iostream::app); + file << args[2].string_val; + file.close(); + + } else { + error("Unknown submodule of file"); + return Value("Error"); + } + } else { + error("Expecting identifier of submodule in file module"); + return Value("Error"); + } + return Value("Error"); +} diff --git a/src/modules/file/file.h b/src/modules/file/file.h new file mode 100644 index 0000000..0e4c442 --- /dev/null +++ b/src/modules/file/file.h @@ -0,0 +1,8 @@ +#pragma once + +#include "../../defs/defs.h" +#include + +namespace modules { + Value file(std::vector args); +} diff --git a/src/modules/print/print.cpp b/src/modules/print/print.cpp index 4f3ebd4..b0d0e75 100644 --- a/src/modules/print/print.cpp +++ b/src/modules/print/print.cpp @@ -8,6 +8,7 @@ Value modules::print(std::vector values) { for (Value value : values) { switch (value.valtype) { + case ValueType::Identifier: case ValueType::String: std::cout << value.string_val; break; @@ -33,7 +34,7 @@ Value modules::print(std::vector values) { break; } default: - error("FIXME: Unhandled type in print module"); + error("FIXME: Unhandled type in print module.\nDebug info: \n" + value.toString()); break; }