IndexNextUpPreviousUrbi SDK 3.0.0

Chapter 21
urbiscript Standard Library

This chapter details the predefined objects.

 21.1 Barrier
  21.1.1 Prototypes
  21.1.2 Construction
  21.1.3 Slots
 21.2 Binary
  21.2.1 Prototypes
  21.2.2 Construction
  21.2.3 Slots
 21.3 Boolean
  21.3.1 Truth Values
  21.3.2 Prototypes
  21.3.3 Construction
  21.3.4 Slots
 21.4 CallMessage
  21.4.1 Examples
  21.4.2 Prototypes
  21.4.3 Slots
 21.5 Channel
  21.5.1 Prototypes
  21.5.2 Construction
  21.5.3 Slots
 21.6 Code
  21.6.1 Prototypes
  21.6.2 Construction
  21.6.3 Slots
 21.7 Comparable
  21.7.1 Example
  21.7.2 Prototypes
  21.7.3 Slots
 21.8 Container
  21.8.1 Prototypes
  21.8.2 Slots
 21.9 Control
  21.9.1 Prototypes
  21.9.2 Slots
 21.10 Date
  21.10.1 Prototypes
  21.10.2 Construction
  21.10.3 Slots
 21.11 Dictionary
  21.11.1 Example
  21.11.2 Hash values
  21.11.3 Prototypes
  21.11.4 Construction
  21.11.5 Slots
 21.12 Directory
  21.12.1 Prototypes
  21.12.2 Construction
  21.12.3 Slots
 21.13 Duration
  21.13.1 Prototypes
  21.13.2 Construction
  21.13.3 Slots
 21.14 Enumeration
  21.14.1 Examples
  21.14.2 Prototypes
  21.14.3 Construction
  21.14.4 Slots
 21.15 Event
  21.15.1 Examples
  21.15.2 Synchronicity of Event Handling
  21.15.3 Sustained Events
  21.15.4 Prototypes
  21.15.5 Construction
  21.15.6 Slots
 21.16 Exception
  21.16.1 Prototypes
  21.16.2 Construction
  21.16.3 Slots
 21.17 Executable
  21.17.1 Prototypes
  21.17.2 Construction
  21.17.3 Slots
 21.18 File
  21.18.1 Prototypes
  21.18.2 Construction
  21.18.3 Slots
 21.19 Finalizable
  21.19.1 Example
  21.19.2 Prototypes
  21.19.3 Construction
  21.19.4 Slots
 21.20 Float
  21.20.1 Prototypes
  21.20.2 Construction
  21.20.3 Slots
 21.21 Float.limits
  21.21.1 Prototypes
  21.21.2 Slots
 21.22 FormatInfo
  21.22.1 Prototypes
  21.22.2 Construction
  21.22.3 Slots
 21.23 Formatter
  21.23.1 Prototypes
  21.23.2 Construction
  21.23.3 Slots
 21.24 Global
  21.24.1 Prototypes
  21.24.2 Slots
 21.25 Group
  21.25.1 Example
  21.25.2 Prototypes
  21.25.3 Construction
  21.25.4 Slots
 21.26 Hash
  21.26.1 Prototypes
  21.26.2 Construction
  21.26.3 Slots
 21.27 InputStream
  21.27.1 Prototypes
  21.27.2 Construction
  21.27.3 Slots
 21.28 IoService
  21.28.1 Example
  21.28.2 Prototypes
  21.28.3 Construction
  21.28.4 Slots
 21.29 Job
  21.29.1 Prototypes
  21.29.2 Construction
  21.29.3 Slots
 21.30 Kernel1
  21.30.1 Prototypes
  21.30.2 Construction
  21.30.3 Slots
 21.31 Lazy
  21.31.1 Examples
  21.31.2 Caching
  21.31.3 Prototypes
  21.31.4 Construction
  21.31.5 Slots
 21.32 List
  21.32.1 Prototypes
  21.32.2 Construction
  21.32.3 Slots
 21.33 Loadable
  21.33.1 Example
  21.33.2 Prototypes
  21.33.3 Construction
  21.33.4 Slots
 21.34 Lobby
  21.34.1 Examples
  21.34.2 Prototypes
  21.34.3 Construction
  21.34.4 Slots
 21.35 Location
  21.35.1 Prototypes
  21.35.2 Construction
  21.35.3 Slots
 21.36 Logger
  21.36.1 Examples
  21.36.2 Existing Categories
  21.36.3 Prototypes
  21.36.4 Construction
  21.36.5 Slots
 21.37 Math
  21.37.1 Prototypes
  21.37.2 Construction
  21.37.3 Slots
 21.38 Matrix
  21.38.1 Prototypes
  21.38.2 Construction
  21.38.3 Slots
 21.39 Mutex
  21.39.1 Prototypes
  21.39.2 Construction
  21.39.3 Slots
 21.40 nil
  21.40.1 Prototypes
  21.40.2 Construction
  21.40.3 Slots
 21.41 Object
  21.41.1 Prototypes
  21.41.2 Construction
  21.41.3 Slots
 21.42 Orderable
  21.42.1 Example
  21.42.2 Prototypes
  21.42.3 Slots
 21.43 OutputStream
  21.43.1 Prototypes
  21.43.2 Construction
  21.43.3 Slots
 21.44 Pair
  21.44.1 Prototypes
  21.44.2 Construction
  21.44.3 Slots
 21.45 Path
  21.45.1 Prototypes
  21.45.2 Construction
  21.45.3 Slots
 21.46 Pattern
  21.46.1 Prototypes
  21.46.2 Construction
  21.46.3 Slots
 21.47 Position
  21.47.1 Prototypes
  21.47.2 Construction
  21.47.3 Slots
 21.48 Primitive
  21.48.1 Prototypes
  21.48.2 Construction
  21.48.3 Slots
 21.49 Process
  21.49.1 Example
  21.49.2 Prototypes
  21.49.3 Construction
  21.49.4 Slots
 21.50 Profile
  21.50.1 Example
  21.50.2 Prototypes
  21.50.3 Construction
  21.50.4 Slots
 21.51 Profile.Function
  21.51.1 Prototypes
  21.51.2 Construction
  21.51.3 Slots
 21.52 PseudoLazy
  21.52.1 Prototypes
  21.52.2 Slots
 21.53 PubSub
  21.53.1 Prototypes
  21.53.2 Construction
  21.53.3 Slots
 21.54 PubSub.Subscriber
  21.54.1 Prototypes
  21.54.2 Construction
  21.54.3 Slots
 21.55 RangeIterable
  21.55.1 Prototypes
  21.55.2 Slots
 21.56 Regexp
  21.56.1 Prototypes
  21.56.2 Construction
  21.56.3 Slots
 21.57 Semaphore
  21.57.1 Prototypes
  21.57.2 Construction
  21.57.3 Slots
 21.58 Serializables
  21.58.1 Prototypes
  21.58.2 Slots
 21.59 Server
  21.59.1 Prototypes
  21.59.2 Construction
  21.59.3 Slots
 21.60 Singleton
  21.60.1 Prototypes
  21.60.2 Construction
  21.60.3 Slots
 21.61 Slot
  21.61.1 Accessing the slot object
  21.61.2 Key features
  21.61.3 Split mode
  21.61.4 Construction
  21.61.5 Prototypes
  21.61.6 Slots
 21.62 Socket
  21.62.1 Example
  21.62.2 Prototypes
  21.62.3 Construction
  21.62.4 Slots
 21.63 StackFrame
  21.63.1 Prototypes
  21.63.2 Construction
  21.63.3 Slots
 21.64 Stream
  21.64.1 Prototypes
  21.64.2 Construction
  21.64.3 Slots
 21.65 String
  21.65.1 Prototypes
  21.65.2 Construction
  21.65.3 Slots
 21.66 Subscription
  21.66.1 Prototypes
  21.66.2 Construction
  21.66.3 Slots
 21.67 System
  21.67.1 Prototypes
  21.67.2 Slots
 21.68 System.PackageInfo
  21.68.1 Prototypes
  21.68.2 Slots
 21.69 System.Platform
  21.69.1 Prototypes
  21.69.2 Slots
 21.70 Tag
  21.70.1 Examples
  21.70.2 Hierarchical tags
  21.70.3 Prototypes
  21.70.4 Construction
  21.70.5 Slots
 21.71 Timeout
  21.71.1 Examples
  21.71.2 Prototypes
  21.71.3 Construction
  21.71.4 Slots
 21.72 Traceable
  21.72.1 Prototypes
  21.72.2 Slots
 21.73 TrajectoryGenerator
  21.73.1 Examples
  21.73.2 Prototypes
  21.73.3 Construction
  21.73.4 Slots
 21.74 Triplet
  21.74.1 Prototypes
  21.74.2 Construction
  21.74.3 Slots
 21.75 Tuple
  21.75.1 Prototypes
  21.75.2 Construction
  21.75.3 Slots
 21.76 UObject
  21.76.1 Prototypes
  21.76.2 Slots
 21.77 uobjects
  21.77.1 Prototypes
  21.77.2 Slots
 21.78 UValue
  21.78.1 Prototypes
  21.78.2 Slots
 21.79 UValueSerializable
  21.79.1 Example
  21.79.2 Prototypes
  21.79.3 Slots
 21.80 Vector
  21.80.1 Prototypes
  21.80.2 Construction
  21.80.3 Slots
 21.81 void
  21.81.1 Prototypes
  21.81.2 Construction
  21.81.3 Slots

21.1 Barrier

Barrier is used to wait until another job raises a signal. This can be used to implement blocking calls waiting until a resource is available.

21.1.1 Prototypes

21.1.2 Construction

A Barrier can be created with no argument. Calls to signal and wait done on this instance are restricted to this instance.

 
Barrier.new(); 
[00000000] Barrier_0x25d2280  

21.1.3 Slots

21.2 Binary

A Binary object, sometimes called a blob, is raw memory, decorated with a user defined header.

21.2.1 Prototypes

21.2.2 Construction

Binaries are usually not made by users, but they are heavily used by the internal machinery when exchanging Binary UValues. A binary features some content and some keywords, both simple Strings.

 
Binary.new("my header""my content"); 
[00000001] BIN 10 my header 
my content  

Beware that the third line above (‘my content’), was output by the system, although not preceded by a timestamp.

21.2.3 Slots

21.3 Boolean

There is no object Boolean in urbiscript, but two specific objects true and false. They are the result of all the comparison statements.

21.3.1 Truth Values

As in many programming languages, conditions may be more than only true and false. Whether some value is considered as true depends on the type of this. Actually, by default objects as considered “true”, objects evaluating to “false” are the exception:

The method Object.asBool is in charge of converting some arbitrary value into a Boolean.

 
assert(Global.asBool() == true); 
assert(nil.asBool() ==    false); 
void.asBool(); 
[00000421:error] !!! unexpected void  

21.3.2 Prototypes

The objects true and false have the following prototype.

21.3.3 Construction

There are no constructors, use true and false. Since they are singletons, clone will return themselves, not new copies.

 
true; 
!false; 
(2 < 6) === true; 
true.new() === true; 
(6 < 2) === false;  

21.3.4 Slots

21.4 CallMessage

Capturing a method invocation: its target and arguments.

21.4.1 Examples

21.4.1.1 Evaluating an argument several times

The following example implements a lazy function which takes an integer n, then arguments. The n-th argument is evaluated twice using evalArgAt.

 
function callTwice 

  var n = call.evalArgAt(0); 
  call.evalArgAt(n); 
  call.evalArgAt(n) 
} |; 
 
// Call twice echo("foo"). 
callTwice(1, echo("foo"), echo("bar")); 
[00000001] *** foo 
[00000002] *** foo 
 
// Call twice echo("bar"). 
callTwice(2, echo("foo"), echo("bar")); 
[00000003] *** bar 
[00000004] *** bar  

21.4.1.2 Strict Functions

Strict functions do support call.

 
function strict(x) 

  echo("Entering"); 
  echo("Strict: " + x); 
  echo("Lazy:   " + call.evalArgAt(0)); 
} |; 
 
