summaryrefslogtreecommitdiff
path: root/ipl/procs/ximage.icn
diff options
context:
space:
mode:
Diffstat (limited to 'ipl/procs/ximage.icn')
-rw-r--r--ipl/procs/ximage.icn209
1 files changed, 209 insertions, 0 deletions
diff --git a/ipl/procs/ximage.icn b/ipl/procs/ximage.icn
new file mode 100644
index 0000000..e50ae1c
--- /dev/null
+++ b/ipl/procs/ximage.icn
@@ -0,0 +1,209 @@
+############################################################################
+#
+# File: ximage.icn
+#
+# Subject: Procedures to produce string image of structured data
+#
+# Author: Robert J. Alexander
+#
+# Date: May 19, 1996
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+#
+# ximage(x) : s
+#
+# Produces a string image of x. ximage() differs from image() in that
+# it outputs all elements of structured data types. The output
+# resembles Icon code and is thus familiar to Icon programmers.
+# Additionally, it indents successive structural levels in such a way
+# that it is easy to visualize the data's structure. Note that the
+# additional arguments in the ximage procedure declaration are used for
+# passing data among recursive levels.
+#
+# xdump(x1,x2,...,xn) : xn
+#
+# Using ximage(), successively writes the images of x1, x2, ..., xn to
+# &errout.
+#
+# Some Examples:
+#
+# The following code:
+# ...
+# t := table() ; t["one"] := 1 ; t["two"] := 2
+# xdump("A table",t)
+# xdump("A list",[3,1,3,[2,4,6],3,4,3,5])
+#
+# Writes the following output (note that ximage() infers the
+# predominant list element value and avoids excessive output):
+#
+# "A table"
+# T18 := table(&null)
+# T18["one"] := 1
+# T18["two"] := 2
+# "A list"
+# L25 := list(8,3)
+# L25[2] := 1
+# L25[4] := L24 := list(3)
+# L24[1] := 2
+# L24[2] := 4
+# L24[3] := 6
+# L25[6] := 4
+# L25[8] := 5
+#
+
+
+procedure ximage(x,indent,done) #: string image of value
+ local i,s,ss,state,t,xtag,tp,sn,sz
+ static tr, name
+
+ initial name := proc("name", 0) # REG: in case name is a global
+
+ #
+ # If this is the outer invocation, do some initialization.
+ #
+ if /(state := done) then {
+ tr := &trace ; &trace := 0 # postpone tracing while in here
+ indent := ""
+ done := table()
+ }
+ #
+ # Determine the type and process accordingly.
+ #
+ indent := (if indent == "" then "\n" else "") || indent || " "
+ ss := ""
+ tp := type(x)
+ s := if xtag := \done[x] then xtag else case tp of {
+ #
+ # Unstructured types just return their image().
+ #
+ "integer": x
+ "null" | "string" | "real" | "cset" | "window" |
+ "co-expression" | "file" | "procedure" | "external": image(x)
+ #
+ # List.
+ #
+ "list": {
+ image(x) ? {
+ tab(6)
+ sn := tab(find("("))
+ sz := tab(0)
+ }
+ done[x] := xtag := "L" || sn
+ #
+ # Figure out if there is a predominance of any object in the
+ # list. If so, make it the default object.
+ #
+ t := table(0)
+ every t[!x] +:= 1
+ s := [,0]
+ every t := !sort(t) do if s[2] < t[2] then s := t
+ if s[2] > *x / 3 & s[2] > 2 then {
+ s := s[1]
+ t := ximage(s,indent || " ",done)
+ if t ? (not any('\'"') & ss := tab(find(" :="))) then
+ t := "{" || t || indent || " " || ss || "}"
+ }
+ else s := t := &null
+ #
+ # Output the non-defaulted elements of the list.
+ #
+ ss := ""
+ every i := 1 to *x do if x[i] ~=== s then {
+ ss ||:= indent || xtag || "[" || i || "] := " ||
+ ximage(x[i],indent,done)
+ }
+ s := tp || sz
+ s[-1:-1] := "," || \t
+ xtag || " := " || s || ss
+ }
+ #
+ # Set.
+ #
+ "set": {
+ image(x) ? {
+ tab(5)
+ sn := tab(find("("))
+ }
+ done[x] := xtag := "S" || sn
+ every i := !sort(x) do {
+ t := ximage(i,indent || " ",done)
+ if t ? (not any('\'"') & s := tab(find(" :="))) then
+ t := "{" || t || indent || " " || s || "}"
+ ss ||:= indent || "insert(" || xtag || "," || t || ")"
+ }
+ xtag || " := " || "set()" || ss
+ }
+ #
+ # Table.
+ #
+ "table": {
+ image(x) ? {
+ tab(7)
+ sn := tab(find("("))
+ }
+ done[x] := xtag := "T" || sn
+ #
+ # Output the table elements. This is a bit tricky, since
+ # the subscripts might be structured, too.
+ #
+ every i := !sort(x) do {
+ t := ximage(i[1],indent || " ",done)
+ if t ? (not any('\'"') & s := tab(find(" :="))) then
+ t := "{" || t || indent || " " || s || "}"
+ ss ||:= indent || xtag || "[" ||
+ t || "] := " ||
+ ximage(i[2],indent,done)
+ }
+ #
+ # Output the table, including its default value (which might
+ # also be structured).
+ #
+ t := ximage(x[[]],indent || " ",done)
+ if t ? (not any('\'"') & s := tab(find(" :="))) then
+ t := "{" || t || indent || " " || s || "}"
+ xtag || " := " || "table(" || t || ")" || ss
+ }
+ #
+ # Record.
+ #
+ default: {
+ image(x) ? {
+ move(7)
+ t := ""
+ while t ||:= tab(find("_")) || move(1)
+ t[-1] := ""
+ sn := tab(find("("))
+ }
+ done[x] := xtag := "R_" || t || "_" || sn
+ every i := 1 to *x do {
+ name(x[i]) ? (tab(find(".")),sn := tab(0))
+ ss ||:= indent || xtag || sn || " := " ||
+ ximage(\x[i],indent,done)
+ }
+ xtag || " := " || t || "()" || ss
+ }
+ }
+ #
+ # If this is the outer invocation, clean up before returning.
+ #
+ if /state then {
+ &trace := tr # restore &trace
+ }
+ #
+ # Return the result.
+ #
+ return s
+end
+
+
+#
+# Write ximages of x1,x1,...,xn.
+#
+procedure xdump(x[]) #: write images of values
+ every write(&errout,ximage(!x))
+ return x[-1] | &null
+end