Multi-Expressions

To access a value of a variable, XSharper transformations are used:

<!-- Print Hello world! -->
<set name="x" value="Hello" />
<print>${x} world!</print>

Multi-expression is a piece of text included between the special characters ${ } (${{...}} or [[ ... ]] may be used instead, as described below ).

The word "multi-" means that several expressions may be concatenated with | and the first set value is chosen.

<!-- Prints TestB because variable a is not defined and b is defined -->
<set name="b" value="TestB" />
<set name="c" value="TestC" />
<print>${a|b|c}</print>

There are different types of expressions, and the expression type is determined by the first character of an expression as explained below.

Calculated expressions

If first character of an expression is = , it is interpreted using rules close to those of C#, although much more forgiving in conversions between types.

For example (int)"20d" will throw an exception in normal C#, yet will produce a double value of 20.0 in XSharper calculated expression.

<!-- EXP1.XSH will print 
	Type of 'num' is System.String 
	Type of 'text' is System.String
	Expression value=52 
	ArrayLength=3
	'aa' is larger than 'bb'=False
	C:\Windows has 226 files
-->
<set num="20" />
<set text="Hello" />
<print>Type of 'num' is ${=$num.GetType().FullName}</print>
<print>Type of 'text' is ${=$text.GetType().FullName}</print>
<print>Expression value=${= 2*$num+($text.Length+1)*2}</print>
<print>ArrayLength=${= new int[] { 1,2,3}.Length }</print>
<print>'aa' is larger than 'bb'=${= 'aa' #GT# 'bb' }</print>

Some notable differences from C# syntax:

  • Multiple quote types are allowed, single, double and backtick ( ` ), and all are equivalent
  • There are no escape characters. "\aaa\" is a string \aaa\.
  • Everything is case insensitive
  • Conversion between types is very permissive. For example (int)"0x20" produces 32, and not an exception. And (int)(FileOptions)"asynchronous" produces 1073741824 (0x40000000) which is an integer value of System.IO.FileOptions.Asynchronous
  • Template classes cannot be created (yet) with new, and can be explicitly invoked.
  • Because <, & and > are difficult to use with XML, comparison and binary operators can be entered with #..# syntax:
    #OR# ||
    #AND# &&
    #BOR# |
    #BAND# &
    #BXOR# ^
    #EQ# ==
    #NEQ# !=
    #LT# <
    #GT# >
    #LE# <=
    #GE# >=
    #NOT# !
    #NEG# ~
  • Arrays may be created just using {} using the most common type. For example "${= { 1,2,3}}" produces an array of integers, and "${= { 1.0, 2.4d, 0x22 }}" an array of doubles.
  • Assignment = operator is NOT supported. If you must, properties of objects can be set via x.set_PropertyName(value) syntax. XSharper variables may be set as c.Set('varName',value).
  • Likewise, postfix/suffix operations, like a++ or --a, are not supported
  • Overridden operators are not supported
  • There is a special concept of "no-name" object, which is assumed to be a combination of current script context (referenced as 'c' or 'Context') and XSharper.Core.Utils class.

    This allows shorter syntax like .Print('a,b,c') instead of Context.Print('a','b','c'). Or .RegistryGet("HKLM\SOFTWARE\Microsoft\.NETFramework\InstallRoot",null) instead of XS.Utils.RegistryGet("HKLM\SOFTWARE\Microsoft\.NETFramework\InstallRoot",null).

Numbers

If an expression is a valid number, it is the value of the expression.

<!-- prints 2000 -->
<print>${2e3}</print>

Quoted strings

If an expression starts with ', or ", or `, the expression is treated as string (expecting a matching character at the end).

<!-- prints Michael Jackson -->
<print>Michael ${'Jackson'}</print>

Environment variables

If the first character is %, environment variable is used:

<!-- EXP2.XSH will print 
		command interpreter=C:\Windows\system32\cmd.exe
		home drive=C:
		xsh_path=[NULL]
-->
<print tr='expand trim multiline'>
	command interpreter=${%COMSPEC%}
	home drive=${%HOMEDRIVE%}
	xsh_path=${%XSH_PATH%|'[NULL]'}
</print>

By default, environment variables of the current process are accessed. To access variables of the current user or machine, user: and machine: prefixes are used instead. For example:

<print>System PATH=${%machine:PATH%}</print>

Variable name

If all the previous checks fail, the value is treated as variable name. Empty variable names are also allowed:

<!-- Prints The desert is Tiramisu, as the variable desert is not set -->
<set name="" value="Tiramisu" />
<print>The desert is ${desert|}</print>

<eval> action

Multiple expressions may be interpreted in sequence using action:

<eval>
	c.WriteLine(`Length of AAA `+'AAA'.length);
	c.WriteLine("Length of BB "+'BB'.length);
	c.Set("a",20);
	c.Print("A=${a}");
</eval>

The script below makes a screenshot and saves it to scrshot.png:

<reference name="System.Windows.Forms" addUsing="true" />
<eval>	c.Set('v',SystemInformation.VirtualScreen);
		c.Set('bmp',new Drawing.Bitmap($v.Width,$v.Height));
		c.Set('g',Drawing.Graphics.FromImage($bmp));
		$g.CopyFromScreen( new Drawing.Point(0,0), Drawing.Point.Empty, $bmp.Size);
		$bmp.Save('scrshot.png');
</eval>