strict({echo("1"); 1}); 
[00000011] *** 1 
[00000013] *** Entering 
[00000012] *** Strict: 1 
[00000013] *** 1 
[00000014] *** Lazy:   1  

21.4.2 Prototypes

21.4.3 Slots

21.5 Channel

Returning data, typically asynchronous, with a label so that the “caller” can find it in the flow.

21.5.1 Prototypes

21.5.2 Construction

Channels are created like any other object. The constructor must be called with a string which will be the label.

 
var ch1 = Channel.new("my_label"); 
[00000201] Channel<my_label> 
 
ch1 << 1; 
[00000201:my_label] 1 
 
var ch2 = ch1; 
[00000201] Channel<my_label> 
 
ch2 << 1/2; 
[00000201:my_label] 0.5  

21.5.3 Slots

21.6 Code

Functions written in urbiscript.

21.6.1 Prototypes

21.6.2 Construction

The keywords function and closure build Code instances.

 
function(){}.protos[0] === ’package’.lang.getSlotValue("Code"); 
closure (){}.protos[0] === ’package’.lang.getSlotValue("Code");  

21.6.3 Slots

21.7 Comparable

Objects that can be compared for equality and inequality. See also Orderable.

21.7.1 Example

This object, made to serve as prototype, provides a definition of != based on ==. Object provides a default implementation of == that bounces on the physical equality ===.

 
class Foo : Comparable 

  var value = 0; 
  function init (v)    { value = v; }; 
  function ’==’ (that) { value == that.value; }; 
}|; 
assert 

  Foo.new(1) == Foo.new(1); 
  Foo.new(1) != Foo.new(2); 
};  

21.7.2 Prototypes

21.7.3 Slots

21.8 Container

This object is meant to be used as a prototype for objects that support has and hasNot methods. Any class using this prototype must redefine either has, hasNot or both.

21.8.1 Prototypes

21.8.2 Slots

21.9 Control

Control is a namespace for control sequences used by the Urbi engine to execute some urbiscript features. It is internal; in other words, users are not expected to use it, much less change it.

21.9.1 Prototypes

21.9.2 Slots

21.10 Date

This class is meant to record dates in time, with microsecond resolution. See also System.time.

This feature is experimental. It might be changed in the future. Feedback on its use would be appreciated.

21.10.1 Prototypes

21.10.2 Construction

Without argument, newly constructed Dates refer to the current date.

 
Date.new; 
[00000001] 2010-08-17 14:40:52.549726  

With a string argument d, refers to the date contained in d. The string should be formatted as ‘yyyy-mm-dd hh:mn:ss ’ (see asString). mn and ss are optional. If the block ‘hh:mn:ss ’ is absent, the behavior is undefined.

 
Date.new("2003-10-10 20:10:50:637"); 
[00000001] 2003-10-10 20:10:50.637000 
 
Date.new("2003-10-10 20:10:50"); 
[00000001] 2003-10-10 20:10:50.000000 
 
Date.new("2003-Oct-10 20:10"); 
[00000002] 2003-10-10 20:10:00.000000 
 
Date.new("2003-10-10 20"); 
[00000003] 2003-10-10 20:00:00.000000  

Pay attention that the format is rather strict; for instance too many spaces between day and time result in an error.

 
Date.new("2003-10-10  20:10:50"); 
[00001968:error] !!! new: cannot convert to date: 2003-10-10  20:10:50  

Pay attention that the format is not strict enough either; for instance, below, the ‘.’ separator seem to prefix microseconds, but actually merely denotes the minutes. Seconds must be spelled out in order to introduce microseconds.

 
Date.new("2003-10-10 00.12"); 
[00000003] 2003-10-10 00:12:00.000000 
 
Date.new("2003-10-10 00:00.12"); 
[00000003] 2003-10-10 00:00:12.000000  

21.10.3 Slots

21.11 Dictionary

A dictionary is an associative array, also known as a hash in some programming languages. They are arrays whose indexes are arbitrary objects.

21.11.1 Example

The following session demonstrates the features of the Dictionary objects.

 
var d = ["one" => 1, "two" => 2]; 
[00000001] ["one" => 1, "two" => 2] 
 
for (var p : d) 
  echo (p.first + " => " + p.second); 
[00000003] *** one => 1 
[00000002] *** two => 2 
 
"three" in d; 
[00000004] false 
d["three"]; 
[00000005:error] !!! missing key: three 
d["three"] = d["one"] + d["two"]|; 
"three" in d; 
[00000006] true 
d.getWithDefault("four", 4); 
[00000007] 4  

21.11.2 Hash values

Arbitrary objects can be used as dictionary keys. To map to the same cell, two objects used as keys must have equal hashes (retrieved with the Object.hash method) and be equal to each other (in the Object.’==’ sense).

This means that two different objects may have the same hash: the equality operator (Object.’==’) is checked in addition to the hash, to handle such collision. However a good hash algorithm should avoid this case, since it hinders performances.

See Object.hash for more detail on how to override hash values. Most standard value-based classes implement a reasonable hash function: see Float.hash, String.hash, List.hash, …

21.11.3 Prototypes

21.11.4 Construction

The Dictionary constructor takes arguments by pair (key, value).

 
Dictionary.new("one", 1, "two", 2); 
[00000000] ["one" => 1, "two" => 2] 
Dictionary.new(); 
[00000000] [ => ]  

There must be an even number of arguments.

 
Dictionary.new("1", 2, "3"); 
[00000001:error] !!! new: odd number of arguments  

You are encouraged to use the specific syntax for Dictionary literals:

 
["one" => 1, "two" => 2]; 
[00000000] ["one" => 1, "two" => 2] 
[=>]; 
[00000000] [ => ]  

An extra comma can be added at the end of the list.

 

  "one" => 1, 
  "two" => 2, 
]; 
[00000000] ["one" => 1, "two" => 2]  

It is guaranteed that the pairs to insert are evaluated left-to-write, key first, the value.

 
   ["a".fresh() => "b".fresh(), "c".fresh() => "d".fresh()] 
== ["a_5"     => "b_6",     "c_7"     => "d_8"];  

Duplicate keys in Dictionary literal are an error. On this regards, urbiscript departs from choices made in JavaScript, Perl, Python, Ruby, and probably many other languages.

 
["one" => 1, "one" => 2]; 
[00000001:error] !!! duplicate dictionary key: "one"  

21.11.5 Slots

21.12 Directory

A Directory represents a directory of the file system.

21.12.1 Prototypes

21.12.2 Construction

A Directory can be constructed with one argument: the path of the directory using a String or a Path. It can also be constructed by the method open of Path.

 
Directory.new("."); 
[00000001] Directory(".") 
Directory.new(Path.new(".")); 
[00000002] Directory(".")  

21.12.3 Slots

21.13 Duration

This class records differences between Dates.

This feature is experimental. It might be changed in the future. Feedback on its use would be appreciated.

21.13.1 Prototypes

21.13.2 Construction

Without argument, a null duration.

 
Duration.new(); 
[00000001] Duration(0s) 
Duration.new(1h); 
[00023593] Duration(3600s)  

Durations can be negative.

 
Duration.new(-1); 
[00000001] Duration(-1s)  

21.13.3 Slots

21.14 Enumeration

Prototype of enumeration types.

21.14.1 Examples

See Section 20.5.

21.14.2 Prototypes

21.14.3 Construction

An Enumeration is created with two arguments: the name of the enumeration type, and the list of possible values. Most of the time, it is a good idea to store it in a variable with the same name.

 
var Direction = Enumeration.new("Direction", ["up""down""left""right"]); 
[00000001] Direction 
Direction.up; 
[00000002] up  

The following syntax is equivalent.

 
enum Direction 

  up, 
  down, 
  left, 
  right 
}; 
[00000001] Direction  

The created values are derive from the created enumeration type.

 
Direction.isA(Enumeration); 
Direction.up.isA(Direction);  

21.14.4 Slots

21.15 Event

An event can be “emitted” and “caught”, or “sent” and “received”. See also Section 11.2.

21.15.1 Examples

There are several examples of uses of events in the documentation of event-based constructs. See at (Listing 20.11.1), waituntil (Listing 20.11.2), whenever (Listing 20.11.4), and so forth. The tutorial chapter about event-based programming contains other examples, see Listing 11.

21.15.2 Synchronicity of Event Handling

A particular emphasis should be put on the synchronicity of the event handling, i.e., whether the bodies of the event handlers are run before the control flow returns from the event emission. By default, (i.e., at (e?...) and e!(...)/e.emit(...))) the execution is asynchronous, but if either the emitted or the handler is marked asynchronous (i.e., at sync (e?...) or e.syncEmit(...)), then the execution is synchronous.

Contrast the following examples:

Asynchronous handlers  

 
var e = Event.new() |; 
 
at (e?) 
  { echo("a"); sleep(20ms); echo("b") } 
onleave 
  { echo("c"); sleep(20ms); echo("d") }; 
 
e! | echo("done"); 
[00000001] *** done 
sleep(25ms); 
[00000002] *** a 
[00000003] *** c 
[00000101] *** b 
[00000102] *** d 
 
e.syncEmit() | echo("done"); 
[00000001] *** a 
[00000101] *** b 
[00000102] *** c 
[00000202] *** d 
[00000203] *** done  

Synchronous handlers  

 
var e = Event.new() |; 
 
at sync (e?) 
  { echo("a"); sleep(20ms); echo("b") } 
onleave 
  { echo("c"); sleep(20ms); echo("d") }; 
 
e! | echo("done"); 
// No need to sleep. 
[00000011] *** a 
[00000031] *** b 
[00000031] *** c 
[00000052] *** d 
[00000052] *** done 
 
e.syncEmit() | echo("done"); 
[00000052] *** a 
[00000073] *** b 
[00000073] *** c 
[00000094] *** d 
[00000094] *** done  

For more information about the synchronicity of event handlers, see Listing 20.11.1.3.

21.15.3 Sustained Events

Events can also be sustained during a time span starting at trigger and ending at handler.stop. Note that the onleave-clauses of the event handlers is not executed right after the event was first triggered, but rather when it is stopped.

Synchronicity for sustained events is more complex: the at-clause is handled asynchronously iff both the emission and the handler are asynchronous, whereas the onleave-clause is handled asynchronously iff the emission was synchronous. Be warned, but do not depend on this, as in the future we might change this.

Asynchronous Trigger  

 
var e = Event.new()|; 
at (e?(var v)) 
  { echo("a"+v); sleep(20ms); echo("b"+v) } 
onleave 
  { echo("c"+v); sleep(20ms); echo("d"+v) }; 
 
var handler = e.trigger(1) | echo("triggered"); 
[00000001] *** triggered 
[00000002] *** a1 
[00000102] *** b1 
sleep(200ms); 
handler.stop() | echo("stopped"); 
[00000301] *** stopped 
sleep(25ms); 
[00000302] *** c1 
[00000402] *** d1 
 
// at and onleave clauses may overlap. 
handler = e.trigger(2) | handler.stop(); 
sleep(25ms); 
[00000001] *** a2 
[00000002] *** c2 
sleep(25ms); 
[00000201] *** b2 
[00000202] *** d2 
 
handler = e.syncTrigger(3) | echo("triggered"); 
[00000002] *** a3 
[00000102] *** b3 
[00000001] *** triggered 
handler.stop() | echo("stopped"); 
[00000302] *** c3 
[00000402] *** d3 
[00000301] *** stopped  

Synchronous Trigger  

 
var e = Event.new()|; 
at sync (e?(var v)) 
  { echo("a"+v); sleep(20ms); echo("b"+v) } 
onleave 
  { echo("c"+v); sleep(20ms); echo("d"+v) }; 
 
var handler = e.trigger(1) | echo("triggered"); 
// No need to sleep. 
[00000002] *** a1 
[00000102] *** b1 
[00000001] *** triggered 
handler.stop() | echo("stopped"); 
[00000301] *** stopped 
sleep(25ms); 
[00000302] *** c1 
[00000402] *** d1 
 
