User Tools

Site Tools


language_overview

The Nanosyntax language

This page is accurate as of Nanoverse v1.0.0-a6. If you are using a later version, some aspects may have changed.

Nanoverse uses a declarative programming language with a functional flavor. This language, which is designed specifically for agent-based modeling, is called Nanosyntax. In Nanosyntax, the user defines the desired properties of the simulation, including relationships between simulation components and between the current and future state of the simulation. The user generally does not mutate simulation state directly, instead using functions to define these changes (and when they should occur) relative to other properties of the simulation.

Note: the Nanosyntax language is evolving rapidly. Please check back to this page after each release for information on syntax changes.

Objects and properties

Nanoverse simulations are specified as a hierarchy of object specifications. Objects can have zero or more properties. Properties can themselves be object specifications, or they can be constant primitives (see below).

Aficionados might note that object specifications are object supplier functions, not the objects themselves. That is, the user is specifying what kind of object will be created when the time comes, rather than actually creating one right then and there. For example, a user may define a particular kind of Agent, with a unique set of behaviors (and properties in upcoming releases of Nanoverse). Defining this Agent does not actually create one. It is specifying what the Agent will be like when it is placed into the simulation, for example through a Scatter or Fill process. In this sense, object specifications are functions with a no input and with an object as output.

Some properties are optional, meaning that a default is supplied if the user omits a value. The root object is the simulation itself. It has several properties, all of which are optional. As a result, a completely blank file is a valid Nanoverse project: it represents a simulation in which the user has omitted all simulation properties.

Sentences

Assignments

The most basic sentence in Nanosyntax is a key-value pair, called an assignment:

property: Value;

Notice that Value is capitalized, whereas property is not. Object specifications are always capitalized, and in this case the value of property is defined to be an object specification of type Value. If the value of the property does not match the expected type, the Nanoverse compiler will halt with an error.

Hierarchies

What if Value had properties of its own? We can assign them the same way:

property: Value: subProperty: SubValue;

Whitespace

The sentence above is hard to read. Fortunately, Nanoverse is not sensitive to whitespace, meaning that you can format sentences however you wish. For example, you may wish to communicate the hierarchical structure of this sentence with indentation:

property: 
 Value: 
  subProperty: 
   SubValue;

Blocks

You can also use curly brackets to indicate blocks. (As of Nanoverse 1.0.0-a6, you have to terminate a block with a trailing semicolon, but we're working on it!)

property { 
 Value { 
  subProperty { 
   SubValue;
  };
 };
};

Types

Every property can take a value, and every value has a type. Since object specifications provide values for properties, they must have the same type as the property itself. If they do not, Nanoverse will halt with a compiler error. Nanoverse has four base types, named after the kind of information they supply: primitives, objects, lists, and maps.

Types and classes

A type refers to the ways in which an object can communicate with other objects. That is, types refer to object interfaces. A class refers to the way in which those interactions unfold. That is, a class refers to the implementation of an object. Typically, Nanoverse objects have one class and one type. Many types are implemented by more than one class.

For example, the Shape type (which is used to specify the shape of the arena boundary) could be implemented as a Rectangle, a Line, a Cube or a Hexagon. These are each classes with the type Shape.

Primitives

Primitives represent values of a basic data type. The basic types are String (text enclosed in brackets), Float (real numbers), Integer (integer numbers), and Boolean (true or false values). Constants are specified as they are in most computer languages:

myString: "abc";
myFloat: 3.14;
myInteger: 3;
myBoolean: True;

There are also non-constant functions that have a primitive return type. Examples include built-in reporting functions that report the value of a layer, as well as random number generators.

myRandomFloat: Uniform {
  min: 2.0;
  max: 10.0;
};

Objects

As the name suggests, object values return objects. These objects might have properties of their own, resulting in a property hierarchy. They are specified in exactly the same manner as primitive functions:

myObject: 
 SomeObject:
  subProperty: 
   AnotherObject;

Lists

Some properties can accept multiple arguments. Such a value is called a list. Lists have an expected element type, and all elements of the list must have that type. Syntactically, lists are specified like blocks, except that each element is a value.

// List of objects
myObjectList {
 AnObject;
 AnotherObject;
 AndAnother;
};

// List of primitives
myPrimitiveList {
 1;
 2;
 3;
 4;
};

// Block -- not a list!
myBlock {
 property: AnObject;
 anotherProperty: AnotherObject;
};

Maps

Some properties may expect a correspondence between names and values. Such a value is called a map. Maps are exactly the same as blocks, except that the user provides an arbitrary list of properties. As with lists, each property must have the same type, called the element type of the map. Maps are indistinguishable from blocks except by context.

// Is it a block or a map? Only context will tell.
blockOrMap {
 key: Value;
 anotherKey: AnotherValue;
};
language_overview.txt · Last modified: 2015/11/17 11:20 by david