ref: 3f316c5c9265618fe7095cc39c4cb10909cbe468
parent: 8ef27e2fe652a8b29a8b57589863f2f2b45f9425
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Fri Jul 16 16:09:02 EDT 2021
Implement a bit more of prolog flag predicates set_prolog_flag/2 and current_prolog_flag/2
--- a/builtins.c
+++ b/builtins.c
@@ -38,7 +38,7 @@
BuiltinProto(builtincatch);
BuiltinProto(builtinthrow);
BuiltinProto(builtinsetprologflag);
-BuiltinProto(builtincurrentprologflag);
+BuiltinProto(builtincurrentprologflags);
BuiltinProto(builtinopen);
BuiltinProto(builtinclose);
BuiltinProto(builtincurrentinput);
@@ -125,10 +125,10 @@
return builtincatch;
if(Match(L"throw", 1))
return builtinthrow;
- if(Match(L"set_prolog_flag", 2))
+ if(Match(L"$set_prolog_flag", 2))
return builtinsetprologflag;
- if(Match(L"current_prolog_flag", 2))
- return builtincurrentprologflag;
+ if(Match(L"current_prolog_flags", 1))
+ return builtincurrentprologflags;
if(Match(L"open", 4))
return builtinopen;
if(Match(L"close", 2))
@@ -605,12 +605,13 @@
}
int
-builtincurrentprologflag(Term *goal, Binding **bindings, Module *module)
+builtincurrentprologflags(Term *goal, Binding **bindings, Module *module)
{
- USED(goal);
- USED(bindings);
USED(module);
- return 0;
+ Term *flagsandvals = goal->children;
+ Term *list = getallflags();
+ Term *realflagsandvals = mklist(list);
+ return unify(flagsandvals, realflagsandvals, bindings);
}
int
@@ -621,15 +622,7 @@
Term *key = goal->children;
Term *value = key->next;
- if(key->tag == VariableTerm || value->tag == VariableTerm)
- Throw(instantiationerror());
-
- if(key->tag != AtomTerm)
- Throw(typeerror(L"atom", key));
-
- Term *error = setflag(key->text, value);
- if(error)
- Throw(error);
+ setflag(key->text, value);
return 1;
}
--- a/dat.h
+++ b/dat.h
@@ -109,12 +109,47 @@
/* Flags */
enum {
+ BoundedTrue,
+ BoundedFalse,
+};
+
+enum {
+ IntegerRoundDown,
+ IntegerRoundTowardZero,
+};
+
+enum {
+ CharConversionOn,
+ CharConversionOff,
+};
+
+enum {
+ DebugOn,
+ DebugOff,
+};
+
+enum {
+ UnknownError,
+ UnknownFail,
+ UnknownWarning,
+};
+
+enum {
DoubleQuotesChars,
DoubleQuotesCodes,
DoubleQuotesAtom,
};
+int flagbounded;
+vlong flagmaxinteger;
+vlong flagmininteger;
+int flagintegerroundingfunction;
+int flagcharconversion;
+int flagdebug;
+vlong flagmaxarity;
+int flagunknown;
int flagdoublequotes;
+
/* State of the running system */
Choicepoint *choicestack;
--- a/flags.c
+++ b/flags.c
@@ -5,36 +5,160 @@
#include "dat.h"
#include "fns.h"
-Term *setdoublequotes(Term *);
+void setcharconversion(Term *);
+void setdebug(Term *);
+void setunknown(Term *);
+void setdoublequotes(Term *);
+static Rune *boundedvals[] = {
+ [BoundedTrue] = L"true",
+ [BoundedFalse] = L"false"
+};
+
+static Rune *integerroundvals[] = {
+ [IntegerRoundDown] = L"down",
+ [IntegerRoundTowardZero] = L"toward_zero"
+};
+
+static Rune *charconversionvals[] = {
+ [CharConversionOn] = L"on",
+ [CharConversionOff] = L"off"
+};
+
+static Rune *debugvals[] = {
+ [DebugOn] = L"on",
+ [DebugOff] = L"off"
+};
+
+static Rune *unknownvals[] = {
+ [UnknownError] = L"error",
+ [UnknownFail] = L"fail",
+ [UnknownWarning] = L"warning"
+};
+
+static Rune *doublequotesvals[] = {
+ [DoubleQuotesChars] = L"chars",
+ [DoubleQuotesCodes] = L"codes",
+ [DoubleQuotesAtom] = L"atom"
+};
+
void
initflags(void)
{
+ uvlong zero = 0;
+
+ flagbounded = BoundedTrue;
+ flagmaxinteger = (~zero)>>1;
+ flagmininteger = flagmaxinteger+1;
+ flagintegerroundingfunction = IntegerRoundDown;
+ flagcharconversion = CharConversionOff;
+ flagdebug = DebugOff;
+ flagunknown = UnknownError;
flagdoublequotes = DoubleQuotesChars;
}
-Term *
+void
setflag(Rune *flag, Term *value)
{
- if(runestrcmp(flag, L"double_quotes") == 0)
- return setdoublequotes(value);
- else
- return permissionerror(L"modify", L"flag", mkatom(flag));
+ if(runestrcmp(flag, L"char_conversion") == 0)
+ setcharconversion(value);
+ else if(runestrcmp(flag, L"debug") == 0)
+ setdebug(value);
+ else if(runestrcmp(flag, L"unknown") == 0)
+ setunknown(value);
+ else if(runestrcmp(flag, L"double_quotes") == 0)
+ setdoublequotes(value);
}
Term *
-setdoublequotes(Term *value)
+getallflags(void)
{
- if(value->tag != AtomTerm)
- return typeerror(L"atom", value);
+ Term *boundedval = mkatom(boundedvals[flagbounded]);
+ Term *maxintval = mkinteger(flagmaxinteger);
+ Term *minintval = mkinteger(flagmininteger);
+ Term *roundingval = mkatom(integerroundvals[flagintegerroundingfunction]);
+ Term *charconvval = mkatom(charconversionvals[flagcharconversion]);
+ Term *debugval = mkatom(debugvals[flagdebug]);
+ Term *unknownval = mkatom(unknownvals[flagunknown]);
+ Term *doublequotesval = mkatom(doublequotesvals[flagdoublequotes]);
- if(runestrcmp(value->text, L"chars") == 0)
- flagdoublequotes = DoubleQuotesChars;
- else if(runestrcmp(value->text, L"codes") == 0)
- flagdoublequotes = DoubleQuotesCodes;
- else if(runestrcmp(value->text, L"atom") == 0)
- flagdoublequotes = DoubleQuotesAtom;
- else
- return domainerror(L"flag_value", value);
- return nil;
+ Term *boundedkey = mkatom(L"bounded");
+ boundedkey->next = boundedval;
+ Term *maxintkey = mkatom(L"max_integer");
+ maxintkey->next = maxintval;
+ Term *minintkey = mkatom(L"min_integer");
+ minintkey->next = minintval;
+ Term *roundingkey = mkatom(L"integer_rounding_function");
+ roundingkey->next = roundingval;
+ Term *charconvkey = mkatom(L"character_conversion");
+ charconvkey->next = charconvval;
+ Term *debugkey = mkatom(L"debug");
+ debugkey->next = debugval;
+ Term *unknownkey = mkatom(L"unknown");
+ unknownkey->next = unknownval;
+ Term *doublequoteskey = mkatom(L"double_quotes");
+ doublequoteskey->next = doublequotesval;
+
+ Term *boundedflag = mkcompound(L"flag", 2, boundedkey);
+ Term *maxintflag = mkcompound(L"flag", 2, maxintkey);
+ Term *minintflag = mkcompound(L"flag", 2, minintkey);
+ Term *roundingflag = mkcompound(L"flag", 2, roundingkey);
+ Term *charconvflag = mkcompound(L"flag", 2, charconvkey);
+ Term *debugflag = mkcompound(L"flag", 2, debugkey);
+ Term *unknownflag = mkcompound(L"flag", 2, unknownkey);
+ Term *doublequotesflag = mkcompound(L"flag", 2, doublequoteskey);
+
+ boundedflag->next = maxintflag;
+ maxintflag->next = minintflag;
+ minintflag->next = roundingflag;
+ roundingflag->next = charconvflag;
+ charconvflag->next = debugflag;
+ debugflag->next = unknownflag;
+ unknownflag->next = doublequotesflag;
+
+ return boundedflag;
+}
+
+void
+setcharconversion(Term *value)
+{
+ int max = 2;
+ int i;
+ for(i = 0; i < max; i++){
+ if(runestrcmp(value->text, charconversionvals[i]) == 0)
+ flagcharconversion = i;
+ }
+}
+
+void
+setdebug(Term *value)
+{
+ int max = 2;
+ int i;
+ for(i = 0; i < max; i++){
+ if(runestrcmp(value->text, debugvals[i]) == 0)
+ flagdebug = i;
+ }
+}
+
+void
+setunknown(Term *value)
+{
+ int max = 3;
+ int i;
+ for(i = 0; i < max; i++){
+ if(runestrcmp(value->text, unknownvals[i]) == 0)
+ flagunknown = i;
+ }
+}
+
+void
+setdoublequotes(Term *value)
+{
+ int max = 3;
+ int i;
+ for(i = 0; i < max; i++){
+ if(runestrcmp(value->text, doublequotesvals[i]) == 0)
+ flagdoublequotes = i;
+ }
}
\ No newline at end of file
--- a/fns.h
+++ b/fns.h
@@ -30,7 +30,8 @@
/* flags.c */
void initflags(void);
-Term *setflag(Rune *, Term *);
+void setflag(Rune *, Term *);
+Term *getallflags(void);
/* error.c */
Term *instantiationerror(void);
--- a/repl.pl
+++ b/repl.pl
@@ -52,8 +52,10 @@
write_result([B|Bs], State) :- write_bindings([B|Bs]), write_state(State).
write_bindings([]).
-write_bindings([B|Bs]) :-
- write(B),
+write_bindings([Var = Val|Bs]) :-
+ write(Var),
+ write(' = '),
+ writeq(Val),
( Bs = []
-> true
; put_char(','), nl
--- a/stdlib.pl
+++ b/stdlib.pl
@@ -549,3 +549,60 @@
nl(S) :-
put_char(S, '
'). % This should really be \n
+
+% flags
+set_prolog_flag(Flag, Value) :-
+ is_nonvar(Flag),
+ is_nonvar(Value),
+ is_atom(Flag),
+ is_prolog_flag(Flag),
+ is_appropriate_flag_value(Flag, Value),
+ is_modifiable_flag(Flag),
+ '$set_prolog_flag'(Flag, Value).
+
+current_prolog_flag(Flag, Value) :-
+ is_atom_or_var(Flag),
+ ( atom(Flag)
+ -> is_prolog_flag(Flag)
+ ; true
+ ),
+ current_prolog_flags(FlagsAndValues),
+ member(flag(Flag, Value), FlagsAndValues).
+
+is_prolog_flag(Flag) :-
+ member(Flag,
+ [ bounded
+ , max_integer
+ , min_integer
+ , integer_rounding_function
+ , char_conversion
+ , debug
+ , max_arity
+ , unknown
+ , double_quotes]),
+ !
+ ; domain_error(prolog_flag, Flag).
+
+is_modifiable_flag(Flag) :-
+ member(Flag, [char_conversion, debug, unknown, double_quotes]),
+ !
+ ; permission_error(modify, flag, Flag).
+
+is_appropriate_flag_value(Flag, Value) :-
+ appropriate_flag_values(Flag, Values),
+ member(Value, Values),
+ !
+ ; domain_error(flag_value, Flag + Value).
+
+appropriate_flag_values(bounded, [true, false]).
+appropriate_flag_values(max_integer, [Val]) :-
+ current_prolog_flag(max_integer, Val).
+appropriate_flag_values(min_integer, [Val]) :-
+ current_prolog_flag(min_integer, Val).
+appropriate_flag_values(integer_rounding_function, [down, toward_zero]).
+appropriate_flag_values(char_conversion, [on, off]).
+appropriate_flag_values(debug, [on, off]).
+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