// at and onleave clauses don’t overlap. 
handler = e.trigger(2) | handler.stop(); 
sleep(25ms); 
[00000001] *** a2 
[00000201] *** b2 
[00000002] *** c2 
[00000202] *** d2 
 
 
handler = e.syncTrigger(3) | echo("triggered"); 
[00000002] *** a3 
[00000102] *** b3 
[00000001] *** triggered 
handler.stop() | echo("stopped"); 
[00000302] *** c3 
[00000402] *** d3 
[00000301] *** stopped  

21.15.4 Prototypes

21.15.5 Construction

An Event is created like any other object. The constructor takes no argument.

 
var e = Event.new(); 
[00000001] Event_0x9ad8118  

21.15.6 Slots

21.16 Exception

Exceptions are used to handle errors. More generally, they are a means to escape from the normal control-flow to handle exceptional situations.

The language support for throwing and catching exceptions (using try/catch and throw, see Section 20.8) work perfectly well with any kind of object, yet it is a good idea to throw only objects that derive from Exception.

21.16.1 Prototypes

21.16.2 Construction

There are several types of exceptions, each of which corresponding to a particular kind of error. The top-level object, Exception, takes a single argument: an error message.

 
Exception.new("something bad has happened!"); 
[00000001] Exception ‘something bad has happened!’ 
Exception.Arity.new("myRoutine", 1, 10, 23); 
[00000002] Exception.Arity ‘myRoutine: expected between 10 and 23 arguments, given 1’  

21.16.3 Slots

Exception has many slots which are specific exceptions. See Section 21.16.3.2 for their documentation.

21.16.3.1 General Features

21.16.3.2 Specific Exceptions

In the following, since these slots are actually Objects, what is presented as arguments to the slots are actually arguments to pass to the constructor of the corresponding exception type.

21.17 Executable

This class is used only as a common ancestor to Primitive and Code.

21.17.1 Prototypes

21.17.2 Construction

There is no point in constructing an Executable.

21.17.3 Slots

21.18 File

21.18.1 Prototypes

21.18.2 Construction

Files may be created from a String, or from a Path. Using new, the file must exist on the file system, and must be a file. You may use create to create a file that does not exist (or to override an existing one).

 
File.new("file.txt"); 
[00000001:error] !!! new: no such file or directory: file.txt 
 
File.create("file.txt"); 
[00000002] File("file.txt") 
 
File.new(Path.new("file.txt")); 
[00000003] File("file.txt")  

You may use InputStream and OutputStream to read or write to Files.

21.18.3 Slots

21.19 Finalizable

Objects that derive from this object will execute their finalize routine right before being destroyed (reclaimed) by the system. It is comparable to a destructor.

21.19.1 Example

The following object is set up to die verbosely.

 
var obj = 
  do (Finalizable.new()) 
  { 
    function finalize () 
    { 
      echo ("Ouch"); 
    } 
  }|;  

It is reclaimed by the system when it is no longer referenced by any other object.

 
var alias = obj|; 
obj = nil|;  

Here, the object is still alive, since alias references it. Once it no longer does, the object dies.

 
alias = nil|; 
[00000004] *** Ouch  

21.19.2 Prototypes

21.19.3 Construction

The constructor takes no argument.

 
Finalizable.new(); 
[00000527] Finalizable_0x135360  

Because of specific constraints of Finalizable, you cannot change the prototype of an object to make it “finalizable”: it must be an instance of Finalizable from its inception.

There, instead of this invalid constructs,

 
class o2 

  protos = [Finalizable]; 
  function finalize() 
  { 
    echo("Ouch"); 
  } 
}|; 
[00000010:error] !!! apply: cannot inherit from a Finalizable without being one  

write:

 
class o1 : Finalizable 

  function finalize() 
  { 
    echo("Ouch"); 
  } 
}|; 
// Or 
var o3 = 
  do (Finalizable.new()) 
  { 
    function finalize() 
    { 
      echo("Ouch"); 
    } 
  }|;  

If you need multiple prototypes, do as follows.

 
import Global.*; 
class Global.Foo 

  function init() 
  { 
    echo("1"); 
  }; 
}|; 
 
class Global.FinalizableFoo 

  addProto(Foo.new()); 
 
  function ’new’() 
  { 
    var r = clone() | 
    r.init() | 
    Finalizable.new().addProto(r); 
  }; 
 
  function init() 
  { 
    echo("2"); 
  }; 
 
  function finalize() 
  { 
    echo("3"); 
  }; 
 
}|; 
 
var i = FinalizableFoo.new()|; 
[00000117] *** 1 
[00000117] *** 2 
 
i = nil; 
[00000117] *** 3  

21.19.4 Slots

21.20 Float

A Float is a floating point number. It is also used, in the current version of urbiscript, to represent integers.

21.20.1 Prototypes

21.20.2 Construction

The most common way to create fresh floats is using the literal syntax. Numbers are composed of three parts:

integral
(mandatory) a non empty sequence of (decimal) digits;
fractional
(optional) a period, and a non empty sequence of (decimal) digits;
exponent
(optional) either ‘e’ or ‘E’, an optional sign (‘+’ or ‘-’), then a non-empty sequence of digits.

In other words, float literals match the [0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)? regular expression. For instance:

 
0 == 0000.0000; 
// This is actually a call to the unary ’+’. 
+1 == 1; 
0.123456 == 123456 / 1000000; 
1e3 == 1000; 
1e-3 == 0.001; 
1.234e3 == 1234;  

Actually, underscores can be inserted between digits to improve legibility.

 
123_456.78_90 == 1234567890 / 10_000;  

There are also some special numbers, nan, inf.

 
Math.log(0) == -inf; 
Math.exp(-inf) == 0; 
(inf/inf).isNan;  

A null float can also be obtained with new.

 
Float.new() == 0;  

21.20.3 Slots

21.21 Float.limits

This singleton handles various limits related to the Float objects.

21.21.1 Prototypes

21.21.2 Slots

21.22 FormatInfo

A format info is used when formatting a la printf. It store the formatting pattern itself and all the format information it can extract from the pattern.

21.22.1 Prototypes

21.22.2 Construction

The constructor expects a string as argument, whose syntax is similar to printf’s. It is detailed below.

 
FormatInfo.new("%+2.3d"); 
[00000001] %+2.3d  

A formatting pattern must one of the following (brackets denote optional arguments):

where:

When accepted, the format string is decoded, and its features are made available as separate slots of the FormatInfo object.

 
do (FormatInfo.new("%5$+’=#06.12X")) 

  assert 
  { 
    rank      == 5;    // 5$ 
    prefix    == "+";  // + 
    group     == " ";  // ’ 
    alignment == 0;    // = 
    alt       == true; // # 
    pad       == "0";  // 0 
    width     == 6;    // 6 
    precision == 12;   // .12 
    uppercase == 1;    // X 
    spec      == "x";  // X 
  }; 
}|;  

Formats that do not conform raise errors.

 
FormatInfo.new("foo"); 
[00000001:error] !!! new: format: pattern does not begin with %: foo 
 
FormatInfo.new("%20m"); 
[00000002:error] !!! new: format: invalid conversion type character: m 
 
FormatInfo.new("%"); 
[00000003:error] !!! new: format: trailing ‘%’ 
 
FormatInfo.new("%ss"); 
[00062475:error] !!! new: format: spurious characters after format: s 
 
FormatInfo.new("%.ss"); 
[00071153:error] !!! new: format: invalid width after ‘.’: s 
 
FormatInfo.new("%|-8.2f|%%"); 
[00034983:error] !!! new: format: spurious characters after format: %%  

21.22.3 Slots

21.23 Formatter

A formatter stores format information of a format string like used in printf in the C library or in boost::format.

21.23.1 Prototypes

21.23.2 Construction

Formatters are created from format strings: they are split into regular strings and formatting patterns (FormatInfo), and stores them.

 
Formatter.new("Name:%s, Surname:%s;"); 
[00000001] Formatter ["Name:", %s, ", Surname:", %s, ";"]  

All the patterns are introduced with the percent character (%), and they must conform to a specific syntax, detailed in the section on the construction of the FormatInfo. To denote the percent character instead of introducing a formatting-specification, use two percent characters.

 
var f = Formatter.new("%10s level: %-4.1f%%"); 
[00039525] Formatter [%10s, " level: ", %-4.1f, "%"] 
 
for (var d: ["Battery" => 83.3, "Sound" => 60]) 
  echo (f % d.asList()); 
[00041133] ***    Battery level: 83.3% 
[00041138] ***      Sound level: 60  %  

Patterns can either all be non-positional (e.g., %s%s), or all positional (e.g., %1$s%2$s).

 
Formatter.new("%s%s"); 
[00371506] Formatter [%s, %s] 
Formatter.new("%1$s%2$s"); 
[00385602] Formatter [%1$s, %2$s] 
 
Formatter.new("%1$s%s"); 
[00409657:error] !!! new: format: cannot mix positional and non-positional\ 
 arguments: %1$s vs. %s  

21.23.3 Slots

21.24 Global

Global is designed for the purpose of being global namespace. Since Global is a prototype of Object and all objects are an Object, all slots of Global are accessible from anywhere.

21.24.1 Prototypes

21.24.2 Slots

21.25 Group

A transparent means to send messages to several objects as if they were one.

21.25.1 Example

The following session demonstrates the features of the Group objects. It first creates the Sample family of object, makes a group of such object, and uses that group.

 
class Sample 

  var value = 0; 
  function init(v)    { value = v; }; 
  function asString() { "<" + value.asString() + ">"; }; 
  function timesTen() { new(value * 10); }; 
  function plusTwo()  { new(value + 2); }; 
}; 
[00000000] <0> 
 
var group = Group.new(Sample.new(1), Sample.new(2)); 
[00000000] Group [<1>, <2>] 
group << Sample.new(3); 
[00000000] Group [<1>, <2>, <3>] 
group.timesTen.plusTwo; 
[00000000] Group [<12>, <22>, <32>] 
 
// Bouncing getSlot and updateSlot. 
group.value; 
[00000000] Group [1, 2, 3] 
group.value = 10; 
[00000000] Group [10, 10, 10] 
 
// Bouncing to each&. 
var sum = 0| 
for& (var v : group) 
  sum += v.value; 
sum; 
[00000000] 30  

21.25.2 Prototypes

21.25.3 Construction

Groups are created like any other object. The constructor can take members to add to the group.

 
Group.new(); 
[00000000] Group [] 
Group.new(1, "two"); 
[00000000] Group [1, "two"]  

21.25.4 Slots

21.26 Hash

A hash is a condensed, easily comparable representation of another value. They are mainly used to map Dictionary keys to values.

Equal objects must always have the same hash. Different objects should, as much as possible, have different hashes.

21.26.1 Prototypes

21.26.2 Construction

Objects can be hashed with Object.hash.

 
Object.new().hash().isA(Hash);  

21.26.3 Slots

21.27 InputStream

InputStreams are used to read (possibly binary) files by hand. File provides means to swallow a whole file either as a single large string, or a list of lines. InputStream provides a more fine-grained interface to read files.

21.27.1 Prototypes

Windows Issues

Beware that because of limitations in the current implementation, one cannot safely read from two different files at the same time under Windows.

21.27.2 Construction

An InputStream is a reading-interface to a file, so its constructor requires a File.

 
InputStream.new(0); 
[00000919:error] !!! new: argument 1: unexpected 0, expected a File 
 
File.save("file.txt""1\n2\n"); 
var i1 = InputStream.new(File.new("file.txt")); 
[00001208] InputStream_0x1046d16e0  

Cloning a closed Stream is valid, but it is forbidden to clone an opened one.

 
var i2 = InputStream.clone().new(File.new("file.txt")); 
[00001211] InputStream_0x1045f6760 
 
i1.clone(); 
[00001288:error] !!! clone: cannot clone opened Streams  

Do not forget to close the streams you opened (Section 21.64.2).

 
i1.close(); 
i2.close();  

21.27.3 Slots

21.28 IoService

An IoService is used to manage the various operations of a set of Socket.

All Socket and Server are by default using the default IoService which is polled regularly by the system.

21.28.1 Example

Using a different IoService is required if you need to perform synchronous read operations.

The Socket must be created by the IoService that will handle it using its makeSocket function.

 
var io = IoService.new()|; 
var s = io.makeSocket()|;  

