xtree.jl

Pollen/xtree/xtree.jl is a source file in module Pollen

			
			
			
			abstract
			 
			type
			 

	
			XTree
			 
			end
			

			

			
			
			
			"""
			

			    Leaf(value) <: XTree

			

			A leaf node in an `XTree`. It holds a single value.

			"""
			

			
			
			struct
			
			 
			

	
			Leaf
			{
			T
			}
			 
			<:
			 

	
			XTree
			
			
    
			
			data
			::
			T
			

			end
			

			

			
			
			
			Base
			.
			
			getindex
			(
			
			xleaf
			::

	
			Leaf
			)
			 
			=
			 
			
			xleaf
			.
			
			data
			

			

			
			

	
			Leaf
			(
			
			leaf
			::

	
			Leaf
			)
			 
			=
			 
			leaf
			

			

			
			
			
			AbstractTrees
			.
			
			children
			(
			
			::

	
			Leaf
			)
			 
			=
			 
			
			(
			)
			

			
			
			
			AbstractTrees
			.
			
			printnode
			(
			
			io
			::
			IO
			,
			 
			
			xleaf
			::

	
			Leaf
			)
			 
			=
			 
			
			print
			(
			io
			,
			 
			
			xleaf
			[
			]
			)
			

			
			function
			 
			
			
			AbstractTrees
			.
			
			printnode
			(
			
			io
			::
			IO
			,
			 
			
			xleaf
			::
			

	
			Leaf
			{
			String
			}
			)
			
			
    
			
			if
			
			 
			
			get
			(
			io
			,
			 
			
			:
			color
			,
			 
			false
			)
			 
			&&
			 
			
			!
			
			get
			(
			io
			,
			 
			
			:
			compact
			,
			 
			false
			)
			
			
        
			
			print
			(
			io
			,
			 
			
			"
			$
			(
			
			crayon
			
			"
			green
			"
			)
			\"
			$
			(
			
			xleaf
			[
			]
			)
			\"
			$
			(
			
			crayon
			
			"
			reset
			"
			)
			"
			)
			
    
			else
			
			
        
			
			print
			(
			io
			,
			 
			
			"
			\"
			$
			(
			
			xleaf
			[
			]
			)
			\"
			"
			)
			
    
			end
			

			end
			

			

			
			
			
			"""
			

			    Node(tag, children...; attributes...)

			

			A non-leaf node in an `XTree`. It has a tag, can hold a number of

			children nodes and key-value attributes.

			

			You can access and modify these using

			

			- [`tag`](#) and [`withtag`](#)

			- [`AbstractTrees.children`](#) and [`withchildren`](#)

			- [`attributes`](#) and [`withattributes`](#)

			

			## Examples

			

			```julia

			Node(:paragraph,

			    "I am a sentence", "This one is short";

			    class = "tight")

			

			# Equivalently

			Node(:paragraph,

			    ["I am a sentence", "This one is short"],

			    Dict(:class => "tight"))

			```

			"""
			

			
			
			Base
			.
			
			@
			kwdef
			 
			
			
			struct
			
			 
			

	
			Node
			{
			
			T
			 
			<:
			 

	
			XTree
			,
			 
			
			D
			 
			<:
			 
			
			Dict
			{
			Symbol
			}
			}
			 
			<:
			 

	
			XTree
			
			
    
			

	
			tag
			::
			Symbol
			
    
			
			children
			::
			
			Vector
			{
			T
			}
			
    
			

	
			attributes
			::
			D
			

			end
			

			

			
			
			
			Base
			.
			
			show
			(
			
			io
			::
			IO
			,
			 
			
			xnode
			::

	
			Node
			)
			 
			=
			 
			
			print_tree
			(
			io
			,
			 
			xnode
			
			;
			 
			
			maxdepth
			 
			=
			 
			4
			)
			

			

			
			function
			 
			

	
			Node
			(
			

	
			tag
			::
			Symbol
			,
			 
			
			children
			...
			
			;
			 
			

	
			attributes
			...
			)
			
			
    
			
			return
			 
			

	
			Node
			(

	
			tag
			,
			
                
			
			[
			
			
			_xtree
			(
			x
			)
			 
			for
			
			 
			x
			 
			in
			 
			children
			]
			,
			
                
			
			Dict
			(
			
			pairs
			(

	
			attributes
			)
			)
			)
			

			end
			

			

			
			function
			 
			

	
			Node
			(
			

	
			tag
			::
			Symbol
			,
			 
			
			children
			::
			
			AbstractVector
			{
			
			<:

	
			XTree
			}
			)
			
			
    
			

	
			Node
			(

	
			tag
			,
			 
			children
			,
			 
			
			
			Dict
			{
			Symbol
			,
			 
			Any
			}
			(
			)
			)
			

			end
			

			

			
			
			_xtree
			(
			
			node
			::

	
			Node
			)
			 
			=
			 
			node
			

			
			
			_xtree
			(
			
			leaf
			::

	
			Leaf
			)
			 
			=
			 
			leaf
			

			
			
			_xtree
			(
			x
			)
			 
			=
			 
			

	
			Leaf
			(
			x
			)
			

			

			
			
			
			AbstractTrees
			.
			
			children
			(
			
			xnode
			::

	
			Node
			)
			 
			=
			 
			
			xnode
			.
			
			children
			

			
			
			
			"""
			

			    tag(node)

			

			Get the symbol tag of a [`Node`](#).

			

			## Examples

			

			{cell}

			```julia

			using Pollen

			tag(Node(:md, "hi"))

			```

			"""
			

			
			

	
			tag
			(
			
			xnode
			::

	
			Node
			)
			 
			=
			 
			
			xnode
			.
			

	
			tag
			

			
			

	
			attributes
			(
			
			xnode
			::

	
			Node
			)
			 
			=
			 
			
			xnode
			.
			

	
			attributes
			

			

			
			
			
			Base
			.
			
			iterate
			(
			
			xnode
			::

	
			Node
			)
			 
			=
			 
			
			iterate
			(
			
			children
			(
			xnode
			)
			)
			

			
			
			
			Base
			.
			
			iterate
			(
			
			xnode
			::

	
			Node
			,
			 
			state
			)
			 
			=
			 
			
			iterate
			(
			
			children
			(
			xnode
			)
			,
			 
			state
			)
			

			
			
			
			
			Base
			.
			
			IteratorSize
			(
			
			::
			
			Type
			{
			

	
			Node
			{
			T
			}
			}
			)
			 
			where
			 
			{
			T
			}
			 
			=
			 
			
			
			Base
			.
			
			SizeUnknown
			(
			)
			

			
			
			
			
			Base
			.
			
			eltype
			(
			
			::
			
			Type
			{
			

	
			Node
			{
			T
			}
			}
			)
			 
			where
			 
			{
			T
			}
			 
			=
			 
			T
			

			

			
			
			
			
			Base
			.
			
			eltype
			(
			
			::
			
			Type
			{
			
			<:
			
			TreeIterator
			{
			
			<:
			

	
			Node
			{
			T
			}
			}
			}
			)
			 
			where
			 
			{
			T
			}
			 
			=
			 
			T
			

			
			
			
			
			Base
			.
			
			IteratorEltype
			(
			
			::
			
			Type
			{
			
			<:
			
			TreeIterator
			{
			
			<:
			

	
			Node
			{
			T
			}
			}
			}
			)
			 
			where
			 
			{
			T
			}
			 
			=
			 
			
			
			Base
			.
			
			HasEltype
			(
			)

