From 94efaf46cd18746d7fa04289e38f838bca9ca003 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 30 Jan 2026 10:26:35 -0500 Subject: [PATCH] xo-expression2 xo-reader2: local symtab stack in PSM --- xo-expression2/CMakeLists.txt | 24 +++++++ .../idl/IPrintable_DLocalSymtab.json5 | 13 ++++ .../idl/ISymbolTable_DLocalSymtab.json5 | 12 ++++ .../include/xo/expression2/Binding.hpp | 1 + .../include/xo/expression2/DLocalSymtab.hpp | 11 +++- .../detail/IExpression_DIfElseExpr.hpp | 2 +- .../detail/IGCObject_DVariable.hpp | 2 +- .../detail/IPrintable_DIfElseExpr.hpp | 2 +- .../symtab/IPrintable_DLocalSymtab.hpp | 62 +++++++++++++++++++ .../symtab/ISymbolTable_DLocalSymtab.hpp | 60 ++++++++++++++++++ xo-expression2/src/expression2/CMakeLists.txt | 3 + .../src/expression2/DLocalSymtab.cpp | 62 ++++++++++++++++++- .../expression2/IExpression_DIfElseExpr.cpp | 2 +- .../src/expression2/IGCObject_DVariable.cpp | 2 +- .../expression2/IPrintable_DIfElseExpr.cpp | 2 +- .../expression2/IPrintable_DLocalSymtab.cpp | 28 +++++++++ .../expression2/ISymbolTable_DLocalSymtab.cpp | 34 ++++++++++ .../expression2_register_facets.cpp | 9 +++ .../xo/reader2/DExpectFormalArglistSsm.hpp | 8 ++- xo-reader2/include/xo/reader2/DLambdaSsm.hpp | 4 +- .../include/xo/reader2/ParserStateMachine.hpp | 31 +++++++++- .../src/reader2/DExpectFormalArglistSsm.cpp | 25 +++++--- xo-reader2/src/reader2/DLambdaSsm.cpp | 52 ++++++++++++++++ xo-reader2/src/reader2/ParserStack.cpp | 2 +- xo-reader2/src/reader2/ParserStateMachine.cpp | 20 ++++++ xo-reader2/utest/SchematikaParser.test.cpp | 6 +- xo-tokenizer2/include/xo/tokenizer2/Token.hpp | 2 +- 27 files changed, 447 insertions(+), 34 deletions(-) create mode 100644 xo-expression2/idl/IPrintable_DLocalSymtab.json5 create mode 100644 xo-expression2/idl/ISymbolTable_DLocalSymtab.json5 create mode 100644 xo-expression2/include/xo/expression2/symtab/IPrintable_DLocalSymtab.hpp create mode 100644 xo-expression2/include/xo/expression2/symtab/ISymbolTable_DLocalSymtab.hpp create mode 100644 xo-expression2/src/expression2/IPrintable_DLocalSymtab.cpp create mode 100644 xo-expression2/src/expression2/ISymbolTable_DLocalSymtab.cpp diff --git a/xo-expression2/CMakeLists.txt b/xo-expression2/CMakeLists.txt index 63ff9fad..ae1bb8c2 100644 --- a/xo-expression2/CMakeLists.txt +++ b/xo-expression2/CMakeLists.txt @@ -34,6 +34,30 @@ xo_add_genfacet( # ---------------------------------------------------------------- +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-symboltable-localsymtab + FACET_PKG xo_expression2 + FACET SymbolTable + REPR LocalSymtab + INPUT idl/ISymbolTable_DLocalSymtab.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR symtab + OUTPUT_CPP_DIR src/expression2 +) + +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-localsymtab + FACET_PKG xo_printable2 + FACET Printable + REPR LocalSymtab + INPUT idl/IPrintable_DLocalSymtab.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR symtab + OUTPUT_CPP_DIR src/expression2 +) + +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacet( TARGET xo-expression2-facet-expression diff --git a/xo-expression2/idl/IPrintable_DLocalSymtab.json5 b/xo-expression2/idl/IPrintable_DLocalSymtab.json5 new file mode 100644 index 00000000..3f17e64e --- /dev/null +++ b/xo-expression2/idl/IPrintable_DLocalSymtab.json5 @@ -0,0 +1,13 @@ +{ + mode: "implementation", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DLocalSymtab", + using_doxygen: true, + repr: "DLocalSymtab", + doc: [ "implement APrintable for DLocalSymtab" ], +} diff --git a/xo-expression2/idl/ISymbolTable_DLocalSymtab.json5 b/xo-expression2/idl/ISymbolTable_DLocalSymtab.json5 new file mode 100644 index 00000000..026c0ed1 --- /dev/null +++ b/xo-expression2/idl/ISymbolTable_DLocalSymtab.json5 @@ -0,0 +1,12 @@ +{ + mode: "implementation", + includes: [ ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SymbolTable.json5", + brief: "provide ASymbolTable interface for DLocalSymtab", + using_doxygen: true, + repr: "DLocalSymtab", + doc: [ "implement ASymbolTable for DLocalSymtab" ], +} diff --git a/xo-expression2/include/xo/expression2/Binding.hpp b/xo-expression2/include/xo/expression2/Binding.hpp index e97cc715..6dffb16b 100644 --- a/xo-expression2/include/xo/expression2/Binding.hpp +++ b/xo-expression2/include/xo/expression2/Binding.hpp @@ -25,6 +25,7 @@ namespace xo { static Binding local(int32_t j_slot) { return Binding(0, j_slot); } bool is_global() const { return i_link_ == s_link_global; } + bool is_local() const { return (i_link_ == 0) && (j_slot_ >= 0); } int32_t i_link() const noexcept { return i_link_; } int32_t j_slot() const noexcept { return j_slot_; } diff --git a/xo-expression2/include/xo/expression2/DLocalSymtab.hpp b/xo-expression2/include/xo/expression2/DLocalSymtab.hpp index 9eada176..01d9aa85 100644 --- a/xo-expression2/include/xo/expression2/DLocalSymtab.hpp +++ b/xo-expression2/include/xo/expression2/DLocalSymtab.hpp @@ -45,20 +45,23 @@ namespace xo { /** @defgroup scm-lambdaexpr-constructors **/ ///@{ - /** empty instance with capacity for n slots. + /** empty instance with parent @p p and capacity for @p n slots. * Caller must ensure that slots_[0..n) are actually addressable **/ - DLocalSymtab(size_type n); + DLocalSymtab(DLocalSymtab * p, size_type n); /** scaffold empty symtab instance, * with capacity for @p n slots, using memory from allocator @p mm **/ - static DLocalSymtab * _make_empty(obj mm, size_type n); + static DLocalSymtab * _make_empty(obj mm, + DLocalSymtab * p, + size_type n); ///@} /** @defgroup scm-lambdaexpr-methods **/ ///@{ + DLocalSymtab * parent() const noexcept { return parent_; } size_type capacity() const noexcept { return capacity_; } size_type size() const noexcept { return size_; } @@ -96,6 +99,8 @@ namespace xo { ///@} private: + /** parent symbol table from scoping surrounding this one **/ + DLocalSymtab * parent_ = nullptr; /** actual range of slots_[] array. Can use inices in [0,..,n) **/ size_type capacity_ = 0; /** number of slots in use **/ diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DIfElseExpr.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DIfElseExpr.hpp index 03500a39..7d726dde 100644 --- a/xo-expression2/include/xo/expression2/detail/IExpression_DIfElseExpr.hpp +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DIfElseExpr.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/IExpression_DIfElseExpr.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DVariable.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DVariable.hpp index aee612ea..24dc591f 100644 --- a/xo-expression2/include/xo/expression2/detail/IGCObject_DVariable.hpp +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DVariable.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DVariable.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DIfElseExpr.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DIfElseExpr.hpp index e9cf67ff..fcf80fd5 100644 --- a/xo-expression2/include/xo/expression2/detail/IPrintable_DIfElseExpr.hpp +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DIfElseExpr.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DIfElseExpr.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/include/xo/expression2/symtab/IPrintable_DLocalSymtab.hpp b/xo-expression2/include/xo/expression2/symtab/IPrintable_DLocalSymtab.hpp new file mode 100644 index 00000000..c013e937 --- /dev/null +++ b/xo-expression2/include/xo/expression2/symtab/IPrintable_DLocalSymtab.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DLocalSymtab.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLocalSymtab.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DLocalSymtab.hpp" + +namespace xo { namespace scm { class IPrintable_DLocalSymtab; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DLocalSymtab + **/ + class IPrintable_DLocalSymtab { + public: + /** @defgroup scm-printable-dlocalsymtab-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dlocalsymtab-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DLocalSymtab & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DLocalSymtab.hpp b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DLocalSymtab.hpp new file mode 100644 index 00000000..72f409dd --- /dev/null +++ b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DLocalSymtab.hpp @@ -0,0 +1,60 @@ +/** @file ISymbolTable_DLocalSymtab.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISymbolTable_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISymbolTable_DLocalSymtab.json5] + **/ + +#pragma once + +#include "SymbolTable.hpp" +#include "DLocalSymtab.hpp" + +namespace xo { namespace scm { class ISymbolTable_DLocalSymtab; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISymbolTable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISymbolTable_DLocalSymtab + **/ + class ISymbolTable_DLocalSymtab { + public: + /** @defgroup scm-symboltable-dlocalsymtab-type-traits **/ + ///@{ + using Copaque = xo::scm::ASymbolTable::Copaque; + using Opaque = xo::scm::ASymbolTable::Opaque; + ///@} + /** @defgroup scm-symboltable-dlocalsymtab-methods **/ + ///@{ + // const methods + /** true iff this is toplevel (global) symbol table. **/ + static bool is_global_symtab(const DLocalSymtab & self) noexcept; + /** report ingredients needed to address variable at runtime. **/ + static Binding lookup_binding(const DLocalSymtab & self, const DUniqueString * sym) noexcept; + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/src/expression2/CMakeLists.txt b/xo-expression2/src/expression2/CMakeLists.txt index 03bd8230..8e6565c4 100644 --- a/xo-expression2/src/expression2/CMakeLists.txt +++ b/xo-expression2/src/expression2/CMakeLists.txt @@ -39,6 +39,9 @@ set(SELF_SRCS ISymbolTable_Any.cpp + ISymbolTable_DLocalSymtab.cpp + IPrintable_DLocalSymtab.cpp + StringTable.cpp DUniqueString.cpp diff --git a/xo-expression2/src/expression2/DLocalSymtab.cpp b/xo-expression2/src/expression2/DLocalSymtab.cpp index c38096ff..85631d34 100644 --- a/xo-expression2/src/expression2/DLocalSymtab.cpp +++ b/xo-expression2/src/expression2/DLocalSymtab.cpp @@ -5,14 +5,21 @@ #include "DLocalSymtab.hpp" #include "DUniqueString.hpp" +#include +#include #include namespace xo { + using xo::print::APrintable; using xo::facet::typeseq; + using xo::print::ppstate; namespace scm { - DLocalSymtab::DLocalSymtab(size_type n) : capacity_{n}, size_{0} + DLocalSymtab::DLocalSymtab(DLocalSymtab * p, + size_type n) : parent_{p}, + capacity_{n}, + size_{0} { for (size_type i = 0; i < n; ++i) { void * mem = &slots_[i]; @@ -21,12 +28,14 @@ namespace xo { } DLocalSymtab * - DLocalSymtab::_make_empty(obj mm, size_type n) + DLocalSymtab::_make_empty(obj mm, + DLocalSymtab * p, + size_type n) { void * mem = mm.alloc(typeseq::id(), sizeof(DLocalSymtab) + (n * sizeof(Slot))); - return new (mem) DLocalSymtab(n); + return new (mem) DLocalSymtab(p, n); } Binding @@ -68,6 +77,53 @@ namespace xo { return Binding(); } + bool + DLocalSymtab::pretty(const ppindentinfo & ppii) const + { + ppstate * pps = ppii.pps(); + + if (ppii.upto()) { + /* perhaps print on one line */ + if (!pps->print_upto("print_upto(xrefrtag("size", size_))) + return false; + + for (size_type i = 0; i < size_; ++i) { + char buf[32]; + snprintf(buf, sizeof(buf), "[%u]", i); + + assert(slots_[i].var_); + + obj arg_pr(const_cast(slots_[i].var_)); + + if (!pps->print_upto(xrefrtag(buf, arg_pr))) + return false; + } + + pps->write(">"); + return true; + } else { + /* with line breaks */ + + pps->write("newline_pretty_tag(ppii.ci1(), "size", size_); + + for (size_type i = 0; i < size_; ++i) { + char buf[32]; + snprintf(buf, sizeof(buf), "[%u]", i); + + assert(slots_[i].var_); + + obj arg_pr(const_cast(slots_[i].var_)); + + pps->newline_pretty_tag(ppii.ci1(), buf, arg_pr); + } + + pps->write(">"); + return false; + } + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-expression2/src/expression2/IExpression_DIfElseExpr.cpp b/xo-expression2/src/expression2/IExpression_DIfElseExpr.cpp index 78680310..d913eaf0 100644 --- a/xo-expression2/src/expression2/IExpression_DIfElseExpr.cpp +++ b/xo-expression2/src/expression2/IExpression_DIfElseExpr.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/IExpression_DIfElseExpr.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/src/expression2/IGCObject_DVariable.cpp b/xo-expression2/src/expression2/IGCObject_DVariable.cpp index 8735b286..4af0f906 100644 --- a/xo-expression2/src/expression2/IGCObject_DVariable.cpp +++ b/xo-expression2/src/expression2/IGCObject_DVariable.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DVariable.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/src/expression2/IPrintable_DIfElseExpr.cpp b/xo-expression2/src/expression2/IPrintable_DIfElseExpr.cpp index ec68b9fc..a75cd6a4 100644 --- a/xo-expression2/src/expression2/IPrintable_DIfElseExpr.cpp +++ b/xo-expression2/src/expression2/IPrintable_DIfElseExpr.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DIfElseExpr.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/src/expression2/IPrintable_DLocalSymtab.cpp b/xo-expression2/src/expression2/IPrintable_DLocalSymtab.cpp new file mode 100644 index 00000000..dbd4887b --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DLocalSymtab.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DLocalSymtab.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLocalSymtab.json5] +**/ + +#include "symtab/IPrintable_DLocalSymtab.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DLocalSymtab::pretty(const DLocalSymtab & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DLocalSymtab.cpp */ \ No newline at end of file diff --git a/xo-expression2/src/expression2/ISymbolTable_DLocalSymtab.cpp b/xo-expression2/src/expression2/ISymbolTable_DLocalSymtab.cpp new file mode 100644 index 00000000..778cfdf4 --- /dev/null +++ b/xo-expression2/src/expression2/ISymbolTable_DLocalSymtab.cpp @@ -0,0 +1,34 @@ +/** @file ISymbolTable_DLocalSymtab.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISymbolTable_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISymbolTable_DLocalSymtab.json5] +**/ + +#include "symtab/ISymbolTable_DLocalSymtab.hpp" + +namespace xo { + namespace scm { + auto + ISymbolTable_DLocalSymtab::is_global_symtab(const DLocalSymtab & self) noexcept -> bool + { + return self.is_global_symtab(); + } + + auto + ISymbolTable_DLocalSymtab::lookup_binding(const DLocalSymtab & self, const DUniqueString * sym) noexcept -> Binding + { + return self.lookup_binding(sym); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISymbolTable_DLocalSymtab.cpp */ \ No newline at end of file diff --git a/xo-expression2/src/expression2/expression2_register_facets.cpp b/xo-expression2/src/expression2/expression2_register_facets.cpp index a6bd50e5..06ccc7d5 100644 --- a/xo-expression2/src/expression2/expression2_register_facets.cpp +++ b/xo-expression2/src/expression2/expression2_register_facets.cpp @@ -27,6 +27,9 @@ #include #include +#include +#include + #include #include #include @@ -74,6 +77,9 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + log && log(xtag("DUniqueString.tseq", typeseq::id())); log && log(xtag("DDefineExpr.tseq", typeseq::id())); log && log(xtag("DVariable.tseq", typeseq::id())); @@ -82,7 +88,10 @@ namespace xo { log && log(xtag("DLambdaExpr.tseq", typeseq::id())); log && log(xtag("DIfElseExpr.tseq", typeseq::id())); + log && log(xtag("DLocalSymtab.tseq", typeseq::id())); + log && log(xtag("AExpression.tqseq", typeseq::id())); + log && log(xtag("ASymbolTable.tseq", typeseq::id())); return true; } diff --git a/xo-reader2/include/xo/reader2/DExpectFormalArglistSsm.hpp b/xo-reader2/include/xo/reader2/DExpectFormalArglistSsm.hpp index 289b7cf5..81d7e85d 100644 --- a/xo-reader2/include/xo/reader2/DExpectFormalArglistSsm.hpp +++ b/xo-reader2/include/xo/reader2/DExpectFormalArglistSsm.hpp @@ -71,14 +71,18 @@ namespace xo { /** @defgroup scm-expectformalarglistssm-methods general methods **/ ///@{ - /** update state on incoming token @p tk, with overall parser state in @p psm **/ + /** update state on incoming token @p tk, with overall parser state in @p p_psm **/ void on_leftparen_token(const Token & tk, ParserStateMachine * p_psm); - /** update state on incoming token @p tk, with overall parser state in @p psm **/ + /** update state on incoming token @p tk, with overall parser state in @p p_psm **/ void on_comma_token(const Token & tk, ParserStateMachine * p_psm); + /** update state on incoming rightparen token @p tk, with overall parser state in @p p_psm **/ + void on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm); + ///@} /** @defgroup scm-expectformalarglistssm-ssm-facet syntaxstatemachine facet methods **/ ///@{ diff --git a/xo-reader2/include/xo/reader2/DLambdaSsm.hpp b/xo-reader2/include/xo/reader2/DLambdaSsm.hpp index 8800ad1c..22185269 100644 --- a/xo-reader2/include/xo/reader2/DLambdaSsm.hpp +++ b/xo-reader2/include/xo/reader2/DLambdaSsm.hpp @@ -144,8 +144,6 @@ namespace xo { #ifdef NOT_YET virtual const char * get_expect_str() const override; - virtual void on_formal_arglist(const std::vector> & argl, - parserstatemachine * p_psm) override; virtual void on_leftbrace_token(const token_type & tk, parserstatemachine * p_psm) override; virtual void on_colon_token(const token_type & tk, @@ -173,10 +171,10 @@ namespace xo { /** parsing state-machine state **/ lambdastatetype lmstate_ = lambdastatetype::lm_0; -#ifdef NOT_YET /** lambda environment (for formal parameters) **/ DLocalSymtab * local_symtab_ = nullptr; +#ifdef NOT_YET /** explicit return type (if supplied) **/ TypeDescr explicit_return_td_ = nullptr; diff --git a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp index 1c5729a6..fbf636e3 100644 --- a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp +++ b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp @@ -6,6 +6,8 @@ #pragma once #include "ParserResult.hpp" +#include +#include #include #include #include @@ -47,6 +49,7 @@ namespace xo { bool debug_flag() const noexcept { return debug_flag_; } ParserStack * stack() const noexcept { return stack_; } obj expr_alloc() const noexcept { return expr_alloc_; } + DLocalSymtab * local_symtab() const noexcept { return local_symtab_; } const ParserResult & result() const noexcept { return result_; } /** true iff state machine is currently idle (at top-level) **/ @@ -79,6 +82,15 @@ namespace xo { **/ const DUniqueString * intern_string(std::string_view str); + /** push nested local symtab while parsing the body of a lambda expression; + * restore previous symtab at the end of lambda-expression definition. + * See @ref pop_local_symtab + **/ + void push_local_symtab(DLocalSymtab * symtab); + + /** pop nested symbol table from symbol-table stack **/ + void pop_local_symtab(); + /** add variable to current local environment (innermost lexical scope) **/ void upsert_var(DVariable * var); @@ -219,8 +231,10 @@ namespace xo { * after encountering a parsing error. **/ DArena::Checkpoint parser_alloc_ckp_; - - /** parser stack. Memory from @ref parser_alloc_ **/ + /** parser stack. Memory always from @ref parser_alloc_; + * elements that should survive parsing allocate from + * @ref expr_alloc_, see below. + **/ ParserStack * stack_ = nullptr; /** Allocator for parsed expressions. @@ -239,6 +253,19 @@ namespace xo { **/ obj expr_alloc_; + /** symbol table with local bindings. + * non-null during parsing of lambda expressions. + * Always allocated from @p expr_alloc_. + * Push local symbol table here to remember local params + * during the body of a lambda expression. + **/ + DLocalSymtab * local_symtab_ = nullptr; + + /** global symbol table. + * Toplevel definitions go here. + **/ + DGlobalSymtab * global_symtab_ = nullptr; + /** current output from parser **/ ParserResult result_; diff --git a/xo-reader2/src/reader2/DExpectFormalArglistSsm.cpp b/xo-reader2/src/reader2/DExpectFormalArglistSsm.cpp index 63113f4e..bebe4108 100644 --- a/xo-reader2/src/reader2/DExpectFormalArglistSsm.cpp +++ b/xo-reader2/src/reader2/DExpectFormalArglistSsm.cpp @@ -126,6 +126,10 @@ namespace xo { this->on_comma_token(tk, p_psm); return; + case tokentype::tk_rightparen: + this->on_rightparen_token(tk, p_psm); + return; + // all the not-yet-handled cases case tokentype::tk_lambda: case tokentype::tk_def: @@ -139,7 +143,6 @@ namespace xo { case tokentype::tk_bool: case tokentype::tk_semicolon: case tokentype::tk_invalid: - case tokentype::tk_rightparen: case tokentype::tk_leftbracket: case tokentype::tk_rightbracket: case tokentype::tk_leftbrace: @@ -300,20 +303,22 @@ namespace xo { this->get_expect_str()); } -#ifdef NOT_YET void - expect_formal_arglist_xs::on_rightparen_token(const token_type & tk, - parserstatemachine * p_psm) + DExpectFormalArglistSsm::on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm) { - if (farglxs_type_ == formalarglstatetype::argl_1b) { - std::unique_ptr self = p_psm->pop_exprstate(); + if (fastate_ == formalarglstatetype::argl_1b) { + DArray * args = argl_; - p_psm->top_exprstate().on_formal_arglist(this->argl_, p_psm); - } else { - exprstate::on_rightparen_token(tk, p_psm); + p_psm->pop_ssm(); + p_psm->on_parsed_formal_arglist(args); + return; } + + p_psm->illegal_input_on_token("DExpectFormalArglistSsm::on_rightparen_token", + tk, + this->get_expect_str()); } -#endif bool DExpectFormalArglistSsm::pretty(const ppindentinfo & ppii) const diff --git a/xo-reader2/src/reader2/DLambdaSsm.cpp b/xo-reader2/src/reader2/DLambdaSsm.cpp index 99e01ffd..4bcbb844 100644 --- a/xo-reader2/src/reader2/DLambdaSsm.cpp +++ b/xo-reader2/src/reader2/DLambdaSsm.cpp @@ -9,6 +9,9 @@ #include "ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp" #include "ParserStateMachine.hpp" #include "syntaxstatetype.hpp" +#include +#include +//#include #include #include #include @@ -28,6 +31,7 @@ namespace xo { using xo::print::APrintable; using xo::mm::AAllocator; + using xo::mm::AGCObject; using xo::facet::FacetRegistry; using xo::reflect::typeseq; @@ -353,6 +357,54 @@ namespace xo { DLambdaSsm::on_parsed_formal_arglist(DArray * arglist, ParserStateMachine * p_psm) { + if (lmstate_ == lambdastatetype::lm_1) { + this->lmstate_ = lambdastatetype::lm_2; + /// something with top env frame ? + + /// TODO: arena-friendly non-gc-aware vector; + // use instead of DArray for arglist. + // something like DTypedArray + + /// create LocalSymtab from arglist + + DLocalSymtab * symtab + = DLocalSymtab::_make_empty(p_psm->expr_alloc(), + p_psm->local_symtab(), + arglist->size()); + assert(symtab); + + for (DArray::size_type i = 0, n = arglist->size(); i < n; ++i) { + obj param = arglist->at(i); + + // sad! runtime poly conversion from obj + // We on need this because of (suboptimally) using DArray to store arglist + + obj param_expr + = FacetRegistry::instance().variant(param); + obj param_var + = obj::from(param_expr); + + assert(param_expr.data()); + assert(param_var.data()); + + Binding b = symtab->append_var(p_psm->expr_alloc(), + param_var.data()->name(), + param_var.data()->typeref()); + + assert(b.is_local()); + + this->local_symtab_ = symtab; + } + + // stash env frame: records local variables while we handle lambda body + + p_psm->push_local_symtab(symtab); + + // control reenters via .on_colon_token() / .on_leftbrace_token() + + return; + } + p_psm->illegal_parsed_formal_arglist("DLambdaSsm::on_parsed_formal_arglist", arglist, this->get_expect_str()); diff --git a/xo-reader2/src/reader2/ParserStack.cpp b/xo-reader2/src/reader2/ParserStack.cpp index 9af9f339..e3ffb290 100644 --- a/xo-reader2/src/reader2/ParserStack.cpp +++ b/xo-reader2/src/reader2/ParserStack.cpp @@ -70,7 +70,7 @@ namespace xo { std::size_t i_frame = 0; while (frame) { - char buf[80]; + char buf[32]; snprintf(buf, sizeof(buf), "[%lu]", i_frame); auto ssm = (FacetRegistry::instance().variant diff --git a/xo-reader2/src/reader2/ParserStateMachine.cpp b/xo-reader2/src/reader2/ParserStateMachine.cpp index 0316515e..085cce56 100644 --- a/xo-reader2/src/reader2/ParserStateMachine.cpp +++ b/xo-reader2/src/reader2/ParserStateMachine.cpp @@ -88,6 +88,20 @@ namespace xo { return stringtable_.intern(str); } + void + ParserStateMachine::push_local_symtab(DLocalSymtab * symtab) + { + this->local_symtab_ = symtab; + } + + void + ParserStateMachine::pop_local_symtab() + { + assert(local_symtab_); + + this->local_symtab_ = local_symtab_->parent(); + } + void ParserStateMachine::upsert_var(DVariable * var) { @@ -310,6 +324,12 @@ namespace xo { xtag("expecting", expect_str), xtag("ssm", ssm_name), xtag("via", "ParserStateMachine::illegal_parsed_formal_arglist")); + + assert(expr_alloc_); + + auto errmsg = DString::from_str(expr_alloc_, errmsg_string); + + this->capture_error(ssm_name, errmsg); } void diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index cedb4c1d..cc1e51fa 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -327,11 +327,10 @@ namespace xo { REQUIRE(result.is_incomplete()); } -#ifdef NOT_YET { - auto & result = parser.on_token(Token::else_token()); + auto & result = parser.on_token(Token::rightparen_token()); - log && log("after else token:"); + log && log("after rightparen token:"); log && log(xtag("parser", &parser)); log && log(xtag("result", result)); @@ -340,6 +339,7 @@ namespace xo { REQUIRE(result.is_incomplete()); } +#ifdef NOT_YET { auto & result = parser.on_token(Token::string_token("fooey")); diff --git a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp index 607bc0a4..66427c3e 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp @@ -94,7 +94,7 @@ namespace xo { /** token representing left parenthesis @c "(" **/ static Token leftparen_token() { return Token(tokentype::tk_leftparen); } /** Token representing right parenthesis @c ")" **/ - static Token rightparen() { return Token(tokentype::tk_rightparen); } + static Token rightparen_token() { return Token(tokentype::tk_rightparen); } /** token representing left bracket @c "[" **/ static Token leftbracket() { return Token(tokentype::tk_leftbracket); } /** token representing right bracket @c "]" **/