You can then use this socket like any other.

 
// Make a simple hello server. 
var serverPort = 0| 
do (Server.new()) 

  listen("127.0.0.1""0"); 
  lobby.serverPort = port; 
  at (connection?(var s)) 
  { 
    s.write("hello"); 
  } 
}|; 
// Connect to it using our socket. 
s.connect("0.0.0.0", serverPort); 
at (s.received?(var data)) 
  echo("received something"); 
s.write("1;");  

…except that nothing will be read from the socket unless you call one of the poll/pollFor/pollOneFor functions of io.

 
sleep(200ms); 
s.isConnected(); // Nothing was received yet 
[00000001] true 
io.poll(); 
[00000002] *** received something 
sleep(200ms);  

21.28.2 Prototypes

21.28.3 Construction

A IoService is constructed with no argument.

21.28.4 Slots

21.29 Job

Jobs are independent threads of executions. Jobs can run concurrently. They can also be managed using Tags.

21.29.1 Prototypes

21.29.2 Construction

A Job is typically constructed via Control.detach, Control.disown, or Code.spawn.

 
detach(sleep(10)); 
[00202654] Job<shell_7> 
 
disown(sleep(10)); 
[00204195] Job<shell_8> 
 
function () { sleep(10) }.spawn(false); 
[00274160] Job<shell_9>  

21.29.3 Slots

21.30 Kernel1

This object plays the role of a name-space in which obsolete functions from urbiscript 1.0 are provided for backward compatibility. Do not use these functions, scheduled for removal.

21.30.1 Prototypes

21.30.2 Construction

Since it is a Singleton, you are not expected to build other instances.

21.30.3 Slots

21.31 Lazy

Lazies are objects that hold a lazy value, that is, a not yet evaluated value. They provide facilities to evaluate their content only once (memoization) or several times. Lazy are essentially used in call messages, to represent lazy arguments, as described in Section 21.4.

21.31.1 Examples

21.31.1.1 Evaluating once

One usage of lazy values is to avoid evaluating an expression unless it’s actually needed, because it’s expensive or has undesired side effects. The listing below presents a situation where an expensive-to-compute value (heavy_computation) might be needed zero, one or two times. The objective is to save time by:

We thus make the wanted expression lazy, and use the value method to fetch its value when needed.

 
// This function supposedly performs expensive computations. 
function heavy_computation() 

  echo("Heavy computation"); 
  return 1 + 1; 
}|; 
 
// We want to do the heavy computations only if needed, 
// and make it a lazy value to be able to evaluate it "on demand". 
var v = Lazy.new(closure () { heavy_computation() }); 
[00000000] heavy_computation() 
/* some code */
// So far, the value was not needed, and heavy_computation 
// was not evaluated. 
/* some code */
// If the value is needed, heavy_computation is evaluated. 
v.value(); 
[00000000] *** Heavy computation 
[00000000] 2 
// If the value is needed a second time, heavy_computation 
// is not reevaluated. 
v.value(); 
[00000000] 2  

21.31.1.2 Evaluating several times

Evaluating a lazy several times only makes sense with lazy arguments and call messages. See example with call messages in Section 21.4.1.1.

21.31.2 Caching

Lazy is meant for functions without argument. If you need caching for functions that depend on arguments, it is straightforward to implement using a Dictionary. In the future urbiscript might support dictionaries whose indices are not only strings, but in the meanwhile, convert the arguments into strings, as the following sample object demonstrates.

 
class UnaryLazy 

  function init(f) 
  { 
    results = [ => ]; 
    func = f; 
  }; 
  function value(p) 
  { 
    var sp = p.asString(); 
    if (results.has(sp)) 
      return results[sp]; 
    var res = func(p); 
    results[sp] = res | 
    res 
  }; 
  var results; 
  var func; 
} | 
// The function to cache. 
var inc = function(x) { echo("incing " + x) | x+1 } | 
// The function with cache. UnaryLazy simply takes the function as argument. 
var p = UnaryLazy.new(inc); 
[00062847] UnaryLazy_0x78b750 
p.value(1); 
[00066758] *** incing 1 
[00066759] 2 
p.value(1); 
[00069058] 2 
p.value(2); 
[00071558] *** incing 2 
[00071559] 3 
p.value(2); 
[00072762] 3 
p.value(1); 
[00074562] 2  

21.31.3 Prototypes

21.31.4 Construction

Lazies are seldom instantiated manually. They are mainly created automatically when a lazy function call is made (see Section 20.3.4). One can however create a lazy value with the standard new method of Lazy, giving it an argument-less function which evaluates to the value made lazy.

 
Lazy.new(closure () { /* Value to make lazy */ 0 }); 
[00000000] 0  

21.31.5 Slots

21.32 List

Lists implement possibly-empty ordered (heterogeneous) collections of objects.

21.32.1 Prototypes

21.32.2 Construction

Lists can be created with their literal syntax: a possibly empty sequence of expressions in square brackets, separated by commas. Non-empty lists may end with a comma (Section 20.1.6.5).

 
[]; // The empty list 
[00000000] [] 
[1, "2", [3,],]; 
[00000000] [1, "2", [3]]  

However, new can be used as expected.

 
List.new(); 
[00000001] [] 
[1, 2, 3].new(); 
[00000002] [1, 2, 3]  

21.32.3 Slots

21.33 Loadable

Loadable objects can be switched on and off — typically physical devices.

21.33.1 Example

The intended use is rather as follows:

 
import gsrapi.*; 
class Motor: Loadable 

  var val = 0; 
  function go(var d) 
  { 
    if (load) 
      val += d 
    else 
      echo("cannot advance, the motor is off")|; 
  }; 
}; 
[00000002] Motor 
 
var m = Motor.new(); 
[00000003] Motor_0x42364388 
 
m.load; 
[00000004] false 
 
m.go(1); 
[00000006] *** cannot advance, the motor is off 
 
m.on(); 
[00000007] Motor_0x42364388 
 
m.go(123); 
m.val; 
[00000009] 123  

21.33.2 Prototypes

21.33.3 Construction

Loadable can be constructed, but it hardly makes sense. This object should serve as a prototype.

21.33.4 Slots

21.34 Lobby

A lobby is the local environment for each (remote or local) connection to an Urbi server.

21.34.1 Examples

Since every lobby is-a Channel, one can use the methods of Channel.

 
lobby << 123; 
[00478679] 123 
lobby << "foo"
[00478679] "foo"  

21.34.2 Prototypes

21.34.3 Construction

A lobby is implicitly created at each connection. At the top level, this is a Lobby.

 
this.protos; 
[00000001] [Lobby] 
this.protos[0].protos; 
[00000003] [Channel_0x4233b248]  

Lobbies cannot be cloned, they must be created using create.

 
Lobby.new(); 
[00000177:error] !!! new: ‘Lobby’ objects cannot be cloned 
Lobby.create(); 
[00000174] Lobby_0x126450  

21.34.4 Slots

21.35 Location

This class aggregates two Positions and provides a way to print them as done in error messages.

21.35.1 Prototypes

21.35.2 Construction

Without argument, a newly constructed Location has its Positions initialized to the first line and the first column.

 
Location.new(); 
[00000001] 1.1  

With a Position argument p, the Location will clone the Position into the begin and end Positions.

 
Location.new(Position.new("file.u",14,25)); 
[00000001] file.u:14.25  

With two Positions arguments begin and end, the Location will clone both Positions into its own fields.

 
Location.new(Position.new("file.u",14,25), Position.new("file.u",14,35)); 
[00000001] file.u:14.25-34  

21.35.3 Slots

21.36 Logger

Logger is used to report information to the final user or to the developer. It allows to pretty print warnings, errors, debug messages or simple logs. Logger can also be used as Tag objects for it to handle nested calls indentation. A log message is assigned a category which is shown between brackets at beginning of lines, and a level which defines the context in which it has to be shown (see Section 19.1.2). Log level definition and categories filtering can be changed using environment variables defined in Section 19.1.2.

21.36.1 Examples

The proper use of Loggers is to instantiate your own category, and then to use the operator << for log messages, possibly qualified by the proper level (in increase order of importance: dump, debug, trace, log, warn, err):

 
var logger = Logger.new("Category")|; 
 
logger.dump() << "Low level debug message"|; 
// Nothing displayed, unless the debug level is set to DUMP. 
 
logger.warn() << "something wrong happened, proceeding"|; 
[       Category        ] something wrong happened, proceeding 
 
logger.err() << "something really bad happened!"|; 
[       Category        ] something really bad happened!  

You may also directly use the logger and passing arguments to these slots.

 
Logger.log("message""Category") |; 
[       Category        ] message 
 
Logger.log("message""Category") : 

  Logger.log("indented message""SubCategory"
}|; 
[       Category        ] message 
[      SubCategory      ]   indented message  

21.36.2 Existing Categories

Urbi SDK comes with a number of built-in categories that all belong to one of the four following category families. Precise categories are provided for information, but there is no guarantee that these categories will maintained, that their semantics will not change, or that they are all listed here.

Libport
The Libport library.
Sched
The coroutine library.
Serialize
The serialization library.
Urbi
Everything about Urbi SDK.
Urbi.Parser
Bison parser traces.
Urbi.Scanner
Flex scanner traces.

21.36.3 Prototypes

21.36.4 Construction

Logger can be used as is, without being cloned. It is possible to clone Logger defining a category and/or a level of debug.

 
Logger.log("foo"); 
[        Logger         ] foo 
[00004702] Logger<Logger> 
 
Logger.log("bar""Category") |; 
[       Category        ] bar 
 
var l = Logger.new("Category2"); 
[00004703] Logger<Category2> 
 
l.log("foo")|; 
[       Category2       ] foo 
 
l.log("foo""ForcedCategory") |; 
[    ForcedCategory     ] foo  

21.36.5 Slots

21.37 Math

This object is meant to play the role of a name-space in which the mathematical functions are defined with a more conventional notation. Indeed, in an object-oriented language, writing pi.cos makes perfect sense, yet cos(pi) is more usual.

Math is a package, so you can use

 
import Math.*;  

to make its Slots visible.

21.37.1 Prototypes

21.37.2 Construction

Since it is a Singleton, you are not expected to build other instances.

21.37.3 Slots

21.38 Matrix

21.38.1 Prototypes

21.38.2 Construction

The init function is overloaded, and its behavior depends on the number of arguments and their types.

When there is a single argument, it can either be a List, or another Matrix.

If it’s a List of “Vectors and/or Lists of Floats”, then they must have the same sizes and constitute the rows.

 
var listList     = Matrix.new([           [0, 1],             [0, 1] ]); 
[00071383] Matrix([ 
  [0, 1], 
  [0, 1]]) 
var listVector   = Matrix.new([           [0, 1],  Vector.new([0, 1])])|; 
var vectorList   = Matrix.new([Vector.new([0, 1]),            [0, 1] ])|; 
var vectorVector = Matrix.new([Vector.new([0, 1]), Vector.new([0, 1])])|; 
 
assert 

  listList == listVector; 
  listList == vectorList; 
  listList == vectorVector; 
}; 
Matrix.new([           [0],            [1, 2]]); 
[00000030:error] !!! new: expecting rows of size 1, got size 2 for row 2 
Matrix.new([Vector.new([0]),           [1, 2]]); 
[00000056:error] !!! new: expecting rows of size 1, got size 2 for row 2 
Matrix.new([           [0], Vector.new([1, 2])]); 
[00000071:error] !!! new: expecting rows of size 1, got size 2 for row 2 
Matrix.new([Vector.new([0]), Vector.new([1, 2])]); 
[00052403:error] !!! new: expecting rows of size 1, got size 2 for row 2  

If it’s a Matrix, then there is a deep-copy: they are not aliases.

 
var m1 = Matrix.new([[1, 1], [1, 1]])|; 
var m2 = Matrix.new(m1)|; 
m2[0, 0] = 0|; 
assert 

  m1 == Matrix.new([[1, 1], [1, 1]]); 
  m2 == Matrix.new([[0, 1], [1, 1]]); 
};  

When given two Float arguments, they must be the two integers, defining the size of the null Matrix.

 
Matrix.new(2, 3); 
[00051329] Matrix([ 
  [0, 0, 0], 
  [0, 0, 0]])  

