AndreVanDelft / scala

The SubScript extension to the Scala programming language
http://www.subscript-lang.org/
12 stars 1 forks source link

^ Result Catchers #36

Open AndreVanDelft opened 10 years ago

AndreVanDelft commented 10 years ago

^ Result Catchers

Script calls and code fragments may be followed by result catchers: a caret(^) optionally followed by a simple variable designator There is no spacing allowed, to prevent ambiguity of the optional designator with a script call. If such a variable is not specified explicitly after the caret, the script result value $result is assumed. An alternative would be to catch the result-exception value in a Try[]; FTTB we stick to the result.

A variable name that starts with $ (except for $, $result and $failure) is implicitly declared as local variable in the script, with an appropriate type: the most specific common supertype of all the result types of the calls and code fragments that the variable appears next to as result catcher.

If a script body consists of just a code fragment or a script call without a result catcher, an implicit one is assumed for the script result value. (Maybe widen this condition to activation code containing a code fragment or calls) If the calling script has no explicit result type declared, then the result type becomes the most specific common supertype of its script calls and code fragments that have result catchers for $result.

In this respect the script calls and code fragments body of a script lambda are normally supposed to belong to that lambda, rather than to the enclosing script. Note that the operands of the data flow operator are lambdas. It makes sense that in a ~~> b the result value from a goes to b. However, the entire dataflow construct should be seen as a lambda in itself; its result value will be fed by the RHS (b). This is something still to be worked out.

Probably a ~~> b^ should be interpreted as (a ~~> (b^))^, and a ~~> b ~/~> c ^ as (a ~~> (b^) ~/~> (c^))^. a ~~> b^ ~/~> c would not be illegal, but it would make no sense.

The caret may be implemented in two ways: as a separate node or as a optional parameter to the DSL methods _call, _normal etc. This parameter would then have type

  (Symbol, N_Call[R] => Unit)

Given an actual result catcher ^$ of type R the parameter would be something like:

`$ -> ((here:N_Call[R])=> $ = here.getResult)

The symbol part is for debugging: the node from which the result value is grabbed gets in the graphical debugger an extra label with actual value information, such as ^$=10.

AndreVanDelft commented 9 years ago

{code}^a (no whitespace between ^ and a) would be shorthand for: {try{a=Success{code}} catch {case t:Throwable => a=Failure(t)}

so a should be a variable of type Try[T] for some appropriate T.

{code}^ would be shorthand for {code}^$ i.e. this sets the result of the current script.

Exception: if the name a starts with a $ (and followed by at least 1 alphanumeric character), then such a result catcher would get a preceding declaration for that variable with the appropriate type. So {code}^$a; x would be like: var $a=_; {code}^$a; x That is, without recursive application of this rule; $a would be known in x.

AndreVanDelft commented 9 years ago

Some form of the result catchers is working now. A better word is: result propagator. Some rules: Code fragments and script calls may have explicit or implicit result propagation markers. If such a marker is present, then the enclosing script's result (a Try) becomes the Try of the marked element, upon success or failure (=active deactivation without success).

The "^" suffix is an explicit marker. If a script body has only a single code fragment or call, then that fragment or call gets the implicit marker (if it did not have an explicit one) If a larger expression than a single code fragment or call has the explicit marker suffix, then all code fragments and calls inside it get the implicit marker.

Note; children of the arrow operators ~~> etc are lambda's, and therefore regarded as scripts in this context.

This was not too hard to implement. We need care, though, on determining what to do exactly with arrow constructs.

Parboiled has transforming markers such as "captureAll"; that one creates a sequence of captured elements. Maybe we can do something similar. The marker symbol may be followed immediately by such a transformer. This will require experimentation.