Topple
Topple, created by User:H33T33, was developed using C.
Topple (conditionally) ignores whitespace, which means you can cram everything into one line. Good luck with that though.
Overview
Unless otherwise specified, whitespace in any given code example is purely for organization.Command | Description | Example(s) | Output |
---|---|---|---|
.
|
"Admits” a given character
|
a. b. c.
|
None |
,
|
Outputs characters w/o admitting them | a,b,c,
|
abc
|
@
|
Outputs all admitted characters and deletes them | a.b.c. @
|
abc
|
&
|
Outputs all admitted characters without deleting them | a.b.c. &
|
abc
|
|
|
Deletes all admitted characters | a.b.c.| @
|
None |
:
|
Outputs an admitted character at a given index (deleted upon use)
|
a.b.c. 0:
|
a
|
;
|
Takes admitted character from a given index and copies it.
|
a.b.c. 0; @
|
abca
|
=
|
Defines variables
|
a=1
|
None |
^
|
Calls variables
|
a=1 a^. @
|
1
|
!
|
Takes user input | !. @
|
Whatever the user inputs |
?
|
Compares two values. Returns ‘1’ if the two are the same or ‘0’ if the two are not the same (last admitted characters, deleted upon use) | a.b.?. @
|
0
|
#
|
Returns a random number between 0 and 9 | #. @
|
0-9
|
<...>
|
FOR Loop, loops based on a given amount (last admitted character, deleted upon use) | 3.<a.@>
|
aaa
|
(...)
|
IF Statement, conditionally runs code based on a given character (last admitted character, deleted upon use) | 1.(a.@)
|
a
|
[...]
|
ELSE Statement, will run only if the last IF Statement did not | 0.(a.@)[b.@]
|
b
|
{...}
|
WHILE Loop, will run as long as the last admitted character (checked at the start of each loop) is non-zero | 1.{a.@}
|
aaaaaaaaaaa...
|
_..._
|
Used for commenting | _a.b.c.@_
|
None |
+
|
Increments an admitted character at a given index
|
1.2.3. 0+@
|
223
|
-
|
Decrements an admitted character at a given index
|
1.2.3. 0-@
|
023
|
*
|
Quits the program |
Special Characters
Character | Description |
---|---|
\
|
New Line (\n) |
Source Code
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <sys/time.h> #define MAX_SIZE 500 // Size of console, max amount of vals/vars, etc. Currently the best way I know to do this. char console[MAX_SIZE]; char vals[MAX_SIZE][MAX_SIZE]; // Values char vars[MAX_SIZE][2]; // Variables ([0]=name,[1]=value) int nest = 0; // Keeps track of nested IFs, FORs, etc. while processing them. Ensures that code outside of an IF or FOR is not included int skip = 0; // When processing loops/IFs, will be used to count how many characters need to be skipped (only code within IFs, Loops, etc. will skip) int ifRun = 1; // Bool, If 0, ELSE code ([] brackets) will run. Otherwise, nothing happens. int commenting = 0; // Bool, Allows for commenting w/ proper punctuation char input; //All Vars above MUST be public or some pieces of the program may not work properly, specifically loops and IFs //No idea if this will cause problems later. But if it works, it works void clear() { printf("\e[1;1H\e[2J"); } long long timeInMilliseconds(void) { // Returns the current time in milliseconds struct timeval tv; gettimeofday(&tv,NULL); return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000); } int readFile() { // Reads a given file FILE* fptr; fptr = fopen("main.txt", "r"); for(int i = 0; i<MAX_SIZE; i++) console[i]=fgetc(fptr); return 0; } char proCon(char In[MAX_SIZE]) { // Process Console for(int i = 0; i < MAX_SIZE; i++) { // Skips characters used in an IF, ELSE, or FOR if(!commenting) { if(skip) { skip--; continue; } if(In[i]=='.') { // "Admits" a given character for(int j = 0; j<MAX_SIZE; j++) { if(*vals[j] == '\0') { if(In[i-1] == '\\') { *vals[j] = '\n'; } else if(In[i-1] == '!') { // Takes User Input scanf(" %c",&input); *vals[j] = input; } else if(In[i-1]=='?') { // IF statement // Conditional True/False for(int j = 0; j < MAX_SIZE; j++) { if(*vals[j]=='\0') { if(*vals[j-2]==*vals[j-1]) { *vals[j-2] = '1'; // True } else { *vals[j-2] = '0'; // False } *vals[j-1] = '\0'; break; } } } else if(In[i-1]=='#') { // Returns a random number (0 - 9) srand(timeInMilliseconds()); // Sets seed for the random stuff int num1=rand()%10; int num2=num1; while(num1 == num2) { // Continuously randomizing num1 until it is no longer the same as num2. srand(timeInMilliseconds()); num1 = rand()%10; } *vals[j] = num1+'0'; break; } else if(In[i-1]=='^') { // Calls variables for(int j = 0; j<MAX_SIZE; j++) { if(vars[j][0]==In[i-2]) { for(int k = 0; k<MAX_SIZE; k++) { if(*vals[k]=='\0') { *vals[k] = vars[j][1]; break; } } break; } } } else if(In[i-1]=='+') { // Increments an admitted character at a given index by 1 *vals[In[i-2]-'0']+=1; } else if(In[i-1]=='-') { // Decrements an admitted character at a given index by 1 *vals[In[i-2]-'0']-=1; } else { *vals[j] = In[i-1]; } break; } } } if(In[i]==',') { // Output characters w/o admitting them, but cannot use commands or special characters if(In[i-1]=='\\') { printf("\n"); } else { printf("%c",In[i-1]); } } else if(In[i-1]=='<') { // FOR Loop nest++; int r=0; for(int j = 0; j < MAX_SIZE; j++) { if(*vals[j] == '\0') { r = *vals[j-1]-'0'; *vals[j-1]='\0'; break; } } char subCon[MAX_SIZE]; for(int k = 0; k<MAX_SIZE; k++) subCon[k]='\0'; for(int j = 0; In[i+j]!='\0'; j++) { if(In[i+j]=='<') nest++; if(In[i+j]=='>') nest--; if(!nest) break; subCon[j] = In[i+j]; skip+=j+1; } //printf("%d\n",r); for(int j = 0; j < r && j>=0; j++) { proCon(subCon); } } else if(In[i-1]=='(') { // IF Statement int condition=0; nest++; for(int j = 0; j < MAX_SIZE; j++) { // Finds last admitted character and checks if it's a non-zero value. if(*vals[j] == '\0') { condition = (*vals[j-1]!='0'); *vals[j-1] = '\0'; break; } } char subCon[MAX_SIZE]; for(int j = 0; j<MAX_SIZE; j++) subCon[j]='\0'; for(int j = 0; In[i+j]!='\0'; j++) { if(In[i+j]=='(') nest++; if(In[i+j]==')') nest--; if(!nest) { skip+=j+1; break; } subCon[j] = In[i+j]; } if(condition) { proCon(subCon); ifRun=1; } else { ifRun=0; } } else if(In[i-1]=='[') { // ELSE Statement. If the last IF or WHILE Statement did not run, this will run in place of it. nest++; char subCon[MAX_SIZE]; for(int j = 0; j<MAX_SIZE; j++) subCon[j]='\0'; for(int j = 0; In[i+j]!='\0'; j++) { if(In[i+j]=='[') nest++; if(In[i+j]==']') nest--; if(!nest) { skip+=j+1; break; } subCon[j] = In[i+j]; } if(!ifRun) { proCon(subCon); ifRun=1; } } else if(In[i-1]=='{') { int breakLoop=0; nest++; char subCon[MAX_SIZE]; for(int j = 0; j<MAX_SIZE; j++) subCon[j]='\0'; for(int j = 0; In[i+j]!='\0'; j++) { if(In[i+j]=='{') nest++; if(In[i+j]=='}') nest--; if(!nest) { skip+=j+1; break; } subCon[j] = In[i+j]; } while(1) { for(int j = 0; j < MAX_SIZE; j++) { if(*vals[j]=='\0') { breakLoop = (*vals[j-1]!='0'); *vals[j-1]='\0'; break; } } if(!breakLoop) { break; } else { proCon(subCon); } breakLoop=0; } } else if(In[i-1]=='@') { // Outputs all admitted characters, then clears for(int j = 0; j<MAX_SIZE; j++) { printf("%c",*vals[j]); *vals[j] = '\0'; } } else if(In[i-1]=='&') { // Outputs all admitted characters w/o clearing for(int j = 0; j<MAX_SIZE; j++) { printf("%c",*vals[j]); } } else if(In[i-1]=='|') { // Clears all admitted data for(int j = 0; j<MAX_SIZE; j++) *vals[j] = '\0'; } else if(In[i-1]==':') { // Outputs admitted character at a given index *vals[In[i-2]-'0'] = '\0'; for(int j = In[i-2]-'0'; j < MAX_SIZE; j++) *vals[j]=*vals[j+1]; } else if(In[i-1]==';') { // Pulls an admitted value from a given index and admits it again for(int j = 0; j < MAX_SIZE; j++){ if(*vals[j]=='\0'){ *vals[j] = *vals[In[i-2]-'0']; break; } } } else if(In[i-1]=='=') { // Defines variables for(int j = 0; j<MAX_SIZE; j++) { if(vars[j][0]=='\0' || vars[j][0]==In[i-2]) { vars[j][0] = In[i-2]; vars[j][1] = In[i]; break; } } } else if(In[i-1]=='~') { clear(); } else if(In[i-1]=='*') { // Quits the program exit(0); } } if(In[i]=='_') { // Toggles commenting commenting = !commenting; } } } int main() { for(int i = 0; i < MAX_SIZE; i++) { // Clears values and variables before use for(int j = 0; j < MAX_SIZE; j++) { vals[i][j] = '\0'; vars[i][j] = '\0'; } } readFile(); printf("Output:\n"); proCon(console); return 0; }
Examples of the syntax and how to use the language will be added soon
I am unsure what to do with the below as this is my first time doing this. I added WHILE loops, so it should be Turing complete now, but I'll leave that to the professionals to decide.
Computational class
In its current iteration, Topple is total, but could be Turing complete if it had access to an infinite loop construct.
The admitted characters list can be used as the word of a tag system. An initial word can be admitted by simply admitting each character in turn. To check a character to see which rule to produce, the pattern 0;. C. ? (x. y. z.)
can be used for each rule. The C
is the character which produces the rule when at the start of the word, and x. y. z.
are the characters to add to the end of the word. The pattern copies the start of the word, pushes the character to check, then compares them whilst deleting them, pushing 1/0 to the word. The brackets then remove that last character from the word and conditionally perform the rule. This only ever changes the word if the rule was matched, and only according to the rule.
A list of tag system rules can be translated into Topple by using the above construction for each rule. At the end of the list m many 0:
can be used to delete characters from the start of the word. For a 2-tag system 0: 0:
would be used.
There are likely several other equally powerful reduction schemes for Topple (perhaps using variables), however, the language is total. There is no way to perform an infinite loop, as the only loop available (the FOR loop) is only able to loop a finite amount of times.