From dbf52344ae5e370f5e2e140ed57e37008aea2248 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sun, 18 Aug 2024 20:01:40 +0100 Subject: [PATCH] Implement reading of code from files in the entry point --- CMakeLists.txt | 2 ++ README.md | 2 +- example.vli | 3 +++ src/common.hpp | 5 +++-- src/error.hpp | 1 + src/fio.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/fio.hpp | 7 +++++++ src/vli.cpp | 29 ++++++++++++++++++++++------- 8 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 example.vli create mode 100644 src/fio.cpp create mode 100644 src/fio.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 852dea1..609e7be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ target_sources(vm_lib src/utf8.cpp src/compiler.cpp src/opcode.cpp + src/fio.cpp PUBLIC FILE_SET HEADERS @@ -37,6 +38,7 @@ target_sources(vm_lib src/utf8.hpp src/compiler.hpp src/opcode.hpp + src/fio.hpp ) add_executable(vli src/vli.cpp) diff --git a/README.md b/README.md index f3a78f5..4032411 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ To run: ```sh cmake . make -./vli +./vli example.vli ``` To run tests: diff --git a/example.vli b/example.vli new file mode 100644 index 0000000..84dc672 --- /dev/null +++ b/example.vli @@ -0,0 +1,3 @@ +;; Check that lambdas can be passed as arguments + +((lambda (f y) (f y)) (lambda (x) (* x x)) 2) diff --git a/src/common.hpp b/src/common.hpp index 22b3ed3..a591b62 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -459,8 +459,7 @@ class String : public Object { return _value->data[idx]; } - Result concat(const char* rhs) { - uint64_t rhs_size = strlen(rhs); + Result concat(const char* rhs, uint64_t rhs_size) { uint64_t lhs_size = size(); uint64_t res_size = lhs_size + rhs_size; @@ -473,6 +472,8 @@ class String : public Object { return String(TRY(MkGcRoot(pod))); } + Result concat(const char* rhs) { return concat(rhs, strlen(rhs)); } + Result concat(const char32_t* rhs, uint64_t rhs_size) { uint64_t lhs_size = size(); uint64_t res_size = lhs_size + rhs_size; diff --git a/src/error.hpp b/src/error.hpp index f88fa4e..dced58c 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -15,6 +15,7 @@ enum class ErrorCode { EndOfProgram, CompilationError, ArgumentCountMismatch, + IOError, }; void seterr(const char* err); diff --git a/src/fio.cpp b/src/fio.cpp new file mode 100644 index 0000000..a343eea --- /dev/null +++ b/src/fio.cpp @@ -0,0 +1,39 @@ +#include "fio.hpp" + +#include + +Result read_fh(FILE* file) { + size_t chunk_size = 1024; + const size_t buf_size = chunk_size; + size_t pos = 0; + + char buf[chunk_size]; + + String res = TRY(String::create("")); + + while (1) { + size_t num_bytes = fread(&buf[pos], 1, chunk_size, file); + + if (ferror(stdin)) { + return ERROR(IOError); + } + res = TRY(res.concat(buf, num_bytes)); + if (num_bytes < chunk_size) break; + } + + return std::move(res); +} + +Result read_file(const char* filename) { + FILE* fh = fopen(filename, "r"); + + if (!fh) { + return ERROR(IOError); + } + + auto res = read_fh(fh); + fclose(fh); + return res; +} + +Result read_stdin() { return read_fh(stdin); } diff --git a/src/fio.hpp b/src/fio.hpp new file mode 100644 index 0000000..9129193 --- /dev/null +++ b/src/fio.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "common.hpp" + +Result read_file(const char* filename); + +Result read_stdin(); diff --git a/src/vli.cpp b/src/vli.cpp index cf0014e..3aaee7e 100644 --- a/src/vli.cpp +++ b/src/vli.cpp @@ -1,20 +1,35 @@ +#include + +#include #include #include "arena.hpp" #include "common.hpp" #include "compiler.hpp" +#include "die.hpp" +#include "fio.hpp" #include "reader.hpp" #include "vm.hpp" #include "writer.hpp" StaticArena<64 * 1024 * 1024> arena; -Result run() { - // auto code_str = TRY(String::create("(* (+ 1 2 3) (/ 4 2))")); - auto code_str = - TRY(String::create("((lambda (f y) (f y)) (lambda (x) (* x x)) 2)")); +Result run(int argc, const char* argv[]) { + String src = DIEX(String::create("")); + if (argc == 1) { + if (isatty(STDIN_FILENO)) { + die("Code expected at stdin, not a tty.\n"); + } + src = TRY(read_stdin()); + } else { + src = TRY(read_file(argv[1])); + } - auto parsed = TRY(read_one(code_str)); + // auto code_str = TRY(String::create("(* (+ 1 2 3) (/ 4 2))")); + // auto code_str = + // TRY(String::create("((lambda (f y) (f y)) (lambda (x) (* x x)) 2)")); + + auto parsed = TRY(read_one(src)); auto code_str_written = TRY(write_one(parsed)); TRY(arena_gc()); @@ -36,7 +51,7 @@ Result run() { return Result(); } -int main() { - DIEX(run()); +int main(int argc, const char* argv[]) { + DIEX(run(argc, argv)); return 0; }