have a server that like does stuff now
This commit is contained in:
parent
fa16da8178
commit
6c45f30919
@ -6,7 +6,7 @@
|
|||||||
version = undefined :: undefined | http10 | http11 | http20,
|
version = undefined :: undefined | http10 | http11 | http20,
|
||||||
headers = undefined :: undefined | [{Key :: binary(), Value :: binary()}],
|
headers = undefined :: undefined | [{Key :: binary(), Value :: binary()}],
|
||||||
cookies = undefined :: undefined | #{Key :: binary() := Value :: binary()},
|
cookies = undefined :: undefined | #{Key :: binary() := Value :: binary()},
|
||||||
enctype = undefined :: undefined | none | urlencoded | multipart(),
|
enctype = undefined :: undefined | none | urlencoded | json | multipart(),
|
||||||
size = undefined :: undefined | none | non_neg_integer(),
|
size = undefined :: undefined | none | non_neg_integer(),
|
||||||
body = undefined :: undefined | none | body()}).
|
body = undefined :: undefined | none | body()}).
|
||||||
|
|
||||||
@ -20,6 +20,6 @@
|
|||||||
|
|
||||||
-type method() :: get | post | options.
|
-type method() :: get | post | options.
|
||||||
-type multipart() :: {multipart, Boundary :: binary()}.
|
-type multipart() :: {multipart, Boundary :: binary()}.
|
||||||
-type body() :: {partial, binary()} | {multipart, [body_part()]} | binary().
|
-type body() :: {partial, binary()} | {multipart, [body_part()]} | zj:value() | binary().
|
||||||
-type body_part() :: {Field :: binary(), Data :: binary()}
|
-type body_part() :: {Field :: binary(), Data :: binary()}
|
||||||
| {Field :: binary(), Name :: binary(), Data :: binary()}.
|
| {Field :: binary(), Name :: binary(), Data :: binary()}.
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
<script>
|
<script>
|
||||||
let ielt = document.getElementById('wfc-input');
|
let ielt = document.getElementById('wfc-input');
|
||||||
let oelt = document.getElementById('wfc-output');
|
let oelt = document.getElementById('wfc-output');
|
||||||
let MAX_OELT_HEIGHT = 100;
|
let MAX_OELT_HEIGHT = 300;
|
||||||
|
|
||||||
function auto_resize_output() {
|
function auto_resize_output() {
|
||||||
// if the user has manually resized their output, we do nothing
|
// if the user has manually resized their output, we do nothing
|
||||||
@ -46,12 +46,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function on_server_return(x) {
|
async function on_server_return(response) {
|
||||||
console.log('on_server_return:', x);
|
console.log('on_server_return:', response);
|
||||||
|
if (response.ok) {
|
||||||
|
let jsbs = await response.json();
|
||||||
|
console.log('jsbs', jsbs);
|
||||||
|
// jsbs: {ok: true, result: string} | {ok: false, error: string}
|
||||||
|
if (jsbs.ok) {
|
||||||
|
// this means got a result back from server
|
||||||
|
// put it in
|
||||||
|
oelt.value += jsbs.result;
|
||||||
|
oelt.value += '\n';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// this is an error at the WFC level
|
||||||
|
oelt.value += jsbs.error;
|
||||||
|
oelt.value += '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// this means we sent an invalid request
|
||||||
|
else {
|
||||||
|
oelt.value += 'HTTP ERROR, SEE BROWSER CONSOLE\n'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function on_some_bullshit(x) {
|
function on_some_bullshit(x) {
|
||||||
console.log('on_some_bullshit:', x);
|
console.log('on_some_bullshit:', x);
|
||||||
|
oelt.value += 'NETWORK ERROR, SEE BROWSER CONSOLE\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetch_wfcin(user_line) {
|
function fetch_wfcin(user_line) {
|
||||||
@ -82,11 +103,11 @@
|
|||||||
let nonempty_contents = contents.trim().length > 0;
|
let nonempty_contents = contents.trim().length > 0;
|
||||||
if (nonempty_contents) {
|
if (nonempty_contents) {
|
||||||
// put in output
|
// put in output
|
||||||
// if it's nonempty add a newline
|
// // if it's nonempty add a newline
|
||||||
if (oelt.value.length > 0) {
|
// if (oelt.value.length > 0) {
|
||||||
oelt.value += '\n';
|
// oelt.value += '\n';
|
||||||
}
|
// }
|
||||||
oelt.value += '> ' + contents;
|
oelt.value += '> ' + contents + '\n';
|
||||||
oelt.hidden = false;
|
oelt.hidden = false;
|
||||||
|
|
||||||
// query backend for result
|
// query backend for result
|
||||||
|
|||||||
@ -263,11 +263,42 @@ default_css(Sock) ->
|
|||||||
http_err(Sock, 500)
|
http_err(Sock, 500)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
wfcin(Sock, #request{enctype = json, body = #{"wfcin" := Input}}) ->
|
||||||
|
tell("wfcin good request: ~tp", [Input]),
|
||||||
|
RespObj =
|
||||||
|
try
|
||||||
|
case wfc_read:expr(Input) of
|
||||||
|
%% FIXME support multiple expressions
|
||||||
|
{ok, Expr, _Rest} ->
|
||||||
|
case wfc_eval:eval(Expr, wfc_eval_context:default()) of
|
||||||
|
{ok, noop, _NewContext} -> jsgud("<noop>");
|
||||||
|
{ok, Sentence, _NewContext} -> jsgud(wfc_pp:sentence(Sentence));
|
||||||
|
{error, Message} -> jsbad(Message)
|
||||||
|
end;
|
||||||
|
{error, Message} ->
|
||||||
|
jsbad(Message)
|
||||||
|
end
|
||||||
|
catch
|
||||||
|
error:E:S ->
|
||||||
|
ErrorMessage = unicode:characters_to_list(io_lib:format("parser crashed: ~p:~p", [E, S])),
|
||||||
|
jsbad(ErrorMessage)
|
||||||
|
end,
|
||||||
|
Body = zj:encode(RespObj),
|
||||||
|
Response = #response{headers = [{"content-type", "application/json"}],
|
||||||
|
body = Body},
|
||||||
|
respond(Sock, Response);
|
||||||
wfcin(Sock, Request) ->
|
wfcin(Sock, Request) ->
|
||||||
tell("wfcin request: ~tp", [Request]),
|
tell("wfcin: bad request: ~tp", [Request]),
|
||||||
http_err(Sock, 501).
|
http_err(Sock, 400).
|
||||||
|
|
||||||
|
jsgud(X) ->
|
||||||
|
#{"ok" => true,
|
||||||
|
"result" => X}.
|
||||||
|
|
||||||
|
jsbad(X) ->
|
||||||
|
#{"ok" => false,
|
||||||
|
"error" => X}.
|
||||||
|
|
||||||
%% FIXME
|
|
||||||
http_err(Sock, N) ->
|
http_err(Sock, N) ->
|
||||||
Slogan = qhl:slogan(N),
|
Slogan = qhl:slogan(N),
|
||||||
Body = ["<!doctype html>"
|
Body = ["<!doctype html>"
|
||||||
|
|||||||
@ -220,7 +220,6 @@ terminate(_, _) ->
|
|||||||
do_listen(PortNum, State = #s{port_num = none}) ->
|
do_listen(PortNum, State = #s{port_num = none}) ->
|
||||||
SocketOptions =
|
SocketOptions =
|
||||||
[inet6,
|
[inet6,
|
||||||
{packet, line},
|
|
||||||
{active, once},
|
{active, once},
|
||||||
{mode, binary},
|
{mode, binary},
|
||||||
{keepalive, true},
|
{keepalive, true},
|
||||||
|
|||||||
@ -46,7 +46,7 @@ rep(String) ->
|
|||||||
case wfc_read:expr(String) of
|
case wfc_read:expr(String) of
|
||||||
{ok, Expr, Rest} ->
|
{ok, Expr, Rest} ->
|
||||||
case wfc_eval:eval(Expr) of
|
case wfc_eval:eval(Expr) of
|
||||||
{ok, Result, NewContext} ->
|
{ok, Result, _NewContext} ->
|
||||||
io:format("result: ~s~n", [wfc_pp:eval_result(Result)]),
|
io:format("result: ~s~n", [wfc_pp:eval_result(Result)]),
|
||||||
%io:format("context: ~tw~n", [NewContext]),
|
%io:format("context: ~tw~n", [NewContext]),
|
||||||
ok;
|
ok;
|
||||||
@ -107,10 +107,10 @@ mul([Arg | Rest]) ->
|
|||||||
case to_sentence(Arg) of
|
case to_sentence(Arg) of
|
||||||
{ok, S} ->
|
{ok, S} ->
|
||||||
case mul(Rest) of
|
case mul(Rest) of
|
||||||
{ok, S2} -> wfc_sentence:mul(S, S2);
|
{ok, S2} -> {ok, wfc_sentence:mul(S, S2)};
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end;
|
end;
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end;
|
end;
|
||||||
mul([]) ->
|
mul([]) ->
|
||||||
wfc_sentence:zero().
|
{ok, wfc_sentence:one()}.
|
||||||
|
|||||||
@ -21,7 +21,9 @@
|
|||||||
%-type sexp() :: {sexp, [expr()]}.
|
%-type sexp() :: {sexp, [expr()]}.
|
||||||
%-type expr() :: sexp() | ltr() | op() | snowflake() | pattern() | val().
|
%-type expr() :: sexp() | ltr() | op() | snowflake() | pattern() | val().
|
||||||
|
|
||||||
-spec eval(expr()) -> {ok, eval_result(), context()} | {error, string()}.
|
-spec eval(expr()) -> Result
|
||||||
|
when Result :: {ok, eval_result(), NewContext :: context()}
|
||||||
|
| {error, string()}.
|
||||||
|
|
||||||
eval(Expr) ->
|
eval(Expr) ->
|
||||||
eval(Expr, wfc_eval_context:default()).
|
eval(Expr, wfc_eval_context:default()).
|
||||||
@ -57,6 +59,24 @@ eval_sexp(Args = [{snowflake, <<"define">>}, {pattern, Pat}, Expr], Ctx0) ->
|
|||||||
Error ->
|
Error ->
|
||||||
Error
|
Error
|
||||||
end;
|
end;
|
||||||
|
eval_sexp([{snowflake, SF} | Args], Ctx0) ->
|
||||||
|
% first evaluate the arguments individually
|
||||||
|
case eval_sexp_args(Args, Ctx0, []) of
|
||||||
|
% assuming they each evaluate to sentences and some new context
|
||||||
|
{ok, Sentences, Ctx1} ->
|
||||||
|
% look up the snowflake in the context
|
||||||
|
case wfc_eval_context:resolve_snowflake(SF, Ctx1) of
|
||||||
|
{ok, SnowflakeFun} ->
|
||||||
|
case SnowflakeFun(Sentences) of
|
||||||
|
{ok, Sentence} -> {ok, Sentence, Ctx1};
|
||||||
|
Error -> Error
|
||||||
|
end;
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end;
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end;
|
||||||
eval_sexp([{op, '+'} | Exprs], Ctx) ->
|
eval_sexp([{op, '+'} | Exprs], Ctx) ->
|
||||||
case eval_sexp_args(Exprs, Ctx, []) of
|
case eval_sexp_args(Exprs, Ctx, []) of
|
||||||
{ok, Sentences, NewCtx} -> {ok, wfc_sentence:add(Sentences), NewCtx};
|
{ok, Sentences, NewCtx} -> {ok, wfc_sentence:add(Sentences), NewCtx};
|
||||||
|
|||||||
@ -7,15 +7,17 @@
|
|||||||
-export([
|
-export([
|
||||||
new/0,
|
new/0,
|
||||||
default/0,
|
default/0,
|
||||||
|
default_snowflakes/0,
|
||||||
define/3,
|
define/3,
|
||||||
resolve_pattern/2
|
resolve_pattern/2,
|
||||||
|
resolve_snowflake/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-type sentence() :: wfc_sentence:sentence().
|
-type sentence() :: wfc_sentence:sentence().
|
||||||
|
|
||||||
-record(ctx,
|
-record(ctx,
|
||||||
{snowflakes :: #{binary() := fun()},
|
{snowflakes = #{} :: #{binary() := fun(([sentence()]) -> {ok, sentence()} | {error, string()})},
|
||||||
patterns :: #{binary() := sentence()}}).
|
patterns = #{} :: #{binary() := sentence()}}).
|
||||||
|
|
||||||
-opaque context() :: #ctx{}.
|
-opaque context() :: #ctx{}.
|
||||||
|
|
||||||
@ -25,10 +27,12 @@ new() ->
|
|||||||
patterns = #{}}.
|
patterns = #{}}.
|
||||||
|
|
||||||
|
|
||||||
%% FIXME
|
|
||||||
default() ->
|
default() ->
|
||||||
new().
|
#ctx{snowflakes = default_snowflakes()}.
|
||||||
|
|
||||||
|
default_snowflakes() ->
|
||||||
|
#{<<"and">> => fun wfc:mul/1,
|
||||||
|
<<"xor">> => fun wfc:add/1}.
|
||||||
|
|
||||||
define(Pat, Sentence, Ctx = #ctx{patterns = OldPatterns}) ->
|
define(Pat, Sentence, Ctx = #ctx{patterns = OldPatterns}) ->
|
||||||
NewPatterns = maps:put(Pat, Sentence, OldPatterns),
|
NewPatterns = maps:put(Pat, Sentence, OldPatterns),
|
||||||
@ -39,3 +43,9 @@ resolve_pattern(Pat, Ctx = #ctx{patterns = Patterns}) ->
|
|||||||
error -> {error, wfc_utils:str("wfc_eval_context:resolve_pattern: not found: ~w; context: ~w", [Pat, Ctx])};
|
error -> {error, wfc_utils:str("wfc_eval_context:resolve_pattern: not found: ~w; context: ~w", [Pat, Ctx])};
|
||||||
Result -> Result
|
Result -> Result
|
||||||
end.
|
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: ~w; context: ~w", [SF, Ctx])};
|
||||||
|
Result -> Result
|
||||||
|
end.
|
||||||
|
|||||||
@ -22,7 +22,9 @@
|
|||||||
-type expr() :: sexp() | ltr() | op() | snowflake() | pattern() | val().
|
-type expr() :: sexp() | ltr() | op() | snowflake() | pattern() | val().
|
||||||
|
|
||||||
|
|
||||||
-spec expr(string()) -> {ok, expr(), Rest :: string()} | {error, string()}.
|
-spec expr(string()) -> Result
|
||||||
|
when Result :: {ok, Expression :: expr(), Rest :: string()}
|
||||||
|
| {error, string()}.
|
||||||
|
|
||||||
expr(Str0) ->
|
expr(Str0) ->
|
||||||
{ok, skip, Str1} = whitespace(Str0),
|
{ok, skip, Str1} = whitespace(Str0),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user