MODULE Unparse; (* Procedures for converting Juno values to texts *) IMPORT Text; CONST DefaultNumPrec = 4; PRIVATE VAR prec := DefaultNumPrec - 1; (* This module maintains a current numeric precision, which is the precision it uses when unparsing numbers. A number's "precision" is defined to be its number of significant digits. *) PROC SetNumPrec(p) IS prec := p - 1 END; PROC p := GetNumPrec() IS p := prec + 1 END; UI SetTool(SetNumPrec); (* Set/get the current numeric precision. *) UI Param(SetNumPrec, DefaultNumPrec); UI Param(SetNumPrec, 0); UI Param(SetNumPrec, 1); UI Param(SetNumPrec, 2); UI Param(SetNumPrec, 3); UI Param(SetNumPrec, 4); UI Param(SetNumPrec, 5); CONST DefaultBreakDepth = 0; PRIVATE VAR breakDepth := DefaultBreakDepth; (* This module maintains a list-breaking depth. *) PROC SetBreakDepth(d) IS breakDepth := d END; PROC d := GetBreakDepth() IS d := breakDepth END; UI SetTool(SetBreakDepth); (* Set/get the list break depth. *) UI Param(SetBreakDepth, DefaultBreakDepth); UI Param(SetBreakDepth, 0); UI Param(SetBreakDepth, 1); UI Param(SetBreakDepth, 2); UI Param(SetBreakDepth, 1000); PROC t := Point(p) IS t := "(" & Text.FromNum(CAR(p), prec) & ", " & Text.FromNum(CDR(p), prec) & ")" END; (* Return a textual representation of the point "p". It is a checked run-time error for "p" not to be a pair of numbers. *) PROC t := Value(val) IS t := ValueToDepth(val, 0) END; (* Set "t" to a textual representation of "val". By default, "t" will not contain any added newline characters. However, if "val" is a list and the current list break depth is positive, then list elements nested to a depth up to the current list break depth will be separated by newlines and enough spaces so they will be nicely formatted if rendered in a fixed-width font using any of the procedures in the "TypeLinesL" module. *) PRIVATE PROC t := ValueToDepth(val, depth) IS IF val = NIL -> t := "NIL" | TEXT(val) -> t := val | REAL(val) -> t := Text.FromNum(val, prec) | PAIR(val) -> IF IsList(CDR(val)) # NIL -> t := ListVal(val, depth) | t := Pair(val) FI FI END; PRIVATE PROC res := IsList(v) IS IF v = NIL -> res := 0 | PAIR(v) -> res := IsList(CDR(v)) | res := NIL FI END; /* Return non-NIL iff "v" is a list. */ PRIVATE PROC t := Pair(pr) IS t := "(" & ValueToDepth(CAR(pr), breakDepth) & ", " & ValueToDepth(CDR(pr), breakDepth) & ")" END; /* Return the textual representation of "pr", which is known to be a pair. */ PRIVATE PROC t := ListVal(l, depth) IS t := "[" & ValueToDepth(CAR(l), depth + 1) & ListBody(CDR(l), depth) & "]" END; /* Return a textual representation of "l", which is known to be a list. */ PRIVATE PROC t := ListBody(l, depth) IS IF l = NIL -> t := "" | depth < breakDepth -> t := ",\n " & Spaces(depth) & ValueToDepth(CAR(l), depth + 1) & ListBody(CDR(l), depth) | t := ", " & ValueToDepth(CAR(l), depth) & ListBody(CDR(l), depth) FI END; PRIVATE CONST SpacesStr = " "; PRIVATE VAR spacesStrLen := Text.Length(SpacesStr); PRIVATE PROC t := Spaces(n) IS t := ""; DO n > spacesStrLen -> t := t & SpacesStr; n := n - spacesStrLen OD; t := t & Text.Sub(SpacesStr, 0, n) END; /* Set "t" to a string of "n" spaces. */ PRIVATE VAR history := NIL; PROC Save() IS history := ((prec, breakDepth), history) END; PROC Restore() IS VAR head IN head := CAR(history); prec := CAR(head); breakDepth := CDR(head) END; history := CDR(history) END; UI PointTool(Save); UI PointTool(Restore); (* Save/restore the current state of this module. *)