---- -- `Tag` Registry. -- -- @classmod Registry class Registry --- internals for `Tag` -- @section internals --- lookup the last registration. -- -- @tparam number|string index the registration index -- @treturn any last: (index) => if tag = @last_map[index] then tag.builtin --- set the current registration. -- -- @tparam Tag tag the Tag to register -- @treturn boolean whether the tag is new register: (tag) => index = tag\index! if index and not @map[index] or ignore_dup L\trace "reg: registering #{index} (#{ignore_dup})" @map[index] = tag nil else if index L\warn "duplicate tag [#{index}], reassigning repeated occurrence" tag\set nil table.insert @pending, tag L\trace "reg: registered pending" true --- members -- @section members --- begin an evaluation cycle. -- -- All calls go `begin_eval` must be matched with a call to -- `assign_tags` followed by either `end_eval` or `rollback_eval`. begin_eval: => assert not @map, "unfinished evaluation cycle" @map, @pending = {}, {} --- assign unique tags to pending registrations. -- -- Assigns a unique number to each tag added in this evaluation cycle. assign_tags: => next_tag = 1 for tag in *@pending if not tag\index! while @map[next_tag] next_tag += 1 L\trace "assigned new tag #{next_tag} to #{tag}" tag\set next_tag @map[tag\index!] = tag --- abort an evaluation cycle. -- -- Destroys all pending registrations rollback_eval: => assert @map, "no eval cycle to abort" for tag in *@pending if builtin = tag.builtin builtin\destroy! @map, @pending = nil, nil --- end an evaluation cycle. -- -- Register all pending `Tag`s and destroy all orphaned registrations. -- @treturn bool whether any changes to the AST were made end_eval: => -- destroy old registrations for index, tag in pairs @last_map if builtin = tag.builtin builtin\destroy! -- mark all regisrations complete for index, tag in pairs @map tag.pending = nil dirty = #@pending > 0 @last_map, @map, @pending = @map, nil, nil dirty --- destroy this Registry and all associated Registrations. -- needs to be called *after* `:eval`. destroy: => assert not @tag, "unfinished evaluation cycle" for index, tag in pairs @last_map if builtin = tag.builtin builtin\destroy! @last_map = {} --- the module associated with this Registry -- @tfield Module module --- static functions -- @section static --- create a new Registry. -- @classmethod -- @tparam Module module new: (@module) => @last_map = {} { :Registry }