From 66d9bc5cd6ed26c4f8e6ce5fcc6a26d755a5fc73 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 16 Feb 2026 11:03:09 -0500 Subject: [PATCH] xo-reader2: bugfix: checkpoint before allocating SSMs --- include/xo/reader2/DDefineSsm.hpp | 8 ++++++-- include/xo/reader2/DParenSsm.hpp | 5 ++++- include/xo/reader2/ParserStack.hpp | 4 +++- include/xo/reader2/ParserStateMachine.hpp | 6 ++++-- src/reader2/DApplySsm.cpp | 6 +++--- src/reader2/DDefineSsm.cpp | 20 +++++++++++++------- src/reader2/DExpectExprSsm.cpp | 4 +++- src/reader2/DExpectFormalArgSsm.cpp | 4 +++- src/reader2/DExpectFormalArglistSsm.cpp | 4 +++- src/reader2/DExpectSymbolSsm.cpp | 4 +++- src/reader2/DExpectTypeSsm.cpp | 4 +++- src/reader2/DIfElseSsm.cpp | 4 +++- src/reader2/DLambdaSsm.cpp | 4 +++- src/reader2/DParenSsm.cpp | 14 ++++++++++---- src/reader2/DProgressSsm.cpp | 6 +++--- src/reader2/DSequenceSsm.cpp | 6 ++++-- src/reader2/ParserStack.cpp | 3 ++- src/reader2/ParserStateMachine.cpp | 8 +++++--- 18 files changed, 78 insertions(+), 36 deletions(-) diff --git a/include/xo/reader2/DDefineSsm.hpp b/include/xo/reader2/DDefineSsm.hpp index d42246ef..6380a233 100644 --- a/include/xo/reader2/DDefineSsm.hpp +++ b/include/xo/reader2/DDefineSsm.hpp @@ -87,8 +87,12 @@ namespace xo { /** create instance using memory from @p parser_mm. * Initial expression scaffold @p def_expr **/ - static DDefineSsm * make(DArena & parser_mm, - DDefineExpr * def_expr); + static DDefineSsm * _make(DArena & parser_mm, + DDefineExpr * def_expr); + + /** create fop referring to new DDefineSsm **/ + static obj make(DArena & parser_mm, + DDefineExpr * def_expr); /** start nested parser for a define-expression, * on top of parser state machine @p p_psm diff --git a/include/xo/reader2/DParenSsm.hpp b/include/xo/reader2/DParenSsm.hpp index 6f359b65..818e0470 100644 --- a/include/xo/reader2/DParenSsm.hpp +++ b/include/xo/reader2/DParenSsm.hpp @@ -62,7 +62,10 @@ namespace xo { /** create instance using memory from @p parser_mm **/ - static DParenSsm * make(DArena & parser_mm); + static DParenSsm * _make(DArena & parser_mm); + + /** create fop pointing with new DParenSsm using memory from @p parser_mm **/ + static obj make(DArena & parser_mm); /** push DParenSsm instance onto @p p_psm stack **/ static void start(ParserStateMachine * p_psm); diff --git a/include/xo/reader2/ParserStack.hpp b/include/xo/reader2/ParserStack.hpp index 936c57e5..ef5705e9 100644 --- a/include/xo/reader2/ParserStack.hpp +++ b/include/xo/reader2/ParserStack.hpp @@ -30,9 +30,11 @@ namespace xo { ParserStack * parent); /** create new top of stack for syntax @p ssm, using memory from @p mm. - * previous stack given by @p parent + * previous stack given by @p parent. + * Checkpoint @p ckp will refer to stack _before_ allocating @p ssm **/ static ParserStack * push(ParserStack * stack, + DArena::Checkpoint ckp, DArena & mm, obj ssm); diff --git a/include/xo/reader2/ParserStateMachine.hpp b/include/xo/reader2/ParserStateMachine.hpp index 97c8c6e5..2dfba437 100644 --- a/include/xo/reader2/ParserStateMachine.hpp +++ b/include/xo/reader2/ParserStateMachine.hpp @@ -97,8 +97,10 @@ namespace xo { /** establish toplevel @p ssm. Must have empty stack **/ void establish_toplevel_ssm(obj ssm); - /** push syntax @p ssm onto @ref stack_ **/ - void push_ssm(obj ssm); + /** push syntax @p ssm onto @ref stack_, restore parser stack to @p ckp + * when popped + **/ + void push_ssm(DArena::Checkpoint ckp, obj ssm); /** pop syntax state machine from top of @ref stack_ **/ void pop_ssm(); diff --git a/src/reader2/DApplySsm.cpp b/src/reader2/DApplySsm.cpp index 4cd3aaec..a741ce4b 100644 --- a/src/reader2/DApplySsm.cpp +++ b/src/reader2/DApplySsm.cpp @@ -89,14 +89,14 @@ namespace xo { { scope log(XO_DEBUG(p_psm->debug_flag())); + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + DApplySsm * apply_ssm = DApplySsm::make(p_psm->parser_alloc(), fn_expr); obj ssm(apply_ssm); - p_psm->push_ssm(ssm); - //OBSOLETE //p_psm->top_exprstate().on_expr(fn_expr.get(), p_psm); - //OBSOLETE //p_psm->on_token(token_type::leftparen(), p_psm); + p_psm->push_ssm(ckp, ssm); } syntaxstatetype diff --git a/src/reader2/DDefineSsm.cpp b/src/reader2/DDefineSsm.cpp index 2d2ecb0b..78e29250 100644 --- a/src/reader2/DDefineSsm.cpp +++ b/src/reader2/DDefineSsm.cpp @@ -343,8 +343,8 @@ namespace xo { {} DDefineSsm * - DDefineSsm::make(DArena & mm, - DDefineExpr * def_expr) + DDefineSsm::_make(DArena & mm, + DDefineExpr * def_expr) { void * mem = mm.alloc(typeseq::id(), sizeof(DDefineSsm)); @@ -352,6 +352,13 @@ namespace xo { return new (mem) DDefineSsm(def_expr); } + obj + DDefineSsm::make(DArena & mm, + DDefineExpr * def_expr) + { + return obj(_make(mm, def_expr)); + } + void DDefineSsm::start(DArena & mm, obj expr_mm, @@ -361,14 +368,13 @@ namespace xo { assert(p_psm->stack()); + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + DDefineExpr * def_expr = DDefineExpr::make_empty(expr_mm); - DDefineSsm * define_ssm = DDefineSsm::make(mm, def_expr); + auto define_ssm = DDefineSsm::make(mm, def_expr); - obj ssm - = with_facet::mkobj(define_ssm); - - p_psm->push_ssm(ssm); + p_psm->push_ssm(ckp, define_ssm); // note: triggers poly dispatch p_psm->on_token(Token::def_token()); diff --git a/src/reader2/DExpectExprSsm.cpp b/src/reader2/DExpectExprSsm.cpp index c763e2a4..767df9bf 100644 --- a/src/reader2/DExpectExprSsm.cpp +++ b/src/reader2/DExpectExprSsm.cpp @@ -69,6 +69,8 @@ namespace xo { bool cxl_on_rightbrace, ParserStateMachine * p_psm) { + DArena::Checkpoint ckp = mm.checkpoint(); + DExpectExprSsm * exp_expr = DExpectExprSsm::make(mm, allow_defs, @@ -76,7 +78,7 @@ namespace xo { obj ssm = with_facet::mkobj(exp_expr); - p_psm->push_ssm(ssm); + p_psm->push_ssm(ckp, ssm); } void diff --git a/src/reader2/DExpectFormalArgSsm.cpp b/src/reader2/DExpectFormalArgSsm.cpp index d865cd71..47d55f6a 100644 --- a/src/reader2/DExpectFormalArgSsm.cpp +++ b/src/reader2/DExpectFormalArgSsm.cpp @@ -56,7 +56,9 @@ namespace xo { void DExpectFormalArgSsm::start(ParserStateMachine * p_psm) { - p_psm->push_ssm(DExpectFormalArgSsm::make(p_psm->parser_alloc())); + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DExpectFormalArgSsm::make(p_psm->parser_alloc())); DExpectSymbolSsm::start(p_psm); } diff --git a/src/reader2/DExpectFormalArglistSsm.cpp b/src/reader2/DExpectFormalArglistSsm.cpp index 5f609807..3ce11ae8 100644 --- a/src/reader2/DExpectFormalArglistSsm.cpp +++ b/src/reader2/DExpectFormalArglistSsm.cpp @@ -87,7 +87,9 @@ namespace xo { void DExpectFormalArglistSsm::start(ParserStateMachine * p_psm) { - p_psm->push_ssm(DExpectFormalArglistSsm::make(p_psm->parser_alloc())); + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DExpectFormalArglistSsm::make(p_psm->parser_alloc())); } syntaxstatetype diff --git a/src/reader2/DExpectSymbolSsm.cpp b/src/reader2/DExpectSymbolSsm.cpp index b252055b..6f289edd 100644 --- a/src/reader2/DExpectSymbolSsm.cpp +++ b/src/reader2/DExpectSymbolSsm.cpp @@ -31,6 +31,8 @@ namespace xo { void DExpectSymbolSsm::start(ParserStateMachine * p_psm) { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + DExpectSymbolSsm * sym_ssm = DExpectSymbolSsm::make(p_psm->parser_alloc()); @@ -40,7 +42,7 @@ namespace xo { obj ssm = with_facet::mkobj(sym_ssm); - p_psm->push_ssm(ssm); + p_psm->push_ssm(ckp, ssm); } syntaxstatetype diff --git a/src/reader2/DExpectTypeSsm.cpp b/src/reader2/DExpectTypeSsm.cpp index f7ee3689..412a5cab 100644 --- a/src/reader2/DExpectTypeSsm.cpp +++ b/src/reader2/DExpectTypeSsm.cpp @@ -34,13 +34,15 @@ namespace xo { void DExpectTypeSsm::start(ParserStateMachine * p_psm) { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + DExpectTypeSsm * expect_type_ssm = DExpectTypeSsm::make(p_psm->parser_alloc()); auto ssm = with_facet::mkobj(expect_type_ssm); - p_psm->push_ssm(ssm); + p_psm->push_ssm(ckp, ssm); } syntaxstatetype diff --git a/src/reader2/DIfElseSsm.cpp b/src/reader2/DIfElseSsm.cpp index ccf4705f..521a59a1 100644 --- a/src/reader2/DIfElseSsm.cpp +++ b/src/reader2/DIfElseSsm.cpp @@ -70,13 +70,15 @@ namespace xo { { scope log(XO_DEBUG(p_psm->debug_flag())); + DArena::Checkpoint ckp = parser_mm.checkpoint(); + DIfElseExpr * if_expr = DIfElseExpr::_make_empty(expr_mm); DIfElseSsm * if_ssm = DIfElseSsm::_make(parser_mm, if_expr); obj ssm = with_facet::mkobj(if_ssm); - p_psm->push_ssm(ssm); + p_psm->push_ssm(ckp, ssm); // note: triggers poly dispatch p_psm->on_token(Token::if_token()); diff --git a/src/reader2/DLambdaSsm.cpp b/src/reader2/DLambdaSsm.cpp index a2c2dfbd..6308ae08 100644 --- a/src/reader2/DLambdaSsm.cpp +++ b/src/reader2/DLambdaSsm.cpp @@ -78,7 +78,9 @@ namespace xo { void DLambdaSsm::start(ParserStateMachine * p_psm) { - p_psm->push_ssm(DLambdaSsm::make(p_psm->parser_alloc())); + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DLambdaSsm::make(p_psm->parser_alloc())); p_psm->on_token(Token::lambda_token()); } diff --git a/src/reader2/DParenSsm.cpp b/src/reader2/DParenSsm.cpp index 972d503a..ad86ddd5 100644 --- a/src/reader2/DParenSsm.cpp +++ b/src/reader2/DParenSsm.cpp @@ -40,7 +40,7 @@ namespace xo { {} DParenSsm * - DParenSsm::make(DArena & mm) + DParenSsm::_make(DArena & mm) { void * mem = mm.alloc(typeseq::id(), sizeof(DParenSsm)); @@ -48,14 +48,20 @@ namespace xo { return new (mem) DParenSsm(); } + obj + DParenSsm::make(DArena & mm) + { + return obj(_make(mm)); + } + void DParenSsm::start(ParserStateMachine * p_psm) { - DParenSsm * paren_ssm = DParenSsm::make(p_psm->parser_alloc()); + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); - auto ssm = with_facet::mkobj(paren_ssm); + auto paren_ssm = DParenSsm::make(p_psm->parser_alloc()); - p_psm->push_ssm(ssm); + p_psm->push_ssm(ckp, paren_ssm); } syntaxstatetype diff --git a/src/reader2/DProgressSsm.cpp b/src/reader2/DProgressSsm.cpp index 94efb30d..e4cdf46b 100644 --- a/src/reader2/DProgressSsm.cpp +++ b/src/reader2/DProgressSsm.cpp @@ -164,12 +164,14 @@ namespace xo { optype op, ParserStateMachine * p_psm) { + DArena::Checkpoint ckp = parser_mm.checkpoint(); + DProgressSsm * progress_ssm = DProgressSsm::make(parser_mm, lhs, op); obj ssm(progress_ssm); - p_psm->push_ssm(ssm); + p_psm->push_ssm(ckp, ssm); } void @@ -324,8 +326,6 @@ namespace xo { { scope log(XO_DEBUG(p_psm->debug_flag())); - (void)tk; - obj expr = this->assemble_expr(p_psm); p_psm->pop_ssm(); // completes self diff --git a/src/reader2/DSequenceSsm.cpp b/src/reader2/DSequenceSsm.cpp index 7a65d60d..87460804 100644 --- a/src/reader2/DSequenceSsm.cpp +++ b/src/reader2/DSequenceSsm.cpp @@ -22,8 +22,10 @@ namespace xo { void DSequenceSsm::start(ParserStateMachine * p_psm) { - p_psm->push_ssm(DSequenceSsm::make(p_psm->parser_alloc(), - p_psm->expr_alloc())); + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DSequenceSsm::make(p_psm->parser_alloc(), + p_psm->expr_alloc())); /* want to accept anything that starts an expression, * except that rightbrace '}' ends it */ diff --git a/src/reader2/ParserStack.cpp b/src/reader2/ParserStack.cpp index e3ffb290..9ab919b2 100644 --- a/src/reader2/ParserStack.cpp +++ b/src/reader2/ParserStack.cpp @@ -22,11 +22,12 @@ namespace xo { ParserStack * ParserStack::push(ParserStack * stack, + DArena::Checkpoint ckp, DArena & mm, obj ssm) { - DArena::Checkpoint ckp = mm.checkpoint(); + //DArena::Checkpoint ckp = mm.checkpoint(); // wrong, must precede allocation of ssm void * mem = mm.alloc(typeseq::id(), sizeof(ParserStack)); diff --git a/src/reader2/ParserStateMachine.cpp b/src/reader2/ParserStateMachine.cpp index bbb4841e..1223abe2 100644 --- a/src/reader2/ParserStateMachine.cpp +++ b/src/reader2/ParserStateMachine.cpp @@ -75,18 +75,20 @@ namespace xo { assert(stack_ == nullptr); - this->stack_ = ParserStack::push(nullptr /*stack*/, parser_alloc_, ssm); + DArena::Checkpoint ckp = parser_alloc_.checkpoint(); + + this->stack_ = ParserStack::push(nullptr /*stack*/, ckp, parser_alloc_, ssm); this->parser_alloc_ckp_ = parser_alloc_.checkpoint(); } void - ParserStateMachine::push_ssm(obj ssm) + ParserStateMachine::push_ssm(DArena::Checkpoint ckp, obj ssm) { scope log(XO_DEBUG(debug_flag_)); // note: using parser_alloc_ for parser stack, since stacklike behavior - this->stack_ = ParserStack::push(stack_, parser_alloc_, ssm); + this->stack_ = ParserStack::push(stack_, ckp, parser_alloc_, ssm); } void