The Chirp Language Specification

Li Xu and Fred Martin
{xu, fredm}@cs.uml.edu
Department of Computer Science
University of Massachusetts Lowell
Lowell, MA 01854, USA

July 2005

1  Introduction

Chirp is a simple C-like language designed for programming educational robots, in particular, the Handy Cricket [1] based embedded robots. The Chirp language exposes the capabilities of the Handy Cricket virtual machine, as discussed by Martin et al [3]. This document describes the language features and specification of Chirp.

Chirp has a syntax similar to C, which allows programmers who are familiar with C/C++ or Java languages to quickly pick it up and start programming the cricket robots. However, as Chirp is designed to support embedded robot control rather than general-purpose computing, the language features of Chirp have been greatly simplified and only include data types and language constructs essential for writing cricket control programs. As a result, Chirp has a small language structure and provides a quick and yet extensible mechanism to develop cricket based robotic applications.

Chirp supports only two basic data types: integer and byte. Integer types are 16-bit numbers and byte types are 8-bit. Boolean values are treated similar to C: 0 represents logical false, and any non-zero values represent logical true. Chirp also supports single dimension arrays of the basic data types. There are no reference types such as pointers in Chirp.

Chirp only supports global variables and formal variables of functions. Functions do not have local variables. This restriction is consistent with the cricket run-time system which has small stacks for function invocation.

Computation in Chirp is realized through expression evaluation. Chirp supports C-like general expressions, in which variable and array references, function calls and constants are used as building blocks to construct more complex expressions, including arithmetic, relational and boolean expressions. Expression values are used in Chirp control statements.

Chirp supports a set of simplified control constructs. Allowable statements are assignments to global variables, if-else conditional statements, unconditional loops, loops with a calculated loop count and return statement to return from functions.

Chirp supports control abstraction through functions. Chirp functions are similar to C functions, which can take formal arguments, return a result or have void return type. The function body is a sequence of Chirp statements. Like C, the function with name “main” and void return type is designated as the entry point of Chirp programs. Each Chirp program must have a “main” program with the specified type signature.

To support robotic control interface, Chirp provides a special construct “interface”. An interface aggregates related I/O functions within a single namespace. The language run-time provides built-in interfaces, including System, System.Motor, System.Sensor, System.Bus, etc, which user can use directly in Chirp programs. User can also define new interfaces using the interface construct.

Another special construct of Chirp is “trigger”, which allows user to define a second thread of control in addition to the main control flow. Cricket robots allow user to define two threads of control flow: one foreground thread is the main control flow running on the processor, and the other is a background thread (“trigger” thread) which specifies a condition and an execution block. The processor will check the condition and if it is satisfied, the execution block will run in the trigger thread. The trigger construct allows user to specify the condition and execution block in Chirp. User can use the with statement to attach a trigger to a loop construct in the Chirp program.

Figure 1 shows an example Chirp program, which will repeatedly turn on and off the cricket A and B motor and check the A sensor reading in the background. If the sensor reading is above the threshold 10, the cricket will make a beep.


//Comment: example chirp program for motor and sensor control

trigger SensorChecker {
   (System.Sensor.getA() > 10) : {
        System.Sound.beep();
   }
}
    
void main() {
   loop {
      System.Motor.selectA();
      System.Motor.run();
      System.wait(10);
      System.Motor.stop();
      System.Motor.selectB();
      System.Motor.run();
      System.wait(10);
      System.Motor.stop();
   } with SensorChecker;
}

Figure 1: Example Chirp program

 

2  Chirp Syntax

Chirp is case sensitive, that is, Foo and foo are distinct names. Chirp keywords are reserved – the programmer cannot use a Chirp keyword as the name of a variable. The valid keywords are: int, byte, if, else, with, loop, return, interface, trigger.

The following characters have special meaning in a Chirp program:

{ } ’ < > = + - * / % ! [ ] ( ) . , ; :

The Chirp grammar in Figure 2 provides the usage of the special characters.

Chirp accepts C/C++ style comments: comments are delimited by matching /* and */, or follow // until the end of the line.

Chirp identifiers start with a letter or the underscore character which is then followed by letter, underscore or digit characters. Chirp identifiers are used for variable, array, function, interface and trigger names. Chirp identifiers are defined as follows:

ChirpLettera | b | c | ... | z | A | B | ... | Z | _
Digit0 | 1 | 2 | ... | 9
IDChirpLetter ( ChirpLetter | Digit )*

Chirp constants are integers, which can be in either decimal or hexadecimal form, for example, 999 and 0xff.

Chirp supports the following boolean, relational and arithmetic operators:

The syntax of Chirp is described using the EBNF grammar shown in Figure 2. The terminal tokens are in the typewriter font.


program( declaration )+
declarationvariable_declaration | function_declaration | interface_declaration |
  trigger_declaration
