I had written the code for user input a while ago, but apparently it didn't get put on github. And then my local copy got deleted. But I rewrote it today, and I fixed a bug with reverse bifurcation. So it should work now. And I have confirmed that it did indeed get put on github, so I don't need to worry about this happening again.
~ATH is a programming language. A programming language is a language that can be used to write programs in, that can afterwards be run. ~ATH appears in Homestuck, and drocta ~ATH is my attempt at making it a real thing.
drocta ~ATH is limited to what is physically possible of course, because it actually exists. It is also limited to fit well with the comic, and how much of it I have created so far.
As such, so far all the programs that can be written in drocta ~ATH are text only, do not yet accept input (input in progress), and tend to be stupidly long.
It is however capable of computing anything a computer can given enough time and memory.
~ATH is based on objects, and the lives thereof.
For example, in homestuck, there are programs that relate things to the lifespan of a universe, or a person, etc.
Of course, in order to make an interpreter possible, we have to limit ourselves to virtual objects. Ones that do not actually exist.
References to these objects are stored in things called variables. You probably know what these are already, but if you don't, think of a variable as a box that can have a thing in it. Each box has a name. You can say "do something with whatever is in the box called "apple".
In ~ATH, every object is either "alive" or "dead". Note that it is the object that is alive or dead, not the variable that refers to the object.
Now onto the actual syntax!:
Currently(as of build 7), drocta ~ATH has 5 different commands: import, ~ATH(){}, .DIE();, print, and BIFURCATE.
First we will go over the import statement. The import statement has the purpose of creating a new variable and a new object. Unlike other operations that can create a new object, the object created by import is initially unrelated to all of the other objects.
The syntax of the import command is:
import anything other than semicolons here VARIABLENAME;
The things between import and the last space before the semicolon are ignored.
In future versions, the import statement might also do additional things, such as using things from other files. But for now it just initializes variables.
EXAMPLES:
If you wanted to make a new variable called BANANA, and you wanted the reader to know that BANANA is a fruit, you would say:
import FRUIT BANANA;
or you could say
import YELLOW FRUIT BANANA;
The things that go before the variable name don't actually matter, you can say
import ghsdgh hgsdkhg hgksdhg hgskdjg BANANA;
if you wanted.
Now for the next command: The eponymous ~ATH loop!
The syntax of it is as follows:
~ATH(VARNAME){ Some other code goes here }
What this does, is each time the code execution gets to the ~, it checks what the variable in the parentheses is, and then checks the object the variable points to. If the object is alive, it continues. If the object is dead, it skips to after the }. When the Code execution reaches the }, (that is, if it did not skip to after it), it will jump back to the corresponding ~. Code execution will keep going around in this loop until the object pointed to by the variable is not alive. In later versions, there may be an additional requirement that the } be followed by EXECUTE(code here); Where code here can be replaced with ~ATH code, NULL, or possibly a file name. But currently, this is not the case. Now onto the command BIFURCATE!: Bufurcate actually has 2 forms, the standard bifurcate, And the reverse bifurcate. The first of the two has syntax as follows:
BIFURCATE VARNAME1[VARNAME2,VARNAME3];
What this does, is it takes the object pointed to by the first variable, and determines two objects, which are stored in the other two variables. The two objects determined will always be the same for a particular object. If you for example say:
BIFURCATE V1[V2,V3]; V2.DIE(); BIFURCATE V1[V4,V5];
then V4 and V2 will point to the same object, which will be dead.
The other form of the BIFURCATE command has syntax as follows:
BIFURCATE [VAR1,VAR2]VAR3;
This is pretty much the inverse operation. That is, it undoes the other one. If you say for example:
BIFURCATE A[B,C]; BIFURCATE [B,C]D;
then A and D will point to the same object. To be clear, undoing the other is not the only time you can use it. It will take any two objects, and determine an object from those two. If there is already an object for the combination of those two, then that object is the resultant object. If none has been created yet (and the two arent split from something in that order), it will create a new object, which it will put in VAR3.
To be clear, if you say:
BIFURCATE A[B,C]; BIFURCATE [C,B]D;
A and D will NOT point to the same object, unless you create A such that B and C are the same. That is, if you say:
BIFURCATE [Y,Y]A; BIFURCATE A[B,C]; BIFURCATE [C,B]D;
A and D WILL point to the same object, and B and C will both point to the same object as Y (and as each other).
The Final command is print.
print is pretty simple, but its syntax might change somewhat.
Currently the syntax is:
print the text you want to output;
Note the semicolon. the semicolon is important.
So hello world would be
print Hello, World.;
SYNTAX EXPLANATION COMPLETE! PLEASE SUGGEST CLARIFICATIONS IF NECESSARY.
MESSAGE END.
This post will cover how to actually determine WHAT the user has typed, instead of just how long it is. It will also include how to interpret what the user enters as a binary number, so that its easier to type.
An Essential part of making it interpret binary numbers is making it double numbers repeatedly.
This actually has a few ways that can be done, so this is one of the first situations where coding style for this problem might differ from person to person. Because of this, I will say more than one way to do it.
The first way to do this it to copy the number twice, and then start from zero and add both of the copies. This is relatively inefficient, and would take
a copy thing, consisting of two bifurcates (which would take a little time)
where the size of the initial number is N, 2N normal bifurcates, 2N reverse bifurcates, and 4N lines relating to the actual loop
assuming each command takes the same amount of time (which is an oversimplification) this would take 9N+C line times. (C is a constant) This might be acceptable, but there is a more efficient and nicer looking way.
The second way is nicer looking, but still not the most effecient. However, when multiplying by a larger number(such as 3, or 4, or even large numbers), this method is part of what would be used.
The second method is essentially copying the number (using a reverse bifurcate and a normal bifurcate), and then adding the number to zero, except instead of each loop increasing the new number by one, it increases it by two. This is shorter, and it looks nicer. It also only takes half as many normal bifurcates. As a result, the number of steps it would take (again assuming each step is the same length) is 8N+C, instead of 9N+C
this one I will write out, but it is still not the best way:
//N is the number initially BIFURCATE [NULL,NULL]2NULL; BIFURCATE [N,N]G; BIFURCATE G[NCOPY,JUNK]; BIFURCATE 2NULL[RESULT,JUNK]; ~ATH(NCOPY){ BIFURCATE NCOPY[JUNK,NCOPY]; BIFURCATE [BLAH,RESULT]RESULT; BIFURCATE [BLAH,RESULT]RESULT; }
ok, so yeah. that takes N, and puts twice N into RESULT, but it is still inefficient.
A more efficient version is to copy the initial number, and add the number to itself. This way you only have to do half the number of reverse BIFURCATE statements. This is much more efficient, taking instead the steps:
a copy thing, consisting of two bifurcates (which would take a little time)
where the size of the initial number is N, N normal bifurcates, N reverse bifurcates, and 2N lines relating to the actual loop
This has 7N+C steps, which is a significant improvement. I think it is the fastest way to double a number in drocta ~ATH.
It is as follows (N is the number)
BIFURCATE [N,N]G; BIFURCATE G[NCOPY,RESULT]; ~ATH(NCOPY){ BIFURCATE NCOPY[JUNK,NCOPY]; BIFURCATE [BLAH,RESULT]RESULT; }
This is shortest and fastest solution I have found. If you find a shorter or faster method, please tell me.
Ok. Now we can double numbers. That is good. That is an important step. But we still haven't gotten user input to be read in any reasonable way.
Hang on, I'm GETTING TO THAT. GEEZ. (I'm kidding, no one has been complaining about my taking so long, other than myself)
Ok, so here goes:
To interpret the binary number input and convert it to a "number", we can follow the following algorithm:
start with zero.(this is before the loop)
If there are any characters left, double the number that is being created.
remove the first character from the remaining characters. If it is "1" or whatever symbol (or alternatively if it is not "0"), add one to the number that is being created. Otherwise, continue onto step 4 without doing anything first.
go back to the start of the loop (step 2)
Ok. thats the algorithm we are going to use. But I STILL haven't explained how to recognize what the next character is. Seriously what is up with that?
What you do is you bifurcate the rest of the input into [the next character,the rest of the input].
Now you have the next character. Then what you do is you reverse bifurcate it with some other object, and then you check whether that object is already dead or not.
But how do you make it so the combination is already dead? How do you get the object for the character before the user has even inputed it?
Answer: You don't. Not in the current version of drocta ~ATH anyway. You will have to tell the user to enter all the characters they will be using ahead of time. Yes this is horrible and stupid. No its not exactly like that in the comic. Its ~ATH what do you expect? :P
that might change in future versions, but I will try to stay backwards compatible with that.
but anyway, back to comparing it:
so you say something along the lines of:
import comparingobject CMP1; othercodehere makeNEQ1besomethingalive BIFURCATE [CMP1,CHAR]EQ1; BIFURCATE [NULL,NULL]2NULL; ~ATH(EQ1){ print yep, they are equal; BIFURCATE 2NULL[EQ1,NEQ1]; } ~ATH(NEQ1){ print nope, they are not equal; BIFURCATE 2NULL[NEQ1,JUNK]; }
in the othercodehere you get the character a head of time, and say BIFURCATE[CMP1,THECHARTHATMATCHESWITHCMP1]D; D.DIE();
That makes it so that it will go through the one section of code if the character is the right one, but something else if it is something else.
Which is what we want.
So to put it all together, and make the thing that interprets the input as a binary number(hold on tight(ok, what, why did I say that), this will be a long one(why am I talking like this?)):
import blah BLAH; print please enter whatever character you will be using for binary zero.; INPUT ZEROCHAR; BIFURCATE ZEROCHAR[ZEROCHAR,JUNK]; import chrcmp CMP0; BIFURCATE [CMP0,ZEROCHAR]D; D.DIE(); print please enter whatever character you will be using for binary one.; INPUT ONECHAR; BIFURCATE ONECHAR[ONECHAR,JUNK]; import chrcmp CMP1; BIFURCATE [CMP1,ONECHAR]D; D.DIE(); BIFURCATE [NULL,NULL]2NULL; BIFURCATE 2NULL[OUTNUM,JUNK]; print please input the binary number you want.(it will be converted to unary); INPUT BINNUM; ~ATH(BINNUM){ BIFURCATE [OUTNUM,OUTNUM]G; BIFURCATE G[NCOPY,OUTNUM]; ~ATH(NCOPY){ BIFURCATE NCOPY[JUNK,NCOPY]; BIFURCATE [BLAH,OUTNUM]OUTNUM; } BIFURCATE BINNUM[CHAR,BINNUM]; BIFURCATE [CMP0,CHAR]NEQ0; ~ATH(NEQ0){ BIFURCATE [BLAH,OUTNUM]OUTNUM; BIFURCATE 2NULL[NEQ0,JUNK]; } } print ok, going to print it out in unary, with each digit on one line. If the number you entered was large you might want to close the program instead of hitting enter.; INPUT JUNK; BIFURCATE [OUTNUM,OUTNUM]GOUTNUM; BIFURCATE GOUTNUM[OUTNUMCOPY,JUNK]; ~ATH(OUTNUMCOPY){ BIFURCATE OUTNUMCOPY[JUNK,OUTNUMCOPY]; print 1; } print Am I a terrible person for writing this?;
Oh gosh. I wish I could indent in tumblr. that is terrible to read. tumblr is a terrible source code editor.
One time someone called me a masochaist for writing this type of stuff.
And then we just have to put that together with the adding thing, and then maybe add a better way of outputting the number. maybe in binary.
HAHAHAHAH
ok, yeah, I'm going to put it together in the next post, not this one, because I have to homework now.(using the noun homework as a verb was intentional)
yeah. putting it together in the next post.
As always, if something was confusing, please ask for clarification.
If its not obvious, this blog will teach techniques in a version of ~ATH Specifically, drocta ~ATH. And yes, I'm serious. I believe that I probably am the author of the longest ( possibly up to third longest) ~ATH program. Specifically, bubble sort. Further, I believe I am the author of the first ~ATH interpreter. (I am the drocta of drocta ~ATH) Link here: http://www.mspaforums.com/showthread.php?50314-ATH-interpreter This blog is intended to serve as a tutorial on writing things in drocta ~ATH. First I will go over the syntax. Then how to make conditional like things. Then how to make finite loops. Then perhaps storing "numbers". Then copying "numbers" Then comparing "numbers" Then lists In such a way I intend to work our way up to you understanding how to write bubble sort in drocta ~ATH. After that, we might even implement brainf*** in it. Or a universal Turing machine. Of course, when I say "numbers", the quotes are there for a reason. Numbers are not built into drocta ~ATH. One has to build them. Now how do I tag things...? Ah, that's how. In case it wasn't clear, the interpreter for drocta ~ATH does not attempt the impossible. It cannot trigger the apocalypse. It's just a python script that interprets ~ATH scripts. Don't worry if you don't already know how to program. I intend to make the posts fairly accessible.
I've realized that recently, my tutorial posts have been too much code and not enough explanation. That was a mistake on my part, so I am going to go back now and give better explanations.
Also, I have started to make a table of contents page.
I figured that if someone wanted to read the tutorial after a significant part of it were finished, that they might have trouble, because it would kind of be in reverse order.
So TABLE OF CONTENTS AHOY!
Yeah.
So uh, any suggested changes to the format of the TOC page?
Why cant I mark this as a post that can be answered? I can let people photo reply, but once it goes in drafts I can't let people answer this question? Or is it too long?
What is with this interface?
I am still here, and I am wondering what my update schedule for this tutorial should be.
Its been a week or two since I last posted part of the tutorial, so I feel like I probably should have posted during that time, but I haven't.
I will probably post one today.
Do you have any suggestions for what type of update schedule I should keep on this tutorial?
Learn ~ATH turned 1 today!
yaaaay!
So I think that my explanations of things hasn't been very clear so far, and while I can't promise that they will improve, I do intend to teach programming in person at my school, which might help me to know how to make this tutorial better. Maybe, maybe not.
May things go well!
So, I just found this and have no clue what's going on. Could you maybe make, like, a simple guide to programming ~ATH? I understand how your python works, but not how to program ~ATH.
Hi!That is sort of what this blog was meant to be.I was trying to explain how to write programs in it, starting with “how do I represent numbers in it?” but then I started prioritizing other projects.I do want to get back to this one though.Perhaps I can give a brief summary in this ask response, and you can tell me what parts you would like clarification on? I will attempt that. I would appreciate it if you tell me what parts of this explanation you are unclear on, or say more about what you don’t understand about how to use drocta ~ATH.
(drocta ~ATH, as a reminder, is my interpretation of how ~ATH could work, which attempts to stay as true to the comic as it can, while still being turing complete, and also possible to implement in reality)In drocta ~ATH there are things called objects. Every object (except for possibly one depending on the specific version of the interpreter, but that isn’t an important detail.) is initially alive. Once an object dies, it cannot be made alive again.Every object has a left half, and a right half, which are both objects. Just because an object is dead does not mean that its left or right halves are dead. Similarly, just because both an object’s left and right halves are dead does not mean that the object is dead.
Also, for any two objects (possibly the same object), there is an object such that the left half of it is the first object, and the right half of it is the second object.
(skippable sidenote : Yes, this would mean that there are infinitely many objects, but they are only /really/ created by the interpreter when they become relevant, so really there are only ever finitely many that the computer is keeping track of)
A variable, in drocta ~ATH, refers to an object. However, it often does not always refer to the same object at different points during the program.
For example, suppose you want some variable to refer to a number which changes during the program. The way that the number which the variable refers to changes is by changing what object the variable refers to.
There are two ways to change what object a variable refers to.
1:Suppose you have three variables names VAR1, VAR2, VAR3.BIFURCATE VAR1[VAR2,VAR3];will take the left half of the object that VAR1 points to, and make VAR2 point to it, instead of whatever it was pointing to before, if anything, and it takes the right half, and makes VAR3 point to it instead of whatever it was pointing to before, if anything.
2:Again, with three variables VAR1, VAR2, VAR3:BIFURCATE [VAR1,VAR2]VAR3;will take the object pointed to by VAR1, and the object pointed to by VAR2, and finds the object such that the left half is the first one, and the right half is the second one, and makes VAR3 point to this object.
Also, when you initially declare an variable it makes a new object for it.
Now, in order to make an object dead, you take a variable (named, say, examplevariable) which currently points to it, and put examplevariable.DIE();and then the object will be dead. Note that this does not make examplevariable point to a different object, which is the same as the one it pointed to before except for being dead. This actually changes the object.In fact, this is the only operation that actually changes an object.
loops:How do you do control flow with this?Well, you use ~ATH loops.
A ~ATH loop looks like this:
~ATH(SOMEVARIABLENAME){//SOME CODE GOES HERE}
What this will do, is it will check if the object currently pointed to by SOMEVARIABLENAME is dead, and if it is not, it runs the code which is {between the curly brackets}. Then, it checks again if the object currently pointed to by SOMEVARIABLENAME is dead, and if not, runs the code inside again. This keeps on repeating until a time that it checks if SOMEVARIABLENAME currently points to an object which is dead, and it is, at which point the program keeps running after the curly brackets.
Note that which object the variable name points to may be changed by the code inside the curly brackets, and probably will be. Changing which object the variable is pointing to is the main way to make the loop exit.
speaking of, let’s get to numbers:
drocta ~ATH doesn’t have numbers as a built in thing. You have to make up your own numbers. But there is a sort of standard way to do so. Where by “standard” I mean, “it is the way that makes the most sense / is the most obvious, and is the way I usually do it”
if some object is the positive integer n, then an object x which has n as the right half, and some object which is alive as the left half, then that object x is n+1 .1 is an object where the left half is a dead object, and the right half is anything.
The reason for this is because this way you can make loops which do things n times, for n>0.
say the object representing n is pointed to by VAR1 , and VAR2 doesn’t point to anything you care about, but it does point to something which is alive, and VAR3 points to an object which represents 1, but you aren’t using it for anything else. You can make a loop like this:
~ATH(VAR2){BIFURCATE VAR1[VAR2,VAR1]; //decrease VAR1 by 1BIFURCATE [VAR2,VAR3]VAR3; /* increase VAR3 by 1, except if this is the last time through the loop, in which case this makes a small error, but one which will be fixed later *///put the stuff you want in the loop here.//Don’t do things to VAR1, VAR2, or VAR3 that you don’t undo though.
}BIFURCATE VAR3[JUNK,VAR3]; //removes the extra thing that was added to VAR3.
The result of this is that it will do the code you put in the middle n times, and that VAR3 will still store the number n afterwards.
Following processes like these, it is possible to do basically anything you could with a “counter machine / minsky machine” .
Fortunately, there are also things which make things a bit more convenient than using a minsky machine.
In much the same way that you can create numbers, you can also make lists.Just put the successive entries in the list as left halfs of objects, and have the right halves be the list as made so far. (so, basically, the left half is the first element, and the right half is the rest).A caveat here is to make sure that the left half is never a dead object, because that can make it so that the end of the list is detected pre-maturely. However, you might at some point (if you write a lot of drocta ~ATH, which, I am not certain why you would, haha) find that useful to cut the remaining part of a list off.
Of course, when I say to put something as the left half or right half of an object, feel free to switch that in each case. It doesn’t matter as long as you are consistent.
oh, I left out the parts about how to do input and output .
there are some example files on the github for you to check out which have that?
Please let me know if you have any further questions. I’m not sure which parts of this need clarification, so if part of it is unclear, you would be doing me and any other readers of my blog a favor by asking me to clarify them, so please do not hesitate to ask me to clarify any specific part, or to ask me any other question about ~ATH.
Thank you for your interest,
~drocta / ~hE
I couldn't help but notice that out of some of the best things you could do, no link to the download in the sidebar? You may want to do that...
uh, yes. that would be good to do.
I put a link in the about section, but I don't actually know how to put links in the sidebar outside of that.
do you think you could explain that for me?(I am not particularly experienced with tumblr)
EDIT:Nevermind, my friend from school told me where the feature is.
PRINT2 prints a string object as a string. If you give it something that is not a string object it will probably crash, or output the empty string.
Now, to import user defined functions use
importf filename as FUNCTIONNAME;
Why didn't I put this up earlier?
because I have other projects and because sometimes I am busy/lazy.
OK!
So to make a function to import, you pretty much make a ~ATH file like normal, except the object passed into the function is put into the variable ARGS, and when you want to pass the output object of the function out, you have it as an argument to the DIE method.
It can either be when saying THIS.DIE(RETURNOBJ); or ANYOTHERVARIABLE.DIE(RETURNOBJ);
The object your killing doesn't have to be the one tied to the life of the function or anything.
Oh I should clarify, the THIS variable/object will refer to the current function, not the file that called it.
It CAN be returned, and will be dead when you exit the function.
PROGRESS!
FUNCTIONS WORK.
LESS SPAGHETTI CODE.
although this starts to make me wonder if maybe this strays too far from what ~ATH is like in comic,
but w/e.
Ok, if you tried running a script with the interpreter, it might not have run properly. The part of the code that handles what part of the code is executed next is buggy. It is in the process of being fixed. Also, if python gives you a syntax error, it is probably because you are using a different version of python. Change raw_input to input And change print stuff to print(stuff) I will post an introduction to the syntax soon.
News and tutorials on drocta ~ATH by drocta. interpreter here A brief summary of how to write code in the language (but also see the table of contents)
38 posts