xo-reader2: utest with variable reference. Works !

This commit is contained in:
Roland Conybeare 2026-02-16 23:25:34 -05:00
commit 57f6f9073e
5 changed files with 125 additions and 47 deletions

View file

@ -27,7 +27,7 @@ namespace xo {
Binding::print(std::ostream & os) const Binding::print(std::ostream & os) const
{ {
if (i_link_ == c_link_global) { if (i_link_ == c_link_global) {
os << "{path:global}"; os << "{path:global:" << j_slot_ << "}";
} else if (i_link_ == c_link_sentinel) { } else if (i_link_ == c_link_sentinel) {
os << "{path}"; os << "{path}";
} else { } else {

View file

@ -69,6 +69,8 @@ namespace xo {
DGlobalSymtab::upsert_variable(obj<AAllocator> mm, DGlobalSymtab::upsert_variable(obj<AAllocator> mm,
DVariable * var) DVariable * var)
{ {
scope log(XO_DEBUG(true), std::string_view(*var->name()));
// It's possible there's already a global variable // It's possible there's already a global variable
// with the same name. // with the same name.
// //
@ -78,6 +80,8 @@ namespace xo {
DVariable * existing = this->lookup_variable(var->name()); DVariable * existing = this->lookup_variable(var->name());
if (existing) { if (existing) {
log && log("variable with this symbol already exists");
if (existing == var) { if (existing == var) {
// impossible, but.. noop, right? // impossible, but.. noop, right?
return; return;
@ -91,6 +95,8 @@ namespace xo {
// //
(*vars_)[existing->path().j_slot()] = obj<AGCObject,DVariable>(var); (*vars_)[existing->path().j_slot()] = obj<AGCObject,DVariable>(var);
} else { } else {
log && log("variable is new");
DArray::size_type n = vars_->size(); DArray::size_type n = vars_->size();
// NOTE: expansion of var_ array here is moot at present (Feb 2026), // NOTE: expansion of var_ array here is moot at present (Feb 2026),
@ -146,8 +152,7 @@ namespace xo {
{ {
assert(sym); assert(sym);
scope log(XO_DEBUG(true), "stub"); scope log(XO_DEBUG(true), std::string_view(*sym));
log && log(xtag("sym", std::string_view(*sym)));
auto ix = map_->find(sym); auto ix = map_->find(sym);

View file

@ -11,6 +11,7 @@
#include "DIfElseSsm.hpp" #include "DIfElseSsm.hpp"
#include "ParenSsm.hpp" #include "ParenSsm.hpp"
#include "ExpectExprSsm.hpp" #include "ExpectExprSsm.hpp"
#include "VarRef.hpp"
#include <xo/expression2/DConstant.hpp> #include <xo/expression2/DConstant.hpp>
#include <xo/expression2/detail/IExpression_DConstant.hpp> #include <xo/expression2/detail/IExpression_DConstant.hpp>
@ -204,23 +205,23 @@ namespace xo {
void void
DToplevelSeqSsm::on_symbol_token(const Token & tk, DToplevelSeqSsm::on_symbol_token(const Token & tk,
ParserStateMachine * p_psm) ParserStateMachine * p_psm)
{ {
switch (seqtype_) { switch (seqtype_) {
case exprseqtype::toplevel_interactive: case exprseqtype::toplevel_interactive:
{ {
#ifdef NOT_YET auto varref = obj<AExpression,DVarRef>(p_psm->lookup_varref(tk.text()));
obj<AExpression,DVariable> var = p_psm->lookup_var(tk.text());
if (var) { if (varref) {
DProgressSsm::start(var, p_psm); DProgressSsm::start(p_psm->parser_alloc(),
varref,
p_psm);
return;
} else { } else {
p_psm->unknown_variable_error("DToplevelSeqSsm::on_symbol_token", p_psm->error_unbound_variable("DToplevelSeqSsm",
tk, tk.text());
this->get_expect_str(), return;
p_psm);
} }
#endif
} }
break; break;
case exprseqtype::toplevel_batch: case exprseqtype::toplevel_batch:

View file

@ -156,6 +156,16 @@ namespace xo {
{ {
scope log(XO_DEBUG(debug_flag_)); scope log(XO_DEBUG(debug_flag_));
const DUniqueString * ustr = stringtable_.lookup(symbolname);
if (!ustr) {
// if we don't already know the symbol,
// -> can't be a valid variable reference
// (whether global or local)
return nullptr;
}
// TODO: // TODO:
// 1. check global symtab // 1. check global symtab
// 2. combine local+global symtab into indept struct // 2. combine local+global symtab into indept struct
@ -163,52 +173,46 @@ namespace xo {
// //
if (local_symtab_) { if (local_symtab_) {
const DUniqueString * ustr = stringtable_.lookup(symbolname); DLocalSymtab * symtab = local_symtab_;
if (ustr) { // count #of nested scopes to cross, to reach symbol
DLocalSymtab * symtab = local_symtab_; //
int32_t link_count = 0;
// count #of nested scopes to cross, to reach symbol while (symtab) {
// Binding b = symtab->lookup_binding(ustr);
int32_t link_count = 0;
while (symtab) { if (b.is_local()) {
Binding b = symtab->lookup_binding(ustr); assert(b.i_link() == 0);
if (b.is_local()) { DVariable * vardef = symtab->lookup_var(b);
assert(b.i_link() == 0); assert(vardef);
DVariable * vardef = symtab->lookup_var(b); /** ascii diagram here
assert(vardef); **/
return DVarRef::make(expr_alloc_,
/** ascii diagram here vardef,
**/ link_count);
} else {
return DVarRef::make(expr_alloc_, assert(b.is_null());
vardef,
link_count);
} else {
assert(b.is_null());
}
++link_count;
symtab = symtab->parent();
} }
} else {
// if we don't already know the symbol,
// -> can't be a valid variable reference
// (whether global or local)
return nullptr; ++link_count;
symtab = symtab->parent();
} }
} }
// TODO: check global symtab also DVariable * vardef = global_symtab_->lookup_variable(ustr);
log.retroactively_enable(); if (vardef) {
log("STUB: check global symtab"); return DVarRef::make(expr_alloc_,
vardef,
0 /*link_count -- n/a for globals*/);
}
// symbol not found
return nullptr; return nullptr;
} }

View file

@ -11,6 +11,7 @@
#include <xo/reader2/init_reader2.hpp> #include <xo/reader2/init_reader2.hpp>
#include <xo/expression2/DefineExpr.hpp> #include <xo/expression2/DefineExpr.hpp>
#include <xo/expression2/ApplyExpr.hpp> #include <xo/expression2/ApplyExpr.hpp>
#include <xo/expression2/VarRef.hpp>
#include <xo/expression2/Constant.hpp> #include <xo/expression2/Constant.hpp>
#include <xo/procedure2/Primitive_gco_2_gco_gco.hpp> #include <xo/procedure2/Primitive_gco_2_gco_gco.hpp>
#include <xo/object2/Float.hpp> #include <xo/object2/Float.hpp>
@ -31,6 +32,7 @@ namespace xo {
using xo::scm::AExpression; using xo::scm::AExpression;
using xo::scm::DDefineExpr; using xo::scm::DDefineExpr;
using xo::scm::DApplyExpr; using xo::scm::DApplyExpr;
using xo::scm::DVarRef;
using xo::scm::DConstant; using xo::scm::DConstant;
//using xo::scm::ParserResult; //using xo::scm::ParserResult;
@ -232,7 +234,7 @@ namespace xo {
{ {
const auto & testname = Catch::getResultCapture().getCurrentTestName(); const auto & testname = Catch::getResultCapture().getCurrentTestName();
constexpr bool c_debug_flag = true; constexpr bool c_debug_flag = false;
scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); scope log(XO_DEBUG(c_debug_flag), xtag("test", testname));
ParserFixture fixture(testname, c_debug_flag); ParserFixture fixture(testname, c_debug_flag);
@ -267,6 +269,72 @@ namespace xo {
log && fixture.log_memory_layout(&log); log && fixture.log_memory_layout(&log);
} }
TEST_CASE("SchematikaParser-interactive-def2", "[reader2][SchematikaParser]")
{
const auto & testname = Catch::getResultCapture().getCurrentTestName();
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag), xtag("test", testname));
ParserFixture fixture(testname, c_debug_flag);
auto & parser = *(fixture.parser_);
parser.begin_interactive_session();
{
/** Walkthrough parsing input equivalent to:
*
* def foo : f64 = 3.141593 ;
*
**/
std::vector<Token> tk_v{
Token::def_token(),
Token::symbol_token("foo"),
Token::colon_token(),
Token::symbol_token("f64"),
Token::singleassign_token(),
Token::f64_token("3.141593"),
Token::semicolon_token(),
};
utest_tokenizer_loop(&parser, tk_v, c_debug_flag);
const auto & result = parser.result();
{
auto expr = obj<AExpression,DDefineExpr>::from(result.result_expr());
REQUIRE(expr);
}
parser.reset_result();
}
{
/** Walkthrough parsing input equivalent to:
*
* foo ;
*
**/
std::vector<Token> tk_v{
// Token::f64_token("2.0"),
// Token::star_token(),
Token::symbol_token("foo"),
Token::semicolon_token(),
};
utest_tokenizer_loop(&parser, tk_v, c_debug_flag);
const auto & result = parser.result();
{
auto expr = obj<AExpression,DVarRef>::from(result.result_expr());
REQUIRE(expr);
}
}
log && fixture.log_memory_layout(&log);
}
TEST_CASE("SchematikaParser-interactive-integer", "[reader2][SchematikaParser]") TEST_CASE("SchematikaParser-interactive-integer", "[reader2][SchematikaParser]")
{ {
const auto & testname = Catch::getResultCapture().getCurrentTestName(); const auto & testname = Catch::getResultCapture().getCurrentTestName();