On Sun, Nov 05, 2023 at 05:49:45PM +0100, Ralf Hemmecke wrote:
> On 11/4/23 19:34, Waldek Hebisch wrote:
> > Yes.  I am looking at other formatters.  For MathML we probably
> > should use appropriate unicode characters.  Two candidates I
> > found are:
> > 
> > 219D;RIGHTWARDS WAVE ARROW
> > 21DD;RIGHTWARDS SQUIGGLE ARROW;
> 
> There seem to be HTML names for it (see attachment).
> 
>     <p>rarrw  (&rarrw;) </p>
>     <p>zigarr (&zigrarr;)</p>
> 
> According to https://www.w3.org/TR/MathML2/byalpha.html it seems that these
> are also the MATHML names for these arrows.
> 
> BTW, when I enter $\rightsquigarrow$ into jFriCAS, then MathJax translates
> it to
> 
> <math xmlns="http://www.w3.org/1998/Math/MathML";>
>   <mo stretchy="false">&#x21DD;<!-- ⇝ --></mo>
> </math>
> 
> > By name the second is better match, but in my Firefox the
> > first looks a bit better.
> 
> I am definitely for zigarr (21DD).

OK.

> > > BTW, I wonder whether we could get rid of "TAG" and replace it with "~>" 
> > > or
> > > "LEADSTO" and either "->" or "TO", and "+->" or "MAPSTO" as the tags that
> > > appear in an OutputForm.
> > 
> > I am not sure what you exactly propose.  If we use 3 different symbols,
> > than changing "TAG" to "~>" in source files is reasonable.
> 
> I was not sure whether to use the arrow symbols itself as tags (OutputForm
> operators) or rather use names. I am OK with arrow symbols.
> 
> BTW, can you create a pull request with your proposed code, then I could add
> corrections to the formatters, if I find something incomplete.

Attached is complete diff + added file.  I did nothing for Fortran,
as the symbols are meanigless there.  I made hopefully correct
changes for other formatters.

-- 
                              Waldek Hebisch

-- 
You received this message because you are subscribed to the Google Groups 
"FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to fricas-devel+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/fricas-devel/ZUklFdGRJQW12M4P%40fricas.org.
diff --git a/src/algebra/fmt1d.spad b/src/algebra/fmt1d.spad
index 04858e0..d0a1c17 100644
--- a/src/algebra/fmt1d.spad
+++ b/src/algebra/fmt1d.spad
@@ -470,7 +470,8 @@ Here we (wrongly) return \verb|+%Infinity| and \verb|-%Infinity| for
         o(2, "and",         nary(" and ",      300, FE 300))
         o(2, "or",          nary(" or ",       200, FE 200))
         o(2, "LET",         nary(":=",         125, FE 125))
-        o(2, "TAG",         nary(" -> ",       100, FE 100))
+        o(2, "->",          nary("->",         1001, FE 1001))
+        o(2, "~>",          nary(" ~> ",       100, FE 100))
         o(2, "+->",         nary(" +-> ",      100, FE 100))
         o(2, "|",           nary(" | ",        100, FE 100))
 
diff --git a/src/algebra/fmt2d.spad b/src/algebra/fmt2d.spad
index 8325428..7210238 100644
--- a/src/algebra/fmt2d.spad
+++ b/src/algebra/fmt2d.spad
@@ -530,7 +530,8 @@ data structure.
         o(2, "and",         nary(" and ",      300, FE 300))
         o(2, "or",          nary(" or ",       200, FE 200))
         o(2, "LET",         nary(" := ",       125, FE 125))
-        o(2, "TAG",         nary(" -> ",       100, FE 100))
+        o(2, "->",          nary("->",         1001, FE 1001))
+        o(2, "~>",          nary(" ~> ",       100, FE 100))
         o(2, "+->",         nary(" +-> ",      100, FE 100))
         o(2, "|",           nary(" | ",        100, FE 100))
 
