[Tinyos-commits] CVS: tinyos-1.x/tos/lib/VM/languages/motlle/doc
tinyscheme.txt, NONE, 1.1 motlle.txt, 1.1, 1.2
David Gay
idgay at users.sourceforge.net
Tue Oct 25 17:28:29 PDT 2005
Update of /cvsroot/tinyos/tinyos-1.x/tos/lib/VM/languages/motlle/doc
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv791
Modified Files:
motlle.txt
Added Files:
tinyscheme.txt
Log Message:
unfinished tinyscheme documentation
--- NEW FILE: tinyscheme.txt ---
An Introduction to TinyScheme
=============================
October 2005
0) Preface
==========
TinyScheme is a scripting language for motes built in the Mate
virtual-machine framework. It's basically an implementation of the
Scheme programming language, but with a few significant features
missing (see below for more details).
At this point, if you hate Scheme's syntax but like the concept of a
full-featured scripting language, you might want to check the documentation
for "motlle", which should be available from the same directory/web
page as this document. motlle is essentially TinyScheme with a C-like
syntax; except for a few library routine changes, VMs for motlle and
TinyScheme are identical.
This document assumes you are already familiar with sensor networks and the
Mate framework, but detailed knowledge of TinyOS is not required (you only
need to be able to compile and install existing TinyOS programs).
Compared to TinyScript, TinyScheme supports more advanced data structures
(arrays, lists, etc), but in counterpart it is a little less efficient and
does not support concurrent handler execution.
The classic "Count the LEDs" example in motlle is:
(define i 0) ; declare i
(settimer0 10) ; start timer
(define (timer0) ; timer handler: increment i, set the LEDs
(set! i (+ i 1))
(led (& i 7)))
As this examples shows, TinyScheme uses the standard Mate handlers and
function libraries (in this case, the timer0 handler and settimer0, led
functions)
The current version of TinyScheme only supports the pc (tossim), mica2 and
mica2dot platforms. The PC-side support tools have only been tested on
x86-based machines.
1) Building a TinyScheme VM
===========================
Note: before building a TinyScheme VM, make sure you have configured motlle
by running `make' in motlle's main directory (see INSTALL file).
The examples directory contains a file called scheme.vmsf which defines
a simple TinyScheme VM. We reproduce it here with comments explaining its
contents. Currently, TinyScheme does not support the GUI-based VM builder,
so to create your own VM you must create your own .vmsf file similar
to scheme.vmsf (we suggest using scheme.vmsf as your starting point).
# Declare the VM. You will want to specify a separate name (NAME=)
# and directory (DIR=) for each VM.
<VM NAME="TinySchemeVM" DESC="A basic TinyScheme VM with single-hop communication."
DIR="../../../../../../apps/TinySchemeVM">
# 1024 is the amount of RAM available for TinyScheme programs. You can
# increase while there is RAM available...
<OPTION CAPSULE_SIZE=1024>
# The following lines should always be present (the paths are
# relative to the .vmsf file, so you may need to adjust them
# depending on where your file is)
<SEARCH PATH="../../../opcodes">
<SEARCH PATH="../../../contexts">
<SEARCH PATH="../mate">
<SEARCH PATH="../mate/rep-16">
<SEARCH PATH="../mate/runtime">
<SEARCH PATH="../mate/runtime/sgen">
<SEARCH PATH="../matelib">
<SEARCH PATH="../matelib/sgen">
<SEARCH PATH="../../../../Util">
# Use the TinyScheme language
<LANGUAGE NAME="TinyScheme">
# Load the basic TinyScheme functions
<LOAD FILE="../mate/runtime/sgen/intfns.vmsf">
# Here is where you add VM-specific contexts and functions, either
# from Mate's library (led, id, the mica sensorboard) or from TinyScheme's
# (the commfns.vmsf file, which contains single-hop communication
# primitives)
<FUNCTION NAME="led">
<FUNCTION name="id">
<FUNCTION name="sleep">
<CONTEXT NAME="Timer0">
<LOAD FILE="../../../sensorboards/micasb.vmsf">
<LOAD FILE="../matelib/sgen/commfns.vmsf">
Once you have a .vmsf file, you build a TinyScheme VM by executing the
motllevm-build script found in the tools directory, passing the .vmsf file
as its argument (you will typically need to be in the directory containing
the .vmsf file when doing this). This will generate a VM in the directory
specified by the DIR= directive. You build and install the generated VM
like a usual TinyOS program.
Note that TinyScheme library functions are found in directonies named sgen,
while motlle library functions are found in directonies named gen.
2) Running TinyScheme programs
==============================
The tools/mload utility is used to install TinyScheme programs on motes with
TinyScheme VMs. This utility expects to find the conf.mt file that
motllevm-build generated in the current directory. motllevm-build places
this file in the VM's directory (the one specified by DIR=), so you have
two main choices for how to run mload:
- run it from the VM's directory
- create a symbolic link to conf.mt in the current directory before
executing mload (`ln -s <path to VM dir>/conf.mt').
Using mload is straightforward:
mload <file containing TinyScheme source>: compiles and loads the file
mload -e "<TinyScheme expression>": run a 1-line TinyScheme program
(mload -e "(led 4)") is a good test that your VM is working...)
The examples directory contains two simple TinyScheme applications:
- cnttoleds.ts: seen above
- oscilloscope.ts: a TinyScheme version of the TinyOS OscilloscopeRF
application.
3) TinyScheme vs Scheme
=======================
The major differences between TinyScheme and Scheme are:
- there is no tail-recursion-elimination support
=> don't write recursive loops, especially as motes have no RAM ;-)
use do
- named let, quasiquote and macros are not available
- there is no call-with-current-continuation and no support for delayed
evaluation
- characters and booleans are integers (like in C), rather than separate
types
- all input/output and character and most string procedures are missing
- numbers are integers and, optionally 32-bit floats; the handling of
numbers doesn't quite match the Scheme standard
- equal?, member, assoc are not available
In more detail, and matching the structure of the "Revised^5 Report on
the Algorithmic Language Scheme":
3.2 Disjointness of Types
Character, boolean and port types do not exist.
3.5 Proper tail recursion
-- is not available
4.1.4 Procedures
The <variable> form of arguments is supported, but the <variable> receives
a vector of the arguments.
The (<variable1> ... <variablen> . <variablen+1>) form of arguments is not
supported.
4.1.5 Conditionals
The result of (if <test> <consequent>) is unspecfied even when <consequent>
is evaluated.
4.2.4 Iteration
-- "Named let", i.e., (let <variable> <bindings> <body>), is not available
4.2.5 Delayed evaluation
-- is not available
4.2.6 Quasiquotation
-- is not available
4.3 Macros
-- are not available
5.3 Syntax definitions
-- are not available
6.1 Equivalence predicates
eqv? and eq? behave identically
-- equal? is not available
6.2 Numbers
The numbers available depend on the configuration of the TinyScheme
VM. Choices are 15-bit integers only or 16-bit integers and 32-bit
floating-point numbers. See Section XXX for more details.
Numbers behave mostly like Scheme numbers should. The departures are:
- there is no exact/inexact distinction
- the lexical syntax for numbers is that of C, except that the #b, #o, #d
and #x radix specifiers are supported
- floating-point numbers that are integers can not be used where integers
are expected
- =, <, >, <= and >= only accept two arguments (and = is actually eqv?)
- the optional more-than-2-arguments form of - and / are not available
- round, numerator, denominator, rationalize, gcd, lcm are not available
- numerical input and output is not available
- expt is only available with a floating-point VM
6.3.1 Booleans
Booleans are handled as in C -- 0 is false, everything else is true. #t is
the same as 1 and #f is the same as 0. The boolean? procedure does not exist.
6.3.2 Pairs and lists
c[ad]*r are only available up to three a+d's (i.e., the four car/cdr forms
are absent).
-- member and assoc are not available
6.3.3 Symbols
-- symbol->string and string->symbol are not available
6.3.4 Characters
Characters are integers, as in C. For instance, #\a is 97. None of the
character procedures are available.
6.3.5 Strings
The string lexical syntax is that of C.
-- the string comparison and substring functions are not available
6.4 Control features
apply is changed to
(apply proc vector)
Calls proc with the values in vector as the actual arguments.
-- force, call-with-current-continuation, values, call-with-values,
dynamic-wind are not available
6.5 Eval
-- eval and its related functions are not available
6.6 Input and output
-- Scheme's I/O functions are not available. See the description of the
motlle/TinyScheme communication library below.
7.1.1 Lexical structure
The lexical changes from Scheme (already mentioned above) are:
- strings follow the C syntax
- numbers follow C syntax, except that the #b, #o, #d and #x radix
specifiers are supported
Additional features
-------------------
Bitwise operations are supported:
(| n1 ...): bit-wise or of its integer arguments
(& n1 ...): bit-wise and of its integer arguments
(^ n1 ...): bit-wise xor of its integer arguments
Some vector, string and list operations are unified:
(any-ref x n): applies to vectors, lists, strings
(any-set! x1 n x2): applies to vectors, lists (sets the n-1th car), strings
map, for-each, length, reverse and append's arguments can be lists,
vectors or strings
A few miscellaneous functions are also available:
error: i -> . Causes error i
garbage_collect: -> . Does a garbage collection
4) Mote library
===============
As mentioned above, TinyScheme can use standard Mate librarires such as sensor
access. It also currently comes with its own set of mote-specific functions
(some of these will be merged with the standard Mate libraries in future
releases). The only documented library at this point is the communications
library.
This description
includes a function signature of the form "X1 X2 X3 ... -> Y.",
where the Xi's describe the number and type of arguments, and Y
the type of the result, using the following conventions:
x, y, x1, y1, x2, y2, ... : a value of any type
n, n1, n2, ... : a number (int or float)
i, i1, i2, ... : an integer
r, r1, r2, ... : a float (real number)
b, b1, b2, ... : a boolean value (0 = FALSE, everything else = TRUE)
s, s1, s2, ... : a string
fn, fn1, ... : a function (or closure as it is sometimes known)
l, l1, l2, ... : a list
v, v1, v2, ... : a vector
If Y is absent, the function has no (useful) result.
4.1 Using Mate libraries
------------------------
To use a Mate function or context, you can just include it in your .vmsf
file with
<FUNCTION NAME=...>
and
<CONTEXT NAME=...>
At this point, only functions take integer arguments, and those returning
integer or sensor values will work with TinyScheme (in particular, functions
relating to Mate buffers cannot be used).
4.2 Communication functions
---------------------------
To include the communications library in a VM, add
<LOAD FILE="../matelib/sgen/commfns.vmsf">
to your .vmsf file (base.vmsf already contains this library).
This library supports single-hop, broadcast and serial port communication.
It includes three functions and one context:
send: i s -> b. Send packet s to address i, returning success/failure.
if i is uart_addr, sends to the serial port
if i is bcast_addr, broadcasts the message
encode: v -> s. Encode a vector as a string. Produces a string which
is the concatenation of the elements of v, each encoded as follows:
i: encode as 2 little-endian bytes
f: encode as 4-byte float
s: encode n-char string as n identical bytes
i . x: encode x as usual, pad (w/ 0s) or truncate to n bytes
ignored for floats (always encoded as 4 bytes)
decode: s v -> v. Decode string s into v, based on the decoding rules
specified in v. Elements of v should be:
i: 1->1-byte unsigned, 2->2-byte unsigned,
-1->1-byte signed, -2->2-byte signed
f: decode a 4-byte float
s2: overwrite s2 with chars from s
The context is called receive, and is executed when a message sent via
'send' from another mote is received. To access the message, you use the
received_msg: -> s. Return received message
function.
The messages sent and received by this library use active message id 42.
For example, in the oscillosope application, mote 0 forwards all received
messages to the serial port:
any receive() {
if (id() == 0)
send(uart_addr, received_msg());
}
Messages are typically sent using encode:
// send a 4-byte message with the values of x and y
send(bcast_addr, encode(vector(x, y)));
This message could be decoded like this:
any receive() {
any decoded = decode(received_msg(), vector(2, 2));
// decoded[0] is now the x value sent, and decode[1] the y value
}
The oscilloscope.mt example contains a more complex use:
any readings = make_vector(10);
...
send(bcast_addr, encode(vector(id(), current, 0, encode(readings))));
This creates a 26 byte message whose format is:
bytes 0, 1: the sender's node id
bytes 2, 3: the value of current
bytes 4, 5: 0
bytes 6-25: the 10 elements of readings, encoded with 2 bytes per number
This is the format expected by the net.tinyos.oscope.oscilloscope application.
XXX vmsf configuration
The default scheme.vmsf configuration given above has 15-bit integers only.
If you replace
<SEARCH PATH="../mate/rep-16">
by
<SEARCH PATH="../mate/rep-float">
and
<LOAD FILE="../mate/runtime/gen/intfns.vmsf">
by
<LOAD FILE="../mate/runtime/gen/floatfns.vmsf">
in your .vmsf file, you get 16-bit integers and 32-bit floating-point
numbers.
Note that / (real division) is only available if you have a floating-point
VM. If you use rep-16, you get quotient (integer division) but not /.
Index: motlle.txt
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/tos/lib/VM/languages/motlle/doc/motlle.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** motlle.txt 11 Dec 2004 01:42:23 -0000 1.1
--- motlle.txt 26 Oct 2005 00:28:27 -0000 1.2
***************
*** 20,27 ****
and does not support concurrent handler execution.
The classic "Count the LEDs" example in motlle is:
any i = 0; // declare i
settimer0(10); // start timer
! any timer0() { // timer handler: increment i, set the LEDs
led(++i & 7);
}
--- 20,34 ----
and does not support concurrent handler execution.
+ If you don't want to learn a new language, you might want to check the
+ documentation for TinyScheme, which should be available from the same
+ directory/web page as this document. TinyScheme is an implementation of the
+ Scheme programming language, with a missing features. Except for a few
+ library routine changes, VMs for motlle and TinyScheme are identical.
+
The classic "Count the LEDs" example in motlle is:
any i = 0; // declare i
settimer0(10); // start timer
! any timer0() // timer handler: increment i, set the LEDs
! {
led(++i & 7);
}
***************
*** 90,93 ****
--- 97,103 ----
VM like a usual TinyOS program.
+ Note that motlle library functions are found in directonies named gen,
+ while TinyScheme library functions are found in directonies named sgen.
+
2) Running MOTLLE programs
==========================
More information about the Tinyos-commits
mailing list