Fortran · 5135 bytes Raw Blame History
1 module jump_stack_module
2 use iso_fortran_env, only: int32
3 implicit none
4 private
5
6 public :: jump_stack_t
7 public :: init_jump_stack, cleanup_jump_stack
8 public :: push_jump_location, pop_jump_location
9 public :: peek_jump_location, is_jump_stack_empty
10
11 ! Maximum number of jump locations to track
12 integer, parameter :: MAX_JUMP_STACK = 100
13
14 ! Jump location entry
15 type :: jump_location_t
16 character(len=:), allocatable :: filename
17 integer(int32) :: line
18 integer(int32) :: column
19 end type jump_location_t
20
21 ! Jump stack for navigation history
22 type :: jump_stack_t
23 type(jump_location_t), allocatable :: locations(:)
24 integer :: top = 0
25 integer :: capacity = MAX_JUMP_STACK
26 end type jump_stack_t
27
28 contains
29
30 subroutine init_jump_stack(stack)
31 type(jump_stack_t), intent(out) :: stack
32
33 allocate(stack%locations(MAX_JUMP_STACK))
34 stack%top = 0
35 stack%capacity = MAX_JUMP_STACK
36 end subroutine init_jump_stack
37
38 subroutine cleanup_jump_stack(stack)
39 type(jump_stack_t), intent(inout) :: stack
40 integer :: i
41
42 if (allocated(stack%locations)) then
43 ! Deallocate all filename strings
44 do i = 1, stack%top
45 if (allocated(stack%locations(i)%filename)) then
46 deallocate(stack%locations(i)%filename)
47 end if
48 end do
49 deallocate(stack%locations)
50 end if
51 stack%top = 0
52 end subroutine cleanup_jump_stack
53
54 subroutine push_jump_location(stack, filename, line, column)
55 type(jump_stack_t), intent(inout) :: stack
56 character(len=*), intent(in) :: filename
57 integer(int32), intent(in) :: line, column
58 integer :: i
59
60 ! Don't push if same as current top location
61 if (stack%top > 0) then
62 if (allocated(stack%locations(stack%top)%filename)) then
63 if (stack%locations(stack%top)%filename == filename .and. &
64 stack%locations(stack%top)%line == line) then
65 return ! Don't duplicate the same location
66 end if
67 end if
68 end if
69
70 ! If stack is full, shift everything down
71 if (stack%top >= stack%capacity) then
72 ! Deallocate the first location's filename
73 if (allocated(stack%locations(1)%filename)) then
74 deallocate(stack%locations(1)%filename)
75 end if
76
77 ! Shift all locations down by one
78 do i = 1, stack%capacity - 1
79 stack%locations(i) = stack%locations(i + 1)
80 end do
81 stack%top = stack%capacity - 1
82 end if
83
84 ! Add new location
85 stack%top = stack%top + 1
86 if (allocated(stack%locations(stack%top)%filename)) then
87 deallocate(stack%locations(stack%top)%filename)
88 end if
89 allocate(character(len=len_trim(filename)) :: stack%locations(stack%top)%filename)
90 stack%locations(stack%top)%filename = trim(filename)
91 stack%locations(stack%top)%line = line
92 stack%locations(stack%top)%column = column
93 end subroutine push_jump_location
94
95 function pop_jump_location(stack, filename, line, column) result(success)
96 type(jump_stack_t), intent(inout) :: stack
97 character(len=:), allocatable, intent(out) :: filename
98 integer(int32), intent(out) :: line, column
99 logical :: success
100
101 success = .false.
102 if (stack%top <= 0) return
103
104 ! Get the top location
105 if (allocated(stack%locations(stack%top)%filename)) then
106 allocate(character(len=len(stack%locations(stack%top)%filename)) :: filename)
107 filename = stack%locations(stack%top)%filename
108 line = stack%locations(stack%top)%line
109 column = stack%locations(stack%top)%column
110
111 ! Remove from stack
112 deallocate(stack%locations(stack%top)%filename)
113 stack%top = stack%top - 1
114 success = .true.
115 end if
116 end function pop_jump_location
117
118 function peek_jump_location(stack, filename, line, column) result(success)
119 type(jump_stack_t), intent(in) :: stack
120 character(len=:), allocatable, intent(out) :: filename
121 integer(int32), intent(out) :: line, column
122 logical :: success
123
124 success = .false.
125 if (stack%top <= 0) return
126
127 ! Get the top location without removing it
128 if (allocated(stack%locations(stack%top)%filename)) then
129 allocate(character(len=len(stack%locations(stack%top)%filename)) :: filename)
130 filename = stack%locations(stack%top)%filename
131 line = stack%locations(stack%top)%line
132 column = stack%locations(stack%top)%column
133 success = .true.
134 end if
135 end function peek_jump_location
136
137 function is_jump_stack_empty(stack) result(is_empty)
138 type(jump_stack_t), intent(in) :: stack
139 logical :: is_empty
140
141 is_empty = (stack%top <= 0)
142 end function is_jump_stack_empty
143
144 end module jump_stack_module