summaryrefslogtreecommitdiff
path: root/ipl/mprogs/scat.icn
blob: 631be9cf9de5b51b16bdaed40d367dda1c070f7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
############################################################################
#
#	File:     scat.icn
#
#	Subject:  Program to produce call/result scatterplot
#
#	Author:   Clinton Jeffery
#
#	Date:     November 11, 1997
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
# Press the left mouse button atop any plotted point to see the list of
#  procedures at that point.  Execution (and point motion) is suspended
#  until the mouse button is released.
#
############################################################################
#
#  Requires:  Version 9 graphics
#
############################################################################
#
#  Links:   eemutils, vinit
#
############################################################################
#
#  Includes:  evdefs.icn
#
############################################################################

$include "evdefs.icn"

link emutils
link evinit

global	at,	# table of counts of procedures at a given point
	call,	# table of call counts
	rslt	# table of result counts

record activation (p, parent, children)

procedure main(av)
   local mask, maxmax, maxmatch, current_proc, L, max, i, k, child, e

   EvInit(av) | stop("*** cannot load SP")

   kill_output()

   &window := open("scat","x","geometry=150x180") | stop("can't open window")
   current_proc := activation(,activation(,,,,[]),[])
   call := table(0)
   rslt := table(0)
   at := table(0)
   mask := ProcMask ++ E_MXevent
   maxmax := 0
   maxmatch := 0

   while EvGet(mask) do {
	case &eventcode of {
  	   E_Pcall: {
	    move(&eventvalue, 1, 0)
    	      current_proc := activation(&eventvalue, current_proc, [])
    	      put(current_proc.parent.children, current_proc)
    	      }
  	   E_Psusp: {
	    move(current_proc.p, 0, 1)
    	      current_proc := current_proc.parent
    	      }
  	   E_Presum: {
    	      current_proc := current_proc.children[-1]
    	      }
  	   E_Pret: {
	    move(current_proc.p, 0, 1)
    	      pull(current_proc.parent.children)
    	      current_proc := current_proc.parent
    	      }
  	   E_Pfail: {
    	      pull(current_proc.parent.children)
    	      current_proc := current_proc.parent
    	      }
  	   E_Prem: {
    	      child := pull(current_proc.children)
    	      current_proc.children |||:= child.children
    	      }
	 E_MXevent: {
	    case &eventvalue of {
		 "q" | "\033": stop("terminated")
		 &lpress | &ldrag : {
		  repeat {
		     L := []
		     every k := key(call) do {
			if -3 < 2*log(call[k]+2,1.25)+2 - &x < 3 &
			   -3 < 2*log(rslt[k]+2,1.25)+2 - &y < 3 then {
			   put(L, procedure_name(k))
			   }
			}
		     if max := * (L[1]) then {
			every max <:= *( !L )
			maxmax <:= max
			}
		     maxmatch <:= *L
		     &col := WAttrib("columns") - maxmax
		     &row := WAttrib("lines") - maxmatch - 1
		     EraseArea(&x,&y)
		     if *L > 0 then {
			every i := 1 to *L do {
			   GotoRC(WAttrib("lines")-*L+i,WAttrib("columns")-max)
			   writes(&window,L[i])
			   }
			e := Event()
			every i := 1 to *L do {
			   GotoRC(WAttrib("lines")-*L+i,WAttrib("columns")-max)
			   writes(&window,L[i])
			   }
			}
		     else e := Event()
			
		     if e === &lrelease then break
		     }
		  }
		 }
	    }
	 }
	}

end

procedure procedure_name(p)
  return image(p) ? { ="procedure "; tab(0) }
end

procedure move(who, iscall, isrslt)
   if (at[integer(2*log(call[who]+2,1.25)) || "," || integer(2*log(rslt[who]+2,1.25))] -:= 1) = 0 then
      EraseArea(2*log(call[who]+2,1.25) + 2, 2*log(rslt[who]+2,1.25) + 2, 2, 2)
   call[who] +:= iscall
   rslt[who] +:= isrslt
   if (at[integer(2*log(call[who]+2,1.25)) || "," || integer(2*log(rslt[who]+2,1.25))] +:= 1) = 1 then
      FillRectangle(2*log(call[who]+2,1.25) + 2, 2*log(rslt[who]+2,1.25) + 2, 2, 2)
end