114 lines
3.0 KiB
Erlang
114 lines
3.0 KiB
Erlang
-module(wfc_eval_context).
|
|
-vsn("0.2.0").
|
|
|
|
-export_type([
|
|
context/0
|
|
]).
|
|
|
|
-export([
|
|
new/0,
|
|
default/0,
|
|
default_snowflakes/0,
|
|
define/3,
|
|
undefine/2,
|
|
resolve_pattern/2,
|
|
resolve_snowflake/2
|
|
]).
|
|
|
|
-type sentence() :: wfc_sentence:sentence().
|
|
|
|
-record(ctx,
|
|
{snowflakes = #{} :: #{binary() := fun(([sentence()]) -> {ok, sentence()} | {error, string()})},
|
|
patterns = #{} :: #{binary() := sentence()}}).
|
|
|
|
-opaque context() :: #ctx{}.
|
|
|
|
|
|
new() ->
|
|
#ctx{snowflakes = #{},
|
|
patterns = #{}}.
|
|
|
|
|
|
default() ->
|
|
#ctx{snowflakes = default_snowflakes()}.
|
|
|
|
default_snowflakes() ->
|
|
#{<<"and">> => fun wfc:mul/1,
|
|
<<"xor">> => fun wfc:add/1,
|
|
<<"implies">> => fun snf_implies/1,
|
|
<<"ior">> =>
|
|
fun IOR([S1 | Rest]) ->
|
|
case IOR(Rest) of
|
|
{ok, S2} -> {ok, sf_ior(S1, S2)};
|
|
Error -> Error
|
|
end;
|
|
IOR([]) ->
|
|
{ok, wfc:one()}
|
|
end,
|
|
<<"not">> =>
|
|
fun ([S]) -> {ok, sf_not(S)};
|
|
(Bad) -> {error, wfc_utils:str("not/1: wrong number of arguments: ~p", [Bad])}
|
|
end,
|
|
<<"impliedby">> =>
|
|
fun ([A, B]) -> {ok, sf_impliedby(A, B)};
|
|
(Bad) -> {error, wfc_utils:str("impliedby/2: wrong number of arguments: ~p", [Bad])}
|
|
end,
|
|
<<"iff">> =>
|
|
fun ([A, B]) -> {ok, sf_iff(A, B)};
|
|
(Bad) -> {error, wfc_utils:str("iff/2: wrong number of arguments: ~p", [Bad])}
|
|
end
|
|
}.
|
|
|
|
snf_implies([A, B]) -> {ok, sf_implies(A, B)};
|
|
snf_implies(Bad) -> {error, wfc_utils:str("implies/2: wrong number of arguments: ~p", [Bad])}.
|
|
|
|
|
|
sf_ior(A, B) ->
|
|
wfc_sftt:appl_ttf(fun ttf_ior/2, [A, B]).
|
|
|
|
sf_not(A) ->
|
|
{ok, Result} = wfc:add([wfc_sentence:one(), A]),
|
|
Result.
|
|
|
|
sf_implies(A, B) ->
|
|
wfc_sftt:appl_ttf(fun ttf_implies/2, [A, B]).
|
|
|
|
sf_impliedby(A, B) ->
|
|
sf_implies(B, A).
|
|
|
|
sf_iff(A, B) ->
|
|
{ok, Result} = wfc:mul([sf_implies(A, B), sf_impliedby(A, B)]),
|
|
Result.
|
|
|
|
ttf_ior(0, 0) -> 0;
|
|
ttf_ior(1, 0) -> 1;
|
|
ttf_ior(0, 1) -> 1;
|
|
ttf_ior(1, 1) -> 1.
|
|
|
|
ttf_implies(0, 0) -> 1;
|
|
ttf_implies(1, 0) -> 0;
|
|
ttf_implies(0, 1) -> 1;
|
|
ttf_implies(1, 1) -> 1.
|
|
|
|
|
|
|
|
define(Pat, Sentence, Ctx = #ctx{patterns = OldPatterns}) ->
|
|
NewPatterns = maps:put(Pat, Sentence, OldPatterns),
|
|
{ok, Ctx#ctx{patterns = NewPatterns}}.
|
|
|
|
undefine(Pat, Ctx = #ctx{patterns = OldPatterns}) ->
|
|
NewPatterns = maps:remove(Pat, OldPatterns),
|
|
{ok, Ctx#ctx{patterns = NewPatterns}}.
|
|
|
|
resolve_pattern(Pat, Ctx = #ctx{patterns = Patterns}) ->
|
|
case maps:find(Pat, Patterns) of
|
|
error -> {error, wfc_utils:str("wfc_eval_context:resolve_pattern: not found: ~s; context: ~w", [Pat, Ctx])};
|
|
Result -> Result
|
|
end.
|
|
|
|
resolve_snowflake(SF, Ctx = #ctx{snowflakes = Snowflakes}) ->
|
|
case maps:find(SF, Snowflakes) of
|
|
error -> {error, wfc_utils:str("wfc_eval_context:resolve_snowflake: not found: ~s; context: ~w", [SF, Ctx])};
|
|
Result -> Result
|
|
end.
|