xo-reader: handle sequence with embedded local vars
This commit is contained in:
parent
dad6b2562c
commit
7fad60290d
5 changed files with 225 additions and 8 deletions
57
include/xo/reader/let1_xs.hpp
Normal file
57
include/xo/reader/let1_xs.hpp
Normal 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 */
|
||||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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
116
src/reader/let1_xs.cpp
Normal 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 */
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue