Object oriented Thue

From Esolang
Jump to navigation Jump to search

Object oriented Thue was created by User:4D enthusiast in 2012. It is based on Thue, but it has 2 extra reserved characters: "{" and "}", which are used to represent the boundaries of objects. The purpose of this language is to allow greater efficiency in a language similar to Thue, for example, bypassing the Thue Symbol Sorting Theorem. It is Turing complete because it is trivially an extension of the already Turing-complete Thue. Each object has its own internal string, which is inaccessible from outside, and may have child objects embedded in the string.

Syntax

In the source code of OOT, the main type of line, as in Thue, is the substitution rules. They consist of two strings separated by "::=". Whenever the left-hand-side string appears in an applicable data-string, it may be replaced by the RHS. If any non-empty line before the end does not contain ::= and does not fit any other pattern, it is interpreted as the start of a class. The contents of that line are normally the name of the class. The class ends when there is a line containing only a "}". When an object is embedded inside of another object's string, it is represented by "{ClassName}", and can be manipulated by the substitution rules of the containing class, but only as a unit. The brackets must match up in each rule and the string inside of them must be the name of some defined class at all times. The reference can also contain numbers to refer to a particular object when written on the RHS of substitution rules, for example, if you want to swap two Duck objects when there is an "s" present, you could write

s{Duck}{Duck}::={Duck}{1}{Duck}{0}

If no numbers are present, the order is assumed to be the same as in the LHS (i.e. the nth unlabelled object on the RHS refers to the nth object of that class on the LHS, irrespective of any numerically tagged objects). {Class}{n} refers to the nth appearance of {Class} in the LHS (starting at 0), not counting anything referred to in the LHS as a sub- or super-class. Negative numbers are not allowed, and if n is at least the number of references to that class in the LHS, a new object is created, with a blank internal string. To avoid ambiguity, class names must not consist solely of digits. Objects may also be copied like this, for example:

{Object}::={Object}{Object}{0}

In this case, a shallow copy is produced of the object. The creation of deep copies must be explicitly programmed. Any rules inside a class declaration will only operate on the inner strings of the objects, but may operate over the boundary either side to permit data transmission into and out of the object:

