These reference chapters comprehensively describe the Acorn language. They assume the reader has some familiarity with programming languages as well as how an Acorn program is built up from basic tokens. For a gentler introduction to the language, seek out an Acorn Guide.
Values, Collections, Methods and Types
Before getting into the details, let's introduce some key concepts:
- Every piece of data we work with (including methods and types) is a value. As with other dynamic languages, every value specifies both its contents and its type. For example, the value 12 has the type Integer and the contents of 12.
- Multiple values can be gathered together into collections. There are several types of collections (e.g., List, Index or Part) which organize their values in different ways. A collection's individual values can be accessed using its integer position or symbolic index.
- Every time we want to do something (which is always), we do it with a method. A method is a procedure which, when given some values (the parameters), performs work, and returns back one or more value(s). There are several types of methods, as detailed in the method definition chapter.
- A value's type establishes the named properties that apply to any value of that type.
A property can hold any value, but most often hold methods able to manipulate any value
whose type the property belongs to.
For example: the Integer type has the property '+', a method used to add one integer to another.
Although Acorn allows the creation of arbitrarily many custom types, the language's core types are globally available. These core types are regularly mentioned in this reference. The names of global types begin with a capital letter.
These concepts are deeply intertwined: Every value has a type. Every type is a collection of properties. A property can hold a method. Every method operates on values. Every method and type is itself a value.
The term is the basic building block for an expression. A term can be one of the following: a literal, a variable, or a pseudo-variable (e.g., 'this', 'self' or '...'). With the exception of the splat ('...'), a simple term references a single stored value.
A literal is a specific unchangeable value, as represented by a number token, symbol or text token, or the reserved names null, true or false. For example (with comments to indicate each literal's type):
123 # Integer 3.4 # Float "Hello" # Text 'sum' # Symbol false # Bool null # Null (represents the absence of a value)
Note Text literals are flagged as read-only. Any attempt to modify them fails. This ensures the literal can never be corrupted by any downstream method.
Pseudo-variables: self, this, context, selfmethod, baseurl and ...
These pseudo-variables look like variables, but are not, as their value is managed by Acorn based on the context where they are encountered. Programs cannot change their value.
- self is the value which is passed to a method, indicating what the method is supposed to be acting on.
- this is the value that is the focus of attention within a 'this' block.
- context holds the value of the current execution context that preserves state information about all currently running methods and their local variables. Using its properties, one can obtain information about all actively-running methods, and their local variables.
- selfmethod holds the value of the currently executing running Method or Closure.
- baseurl holds the url symbol for the program resource that defined the currently running method. Any relative addresses for resources are resolved based on this baseurl.
- ... (splat) refers to all remaining parameters passed to a method after the ones that have been given variable names.
A variable holds a single value. A variable's value is set, modified and retrieved using its name. A variable's value may be changed as often as desired. Acorn does not enforce or restrict what type of value a variable can hold.
Variables are always represented with a non-reserved name token.
The value of a variable is set using an assignment expression:
a = 3.4 # a's value is now 3.4 b = 'abc' # b's value is now the symbol 'abc' a = b # changes a's value to the symbol 'abc' b = true # changes b's value to the literal true
Any variable to the left of the assignment operator '=' sets the variable's value. A variable found anywhere else retrieves (gets) the value of the variable.
There are several situations where it is helpful to assign multiple values to multiple variables:
# Swap the variable values for a and b a,b = b,a # Capture multiple return values from a method, # such as destructuring the values held by a collection x,y,z = position.unpack # Obtain certain values from the splat template, val1, val2 = ...
A variable's value is stored within a larger collection of values, which we call its scope. A variable's scope is determined by the first character of the variable name:
- Each method has its own parameter, local and closure variables,
all of which start with a lowercase letter ('a' to 'z'):
- the parameters passed to the method.
- the local variables which are created anew each time the method is performed, so that two identically-named local variables in different scopes will not collide with each other. These local variables are destroyed as soon as the work of the method is complete.
- the closure variables, which stick around every time a closure's method is re-performed. Closure variables are kept separately from the temporary local variables, assembled as part of a created closure and lasting as long as the closure does.
- private instance variables, members of 'self', start with an underscore ('_').
- global variables, shared across all methods,
start with a capital letter (global Types) or '$' (environment variables).
Any method can retrieve or change a global value at any time, Unless one is careful to restrict use of global variables only to a few that are widely needed, there is a great risk of global variable pollution and corruption. Generally, the global context is used for types and environment variables (e.g., '$').