diff --git a/README.md b/README.md index 4d325998e..30f823eea 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Procedures for each standard are provided by the following R7RS-style libraries: cmake -B build -DCMAKE_BUILD_TYPE=Release cd build make package -sudo apt install build/meevax_0.5.183_amd64.deb +sudo apt install build/meevax_0.5.184_amd64.deb ``` or @@ -122,9 +122,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.183.so` and executable `meevax` +| `all` | Build shared-library `libmeevax.0.5.184.so` and executable `meevax` | `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.183_amd64.deb` +| `package` | Generate debian package `meevax_0.5.184_amd64.deb` | `install` | Copy files into `/usr/local` directly ## Usage diff --git a/VERSION b/VERSION index 1db40e762..b626e785f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.183 +0.5.184 diff --git a/include/meevax/kernel/syntactic_environment.hpp b/include/meevax/kernel/syntactic_environment.hpp index a4a73af4c..b6a17f3ab 100644 --- a/include/meevax/kernel/syntactic_environment.hpp +++ b/include/meevax/kernel/syntactic_environment.hpp @@ -729,78 +729,6 @@ inline namespace kernel using pair::pair; - inline auto generate(object const& expression, - object const& bound_variables = nullptr, // list of - object const& free_variables = nullptr, - object const& continuation = list(make(instruction::stop)), - bool tail = false) -> object - { - if (expression.is()) /* -------------------------------------------- - * - * ( ...) syntax - * - * Note: In many dialects of Lisp, the empty list, (), is a legitimate - * expression evaluating to itself. In Scheme, it is an error. - * - * --------------------------------------------------------------------- */ - { - return cons(make(instruction::load_constant), nullptr, continuation); - } - else if (not expression.is()) /* ----------------------------------- - * - * R7RS 4.1.1. Variable references - * - * syntax - * - * An expression consisting of a variable (section 3.1) is a variable - * reference. The value of the variable reference is the value stored in - * the location to which the variable is bound. It is an error to - * reference an unbound variable. - * - * --------------------------------------------------------------------- */ - { - if (expression.is()) - { - return generator::reference(*this, expression, bound_variables, free_variables, continuation, tail); - } - else if (expression.is()) - { - if (let const& identity = std::as_const(*this).identify(expression, bound_variables, free_variables); identity != f) // The syntactic-closure is an alias - { - return generator::reference(*this, expression, bound_variables, free_variables, continuation, tail); - } - else - { - assert(car(expression).is()); - - return car(expression).as() - .compile(cddr(expression), - unify(caar(expression), bound_variables), - map([&](let const& free_variable) - { - return cons(free_variable, - make(bound_variables, free_variables)); - }, - cadr(expression) /* free-variables of syntactic-closure */, - free_variables), - continuation); - } - } - else // is - { - return cons(make(instruction::load_constant), expression, continuation); - } - } - else if (let const& identity = std::as_const(*this).identify(car(expression), bound_variables, free_variables); identity.is() and cdr(identity).is()) - { - return cdr(identity).as().generate(*this, cdr(expression), bound_variables, free_variables, continuation, tail); - } - else - { - return generator::call(*this, expression, bound_variables, free_variables, continuation, tail); - } - } - template inline auto compile(object const& expression, object const& bound_variables, @@ -923,6 +851,78 @@ inline namespace kernel return expander::call(*this, expression, bound_variables, free_variables); } + inline auto generate(object const& expression, + object const& bound_variables = nullptr, // list of + object const& free_variables = nullptr, + object const& continuation = list(make(instruction::stop)), + bool tail = false) -> object + { + if (expression.is()) /* -------------------------------------------- + * + * ( ...) syntax + * + * Note: In many dialects of Lisp, the empty list, (), is a legitimate + * expression evaluating to itself. In Scheme, it is an error. + * + * --------------------------------------------------------------------- */ + { + return cons(make(instruction::load_constant), nullptr, continuation); + } + else if (not expression.is()) /* ----------------------------------- + * + * R7RS 4.1.1. Variable references + * + * syntax + * + * An expression consisting of a variable (section 3.1) is a variable + * reference. The value of the variable reference is the value stored in + * the location to which the variable is bound. It is an error to + * reference an unbound variable. + * + * --------------------------------------------------------------------- */ + { + if (expression.is()) + { + return generator::reference(*this, expression, bound_variables, free_variables, continuation, tail); + } + else if (expression.is()) + { + if (let const& identity = std::as_const(*this).identify(expression, bound_variables, free_variables); identity != f) // The syntactic-closure is an alias + { + return generator::reference(*this, expression, bound_variables, free_variables, continuation, tail); + } + else + { + assert(car(expression).is()); + + return car(expression).as() + .compile(cddr(expression), + unify(caar(expression), bound_variables), + map([&](let const& free_variable) + { + return cons(free_variable, + make(bound_variables, free_variables)); + }, + cadr(expression) /* free-variables of syntactic-closure */, + free_variables), + continuation); + } + } + else // is + { + return cons(make(instruction::load_constant), expression, continuation); + } + } + else if (let const& identity = std::as_const(*this).identify(car(expression), bound_variables, free_variables); identity.is() and cdr(identity).is()) + { + return cdr(identity).as().generate(*this, cdr(expression), bound_variables, free_variables, continuation, tail); + } + else + { + return generator::call(*this, expression, bound_variables, free_variables, continuation, tail); + } + } + inline auto identify(object const& variable, object const& bound_variables, object const& free_variables) const -> object @@ -933,6 +933,12 @@ inline namespace kernel } else if (let const& x = assq(variable, free_variables); x != f) { + /* + If a macro transformer inserts a free reference to an identifier, + the reference refers to the binding that was visible where the + transformer was specified, regardless of any local bindings that + surround the use of the macro. + */ return cdr(x).as().inject(car(x), bound_variables); } else