from AbstractTrees >= v0.4


			
			
			
			if
			 
			
			isdefined
			(
			AbstractTrees
			,
			 
			
			:
			ChildIndexing
			)
			
			
    
			
			
			
			AbstractTrees
			.
			
			ChildIndexing
			(
			
			::
			
			Type
			{
			
			<:

	
			XTree
			}
			)
			 
			=
			 
			
			
			AbstractTrees
			.
			
			IndexedChildren
			(
			)
			

			end
			

			

			
			
			
			"""
			

			    withchildren(node, children)

			

			Replace `node`'s children with `children`.

			"""
			

			
			

	
			withchildren
			(
			
			xnode
			::

	
			Node
			,
			 
			children
			)
			 
			=
			 
			

	
			Node
			(
			

	
			tag
			(
			xnode
			)
			,
			 
			children
			,
			 
			

	
			attributes
			(
			xnode
			)
			)
			

			
			
			
			"""
			

			    withtag(node, tag)

			

			Replace the tag of `node` with `tag`.

			"""
			

			
			

	
			withtag
			(
			
			node
			::

	
			Node
			,
			 

	
			tag
			)
			 
			=
			 
			

	
			Node
			(

	
			tag
			,
			 
			
			children
			(
			node
			)
			,
			 
			

	
			attributes
			(
			node
			)
			)
			

			
			
			
			"""
			

			    withattributes(node, attributes)

			

			Replace `node`'s attributes with `attributes`.

			"""
			

			
			

	
			withattributes
			(
			
			xnode
			::

	
			Node
			,
			 

	
			attributes
			)
			 
			=
			 
			

	
			Node
			(
			

	
			tag
			(
			xnode
			)
			,
			 
			
			children
			(
			xnode
			)
			,
			 

	
			attributes
			)

