From 9d3f7ae6269da091b9042211be20cb0077d71147 Mon Sep 17 00:00:00 2001 From: Hisashi Horikawa Date: Sun, 8 Sep 2024 15:26:51 +0900 Subject: [PATCH] EVAL() fixed. --- README.md | 26 +++++++++++--------------- environment.cpp | 7 ++++++- evaluation.cpp | 23 ++++++++++++++++++----- test/evaluation_test.cpp | 13 +++++++++---- 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index f5541ee..5b436fe 100644 --- a/README.md +++ b/README.md @@ -16,33 +16,29 @@ C++17 - REPL Read-Eval-Print-Loop + ✅ GNU Readline はライセンスが GPLv3 なので使えない。libedit-devel を利用 - - Reader, Print - + ✅ ファイルからの読み込み `READ()` 関数, S式の構築、画面への表示 `PRINT()` 関数 - - 文法をユーザが拡張できるので, bison/flex は使えない。手書き。 + - Reader, Print -- ファイルからの読み込み `READ()` 関数, S式の構築、画面への表示 `PRINT()` 関数. 文法をユーザが拡張できるので, bison/flex は使えない。手書き。 + ✅ Standard Macro Characters + reader macro + Sharpsign (dispatching macro character) - `simple-vector` - - Environments + - Environment + ✅ 変数定義. `SETQ` - + レキシカルスコープ. `LET`, `LET*` - + ビルトイン関数 - + ✅ 関数呼び出し. Function `FUNCALL` + + ✅ レキシカルスコープ. `LET`, `LET*` + + ✅ ビルトイン関数の登録 - - Eval - + `EVAL()` をつくる - + atom の評価 + - Eval -- `EVAL()` が AST を評価. + + ✅ 関数呼び出し. Function `FUNCALL` + + ✅ atom の評価 + `lambda` 式からクロージャをつくる + ユーザ定義関数 - - - Special operator `IF`, macro `DO` - - - Tail Call Optimization (TCO) + + ✅ Special operator `IF` + + macro `DO` + + ✅ Tail Call Optimization (TCO) - Files - - ✅ Quoting `QUOTE` + - Quoting `QUOTE` - Macros + Backquote `quasiquote`, Comma `unquote`, `,@` `unquote-splicing` diff --git a/environment.cpp b/environment.cpp index a12bee1..c8396a0 100644 --- a/environment.cpp +++ b/environment.cpp @@ -5,6 +5,7 @@ #include #include #include +#include using namespace icu; namespace my { @@ -90,9 +91,13 @@ FuncPtr Environment::find_function(const UnicodeString& symbol) throw std::invalid_argument(symbol.toUTF8String(u) ); } + extern void PRINT(const value_t& value, std::ostream& out); -void Environment::set_value(const UnicodeString& symbol, const value_t& value, bool constant) +void Environment::set_value(const UnicodeString& symbol, const value_t& value, + bool constant) { + std::cout << __func__ << ": "; PRINT(value, std::cout); std::cout << "\n"; // DEBUG + m_values.insert(std::make_pair(symbol, BoundValue { .val = value, .constant = constant})); } diff --git a/evaluation.cpp b/evaluation.cpp index 055394a..590b7d0 100644 --- a/evaluation.cpp +++ b/evaluation.cpp @@ -4,15 +4,21 @@ #include "s_expr.h" #include "environment.h" +#include namespace my { value_t EVAL(value_t ast, EnvPtr env); -// そのまま返す -static value_t eval_atom(const value_t& ast, EnvPtr env) +static value_t eval_atom(const value_t& atom, EnvPtr env) { - return ast; + std::shared_ptr sym = OBJECT_CAST(atom); + if (sym != nullptr) { + return env->find_value(sym->name()); + } + + // そのまま返す + return atom; } @@ -195,10 +201,13 @@ static Trampoline do_let_star(std::shared_ptr form, EnvPtr env) return Trampoline(Trampoline::MORE, make_progn(form->sub(2)), inner); // TCO } +extern void PRINT(const value_t& value, std::ostream& out); // lambda form と (function ...) と共用 static FuncPtr get_function(const value_t& func_name, EnvPtr env) { + std::cout << __func__ << ": "; PRINT(func_name, std::cout); std::cout << "\n"; // DEBUG + std::shared_ptr sym = OBJECT_CAST(func_name); if (sym) { // 1. (funcall #'+ 1 2 3) => 6 @@ -264,8 +273,8 @@ static const SpecialForm specialForms[] = { // {"labels", }, // {"macrolet", do_macrolet}, // define local macros {"FUNCTION", do_function}, - {"let", do_let_star}, // `let` performs the bindings in parallel - {"let*", do_let_star}, // `let*` does them sequentially + {"LET", do_let_star}, // `let` performs the bindings in parallel + {"LET*", do_let_star}, // `let*` does them sequentially // {"progv", }, {"SETQ", do_setq}, //{"block", }, @@ -306,6 +315,8 @@ value_t macroExpand(const value_t& ast, EnvPtr env) { */ static ListPtr eval_args(ListPtr args, EnvPtr env) { + std::cout << __func__ << ": "; PRINT(args, std::cout); std::cout << "\n"; // DEBUG + if (args->length() == 0) return nilValue; @@ -320,6 +331,8 @@ static ListPtr eval_args(ListPtr args, EnvPtr env) value_t EVAL(value_t ast, EnvPtr env) { while (true) { + std::cout << "EVAL() loop: "; PRINT(ast, std::cout); std::cout << "\n"; // DEBUG + ListPtr list = OBJECT_CAST(ast); if (!list || list->empty() ) return eval_atom(ast, env); diff --git a/test/evaluation_test.cpp b/test/evaluation_test.cpp index 6d0fca7..f23e6e1 100644 --- a/test/evaluation_test.cpp +++ b/test/evaluation_test.cpp @@ -1,10 +1,12 @@ #include "../environment.h" #include +#include namespace my { extern value_t EVAL(value_t ast, EnvPtr env); extern bool value_isTrue(const value_t& value) ; + extern void PRINT(const value_t& value, std::ostream& out); } my::value_t func1(my::EnvPtr args) { @@ -17,8 +19,11 @@ my::value_t func1(my::EnvPtr args) { my::value_t func2(my::EnvPtr args) { my::value_t x = args->find_value("X"); - int64_t v = std::get(x); - printf("func2: %ld\n", v); + + std::cout << __func__ << ": "; PRINT(x, std::cout); std::cout << "\n"; // DEBUG + + double v = std::get(x); + printf("func2: %f\n", v); return x; } @@ -35,8 +40,8 @@ my::value_t do_not(my::EnvPtr args) { // Function WRITE, PRIN1, PRINT, PPRINT, PRINC my::value_t do_print(my::EnvPtr args) { my::value_t x = args->find_value("X"); - int64_t v = std::get(x); - printf("%ld\n", v); + double v = std::get(x); + printf("%f\n", v); return my::nilValue; }