I am playing around with this function
recursive function to_string(tree) result(out)
type(btree_t), pointer :: tree
character(len=:), allocatable :: out
character(len=1024) :: ch
select case(tree%binop)
case(0)
write(ch,"(i0)") int(tree%v)
out=trim(ch)
case(1)
out="("//to_string(tree%l)//"+"//to_string(tree%r)//")"
case(2)
out="("//to_string(tree%l)//"-"//to_string(tree%r)//")"
case(3)
out="("//to_string(tree%l)//"*"//to_string(tree%r)//")"
case(4)
out="("//to_string(tree%l)//"/"//to_string(tree%r)//")"
end select
out=trim(out)
end function to_string
It produces randomly unexpected results.
If I replace it with
recursive function to_string_trim(tree) result(out)
type(btree_t), pointer :: tree
character(len=:), allocatable :: out
character(len=1024) :: ch
select case(tree%binop)
case(0)
write(ch,"(i0)") int(tree%v)
out=trim(ch)
case(1)
out="("//trim(to_string(tree%l))//"+"//trim(to_string(tree%r))//")"
case(2)
out="("//trim(to_string(tree%l))//"-"//trim(to_string(tree%r))//")"
case(3)
out="("//trim(to_string(tree%l))//"*"//trim(to_string(tree%r))//")"
case(4)
out="("//trim(to_string(tree%l))//"/"//trim(to_string(tree%r))//")"
end select
end function to_string_trim
It works as expected.
Here is the whole code if you wish to try:
implicit none
type :: btree_t
integer :: id=0
type(btree_t), pointer :: l=>null()
type(btree_t), pointer :: r=>null()
integer :: binop=0
real :: v=0
end type
type :: dummy_t
end type
type :: btree_p
type(btree_t), pointer :: p=>null()
end type
interface operator(.op.)
procedure op_dummy_dummy
procedure op_dummy_btree
procedure op_btree_dummy
procedure op_btree_btree
end interface
type(btree_t), pointer :: e
type(dummy_t) :: a
type(btree_p) :: trees(6)
integer, allocatable :: operators(:)
real, allocatable :: values(:)
trees(1) % p=>((a.op.a).op.a).op.a
trees(2) % p=>(a.op.(a.op.a)).op.a
trees(3) % p=>(a.op.a).op.(a.op.a)
trees(4) % p=>((a.op.a).op.a).op.a
trees(5) % p=>(a.op.(a.op.a)).op.a
trees(6) % p=>(a.op.a).op.(a.op.a)
call swap(trees(4) % p)
call swap(trees(5) % p)
call swap(trees(6) % p)
block
integer :: itree
integer :: iop, jop, kop
!tree_loop: do itree=1,6
!do iop=1,4; do jop=1,4; do kop=1,4
itree=3
e=>trees(itree)%p
iop=3;jop=2;kop=3
operators=[iop,jop,kop]
values=[1.,1.,1.,13.]
call filltree(e, operators, values)
! if (eval(e)==24) exit tree_loop
! print"(a,a,i0,4x,3(i0,x))",to_string(e),"=",int(eval(e)),iop,jop,kop !this doesn't print correctly
print"(a,a,i0,4x,3(i0,x))",to_string_trim(e),"=",int(eval(e)),iop,jop,kop
!enddo;enddo;enddo
!end do tree_loop
!print"(a,a,i0,4x,3(i0,x))",to_string(e),"=",int(eval(e)),iop,jop,kop
end block
contains
function op_dummy_dummy(v1,v2) result(out)
type(dummy_t), intent(in) :: v1
type(dummy_t), intent(in) :: v2
type(btree_t), pointer :: a, b, out
allocate(out, a, b)
out%l=>a
out%r=>b
end function op_dummy_dummy
function op_btree_dummy(a,v2) result(out)
type(btree_t), intent(in), pointer :: a
type(dummy_t), intent(in) :: v2
type(btree_t), pointer :: b, out
allocate(out, b)
out%l=>a
out%r=>b
end function op_btree_dummy
function op_dummy_btree(v1,b) result(out)
type(dummy_t), intent(in) :: v1
type(btree_t), intent(in), pointer :: b
type(btree_t), pointer :: a, out
allocate(out, a)
out%l=>a
out%r=>b
end function op_dummy_btree
function op_btree_btree(a,b) result(out)
type(btree_t), intent(in), pointer :: a
type(btree_t), intent(in), pointer :: b
type(btree_t), pointer :: out
allocate(out)
out%l=>a
out%r=>b
end function op_btree_btree
recursive subroutine filltree(tree, operators, values)
type(btree_t), pointer :: tree, first, second
integer, allocatable :: operators(:)
integer, allocatable :: nextops(:)
real :: values(:)
if (associated(tree%l).and.associated(tree%r)) then
tree%binop=operators(1)
operators=operators(2:)
call filltree(tree%l, operators, values)
call filltree(tree%r, operators, values)
else
tree%v=values(1)
values=values(2:)
end if
end subroutine filltree
recursive subroutine swap(tree)
type(btree_t), pointer :: tree,a,b
a=>tree%l
b=>tree%r
if (tree%binop>0) then
call swap(a)
call swap(b)
tree%l=>b
tree%r=>a
end if
end subroutine swap
real recursive function eval(tree) result(out)
type(btree_t), pointer :: tree,a,b
a=>tree%l
b=>tree%r
select case (tree%binop)
case(0)
out=tree%v
case(1)
out=eval(a)+eval(b)
case(2)
out=eval(a)-eval(b)
case(3)
out=eval(a)*eval(b)
case(4)
out=eval(a)/eval(b)
end select
end function eval
recursive function to_string_l(tree) result(out)
type(btree_t), pointer :: tree
character(len=100) :: out
character(len=1024) :: ch
select case(tree%binop)
case(0)
write(ch,"(i0)") int(tree%v)
out=trim(ch)
case(1)
out="("//trim(to_string(tree%l))//"+"//trim(to_string(tree%r))//")"
case(2)
out="("//trim(to_string(tree%l))//"-"//trim(to_string(tree%r))//")"
case(3)
out="("//trim(to_string(tree%l))//"*"//trim(to_string(tree%r))//")"
case(4)
out="("//trim(to_string(tree%l))//"/"//trim(to_string(tree%r))//")"
end select
end function to_string_l
recursive function to_string_trim(tree) result(out)
type(btree_t), pointer :: tree
character(len=:), allocatable :: out
character(len=1024) :: ch
select case(tree%binop)
case(0)
write(ch,"(i0)") int(tree%v)
out=trim(ch)
case(1)
out="("//trim(to_string(tree%l))//"+"//trim(to_string(tree%r))//")"
case(2)
out="("//trim(to_string(tree%l))//"-"//trim(to_string(tree%r))//")"
case(3)
out="("//trim(to_string(tree%l))//"*"//trim(to_string(tree%r))//")"
case(4)
out="("//trim(to_string(tree%l))//"/"//trim(to_string(tree%r))//")"
end select
end function to_string_trim
recursive function to_string(tree) result(out)
type(btree_t), pointer :: tree
character(len=:), allocatable :: out
character(len=1024) :: ch
select case(tree%binop)
case(0)
write(ch,"(i0)") int(tree%v)
out=trim(ch)
case(1)
out="("//to_string(tree%l)//"+"//to_string(tree%r)//")"
case(2)
out="("//to_string(tree%l)//"-"//to_string(tree%r)//")"
case(3)
out="("//to_string(tree%l)//"*"//to_string(tree%r)//")"
case(4)
out="("//to_string(tree%l)//"/"//to_string(tree%r)//")"
end select
out=trim(out)
end function to_string
end
example output:
unexpected: ((1(1*13))=0 3 2 3
expected: ((1-1)*(1*13))=0 3 2 3
Can someone explain why this happens? Moreover, if you change the tree (itree
) then it works as expected to some other cases.