ref: e6ce8b1d6da2434232b86c7c115d7ed4961e7f5c
parent: 1c840d5c5ab6326492542886297d5bafa2877c4d
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Tue Jul 20 14:05:21 EDT 2021
Add op/3 and current_op/3
--- a/builtins.c
+++ b/builtins.c
@@ -66,6 +66,8 @@
BuiltinProto(builtinflushoutput);
BuiltinProto(builtinstreamproperties);
BuiltinProto(builtinsetstreamposition);
+BuiltinProto(builtinop);
+BuiltinProto(builtincurrentops);
int compareterms(Term *, Term *);
@@ -187,6 +189,10 @@
return builtinstreamproperties;
if(Match(L"set_stream_position", 2))
return builtinsetstreamposition;
+ if(Match(L"$op", 3))
+ return builtinop;
+ if(Match(L"current_ops", 1))
+ return builtincurrentops;
return nil;
}
@@ -1508,4 +1514,81 @@
reposition(s, pos->ival);
return 1;
+}
+
+int
+builtinop(Term *goal, Binding **bindings, Module *module)
+{
+ USED(bindings);
+ Term *priority = goal->children;
+ Term *specifier = priority->next;
+ Term *operator = specifier->next;
+
+ if(runestrcmp(operator->text, L",") == 0)
+ Throw(permissionerror(L"modify", L"operator", operator));
+
+ int type = 0;
+ if(runestrcmp(specifier->text, L"xf") == 0)
+ type = Xf;
+ else if(runestrcmp(specifier->text, L"yf") == 0)
+ type = Yf;
+ else if(runestrcmp(specifier->text, L"xfx") == 0)
+ type = Xfx;
+ else if(runestrcmp(specifier->text, L"xfy") == 0)
+ type = Xfy;
+ else if(runestrcmp(specifier->text, L"yfx") == 0)
+ type = Yfx;
+ else if(runestrcmp(specifier->text, L"fy") == 0)
+ type = Fy;
+ else if(runestrcmp(specifier->text, L"fx") == 0)
+ type = Fx;
+
+ addoperator(priority->ival, type, operator->text, module);
+ return 1;
+}
+
+int
+builtincurrentops(Term *goal, Binding **bindings, Module *module)
+{
+ Term *ops = goal->children;
+ Term *oplist = nil;
+
+ int level;
+ for(level = 0; level < PrecedenceLevels; level++){
+ Operator *o;
+ for(o = module->operators[level]; o != nil; o = o->next){
+ int type = o->type;
+ while(type != 0){
+ Term *args = mkinteger(o->level);
+ if(type & Xf){
+ args->next = mkatom(L"xf");
+ type = type^Xf;
+ }else if(type & Yf){
+ args->next = mkatom(L"yf");
+ type = type^Yf;
+ }else if(type & Xfx){
+ args->next = mkatom(L"xfx");
+ type = type^Xfx;
+ }else if(type & Xfy){
+ args->next = mkatom(L"xfy");
+ type = type^Xfy;
+ }else if(type & Yfx){
+ args->next = mkatom(L"yfx");
+ type = type^Yfx;
+ }else if(type & Fx){
+ args->next = mkatom(L"fx");
+ type = type^Fx;
+ }else if(type & Fy){
+ args->next = mkatom(L"fy");
+ type = type^Fy;
+ }
+ args->next->next = mkatom(o->spelling);
+ Term *op = mkcompound(L"op", 3, args);
+ oplist = appendterm(oplist, op);
+ }
+ }
+ }
+
+ Term *realops = mklist(oplist);
+ return unify(ops, realops, bindings);
}
\ No newline at end of file
--- a/parser.c
+++ b/parser.c
@@ -281,7 +281,7 @@
if(index == -1){
print("Can't parse, list of length %d contains no operators: ", length);
for(i = 0; i < length; i++)
- print("%S(%d) ", prettyprint(terms[i], 0, 0, 0, currentmod), infos[i].level);
+ print("%S(%d) ", prettyprint(terms[i], 0, 1, 0, currentmod), infos[i].level);
print("\n");
syntaxerror_parser("parseoperators");
}
--- a/stdlib.pl
+++ b/stdlib.pl
@@ -354,6 +354,8 @@
is_list(T) :- list(T), ! ; type_error(list, T).
+is_integer(T) :- integer(T), ! ; type_error(integer, T).
+
% All solutions
findall(Template, Goal, Instances) :-
@@ -628,4 +630,51 @@
appropriate_flag_values(max_arity, [Val]) :-
current_prolog_flag(max_arity).
appropriate_flag_values(unknown, [error, fail, warning]).
-appropriate_flag_values(double_quotes, [chars, codes, atom]).
\ No newline at end of file
+appropriate_flag_values(double_quotes, [chars, codes, atom]).
+
+% Operator table modification and inspection
+
+op(Priority, Op_specifier, Operator) :-
+ is_nonvar(Priority),
+ is_integer(Priority),
+ is_nonvar(Op_specifier),
+ is_atom(Op_specifier),
+ ( operator_priority(Priority), !
+ ; domain_error(operator_priority, Priority)
+ ),
+ ( operator_specifier(Op_specifier), !
+ ; domain_error(operator_specifier, Op_specifier)
+ ),
+ is_nonvar(Operator),
+ ( atom(Operator)
+ -> Ops = [Operator]
+ ; Ops = Operator
+ ),
+ is_list(Ops),
+ op_helper(Priority, Op_specifier, Ops).
+
+op_helper(Priority, Op_specifier, []).
+op_helper(Priority, Op_specifier, [Op|Ops]) :-
+ is_nonvar(Op),
+ is_atom(Op),
+ '$op'(Priority, Op_specifier, Op),
+ op_helper(Priority, Op_specifier, Ops).
+
+operator_priority(P) :-
+ integer(P),
+ P >= 0,
+ P =< 1200.
+
+operator_specifier(S) :-
+ member(S, [xf, yf, xfx, xfy, yfx, fx, fy]).
+
+current_op(Priority, Op_specifier, Operator) :-
+ ( (var(Priority) ; operator_priority(Priority)), !
+ ; domain_error(operator_priority, Priority)
+ ),
+ ( (var(Op_specifier) ; operator_specifier(Op_specifier)), !
+ ; domain_error(operator_specifier, Op_specifier)
+ ),
+ is_atom_or_var(Operator),
+ current_ops(Operators),
+ member(op(Priority, Op_specifier, Operator), Operators).
\ No newline at end of file