Convert
}a::=a}
}b::=b}
{a::=A{
{b::=B{
}

{Convert}abba

this will finish as the string ABBA{Convert}, where the Convert is empty. Clearly in this case the same effect could be obtained by not putting the a's and b's into the object, but objects can store data in a more compressed form and carry it across other data, then let it out at the other side, or allow certain processes to only take place in certain settings more easily than with standard Thue. To avoid ambiguity, curly brackets may only be in a substitution rule of an object's inner string if they refer to the brackets at either side of that object, or form complete pairs referring to other objects. Outside of class declarations, they must form complete pairs referring to objects. Subclasses may also exist, by the first line of the class declaration (its name) being followed by another line without "::=", which is the name of the superclass. Any rules which operate on a class may also operate on a subclass. Substitution rules are inherited by subclasses, but may be cancelled by repeating them in the subclass. This example demonstrates inheritance:

Superclass
X{::={
}I::=}
}
Subclass
Superclass
X{::={
}
{Superclass}X::=X{Superclass}
::=

{Subclass}IX

In this example, the subclass object will destroy the "I", then will be treated as a superclass object, and be moved to the right of the "X", but it will not destroy the "X", because that rule was cancelled in the sub-class declaration. Multiple inheritance should be supported, and a rule will be present in the sub-class if it is present in any of the super-classes. Comments have an explicit syntax, unlike in Thue, and are written as follows:

{Comment here

They may not contain "::=". Any blank lines are also ignored.

The final line in the source code is the starting string. As with strings created by the RHS of rules, it may only contain brackets in matched pairs with valid class-names. Unlike in Thue, a line containing only "::=" is not necessary before the initial string.

Garbage collection

Even when an an object is not in any way reachable from the main string, it is still possible for it to have an effect on the output. Despite this, it is still liable to be garbage-collected. Any such objects may or may not have rules executed on them, but the programmer should not depend on either case. This is necessary to ensure that objects can be safely discarded without causing memory leaks.

Libraries

There are some standard libraries in OOT, mostly input and output. These must be imported at the start with the word "import". Classes in separate class files may be imported by using the file-name of the file containing the class (with the extension .oot). All standard libraries have names which start with "std", but user-defined libraries may not. All classes in standard libraries take input on their right, and produce output on their left, for consistency and ease of chaining output to input. The idea of the libraries is to allow the programs to do things which would not be possible without them (e.g. detecting the time of day), rather than for convenience.

stdio

The input and output of Thue are severely restricted by being text-only and vulnerable to code injection, so in OOT, the I/O is all done through these standard classes. The text-only library is called "stdio". It consists of 4 classes: {TextInput}, {TextOutput}, {HexInput} and {HexOutput}. Whenever a line is typed at the command-line, it appears before all {TextInput} objects, but in escaped form:

escape code character
\( {
\) }
\n new-line
\U008F Unicode character 008F (for example)
\/ \

Any character which is not in ASCII is output using the \Uxxxx code (hexadecimal, with compulsory uppercase). {TextOuptut} objects print everything to their right, which should also be escaped, but will not interact with other objects. If an invalid escape code is encountered, the {TextOutput} object will not execute the rule. By putting the {TextInput} inside other objects, it is possible to avoid rules immediately unintentionally being invoked on their output. The hex versions work the same, but {HexInput} will use the \Uxxxx escape code for all input characters, ASCII or not, and {HexOutput} will not accept any input not thus encoded. The hex variants read to and print from the same input/output streams.

stdfile

This library is for all file related I/O. It contains five classes: {File}, {TextReader}, {TextWriter}, {FileReader} and {FileWriter}. File objects are initialised containing the file location of the program. The table shows codes that the object will accept (and destroy in the process), and the effects that these have:

Code Example Effect notes
: (in Unix-like systems){File}:root/

(in Windows){File}:C/

changes the file to point to the absolute path named
/.../ {File}/subfolder/ changes the file to point to a sub-folder or file uses the same sort of escaping as stdio. If the file or folder does not exist, it is created.
/../ {File}/../ changes the file to point to the parent folder does nothing if the File has no parent folder
L {File}L lists the sub-folders separated by "/" to the left If it is not a folder, it produces nothing. There are "/"s at either end of the list.
D {File}D delete this file or folder The File object still refers to the non-existent file.
TR {File}TR creates a {TextReader} reading from the current file Appears to the left of the {File}
TW {File}TW creates a {TextWriter} writing to the current file
FR {File}FR creates a {FileReader} reading from the current file
FW {File}FW creates a {FileReader} writing to the current file
A {File}A ouputs the File's full address to its left

Whenever there is a single "." to the right of any of the other four objects, it either writes the character to the right of the "." to a file (in ASCII or hexadecimal depending on the sort of writer) or adds a character which was read to the left of the object, and a comma replaces the "." in both cases. "<" and ">" move the pointer in the file to another address expressed in nybbles or characters, depending on the sort of reader, with the numbers in hex, e.g.:

import stdio
import stdfile
{TextReader}{File}::={TextReader}
{TextReader},::=

{TextOuptut}{File}/document.txt/TR<A1>.

this outputs the 161st (0xA1) character in document.txt to standard output.

stdtime

This contains the {Time} class only. This is used for all of the time-dependent things. It accepts 5 sorts of input:

code result
{Time}pFFFp returns "P" after FFF milliseconds. This may have any number of digits.
{Time}ms returns the number of milliseconds since the program started.
{Time}T returns the number of milliseconds since midnight
{Time}D returns the number of milliseconds since the first of January, 2000 (a nice round date)
{Time}b switches this time-object between binary(b) decimal(d) and hexadecimal(h)

stdnetwork

I don't know enough about network access to write this. Could somebody please help?

others

Any suggestions as to more libraries would be welcome on the talk page. I would prefer if they were I/O related, so as to allow as much as possible without adding any libraries which simply make programming easier.

Examples

Hello World:

import stdio
{TextOutput}Hello, World!

cat:

import stdio
{no substitution rules are required.
{TextOutput}{TextInput}

output the file "text.txt"

import stdio
import stdfile
{TextReader}{File}::={TextReader}
{TextReader},::={TextReader}.

{TextOutput}{File}/document.txt/TR.

99 bottles of beer:

import stdio
{"r" for "ready to proceed"
Digit
}i::=9}r
9}-::=8}r
8}-::=7}r
7}-::=6}r
6}-::=5}r
5}-::=4}r
4}-::=3}r
3}-::=2}r
2}-::=d1}!
{d::=d{
1}-::=c0}!
{c::=c{
0}-::=-.9}!
r{-::=-{
r{.::=rR{

}o::=o}!
{9o::=9{9r
{8o::=8{8r
{7o::=7{7r
{6o::=6{6r
{5o::=5{5r
{4o::=4{4r
{3o::=3{3r
{2o::=2{2r
{1o::=1{1r
{0o::=0{0r
r}!::=}r
}

Number
}i::={Digit}i{Digit}i}!
R{Digit}!::={Digit}r
{c{Digit}!::={r
d{Digit}::=D{Digit}x
{D::={X
X{Digit}x!{Digit}::={Digit}r{Digit}
rD{Digit}x!::=r{Digit}r
X{Digit}x!}!::=}1
rc{Digit}!::=r{Digit}r
r}-::=-}!
r}!::=r}r
}o::=O!}!
{Digit}rO::=O{Digit}r
{rO::={O
{O{Digit}r::={{TextOutput}{Digit}o
{TextOutput}{Digit}r{Digit}r::={Digit}r{TextOutput}{Digit}o
{TextOutput}{Digit}r!::={Digit}r
}

Inert
{I need a place-holder class so it won't get eaten by the {TextOutput}
}
rA::=oB
rB{TextOutput}::=rC{TextOutput} bottles of beer on the wall,\n
rC{TextOutput}{Inert}::=oD{TextOutput}{Inert}
rD{TextOutput}::=rE{TextOutput} bottles of beer.\nTake one down, pass it around,\n
rE{TextOutput}{Inert}::=-F{TextOutput}{Inert}
rF::=oG
rG{TextOutput}::=rH{TextOutput} bottles of beer on the wall.\n\n
rH{TextOutput}{Inert}::=rA{TextOutput}{Inert}
{Number}1F{TextOutput}{Inert}::={TextOutput}1 bottle of beer on the wall.\n\n1 bottle of beer on the wall,\n1 bottle of beer.\nTake it down, pass it around,\nno more bottles of beer on the wall!

{Number}iA{TextOutput}{Inert}

External resources