In other cases, the arguments are expected to be Lists of Floats and/or Vectors.

 
Matrix.new([1, 2])                   == Matrix.new([[1, 2]]); 
Matrix.new([1, 2],           [3, 4]) == Matrix.new([[1, 2], [3, 4]]); 
Matrix.new([1, 2], Vector.new(3, 4)) == Matrix.new([[1, 2], [3, 4]]);  

These rows must have equal sizes.

 
// Lists and Lists. 
Matrix.new([0], [1, 2]); 
[00000160:error] !!! new: expecting rows of size 1, got size 2 for row 2 
Matrix.new([0, 1], [2]); 
[00000169:error] !!! new: expecting rows of size 2, got size 1 for row 2 
 
// Lists and Vectors. 
Matrix.new([0], Vector.new(1, 2)); 
[00000178:error] !!! new: expecting rows of size 1, got size 2 for row 2 
Matrix.new(Vector.new(0, 1), [2]); 
[00000186:error] !!! new: expecting rows of size 2, got size 1 for row 2 
 
// Vectors and Vectors. 
Matrix.new(Vector.new(0), Vector.new(1, 2)); 
[00000195:error] !!! new: expecting rows of size 1, got size 2 for row 2 
Matrix.new(Vector.new(0, 1), Vector.new(2)); 
[00000204:error] !!! new: expecting rows of size 2, got size 1 for row 2  

21.38.3 Slots

21.39 Mutex

Mutex allow to define critical sections.

21.39.1 Prototypes

21.39.2 Construction

A Mutex can be constructed like any other Tag but without name.

 
var m = Mutex.new(); 
[00000000] Mutex_0x964ed40  

You can define critical sections by tagging your code using the Mutex.

 
var m = Mutex.new()|; 
m: echo("this is critical section"); 
[00000001] *** this is critical section  

As a critical section, two pieces of code tagged by the same “Mutex” will never be executed at the same time.

Mutexes must be used when manipulating data structures in a non atomic way to avoid inconsistent states.

Consider this apparently simple code:

 
function appendAndTellIfFirst(list, val) 

  var res = list.empty; 
  list << val; 
  res 
}|; 
var l = []; 
[00000001] [] 
appendAndTellIfFirst(l, 1); 
[00000002] true 
appendAndTellIfFirst(l, 2); 
[00000002] false  

Now look what happens if called twice in parallel:

 
l = []; 
[00000001] [] 
var res1; var res2; 
res1 = appendAndTellIfFirst(l, 1) & res2 = appendAndTellIfFirst(l, 2)|; 
res1; 
[00000002] true 
res2; 
[00000003] true 
l.sort(); // order is unspecified 
[00000004] [1, 2]  

Both tasks checked if the list was empty at the same time, and then appened the element.

A mutex will solve this problem:

 
l = []; 
[00000001] [] 
var m = Mutex.new(); 
[00000000] Mutex_0x964ed40 
// redefine the function using the mutex 
appendAndTellIfFirst = function (list, val) 
{m:{ 
  var res = list.empty; 
  list << val; 
  res 
}}|; 
// check again 
res1 = appendAndTellIfFirst(l, 1) & res2 = appendAndTellIfFirst(l, 2)|; 
// we do not know which one was first, but only one was 
[res1, res2].sort(); 
[00000001] [false, true] 
l.sort(); 
[00000004] [1, 2]  

Mutex constructor accepts an optional maximum queue size: code blocks trying to wait when maximum queue size is reached will not be executed:

 
var m = Mutex.new(1)|; 
var e = Event.new()|; 
at(e?) 
  m: { echo("executing at"); sleep(200ms);}; 
e!;e!;e!; 
sleep(600ms); 
[00000001] *** executing at 
[00000001] *** executing at  

As you can see above the message is only displayed twice: First at got executed right away, the second was queued and executed when the first one finished, and the third one got stopped.

21.39.3 Slots

21.40 nil

The special entity nil is an object used to denote an empty value. Contrary to void, it is a regular value which can be read.

21.40.1 Prototypes

21.40.2 Construction

Being a singleton, nil is not to be constructed, just used.

 
nil == nil;  

21.40.3 Slots

21.41 Object

Object includes the mandatory primitives for all objects in urbiscript. All objects in urbiscript must inherit (directly or indirectly) from it.

21.41.1 Prototypes

21.41.2 Construction

A fresh object can be instantiated by cloning Object itself.

 
Object.new(); 
[00000421] Object_0x00000000  

The keyword class also allows to define objects intended to serve as prototype of a family of objects, similarly to classes in traditional object-oriented programming languages (see Section 7.4).

 

  class Foo 
  { 
    var attr = 23; 
  }; 
  assert 
  { 
    Foo.localSlotNames() == ["asFoo""attr""type"]; 
    Foo.asFoo() === Foo; 
    Foo.attr == 23; 
    Foo.type == "Foo"
  }; 
};  

21.41.3 Slots

21.42 Orderable

Objects that have a concept of “less than”. See also Comparable.

21.42.1 Example

This object, made to serve as prototype, provides a definition of < based on >, and vice versa; and definition of <=/>= based on </>==. You must define either < or >, otherwise invoking either method will result in endless recursions.

 
class Foo : Orderable 

  var value = 0; 
  function init (v)   { value = v; }; 
  function ’<’ (that) { value < that.value; }; 
  function asString() { "<" + value.asString + ">"; }; 
}|; 
var one = Foo.new(1)|; 
var two = Foo.new(2)|; 
 
assert 

   one <= one  ;   one <= two  ; !(two <= one); 
 !(one >  one) ; !(one >  two) ;   two >  one; 
  (one >= one) ; !(one >= two) ;   two >= one; 
};  

21.42.2 Prototypes

21.42.3 Slots

21.43 OutputStream

OutputStreams are used to write (possibly binary) files by hand.

21.43.1 Prototypes

21.43.2 Construction

An OutputStream is a writing-interface to a file; its constructor requires a File. If the file already exists, content is appended to it. Remove the file beforehand if you want to override its content.

 
var o1 = OutputStream.new(File.create("file.txt")); 
[00001379] OutputStream_0x10808a300 
 
var o2 = OutputStream.new(File.new("file.txt")); 
[00001396] OutputStream_0x1080872e0  

Cloning a closed Stream is valid, but it is forbidden to clone an opened one.

 
var o3 = OutputStream.clone().new(File.new("file.txt")); 
[00001399] OutputStream_0x10803e7a0 
 
o1.clone(); 
[00001401:error] !!! clone: cannot clone opened Streams  

Do not forget to close the streams you opened (Section 21.64.2).

 
o1.close(); 
o2.close(); 
o3.close();  

21.43.3 Slots

21.44 Pair

A pair is a container storing two objects, similar in spirit to std::pair in C++.

21.44.1 Prototypes

21.44.2 Construction

A Pair is constructed with two arguments.

 
Pair.new(1, 2); 
[00000001] (1, 2) 
 
Pair.new(); 
[00000003:error] !!! new: expected 2 arguments, given 0 
 
Pair.new(1, 2, 3, 4); 
[00000003:error] !!! new: expected 2 arguments, given 4  

21.44.3 Slots

21.45 Path

A Path points to a file system entity (directory, file and so forth).

21.45.1 Prototypes

21.45.2 Construction

Path itself is the root of the file system: / on Unix, and C:\ on Windows.

 
Path; 
[00000001] Path("/")  

A Path is constructed with the string that points to the file system entity. This path can be relative or absolute.

 
Path.new("foo"); 
[00000002] Path("foo") 
 
Path.new("/path/file.u"); 
[00000001] Path("/path/file.u")  

Some minor simplifications are made, such as stripping useless ‘./’ occurrences.

 
Path.new("././///.//foo/"); 
[00000002] Path("./foo")  

21.45.3 Slots

21.46 Pattern

Pattern class is used to make correspondences between a pattern and another Object. The visit is done either on the pattern or on the element against which the pattern is compared.

Patterns are used for the implementation of the pattern matching. So any class made compatible with the pattern matching implemented by this class will allow you to use it implicitly in your scripts.

 
[1, var a, var b] = [1, 2, 3]; 
[00000000] [1, 2, 3] 
a; 
[00000000] 2 
b; 
[00000000] 3  

21.46.1 Prototypes

21.46.2 Construction

A Pattern can be created with any object that can be matched.

 
Pattern.new([1]); // create a pattern to match the list [1]. 
[00000000] Pattern_0x189ea80 
Pattern.new(Pattern.Binding.new("a")); // match anything into "a". 
[00000000] Pattern_0x18d98b0  

21.46.3 Slots

21.47 Position

This class is used to handle file locations with a line, column and file name.

21.47.1 Prototypes

21.47.2 Construction

Without argument, a newly constructed Position has its fields initialized to the first line and the first column.

 
Position.new(); 
[00000001] 1.1  

With a position argument p, the newly constructed Position is a clone of p.

 
Position.new(Position.new(2, 3)); 
[00000001] 2.3  

With two float arguments l and c, the newly constructed Position has its line and column defined and an empty file name.

 
Position.new(2, 3); 
[00000001] 2.3  

With three arguments f, l and c, the newly constructed Position has its file name, line and column defined.

 
Position.new("file.u", 2, 3); 
[00000001] file.u:2.3  

21.47.3 Slots

21.48 Primitive

C++ routine callable from urbiscript.

21.48.1 Prototypes

21.48.2 Construction

It is not possible to construct a Primitive.

21.48.3 Slots

21.49 Process

A Process is a separated task handled by the underneath operating system.

Windows Issues

Process is not yet supported under Windows.

21.49.1 Example

The following examples runs the cat program, a Unix standard command that simply copies on its (standard) output its (standard) input.

 
var p = Process.new("cat", []); 
[00000004] Process cat  

Just created, this process is not running yet. Use run to launch it.

 
p.status; 
[00000005] not started 
 
p.run(); 
p.status; 
[00000006] running  

Then we feed its input, named stdin in the Unix tradition, and close its input.

 
p.stdin << "1\n" | 
p.stdin << "2\n" | 
p.stdin << "3\n" |; 
 
p.status; 
[00000007] running 
 
p.stdin.close();  

At this stage, the status of the process is unknown, as it is running asynchronously. If it has had enough time to “see” that its input is closed, then it will have finished, otherwise we might have to wait for awhile. The method join means “wait for the process to finish”.

 
p.join(); 
 
p.status; 
[00000008] exited with status 0  

Finally we can check its output.

 
p.stdout.asList(); 
[00000009] ["1", "2", "3"]  

21.49.2 Prototypes

21.49.3 Construction

A Process needs a program name to run and a possibly-empty list of command line arguments. Calling run is required to execute the process.

 
Process.new("cat", []); 
[00000004] Process cat 
 
Process.new("cat", ["--version"]); 
[00000004] Process cat  

21.49.4 Slots

21.50 Profile

A Profile object contains information about the efficiency of a piece of code.

21.50.1 Example

21.50.1.1 Basic profiling

One can profile a piece of code with the System.profile function.

 
var profile = System.profile(function() { echo("foo") }); 
[00000001] *** foo 
[00001672] Profile( 
  Yields:                    0 
  Total time (us):        1085 
  Wall-clock time (us):   1085 
  Function calls:           12 
  Max depth:                 5 
 
  .-------------------------------------------------------------------. 
  |   function   |   %    | cumulative |  self  |  calls  |   self    | 
  |              |        |    (us)    |  (us)  |         | (us/call) | 
  |--------------+--------+------------+--------+---------+-----------| 
  |        apply |  26.91 |        292 |    292 |       1 |       292 | 
  |         echo |  25.35 |        567 |    275 |       1 |       275 | 
  |   <profiled> |  20.18 |        786 |    219 |       1 |       219 | 
  |         send |   6.36 |        855 |     69 |       1 |        69 | 
  |        apply |   4.61 |        905 |     50 |       1 |        50 | 
  |         oget |   4.24 |        951 |     46 |       2 |        23 | 
  |            + |   4.06 |        995 |     44 |       2 |        22 | 
  | getSlotValue |   3.32 |       1031 |     36 |       1 |        36 | 
  |            + |   2.76 |       1061 |     30 |       1 |        30 | 
  |     asString |   2.21 |       1085 |     24 |       1 |        24 | 
  ’--------------’--------’------------’--------’---------’-----------’ 
)  