Catamorphism


			
			
			
			
			
			"""
			

			    catafold(f, xtree, state)

			

			Fold a function `f : (node, state) -> (node', state')` post-order over `xtree` and

			return a modified tree as well as the resulting state.

			

			Use [`cata`](#) for a stateless catamorphism and [`fold`](#) if you don't want to

			transform `xtree`.

			"""
			

			
			function
			 
			

	
			catafold
			(
			f
			,
			 
			
			xnode
			::

	
			Node
			,
			 
			state
			
			;
			 
			
			T
			 
			=
			 

	
			XTree
			)
			
			
    
			
			cs
			 
			=
			 
			
			T
			[
			]
			
    
			
			for
			
			 
			c
			 
			in
			 
			
			children
			(
			xnode
			)
			
			
        
			
			
			c
			,
			 
			state
			 
			=
			 
			

	
			catafold
			(
			f
			,
			 
			c
			,
			 
			state
			
			;
			 
			
			T
			 
			=
			 
			T
			)
			
        
			
			push!
			(
			cs
			,
			 
			c
			)
			
    
			end
			
    
			
			return
			 
			
			f
			(
			

	
			withchildren
			(
			xnode
			,
			 
			cs
			)
			,
			 
			state
			)
			

			end
			

			

			
			

	
			catafold
			(
			f
			,
			 
			
			xleaf
			::

	
			Leaf
			,
			 
			state
			
			;
			 
			
			kwargs
			...
			)
			 
			=
			 
			
			f
			(
			xleaf
			,
			 
			state
			)
			

			

			
			
			
			"""
			

			    cata(f, tree)

			

			Transform every node in `tree` with function `f`.

			"""
			

			
			

	
			cata
			(
			f
			,
			 
			
			xnode
			::

	
			Node
			)
			 
			=
			 
			
			f
			(
			

	
			withchildren
			(
			xnode
			,
			 
			

	
			XTree
			[
			
			

	
			cata
			(
			f
			,
			 
			c
			)
			 
			for
			
			 
			c
			 
			in
			 
			
			children
			(
			xnode
			)
			]
			)
			)
			

			
			

	
			cata
			(
			f
			,
			 
			
			xleaf
			::

	
			Leaf
			)
			 
			=
			 
			
			f
			(
			xleaf
			)
			

			

			
			
			
			"""
			

			    fold(f, tree)

			

			Fold over tree in post-order iteration.

			

			## Examples

			

			{cell}

			```julia

			using Pollen

			node = Node(:table, Node(:row, 10, 10), Node(:row, 10, 10))

			Pollen.fold(node, 0) do x, subtree

			    subtree isa Leaf{Int} ? x + subtree[] : x

			end

			```

			"""
			

			
			function
			 
			

	
			fold
			(
			f
			,
			 
			
			tree
			::

	
			XTree
			,
			 
			init
			
			;
			 
			
			iterator
			 
			=
			 
			PostOrderDFS
			)
			
			
    
			
			foldl
			(
			f
			,
			 
			(
			
			l
			 
			for
			
			 
			l
			 
			in
			 
			
			iterator
			(
			tree
			)
			)
			
			;
			 
			
			init
			 
			=
			 
			init
			)
			

			end
			

			

			
			
			
			"""
			

			    fold(f, tree)

			

			Fold over all leaves in `tree` in post-order iteration.

			

			## Examples

			

			```julia

			node = Node(:table, Node(:row, 10, 10), Node(:row, 10, 10))

			Pollen.foldleaves((x, leaf) -> x + leaf[], node, 0)

			```

			"""
			

			
			

	
			foldleaves
			(
			f
			,
			 
			
			xnode
			::

	
			XTree
			,
			 
			init
			)
			 
			=
			 
			
			foldl
			(
			f
			,
			 
			(
			
			
			l
			[
			]
			 
			for
			
			 
			l
			 
			in
			 
			
			Leaves
			(
			xnode
			)
			)
			
			;
			 
			
			init
			 
			=
			 
			init
			)

