Bidiroop

Bidiroop is an esolang by User:BoundedBeans where objects and classes have a different sort of relationship than usual.
==Fundamentals==
There are four first-class types in Bidiroop, two specific and two general.
# Unbounded integers (positive or negative)
# Strings
# Classes (describes the characteristics of its instances, which are objects)
# Objects (describes the characteristics of classes via returning classes from their methods dynamically)
Classes have methods, which cannot be accessed without an object of the type. All methods return classes, but can take any arguments. Objects have their own instance values, which classes can base off of. This effectively, but not technically, means that objects describe classes. In fact, objects fields cannot even be accessed directly except in their own methods, making objects effectively useless other than to describe classes through their methods. However, to allow functions that don't return classes, functions can be declared in a separate way not pertaining to objects.
Classes may contain:
* Inner classes (only accessible from the class's methods)
* Functions (only accessible from the class's methods)
* Fields (cannot be static but can have default values, only accessible from the class's methods)
* Methods (accessible from anywhere)
Methods may contain:
* Local classes
* Functions
* Local variables
All three of those are inaccessible outside the method.
Functions may contain the same things as methods, but they may be outside of classes. Inside of classes, they are static.
Fields and variables can contain any type, including classes. Any type may be a parameter to a function or method, and a function may return any type (methods can only return classes).
If a method or function gets passed the wrong type as a parameter, it will throw an error. However, functions can be overloaded to have different parameter types.
Methods and functions have access to direct members of any level that contains it, but not any indirect members. For example, say that there is a class named Foo, containing a method named Bar and an inner class named Baz. Baz contains method baz_event and an inner class named Baz_Inner. Bar can make objects of Baz (and also run their methods, since that qualifies as the object accessing it), but not Baz_Inner. Bar can also make objects of Foo. However, baz_event can make objects of Baz_Inner.
All functions must have some return value, since they can only be run as part of an expression.
The program begins by executing the function named "main". This language should be garbage collected.
==Syntax==
This language uses indentation to store things, much like Python (the practical one, not the esolang). Unlike Python, the only valid indentation is two spaces, not more, not less.
Variable, field, class, method, and function names should contain only letters and underscores.
==Statements==
 Import (filename)
This loads all functions and classes and their members into memory from the Bidiroop file.
 If (integer)
Runs the indented code only if the integer is not zero.
 If (string)
Runs the indented code only if the string is not empty.
 Else
Runs the indented code if the previous condition was not met.
 While (integer)
Repeats the indented code as long as the integer is not zero
 While (string)
Repeats the indented code as long as the string is not empty.
 Set (variable name), (expression)
Sets the variable to the expression. If the variable does not exist yet, create it. This can be put outside of functions to make global variables.
 Delete (name)
Deletes the variable, function, or class.
 Class (name)
Creates a class; the indented code should be made of Set commands (fields), method declarations, class declarations, and function declarations, comments, and nothing else.
 Method (name)
Must be inside of a class. Creates a method, with the indented code being the content. After the name, there can optionally be a comma followed by a comma separated list of parameter declarations of the format (type) (name), where type can be "Integer", "String", "Class", "Any", or the name of a class to represent an object.
 Function (name)
Creates a function, with the indented code being the content.. After the name, there can optionally be a comma followed by a comma separated list of parameter declarations of the format (type) (name), where type can be "Integer", "String", "Class", "Any", or the name of a class to represent an object.
 Print (expression)
Prints a string or an integer.
 InputInteger (name)
Inputs an integer into the named variable.
 InputString (name)
Inputs a line of input into the named variable as a string.
 Return (expression)
Returns a value from a method or function.
 Comment (expression)
Ignored. Normally the expression should be a string literal, but it doesn't have to be.
 
==Expressions==
Expressions can be made of the following components:
Variable names:
Can be any variable the code has access to, or current for the object calling the currently executing method or function.
Integer literals: same as in most other languages.
String literals: Text between double quotes. The following escape sequences are supported: \n for newline, \" for quote, \\ for backslash.
Objects: Goes something like this: 
 ClassName[my_var: 17 + 8, str: "Hello", x: -10349]. 
The variable names should be replaced with the actual parameter names specified in the class. They can be omitted to leave them at the default specified by the class.
Classes: Typed like this: 
 <C>("String"). 
The string should be a valid class definition (without the header) (the example is therefore not valid, just demonstrates syntax. It can however be an expression instead. This is pretty much the only way for a method to return a class, although the &* operator could be used to combine classes already specified somewhere. ). When creating a class this way, it is always treated as global. Classes that only exist in an expression and aren't assigned to anything will be deleted, unless they are the return value from a function or method, in which it will check if the function or method was called in an assignment statement, in which it will save the class in the variable.
Operators:
 + - addition
 - - subtraction
 * - multiplication
 / - division
 % - modulo
 ^ - exponent
 () - parenthesis for precedence, required for any more than one operator in an expression
 +* - string concatenation (can accept numbers to convert them to strings)
 ^% - discards the second argument, converts the first to a string
 &* - takes two classes, makes a new class with all methods, fields, inner classes, and functions from both. 
 If there are duplicates, it discards the one from the second argument
 /& - logical NAND
 = - 1 if equal, zero if not (also works with strings)
 > - 1 if the first is greater than the second, zero if not.
 (less than can be accomplished with (((a = b) /& (a = b)) /& ((a > b) /& (a > b))) /& (((a = b) /& (a = b)) /& ((a > b) /& (a > b))) )
 -/ - string cut off removing the position of the integer and afterwards
 /- - string cut off removing everything before the position of the integer
 -^ - ignores right, returns length of string
Method calls can be notated as <M>[(Object name)][(Method name)][(comma separated list of parameters)]
Such as <M>[my_object][strip_arguments][" get rid of this whitespace", "hello", "hi! "]
Function calls are the same, but they have no object name and the <M> is <F> instead. 
==Tricks==
===Data-containing objects===
Objects can actually be used as containers of data as normal, but it's a bit weird. They will need getter and setter methods. Setter methods are simple, just set the value and return an empty class. Getters are weird, though. To make a getter you'll need to set a global variable to the value of an object field and return an empty class. Then other code can use the value of that global variable, which now contains the value of the object field. You can also use this as a general way to return things from methods that aren't classes.
===First-class functions===
Functions and methods are not first-class in Bidiroop, but by creating a class containing it from the text of the class, we can effectively emulate that.
===Inheritance===
Bidiroop does not have class inheritance, but it can be emulated with the &* operator, with the first class being the new content and the second class being the superclass. It will then evaluate to the class that is on the left, except that it extends the class on the right. Even normal overriding rules work if there are duplicate names!
==Examples==
===Hello world===
 Function main
 Print "Hello, world!"
===Calculator===
 Class OperatorConstruct
 Method a, op
 Return <C>(("Function apply, Integer a, Integer b\n Return a " +* op) +* " b\nMethod m, Integer a, Integer b\n Print <F>[apply][a, b]\n return <C>(\"\")")
 Function main
 InputInteger arga
 InputString operator
 InputInteger argb
 Set o, OperatorConstruct[]
 Set C, <M>[o][a][operator]
 Set oo, C[]
 Set mrun, <M>[oo][m][arga, argb]
===Truth-machine===
 Function main
 InputInteger val
 If val
 Set TheClass, <C>("Method event\n Set x, 1\n While x\n Print \"1\"\n Return <C>(\"\")")
 Else
 Set TheClass, <C>("Method event\n Print 0\n Return <C>(\"\")")
 Set the_object, TheClass[]
 Set mrun, <M>[the_object][event][]
No object orientation:
 Function main
 InputInteger val
 If val
 While val
 Print val
 Else
 Print 0
===Deadfish interpreter===
 Set accumulator, 0
 Class Deadfish
 Function i
 Set accumulator, accumulator + 1
 If accumulator = 256
 Set accumulator, 0
 Return 0
 Function d
 Set accumulator, accumulator - 1
 If accumulator = -1
 Set accumulator, 0
 Return 0
 Function s
 Set accumulator, accumulator ^ 2
 If accumulator = 256
 Set accumulator, 0
 Return 0
 Function o
 Print accumulator
 Return 0
 Function main
 InputString code
 Set counter, 0
 Set countermax, code -^ code
 Set total_class_str, "Method run\n"
 While countermax > counter
 Set piece, code -/ (counter + 1)
 Set piece, piece /- counter
 Set total_class_str, total_class_str +* (" Set dummy, <F>[" +* (piece +* "][]\n"))
 Set counter, counter + 1
 Set total_class_str, total_class_str +* "Return <C>(\"\")"
 Set ConstructedClass, <C>(total_class_str) &* Deadfish
 Set the_object, ConstructedClass[]
 Set dummy, <M>[the_object][run][]
===Brainfuck interpreter===
This uses 3-cell unbounded brainfuck to prove Bidiroop Turing-complete, since Bidiroop does not have an array feature. Uses integer I/O rather than character. Code should be given as input, all on one line.
 Set cella, 0
 Set cellb, 0
 Set cellc, 0
 Set currentcell, 1
 Class Brainfuck
 Function plus
 If currentcell = 1
 Set cella, cella + 1
 If currentcell = 2
 Set cellb, cellb + 1
 If currentcell = 3
 Set cellc, cellc + 1
 Return 0
 Function minus
 If currentcell = 1
 If currentcell > 0
 Set cella, cella - 1
 If currentcell = 2
 If currentcell > 0
 Set cellb, cellb - 1
 If currentcell = 3
 If currentcell > 0
 Set cellc, cellc - 1
 Return 0
 Function left
 If currentcell = 1
 Set currentcell, 3
 Else
 Set currentcell, currentcell - 1
 Return 0
 Function right
 If currentcell = 3
 Set currentcell, 1
 Else
 Set currentcell, currentcell + 1
 Return 0
 Function input
 If currentcell = 1
 InputInteger cella
 If currentcell = 2
 InputInteger cellb
 If currentcell = 3
 InputInteger cellc
 Return 0
 Function output
 If currentcell = 1
 Print cella
 If currentcell = 2
 Print cellb
 If currentcell = 3
 Print cellc
 Return 0
 Function main
 InputString code
 Set counter, 0
 Set countermax, code -^ code
 Set total_class_str, "Method run\n"
 Set spacing, 1
 While countermax > counter
 Set piece, code -/ (counter + 1)
 Set piece, piece /- counter
 Set scounter, spacing
 While scounter
 Set total_class_str, total_class_str +* " "
 Set scounter, scounter - 1
 If piece = ">"
 Set total_class_str, total_class_str +* "Set dummy, <F>[right][]\n"
 If piece = "<"
 Set total_class_str, total_class_str +* "Set dummy, <F>[left][]\n"
 If piece = "+"
 Set total_class_str, total_class_str +* "Set dummy, <F>[plus][]\n"
 If piece = "-"
 Set total_class_str, total_class_str +* "Set dummy, <F>[minus][]\n"
 If piece = "."
 Set total_class_str, total_class_str +* "Set dummy, <F>[output][]\n"
 If piece = ","
 Set total_class_str, total_class_str +* "Set dummy, <F>[input][]\n"
 If piece = "["
 Comment "A really long way of saying 'While ((currentcell = 1) and (cella > 0)) or (((currentcell = 2) and (cellb > 0)) or ((currentcell = 3) and (cellc > 0)))'"
 Set total_class_str, total_class_str +* "While (((currentcell = 1) /& (cella > 0)) /& ((currentcell = 1) /& (cella > 0)) /& ((currentcell = 1) /& (cella > 0)) /& ((currentcell = 1) /& (cella > 0))) /& (((((currentcell = 2) /& (cellb > 0)) /& ((currentcell = 2) /& (cellb > 0)) /& ((currentcell = 2) /& (cellb > 0)) /& ((currentcell = 2) /& (cellb > 0))) /& (((currentcell = 3) /& (cellc > 0)) /& ((currentcell = 3) /& (cellc > 0)) /& ((currentcell = 3) /& (cellc > 0)) /& ((currentcell = 3) /& (cellc > 0)))) /& ((((currentcell = 2) /& (cellb > 0)) /& ((currentcell = 2) /& (cellb > 0)) /& ((currentcell = 2) /& (cellb > 0)) /& ((currentcell = 2) /& (cellb > 0))) /& (((currentcell = 3) /& (cellc > 0)) /& ((currentcell = 3) /& (cellc > 0)) /& ((currentcell = 3) /& (cellc > 0)) /& ((currentcell = 3) /& (cellc > 0)))))\n"
 Set spacing, spacing + 1
 If piece = "]"
 Set spacing, spacing - 1
 Set counter, counter + 1
 Set total_class_str, total_class_str +* " Return <C>(\"\")"
 Set ConstructedClass, <C>(total_class_str) &* Brainfuck
 Set the_object, ConstructedClass[]
 Set dummy, <M>[the_object][run][]
===Self-interpreter===
Give the program as input, with the final line containing @END
 Function main
 Set code, ""
 Set line, ""
 While (line = "@END") /& (line = "@END")
 Set code, code +* (" " +* (line +* "\n"))
 InputString line
 Set class_string, "Method __code__"
 Set class_string, class_string +* (code +* " <F>[main][]\n Return <C>(\"\")")
 Set ClassedCode, <C>(class_string)
 Set an_object = ClassedCode[]
 Set dummy, <M>[an_object][__code__][]
==Data structures==
Data structures are hard to make in Bidiroop, but not impossible. The main issue is that objects cannot make their fields available through returning. However, this is still possible by setting a global variable to the object field's value. We'll call this global variable globereturn. This way we can implement a getter. We can implement a setter much easier by passing a parameter, and having the method set the value. For both of these, the actual return value of the method will be an empty class.
===Stack===
The stack is the base for a lot of other data structures.
Here is the stack class:
 Class Stack
 Set value, 0
 Set link, 0
 Comment "Stores new stack element with the thing to push as the element and the link being the element you called the method on"
 Comment "You will have to get the value from globereturn"
 Method push, Any thing_to_push
 Set globereturn, Stack[value: thing_to_push, link: current]
 Return <C>("")
 Comment "Returns the linked element; also get the value from globereturn"
 Method pop
 Set globereturn, link
 Return <C>("")
 Method get_value
 Set globereturn, value
 Return <C>("")
Push and pop are the base operations needed. To pop and return the value, you'll need to use get_value, put the value in globereturn somewhere else, then pop. Using just get_value is equivalent to a peek. From these you can form duplicate, swap, roll, etc.
===List with pointer===
A list with a pointer can be accomplished with two stacks, and a delimiting value for each end. I used @FIRST and @LAST for the delimiting values, but you could use anything.
 Class List
 Set stacka, Stack[value: "@FIRST", link: 0]
 Set stackb, Stack[value: "@LAST", link: 0]
 Set pointed, 0
 Comment "left, right, set_value, insert, and remove_pointed modify in place; there isn't any need to pick up the result from globereturn"
 Comment "for get_value and check_bounds you WILL need to get the result from globereturn"
 Method left
 Set dummy, <M>[stackb][push][pointed]
 Set stackb, globereturn
 Set dummy, <M>[stacka][get_value][]
 Set pointed, globereturn
 Set dummy, <M>[stacka][pop][]
 Set stacka, globereturn
 Return <C>("")
 Method right
 Set dummy, <M>[stacka][push][pointed]
 Set stacka, globereturn
 Set dummy, <M>[stackb][get_value][]
 Set pointed, globereturn
 Set dummy, <M>[stackb][pop][]
 Set stackb, globereturn
 Return <C>("")
 Method set_value, Any value_to_set
 Set pointed, value_to_set
 Return <C>("")
 Method get_value
 Set globereturn, pointed
 Return <C>("")
 Method insert, Any value_to_insert
 Set dummy, <M>[stacka][push][value_to_insert]
 Set stacka, globereturn
 Set dummy, <M>[current][left][]
 Return <C>("")
 Method remove_pointed
 Set dummy, <M>[stackb][get_value][]
 Set pointer, globereturn
 Set dummy, <M>[stackb][pop][]
 Set stackb, globereturn
 Return <C>("")
 Comment "Returns 1 if pointer on the border, 0 if not"
 Method check_bounds
 If pointed = "@FIRST"
 Set globereturn, 1
 Else
 If pointed = "@LAST"
 Set globereturn, 1
 Else
 Set globereturn, 0
 Return <C>("")
Now we have everything we need for a list with a pointer. This enables us to make a deque.
===Deque===
 Class Deque
 Set mainlist = List[]
 Comment "remove_first and remove_last also retrieve the value and put it in globereturn. All methods modify in place."
 Method add_first, Any value_to_add
 While <M>[mainlist][check_bounds][] = 0
 Set dummy, <M>[mainlist][left][]
 Set dummy, <M>[mainlist][right][]
 Set dummy, <M>[mainlist][insert][value_to_add]
 Return <C>("")
 Method add_last, Any value_to_add
 While <M>[mainlist][check_bounds][] = 0
 Set dummy, <M>[mainlist][right][]
 Set dummy, <M>[mainlist][insert][value_to_add]
 Return <C>("")
 Method remove_first
 While <M>[mainlist][check_bounds][] = 0
 Set dummy, <M>[mainlist][left][]
 Set dummy, <M>[mainlist][right][]
 Set dummy, <M>[mainlist][get_value][]
 Set deque_local_value_holder, globereturn
 Set dummy, <M>[mainlist][remove_pointed][]
 Set globereturn, deque_local_value_holder
 Return <C>("")
 Method remove_last
 While <M>[mainlist][check_bounds][] = 0
 Set dummy, <M>[mainlist][right][]
 Set dummy, <M>[mainlist][left][]
 Set dummy, <M>[mainlist][get_value][]
 Set deque_local_value_holder, globereturn
 Set dummy, <M>[mainlist][remove_pointed][]
 Set globereturn, deque_local_value_holder
 Return <C>("")
 
===Queue===
A queue can be implemented simply by using only opposite sides of the deque. Funnily enough, you can actually make a stack from a deque too, making a totally pointless stack made out of two stacks.
===Pair===
Pair is separate from the rest of them, and is pretty easy.
 Class Pair
 Set valuea, 0
 Set valueb, 0
 Method set_a, Any value_to_set
 Set valuea, value_to_set
 Return <C>("")
 Method set_b, Any value_to_set
 Set valueb, value_to_set
 Return <C>("")
 Method get_a
 Set globereturn, valuea
 Return <C>("")
 Method get_b
 Set globereturn, valueb
 Return <C>("")
===Dictionary===
This only works with strings, but if you added some sort of equals method to a class, you could make another class kind of like this one using different keys. It does not actually hash the values, merely checks every single one of them until it finds it. It uses a list of pairs to accomplish this.
 Class Dictionary
 Set mainlist, List[]
 Method set, String k, Any v
 Set key_found, 0
 While <M>[mainlist][check_bounds][] = 0
 Set dummy, <M>[mainlist][get_value][]
 Set dictionary_local_value_holder, globereturn
 Set dummy, <M>[dictionary_local_value_holder][get_a]
 If globereturn = k
 Set dummy, <M>[mainlist][set_value][Pair[k, v]]
 Set key_found, 1
 Set dummy, <M>[mainlist][right][]
 If key_found = 0
 Set dummy, <M>[mainlist][insert][Pair[k, v]]
 Set dummy, <M>[mainlist][left][]
 While <M>[mainlist][check_bounds][] = 0
 Set dummy, <M>[mainlist][left][]
 Set dummy, <M>[mainlist][right][]
 Return <C>("")
 Comment "To check if a key exists, use the get method and check that the value is not '@KEY_NOT_FOUND'"
 Method get, String k
 Set key_found, 0
 While <M>[mainlist][check_bounds][] = 0 
 Set dummy, <M>[mainlist][get_value][]
 Set dictionary_local_value_holder, globereturn
 Set dummy, <M>[dictionary_local_value_holder][get_a]
 If globereturn = k
 Set dummy, <M>[mainlist][get_value][]
 Set key_found, 1
 Set dummy, <M>[mainlist][right][]
 If key_found = 0
 Set globereturn, "@KEY_NOT_FOUND"
 Set dummy, <M>[mainlist][left][]
 While <M>[mainlist][check_bounds][] = 0
 Set dummy, <M>[mainlist][left][]
 Set dummy, <M>[mainlist][right][]
 Return <C>("")
 Method remove, String k
 While <M>[mainlist][check_bounds][] = 0 
 Set dummy, <M>[mainlist][get_value][]
 Set dictionary_local_value_holder, globereturn
 Set dummy, <M>[dictionary_local_value_holder][get_a]
 If globereturn = k
 Set dummy, <M>[mainlist][remove_pointed][]
 Set dummy, <M>[mainlist][right][]
 Set dummy, <M>[mainlist][left][]
 While <M>[mainlist][check_bounds][] = 0
 Set dummy, <M>[mainlist][left][]
 Set dummy, <M>[mainlist][right][]
 Return <C>("")
===Summary===
We've basically constructed a stack through a singly-linked list concept. We construct a simple ordered pair as well. We can take two stacks to form a list with a pointer. Using that list, we can construct a few algorithms for the list to work like a deque. With a deque, we can have a queue. Also, a list of pairs, combined with certain algorithms, can make a dictionary from strings to other data types. It is also fully possible to combine these to nest them. We can use list objects as the element of another list to create a matrix. Or we can include a stack object as the values of a dictionary to construct a mapping from strings to stacks. Or nest dictionaries, or whatever else. Trees are really the only base data structure we haven't done, but a binary tree could be a ton of nested pairs, and something bigger could be nested dictionaries with the keys as child identifiers, paths encoded as a list of strings. 
Category:Languages
Category:Turing complete
Category:Object-oriented paradigm
Category:Unimplemented