162 lines
5.5 KiB
C++
162 lines
5.5 KiB
C++
/* 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::scm::Sequence;
|
|
using DefineExpr = xo::scm::DefineExpr;
|
|
using Apply = xo::scm::Apply;
|
|
using Lambda = xo::scm::Lambda;
|
|
using LambdaAccess = xo::scm::LambdaAccess;
|
|
using Environment = xo::scm::SymbolTable;
|
|
using LocalEnv = xo::scm::LocalSymtab;
|
|
using Variable = xo::scm::Variable;
|
|
|
|
namespace scm {
|
|
std::unique_ptr<let1_xs>
|
|
let1_xs::make(std::string lhs_name,
|
|
rp<LocalEnv> local_env,
|
|
rp<Expression> rhs)
|
|
{
|
|
return std::make_unique<let1_xs>(let1_xs(std::move(lhs_name),
|
|
std::move(local_env),
|
|
std::move(rhs)));
|
|
}
|
|
|
|
void
|
|
let1_xs::start(const std::string & lhs_name,
|
|
const rp<Expression> & rhs,
|
|
parserstatemachine * p_psm)
|
|
{
|
|
rp<SymbolTable> parent_env = p_psm->top_envframe().promote();
|
|
rp<Variable> var1 = Variable::make(lhs_name, rhs->valuetype());
|
|
rp<LocalEnv> let_env = LocalEnv::make1(var1, parent_env);
|
|
|
|
p_psm->push_envframe(let_env);
|
|
|
|
// TODO: stash let_env in let1_xs, then pick up directly in .on_rightbrace_token()
|
|
// still have to push here so vars can find it
|
|
//
|
|
p_psm->push_exprstate(let1_xs::make(lhs_name, let_env, rhs));
|
|
|
|
expect_expr_xs::start(true /*allow_defs*/,
|
|
true /*cxl_on_rightbrace*/,
|
|
p_psm);
|
|
}
|
|
|
|
let1_xs::let1_xs(std::string lhs_name,
|
|
rp<LocalEnv> local_env,
|
|
rp<Expression> rhs)
|
|
: exprstate(exprstatetype::let1expr),
|
|
lhs_name_{std::move(lhs_name)},
|
|
local_env_{std::move(local_env)},
|
|
rhs_{std::move(rhs)}
|
|
{}
|
|
|
|
void
|
|
let1_xs::on_expr(bp<Expression> expr,
|
|
parserstatemachine * p_psm)
|
|
{
|
|
constexpr bool c_debug_flag = true;
|
|
scope log(XO_DEBUG(c_debug_flag));
|
|
|
|
bp<DefineExpr> def_expr = DefineExpr::from(expr);
|
|
|
|
if (def_expr) {
|
|
/** starting a nested let here:
|
|
* 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_expr_with_semicolon(bp<Expression> expr,
|
|
parserstatemachine * p_psm)
|
|
{
|
|
/* same as on_expr(), since we only use let1_xs inside a block { .. }
|
|
* This means final ';' is unnecessary
|
|
*/
|
|
|
|
constexpr bool c_debug_flag = true;
|
|
scope log(XO_DEBUG(c_debug_flag));
|
|
|
|
bp<DefineExpr> def_expr = DefineExpr::from(expr);
|
|
|
|
if (def_expr) {
|
|
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_rightbvrace*/,
|
|
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_);
|
|
|
|
/* top env frame was established by let1_xs::start();
|
|
* now unwind it
|
|
*/
|
|
p_psm->pop_envframe();
|
|
|
|
std::string lambda_name = Variable::gensym("let1");
|
|
|
|
rp<SymbolTable> parent_env = p_psm->top_envframe().promote();
|
|
|
|
rp<Expression> lambda
|
|
= Lambda::make_from_env(lambda_name,
|
|
local_env_,
|
|
nullptr /*explicit_return_td*/,
|
|
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->on_rightbrace_token(tk);
|
|
}
|
|
} /*namespace scm*/
|
|
} /*namespace xo*/
|
|
|
|
|
|
/* end let1_xs.cpp */
|