variable_declarationdata_type ID ( = INT )? ; |
  data_type ID [ INT ] ;
data_typeint | byte
function_declarationfunction_type ID ( ( formal ( , formal )* )? ) block
function_typedata_type | void
formaldata_type ID
block{ ( statement )* }
statementassignment_stmt ; | if_else_stmt | loop_stmt | return_stmt ; |
  function_call ; | block
assignment_stmtID ( [ expression ] )? = expression
if_else_stmtif ( expression ) statement ( else statement )?
loop_stmtloop ( ( expression ) )? block ( with ID ;)?
return_stmtreturn ( expression )?
function_callID ( . ID )* ( ( expression ( , expression )* )? )
expression! relational_expr | relational_expr ( ( && | || ) relational_expr )*
relational_expressionarithmetic_expression ( ( == | < | > ) arithmetic_expression )*
arithmetic_expressionterm ( ( + | - ) term )*
termfactor ( ( * | / | % ) factor )*
factorID ( [ expression ] )? | INT | ( expression ) | function_call
interface_declarationinterface ID ( . ID )* { ( function_declaration )+ }
trigger_declarationtrigger ID { ( expression ) : block }
Figure 2: Chirp grammar

 

3  Chirp Specification

3.1  Data Types

Chirp supports two basic data types: int, byte. The int is 16-bit signed integer value, and byte is 8-bit unsigned integer value. Type conversions in Chirp are implicit, that is, the compiler will determine the need of type conversions in expression evaluation if mixed types are used. Type conversions between the int and byte types follow the following rules:

Similar to C, Chirp uses integer types to represent boolean values: 0 represents boolean false and any non-zero value represents boolean true. Chirp allows function return type to be void, indicating there is no return value for the function.

Chirp also supports one-dimension array type with array elements of the basic types.

3.2  Functions and Variables

User can define functions in Chirp similar to C. Functions can have multiple formal arguments of the basic data types and take no or single return value. Chirp supports only global variables and functions don’t have on-stack local variables. This is due to the limited stack size of the cricket embedded processor.

3.3  Assignment Statement

The assignment statement requires that its left-hand side to be a variable or array element and its right-hand side an expression.

3.4  If-Else Statement

The if-else statement evaluates the expression to a boolean value (using the zero/non-zero numeric value as boolean result) and executes the following “then” or “else” branch respectively. The else statement is always bound to the nearest unbound if statement to resolve ambiguity.

3.5  Loop Statement

Chirp does not provide the general-purpose C-style while or for loop. Instead, Chirp provides the simple unconditional and the fixed-iteration count loop constructs. The loop statement will either execute the loop body in repetition, or evaluate the loop count expression and iterate the loop body by the specified loop count.

3.6  Return Statement

The return statement terminates the function and returns the control flow to the caller. For function with non-void return type, function result will be returned to its caller.

3.7  Function Invocation

Chirp functions are invoked by calling the function with the required arguments. Function return values can be used in expression evaluation. For functions defined in Chirp interfaces, function names should be qualified with appropriate interface names.

3.8  Block Statements

Similar to C, Chirp allows user to use curly braces to aggregate statements into code blocks.

3.9  Expressions

Chirp expressions compute values of the basic types. As boolean values are represented by integer values, Chirp defines boolean and, or and not operator to evaluate boolean values. The relational operators are == for equality, < for less-than, and > for greater-than comparison. Chirp also supports common arithmetic operations. Result of non-void function call can also be used in expression evaluation.

3.10  Interfaces

User can use the interface construct to aggregate related I/O interface functions. Chirp interface consists of a list of interface functions. Interface functions can be called through the qualified interface and function names. Chirp interfaces do not have state data.

Chirp provides the following built-in interfaces which users can use directly in their programs.

3.11  Triggers

The cricket robot supports two threads of control: foreground main thread and background trigger thread. Users can specify a boolean condition and the execution code. The cricket will check against the condition when running the main thread. If the condition is true, the processor will switch to run the specified execution code in the second trigger thread. Chirp trigger construct allows user to define this second thread of control flow as a trigger attached to a loop statement. A trigger construct has a condition clause and statement block. If the trigger condition is true, the statement block will be executed in the trigger thread on the cricket. An example use of the trigger construct is shown in Figure 1.

4  Acknowledgments

We would like to thank Kareem Abu Zahra for his help with this work.

References

[1]
Handy Cricket Documentation. http://handyboard.com/cricket/.
[2]
B. W. Kernighan and D. M. Ritchie. The C Programming Language. Prentice Hall, 1988.
[3]
F. Martin, B. Mihkak, and B. Silverman. Metacricket: A designer’s kit for making computational devices. IBM Systems Journal, 39(3), 2000.

This document was translated from LATEX by HEVEA.