The Ruri Reference Manual Copyright 2000 Tom Rothamel Distribution with or without modification is permitted provided copyright notice is maintained. Version 1.0 http://onegeek.org/~tom/software/ruri/ Variable Terminal Tokens This is an identifier name. It can begin with a letter or underscore, and can contain any other letter or number. This is a number. It can be a normal decimal number, positive or negative, like 42 or -121178. It can also be a hexadecimal number prefixed with "0x", like 0x5a or 0x42DE. Lastly, it can be a character constant between single quotes, like 'a', '0' or 'Z'. (The escapes '\n', '\t', and '\f' also happen to be recognized.) This a string that's enclosed in double quotes. The escapes listed above are recognized. Comments Anywhere in the code, a C++-style comment can be used. These are completely ignored. Basic Program Structure The first thing in a ruri program is a list of constants. These constant definitions look something like: const = ; The number can range within the values representable by the 32 bit word size of IJVM. There can be as many constant definitions as needed, but they must all appear before the definition of the main method. This is followed by a main method. The main method has a method body, and looks vaguely like this: main { // Method body } After the main method, one or more additional methods can be declared. Additional methods take a comma separated list of parameters, each of which looks like "word ". The parameter list can be empty, although older versions of ijvmasm generate bad code in that case. Anyway, a method that takes two arguments looks something like: method (word , word ) { // Method body } In both cases, the method body begins with zero or more variable definitions. These take the form: word ; They must appear in the method body before any statements. There's no way to initialize a variable apart from simply assigning to it. Statements An expression can be used as a statement. The value of it is ignored. ; The out statement considers its value to be an ascii character, and sends it to standard output. out ; The push statement leaves the value of the expression on the stack. push ; The return statement causes this method to return the value of the expression. return ; The break statement terminates a for or while loop. break ; The continue statement continues a for or while loop. continue ; Braces are used to declare a block of instructions, useful in conjunction with the various conditional and loop statements. { } In an if statement, if the condition is true, the statement will be executed. if ( ) In an if/else statement, if the condition is true, the first statement is executed, otherwise the second one is. if ( ) else In a while statement, the statement is executed so long as the condition given is true. (Just to clarify, the condition is evaluated before each execution of the statement.) while ( ) In a for statement, the first expression is always executed. After that, as long as the condition remains true, the statement is executed, followed by the second expression. for ( ; ; ) The halt statement causes the virtual machine to halt execution of the code. halt ; The err statement causes the virtual machine to halt execution and return an error. err ; This causes the string to be included verbatim in the generated assembly code. asm ; The out statement causes numerous OUT commands to be generated, resulting in the string being sent to standard output. out ; The goto statement causes control to be transfered to the statement following the label named by the name. goto ; The following syntax is used to declare a label. It can only be used in a list of statements, and more specifically can't be used as a statement as part of one of the conditional or branching statements. ':' Expressions Expressions return values that can be used by ruri statements and conditions. Here they are, from highest to lowest precedence. expr2: All of these request data from memory or the instruction stream. ( ) The value of a lower precedence expression. ~ A boolean not of the expression. The value of the variable with name. const The value of the constant with name. A number between 0 and 255. () The return value of the method with the given name called with the given arguments. (Be sure the number of arguments matches... ruri doesn't check.) in A character read from stdin. [] The value of an element in an array. (This causes ruri to generate IJVMA instructions.) alloca() Allocates an array of expr bytes on the stack. It will be deallocated when the current method returns. (This causes ruri to generate IJVMA instructions.) This causes the string to be placed in an array allocaed for it, with the value being the base of the array. It allocates a new array every time the statement is executed. (This cause ruri to generate IJVMA instructions.) expr11: These are the boolean and and or operators. They all take constant time. & Boolean And. | Boolean Not. expr1: These expressions take an equal or higher precedence operation as a first argument, and return the value of a mathematical operation. They take time proportional to the number that is the right hand side. << Shifts the input to the left by number bits. * Multiplies the input by the number. expr0: These are binary operators that take two inputs of equal or higher precedence. + Adds the inputs. - Subtracts the inputs. expr: The lowest precedence expressions, assignments. These take an input on the right, assign it to a location in ram, and return it's value. = Assigns the input to the variable name. [] = Assigns the input to the array member. (This generates IJVMA.) Pop There is one more thing that can be used in conjunction with expressions. That's pop. Pop takes the top word off the stack. It should only be assigned to arrays or variables, and shouldn't be combined in an expression with any other operation. a = pop; // good buf[10] = pop; // good a = pop + b; // Bad! Arrays An array is implemented using a word to store the base of the array, and then by using subscripting to specify an offset from that base. Normally, the base is set using alloca at runtime. a = alloca(10); a[3] = 'T'; out a[3]; // Outputs 'T'. {Post,Pre}{inc,dec}rement Postincrement, Preincrement, Postdecrement, and Predecrement aren't implemented in ruri. Sorry, C fans. Conditions The following are conditions that are recognized in ruri, in approximate order of precedence. true Always true. false Always false. True if expr is non-zero. < less-than. <= less-than or equals-to. == equals-to. != not-equals-to. >= greater-than or equals-to. > greater-than. ! Not-. && And. || Or. Miscellaneous emit can be fed to ruri to cause it to emit the code for the given statement. This is mostly used for debugging purposes. No checking is done on variable, constant, and method names. It's up to the programmer and/or the assembler to catch misuses or undeclared names.