saker.build Documentation TaskDoc JavaDoc

Variables

The language allows declaring variables which are named storages of an expression value. Variables are uniquely identified by their name, and share the same build target scope.

# assignments
$var = 123
$multiplied = $var * 3

Variables are dereferenced by using the '$' character before the subject expression. The dereferenced expression is usually a string literal, but other expressions are also allowed to support more refined usage of variables:

# assigning non-literal variable names
$get.variable.name() = some_value
$("var{ $varnum }") = 123

A variable with a given name can only be assigned once in a build target. Once it has been assigned, any other assignments to it will result in an exception.

The dereference operator is applied according to the precedence rules of the language.

Variables can also be accessed by using the var() built-in task.

Scope of variables

Variables share the scope of the build target they're declared in. There are no local variables, and assigning, using, or modifying a variable in a seemingly enclosed scope will be not limited to that scope, but to the whole build target scope.

# variable among the global expressions
$outervar = # ...
build{
	# variable in the build target, 
	# named the same as used among the global expressions
	# they are different variables
	$outervar = #...
	
	$targetvar = #...
	
	if example.condition.task() {
		# both references the vars in the build target:
		$outervar
		$targetvar
		# assign a variable of the build target
		$ifvar = 1
	} else {
		# assign a variable of the build target
		$ifvar = 2
	}
	
	# use the variable assigned in the above if statement
	example.task($ifvar)
	
	# same named var as in the below loop
	$item = # ...
	foreach $item in [1, 2] {
		# shadows the $item variable in the build target scope
		$item
		# access the variable $item in the build target scope
		$"item"
		
		# assign a variable of the build target
		# probably erroneous as a variable may be assigned only once
		$foreachvar = # ...
	}
}

As variables can be declared among the global expressions, they cannot be accessed from any of the build target expressions. The global expressions are considered to be a separate build target scope of their own in regards to this.

If a variable is assigned in an if-else statement then it will be visible in the enclosing build target scope.

If a variable is assigned in a foreach expression then it will be visible in the enclosing build target scope. Note that it is probably erroneous to assign a variable in a foreach expressions, as a variable may only be assigned once, and a loop body may run multiple times, therefore assigning the variable more than once.

If one needs to declare file-level variables, see the static() built-in task. For global variables see global(). (It is recommended that developers employ global variables very judiciously.)

Dereference control flow

When a variable is dereferenced, the receiver expression (that is the one retrieving the value of the variable) will be put on hold. It will wait, until the variable is assigned. If the variable is already assigned when its value is being retrieved, the receiver expression will continue to run. If the variable has not yet been assigned, the execution of the receiver expression will be paused until it is assigned.

Based on this logic, it is possible to deadlock the execution of a script. When the variables depend on each other in a circular way, the execution of the script is erroneous, and will result in an exception during the execution of it. One example for this:

# circular variable dependency
$var = $secondvar * 3
$secondvar = some.task(Input = $var)

We can see that the assignment of $var will require the value of $secondvar. However, the assignment of $secondvar requires the output of some.task(Input = $var), which needs the value of $var to run. In this case the execution of the script will deadlock.

Build target parameters

The declared parameters of the build target affect the behaviour of variables. Any input variables of a build target cannot be assigned in the body of the target. All output parameters which doesn't have an assigned value in the parameter list must be assigned during the execution of the build target. See Source file for more information.

build(
	in InputParam,
	out OutputResult,
){
	# runtime error:
	$InputParam = #...
	# assign the output of the target
	$OutputResult = #...
}