xo-reader xo-expression: nested lambdas working properly + docs

This commit is contained in:
Roland Conybeare 2025-07-06 14:13:44 -05:00
commit d46c3a2082
26 changed files with 534 additions and 94 deletions

View file

@ -5,11 +5,15 @@
#pragma once
xxx;
#include "xo/expression/Variable.hpp"
#include "xo/expression/LocalEnv.hpp"
#include <vector>
namespace xo {
namespace scm {
#ifdef OBSOLETE
/** @class envframe
* @brief names/types of formal paremeters introduced by a function
*
@ -17,26 +21,31 @@ namespace xo {
**/
class envframe {
public:
using Variable = xo::ast::Variable;
using Environment = xo::ast::Environment;
using LocalEnv = xo::ast::LocalEnv;
using Variable = xo::ast::Variable;
public:
envframe() = default;
envframe(const std::vector<rp<Variable>> & argl) : argl_(argl) {}
envframe(const std::vector<rp<Variable>> & argl, const rp<Environment> & parent_env);
const std::vector<rp<Variable>> & argl() const { return argl_; }
const std::vector<rp<Variable>> & argl() const { return env_->argv(); }
const rp<LocalEnv> & local_env() const { return env_; }
/** lookup variable by @p name. If found, return it.
* Otherwise return nullptr
**/
rp<Variable> lookup(const std::string & name) const;
bp<Variable> lookup(const std::string & name) const;
/** establish (replacing if already exists) binding for variable @p var **/
/** establish (replacing if already exists) binding for variable @p var.
* Replacement intended for use in interactive sessions
**/
void upsert(bp<Variable> var);
void print (std::ostream & os) const;
private:
std::vector<rp<Variable>> argl_;
rp<LocalEnv> env_;
};
inline std::ostream &
@ -44,6 +53,7 @@ namespace xo {
x.print(os);
return os;
}
#endif
} /*namespace scm*/
} /*namespace xo*/

View file

@ -5,7 +5,7 @@
#pragma once
#include "envframe.hpp"
#include "xo/expression/LocalEnv.hpp"
namespace xo {
namespace scm {
@ -14,6 +14,7 @@ namespace xo {
**/
class envframestack {
public:
using LocalEnv = xo::ast::LocalEnv;
using Variable = xo::ast::Variable;
public:
@ -26,40 +27,40 @@ namespace xo {
* Visit frames in fifo order, report first match;
* nullptr if no matches.
**/
rp<Variable> lookup(const std::string & x) const;
bp<Variable> lookup(const std::string & x) const;
/** update/replace binding for variable @p target.
* New binding may have a different type.
**/
void upsert(bp<Variable> target);
envframe & top_envframe();
void push_envframe(envframe x);
void pop_envframe();
bp<LocalEnv> top_envframe();
void push_envframe(const rp<LocalEnv> & x);
rp<LocalEnv> pop_envframe();
/** relative to top-of-stack.
* 0 -> top (last in), z-1 -> bottom (first in)
**/
envframe & operator[](std::size_t i) {
bp<LocalEnv> operator[](std::size_t i) {
std::size_t z = stack_.size();
assert(i < z);
return stack_[z - i - 1];
return stack_[z - i - 1].get();
}
const envframe & operator[](std::size_t i) const {
bp<LocalEnv> operator[](std::size_t i) const {
std::size_t z = stack_.size();
assert(i < z);
return stack_[z - i - 1];
return stack_[z - i - 1].get();
}
void print (std::ostream & os) const;
private:
std::vector<envframe> stack_;
std::vector<rp<LocalEnv>> stack_;
};
inline std::ostream &

View file

@ -6,6 +6,7 @@
#pragma once
#include "exprstate.hpp"
#include "xo/expression/LocalEnv.hpp"
//#include <cstdint>
namespace xo {
@ -46,6 +47,10 @@ namespace xo {
*
**/
class lambda_xs : public exprstate {
public:
using Environment = xo::ast::Environment;
using LocalEnv = xo::ast::LocalEnv;
public:
lambda_xs();
@ -71,11 +76,15 @@ namespace xo {
/** parsing state-machine state **/
lambdastatetype lmxs_type_ = lambdastatetype::lm_0;
/** formal parameter list **/
std::vector<rp<Variable>> argl_;
/** lambda environment (for formal parameters) **/
rp<LocalEnv> local_env_;
/** body expression **/
rp<Expression> body_;
/** parent environment **/
rp<Environment> parent_env_;
};
} /*namespace scm*/
} /*namespace xo*/

View file

@ -6,14 +6,17 @@
#pragma once
#include "exprstate.hpp"
#include "xo/expression/LocalEnv.hpp"
namespace xo {
namespace scm {
class let1_xs : public exprstate {
public:
using LocalEnv = xo::ast::LocalEnv;
public:
/** given local definition equivalent to
* def lhs_name = rhs
* def lhs_name = rhs;
* rest...
* parse sequence of incoming expressions rest... (until '}')
*
@ -27,21 +30,27 @@ namespace xo {
virtual void on_expr(bp<Expression> expr,
parserstatemachine * p_psm) override;
virtual void on_expr_with_semicolon(bp<Expression> expr,
parserstatemachine * p_psm) override;
virtual void on_rightbrace_token(const token_type & tk,
parserstatemachine * p_psm) override;
private:
let1_xs(std::string lhs_name,
rp<LocalEnv> local_env,
rp<Expression> rhs);
/** named ctor idiom **/
static std::unique_ptr<let1_xs> make(std::string lhs_name,
rp<LocalEnv> local_env,
rp<Expression> rhs);
private:
/** name for new local variable **/
std::string lhs_name_;
/** environment. contains just @ref lhs_name_ **/
rp<LocalEnv> local_env_;
/** set initial value for @ref lhs_name_ from value of this expression **/
rp<Expression> rhs_;

View file

@ -21,6 +21,7 @@ namespace xo {
public:
using Expression = xo::ast::Expression;
using Variable = xo::ast::Variable;
using LocalEnv = xo::ast::LocalEnv;
using token_type = token<char>;
public:
@ -38,15 +39,17 @@ namespace xo {
/** lookup variable name in lexical context represented by
* this psm. nullptr if not found
**/
rp<Variable> lookup_var(const std::string & x) const;
bp<Variable> lookup_var(const std::string & x) const;
/** update/replace binding for variable @p x in lexical context
* represented by this psm. Always acts on innermost frame.
**/
void upsert_var(bp<Variable> x);
void push_envframe(envframe x);
void pop_envframe();
bp<LocalEnv> top_envframe() const;
void push_envframe(const rp<LocalEnv> & x);
rp<LocalEnv> pop_envframe();
size_t env_stack_size() const { return p_env_stack_->size(); }
// ----- parsing outputs -----

View file

@ -51,6 +51,9 @@ namespace xo {
* Handles an expression that produces a value, for example appearing on the
* right-hand side of a definition.
*
* Deals with infix operators, handles operator precedence.
* Also generates argument-type-specific arithmetic expressions,
* for example using ``Apply::make_add2_f64()`` when adding floating-point numbers
**/
class progress_xs : public exprstate {
public:
@ -71,6 +74,8 @@ namespace xo {
virtual void on_expr(bp<Expression> expr,
parserstatemachine * p_psm) override;
virtual void on_expr_with_semicolon(bp<Expression> expr,
parserstatemachine * p_psm) override;
virtual void on_symbol_token(const token_type & tk,
parserstatemachine * p_psm) override;
virtual void on_typedescr(TypeDescr td,