fewd/src/wfc.erl

121 lines
3.0 KiB
Erlang

% @doc
% porcelain wfc ops
-module(wfc).
-export_type([
sentence/0
]).
-export([
test/0,
to_sentence/1,
rep/1,
reps/1,
reps/2,
add/1,
mul/1
]).
test() ->
reptest("(*)"),
reptest("(+)"),
reptest("(+ a b)"),
reptest("(+ a b (* a b))"),
ok.
reptest(S) ->
io:format("input: ~s~n", [S]),
rep(S),
io:format("~n", []).
-type sentence() :: wfc_sentence:sentence().
-spec to_sentence(term()) -> {ok, sentence()} | {error, string()}.
to_sentence(Ltr = {c, _}) -> wfc_sentence:from_ltr(Ltr);
to_sentence(Word = {w, _}) -> wfc_sentence:from_word(Word);
to_sentence({s, Words}) -> wfc_sentence:from_list(Words);
to_sentence(Bad) -> {error, wfc_utils:str("wfc:to_sentence: cannot coerce to sentence: ~p", [Bad])}.
-spec rep(string()) -> ok.
% @doc read/eval/print
rep(String) ->
case wfc_read:expr(String) of
{ok, Expr, Rest} ->
case wfc_eval:eval(Expr) of
{ok, Result, _NewContext} ->
io:format("result: ~s~n", [wfc_pp:eval_result(Result)]),
%io:format("context: ~tw~n", [NewContext]),
ok;
%{ok, Result, NewContext};
{error, Msg} -> io:format("~s~n", [Msg])
end,
io:format("rest: ~p~n", [Rest]);
{error, Message} ->
io:format("~s~n", [Message])
end.
-spec reps(string()) -> ok.
% @doc read/eval/print loop
reps(String) ->
reps(String, wfc_eval_context:default()).
reps(String, Ctx) ->
%io:format("reps(~ts, ~tw)~n", [String, Ctx]),
case wfc_read:expr(String) of
{ok, Expr, Rest} ->
%io:format("{ok, ~tw, ~ts}~n", [Expr, Rest]),
case wfc_eval:eval(Expr, Ctx) of
{ok, Result, NewContext} ->
io:format("result: ~s~n", [wfc_pp:eval_result(Result)]),
io:format("context: ~tw~n", [NewContext]),
reps(Rest, NewContext);
{error, Msg} -> io:format("~s~n", [Msg])
end,
io:format("rest: ~p~n~n", [Rest]);
{error, Message} ->
io:format("~s~n", [Message])
end.
-spec add([term()]) -> {ok, sentence()} | {error, string()}.
add([Arg | Rest]) ->
case to_sentence(Arg) of
{ok, S} ->
case add(Rest) of
{ok, S2} ->
io:format("S2 = ~p~n", [S2]),
{ok, wfc_sentence:add(S, S2)};
Error -> Error
end;
Error -> Error
end;
add([]) ->
{ok, wfc_sentence:zero()}.
-spec mul([term()]) -> {ok, sentence()} | {error, string()}.
mul([Arg | Rest]) ->
case to_sentence(Arg) of
{ok, S} ->
case mul(Rest) of
{ok, S2} -> {ok, wfc_sentence:mul(S, S2)};
Error -> Error
end;
Error -> Error
end;
mul([]) ->
{ok, wfc_sentence:one()}.
zero() -> wfc_sentence:zero().
one() -> wfc_sentence:one().