The result is a Profile object that contains information about which functions where used when evaluating the given code, how many time they were called, how much time was spent in them, …Lines are sorted by decreasing “self time”. Note that the <profiled> special function stands for the function given in parameter. Every line is represented by a Profile.Function object, see its documentation for the meaning of every column.

21.50.1.2 Asynchronous profiling

If the profiled code spawns asynchronous tasks via detach or at for instance, additional statistics will be included in the resulting Profile every time the detached code is executed. This is extremely useful to profile asynchronous code based on at for instance.

 
var x = false|; 
// Make sure ’x’ is visible whoever the caller of ’profiled’ is. 
import this.*; 
function profiled() 

  at (x) 
    echo("true"
  onleave 
    echo("false"
}|; 
 
// This is the profiling for the creation of the ’at’. Note that the 
// condition was already evaluated once, to see whether it should trigger 
// immediately. 
var profile_async = System.profile(getSlotValue("profiled")); 
[00000000] Profile( 
  Yields:                    0 
  Total time (us):          73 
  Wall-clock time (us):     73 
  Function calls:            9 
  Max depth:                 4 
 
  .-------------------------------------------------------------------. 
  |   function   |   %    | cumulative |  self  |  calls  |   self    | 
  |              |        |    (us)    |  (us)  |         | (us/call) | 
  |--------------+--------+------------+--------+---------+-----------| 
  |   <profiled> |  46.58 |         34 |     34 |       1 |        34 | 
  |    at: { x } |  21.92 |         50 |     16 |       1 |        16 | 
  |      onEvent |  15.07 |         61 |     11 |       1 |        11 | 
  |        clone |   9.59 |         68 |      7 |       2 |     3.500 | 
  |          new |   2.74 |         72 |      2 |       2 |         1 | 
  |         init |   1.37 |         73 |      1 |       2 |     0.500 | 
  ’--------------’--------’------------’--------’---------’-----------’ 
) 
 
// Trigger the at twice. 
x = true|; 
[00106213] *** true 
x = false|; 
[00172119] *** false 
 
// The profile now includes additional statistic about the evaluations of 
// the condition and the bodies of the at. 
profile_async; 
[00178623] Profile( 
  Yields:                    2 
  Total time (us):         251 
  Wall-clock time (us):    251 
  Function calls:           29 
  Max depth:                 4 
 
  .-------------------------------------------------------------------. 
  |   function   |   %    | cumulative |  self  |  calls  |   self    | 
  |              |        |    (us)    |  (us)  |         | (us/call) | 
  |--------------+--------+------------+--------+---------+-----------| 
  |   <profiled> |  13.55 |         34 |     34 |       1 |        34 | 
  |        event |  11.55 |         63 |     29 |       1 |        29 | 
  |         send |  11.16 |         91 |     28 |       2 |        14 | 
  |        event |  10.76 |        118 |     27 |       1 |        27 | 
  |    at: { x } |  10.76 |        145 |     27 |       3 |         9 | 
  |        clone |   5.98 |        183 |     15 |       4 |     3.750 | 
  |         echo |   5.58 |        212 |     14 |       2 |         7 | 
  |      onEvent |   4.38 |        223 |     11 |       1 |        11 | 
  |            + |   1.99 |        228 |      5 |       4 |     1.250 | 
  |          new |   1.99 |        233 |      5 |       4 |     1.250 | 
  |     asString |   0.80 |        242 |      2 |       2 |         1 | 
  |         init |   0.80 |        248 |      2 |       4 |     0.500 | 
  ’--------------’--------’------------’--------’---------’-----------’ 
)  

Note that part of the internal machinery shows in these figures (and left visible on purpose). For instance the three additional calls to new correspond to the creation of the changed event.

21.50.2 Prototypes

21.50.3 Construction

Profile objects are not meant to be cloned as they are created by System.profile internal machinery.

21.50.4 Slots

21.51 Profile.Function

A Function object contains information about calls of a given function during a profiling operation.

21.51.1 Prototypes

21.51.2 Construction

Function objects are not meant to be cloned as they are created by System.profile internal machinery. As an example, let us profile the traditional factorial function.

 
function Float.fact() 

  if (this <= 1) 
    this 
  else 
    this * (this - 1).fact(); 
}|;  

To improve the consistency of the results, you are advised to run the profiling system (and function to profile) once before the real measure. This ensures that all the code is loaded and ready to be run: profiling will be about computations, not about initializations.

 
System.profile(function() { 20.fact() })|; 
 
var profile = System.profile(function() { 20.fact() }); 
[00009050] Profile( 
  Yields:                    0 
  Total time (us):         171 
  Wall-clock time (us):    171 
  Function calls:           79 
  Max depth:                22 
 
  .-------------------------------------------------------------------. 
  |   function   |   %    | cumulative |  self  |  calls  |   self    | 
  |              |        |    (us)    |  (us)  |         | (us/call) | 
  |--------------+--------+------------+--------+---------+-----------| 
  |         fact |  70.18 |        120 |    120 |      20 |         6 | 
  |            - |  10.53 |        138 |     18 |      19 |     0.947 | 
  |           <= |   8.77 |        153 |     15 |      20 |     0.750 | 
  |            * |   8.19 |        167 |     14 |      19 |     0.737 | 
  |   <profiled> |   2.34 |        171 |      4 |       1 |         4 | 
  ’--------------’--------’------------’--------’---------’-----------’ 
) 
profile.calls[0]; 
[00123833] Function(’fact’, 20, 0.000120, 0.000006) 
profile.calls[0].isA(Profile.Function); 
[00123933] true  

21.51.3 Slots

21.52 PseudoLazy

21.52.1 Prototypes

21.52.2 Slots

21.53 PubSub

PubSub provides an abstraction over Barrier Barrier to queue signals for each subscriber.

21.53.1 Prototypes

21.53.2 Construction

A PubSub can be created with no arguments. Values can be published and read by each subscriber.

 
var ps = PubSub.new(); 
[00000000] PubSub_0x28c1bc0  

21.53.3 Slots

21.54 PubSub.Subscriber

Subscriber is created by PubSub.subscribe. It provides methods to access to the list of values published by PubSub instances.

21.54.1 Prototypes

21.54.2 Construction

A PubSub.Subscriber can be created with a call to PubSub.subscribe. This way of creating a Subscriber adds the subscriber as a watcher of values published on the instance of PubSub.

 
var ps = PubSub.new() |; 
var sub = ps.subscribe(); 
[00000000] Subscriber_0x28607c0  

21.54.3 Slots

21.55 RangeIterable

This object is meant to be used as a prototype for objects that support an asList method, to use range-based for loops (Listing 20.7.6).

21.55.1 Prototypes

21.55.2 Slots

21.56 Regexp

A Regexp is an object which allow you to match strings with a regular expression.

21.56.1 Prototypes

21.56.2 Construction

A Regexp is created from a regular expression once and for all; it can be used several times to match with other strings.

 
Regexp.new("."); 
[00000001] Regexp(".") 
 
var num = Regexp.new("\\d+\\.\\d+"); 
[00000004] Regexp("\\d+\\.\\d+") 
"1.3" in num; 
[00019618] true 
"1." in num; 
[00023113] false  

urbiscript supports Perl regular expressions, see the perlre man page.

Expressions cannot be empty, and must be syntactically correct.

 
Regexp.new(""); 
[00000001:error] !!! new: invalid regular expression: empty expression: ‘’ 
 
