Perlstone Specification v1.1 (See http://wiki.sk89q.com/wiki/CraftBook/PerlStone for a up-to-date version, and examples) Introduction ------------ Perlstone (semi-humorously named after Perl due to the occasional comparisons between it and line noise) is a simple scripting language used in CraftBook for controlling programmable logic controllers. Basics ------ The state of Perlstone is defined by: * A stack * A 32-cell persistent variable table * A 32-cell temporary variable table * A 32-cell local variable table * A 'shift register' modifying which cell the store and load opcodes access for each variable table. * Three input registers Functions --------- A function consists of a string composed of an arbitrary number of opcodes. They may take arguments, and optionally return a single boolean value. A function returns after the last opcode in it is executed, or when an opcode is executed to explicitly cause it to return. When a function is called, a new temporary variable table created, with all cells initialized to 'false', as well as an stack, which is initialized to contain the arguments that the function was called with. These are persistent only for the duration of the function. Variable tables --------------- All three variable tables are index using the numbers 0-9 as well as the letters a-v. The numbers 0-9 are mapped to the first to tenth cells of the variable table, and the letters a-v are mapped to the eleventh to the 32nd cells of the variable table. Variable tables are labeled using the characters 'p' for the persistent table, 't' for the temp table, and 'l' for the local table. Uppercase versions of the index characters can also be used. When applicable, the uppercase versions ignore the shift register. Each variable table has a shift register which acts as a filter to its cell indexes. When a lowercase table indexer is used, the contents of the shift register is added, modulo 32, to the index before accessing/storing a value. Input Registers --------------- The three input registers are named 'A', 'B', and 'C'. They each contain a single boolean value, and may not be set in Perlstone code, and are instead usually set by the code calling it. Scripts ------- A script consists of up to one hundred functions, separated using the character ':'. They are indexed using the numbers 00 to 99, with the index 0 being the first function, the index 1 being the second, etc. Functions 0-2 are the entry points for a Perlstone program. Every time a programmable logic controller's state updates, all values in the temporary variable table are set to 'false', then, the input registers are set to the inputs to the PLC. Nonexistent inputs will be set to 'false'. Then, the function 00 is used to generate the output A, the function 01 is used to generate the output B, and the function 02 is used to generate the output C. If no value is returned, or the function does not exist, the PLC will behave as if false was returned instead. If an error occurs, script execution will halt, and, an error will display on the PLC's sign. The PLC will not preform further updates until it is destroyed and recreated. Opcodes ------- [opcode][operands] (initial stack -> resulting stack) - description Literal values: + (->t) - pushes 'true' onto the stack - (->t) - pushes 'false' onto the stack Input operations: A (->a) - pushes contents of the input register A onto the stack B (->b) - pushes contents of the input register B onto the stack C (->c) - pushes contents of the input register C onto the stack Memory manipulation operations: >r (->) - increments the shift register for table r by 1 ) - decrements the shift register for table r by 1 er (->) - resets the shift register for table r to 0 Srn (v->) - pops the top value of the stack, and stores it to slot n in the table r Lrn (->v) - pushes the value n in the table r onto the stack Stack operations: d (a->aa) - duplicates the top value of the stack p (a->) - pops the top value of the stack, and discards it vn (v(...)->v) - copies the value n values down in the stack onto the top, where 0 is the top of the stack. (i.e. v0 = d) x (xy->yx) - swaps the top two values of the stack Logical operations: ! (a->r) - pops the top value of the stack, and pushes it's inverse ^ (ab->r) - pops the top two values of the stack, and pushes the xor of them & (ab->r) - pops the top two values of the stack, and pushes the and of them | (ab->r) - pops the top two values of the stack, and pushes the or of them = (ab->r) - pops the top two values of the stack, and pushes their equality .abcd (ef->r) - pops the top two values of the stack (e and f) and if ef is 00, pushes a onto the stack, if ef is 01, pushes b onto the stack, if ef is 10 pushes c onto the stack and if ef is 11 pushes d onto the stack. a, b, c, and d are encoded as either the number '0' and '1' for false and true respectively, or the characters '+' and '-' for true and false respectively Flow control: cffn (123...->r?) - pops n values off the stack and calls the function f, with the previously popped values as the argument. f is the numeric id of the function. tffn (123...->r?) - pops n values off the stack and calls the function f, with the previously popped values as the argument, then returns the value returned by the called function if it exists, and otherwise, returns nothing. f is the numeric id of the function. [c] (v->) - pops a value from the stack. if the value is false, do nothing. otherwise, execute the code block c, then, repeat this process. s - returns from the current function r (v->) - pops the top value of the stack, and pushes that value onto the stack of the calling function then returns from the current function Changelog --------- Version 1.1: Added the >, < and, e opcodes, and the P/R/L modifiers for table affecting opcodes. Added the x opcode.