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 (↝) </p> > <p>zigarr (⇝)</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">⇝<!-- ⇝ --></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("→"),_ + op = "~>"::Symbol => + newNodes("",[formatHtml(first args,prec),tree("⇝"),_ 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("→"), _ + formatHtml(second args, prec)]) op = "+->"::Symbol => newNodes("", [s1, tree("|—›"), 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>→</mo>", + "<mo>⇝</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>→</mo>", s2] ops : S := op = 'LET => ":=" op = "<"::SY => "<" 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)