Regexp.new("("); 
[00003237:error] !!! new: invalid regular expression:\ 
 unmatched marking parenthesis ( or \(: ‘(>>>HERE>>>’ 
 
Regexp.new("*"); 
[00004372:error] !!! new: invalid regular expression:\ 
 the repeat operator "*" cannot start a regular expression: ‘>>>HERE>>>*’  

21.56.3 Slots

21.57 Semaphore

Semaphore are useful to limit the number of access to a limited number of resources.

21.57.1 Prototypes

21.57.2 Construction

A Semaphore can be created with as argument the number of processes allowed to enter critical sections at the same time.

 
Semaphore.new(1); 
[00000000] Semaphore_0x8c1e80  

21.57.3 Slots

21.58 Serializables

This object is used to store the set of prototypes that support exchange data between C++ and urbiscript. See also UValueSerializable and Section 25.18.2.

21.58.1 Prototypes

21.58.2 Slots

Nothing specific. Slots should be mapping from “class” name to “class” implementation. See Section 25.18.2.

21.59 Server

A Server can listen to incoming connections. See Socket for an example.

21.59.1 Prototypes

21.59.2 Construction

A Server is constructed with no argument. At creation, a new Server has its own slot connection. This slot is an event that is launched when a connection establishes.

 
var s = Server.new()| 
s.localSlotNames(); 
[00000001] ["connection"]  

21.59.3 Slots

21.60 Singleton

A singleton is a prototype that cannot be cloned. All prototypes derived of Singleton are also singletons.

21.60.1 Prototypes

21.60.2 Construction

To be a singleton, the object must have Singleton as a prototype. The common way to do this is var s = Singleton.new(), but this does not work : s is not a new singleton, it is the Singleton itself since it cannot be cloned. There are two other ways:

 
// Defining a new class and specifying Singleton as a parent. 
class NewSingleton1: Singleton 

  var asString = "NewSingleton1"
}| 
var s1 = NewSingleton1.new(); 
[00000001] NewSingleton1 
assert(s1 === NewSingleton1); 
assert(NewSingleton1 !== Singleton); 
 
// Create a new Object and set its prototype by hand. 
var NewSingleton2 = Object.new()| 
var NewSingleton2.asString = "NewSingleton2"
NewSingleton2.protos = [Singleton]| 
var s2 = NewSingleton2.new(); 
[00000001] NewSingleton2 
assert(s2 === NewSingleton2); 
assert(NewSingleton2 !== Singleton);  

21.60.3 Slots

21.61 Slot

A slot is an intermediate object that embodies the concept of “variable” or “field” in urbiscript. It contains an underlying value, meta-information about this value, and slots to alter the behavior of read and write operations.

21.61.1 Accessing the slot object

Section Section 20.4.1 describes how to access a slot object.

21.61.2 Key features

The contained value returned by default when Object.getSlotValue is called is stored in the value slot.

The changed slot is an Event that is triggered each time the slot is written to.

Setters and getters to modify the slot behaviors can be installed by writing to set, get, oset and oget.

Two slots can be linked together to build dataflows using operator >>

21.61.3 Split mode

It can sometimes be convenient to store two values in one slot, one which is read, and the other written. For instance, the val slot of a rotational motor Object can be the current motor position when reading, and a target position to reach when writing.

This behavior is controlled by the split slot.

21.61.4 Construction

Slots are automatically created when Object.setSlot is called.

21.61.5 Prototypes

21.61.6 Slots

21.62 Socket

A Socket can manage asynchronous input/output network connections.

21.62.1 Example

The following example demonstrates how both the Server and Socket object work.

This simple example will establish a dialog between server and client. The following object, Dialog, contains the script of this exchange. It is put into Global so that both the server and client can read it. Dialog.reply(var s) returns the reply to a message s.

 
class Dialog 

  var lines = 
  [ 
    "Hi!"
    "Hey!"
    "Hey you doin’?"
    "Whazaaa!"
    "See ya."
  ]|; 
 
  function reply(var s) 
  { 
    for (var i: lines.size - 1) 
      if (s == lines[i]) 
        return lines[i + 1]; 
    "off"
  } 
}|; 
// Import lobby so that Dialog is visible from everywhere. 
import this.*;  

The server, an instance of Server, expects incoming connections, notified by Server.connection event. Once the connection establish, it listens to the socket for incoming messages, notified by the received event. Its reaction to this event is to send the following line of the dialog. At the end of the dialog, the socket is disconnected.

 
var server = 
  do (Server.new()) 
  { 
    at (connection?(var socket)) 
      at (socket.received?(var data)) 
      { 
        var reply = Dialog.reply(data); 
        echo("server: " + reply); 
        socket.write(reply)| 
        if (reply == "off"
          socket.disconnect() 
      }; 
  }|;  

The client, an instance of Socket expects incoming messages, notified by the received event. Its reaction is to send the following line of the dialog.

 
var client = 
  do (Socket.new()) 
  { 
    at (received?(var data)) 
    { 
      var reply = Dialog.reply(data); 
      echo("client: " + reply); 
      write(reply); 
    }; 
  }|;  

The server is then activated, listening to incoming connections on a port that will be chosen by the system among the free ones.

 
server.listen("localhost""0"); 
clog << "connecting to %s:%s" % [server.host, server.port];  

The client connects to the server, and initiates the dialog.

 
client.connect(server.host, server.port); 
echo("client: " + Dialog.lines[0]); 
client.write(Dialog.lines[0]); 
[00000003] *** client: Hi!  

Because this dialog is asynchronous, the easiest way to wait for the dialog to finish is to wait for the disconnected event.

 
waituntil(client.disconnected?) | echo("done"); 
[00000004] *** server: Hey! 
[00000005] *** client: Hey you doin’? 
[00000006] *** server: Whazaaa! 
[00000007] *** client: See ya. 
[00000008] *** server: off 
[00000008] *** done  

There is a catch though: the last message was still being processed by the system, and arrived after we waited for the client is to be disconnected:

 
sleep(100ms); 
[00000009] *** client: off  

This is because both the last message sent from the server, and the disconnection request have arrived at the same “instant” to the client. Both are processed asynchronously, in particular the message reception since the code used an asynchronous at (Listing 20.11.1.3). In the case of asynchronous event handling, this is no guarantee on the order of event processing. This can be addressed by synchronous event processing on the client side; pay extra attention to the sync qualifier passed to at:

 
var syncClient = 
  do (Socket.new()) 
  { 
    at sync (received?(var data)) 
    { 
      var reply = Dialog.reply(data); 
      write(reply); 
      echo("syncClient: " + reply); 
    }; 
  }|; 
 
syncClient.connect(server.host, server.port); 
echo("syncClient: " + Dialog.lines[0]); 
syncClient.write(Dialog.lines[0]); 
[00000003] *** syncClient: Hi! 
waituntil(syncClient.disconnected?) | echo("done"); 
[00000004] *** server: Hey! 
[00000005] *** syncClient: Hey you doin’? 
[00000006] *** server: Whazaaa! 
[00000007] *** syncClient: See ya. 
[00000008] *** server: off 
[00000008] *** syncClient: off 
[00000008] *** done  

This time, as one would expect at first, the *** done appears after the full dialog was performed.

21.62.2 Prototypes

21.62.3 Construction

A Socket is constructed with no argument. At creation, a new Socket has four own slots: connected, disconnected, error and received.

 
var s = Socket.new()|;  

21.62.4 Slots

21.63 StackFrame

This class is meant to record backtrace (see Exception.backtrace) information.

For convenience, all snippets of code are supposed to be run after these function definitions. In this code, the getStackFrame function is used to get the first StackFrame of an exception backtrace. Backtrace of Exception are filled with StackFrames when the is thrown.

 
//#push 1 "foo.u" 
function inner () { throw Exception.new("test") }|; 
 
function getStackFrame() 

  try 
  { 
    inner() 
  } 
  catch(var e) 
  { 
    e.backtrace[0] 
  }; 
}|; 
//pop  

This feature is experimental. It might be changed in the future. Feedback on its use would be appreciated.

21.63.1 Prototypes

21.63.2 Construction

StackFrame are not made to be manually constructed. The initialization function expect 2 arguments, which are the name of the called function and the Location from which it has been called.

 
StackFrame.new("inner"
  Location.new( 
    Position.new("foo.u", 7, 5), 
    Position.new("foo.u", 7, 10) 
  ) 
); 
[00000001] foo.u:7.5-9: inner  

21.63.3 Slots

21.64 Stream

This is used to factor code between InputStream and OutputStream.

21.64.1 Prototypes

21.64.2 Construction

Streams are not meant to be built, rather, use InputStream or OutputStream.

When a stream (OutputStream or InputStream) is opened on a File, that File cannot be removed. On Unix systems, this is handled gracefully (the references to the file are removed, but the content is still there for the streams that were already bound to this file); so in practice, the File appears to be removable. On Windows, the File cannot be removed at all. Therefore, do not forget to close the streams you opened.

21.64.3 Slots

21.65 String

A string is a sequence of characters.

21.65.1 Prototypes

21.65.2 Construction

Fresh Strings can easily be built using the literal syntax. Several escaping sequences (the traditional ones and urbiscript specific ones) allow to insert special characters. Consecutive string literals are merged together. See Section 20.1.6.6 for details and examples.

A null String can also be obtained with String.new.

 
String.new() == ""
String == ""
"123".new() == "123";  

21.65.3 Slots

21.66 Subscription

Connection between InputPorts, see Section 25.7.

21.66.1 Prototypes

21.66.2 Construction

21.66.3 Slots

21.67 System

Details on the architecture the Urbi server runs on.

21.67.1 Prototypes

21.67.2 Slots

21.68 System.PackageInfo

Information about Urbi SDK and its components.

21.68.1 Prototypes

21.68.2 Slots

21.69 System.Platform

A description of the platform (the computer) the server is running on.

21.69.1 Prototypes

21.69.2 Slots

21.70 Tag

A tag is an object meant to label blocks of code in order to control them externally. Tagged code can be frozen, resumed, stopped…See also Section 10.3.

21.70.1 Examples

21.70.1.1 Stop

To stop a tag means to kill all the code currently running that it labels. It does not affect “newcomers”.

 
var t = Tag.new()|; 
var t0 = time|; 
t: every(1s) echo("foo"), 
sleep(2.2s); 
[00000158] *** foo 
[00001159] *** foo 
[00002159] *** foo 
 
t.stop(); 
// Nothing runs. 
sleep(2.2s); 
 
t: every(1s) echo("bar"), 
sleep(2.2s); 
[00000158] *** bar 
[00001159] *** bar 
[00002159] *** bar 
 
t.stop();  

Tag.stop can be used to inject a return value to a tagged expression.

 
var t = Tag.new()|; 
var res; 
detach(res = { t: every(1s) echo("computing") })|; 
sleep(2.2s); 
[00000001] *** computing 
[00000002] *** computing 
[00000003] *** computing 
 
t.stop("result"); 
assert(res == "result");  

21.70.1.2 Block/unblock

To block a tag means:

One can unblock the tag. Contrary to freeze/unfreeze, tagged code does not resume the execution.

 
var ping = Tag.new("ping")|; 
ping: 
  every (1s) 
    echo("ping"), 
assert(!ping.blocked); 
sleep(2.1s); 
[00000000] *** ping 
[00002000] *** ping 
[00002000] *** ping 
 
ping.block(); 
assert(ping.blocked); 
 
ping: 
  every (1s) 
    echo("pong"), 
 
// Neither new nor old code runs. 
ping.unblock(); 
assert(!ping.blocked); 
sleep(2.1s); 
 
// But we can use the tag again. 
ping: 
  every (1s) 
    echo("ping again"), 
sleep(2.1s); 
[00004000] *** ping again 
[00005000] *** ping again 
[00006000] *** ping again  

As with stop, one can force the value of stopped expressions.

 

  var t = Tag.new(); 
  var res = []; 
  for (3) 
    detach(res << {t: sleep()}); 
  t.block("foo"); 
  res; 

== 
["foo""foo""foo"];  

21.70.1.3 Freeze/unfreeze

To freeze a tag means holding the execution of code it labels. This applies to code already being run, and “arriving” pieces of code.

 
var t = Tag.new()|; 
var t0 = time|; 
t: every(1s) echo("time   : %.0f" % (time - t0)), 
sleep(2.2s); 
[00000158] *** time   : 0 
[00001159] *** time   : 1 
[00002159] *** time   : 2 
 
t.freeze(); 
assert(t.frozen); 
t: every(1s) echo("shifted: %.0f" % (shiftedTime - t0)), 
sleep(2.2s); 
// The tag is frozen, nothing is run. 
 
// Unfreeze the tag: suspended code is resumed. 
// Note the difference between "time" and "shiftedTime". 
t.unfreeze(); 
assert(!t.frozen); 
sleep(2.2s); 
[00004559] *** shifted: 2 
[00005361] *** time   : 5 
[00005560] *** shifted: 3 
[00006362] *** time   : 6 
[00006562] *** shifted: 4  

21.70.1.4 Scope tags

Scopes feature a scopeTag, i.e., a tag which will be stopped when the execution reaches the end of the current scope. This is handy to implement cleanups, however the scope was exited from.

 

  var t = scopeTag; 
  t: every(1s) 
      echo("foo"), 
  sleep(2.2s); 
}; 
[00006562] *** foo 
[00006562] *** foo 
[00006562] *** foo 
 

  var t = scopeTag; 
  t: every(1s) 
      echo("bar"), 
  sleep(2.2s); 
  throw 42; 
}; 
[00006562] *** bar 
[00006562] *** bar 
[00006562] *** bar 
[00006562:error] !!! 42 
sleep(2s);  

21.70.1.5 Enter/leave events

Tags provide two events, enter and leave, that trigger whenever flow control enters or leaves tagged statements.

 
var t = Tag.new("t"); 
[00000000] Tag<t> 
 
at (t.enter?) 
  echo("enter"); 
at (t.leave?) 
  echo("leave"); 
 
t: {echo("inside"); 42}; 
[00000000] *** enter 
[00000000] *** inside 
[00000000] *** leave 
[00000000] 42  

This feature provides a concise and safe way to ensure code will be executed upon exiting a chunk of code (like raii in C++ or finally in Java). The exit code will be run no matter what the reason for leaving the block was: natural exit, exceptions, flow control statements like return or break, …

For instance, suppose we want to make sure we turn the gas off when we’re done cooking. Here is the bad way to do it:

 

  function cook() 
  { 
    turnGasOn(); 
    // Cooking code ... 
    turnGasOff(); 
  }| 
 
  enterTheKitchen(); 
  cook(); 
  leaveTheKitchen(); 
};  

This cook function is wrong because there are several situations where we could leave the kitchen with gas still turned on. Consider the following cooking code:

 

  function cook() 
  { 
    turnGasOn(); 
 
    if (mealReady) 
    { 
      echo("The meal is already there, nothing to do!"); 
      // Oops ... 
      return; 
    }; 
 
    for (var i in recipe) 
      if (i in kitchen) 
        putIngredient(i) 
      else 
        // Oops ... 
        throw Exception("missing ingredient: %s" % i); 
 
    // ... 
 
    turnGasOff(); 
  }| 
};  

Here, if the meal was already prepared, or if an ingredient is missing, we will leave the cook function without executing the turnGasOff statement, through the return statement or the exception. One correct way to ensure gas is necessarily turned off is:

 

  function cook() 
  { 
    var withGas = Tag.new("withGas"); 
 
    at (withGas.enter?) 
      turnGasOn(); 
    // Even if exceptions are thrown or return is called, 
    // the gas will be turned off. 
    at (withGas.leave?) 
      turnGasOff(); 
 
    withGas: { 
      // Cooking code... 
    } 
  }| 
};  

If you need your enter/leave functions to be called synchronously and very efficiently, you can as an alternative to enter/leave define the ılocal slots onEnter and onLeave.

 

  function cook() 
  { 
    var withGas = Tag.new("withGas"); 
    var withGas.onEnter = turnGasOn; // copy the function 
    var withGas.onLeave = turnGasOff; 
    withGas : { 
      // Cooking code... 
    }| 
  }| 
};  

The onEnter and onLeave must be local slots, inheritence will not work for them.

Alternatively, the try/finally construct provides an elegant means to achieve the same result (Section 20.8.4).

 

  function cook() 
  { 
    try 
    { 
      turnGasOn(); 
      // Cooking code... 
    } 
    finally 
    { 
      // Even if exceptions are thrown or return is called, 
      // the gas will be turned off. 
      turnGasOff(); 
    } 
  }| 
};  

21.70.1.6 Begin/end