diff --git a/src/algebra/fmtlatex.spad b/src/algebra/fmtlatex.spad
index 480fc76..2ff0863 100644
--- a/src/algebra/fmtlatex.spad
+++ b/src/algebra/fmtlatex.spad
@@ -464,7 +464,8 @@ The operators have been mainly extracted from the definitions of
         o(2, "and",         nary("\land ",     300, FE 300))
         o(2, "or",          nary("\lor ",      200, FE 200))
         o(2, "LET",         nary("\coloneqq ", 125, FE 125))
-        o(2, "TAG",         nary("\to ",       100, FE 100))
+        o(2, "->",          nary("\to ",       1001, FE 1001))
+        o(2, "~>",          nary("\leadsto ",  100, FE 100))
         o(2, "+->",         nary("\mapsto ",   100, FE 100))
         o(2, "|",           nary("\mid ",      100, FE 100))
 
diff --git a/src/algebra/fmtmathjax.spad b/src/algebra/fmtmathjax.spad
index c2d5e72..0bd32f0 100644
--- a/src/algebra/fmtmathjax.spad
+++ b/src/algebra/fmtmathjax.spad
@@ -506,7 +506,8 @@ data structure.
         o(2, "and",         nary("\land ",     300, FE 300))
         o(2, "or",          nary("\lor ",      200, FE 200))
         o(2, "LET",         nary(":=",         125, FE 125))
-        o(2, "TAG",         nary("\to ",       100, FE 100))
+        o(2, "->",          nary("\to ",       1001, FE 1001))
+        o(2, "~>",          nary("\leadsto ",  100, FE 100))
         o(2, "+->",         nary("\mapsto ",   100, FE 100))
         o(2, "|",           nary("\mid ",      100, FE 100))
 
