Topple

From Esolang
Jump to navigation Jump to search

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
  • Does not ignore whitespace
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)
  • Does not ignore whitespace
a.b.c. 0: a
; Takes admitted character from a given index and copies it.
  • Does not ignore whitespace
a.b.c. 0; @ abca
= Defines variables
  • Does not ignore whitespace
a=1 None
^ Calls variables
  • Does not ignore whitespace
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
  • Does not ignore whitespace
1.2.3. 0+@ 223
- Decrements an admitted character at a given index
  • Does not ignore whitespace
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.