xo-reader: handle sequence with embedded local vars

This commit is contained in:
Roland Conybeare 2024-08-23 10:52:51 -04:00
commit 7fad60290d
5 changed files with 225 additions and 8 deletions

View file

@ -0,0 +1,57 @@
/* file let1_xs.hpp
*
* author: Roland Conybeare, Aug 2024
*/
#pragma once
#include "exprstate.hpp"
namespace xo {
namespace scm {
class let1_xs : public exprstate {
public:
/** given local definition equivalent to
* def lhs_name = rhs
* rest...
* parse sequence of incoming expressions rest... (until '}')
*
* Result expression creates and inits @p lhs_name,
* then evaluates expressions that follow definition
* up to same-level '}'
**/
static void start(const std::string & lhs_name,
const rp<Expression> & rhs,
parserstatemachine * p_psm);
virtual void on_expr(ref::brw<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<Expression> rhs);
/** named ctor idiom **/
static std::unique_ptr<let1_xs> make(std::string lhs_name,
rp<Expression> rhs);
private:
/** name for new local variable **/
std::string lhs_name_;
/** set initial value for @ref lhs_name_ from value of this expression **/
rp<Expression> rhs_;
/** evaluate expressions in this sequence, in order, in environment
* with variable @ref lhs_name_ defined
**/
std::vector<rp<Expression>> expr_v_;
};
} /*namespace scm*/
} /*namespace xo*/
/* end let1_xs.hpp */

View file

@ -6,13 +6,22 @@
#pragma once
#include "exprstate.hpp"
#include <vector>
namespace xo {
namespace ast { class Sequence; }
namespace ast { class Lambda; }
namespace scm {
class sequence_xs : public exprstate {
public:
sequence_xs();
using Sequence = xo::ast::Sequence;
using Lambda = xo::ast::Lambda;
public:
/** start parsing a sequence-expr.
* input begins with first expression in the sequence.
**/
static void start(parserstatemachine * p_psm);
virtual void on_expr(ref::brw<Expression> expr,
@ -22,9 +31,13 @@ namespace xo {
parserstatemachine * p_psm) override;
private:
sequence_xs();
/** named ctor idiom **/
static std::unique_ptr<sequence_xs> make();
private:
/** will build SequenceExpr from in-order contents of this vector **/
std::vector<rp<Expression>> expr_v_;
};
} /*namespace scm*/

View file

@ -18,6 +18,7 @@ set(SELF_SRCS
expect_formal_arglist_xs.cpp
expect_type_xs.cpp
lambda_xs.cpp
let1_xs.cpp
envframestack.cpp
envframe.cpp)

116
src/reader/let1_xs.cpp Normal file
View file

@ -0,0 +1,116 @@
/* file let1_xs.cpp
*
* author: Roland Conybeare
*/
#include "let1_xs.hpp"
#include "expect_expr_xs.hpp"
#include "parserstatemachine.hpp"
#include "xo/expression/Sequence.hpp"
#include "xo/expression/DefineExpr.hpp"
#include "xo/expression/Apply.hpp"
#include "xo/expression/Lambda.hpp"
namespace xo {
using Sequence = xo::ast::Sequence;
using DefineExpr = xo::ast::DefineExpr;
using Apply = xo::ast::Apply;
using Lambda = xo::ast::Lambda;
using LambdaAccess = xo::ast::LambdaAccess;
using Variable = xo::ast::Variable;
namespace {
std::string gensym() {
return "genanotherxx";
}
}
namespace scm {
std::unique_ptr<let1_xs>
let1_xs::make(std::string lhs_name,
rp<Expression> rhs)
{
return std::make_unique<let1_xs>(let1_xs(std::move(lhs_name),
std::move(rhs)));
}
void
let1_xs::start(const std::string & lhs_name,
const rp<Expression> & rhs,
parserstatemachine * p_psm)
{
p_psm->push_exprstate(let1_xs::make(std::move(lhs_name),
std::move(rhs)));
expect_expr_xs::start(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
p_psm);
}
let1_xs::let1_xs(std::string lhs_name,
rp<Expression> rhs)
: lhs_name_{std::move(lhs_name)},
rhs_{std::move(rhs)}
{}
void
let1_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
ref::brw<DefineExpr> def_expr = DefineExpr::from(expr);
if (def_expr) {
/** nested_start: control returns via
* .on_expr(x)
* with x something like:
* Apply(Lambda(gensym(),
* [Variable(def_expr->lhs_name(),
* def_expr->valuetype())],
* body...))
* followed immediately by
* .on_rightbrace_token()
**/
let1_xs::start(def_expr->lhs_name(),
def_expr->rhs(),
p_psm);
} else {
this->expr_v_.push_back(expr.promote());
expect_expr_xs::start(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
p_psm);
}
}
void
let1_xs::on_rightbrace_token(const token_type & tk,
parserstatemachine * p_psm)
{
auto self = p_psm->pop_exprstate();
auto expr = Sequence::make(this->expr_v_);
std::string argname = gensym();
rp<Expression> lambda
= Lambda::make(this->lhs_name_,
{Variable::make(argname,
this->rhs_->valuetype())},
expr);
rp<Expression> result
= Apply::make(lambda, {this->rhs_});
p_psm->top_exprstate().on_expr(result, p_psm);
/* caller of let1_xs expects the same rightbrace '}'
* -- remember we pushed let1_xs to handle an embedded def-expr
* in a sequence
*/
p_psm->top_exprstate().on_rightbrace_token(tk, p_psm);
}
} /*namespace scm*/
} /*namespace xo*/
/* end let1_xs.cpp */

View file

@ -3,10 +3,12 @@
#include "sequence_xs.hpp"
#include "parserstatemachine.hpp"
#include "expect_expr_xs.hpp"
#include "let1_xs.hpp"
#include "xo/expression/DefineExpr.hpp"
#include "xo/expression/Sequence.hpp"
namespace xo {
using xo::ast::Sequence;
using xo::ast::DefineExpr;
namespace scm {
std::unique_ptr<sequence_xs>
@ -42,19 +44,47 @@ namespace xo {
*
* becomes:
*
* /-- .outer_seq_expr_
* v
* Sequence(
* ...prefix,
* Apply(Lambda(gen999, [Variable(lhs_name, type(rhs))], sequencify(rest...)),
*
* /-- .inner_lm_expr_
* v
* Apply(Lambda(gen999,
* [Variable(lhs_name, type(rhs))],
* /-- .expr_v_
* v
* sequencify(rest...)),
* rhs))
*
* so amongst other things,
* helpful to have nested seequence_xs that propagates '}' instead of swallowing it.
* helpful to have nested seequence_xs that propagates '}'
* instead of swallowing it.
*/
ref::brw<DefineExpr> def_expr = DefineExpr::from(expr);
this->expr_v_.push_back(expr.promote());
expect_expr_xs::start(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
p_psm);
if (def_expr) {
/** nested_start: control returns via
* .on_expr(x)
* with x something like:
* Apply(Lambda(gensym(),
* [Variable(def_expr->lhs_name(),
* def_expr->valuetype())],
* body...))
* followed immediately by
* .on_rightbrace_token()
**/
let1_xs::start(def_expr->lhs_name(),
def_expr->rhs(),
p_psm);
} else {
this->expr_v_.push_back(expr.promote());
expect_expr_xs::start(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
p_psm);
}
}
void