ocaml / oloop

Evaluate code through the OCaml toploop for inclusion in educational material.
ISC License
12 stars 5 forks source link

distinguish between oloop error vs error in given phrase #16

Closed agarwal closed 9 years ago

agarwal commented 9 years ago

Right now the return type of eval is (Outcometree.out_phrase * 'a Output.t, error * string) Result.t, which I feel is a misuse of the Error value. Normally if a function returns an Error, it means the function failed to execute correctly. However, in this case the Error (err,msg) value is actually a correct result from Oloop's perspective. The eval did its job successfully. It called the toploop and found that the given phrase had some error. As I explain in the documentation of Oloop_script, one could very well want to use Oloop to show examples of incorrect OCaml input.

I plan to define the following type:

type 'a outcome = [
| `Ophr_val of out_value * out_type * 'a Oloop.Output.t
| `Ophr_signature of (out_sig_item * out_value option) list * 'a Oloop.Output.t
| `Ophr_exception of exn * out_val * 'a Oloop.Output.t
| `Lexer of Lexer.error * Location.t * string
| `Syntaxerr of Syntaxerr.error * string
| `Typedecl of Location.t * Typedecl.error * string
| `Typetexp of Location.t * Env.t * Typetexp.error * string
| `Typecore of Location.t * Env.t * Typecore.error * string
| `Symtable of Symtable.error * string
]

The first 3 are semantically equivalent to Outcometree.out_phrase * 'a Output.t, and the rest are equivalent to error * string. Putting them all in a flat list now forces the user to decide what is considered an error or not, which I think is the only option. We really cannot know if evaluation of a script should stop on the first lexer error, for example. Maybe all the subsequent phrases make perfect sense still.

Note that eval could truly fail, e.g. oloop-top shutdown since it was launched. The current implementation doesn't capture this, and maybe it's okay to leave this as an exception.

Chris00 commented 9 years ago

Right, it is a matter of perspective on what an error is. Since most of the time the phrases will be perfectly valid, some helper functions to handle that case smoothly are desirable.

I'm not sure why you want to split the Outcometree.out_phrase. There are already useful functions defined on that value — such as !Oprint.out_phrase. Maybe

| `Phrase of Outcometree.out_phrase * 'a Output.t

is enough — I think Phrase Ophr_eval` is as easy as and not much heavier thanOphr_val`.

agarwal commented 9 years ago

why you want to split the Outcometree.out_phrase

True, maybe we shouldn't. My thinking was that it doesn't stand out as a logically distinct item from what we currently call error due to the fact that it includes exceptions. An exception is maybe an error. Probably we want to provide a few groupings that logically mean the following things:

Now the trick is to think of how to define these. Polymorphic variants would allow us to mix as desired. Or we can provide convenience functions to transform between different representations.

I'll take a shot at it, and we can iterate.

agarwal commented 9 years ago

Done in 2ccac62dc157a5d7eb6f190d3a7cbe979d275b2b.