diff --git a/src/algebra/html.spad b/src/algebra/html.spad
index f50e748..d03c11f 100644
--- a/src/algebra/html.spad
+++ b/src/algebra/html.spad
@@ -217,8 +217,8 @@ HTMLFormat() : public == private where
     -- the precedence of / in the following is relatively low because
     -- the bar obviates the need for parentheses.
     binaryOps     : L Symbol := ["+->"::Symbol, '|, '^, '/, '<, '>, _
-        '=, 'OVER]
-    binaryPrecs   : L I := [0, 0, 900, 700, 400, 400, 400, 700]$(L I)
+        '=, 'OVER, "->"::Symbol]
+    binaryPrecs   : L I := [0, 0, 900, 700, 400, 400, 400, 700, 1001]$(L I)
     naryOps       : L S := ["-","+","*",blank,",",";"," ","ROW","",
        " \cr ","&","/\","\/"]$(L S)
     naryPrecs     : L I := [700, 700, 800, 800, 110, 110, 0, 0, 0, 0, 0, 600, 600]$(L I)
@@ -227,7 +227,7 @@ HTMLFormat() : public == private where
     plexPrecs     : L I := [700, 800, 700, 800, 700]$(L I)
     specialOps    : L Symbol := ['MATRIX, 'BRACKET, 'BRACE, 'CONCATB, _
                      'VCONCAT, 'AGGLST, 'CONCAT, 'OVERBAR, 'ROOT, 'SUB, _
-                     'TAG, 'SUPERSUB, 'ZAG, 'AGGSET, 'SC, 'PAREN,_
+                     "~>"::Symbol, 'SUPERSUB, 'ZAG, 'AGGSET, 'SC, 'PAREN,_
                      'SEGMENT, 'QUOTE, 'theMap, 'SLASH]
 
     -- the next two lists provide translations for some strings for
@@ -448,7 +448,7 @@ HTMLFormat() : public == private where
       row:Tree S := newNodes("tr id='nroot'",[cell1,cell2])
       newNode("table border='0' id='nroot'",row)
 
-    -- formatSpecial handles "theMap","AGGLST","AGGSET","TAG","SLASH",
+    -- formatSpecial handles "theMap","AGGLST","AGGSET","~>","SLASH",
     -- "VCONCAT", "CONCATB","CONCAT","QUOTE","BRACKET","BRACE","PAREN",
     -- "OVERBAR","ROOT", "SEGMENT","SC","MATRIX","ZAG"
     -- note "SUB" and "SUPERSUB" are handled directly by formatHtml
@@ -462,8 +462,8 @@ HTMLFormat() : public == private where
         formatNary(",",args,prec)
       op = 'AGGSET =>
         formatNary(";",args,prec)
-      op = 'TAG =>
-        newNodes("",[formatHtml(first args,prec),tree("&#x02192;"),_
+      op = "~>"::Symbol =>
+        newNodes("",[formatHtml(first args,prec),tree("&#x021DD;"),_
           formatHtml(second args, prec)])
         --RightArrow
       op = 'SLASH =>
@@ -790,6 +790,9 @@ HTMLFormat() : public == private where
           op = '^ => buildSuperscript(s1, s2)
           op = '/ => newNodes("", [s1, tree(string(op)), s2])
           op = 'OVER => buildOver(s1, s2)
+          op = "->"::Symbol =>
+              newNodes("",[formatHtml(first args,prec),tree("&#x02192;"), _
+              formatHtml(second args, prec)])
           op = "+->"::Symbol =>
               newNodes("", [s1, tree("|&mdash;&rsaquo;"), s2])
           newNodes("", [s1, tree(string(op)), s2])
@@ -946,7 +949,7 @@ HTMLFormat() : public == private where
           -- special cases
           -- specialOps are:
           -- MATRIX, BRACKET, BRACE, CONCATB, VCONCAT
-          -- AGGLST, CONCAT, OVERBAR, ROOT, SUB, TAG
+          -- AGGLST, CONCAT, OVERBAR, ROOT, SUB, "~>"
           -- SUPERSUB, ZAG, AGGSET, SC, PAREN
           -- SEGMENT, QUOTE, theMap, SLASH
           member?(op, specialOps) => formatSpecial(op, args, prec)
diff --git a/src/algebra/mathml.spad b/src/algebra/mathml.spad
index 5641f41..999c3d8 100644
--- a/src/algebra/mathml.spad
+++ b/src/algebra/mathml.spad
@@ -360,7 +360,8 @@ MathMLFormat() : public == private where
     plexPrecs     : L I := [ 750, 750, 750, 750, 700]$(L I)
 
     specialOps  : L(SY) := ['MATRIX, 'BRACKET, 'BRACE, 'CONCATB, 'VCONCAT,  _
-                             'AGGLST, 'CONCAT, 'OVERBAR, 'ROOT, 'SUB, 'TAG, _
+                             'AGGLST, 'CONCAT, 'OVERBAR, 'ROOT, 'SUB, _
+                             "~>"::Symbol, _
                              'SUPERSUB, 'ZAG, 'AGGSET, 'SC, 'PAREN, _
                              'SEGMENT, 'QUOTE, 'theMap, 'SLASH, 'PRIME, _
                              'BOX, 'EQUATNUM, 'BINOMIAL, 'NOTHING]
@@ -594,9 +595,9 @@ MathMLFormat() : public == private where
             formatNary(","::SY, "", 0, args, prec)
         op = 'AGGSET =>
             formatNary(";"::SY, "", 0, args, prec)
-        op = 'TAG =>
+        op = "~>"::Symbol =>
             group concat [formatExpr(first args, prec),
-                          "<mo>&#x02192;</mo>",
+                          "<mo>&#x021DD;</mo>",
                             formatExpr(second args, prec)]
                          --RightArrow
         op = 'SLASH =>
@@ -795,6 +796,7 @@ MathMLFormat() : public == private where
                                     s2, "</mrow></mfrac>"]
             op = 'OVER => concat ["<mfrac><mrow>", s1, "</mrow><mrow>",
                                   s2, "</mrow></mfrac>"]
+            op = "->"::SY => concat [s1, "<mo>&#x02192;</mo>", s2]
             ops : S :=
                 op = 'LET => ":="
                 op = "<"::SY => "&lt;"
diff --git a/src/algebra/outform.spad b/src/algebra/outform.spad
index a0f9823..a91a15b 100644
--- a/src/algebra/outform.spad
+++ b/src/algebra/outform.spad
@@ -615,7 +619,7 @@ OutputForm() : Join(SetCategory, ConvertibleTo InputForm) with
         assign(a, b) == convert [eform 'LET,     a, b]
 
         label(a, b) == convert [eform 'EQUATNUM, a, b]
-        rarrow(a, b)== convert [eform 'TAG, a, b]
+        rarrow(a, b)== convert [eform("~>"::Symbol), a, b]
         differentiate(a, nn)==
             zero? nn => a
             nn < 4 => prime(a, nn)
diff --git a/src/algebra/tex.spad b/src/algebra/tex.spad
index a70729d..3fb6b90 100644
--- a/src/algebra/tex.spad
+++ b/src/algebra/tex.spad
@@ -113,10 +113,10 @@ TexFormat() : public == private where
     -- the bar obviates the need for parentheses.
     binaryOps   : L(SY) := ["+->"::SY, "|"::SY, "^"::SY, "/"::SY, "="::SY,
                              "~="::SY, "<"::SY, "<="::SY, ">"::SY, ">="::SY,
-                               'OVER, 'LET]
+                               'OVER, 'LET, "->"::SY]
     binaryPrecs   : L I := [0, 0, 900, 700, 400,
                             400, 400, 400, 400, 400,
-                              700, 125]$(L I)
+                              700, 125, 1001]$(L I)
 
     naryOps     : L(SY) := ["-"::SY, "+"::SY, "*"::SY, ","::SY, ";"::SY,
                              'ROW, 'STRSEP, 'TENSOR]
@@ -128,7 +128,8 @@ TexFormat() : public == private where
     plexPrecs     : L I := [ 750, 750, 750, 750, 700]$(L I)
 
     specialOps  : L(SY) := ['MATRIX, 'BRACKET, 'BRACE, 'CONCATB, 'VCONCAT,  _
-                             'AGGLST, 'CONCAT, 'OVERBAR, 'ROOT, 'SUB, 'TAG, _
+                             'AGGLST, 'CONCAT, 'OVERBAR, 'ROOT, 'SUB, _
+                             "~>"::SY, _
                              'SUPERSUB, 'ZAG, 'AGGSET, 'SC, 'PAREN, _
                              'SEGMENT, 'QUOTE, 'theMap, 'SLASH, 'PRIME]
 
@@ -363,9 +364,9 @@ TexFormat() : public == private where
             formatNary(","::SY, "", 0, args, prec)
         op = 'AGGSET =>
             formatNary(";"::SY, "", 0, args, prec)
-        op = 'TAG =>
+        op = "~>"::SY =>
             group concat [formatExpr(first args, prec),
-                          "\rightarrow",
+                          "\rightsquigarrow",
                             formatExpr(second args, prec)]
         op = 'SLASH =>
             group concat [formatExpr(first args, prec),
@@ -523,6 +524,7 @@ TexFormat() : public == private where
             op = "^"::SY    => " \sp "
             op = "/"::SY     => " \over "
             op = 'OVER  => " \over "
+            op = "->"::SY => " \to "
             op = "+->"::SY   => " \mapsto "
             op = "~="::SY => " \ne "
             op = "<="::SY => " \leq "
diff --git a/src/algebra/texmacs.spad b/src/algebra/texmacs.spad
index c06627b..3d793ef 100644
--- a/src/algebra/texmacs.spad
+++ b/src/algebra/texmacs.spad
@@ -864,10 +864,10 @@ TexmacsFormat() : public == private where
     -- the bar obviates the need for parentheses.
     binaryOps   : L(SY) := ["+->"::SY, "|"::SY, "^"::SY, "/"::SY, "="::SY,
                              "~="::SY, "<"::SY, "<="::SY, ">"::SY, ">="::SY,
-                               'OVER, 'LET]
+                               'OVER, 'LET, "->"::SY]
     binaryPrecs   : L I := [0, 0, 900, 700, 400,
                             400, 400, 400, 400, 400,
-                              700, 125]$(L I)
+                              700, 125, 1001]$(L I)
 
     naryOps     : L(SY) := ["-"::SY, "+"::SY, "*"::SY, ","::SY, ";"::SY,
                              'ROW, 'STRSEP, 'TENSOR]
@@ -879,7 +879,8 @@ TexmacsFormat() : public == private where
     plexPrecs     : L I := [ 750, 750, 750, 750, 700]$(L I)
 
     specialOps  : L(SY) := ['MATRIX, 'BRACKET, 'BRACE, 'CONCATB, 'VCONCAT,  _
-                             'AGGLST, 'CONCAT, 'OVERBAR, 'ROOT, 'SUB, 'TAG, _
+                             'AGGLST, 'CONCAT, 'OVERBAR, 'ROOT, 'SUB, _
+                             "~>"::SY, _
                              'SUPERSUB, 'ZAG, 'AGGSET, 'SC, 'PAREN, _
                              'SEGMENT, 'QUOTE, 'theMap, 'SLASH, 'PRIME, _
                              'BOX, 'EQUATNUM, 'BINOMIAL, 'NOTHING]
@@ -1002,11 +1003,12 @@ TexmacsFormat() : public == private where
             formatNary(","::SY, "", 0, args, prec)
         op = 'AGGSET =>
             formatNary(";"::SY, "", 0, args, prec)
-        op = 'TAG =>
+        op = "~>"::SY =>
+            -- FIXME: Check for correctness
             group concat [formatExpr(first args, prec),
-                          " _"<rightarrow>_" ",
+                          " _"<rightsquigarrow>_" ",
                             formatExpr(second args, prec)]
-                         --RightArrow
+                         --right squiggy arrow
         op = 'SLASH =>
             group concat [formatExpr(first args, prec),
                           " _"/_" ", formatExpr(second args, prec)]
@@ -1226,6 +1228,7 @@ TexmacsFormat() : public == private where
                 op = ">"::SY => "<gtr>"
                 op = ">="::SY => "<geq>"
                 op = "+->"::SY => "<mapsto>"
+                op = "->"::SY => "<rightarrow>"
                 -- FIXME how to do this properly ???
                 op = 'LET   => ":="
                 string(op)
diff --git a/src/interp/Makefile.in b/src/interp/Makefile.in
index 72d19ac..42798fd 100644
--- a/src/interp/Makefile.in
+++ b/src/interp/Makefile.in
@@ -29,7 +29,7 @@ OBJ_files= macros setq \
 	i-coerce i-coerfn i-eval i-funsel i-intern \
 	i-map i-output i-resolv	i-spec1 i-spec2 i-syscmd \
 	i-toplev incl interop int-top lisplib macex match \
-	msg msgdb nlib nrunfast \
+	msg msgdb nformat nlib nrunfast \
 	nrungo nrunopt pathname pf2sex pile \
 	posit ptrees rulesets scan \
 	serror server setvars sfsfun simpbool slam \
diff --git a/src/interp/i-coerce.boot b/src/interp/i-coerce.boot
index a489a7a..2512ebd 100644
--- a/src/interp/i-coerce.boot
+++ b/src/interp/i-coerce.boot
@@ -741,7 +740,7 @@ typeIsASmallInteger x == (x = $SingleInteger)
 
 typeToInputForm(t) == typeToForm(t, '(InputForm))
 
-typeToOutputForm(t) == typeToForm(t, $OutputForm)
+typeToOutputForm(t) == constructor_to_OutputForm(t)
 
 typeToForm(t, toForm) ==
     t0 := devaluate(t)
diff --git a/src/interp/i-output.boot b/src/interp/i-output.boot
index c0d1910..0c3c672 100644
--- a/src/interp/i-output.boot
+++ b/src/interp/i-output.boot
@@ -46,7 +46,8 @@ init_output_properties() ==
       ["**", '"**"], ["^", '"^"], [":", '":"], ["::", '"::"], _
       ["@", '"@"], ["SEL", '"."], ["exquo", '" exquo "], ["div", '" div "], _
       ["quo", '" quo "], ["rem", '" rem "], ["case", '" case "], _
-      ["and", '" and "], ["or", '" or "], ["TAG", '" -> "], _
+      ["and", '" and "], ["or", '" or "], ["~>", '" ~> "], _
+      ["->", '"->"], _
       ["+->", '" +-> "], ["SEGMENT", '".."], ["in", '" in "], _
       ["~=", '"~="], ["JOIN", '" JOIN "], ["EQUATNUM", '"  "], _
       ["=", '" = "], ["==", '" == "], [">=", '" >= "], [">", '" > "], _
@@ -1310,25 +1329,24 @@ formattedFormat expr ==
   FORCE_-OUTPUT(get_formatted_stream())
   NIL
 
+do_formatters(x, was_type) ==
+    if $fortranFormat and not(was_type) then fortranFormat(x)
+    if $algebraFormat then mathprintWithNumber(x)
+    if $texFormat     then texFormat(x)
+    if $mathmlFormat  then mathmlFormat(x)
+    if $texmacsFormat then texmacsFormat(x)
+    if $htmlFormat    then htmlFormat(x)
+    if $formattedFormat then formattedFormat(x)
+
 output(expr,domain) ==
   $resolve_level : local := 0
   if isWrapped expr then expr := unwrap expr
   isMapExpr expr and not(domain is ["FunctionCalled", .]) => BREAK()
-  categoryForm? domain or domain = ["Mode"] =>
-    if $algebraFormat then
-      mathprintWithNumber outputDomainConstructor expr
-    if $texFormat     then
-      texFormat outputDomainConstructor expr
+  categoryForm?(domain) or domain = ["Mode"] =>
+      do_formatters(constructor_to_OutputForm(expr), true)
   T := coerceInteractive(objNewWrap(expr,domain),$OutputForm) =>
-    x := objValUnwrap T
-    if $fortranFormat then fortranFormat x
-    if $algebraFormat then
-      mathprintWithNumber x
-    if $texFormat     then texFormat x
-    if $mathmlFormat  then mathmlFormat x
-    if $texmacsFormat then texmacsFormat x
-    if $htmlFormat    then htmlFormat x
-    if $formattedFormat then formattedFormat x
+      x := objValUnwrap T
+      do_formatters(x, false)
   (FUNCTIONP(opOf domain)) and (not(SYMBOLP(opOf domain))) and
     (printfun := compiledLookup("<<",'(TextWriter TextWriter %), evalDomain domain))
        and (textwrit := compiledLookup("print", '(%), TextWriter())) =>
diff --git a/src/interp/spad.lisp b/src/interp/spad.lisp
index 7d18b3e..abf7938 100644
--- a/src/interp/spad.lisp
+++ b/src/interp/spad.lisp
@@ -85,7 +85,7 @@
 
 ; **** X. Random tables
 
-(MAKEPROP 'TAG '|Led| '(TAG TAG 122 121))
+(MAKEPROP '|~>| '|Led| '(|~>| |~>| 122 121))
 (MAKEPROP 'EQUATNUM '|Nud| '(|dummy| |dummy| 0 0))
 (MAKEPROP 'EQUATNUM '|Led| '(|dummy| |dummy| 10000 0))
 (MAKEPROP 'LET '|Led| '(|:=| LET 125 124))
)package "BOOT"

any_to_string(u) == WRITE_-TO_-STRING(u)

arg_to_OutputForm(arg, t, c) ==
    c => constructor_to_OutputForm(arg)
    isValidType(t) and PAIRP(t) and
            (GETDATABASE(first(t),'CONSTRUCTORKIND) = 'domain) =>
        (val := coerceInteractive(objNewWrap(arg, t), $OutputForm)) =>
            objValUnwrap(val)
        -- Wrong, but we try to produce something
        any_to_string(arg)
    -- Wrong, but we try to produce something
    any_to_string(arg)

prefix_to_string(con) ==
    u := prefix2String(con)
    atom(u) => u
    concatenateStringList([object2String(x) for x in u])

-- fake, to catch possible use
mkCategory_to_OutputForm(argl) ==
    throwMessage('"mkCategory_to_OutputForm called")

-- fake, to catch possible use
Join_to_OutputForm(argl) ==
    throwMessage('"Join_to_OutputForm called")

Record_to_OutputForm(argl) ==
    rres := []
    for [":", name, type] in argl repeat
        r1 := ['CONCAT, name, '":", constructor_to_OutputForm(type)]
        rres := cons(r1, rres)
    cons('Record, reverse(rres))

Union_to_OutputForm(argl) ==
    not(null(argl)) and (first(argl) is [":", name, type]) =>
        -- new style Union
        nargs := [['CONCAT, name, '":", constructor_to_OutputForm(type)]
                  for [":", name, type] in argl]
        ['Union, :nargs]
    -- old style
    nargs := [constructor_to_OutputForm(arg) for arg in argl]
    ['Union, :nargs]

Mapping_to_OutputForm(argl) ==
    -- should we allow this ???
    null(argl) => ['PAREN, ["->", '"()", '"()"]]
    rt := constructor_to_OutputForm(first(argl))
    nargs := [constructor_to_OutputForm(arg) for arg in rest(argl)]
    if #nargs > 1 then
        nargs := ['PAREN, ['AGGLST, :nargs]]
    else if null(nargs) then
        nargs := '"()"
    else
        nargs := first(nargs)
    ['PAREN, ["->", nargs, rt]]

constructor_to_OutputForm(con) ==
    if VECTORP(con) then
        con := devaluate(con)
    STRINGP(con) => CONCAT("_"", con, "_"")
    ATOM(con) =>
        con = $EmptyMode => '"?"
        -- Wrong, but we try to produce something printable
        any_to_string(con)
    op := first(con)
    argl := rest(con)

    op = 'Join => Join_to_OutputForm(argl)
    op = 'mkCategory => mkCategory_to_OutputForm(argl)
    op = 'Record => Record_to_OutputForm(argl)
    op = 'Union => Union_to_OutputForm(argl)
    op = 'Mapping => Mapping_to_OutputForm(argl)
    (abb := constructor?(op)) =>
        null(argl) => constructorName(op)
        con_sig := getConstructorSignature(op)
        cosig := GETDATABASE(op,'COSIG)
        null(con_sig) or null(cosig) =>
            -- Wrong, but we try to produce something
            prefix_to_string(con)
        con_sig := rest(con_sig)
        cosig := rest(cosig)
        if not freeOfSharpVars(con_sig) then
            con_sig := SUBLIS([[s_var, :val]
                               for s_var in $FormalMapVariableList
                               for val in argl], con_sig)
        n_argl := [arg_to_OutputForm(arg, t, c) for arg in argl
                   for t in con_sig for c in cosig]
        [constructorName(op), :n_argl]
    -- Wrong, but we try to produce something
    prefix_to_string(con)

Reply via email to