Topple/Topple 1/Source (C++)

From Esolang
Jump to navigation Jump to search

←Back

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cctype>
#include <string>
#include <ctime>

#define CLEAR() printf("\e[1;1H\e[2J");

typedef struct{
    char name;
    char val;
}var;

void read_file(FILE* file, char dest[]){ // Reads the contents of a given file into a given variable
    int pos=0;
    char ch;
    while((ch=fgetc(file))!=EOF){
        dest[pos]=ch;
        pos++;
    }
}
long long file_size(std::string file_name){
    char ch;
    int size=0;
    FILE* file = fopen(file_name.c_str(),"r");
    while((ch=fgetc(file))!=EOF && ch!='\0' && ch!=0)++size;
    fclose(file);
    return size;
}

unsigned long long random(int min, int max){
    srand(static_cast<unsigned int>(time(0)));
    int num1=min+(time(0)%max);
    int num2=num1;
    while(num1==num2){
        std::cout<<num1<<" "<<num2;
        num1=min+(time(NULL)%max);
    }
    return num1;
}

long arr_len(char data[]){ // Returns the length of a given char array
    int size=0;
    for(int i=0;data[i]!='\0';i++)++size;
    return size;
}

long var_amnt(var vars[]){ // Returns length of a given variable array
    int size=0;
    for(int i=0;vars[i].name!='\0';i++)++size;
    return size;
}

long var_loc(var vars[], char var_name){ // Returns the index of a given variable
    for(int i=0;vars[i].name!='\0';i++){
        if(vars[i].name==var_name) return i;
    }
    return -1;
}

void print(char data[],int delete_values){ // Outputs data and, if 'delete_values' is true, "deletes" it
    for(int i=0; data[i]!='\0'; i++){
        std::cout<<(char)data[i];
        if(delete_values) data[i]='\0';
    }
}
namespace topple_data{
    // array size is temporary, probably
    char held_data[256];
    var variables[64];
}

//when true, characters are ignored until false
int commenting=0;

void process_code(char code[],int size,int start,int end){ // Interprets a given char array as Topple code
    
    int sub_start=start; // start of code blocks
    int sub_end=end; // end of code blocks
    
    int condition=0; // if condition, also acts as loop amount and while condition
    int nest=0; // keeps track of nested ifs/loops
    

    for(int let=start; let<size && let<end; let++){
        if(code[let]=='_') ::commenting=!::commenting;
        if(::commenting)continue; // toggles commenting on/off
        switch(code[let]){
            case '.': // Activates command characters, admits non-command characters
                if(code[let-1]=='#') // admits a random number between 0 and 9
                    topple_data::held_data[arr_len(topple_data::held_data)]=random(0,9)+'0';
                else if(code[let-1]=='^'){ // calls a variable by a given name
                    topple_data::held_data[arr_len(topple_data::held_data)]=topple_data::variables[var_loc(topple_data::variables,code[let-2])].val;
                }
                else if(code[let-1]=='?'){ // returns whether two given values are equal
                    topple_data::held_data[arr_len(topple_data::held_data)-2]=(topple_data::held_data[arr_len(topple_data::held_data)-1]==topple_data::held_data[arr_len(topple_data::held_data)-2])+'0';
                    topple_data::held_data[arr_len(topple_data::held_data)-1]='\0';
                }
                else if(code[let-1]=='!'){
                    std::cin>>topple_data::held_data[arr_len(topple_data::held_data)];
                }
                else if(code[let-1]=='\\') // next line (\n)
                    topple_data::held_data[arr_len(topple_data::held_data)]='\n';
                else topple_data::held_data[arr_len(topple_data::held_data)]=code[let-1];
                break;
            
            // output
            case ',': // outputs the previous character w/o admitting
                std::cout<<code[let-1];
                break;
            case '@': // outputs held data and deletes them
                print(topple_data::held_data,1);
                break;
            case '&': // outputs held data w/o deleting them
                print(topple_data::held_data,0);
                break;

            // IFs/Loops
            case '(': // if statement
                sub_start=let;
                ++nest;
                condition=(topple_data::held_data[arr_len(topple_data::held_data)-1]!='0');
                topple_data::held_data[arr_len(topple_data::held_data)-1]='\0';
                for(int space=let+1; space<size && space<end && nest; space++){ // finds the end of a code block
                /* Turn to function somehow, used elsewhere */
                    ++let;
                    if(code[space]=='(')++nest;
                    else if(code[space]==')')--nest;
                    sub_end=space;
                }
                if(condition)process_code(code,size,sub_start+1,sub_end);
                break;
            case '[': // else statement
                sub_start=let;
                ++nest;
                for(int space=let+1; space<size && space<end && nest; space++){
                    ++let;
                    if(code[space]=='[')++nest;
                    else if(code[space]==']')--nest;
                    sub_end=space;
                }
                if(!condition) process_code(code,size,sub_start+1,sub_end);
                break;
            case '<': // for loop
                sub_start=let;
                ++nest;
                condition=(topple_data::held_data[arr_len(topple_data::held_data)-1])-'0';
                topple_data::held_data[arr_len(topple_data::held_data)-1]='\0';
                for(int space=let+1; space<size && space<end && nest; space++){
                    ++let;
                    if(code[space]=='<')++nest;
                    else if(code[space]=='>')--nest;
                    sub_end=space;
                }
                for(int i=0; i<condition; i++) process_code(code,size,sub_start+1,sub_end);
                break;
            case '{': // while loop
                sub_start=let;
                ++nest;
                condition=topple_data::held_data[arr_len(topple_data::held_data)-1];
                topple_data::held_data[arr_len(topple_data::held_data)-1]='\0';
                for(int space=let+1; space<size && space<end && nest; space++){
                    ++let;
                    if(code[space]=='<')++nest;
                    else if(code[space]=='>')--nest;
                    sub_end=space;
                }
                while(topple_data::variables[var_loc(topple_data::variables,condition)].val!='0')process_code(code,size,sub_start+1,sub_end);
                break;

            // variable management
            case '=': // (re)defines variables
                if(var_loc(topple_data::variables,code[let-1])==-1){
                    topple_data::variables[var_amnt(topple_data::variables)].val=code[let+1];
                    topple_data::variables[var_amnt(topple_data::variables)].name=code[let-1];
                }else{
                    topple_data::variables[var_loc(topple_data::variables,code[let-1])].val=code[let+1];
                }
                break;
            case '^': // increments/decrements variables
                if(code[let+1]=='+') topple_data::variables[var_loc(topple_data::variables,code[let-1])].val++;
                else if(code[let+1]=='-') topple_data::variables[var_loc(topple_data::variables,code[let-1])].val--;
                break;

            // index-dependent commands
            case ':':
                std::cout<<topple_data::held_data[code[let-1]-'0'];
                break;
            case ';':
                topple_data::held_data[arr_len(topple_data::held_data)]=topple_data::held_data[code[let-1]-'0'];
                break;

            // other
            
            case '~': // deletes admitted values
                for(int i=0; i<arr_len(topple_data::held_data); i++) topple_data::held_data[i]='\0';
            case '|': // clears the console
                CLEAR();
                break;
            case '*': // exits the program
                exit(topple_data::held_data[arr_len(topple_data::held_data)-1]);
                break;
        }
    }
}
int main(){
    FILE* file = fopen("main.topp","r");
    
    int size = file_size("main.topp");
    
    char code[size];
    read_file(file,code);
    
    process_code(code,size,0,arr_len(code));
    fclose(file);
    return 0;
}