Equality comparison for Nodes and Leafs. Short-circuits on the first mismatch.


			
			
			
			function
			 
			
			
			Base
			.
			
			:
			(
			==
			)
			(
			
			x1
			::

	
			Node
			,
			 
			
			x2
			::

	
			Node
			)
			
			
    
			
			return
			 
			(
			
			(
			
			

	
			tag
			(
			x1
			)
			 
			==
			 
			

	
			tag
			(
			x2
			)
			)
			 
			&&
			
			
            
			(
			
			

	
			attributes
			(
			x1
			)
			 
			==
			 
			

	
			attributes
			(
			x2
			)
			)
			 
			&&
			
			
            
			(
			
			
			length
			(
			
			children
			(
			x1
			)
			)
			 
			==
			 
			
			length
			(
			
			children
			(
			x2
			)
			)
			)
			 
			&&
			
            
			
			all
			(
			
			
			c1
			 
			==
			 
			c2
			 
			for
			
			 
			
			(
			c1
			,
			 
			c2
			)
			 
			in
			 
			
			zip
			(
			
			children
			(
			x1
			)
			,
			 
			
			children
			(
			x2
			)
			)
			)
			)
			

			end
			

			

			
			
			
			Base
			.
			
			:
			(
			==
			)
			(
			
			::

	
			Node
			,
			 
			_
			)
			 
			=
			 
			false
			

			
			
			
			Base
			.
			
			:
			(
			==
			)
			(
			_
			,
			 
			
			::

	
			Node
			)
			 
			=
			 
			false
			

			

			
			
			
			Base
			.
			
			:
			(
			==
			)
			(
			
			x1
			::

	
			Leaf
			,
			 
			
			x2
			::

	
			Leaf
			)
			 
			=
			
			 
			
			x1
			[
			]
			 
			==
			 
			
			x2
			[
			]
			

			
			
			
			Base
			.
			
			:
			(
			==
			)
			(
			
			::

	
			Leaf
			,
			 
			_
			)
			 
			=
			 
			false
			

			
			
			
			Base
			.
			
			:
			(
			==
			)
			(
			
			::

	
			Node
			,
			 
			
			::

	
			Leaf
			)
			 
			=
			 
			false
			

			
			
			
			Base
			.
			
			:
			(
			==
			)
			(
			
			::

	
			Leaf
			,
			 
			
			::

	
			Node
			)
			 
			=
			 
			false

