Textile
Textile (not to be confused with the markup language under the same name) is an attempt at a textual form of Tile created by User:Dtp09. Its name is a portmanteau of the words "Text" and "Tile", which is basically what it is.
Textile was created to allow for somewhat readable Tile programs, as well as functioning as a somewhat easier way to write complex Tile programs without worrying about how to route the PC across the grid.
Comments
Comments are indicated by a hashtag (#) and comment out the rest of the line. Block comments do not exist.
Functions
Functions are blocks of code that the PC can execute during runtime. Functions are not subroutines and do not return to where they were called from after execution. A function can be jumped to from anywhere in the program, both before and after the function's declaration. Functions can be declared with any alphanumeric label as follows:
LABEL: { #code goes here }
Program Initialization
All textile programs are required to have a function either called "main" or "MAIN". The PC will usually initialize to the first opcode in this function. If there is a debug opcode in the main function, that is where the PC will initialize instead. If the program contains both functions "MAIN" and "main", or neither, then the program will not run.
Opcodes
Opcodes are case insensitive. "NOP" and "Empty" tile states have been removed entirely, as they don't have any function outside of routing the PC across the grid. Every instruction has both a three digit opcode and a full length opcode, either of which can be written and will execute the same instruction.
Tile | Opcode |
---|---|
▀░ | psh / push |
░▀ | red / read |
▀▀ | out / output |
▄░ | sub / subtract |
█░ | add |
▄▀ | mul / multiply |
█▀ | div / divide |
░▄ | wrt / write |
▀▄ | ran / random |
░█ | inp / input |
▀█ | equ / equal |
▄▄ | jmp / jump |
█▄ | les / less |
▄█ | gtr / greater |
██ | dbg / debug |
Command Repitition
Commands can be repeated multiple times in a row with the same operands. They are represented by an asterisk followed by the repetition count. For example, "push*2 $FF" would push 255 to the stack twice.
Operands
Operands come after an opcode and are seperated by commas. Opcodes such as push, jump, greater, less, equal, and random, all have operands,
Push
Push is a very unique opcode. there are many ways to push the same exact thing to make it easier to read. You can push both numbers and ASCII strings to the stack.
Push accepts any quantity of operands. A "push" with no operands will push a single zero to the stack, and a "push" with one or more operands will push every value to the stack in written order.
Number
Numbers are written as 8-bit unsigned integers. They can be written in binary (prefixed %), decimal (no prefix), or hex (prefixed $). For example, to push decimal 108 to the stack, you can write any of the following:
- push $6C
- push 108
- push %01101100
Strings
Pushing a string will push the ASCII code of each character to the stack, ending with the top stack value being the last character in the string. They are represented by text encased in quotes or double-quotes. For example:
push "Tile"
This would push (from bottom to top) 84, 105, 108, 101. In a typical output loop, this would output in reverse, due to the LIFO nature of the stack.
String constants only have one method, and that is String.reverse, which will push every character to the stack in reverse order
Labels
Greater, Less, Equal, Jump, and Random, all accept function labels as operands. Opcodes "greater", "less", "equal", and "jump", all have 1 parameter each, while "random" accepts either 1, 2, or 3 operands. They operate similarly to how they do in Tile, with the "path to the right" being the function given for the comparison instructions, and the "path to the left" being anything after the comparison in the same function.
rand label1 label2 #jump to either of the given functions
Macros
Macros are statements within functions that "insert" code from other functions. Ideally, functions can be declared to be used by macros only, but any functions can be called as a macro. A macro can only call functions declared previously in the program.
MACRO: { # code goes here } ... somefunction: { [MACRO] # the same code will be inserted here }
Macros also follow command repitition, such as for [MACRO]*2, where the code will be inserted into the program twice in a row.
Program termination
Similarly to Tile, programs are terminated during a divide by zero error, or if PC reaches the end of a function.
Examples
Hello, World!
MAIN: { push "Hello, World".reverse jump OUTPUT } OUTPUT: { out push equal EXIT add jump OUTPUT } EXIT: { }
Cat Program
MAIN: { input push equal EXIT # exit if it's a null byte add out # output our input push 1 add # add to input read address push equal OVERFLOW # if the lower byte read address overflowed add jump MAIN } OVERFLOW: { push 1 add*3 # add 1 to input read higher byte push jump MAIN } EXIT: { }
Brainfuck
Written by User:Dtp09, the interpreter has unlimited loop depth, 8-bit unsigned cell storage, and 2^16-6 (65530) cells with wraparound. The program and the brainfuck input can be seperated by a semicolon. Since the program is about 500 lines, it is at Textile/brainfuck.
Compiler/Interpreter
A compiler and interpreter was written also by User:Dtp09 and is hosted here.