From Esolang
Jump to navigation Jump to search

Classtennis is an object-oriented esolang by User:BoundedBeans where programs are only a single expression.

File extensions

.clstns for normal code, .clstnsc for classes (libraries).

.clstnsc should contain a class without constructor arguments to create an object. The name of the class does not have to match the filename. Nested classes (such as field types, method return values, etc.) can be included, and do not need their own file.


An object's members can be accessed with the period, like a normal language. Methods can be run by suffixing them with a pair of parenthesis containing comma-separated parameters. "null" can be used to denote a null object.


Classes are only used to make one object, then they are abandoned. New classes are written like:

`class name`{description}(constructor arguments)

The description is made up of methods and fields, separated by semicolons. A field is written like: F`name`: type; type is a class.

A method is written like: M`name`<parameters>[commands];

Return types are dynamic, but you should be very careful with indeterminate return types since passing one that doesn't match to another function or field could throw an error.

The type of a field or method parameter does not need to be the same class, only have an identical description. The name can even be different. This even works with special names, as long as what they represent is the same as what is passed.

Commands can be:

return return-value;
   return-value can be anything.
setfield `field name`, value;
   field-name is the name of a field of this object, and value is the value to set it to
print value;
   value must be an expression evaluating to an object, which will print out the entire literal object expression.
input `field name`;
   field-name is the name of a field of this object, it will input a valid expression, or else null.
if value-to-test {commands} else {commands};
   value-to-test must be an expression evaluating to an object, and will call its truth() method.
while value-to-test {commands};
   value-to-test must be an expression evaluating to an object, and will call its truth() method
methodcall method;
   where method is a method call which can accept parameters and needs a class and object to work.

All methods implicitly have "return null;" written after them.

Method parameters are written like fields, but they cannot be set.

A method can be contained, named `truth`, which should return a `::Boolean` for use in if statements.

A method with the name of `construct` is a constructor method. If a constructor method with zero arguments is not provided, the default of setting all fields to null is automatically added.

Method calls are written with:

object.`method name`(arg1, arg2, arg3)

There can be any number of arguments, including zero.

Object expressions can be class calls, method calls, a field name in grave accent marks, the keyword this, an object followed by a period and a name in grave accent marks, or a valid combination of these.

Special class names

There are some special class names used for some purposes. Some use the description to specify what to override and what to add. This can allow extension.

The first one is `Current class`, which refers to the class containing it. You can access further from the innermost with `Current class:n` where n is replaced with a number >2, or 1 which does the same thing as just `Current class`.

If a name starts with >>>, it refers to the file path directly after it in the folder the currently running file is in, which should be a valid .clstnsc file. For example, `>>>Dictionary.clstnsc`. It can also include slashes, such as `>>>lib/Set.clstnsc`. This can be used as the name of the class in a .clstnsc file to allow extending a class from another file.

Another special name is `Any`, this is only used in method parameter types and field types, which means that it can accept anything.

`Any` and built-in classes cannot be extended, and must have an empty description.

There are also some built-in classes, having special names that start with two colons.

Built-in classes

   Returns false
   `construct`<`val`: `Any`{}>
   Returns true
   `and`<`val`: `::Boolean`{}>
   Logical and.
   `or`<`val`: `::Boolean`{}>
   Logical or
   `xor`<`val`: `::Boolean`{}>
   Logical xor
   Logical not of the object that called this.
   Returns itself
   `truth`<`val`: `Any`>
   Returns `val`.`truth`, if `val` is null, returns false. 
   May be useful for if-else statements where there are multiple things to check,
   combined with and, or, not, and xor, but you can just call truth directly. 
   Requires a Boolean object as this, which will be discarded.

   Returns zero
   `construct`<`val`: `::Boolean`{}>
   Returns 1 if the `val` is true, -1 otherwise.
   `construct`<`val`: `::Integer`{}>
   Increments the integer
   `add`<`val`: `::Integer`{}>
   Changes this to this + `val`
   `sub`<`val`: `::Integer`{}>
   Changes this to this - `val`
   `mul`<`val`: `::Integer`{}>
   Changes this to this * `val`
   `div`<`val`: `::Integer`{}>
   Changes this to this / `val`
   `equals`<`val`: `::Integer`{}>
   Returns true if this and `val` are equal, false otherwise
   `less than`<`val`: `::Integer`{}>
   Returns true if this is less than `val`, false otherwise
   Returns true if nonzero, false otherwise.
   Greater than or equal to can be simulated with this.`less than`(`val`).`not`()
   Greater than can be simulated with this.`less than`(`val`).`or`(this.`equals`(`val`)).`not`
   Less than or equal to can be simulated with this.`less than`(`val`).`or`(this.`equals`(`val`))


   Returns an empty stack.
   `push`<`val`: `Any`{}>
   Pushes the value to the stack.
   Pops and returns the top value on the stack
   Duplicate can be simulated by popping and pushing twice from a field.
   Swap can be simulated by popping into two different fields, and pushing them back in the wrong order.

A pair class can be made rather easily. Tuples can also be made the same way. Tapes/lists can be simulated by two stacks and a normal value. Deques or queues can be simulated with a tape with distinguishing endpoint items. Dictionaries can be simulated with a list of pairs Binary trees can be simulated by nested pairs. Other trees can be simulated by nested tuples.


Print "`Hello world!`{}()"

`Printer`{M`print`<>[print `Hello world!`{}();]}().`print`()


Input "`::Boolean`{}()" for zero, "`::Boolean`{}(null)" for one.

`Truth Machine`{F`bool`: `::Boolean`{}; M`test`<>[input `bool`; while `bool` {print `bool`;}; print `bool`;]}().`test`()