Printing


			
			
			
			function
			 
			
			
			AbstractTrees
			.
			
			printnode
			(
			
			io
			::
			IO
			,
			 
			
			x
			::

	
			Node
			)
			
			
    
			
			rich
			 
			=
			
			 
			
			get
			(
			io
			,
			 
			
			:
			color
			,
			 
			false
			)
			 
			&&
			 
			
			!
			
			get
			(
			io
			,
			 
			
			:
			compact
			,
			 
			false
			)
			
    
			
			print
			(
			io
			,
			 
			
			"
			Node(:
			"
			)
			
    
			
			rich
			 
			&&
			 
			
			print
			(
			io
			,
			 
			
			crayon
			
			"
			bold
			"
			)
			
    
			
			print
			(
			io
			,
			 
			

	
			tag
			(
			x
			)
			)
			
    
			
			rich
			 
			&&
			 
			
			print
			(
			io
			,
			 
			
			crayon
			
			"
			reset
			"
			)
			
    
			
			if
			 
			
			!
			
			isempty
			(
			
			x
			.
			

	
			attributes
			)
			
			
        
			
			print
			(
			io
			,
			 
			
			"
			; 
			"
			)
			
        
			
			rich
			 
			&&
			 
			
			print
			(
			io
			,
			 
			
			crayon
			
			"
			dark_gray
			"
			)
			
        
			
			for
			
			 
			
			(
			i
			,
			 
			
			(
			key
			,
			 
			value
			)
			)
			 
			in
			 
			
			enumerate
			(
			
			x
			.
			

	
			attributes
			)
			
			
            
			
			if
			
			 
			i
			 
			!=
			 
			1
			
			
                
			
			print
			(
			io
			,
			 
			
			"
			, 
			"
			)
			
            
			end
			
            
			
			print
			(
			io
			,
			 
			key
			,
			 
			
			"
			 = 
			"
			)
			
            
			
			show
			(
			io
			,
			 
			value
			)
			
        
			end
			
        
			
			rich
			 
			&&
			 
			
			print
			(
			io
			,
			 
			
			crayon
			
			"
			reset
			"
			)
			
    
			end
			
    
			
			print
			(
			io
			,
			 
			
			"
			)
			"
			)
			

			end
			

			

			
			@
			testset
			 
			
			"
			XTree
			"
			 
			
			begin
			
    
			
			@
			testset
			 
			
			"
			Node constructors
			"
			 
			
			begin
			
        
			
			@
			test_nowarn
			 
			

	
			Node
			(
			
			:

	
			tag
			)
			
        
			
			@
			test
			
			 
			

	
			tag
			(
			

	
			Node
			(
			
			:

	
			tag
			)
			)
			 
			==
			 
			
			:

	
			tag
			
        
			
			@
			test
			 
			
			isempty
			(
			
			children
			(
			

	
			Node
			(
			
			:

	
			tag
			)
			)
			)
			
        
			
			@
			test
			 
			
			isempty
			(
			

	
			attributes
			(
			

	
			Node
			(
			
			:

	
			tag
			)
			)
			)
			
        
			
			@
			test_nowarn
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			
			[
			]
			)
			
        
			
			@
			test_nowarn
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			

	
			Leaf
			.
			
			(
			
			1
			:
			10
			)
			)
			
        
			
			@
			test
			
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			

	
			Leaf
			.
			
			(
			
			1
			:
			10
			)
			)
			 
			==
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			
			(
			
			1
			:
			10
			)
			...
			)
			
    
			end
			

			
    
			
			@
			test_nowarn
			 
			

	
			Leaf
			(
			1
			)
			
    
			
			@
			test_nowarn
			
			 
			

	
			Leaf
			(
			

	
			Leaf
			(
			1
			)
			)
			 
			isa
			 
			

	
			Leaf
			{
			Int
			}
			

			
    
			
			@
			testset
			 
			
			"
			with*
			"
			 
			
			begin
			
        
			
			node
			 
			=
			 
			

	
			Node
			(
			
			:

	
			tag
			)
			
        
			
			@
			test
			
			 
			

	
			tag
			(
			

	
			withtag
			(
			node
			,
			 
			
			:
			gat
			)
			)
			 
			==
			 
			
			:
			gat
			
        
			
			@
			test
			
			 
			
			length
			(
			
			children
			(
			

	
			withchildren
			(
			node
			,
			 
			

	
			Leaf
			.
			
			(
			
			1
			:
			10
			)
			)
			)
			)
			 
			==
			 
			10
			
        
			
			@
			test
			
			 
			
			

	
			attributes
			(
			

	
			withattributes
			(
			node
			,
			 
			
			Dict
			(
			
			
			:
			x
			 
			=>
			 
			
			"
			hi
			"
			)
			)
			)
			[
			
			:
			x
			]
			 
			==
			 
			
			"
			hi
			"
			
    
			end
			

			end
			

			

			
			@
			testset
			 
			
			"
			fold
			"
			 
			
			begin
			
    
			
			x
			 
			=
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			

	
			Leaf
			.
			
			(
			
			1
			:
			10
			)
			)
			
    
			
			@
			test
			
			 
			

	
			foldleaves
			(
			+
			,
			 
			x
			,
			 
			0
			)
			 
			==
			 
			
			sum
			(
			
			1
			:
			10
			)
			
    
			
			@
			test
			
			 
			

	
			foldleaves
			(
			*
			,
			 
			x
			,
			 
			1
			)
			 
			==
			 
			
			prod
			(
			
			1
			:
			10
			)
			
    
			
			x
			 
			=
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			
			"
			Hello
			"
			,
			 
			
			"
			World
			"
			)
			
    
			
			@
			test
			
			 
			

	
			foldleaves
			(
			*
			,
			 
			x
			,
			 
			
			"
			
			"
			)
			 
			==
			 
			
			"
			HelloWorld
			"
			

			end
			

			

			
			@
			testset
			 
			
			"
			cata
			"
			 
			
			begin
			
    
			
			x
			 
			=
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			

	
			Leaf
			.
			
			(
			
			1
			:
			10
			)
			)
			
    
			
			x_
			 
			=
			 
			
			

	
			cata
			(
			x
			)
			 
			do
			
			 
			node
			
			
        
			
			if
			
			 
			node
			 
			isa
			 

	
			Leaf
			
			
            
			
			return
			 
			

	
			Leaf
			(
			
			-
			
			node
			[
			]
			)
			
        
			else
			
			
            
			
			return
			 
			node
			
        
			end
			
    
			end
			
    
			
			@
			test
			
			 
			x_
			 
			==
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			

	
			Leaf
			.
			
			(
			
			-1
			:
			-1
			:
			-10
			)
			)
			

			end
			

			

			
			@
			testset
			 
			
			"
			catafold
			"
			 
			
			begin
			
    
			
			x
			 
			=
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			

	
			Leaf
			.
			
			(
			
			1
			:
			10
			)
			)
			
    
			
			
			x_
			,
			 
			n
			 
			=
			 
			
			

	
			catafold
			(
			x
			,
			 
			0
			)
			 
			do
			
			 
			node
			,
			 
			state
			
			
        
			
			if
			
			 
			node
			 
			isa
			 

	
			Leaf
			
			
            
			
			return
			
			 
			

	
			Leaf
			(
			
			-
			
			node
			[
			]
			)
			,
			
			 
			state
			 
			+
			 
			1
			
        
			else
			
			
            
			
			return
			
			 
			node
			,
			 
			state
			
        
			end
			
    
			end
			
    
			
			@
			test
			
			 
			x_
			 
			==
			 
			

	
			Node
			(
			
			:

	
			tag
			,
			 
			

	
			Leaf
			.
			
			(
			
			-1
			:
			-1
			:
			-10
			)
			)
			
    
			
			@
			test
			
			 
			n
			 
			==
			 
			10
			

			end