I am still intending to update this.
but I am not good at time management.
I have like 2 hours of free time after school, (because of certain inefficiencies on my part) so that's my stupid excuse.
I am working on writing some responses to some requests for clarification, and then I will do the second part of the converter TO binary.
the print command can have the end of a loop in.
The contents of the print command can be executed.
so if you say:
import blah A; import bleh B; ~ATH(A){ ~ATH(B){ print heh } ~ATH(NULL){ print giant frogs alert; B.DIE(); } }
it should print
"heh } ~ATH(NULL){ print giant frogs alert giant frogs alert"
this of course, is not particularly useful as far as I can tell, except possibly for quines, and possibly obfuscation. but really, is it possibly to write anything in ~ATH that isn't obfuscated?
speaking of not obfuscated, I have started working on adding a feature for user defined functions. I have it pretty much worked out how it will work, but I am not sure how I want to make the user DEFINE the functions. so I haven't been doing NOTHING with regards to this.
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.
I am planning two features to add.
one us user defined functions.
the second is, uh, it would let you make an object that would have itself as one of its components or one of the component of one of its components etc.?
the third one I am not sure if I think it is dumb yet, but I was thinking maybe functions being objects that you can bifurcate together to make functions.
which would allow for macros kind of?
which of these three features are good ideas, (as in, for each, it is a good idea)?
when we left off, we had code to interpret one binary number from user input, and output it as a unary number. In this post we will add the second user input, and maybe make a thing that converts from unary to binary, and then outputs it.
The code for that was the following:
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; }
ok, so what do we need to do after that?
Well we need to make it get two numbers, right?
Yes. Yes we do.
But getting one number was kind of long, wasn't it.
Luckily we don't have to have the entire thing there twice, much of it we can jusst have it in there once.
we COULD define a function, but I haven't added that to the interpreter yet, so yeah...
so a significant portion of that was initialization stuff that doesn't need to be duplicated. the first 14 lines in fact!
so pretty much we just duplicate everything but the first 14 lines.
gee, now I sound lazy for not writing this part earlier.
anyway, here goes:
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 first 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];
}
}
BIFURCATE [BLAH,OUTNUM]UINNUM1;
BIFURCATE UINNUM1[JUNK,UINNUM1];
BIFURCATE 2NULL[OUTNUM,JUNK];
print input the second binary number:;
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];
}
}
BIFURCATE [BLAH,OUTNUM]UINNUM2;
BIFURCATE UINNUM2[JUNK,UINNUM2];
BIFURCATE [UINNUM1,UINNUM1]CUINNUM1;
BIFURCATE CUINNUM1[SUM,JUNK];//haha, some junk
BIFURCATE [UINNUM2,UINNUM2]CUINNUM2;
BIFURCATE CUINNUM2[UINNUM2CPY,JUNK];
~ATH(UINNUM2CPY){
BIFURCATE UINNUM2CPY[JUNK,UINNUM2CPY];
BIFURCATE [BLAH,SUM]SUM;
}
print ok, going to print the sum out in unary, with each digit on one line. If the numbers you entered were large you might want to close the program instead of hitting enter.;
INPUT JUNK;
BIFURCATE [SUM,SUM]GSUM;
BIFURCATE GSUM[SUMCOPY,JUNK];
~ATH(SUMCOPY){
BIFURCATE SUMCOPY[JUNK,SUMCOPY];
print 1;
}
ok. That worked. I haven't made it convert the output to binary yet. I started this the day of the other post, but there was a bug I didnt get around to fixing in it that I didn't find the fix for until today.
that bug was that in the part where it changes the binary number to a unary number, the first time around, the unary number starts at zero and increases to what it should be...
...but I forgot to include the line to reset it back to zero for the second number.
but in works now.
I might make the part where it converts from unary to binary now instead of later, but I have to do stuff.
Sorry for having such a slow post rate, it is partly because I am busy and partly because I am lazy. mostly the [FORMER,LATTER].
hey, it adds the numbers that were entered in binary...
So a future improvement is to make it so it outputs it in binary as well.
Another possible future post is something that shouldn't work but the interpreter has a certain bug that might be amusing, and will not negatively affect many things.
specifically, if you have a "}" inside of a print statement, and you are jumping to the end of a loop, it will jump to the inside of the print statement, and execute the text as code. This is a bug, not a feature, so you should not rely on it when writing stuff. It might be fun to mess with though.
I might add user defined functions to the interpreter soon...
I don't feel that this post really explained much of anything, but I have to do stuff now, so I am going to post this, and possibly modify it later with clarifications.
Feel free to send me messages asking about how some part works.
Fixed the bug. The problem was that it was seeing
\n}\nD.DIE();
and it was checking if the text up to the next semicolon ended with .DIE() and if it did, using the stuff before the . as the variable name. When it should have been seeing the } and jumping back.
Also there may have been a problem with the {} matching. If so, that was fixed too. It was not the last part to be fixed.
BUT ANYWAY: The bug is fixed now.
runs in python 2.7
If you have a different version of python, and it is incompatible, please tell me. If a sufficient number of people want it in a different python version I might make a version of it for multiple python versions.
How do you use this?
Just to be super clear, though you probably understand this, “drocta ~ath” is not for practical purpose. It is purely an amusement.
That being said, to run this, you need to have python 2 installed. (Yes, currently most new python projects are in python 3. Unfortunately I haven’t gotten around to making any of the updates I’ve wanted to on this project, and it has been years since I’ve worked on it.)
To run it: download the github repository from https://github.com/drocta/TILDE-ATH
then, (probably from the command line, though running it in other ways may also work) navigate into the folder where you put all those files, use python 2 in order to run interp_2.py . [1] Then, it will allow you to type something in. It would be good if it gave some sort of prompt saying that it is accepting input, but it currently does not. What you have to type in is the file name of the drocta ~ath program that you want to run.
for example, you might type:
python interp_2.py looptest.~ATH
in order to run the program looptest.~ATH , and then you would see the output:that alternates between “APPLE” and “ORANGE” a number of times (like, 5 times I think).
If it isn’t working for you, let me know and I can try and help you troubleshoot what’s going on.
If you are asking, not “how do I run the programs in this language” but “how do I write programs in this language”, uh, read through the rest of this blog I guess. It isn’t complete, but the point of this blog was meant to be a tutorial for how the language works. If you have any particular questions about how to do a particular thing in the language, then ask that. But I don’t currently have time to re-do the whole project of this blog and put a tutorial for the language as a whole in one response to an ask.
P.S. I am currently in grad school for math (I made this language while in high school). I haven’t been doing all that much programming lately unfortunately.
([1] What’s that? “interp_2.py” is a weird name for the main file? Indeed it is. Originally I had “interp.py” and then before I started using git I made a new version which I called interp_2.py, and then, for basically no good reason, I kept that name for the file. If I go back to this at all, I suspect that I will change that to just “interp.py” or maybe “main.py” or something. idk.)
I have completed the syntax explanation post, and I think it is fairly clear now.
If you find any part of the post to be unclear, and that it requires further explanation, please say so so that I can improve it.
Now that that post is in an acceptable form, We can get on to writing our first few ~ATH programs.
print Hello, World.; THIS.DIE();
That wasn't so hard, was it?
I feel I should note that the syntax of the print command is not entirely finalized, it might change sometime later.
EXPLANATION:
The first line of the program says to output the text "Hello, World."
The 2nd line of the program says to end the program. This is because the variable THIS initially points to a object that is only alive when the program is running. If the object is ever not alive, the program stops.
oh gosh why is this a bullet-ed list I am not good with tumblr
To run a drocta ~ATH program, you need the interpreter (available from the github), and python 2.7 (the interpreter can be easily modified to run with python 3, but it is written to work in 2.7)
Open interp_2.py with python, and when the program comes up, type in the filename of the ~ATH program, and hit enter, this will run the ~ATH program.
With this example, it should output the text
Hello, World.
Now, of course, this is a relatively simple program, but at least its something.
Depending on how you are running the interpreter, the program might close immediately after outputting the text.
That might not be what we want.
To make the program not close until we specifically tell it to, we use the following:
print Hello, World.; ~ATH(THIS){ } THIS.DIE();
EXPLANATION:
The first line is the same as in the first program. It outputs "Hello, World."
The second line is different, this says to start a loop, which will continue until the object pointed to by the variable THIS is dead.
The third line says to go back to the corresponding ~ATH statement.
The fourth line is never executed, because the loop above it will continue until the object pointed to by THIS dies, and if that object dies the program ends. If it were to be executed it would make the object pointed to by THIS die, and the program would end as a result.
This program should be the same, except that it will keep running until you close it manually.
Now you have hello world written in two different ways!
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!
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.
In drocta ~ATH, the control flow (what part of the program is run when) is almost entirely determined by ~ATH loops.
The only case where it isn't is when the object initially pointed to by THIS dies. That ends the program immediately.
This post will show in more detail the basics of its usage.(also introduces the variable NULL)
Is there anything in this post that needs to be clarified?
In a program, you might want something to only happen if something else is true, or you might want it to happen provided that something had not happened.
In many programming languages you would use a command called if.
drocta ~ATH does not have an if statement.
Instead, you create a loop on an object, and inside the loop kill the object.
A little morbid, but isn't ~ATH always?
for example:
SOMECODEHERE ~ATH(SOMEVAR){ SOMEVAR.DIE(); SOMEOTHERSTUFF } SOMEOTHERSTUFF
However, this isn't the only way. There is another way that is likely preferable in most situations. I just thought this way was the most obvious, and would be an easy way to explain the other method, which is quite similar.
The loop doesn't exactly wait for the object to die, but rather repeats so long as the variable points to an object that is alive. The variable can be made to point to an object that is not alive, either by make the object it points to DIE(), or by making it so it points to a different object that is ALREADY DEAD.
(How can you expect to kill it, when it is ALREADY DEAD?!? haha)
So if the object you wanted the part of the script to run if it was alive was important, and you didn't want to kill it, you could just do this:
BIFURCATE [IMPORTANTOBJECTVAR,IMPORTANTOBJECTVAR]BLAH; BIFURCATE BLAH[V,V]; ~ATH(V){ BIFURCATE [V,NULL]V; BIFURCATE V[JUNK,V]; OTHER CODE TO ONLY EXECUTE IF IMPORTHATOBJECT IS ALIVE }
Thats nice to be able to do, isn't it.
In fact, it leads nicely into how to make loops that go around a fixed number of times.
suppose if you had
BIFURCATE [BLAH,NULL]V; ~ATH(V){ BIFURCATE V[BLAH,V]; DO OTHER STUFF, POSSIBLY WITH BLAH } MORE STUFF
V would initially be alive, so it would go into the loop, but then V would be made to point to the NULL object, which is dead, so it wouldn't loop the second time.(it would skip to after the loop
that would do the stuff in the loop once.
now what if you wanted to do it twice?
Just make it so it has to bifurcate the thing twice before moving on! Like so:
BIFURCATE [BLAH,NULL]V; BIFURCATE [BLAH,V]V; ~ATH(V){ BIFURCATE V[BLAH,V]; DO OTHER STUFF, POSSIBLY WITH BLAH } MORE STUFF
this way it will go through the loop, pop off the one side of V, doing the other stuff in the loop. V will still point to something alive after this, so it will do it again, but this time, when it pops off one side of V, the result will be the NULL object, so it will stop.
Thats a loop that goes around twice!
This can be extended to as many number of repetitions as follows:
BIFURCATE [BLAH,NULL]V; BIFURCATE [BLAH,V]V; BIFURCATE [BLAH,V]V; BIFURCATE [BLAH,V]V; ETCETERA BIFURCATE [BLAH,V]V; ~ATH(V){ BIFURCATE V[BLAH,V]; DO OTHER STUFF, POSSIBLY WITH BLAH } MORE STUFF
where the loop will go around however many blahs there are attached to the NULL, because it will keep popping the BLAHs of until it reaches NULL.
The variable V is being used to store how many more loops need to be executed, Which is a number.
V is being used to store a number.
You might be thinking something along the lines of
"Well this is all very nice, but that seems to only allow for loops that loop a predetermined amount of times."
NOT SO!
You can have another loop that makes a variable point to a number, which would then be in another loop! For example, the following will add two numbers in A and B, store the result in C, copy that result to CTEMP, and then print "some text" the ammount of times in CTEMP!
SOME CODE TO GET A AND B HERE import bluh BLAH; BIFURCATE [BLAH,A]ATEMP; BIFURCATE [BLAH,B]BTEMP; BIFURCATE ATEMP[JUNK,ATEMP]; BIFURCATE BTEMP[JUNK,BTEMP]; BIFURCATE [BLAH,NULL]C; BIFURCATE C[JUNK,C]; ~ATH(ATEMP){ BIFURCATE ATEMP[JUNK,ATEMP]; BIFURCATE [BLAH,C]C; } ~ATH(BTEMP){ BIFURCATE BTEMP[JUNK,BTEMP]; BIFURCATE [BLAH,C]C; } BIFURCATE [BLAH,C]CTEMP; BIFURCATE CTEMP[JUNK,CTEMP]; ~ATH(CTEMP){ BIFURCATE CTEMP[JUNK,CTEMP]; print some text; } print DONE!;
YAY! We just added two numbers together! In similar ways, we can also subtract, multiply, divide, etcetera!
if some of this was unclear I would appreciate requests for what needs to be clarified.
Is there anything in this post that needs clarification?
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