The begin and end methods enable to monitor when code is executed. The following example illustrates the proper use of enter and leave events (Section 21.70.1.5), which are used to implement this feature.

 
var myTag = Tag.new("myTag"); 
[00000000] Tag<myTag> 
 
myTag.begin: echo(1); 
[00000000] *** myTag: begin 
[00000000] *** 1 
 
myTag.end: echo(2); 
[00000000] *** 2 
[00000000] *** myTag: end 
 
myTag.begin.end: echo(3); 
[00000000] *** myTag: begin 
[00000000] *** 3 
[00000000] *** myTag: end  

21.70.2 Hierarchical tags

Tags can be arranged in a parent/child relationship: any operation done on a tag — freezing, stopping, …is also performed on its descendants. Another way to see it is that tagging a piece of code with a child will also tag it with the parent. To create a child Tag, simply clone its parent.

 
var parent = Tag.new() | 
var child = parent.clone() | 
 
// Stopping parent also stops children. 

  parent: {sleep(100ms); echo("parent")}, 
  child:  {sleep(100ms); echo("child")}, 
  parent.stop(); 
  sleep(200ms); 
  echo("end"); 
}; 
[00000001] *** end 
 
// Stopping child has no effect on parent. 

  parent: {sleep(100ms); echo("parent")}, 
  child:  {sleep(100ms); echo("child")}, 
  child.stop(); 
  sleep(200ms); 
  echo("end"); 
}; 
[00000002] *** parent 
[00000003] *** end  

Hierarchical tags are commonly laid out in slots so as to reflect their tag hierarchy.

 
var a = Tag.new(); 
var a.b = a.clone(); 
var a.b.c = a.b.clone(); 
 
a:     foo; // Tagged by a 
a.b:   bar; // Tagged by a and b 
a.b.c: baz; // Tagged by a, b and c  

21.70.3 Prototypes

21.70.4 Construction

As any object, tags are created using new to create derivatives of the Tag object. The name is optional, it makes easier to display a tag and remember what it is.

 
// Anonymous tag. 
var t1 = Tag.new(); 
[00000001] Tag<tag_77> 
 
// Named tag. 
var t2 = Tag.new("cool name"); 
[00000001] Tag<cool name>  

21.70.5 Slots

21.71 Timeout

Timeout objects can be used as Tags to execute some code in limited time. See also the timeout construct (Listing 20.10.7).

21.71.1 Examples

Use it as a tag:

 
var t = Timeout.new(300ms); 
[00000000] Timeout_0x133ec0 
t:{ 
  echo("This will be displayed."); 
  sleep(500ms); 
  echo("This will not."); 
}; 
[00000000] *** This will be displayed. 
[00000007:error] !!! new: Timeout_0x133ec0 has timed out. 
[00000007:error] !!!    called from: ---- event handler backtrace: 
[00000007:error] !!!    called from: new  

The same Timeout, t can be reused. It is armed again each time it is used to tag some code.

 
t: { echo("Open"); sleep(1s); echo("Close"); }; 
[00000007] *** Open 
[00000007:error] !!! new: Timeout_0x133ec0 has timed out. 
[00000007:error] !!!    called from: ---- event handler backtrace: 
[00000007:error] !!!    called from: new 
 
t: { echo("Open"); sleep(1s); echo("Close"); }; 
[00000007] *** Open 
[00000007:error] !!! new: Timeout_0x133ec0 has timed out. 
[00000007:error] !!!    called from: ---- event handler backtrace: 
[00000007:error] !!!    called from: new  

Even if exceptions have been disabled, you can check whether the count-down expired with timedOut.

 
t:sleep(500ms); 
[00000007:error] !!! new: Timeout_0x133ec0 has timed out. 
[00000007:error] !!!    called from: ---- event handler backtrace: 
[00000007:error] !!!    called from: new 
 
if (t.timedOut) 
  echo("The Timeout expired."); 
[00000000] *** The Timeout expired.  

21.71.2 Prototypes

21.71.3 Construction

At construction, a Timeout takes a duration, and a Boolean stating whether an exception should be thrown on timeout (by default, it does).

 
Timeout.new(300ms); 
[00000000] Timeout_0x953c1e0 
Timeout.new(300ms, false); 
[00000000] Timeout_0x953c1e8  

21.71.4 Slots

21.72 Traceable

Objects that have a concept of backtrace.

This object, made to serve as prototype, provides a definition of backtrace which can be filtered based on the desired level of verbosity.

This prototype is not made to be constructed.

21.72.1 Prototypes

21.72.2 Slots

21.73 TrajectoryGenerator

The trajectory generators change the value of a given variable from an initial value to a target value. They can be open-loop, i.e., the intermediate values depend only on the initial and/or target value of the variable; or closed-loop, i.e., the intermediate values also depend on the current value value of the variable.

Open-loop trajectories are insensitive to changes made elsewhere to the variable. Closed-loop trajectories are sensitive to changes made elsewhere to the variable — for instance when the human physically changes the position of a robot’s motor.

Trajectory generators are not made to be used directly, rather use the “continuous assignment” syntax (Section 20.12).

21.73.1 Examples

21.73.1.1 Accel

The Accel trajectory reaches a target value at a fixed acceleration (accel attribute).

 
var y = 0; 
y = 50 accel:10,
PICT

21.73.1.2 Cos

The Cos trajectory implements a cosine around the target value, given an amplitude (ampli attribute) and period (cos attribute).

This trajectory is not “smooth”: the initial value of the variable is not taken into account.

 
var y = 0; 
y = 0 cos:2s ampli:10,
PICT

21.73.1.3 Sin

The Sin trajectory implements a sine around the target value, given an amplitude (ampli attribute) and period (sin attribute).

This trajectory is not “smooth”: the initial value of the variable is not taken into account.

 
var y = 0; 
y = 0 sin:2s ampli:10,
PICT

21.73.1.4 Smooth

The Smooth trajectory implements a sigmoid. It changes the variable from its current value to the target value “smoothly” in a given amount of time (smooth attribute).

 
var y = 0; 

  sleep(0.5s); 
  y = 100 smooth:3s, 
},
PICT

21.73.1.5 Speed

The Speed trajectory changes the value of the variable from its current value to the target value at a fixed speed (the speed attribute).

 
var y = 0; 
assign: y = 20 speed: 5, 

  sleep(1s); 
  y = 10; 
  sleep(1s); 
  y = 4; 
},
PICT

If the adaptive attribute is set to true, then the duration of the trajectory is constantly reevaluated.

 
var y = 0; 
assign: y = 20 speed: 5 adaptive: true, 

  sleep(1s); 
  y = 10; 
  sleep(1s); 
  y = 4; 
},
PICT

21.73.1.6 Time

The Time trajectory changes the value of the variable from its current value to the target value within a given duration (the time attribute).

 
var y = 0; 
assign: y = 20 time:3s, 

  sleep(2s); 
  y = 30; 
},
PICT

If the adaptive attribute is set to true, then the duration of the trajectory is constantly reevaluated.

 
var y = 0; 
assign: y = 20 time:3s adaptive: true, 

  sleep(2s); 
  y = 30; 
},
PICT

21.73.1.7 Trajectories and Tags

Trajectories can be managed using Tags. Stopping or blocking a tag that manages a trajectory kill the trajectory.

 
var y = 0; 
assign: y = 0 cos:2s ampli:10, 

  sleep(1.5s); 
  assign.stop; 
},
PICT
 
var y = 0; 
assign: y = 0 cos:2s ampli:10, 

  sleep(1.5s); 
  assign.block; 
  sleep(1s); 
  assign.unblock; 
},
PICT

When a trajectory is frozen, its local time is frozen too, the movement proceeds from where it was rather than from where it would have been had it been not frozen.

 
var y = 0; 
assign: y = 0 cos:2s ampli:10, 

  sleep(1.5s); 
  assign.freeze; 
  sleep(1s); 
  assign.unfreeze; 
},
PICT

21.73.2 Prototypes

21.73.3 Construction

You are not expected to construct trajectory generators by hand, using modifiers is the recommended way to construct trajectories. See Section 20.12 for details about trajectories, and see Section 21.73.1 for an extensive set of examples.

21.73.4 Slots

21.74 Triplet

A triplet (or triple) is a container storing three objects.

21.74.1 Prototypes

21.74.2 Construction

A Triplet is constructed with three arguments.

 
Triplet.new(1, 2, 3); 
[00000001] (1, 2, 3) 
 
Triplet.new(1, 2); 
[00000003:error] !!! new: expected 3 arguments, given 2 
 
Triplet.new(1, 2, 3, 4); 
[00000003:error] !!! new: expected 3 arguments, given 4  

21.74.3 Slots

21.75 Tuple

A tuple is a container storing a fixed number of objects. Examples include Pair and Triplet.

21.75.1 Prototypes

21.75.2 Construction

The Tuple object is not meant to be instantiated, its main purpose is to share code for its descendants, such as Pair. Yet it accepts its members as a list.

 
var t = Tuple.new([1, 2, 3]); 
[00000000] (1, 2, 3)  

The output generated for a Tuple can also be used to create a Tuple. Expressions are put inside parentheses and separated by commas. One extra comma is allowed after the last element. To avoid confusion between a 1 member Tuple and a parenthesized expression, the extra comma must be added. Tuple with no expressions are also accepted.

 
// not a Tuple 
(1); 
[00000000] 1 
 
// Tuples 
(); 
[00000000] () 
(1,); 
[00000000] (1,) 
(1, 2); 
[00000000] (1, 2) 
(1, 2, 3, 4,); 
[00000000] (1, 2, 3, 4)  

21.75.3 Slots

21.76 UObject

UObject is used by the UObject API (see Listing IV) to represent a bound C++ instance.

All the UObjects are copied under a unique name as slots of Global.uobjects.

21.76.1 Prototypes

21.76.2 Slots

21.77 uobjects

This object serves only to store the UObjects that are bound into the system (plug or remote).

21.77.1 Prototypes

21.77.2 Slots

21.78 UValue

The UValue object is used internally by the UObject API and is mostly hidden from the user. Do not depend on it.

21.78.1 Prototypes

21.78.2 Slots

21.79 UValueSerializable

This pseudo-class is made to be derived from. It provides support to exchange data between C++ and urbiscript via uvalueSerialize. See Section 25.18.2.

21.79.1 Example

For the conversion to/from C++ to work properly, your class must be globally accessible and inherit from UValueSerializable.

 
class Point: UValueSerializable 

  var x = 0; 
  var y = 0; 
 
  function init(var xx = 0, var yy = 0) 
  { 
    x = xx| 
    y = yy 
  }; 
 
  function asString() 
  { 
    "<%s, %s>" % [x, y] 
  }; 
}|;  

21.79.2 Prototypes

21.79.3 Slots

21.80 Vector

21.80.1 Prototypes

21.80.2 Construction

The Vector constructor can be either be given a single List (of Floats), or any number of Floats.

Vector can be constructed by using either Vector.new, or the literal syntax < >. However only a subset of the possible expressions are acceted inside this syntax: boolean operators are not allowed.

 
Vector; 
[00000140] <> 
 
Vector.new(); 
[00000146] <> 
 
Vector.new(1.1); 
[00000147] <1.1> 
 
Vector.new(1.1, 2.2, 3.3); 
[00000155] <1.1, 2.2, 3.3> 
 
Vector.new("123"); 
[00000174:error] !!! unexpected "123", expected a Float 
 
Vector.new([]); 
[00000187] <> 
 
Vector.new([1, 2, 3, 4, 5]); 
[00000189] <1, 2, 3, 4, 5> 
 
Vector.new(["123"]); 
[00000193:error] !!! unexpected "123", expected a Float 
 
<1, 1>; 
[00000147] <1, 1> 
 
var x = 1|; 
<1+1, x+2>; 
[00000000] <2, 3>  

21.80.3 Slots

21.81 void

The special entity void is an object used to denote “no value”. It has no prototype and cannot be used as a value. In contrast with nil, which is a valid object, void denotes a value one is not allowed to read.

21.81.1 Prototypes

None.

21.81.2 Construction

void is the value returned by constructs that return no value.

 
void.isVoid; 
{}.isVoid; 
{if (false) 123}.isVoid;  

21.81.3 Slots