Subroutines and scripts

XSharper has a concept of a subroutine, that accepts 0 or more arguments and returns a single object value.

<!-- SUB1.XSH. Calculate squares of 20 and 50 -->
<xsharper>
        <set a="${=20}" />
        <call subId="square" outTo="result">
                <param>${a}</param>
        </call>
        <print>${a}*${a} = ${result}</print>
        <print>50*50 = ${=square(50)}</print>
       
        <!-- Subroutines -->
        <sub id="square">
                <param name="n" required="true" />
                <set ret="${=$n*$n}" />
                <return>${ret}</return>
        </sub>
</xsharper>

As seen above, subroutines may be invoked directly from the expressions.

To execute square subroutine from another script, it's possible to use include action:

<!-- SUB2.XSH. Calculate square of a value specified as a command-line argument -->
<xsharper>
        <include from="sub1.xsh" />
        <param name="v" required="true">Value to calculate square</param>

        <print>${v}*${v} = ${=square($v)}</print>
</xsharper>

Finally, execute another script as if it was executed from command line:

<!-- SUB3.XSH. Print square of a value using SUB2.XSH -->
<xsharper>
        <exec from="sub2.xsh">
                <param>500</param>
        </exec>
</xsharper>

Isolation level

By default, subroutines have read-only access to the variables of the caller and any set or changed variables in the subroutine body are restored.

<set x="50" />
<print>Before call x=${x}</print>
<call subId="sub" isolation="default" />
<print>After call x=${x}</print>

<sub id="sub">
        <print>Sub. Initially x=${x|'Undefined'}.</print>
        <set x="100" />        
        <print>Sub. Later x=${x}.</print>
</sub>

The code above will print:
Before call x=50
Sub. Initially x=50.
Sub. Later x=100.
After call x=50

This behaviour can be changed by caller, by changing attribute isolation

With isolation="none", when no variables are restored, the output will be

Before call x=50
Sub. Initially x=50.
Sub. Later x=100.
After call x=100

With isolation="high", the subroutine will have a totally clean variable list, w/o access to the caller variables at all:

Before call x=50
Sub. Initially x=Undefined.
Sub. Later x=100.
After call x=50