From 1c8789198373a52da9e80dc9b2b1ee2b67af61c4 Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Fri, 16 Jul 2021 00:42:49 +0000 Subject: Make operators local to each module, and implement some more correct prettyprint code, used by write_term --- prettyprint.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 18 deletions(-) (limited to 'prettyprint.c') diff --git a/prettyprint.c b/prettyprint.c index ce75371..ec00583 100644 --- a/prettyprint.c +++ b/prettyprint.c @@ -5,31 +5,77 @@ #include "dat.h" #include "fns.h" -Rune *prettyprintlist(Term *, Rune *, int, int, int, int); -Rune *printlist(Term *, int, int, int); +Rune *prettyprintlist(Term *, Rune *, int, int, int, int, Module *); +Rune *printlist(Term *, int, int, int, Module *); int islist(Term *); +int needsquotes(Rune *); Rune * -prettyprint(Term *t, int quoted, int ignoreops, int numbervars) +prettyprint(Term *t, int quoted, int ignoreops, int numbervars, Module *mod) { Rune *result; Rune *args; + if(mod == nil) + mod = usermodule; switch(t->tag){ case CompoundTerm: - args = printlist(t, quoted, ignoreops, numbervars); - if(args == nil){ - args = prettyprintlist(t->children, L", ", 0, quoted, ignoreops, numbervars); - result = runesmprint("%S(%S)", t->text, args); - free(args); - }else + if(numbervars && t->arity == 1 + && t->children->tag == IntegerTerm + && t->children->ival >= 0 + && runestrcmp(t->text, L"$VAR") == 0){ + vlong n = t->children->ival; + Rune i = L'A' + (n % 26); + vlong j = n / 26; + if(j == 0) + result = runesmprint("%C", i); + else + result = runesmprint("%C%lld", i, j); + break; + } + args = printlist(t, quoted, ignoreops, numbervars, mod); + if(args && !ignoreops){ result = runesmprint("[%S]", args); + free(args); + break; + } + Operator *op = getoperator(t->text, mod); + if(op == nil || ignoreops || !(t->arity == 1 || t->arity == 2)){ + Rune *functor = prettyprint(mkatom(t->text), quoted, ignoreops, numbervars, mod); + args = prettyprintlist(t->children, L", ", 0, quoted, ignoreops, numbervars, mod); + result = runesmprint("%S(%S)", functor, args); + free(functor); + free(args); + break; + }else{ + /* TODO: + 1) Only print spacing between op and args when needed + 2) currectly add () around args in special cases (see 7.10.5.h.2 in spec) + */ + Rune *functor = prettyprint(mkatom(t->text), quoted, ignoreops, numbervars, mod); + Rune *arg1 = prettyprint(t->children, quoted, ignoreops, numbervars, mod); + Rune *arg2 = t->arity == 2 ? prettyprint(t->children->next, quoted, ignoreops, numbervars, mod) : nil; + if(t->arity == 2) + result = runesmprint("%S %S %S", arg1, functor, arg2); + else{ + if(op->type == Xf || op->type == Yf) + result = runesmprint("%S %S", arg1, functor); + else + result = runesmprint("%S %S", functor, arg1); + } + free(functor); + free(arg1); + free(arg2); + } break; case AtomTerm: - result = runesmprint("%S", t->text); + if(quoted && needsquotes(t->text)) + result = runesmprint("'%S'", t->text); + else + result = runesmprint("%S", t->text); break; case VariableTerm: - result = runesmprint("%S(%ulld)", t->text, t->clausenr); + result = runesmprint("_%S", t->text); break; case FloatTerm: result = runesmprint("%f", t->dval); @@ -46,7 +92,7 @@ prettyprint(Term *t, int quoted, int ignoreops, int numbervars) } Rune * -prettyprintlist(Term *t, Rune *sep, int end, int quoted, int ignoreops, int numbervars) +prettyprintlist(Term *t, Rune *sep, int end, int quoted, int ignoreops, int numbervars, Module *mod) { if(t == nil){ if(end) @@ -55,8 +101,8 @@ prettyprintlist(Term *t, Rune *sep, int end, int quoted, int ignoreops, int numb return runesmprint(""); } - Rune *str = prettyprint(t, quoted, ignoreops, numbervars); - Rune *rest = prettyprintlist(t->next, sep, end, quoted, ignoreops, numbervars); + Rune *str = prettyprint(t, quoted, ignoreops, numbervars, mod); + Rune *rest = prettyprintlist(t->next, sep, end, quoted, ignoreops, numbervars, mod); Rune *result; if(t->next != nil) @@ -71,7 +117,7 @@ prettyprintlist(Term *t, Rune *sep, int end, int quoted, int ignoreops, int numb /* printlist prints a list's elements but not the surrounding [ and ] */ Rune * -printlist(Term *list, int quoted, int ignoreops, int numbervars) +printlist(Term *list, int quoted, int ignoreops, int numbervars, Module *mod) { if(list->tag != CompoundTerm || list->arity != 2 || runestrcmp(L".", list->text) != 0) return nil; @@ -79,20 +125,50 @@ printlist(Term *list, int quoted, int ignoreops, int numbervars) Term *head = list->children; Term *tail = head->next; - Rune *headstr = prettyprint(head, quoted, ignoreops, numbervars); + Rune *headstr = prettyprint(head, quoted, ignoreops, numbervars, mod); Rune *tailstr = nil; Rune *result; if(tail->tag == CompoundTerm && tail->arity == 2 && runestrcmp(L".", tail->text) == 0){ - tailstr = printlist(tail, quoted, ignoreops, numbervars); + tailstr = printlist(tail, quoted, ignoreops, numbervars, mod); result = runesmprint("%S, %S", headstr, tailstr); }else if(tail->tag == AtomTerm && runestrcmp(L"[]", tail->text) == 0){ result = runesmprint("%S", headstr); }else{ - tailstr = prettyprint(tail, quoted, ignoreops, numbervars); + tailstr = prettyprint(tail, quoted, ignoreops, numbervars, mod); result = runesmprint("%S | %S", headstr, tailstr); } free(headstr); free(tailstr); return result; } + +int +needsquotes(Rune *text) +{ + Rune *graphics = L"#$&*+-./:<=>?@^~\\"; /* keep in sync with lexer */ + int len = runestrlen(text); + int i; + + if(runestrcmp(text, L"") == 0) + return 1; + + if(runestrchr(graphics, text[0])){ + for(i = 0; i < len; i++){ + if(!runestrchr(graphics, text[i])) + return 1; + } + return 0; + } + + if(len == 1 && runestrchr(L";!,", text[0])) + return 0; + + if(len > 0 && !islowerrune(text[0])) + return 1; + + for(i = 0; i < len; i++) + if(!isalpharune(text[i])) + return 1; + return 0; +} \ No newline at end of file -- cgit v1.2.3