Top | Prev | Next
The programming language is made up of one or more statements. A statement can look like one of the following:
// Add 5 to register 0 REG $0 ATR 5 // Print out the value of register 0 on screen ATB $0 PTB
Each statement is made up of instructions, values (strings and integers), objects, commands, and separators. Strings are described by enclosing it with inverted commas (""). You may use \n to insert a carriage return. An integer is a 32 bit decimal value. An instruction is a defined keyword that tells the interpretor to execute a particular set of functions. For instance, ATR substitutes a value into the specified register. Values can be any literal data or registers containing a value. See Registers for more information. Separators are represented by spaces and is used to separate the instruction and values. A statement can also contain comments, represented by double slashes //. Comments will not be interpreted by IRIS and will be deleted during compilation.
// This is a comment // Comments will not be interpreted
An object is represented by a leading underscore (_) and any child objects or commands are separated by a dot(.) . e.g. _gameEngine.initialize
Registers store the byte position of the loaded code in memory (except for numbers - are stored directly in the registers). Registers can be treated like variables with its values changing in real time. It can store string of characters and numeric values (but limited to a 32 bit integer). In IRIS, you can use up to 256 registers (0 -> 255) each represented by a dollar ($) sign in front of the register number (e.g. $23).
IRIS has 2 types of compile-time modifiers that allow you to replace part of the code with something you have defined. "pre_define.h" file contains definitions of a Macro, a syntax similar to the C language. The replacement occurs before any compilation. "post_define.xml" defines a replacement list in XML form and is called when compiling to byte code.
Example:
#define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480
Macro file is read from the top of file until it finds the definition. You will need to arrange the definition orders accordingly.
[Erroneous Definition] // We want to call ID_CHARACTER, but the string ID_CHARACTER exists in the first definition, // so the latter will not be read #define ID_CHARACTER_1 1 #define ID_CHARACTER 0 [Re-ordered Definition] // We want to call ID_CHARACTER, and ID_CHARACTER exists in the first definition, // so the latter will not be read #define ID_CHARACTER 0 #define ID_CHARACTER_1 1
<irisc> <crypt_key>Uly@Encrypt#6X6O8R3__IRISC:07c05p23L</crypt_key> <source_code> <source>//</source><target>%BREAK%//</target> <source>do {</source><target>%BREAK%%INC_AUTO_NUM%@condition_label_%FILE_PATH%_%AUTO_NUM%:</target> <source>} until</source><target>%BREAK%REG</target> <source> loop</source><target>%BREAK%JMP condition_label_%FILE_PATH%_%AUTO_NUM%%DEREF_AUTO_NUM%</target> <source>}</source><target>%BREAK%@condition_label_%FILE_PATH%_%AUTO_NUM%:%DEREF_AUTO_NUM%</target> <source>function </source><target>%INC_AUTO_NUM%JMP condition_label_%FILE_PATH%_%AUTO_NUM%%BREAK%@</target> <source>() {</source><target>:</target> <source>if(</source><target>%BREAK%%INC_AUTO_NUM%REG </target> <source>) {</source><target>%BREAK%JMP condition_label_%FILE_PATH%_%AUTO_NUM%</target> <source>;</source><target>%EMPTY%%BREAK%</target> <source>(</source><target>%SPACE%</target> <source>)</source><target>%EMPTY%</target> <source>print</source><target>PTX</target> <source>++</source><target> SUM 1</target> <source>--</source><target> SBT 1</target> <source>+=</source><target>SUM</target> <source>+</source><target>SUM</target> <source>-=</source><target>SBT</target> <source>-</source><target>SBT</target> <source>==</source><target>SKE</target> <source>/=</source><target>DIV</target> <source>/</source><target>DIV</target> <source>*=</source><target>MLT</target> <source>*</source><target>MLT</target> <source>></source><target>SKL</target> <source><</source><target>SKG</target> <source>!=</source><target>SKN</target> <source>=</source><target>ATR</target> <source>let </source><target>REG </target> <source>return</source><target>RET</target> <source>exec </source><target>RUN </target> <source>goto </source><target>JMP </target> <source>call </source><target>JMS </target> <source>exit</source><target>HLT</target> <source>$_rga</source><target>$8</target> <source>$_rgb</source><target>$9</target> <source>$_rgc</source><target>$10</target> <source>$_rgd</source><target>$11</target> <source>$_rge</source><target>$12</target> <source>$_rgf</source><target>$13</target> <source>$_once</source><target>$14</target> <source>$_ret</source><target>$15</target> <source>$_OPTREG</source><target>$16</target> </source_code> <engine> <object> <source>xml</source><target>0x00</target> <source>screen</source><target>0x01</target> <source>width</source><target>0x02</target> <source>height</source><target>0x03</target> <source>path</source><target>0x04</target> <source>state</source><target>0x05</target> <source>identifier</source><target>0x06</target> <source>sprite</source><target>0x07</target> <source>media</source><target>0x08</target> <source>cursor</source><target>0x09</target> <source>sound</source><target>0x0A</target> <source>music</source><target>0x0B</target> ... etc </object> <command> <source>initialize</source><target>0x00</target> <source>get</source><target>0x01</target> <source>set</source><target>0x02</target> <source>open</source><target>0x03</target> <source>read</source><target>0x04</target> <source>write</source><target>0x05</target> <source>load</source><target>0x06</target> <source>unload</source><target>0x07</target> <source>create</source><target>0x08</target> <source>use</source><target>0x09</target> <source>refresh</source><target>0x0A</target> <source>clear</source><target>0x0B</target> <source>begin</source><target>0x0C</target> <source>end</source><target>0x0D</target> ...etc </command> </engine> </irisc>
[irisc::crypt_key]
Defines the encryption key to encrypt the compiled binary code. Code is encrypted by XOR-ing the byte code with this encryption key.
[irisc::source_code::source], [irisc::source_code::target]
String defined in source will be replaced by target during compilation. There are special compiler variables you can use to control the replacement behavior.
[irisc::engine::object::source], [irisc::engine::object::target]
String defined in source will be replaced by target during compilation of object codes.
[irisc::engine::command::source], [irisc::engine::command::target]
String defined in source will be replaced by target during compilation of command codes.
Using the basic IRIS instruction sets might be complicated when programming large applications. By using the Macro feature as described previously, we can improve the readability and time to code. IRIS++ is a programming language that encapsulates IRIS with a more comprehensive programming syntax using the Macro replacement technique. For instance, take a look at the following code:
let $0 = 23 + 5;
We have defined "let " as "REG " and =, +, ; as ATR, SUM, %EMPTY%%BREAK% respectively in post_define.xml. Once compiled, the result will be same as:
REG $0 ATR 23 SUM 5
Following are the pre-defined IRIS++ keywords and statements. Note that IRIS++ can only be used for the main execution script and not for external scripts imported by the import statement.
IRIS++ is similar to modern structured programming languages. Since the language is based on IRIS, there are many limitations to what it can do. Here are some points on the features and limitations.
You may use the following mathematical operators: +, -, *, / (addition, subtraction, multiplication, division).
You may use the following logical operators: ==, !=, <, > (equals, not equal to, less than, greater than).
You may use the following assignment operators: =, +=, -=, *=, /=, ++, -- (substitution, addition, subtraction, multiplication, division, increment, decrement).
Declares to manipulate on the specified register
// Let register A to be 23 let $_rga = 23; // Increment register A let $_rga++;
Defines a function. A function name must end with 2 brackets with a space and { symbol.
function initialize() { // Do a function call call main(); } function main() { // Do something and return back to where this function was called return; }
Calls a function. Use the return keyword to return back to where it was called.
call main();
Jumps to a function (and never returns back).
goto main();
Executes an external IRIS script. The external script needs to be compiled.
exec "test.bin";
Halts the program execution.
exit;
mem({memory address} [{assignment operator} {assignment value}]);
Manages the internal memory allocated by the Virtual Machine. Note that the memory keyword uses the UlyGL game library commands to operate on the memory and is not a defined feature in IRIS. The Virtual Machine must support the internal memory access in able to use this keyword.
// memory 0 = 10 // Equivalent to _memory::seek(0); _memory::set(10); mem(0 [= 10]); // memory 0 = 12 (Added 2 to the existing value) mem(0 [+ 2]); // memory 1 = 8 let $_rgb = 10; mem(1 [= 23 + 57 / $_rgb]); // Equivalent to _memory::seek(1); mem(1); // Equivalent to _memory::seek(0); let $_rga = _memory::get(); mem(0 let $_rga = _memory::get());
param[{value0}, {value1},, {value2},,, {value3}]@{function_name};
A short-cut to calling a function using parameters. Parameters are separated by increasing number of commas, up to the number of 6 parameters. Each parameter is assigned to the temporary registers from $_rga to $_rgf.
// Shows text function show_text() { // Call function print_text with parameters set param[ID_FONT_NORMAL, 0,, 0,,, "Hello, World!"]@print_text; return; } function print_text() { _screen::_text::use($_rga); _screen::_text::_x::set($_rgb); _screen::_text::_y::set($_rgc); _screen::_text::set($_rgd); _screen::_text::show(0); return; }
if([condition]) { }
Switches program flow depending on the condition.
// Assign 23 to register A let $_rga = 23; // If register A is 23, return if($_rga == 23) { return; } // [Tips]: Using the logical operator while assigning a value to register if($_rga = _screen::_frame::get() == 30) { // if frame count == 30 then ... }
do { } until [condition] loop;
Provides conditional loop functionality.
let $_rga = 0; // Loop for 3 times (loop until register A equals 3) do { // Increment let $_rga++; } until $_rga == 3 loop;