© Copyright 2000 Handwave Inc. All Rights Reserved.
HandScript Language Specification
1. Introduction
HandScript is a simple scripting language for handheld computers based on Javascript.
HandScript is designed to be usable in small pieces, so a single expression or statement
is a valid program. HandScript can explicitly represent user data, facilitating
creation of databases. HandScript is limited to a small number of built-in
features, making it easy to master. HandScript is extensible in HandScript and in C.
2. Comparison to Javascript and WMLScript
HandScript is derived from Javascript and
WMLScript (WAP [Wireless Access Protocol] Markup Language Script).
Loosely speaking it is "between" those languages: a subset of Javascript
and a superset of WMLScript. However, in the ability to directly represent
data it surpasses both Javascript and WMLScript.
A Subset of Javascript
HandScript is Javascript without objects. It is a language of functions and
libraries of functions. Its types are number, string and array. Numbers include
integers and floating point. Arrays are generalized to allow floating point
and string indexes. Strings are indexable with integers.
A Superset of WMLScript
HandScript is WMLScript plus arrays and the ability to subscript strings.
HandScript includes WMLScript "invalid" type. HandScript uses 64-bit floating
point, whereas WMLScript specifies 32-bit floating point. HandScript, like
WMLScript, supports libraries of functions.
3. Types
HandScript values are one of four types: number, string, array and invalid.
Numbers use 64-bit floating-point representation. Strings are sequences
of 8-bit Ascii values. Arrays are containers for values of any type.
The keyword invalid identifies a unique value whose type is not number, string or array.
HandScript is a "dynamically typed" language. That means that variables do
not have a fixed type associated with them, but instead are capable of containing
values of any type. The same variable can contain values of different types
at different times.
4. Statements
HandScript contains most of the familiar statements of C, Javascript and Java.
(See section 12 for the precise syntax specification of all HandScript statements).
HandScript includes assignment, if, for, while, do,
continue, break, return and var statements.
Example Statements:
var a = 5, b = a+2; //variables can be declared before use
c = b*6.2; //but they need not be declared
if (a+1>b) a--; //if statement
else a++; //with optional else
for (i=0; i<10; i++){ //for statement, 3-part form
a[i] = 0;
}
for (i in a) { //for statement, 1-part form
a[i] = 0;
}
while (i>=0) a[i] = b[i--]; //while statement
do { //do statement
a[i] *= 2;
if (a[i]>limit)
break; //break statement
i += 3;
} while (i<#a);
5. Functions
Functions are used to extend the HandScript language.
The Javascript syntax for function declarations is used. For example:
function factorial(n){
if (n<2) return 1;
return n*factorial(n-1);
}
This is a function with name factorial and formal parameter n.
It calls itself recursively to compute its result.
6. Libraries
Libraries contain groups of related functions. The library that contains a
function is identified in the function name. A function name consists of
either a single identifier, or two identifiers separated by a period. For
example factorial and math.sqrt. When there are two
identifiers in a name, the first identifier defines the library to which the
function belongs. A single identifier name may be thought to
belong to the unnamed library. For the two example function names,
factorial belongs to the unnamed library and math.sqrt
belongs to the math library.
Libraries are a form of name space control. They help a programmer
(or multiple programmers) avoid using the same name for two different
purposes. If a library name is unique, then the only potential function
name collisions are within the library. This is a much more manageable
problem than assuring that a name is unique from all other names ever used.
7. Variables
HandScript variables are named containers for values. A HandScript program
dynamically assigns values to variables. Values have a type, either
number, string, array or invalid. At different times a variable may have
different types of values. For example:
a = 15;
if (a>b) a = "bigger";
else if (a<b) a = "smaller";
else a = invalid;
Variables are either local to a function or global to all functions. The value of a
local variable is no longer available when the function defining the variable returns. The
value of a global variable may be shared among multiple functions or separate
invocations of the same function. Local variable names start with a lowercase
letter, whereas global variable names start with an uppercase letter. In the example
below, the global variable Customer contains an array. The function
cust.define saves an association between id and name in the array:
function cust.define(id, name){
Customer[id] = name;
}
Variable names can also specify a library. Such names consist of two identifiers
separated by a period, where the first identifier defines the library to which the
variable belongs, and the case of the first character of the second identifier
determines whether the variable is local or global. As in function names, libraries
provide name space control for variable names. The example above can be
implemented with a library variable cust.Name as follows:
function cust.define(id, name){
cust.Name[id] = name;
}
8. Strings
Strings are sequences of 8-bit Ascii characters. String literals are enclosed in
either single or double quotes (e.g., "sam" or 'joe'). Strings operators support
concatenation, comparison, slicing and subscripting. Examples are:
return "Mr. " + firstName + " " + lastName; //concatenation
if (name=="joe") joeCt++; //equality comparison
s1 = s[0..4]; //slice, a string of first 5 characters
c = s[i]; //subscript, a string of a single character
Strings are immutable, their individual characters cannot be changed. However,
strings can be used to create new strings through subscripting, slicing and concatenation.
9. Arrays
Arrays are containers for associations between indices and values. Indices are
numbers or strings. Values are numbers, strings or arrays.
Array Initializers
Array Initializers are array creation expressions. Examples are:
{} //an empty (0 valid elements) array
{"sam", "joe"} //this is equivalent to the array below
{0:"sam", 1:"joe"} //associate 0 with "sam", 1 with "joe"
{i+j, i-j, 20:i*j, i/j) //these two are equivalent
{0:i+j, 1:i-j, 20:i*j, 2:i/j}
{{i, j}, {i+1, j-1}} //nested arrays
{"first":"al", "last":"dugan", "tels": {"668-2000","776-0123"}}
Array Access
Array contents are accessed via subscripting. In the example below, an empty
array is assigned 10 elements. The array automatically grows as needed to
contain more elements.
a = {};
for (i=0; i<10; i++) a[i] = i*i;
// now, a == {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
Array subscripts can be of type number or string. For example:
if (person["last"]=="dugan") telephones = person["tels"];
Array entries can be removed by assigning invalid. For example:
err = [UInt16 0xA078, UInt8 newSearch, MemPtr state,
UInt32 type, UInt32, creator, UInt8 onlyLatest,
UInt16Ptr &card, UInt32Ptr &dbID];
In this example, the return type is