[erlang-questions] Programmatic interface to the shell
Éric Pailleau
eric.pailleau@REDACTED
Mon Aug 10 19:17:37 CEST 2015
Hello Joe,
In bottom of this code
https://github.com/erlang/otp/blob/maint/lib/observer/src/observer_procinfo.erl
Is a simple io server, thanks to Dan Gudmunson.
This may help ?
Regards
Le 10 août 2015 19:08, Joe Armstrong <erlang@REDACTED> a écrit :
>
> Wonderful - thanks
>
> The main problem now is that the error messages are not exactly the same
> as in the shell.
>
> ie: The above code for X/0 says
>
> > Send(P, "X/0.").
> ** exception error: an error occurred when evaluating an arithmetic expression
>
> But X/0. in the shell says:
>
> > X/0.
> ** exception error: an error occurred when evaluating an arithmetic expression
> in operator '/'/2
> called as 4 / 0
>
> Do you have any idea how to dig out the error message so it's exactly the same?
>
> I'm asking because I'm writing a tutorial in a "markdown like" language
> and I want to automate production of examples :-)
>
>
> Thanks again
>
> /Joe
>
>
>
>
>
>
>
> On Mon, Aug 10, 2015 at 6:23 PM, Fred Hebert <mononcqc@REDACTED> wrote:
> > On 08/10, Joe Armstrong wrote:
> >>
> >> Hello,
> >>
> >> Is there a *simple* programmatic interface to the Erlang shell?
> >>
> >> I'd like a module "shell_interface" that works like this:
> >>
> >> Pid = shell_interface:new_shell(),
> >>
> >> Returns a new process that behaves like the Erlang shell
> >>
> >> OutStr = shell_interface:eval(Pid, InStr)
> >>
> >
> > Short answer is no. The Erlang shell in the `shell' module asks for
> > information via the IO protocol and pulls it in, rather than you pushing it
> > out.
> >
> > There's ways to inject yourself in there, but it's not simple.
> >
> >> This behaves like the Erlang shell. InStr should be what I typed into the
> >> shell. OutStr should be what the shell replied.
> >>
> >> For this purpose we can assume that InStr represents a complete
> >> sequence of expressions.
> >>
> >
> > This sounds more like an evaluator/interpreter:
> >
> > 1> {ok, Tokens, _} = erl_scan:string("X + 4 * lists:sum([1,2,3,4]).").
> > ...
> > 2> {ok, [Form]} = erl_parse:parse_exprs(Tokens).
> > ...
> > 3> Bindings = erl_eval:add_binding('X', 17, erl_eval:new_bindings()).
> > [{'X',17}]
> > 4> {value, Value, _} = erl_eval:expr(Form, Bindings).
> > {value,57,[{'X',17}]}
> > 5> Value.
> > 57
> >
> > With these basic forms it becomes doable to write a mini-shell the way you'd
> > like it.
> >
> > Eval = fun EvalLoop(Bindings) ->
> > receive
> > {cmd, Caller, Ref, String} ->
> > try
> > {ok, Tokens, _} = erl_scan:string(String),
> > %% many forms can be comma-separated
> > {ok, Forms} = erl_parse:parse_exprs(Tokens),
> > %% eval individually
> > {value, Val, NewBindings} = erl_eval:exprs(Forms,
> > Bindings),
> > Caller ! {ok, Ref, Val},
> > EvalLoop(NewBindings)
> > catch
> > T:R ->
> > Caller ! {raise, Ref, T, R},
> > EvalLoop(Bindings)
> > end
> > end end.
> >
> > Send = fun(Pid, String) ->
> > Ref = erlang:monitor(process, Pid),
> > Pid ! {cmd, self(), Ref, String},
> > receive
> > {ok, Ref, Value} -> Value;
> > {raise, Ref, T, R} -> erlang:T(R)
> > end end.
> >
> > 18> P = spawn(fun() -> Eval([]) end).
> > <0.62.0>
> > 19> Send(P, "X=2+2.").
> > 4
> > 20> Send(P, "X*X.").
> > 16
> > 21> Send(P, "X/0.").
> > ** exception error: an error occurred when evaluating an arithmetic
> > expression
> > 22> Send(P, "X.").
> > 4
> >
> > And there you have an evaluator. It doesn't support all the stuff like
> > 'h().' and whatnot, but is close enough otherwise.
> >
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
More information about the erlang-questions
mailing list