From 52eae6b3e30bf65b851c4b92fce5db3f23b7cfa0 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sat, 28 Sep 2024 19:43:17 +0100 Subject: [PATCH] Port print and println to use tasks/continuations --- src/stdlib.cpp | 105 ++++++++++++++++++++++++++++++++----------------- src/valeri.cpp | 1 + 2 files changed, 70 insertions(+), 36 deletions(-) diff --git a/src/stdlib.cpp b/src/stdlib.cpp index 22632f7..edfde11 100644 --- a/src/stdlib.cpp +++ b/src/stdlib.cpp @@ -22,14 +22,48 @@ struct StdlibTaskEntry { StdlibTaskIdPtr task_ptr; }; +Result raise_task(const StackFrame& stack, StdlibTaskId task_id, + const Array& params) { + auto val = Value(TRY(Task::create((uint64_t)task_id, params))); + auto cont = Value(TRY(Continuation::create(val, stack))); + + return ERROR_OBJ(Raise, cont); +} + +Result raise_task(const StackFrame& stack, StdlibTaskId task_id, + const Value& param) { + Array params = TRY(Array::create()); + params = TRY(params.append(param)); + auto val = Value(TRY(Task::create((uint64_t)task_id, params))); + auto cont = Value(TRY(Continuation::create(val, stack))); + + return ERROR_OBJ(Raise, cont); +} + +Result task_return(const StackFrame& stack, uint64_t idx) { + auto result = TRY(stack.get(idx)); + if (!result.is()) return ERROR(TypeMismatch); + + const auto& task_result = *result.to(); + + auto error = TRY(task_result.error()); + + if (!error.is()) { + return ERROR_OBJ(TaskFailed, error); + } + + auto res = TRY(stack.set(0, TRY(task_result.result()))); + res = TRY(res.ret(0)); + + return res; +} + Result stdlib_unknown(const StackFrame& stack) { return ERROR(NotImplemented); } -Result stdlib_print(const StackFrame& stack) { - auto params = TRY(stack.get(0)); +Result tostring(const Value& params, bool newline = false) { auto size = TRY(params.size()); - String str = TRY(String::create("")); for (uint64_t i = 0; i < size; i++) { @@ -46,21 +80,36 @@ Result stdlib_print(const StackFrame& stack) { } } - TRY(print_string(str)); + if (newline) { + str = TRY(str.concat("\n")); + } - auto nil = Value(TRY(Nil::create())); - auto res = TRY(stack.set(0, nil)); + return str; +} - res = TRY(res.ret(0)); +Result stdlib_print(const StackFrame& stack) { + auto params = TRY(stack.get(0)); + auto stack_size = TRY(stack.size()); - return res; + if (stack_size > 1) { + return task_return(stack, 1); + } + + auto str = Value(TRY(tostring(params))); + + return raise_task(stack, StdlibTaskId::Print, str); } Result stdlib_println(const StackFrame& stack) { - auto res = TRY(stdlib_print(stack)); - std::cout << "\n"; + auto params = TRY(stack.get(0)); + auto stack_size = TRY(stack.size()); - return res; + if (stack_size > 1) { + return task_return(stack, 1); + } + + auto str = Value(TRY(tostring(params, true))); + return raise_task(stack, StdlibTaskId::Print, str); } Result stdlib_prn(const StackFrame& stack) { @@ -307,21 +356,7 @@ Result stdlib_raise(const StackFrame& stack) { auto stack_size = TRY(stack.size()); if (stack_size > 1) { - auto result = TRY(stack.get(1)); - if (!result.is()) return ERROR(TypeMismatch); - - const auto& task_result = *result.to(); - - auto error = TRY(task_result.error()); - - if (!error.is()) { - return ERROR_OBJ(TaskFailed, error); - } - - auto res = TRY(stack.set(0, TRY(task_result.result()))); - res = TRY(res.ret(0)); - - return res; + return task_return(stack, 1); } auto params = TRY(stack.get(0)); @@ -347,7 +382,8 @@ Result stdlib_task(const StackFrame& stack) { Value task_params = TRY(params_array.slice(1, size)); - auto val = Value(TRY(Task::create((uint64_t)task_id.to()->value(), *task_params.to()))); + auto val = Value(TRY(Task::create((uint64_t)task_id.to()->value(), + *task_params.to()))); auto res = TRY(stack.set(0, val)); @@ -389,7 +425,8 @@ Result stdlib_task_print(const Array& params) { auto size = TRY(params.size()); if (size != 1) { - auto err = Value(TRY(Error::create("argument-count-mismatch", "Argument count mismatch"))); + auto err = Value(TRY( + Error::create("argument-count-mismatch", "Argument count mismatch"))); return ERROR_OBJ(ArgumentCountMismatch, err); } @@ -404,15 +441,13 @@ Result stdlib_task_print(const Array& params) { return Value(TRY(Nil::create())); } -#define STDLIB_TASK(name, id) \ - [(uint64_t)StdlibTaskId::id] = {#name, StdlibTaskId::id, \ - stdlib_task_##name} +#define STDLIB_TASK(name, id) \ + [(uint64_t)StdlibTaskId::id] = {#name, StdlibTaskId::id, stdlib_task_##name} static StdlibTaskEntry task_entries[] = { STDLIB_TASK(unknown, Unknown), STDLIB_TASK(print, Print), - [(uint64_t)StdlibTaskId::Max] = {0, StdlibTaskId::Max, - stdlib_task_unknown}, + [(uint64_t)StdlibTaskId::Max] = {0, StdlibTaskId::Max, stdlib_task_unknown}, }; // TODO: this just scans through the array of functions linearly every time. @@ -466,7 +501,6 @@ Result get_stdlib_function_name(StdlibFunctionId fun_id) { return function_entries[(uint64_t)fun_id].name; } - StdlibTaskEntry get_task_entry(const char* name) { for (uint64_t i = 1; i < (uint64_t)StdlibTaskId::Max; i++) { if (strcmp(task_entries[i].name, name) == 0) { @@ -497,8 +531,7 @@ Result get_stdlib_task(const Symbol& name) { return task_id; } -Result call_stdlib_task(StdlibTaskId fun_id, - const Array& params) { +Result call_stdlib_task(StdlibTaskId fun_id, const Array& params) { if (fun_id == StdlibTaskId(0) || fun_id >= StdlibTaskId::Max) { return ERROR(KeyError); } diff --git a/src/valeri.cpp b/src/valeri.cpp index de5ffcc..948a8e3 100644 --- a/src/valeri.cpp +++ b/src/valeri.cpp @@ -103,6 +103,7 @@ Result run_repl() { auto backtrace = TRY(vm.backtrace(2)); print_error(maybe_res, backtrace); } + std::cout << std::flush; } return Result();