Introducing two kinds of variables: pipes and vals.
- pipe – a named FIFO queue. Once the value is read from pipe, it is gone.
- val – a single object. Can be read as many times, as needed
Few /internal/ commands to manipilate these vars:
- set valName – sets named value with a first value from input pipe. If value is not registered in current scope, generates runtime error. If pipe is empty, val remains unset/retains old value
- get valName – gets named value. If value is not registered or not set, generates runtime error
- read pipeName count – reads up to count values (or all values if count == -1) from named pipe and writes them into output pipe. Runtime error if pipe is not registered
- write pipeName – reads values from input pipe and writes into named pipe
In ECL scripts pipes and variables can be used by using $<pipeOrValName>. Parser validates that names are valid (to be described later) and performs replacement of $<name> with one of internal commands by using the following rules:
Two more internal commands can be used to create a 'variable' object:
- pipe name [values] [-input] – Constructs a PipeDeclaration object. If values are given, then it will have this set of values inside, if -input argument is given, then it will be initialized with a conents of a caller's input pipe. Examples:
- val name [value] [-input] – Constructs a ValDeclaration object. If value is given, val will have this value, if '-input is given, then it will be initialized with a value from input pipe. If neither 'value', nor '-input' is set, then such value can be used only in proc.
By itself these commands are pretty useless, but they make a perfect sence when it comes to proc and let
- proc var... body – Creates a new procedure with given pipes/values
- let var... body – Executes in-place command with given pipes/value
- Filling values to New Java class dialog.
- Reusing a value from UI (inspired by ticket #299)
- Repeating actions based on CSV values (inspired by ticket #344)
- Initially I did not plan an '-input' argument for val/proc and thought that this can be 'emulated' just by using implicit declaration of $in pipe (which aliases to current input of current 'let' command. So that this script should write "1 2 3" to log:
But our current evaluation model works in a way that all three 'val' commands will get the same input and output would be "1 1 1". However now I like an '-input' parameter even more than 'automagic' $in.
- 'let' should pass its input as an input to its body to reduce surprise so that scripts like this work (i.e. any block nested into 'with' can be wrapped into a 'let'):
But this creates a problem that if we are using 'let' inside some 'foreach', inner script is being 'trapped' into parent's pipe. I see several possible solutions:
- Implement 'let' in that way that if it has '-input' vals, 'body' does not receive an input. Probably that's a way to go!
- have a command 'void' which returns an empty pipe
- control an input of 'let' script by some special argument '-input' which can accept arbitrary value:
- Current ECL cannot correctly handle when argument vith variable argument count is not the last, but that's exactly what we have in 'let':
However this should be easy to fix (worst case scenario: under-the-hood hardcoded special binding of args for 'let' and 'proc'.
- Everything described here for now can be implemented without modifying parser/compiler (its possbile to use internal commands for now without '$'-expansion)
- Without breaking a compatibility we can modify a 'foreach' implementation so that it also accepts list of variables:
- Probably we don't need named pipes yet, as for three use cases above I did not use them at all.