mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49:31 +00:00
Fix interleaved text and choices
This commit is contained in:
parent
4125a4c99b
commit
aa8dfbd498
4 changed files with 70 additions and 28 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
local class = require("anselme.lib.class")
|
local class = require("anselme.lib.class")
|
||||||
|
|
||||||
local ast = require("anselme.ast")
|
local ast = require("anselme.ast")
|
||||||
local Nil, String, List, Identifier, Boolean = ast.Nil, ast.String, ast.List, ast.Identifier, ast.Boolean
|
local Nil, String, List, Identifier = ast.Nil, ast.String, ast.List, ast.Identifier
|
||||||
|
|
||||||
-- list of event data
|
-- list of event data
|
||||||
local event_buffer_identifier = Identifier:new("_event_buffer")
|
local event_buffer_identifier = Identifier:new("_event_buffer")
|
||||||
|
|
@ -11,9 +11,9 @@ local event_buffer_symbol = event_buffer_identifier:to_symbol{ confined_to_branc
|
||||||
local last_event_type_identifier = Identifier:new("_last_event_type")
|
local last_event_type_identifier = Identifier:new("_last_event_type")
|
||||||
local last_event_type_symbol = last_event_type_identifier:to_symbol{ confined_to_branch = true }
|
local last_event_type_symbol = last_event_type_identifier:to_symbol{ confined_to_branch = true }
|
||||||
|
|
||||||
-- indicate if the next flush should be ignored for the current buffered event
|
-- (per-scope) indicate if we should discard write to an event type
|
||||||
local discard_next_flush_identifier = Identifier:new("_discard_next_flush")
|
local discard_next_events_identifier = Identifier:new("_discard_next_events")
|
||||||
local discard_next_flush_symbol = discard_next_flush_identifier:to_symbol{ confined_to_branch = true }
|
local discard_next_events_symbol = discard_next_events_identifier:to_symbol{ confined_to_branch = true }
|
||||||
|
|
||||||
return class {
|
return class {
|
||||||
init = false,
|
init = false,
|
||||||
|
|
@ -21,48 +21,57 @@ return class {
|
||||||
setup = function(self, state)
|
setup = function(self, state)
|
||||||
state.scope:define(event_buffer_symbol, List:new(state))
|
state.scope:define(event_buffer_symbol, List:new(state))
|
||||||
state.scope:define(last_event_type_symbol, Nil:new())
|
state.scope:define(last_event_type_symbol, Nil:new())
|
||||||
state.scope:define(discard_next_flush_symbol, Nil:new())
|
|
||||||
end,
|
end,
|
||||||
reset = function(self, state)
|
reset = function(self, state)
|
||||||
state.scope:set(event_buffer_identifier, List:new(state))
|
state.scope:set(event_buffer_identifier, List:new(state))
|
||||||
state.scope:set(last_event_type_identifier, Nil:new())
|
state.scope:set(last_event_type_identifier, Nil:new())
|
||||||
state.scope:set(discard_next_flush_identifier, Nil:new())
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- write an event into the event buffer
|
-- write an event into the event buffer
|
||||||
-- will flush if an event of a different type is present in the buffer
|
-- will flush if an event of a different type is present in the buffer
|
||||||
write = function(self, state, event)
|
write = function(self, state, event)
|
||||||
local current_type = state.scope:get(last_event_type_identifier):to_lua(state)
|
-- discard if requested
|
||||||
if current_type ~= nil and current_type ~= event.type then
|
if state.scope:defined_in_current(discard_next_events_symbol) then
|
||||||
self:flush(state)
|
local discard_type = state.scope:get(discard_next_events_identifier):to_lua()
|
||||||
|
if discard_type == event.type then
|
||||||
|
return
|
||||||
|
elseif discard_type ~= nil then
|
||||||
|
state.scope:set(discard_next_events_identifier, Nil:new()) -- fake flush the discarded events
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
-- flush until no event or same type
|
||||||
|
repeat
|
||||||
|
local current_type = state.scope:get(last_event_type_identifier):to_lua(state)
|
||||||
|
if current_type ~= nil and current_type ~= event.type then
|
||||||
|
self:flush(state)
|
||||||
|
end
|
||||||
|
until current_type == nil or current_type == event.type
|
||||||
|
-- write
|
||||||
state.scope:set(last_event_type_identifier, String:new(event.type))
|
state.scope:set(last_event_type_identifier, String:new(event.type))
|
||||||
state.scope:get(event_buffer_identifier):insert(state, event)
|
state.scope:get(event_buffer_identifier):insert(state, event)
|
||||||
end,
|
end,
|
||||||
-- same as :write, but the buffer will be discarded instead of yielded on the next flush
|
-- same as :write, but will not actually write the event, instead discarding all immediately following event of the same type in the same scope
|
||||||
write_and_discard_on_flush = function(self, state, event)
|
write_and_discard_following = function(self, state, event)
|
||||||
self:write(state, event)
|
if not state.scope:defined_in_current(discard_next_events_symbol) then
|
||||||
state.scope:set(discard_next_flush_identifier, Boolean:new(true))
|
state.scope:define(discard_next_events_symbol, String:new(event.type))
|
||||||
|
else
|
||||||
|
state.scope:set(discard_next_events_identifier, String:new(event.type))
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- flush the event buffer: build the event data and yield it
|
-- flush the event buffer: build the event data and yield it
|
||||||
flush = function(self, state)
|
flush = function(self, state)
|
||||||
local last_type = state.scope:get(last_event_type_identifier):to_lua(state)
|
local last_type = state.scope:get(last_event_type_identifier):to_lua(state)
|
||||||
if last_type then
|
if last_type then
|
||||||
local discard_next_flush = state.scope:get(discard_next_flush_identifier):truthy()
|
local last_buffer = state.scope:get(event_buffer_identifier)
|
||||||
if discard_next_flush then
|
local event_president = last_buffer:get(state, 1) -- elected representative of all concerned events
|
||||||
self:reset(state)
|
-- yield event data
|
||||||
else
|
local data = event_president:build_event_data(state, last_buffer)
|
||||||
local last_buffer = state.scope:get(event_buffer_identifier)
|
coroutine.yield(last_type, data)
|
||||||
local event_president = last_buffer:get(state, 1) -- elected representative of all concerned events
|
-- clear room for the future
|
||||||
-- yield event data
|
self:reset(state)
|
||||||
local data = event_president:build_event_data(state, last_buffer)
|
-- post callback
|
||||||
coroutine.yield(last_type, data)
|
if event_president.post_flush_callback then event_president:post_flush_callback(state, last_buffer, data) end
|
||||||
-- clear room for the future
|
|
||||||
self:reset(state)
|
|
||||||
-- post callback
|
|
||||||
if event_president.post_flush_callback then event_president:post_flush_callback(state, last_buffer, data) end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
-- keep flushing until nothing is left (a flush may re-fill the buffer during its execution)
|
-- keep flushing until nothing is left (a flush may re-fill the buffer during its execution)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ return {
|
||||||
function(state, text, func)
|
function(state, text, func)
|
||||||
if func:contains_current_resume_target(state) then
|
if func:contains_current_resume_target(state) then
|
||||||
func:call(state, ArgumentTuple:new())
|
func:call(state, ArgumentTuple:new())
|
||||||
event_manager:write_and_discard_on_flush(state, Choice:new(text, func))
|
event_manager:write_and_discard_following(state, Choice:new(text, func))
|
||||||
else
|
else
|
||||||
event_manager:write(state, Choice:new(text, func))
|
event_manager:write(state, Choice:new(text, func))
|
||||||
end
|
end
|
||||||
|
|
|
||||||
19
test/results/choice text interleaved.ans
Normal file
19
test/results/choice text interleaved.ans
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
--# run #--
|
||||||
|
--- choice ---
|
||||||
|
=> | {}"a" |
|
||||||
|
--- text ---
|
||||||
|
| {}"-> a" |
|
||||||
|
--- choice ---
|
||||||
|
=> | {}"aa" |
|
||||||
|
> | {}"ab" |
|
||||||
|
--- text ---
|
||||||
|
| {}"-> aa" |
|
||||||
|
| {}"x" |
|
||||||
|
--- choice ---
|
||||||
|
=> | {}"b" |
|
||||||
|
--- text ---
|
||||||
|
| {}"-> b" |
|
||||||
|
--- return ---
|
||||||
|
()
|
||||||
|
--# saved #--
|
||||||
|
{}
|
||||||
14
test/tests/choice text interleaved.ans
Normal file
14
test/tests/choice text interleaved.ans
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
:@choice = 1
|
||||||
|
|
||||||
|
:f = $_
|
||||||
|
| a |>
|
||||||
|
|-> a
|
||||||
|
| aa |>
|
||||||
|
|-> aa
|
||||||
|
| ab |>
|
||||||
|
|-> ab
|
||||||
|
| x
|
||||||
|
| b |>
|
||||||
|
|-> b
|
||||||
|
|
||||||
|
f!
|
||||||
Loading…
Add table
Add a link
Reference in a new issue