-
Notifications
You must be signed in to change notification settings - Fork 3
Types
golog++
is a strictly typed language without implicit conversion.
The basic types bool
, number
and string
are always defined.
All other types are user-defined.
golog++
does not distinguish between floating-point and integral numbers, and it does not specify any conversion logic.
Number conversion is handled by the semantics backend, which should be transparent to the programmer.
All non-strings can be converted to strings with the to_string(_)
function, and strings can be concatenated with the +
operator.
A symbol is a known, unquoted name that must be defined as an element of some domain before it can be referenced anywhere else in the code.
User-defined types are structures: Either Domains, lists of an arbitrary number of elements of the same type (accessible by index), or compounds of a finite number of named elements which can have different types. Since there is an infinite number possible type compositions, new complex types must be defined before they can be used anywhere in the code.
list[TYPE]
list[number]
list[list[number]]
This defines two list types. One that contains numbers and one that contains lists of numbers.
A compound is a typesafe key-value structure that can contain elements of mixed types.
compound Quaternion {
number x,
number y,
number z,
number w
}
compound Vector3 {
number x,
number y,
number z
}
compound Pose {
Vector3 trans,
Quaternion rot,
string frame
}
Compound access:
procedure print_vector(Vector3 v) {
print("( x=" + v.x + ", y=" + v.y + ", z=" + v.z + ")");
}
golog++
has no implicit type conversion.
The only case where an assignment between expressions of inequal types is possible is if the left-hand side's type subsumes the right-hand side's type.
Since all built-in types can be thought of as infinite sets, only user-defined domain
types can be subsumed by other types, because they are the only ones that have a defined, finite number of elements.
This is equivalent to saying golog++
has only downcasting and no upcasting in OOP terms.
symbol domain block = {a, b, c}
symbol domain location = block | {table} // Set union, i.e. location = {a, b, c, table}
Here, the type location
subsumes the type block
(i.e. block
is a subset of location
). The type symbol
subsumes location
, and thereby also block
. Thus, given:
block fluent b();
location fluent l();
symbol fluent s();
The following are valid assignments:
s() = l();
s() = b();
l() = b();
While the following are invalid and will raise a TypeError when attempting to load the code:
b() = l();
b() = s();
l() = s();
Note that by extension, every builtin type T
is a strict superset of every user-defined type T domain USERTYPE
.