view interps/glass/builtins.cc @ 12500:e48c08805365 draft default tip

<b_jonas> ` learn \'The password of the month is Cthulhuquagdonic Mothraquagdonic Narwhalicorn.\' # https://logs.esolangs.org/libera-esolangs/2024-04.html#lKE Infinite craft
author HackEso <hackeso@esolangs.org>
date Wed, 01 May 2024 06:39:10 +0000
parents 859f9b4339e6
children
line wrap: on
line source

/*
 * Copyright (c) 2005  Gregor Richards
 *
 * This file is part of Glass.
 * 
 * Glass is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * Glass is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Glass; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <cstdio>
#include <iostream>
#include <sstream>
using namespace std;

#include "builtins.h"
#include "func.h"
#include "glass.h"
#include "klass.h"
#include "klassi.h"
#include "parseq.h"
#include "variable.h"

#define POP \
{ \
    if (mainStack.size() != 0) { \
        delete mainStack[0]; \
        mainStack.pop_front(); \
    } \
}

char builtinDefinitions[] = "{A \
[a~A.a~] \
[s~A.s~] \
[m~A.m~] \
[d~A.d~] \
[(mod)~A.mod~] \
[f~A.f~] \
[e~A.e~] \
[(ne)~A.ne~] \
[(lt)~A.lt~] \
[(le)~A.le~] \
[(gt)~A.gt~] \
[(ge)~A.ge~] \
} \
{S \
[l~S.l~] \
[i~S.i~] \
[(si)~S.si~] \
[a~S.a~] \
[d~S.d~] \
[e~S.e~] \
[(ns)~S.ns~] \
[(sn)~S.sn~] \
} \
{V \
[n~V.n~] \
[d~V.d~] \
} \
{O \
[o~O.o~] \
[(on)~O.on~] \
} \
{I \
[l~I.l~] \
[c~I.c~] \
[e~I.e~] \
[n~I.n~] \
} \
{(Debug) \
[(cl)~Debug.cl~] \
[(fl)~Debug.fl~] \
[(fc)~Debug.fc~] \
[s~Debug.s~] \
}";


#define BUILTIN(A, B) else if (which == A && mainStack.size() >= B)
void doBuiltin(string which)
{
    if (0) {
    } BUILTIN("A.a", 2) {
        mainStack[1]->nval = mainStack[1]->nval + mainStack[0]->nval;
        POP;
    } BUILTIN("A.s", 2) {
        mainStack[1]->nval = mainStack[1]->nval - mainStack[0]->nval;
        POP;
    } BUILTIN("A.m", 2) {
        mainStack[1]->nval = mainStack[1]->nval * mainStack[0]->nval;
        POP;
    } BUILTIN("A.d", 2) {
        if (mainStack[0]->nval != 0)
            mainStack[1]->nval = mainStack[1]->nval / mainStack[0]->nval;
        POP;
    } BUILTIN("A.mod", 2) {
        long long a = (long long) mainStack[1]->nval;
        long long b = (long long) mainStack[0]->nval;
        if (b != 0)
            mainStack[1]->nval = a % b;
        POP;
    } BUILTIN("A.f", 1) {
        mainStack[0]->nval = (long long) mainStack[0]->nval;
    } BUILTIN("A.e", 2) {
        mainStack[1]->nval = mainStack[1]->nval == mainStack[0]->nval;
        POP;
    } BUILTIN("A.ne", 2) {
        mainStack[1]->nval = mainStack[1]->nval != mainStack[0]->nval;
        POP;
    } BUILTIN("A.lt", 2) {
        mainStack[1]->nval = mainStack[1]->nval < mainStack[0]->nval;
        POP;
    } BUILTIN("A.le", 2) {
        mainStack[1]->nval = mainStack[1]->nval <= mainStack[0]->nval;
        POP;
    } BUILTIN("A.gt", 2) {
        mainStack[1]->nval = mainStack[1]->nval > mainStack[0]->nval;
        POP;
    } BUILTIN("A.ge", 2) {
        mainStack[1]->nval = mainStack[1]->nval >= mainStack[0]->nval;
        POP;
    } BUILTIN("S.l", 1) {
        mainStack[0]->nval = mainStack[0]->sval.length();
        mainStack[0]->type = VAR_NUMBER;
        mainStack[0]->sval = "";
    } BUILTIN("S.i", 2) {
        if (mainStack[0]->nval >= 0 &&
            mainStack[0]->nval < mainStack[1]->sval.length()) {
            mainStack[1]->sval = mainStack[1]->sval[(int) mainStack[0]->nval];
        } else {
            mainStack[1]->sval = "";
        }
        POP;
    } BUILTIN("S.si", 3) {
        if (mainStack[1]->nval >= 0 &&
            mainStack[1]->nval < mainStack[2]->sval.length() &&
            mainStack[0]->sval.length() > 0) {
            mainStack[2]->sval[(int) mainStack[1]->nval] = mainStack[0]->sval[0];
        }
        POP; POP;
    } BUILTIN("S.a", 2) {
        mainStack[1]->sval += mainStack[0]->sval;
        POP;
    } BUILTIN("S.d", 2) {
        mainStack[0]->sval = mainStack[1]->sval.substr((int) mainStack[0]->nval);
        mainStack[0]->type = VAR_STRING;
        mainStack[1]->sval = mainStack[1]->sval.substr(0, (int) mainStack[0]->nval);
    } BUILTIN("S.e", 2) {
        mainStack[1]->nval = (mainStack[1]->sval == mainStack[0]->sval);
        mainStack[1]->type = VAR_NUMBER;
        mainStack[1]->sval = "";
        POP;
    } BUILTIN("S.ns", 1) {
        mainStack[0]->sval = (char) mainStack[0]->nval;
        mainStack[0]->type = VAR_STRING;
    } BUILTIN("S.sn", 1) {
        if (mainStack[0]->sval.length() > 0) {
            mainStack[0]->nval = mainStack[0]->sval[0];
        } else {
            mainStack[0]->nval = 0;
        }
        mainStack[0]->type = VAR_NUMBER;
        mainStack[0]->sval = "";
    } BUILTIN("V.n", 0) {
        // find one
        unsigned int i;
        stringstream nm;
        for (i = 1; i != 0; i++) {
            // check this name ...
            nm.str("");
            nm << "Anonymous" << i;
            if (globalVars.find(nm.str()) == globalVars.end()) {
                // it's free
                globalVars[nm.str()] = new Variable();
                mainStack.push_front(new Variable(VAR_VARIABLEP, nm.str()));
                return;
            }
        }
        // uh oh!
        mainStack.push_front(new Variable());
    } BUILTIN("V.d", 1) {
        // TODO
#ifndef IRC
    } BUILTIN("O.o", 1) {
        cout << mainStack[0]->sval;
        fflush(stdout);
        POP;
    } BUILTIN("O.on", 1) {
        cout << mainStack[0]->nval;
        fflush(stdout);
        POP;
#else
    } BUILTIN("O.o", 1) {
        IRC_o += mainStack[0]->sval;
        POP;
    } BUILTIN("O.on", 1) {
        stringstream IRC_os;
        IRC_os << mainStack[0]->nval;
        IRC_o += IRC_os.str();
        POP;
#endif
#ifndef IRC
    } BUILTIN("I.l", 0) {
        char line[1025];
        string sline;
        
        line[1024] = '\0';
        line[0] = '\0';
        fgets(line, 1024, stdin); // ignore errors purposely
        sline = line;
        
        mainStack.push_front(new Variable(VAR_STRING, sline));

    } BUILTIN("I.c", 0) {
        int ic = getchar();
        string ics;
        
        if (ic == EOF) ic = 0;
        ics = ic;
        
        mainStack.push_front(new Variable(VAR_STRING, ics));

    } BUILTIN ("I.n", 0) {
        int in;
        int inn;
        scanf ("%d",&in);
        inn = in;
        mainStack.push_front(new Variable(VAR_NUMBER, inn));

    } BUILTIN("I.e", 0) {
        if (feof(stdin) || ferror(stdin)) {
            mainStack.push_front(new Variable(VAR_NUMBER, 1.0));
        } else {
            mainStack.push_front(new Variable(VAR_NUMBER, 0.0));
        }
#else
    } BUILTIN("I.l", 0) {
        mainStack.push_front(new Variable(VAR_STRING, ""));
    } BUILTIN("I.c", 0) {
        mainStack.push_front(new Variable(VAR_STRING, ""));
    } BUILTIN("I.e", 0) {
        mainStack.push_front(new Variable(VAR_NUMBER, 1.0));
#endif
    } BUILTIN("Debug.cl", 0) {
        map<string,Variable *>::iterator svari;
        for (svari = globalVars.begin(); svari != globalVars.end(); svari++) {
            if (svari->second->type == VAR_KLASS) {
#ifndef IRC
                cout << svari->first << " ";
#else
                IRC_o += svari->first + " ";
#endif
            }
        }
    } BUILTIN("Debug.fl", 1) {
        if (mainStack[0]->type != VAR_STRING) { POP; return; }
        if (globalVars.find(mainStack[0]->sval) != globalVars.end()) {
            Klass *tolist = globalVars[mainStack[0]->sval]->kval;
            map<string,Func *>::iterator sfuni;
            for (sfuni = tolist->functions.begin(); sfuni != tolist->functions.end(); sfuni++) {
#ifndef IRC
                cout << sfuni->first << " ";
#else
                IRC_o += sfuni->first + " ";
#endif
            }
        }
        POP;
    } BUILTIN("Debug.fc", 2) {
        if (mainStack[0]->type != VAR_STRING ||
            mainStack[1]->type != VAR_STRING) { POP; POP; return; }
        
        if (globalVars.find(mainStack[1]->sval) != globalVars.end()) {
            Klass *tolist = globalVars[mainStack[1]->sval]->kval;
            if (tolist->functions.find(mainStack[0]->sval) != tolist->functions.end()) {
                Func *ftolist = tolist->functions[mainStack[0]->sval];
                
                // now output it all
                string cont = ftolist->contents->dump();
#ifndef IRC
                cout << cont;
#else
                IRC_o += cont;
#endif
            }
        }
        POP; POP;
    } BUILTIN("Debug.s", 0) {
        unsigned int ui;
        stringstream dso;
        for (ui = 0; ui < mainStack.size(); ui++) {
            switch (mainStack[ui]->type) {
                case VAR_VARIABLEP:
                    dso << "(" << mainStack[ui]->sval << ")";
                    break;
                    
                case VAR_NUMBER:
                    dso << "<" << mainStack[ui]->nval << ">";
                    break;
                    
                case VAR_STRING:
                    dso << "\"" << mainStack[ui]->sval << "\"";
                    break;
                    
                case VAR_KLASS:
                    dso << "(" << mainStack[ui]->kval->name << "*:c)";
                    break;
                    
                case VAR_KLASSI:
                    dso << "(" << mainStack[ui]->kival->of->name << "*:ci)";
                    break;
                    
                case VAR_FUNC:
                    dso << "(" << mainStack[ui]->fval->name << "*:f)";
                    break;
                    
                case VAR_FUNCI:
                    dso << "(" << mainStack[ui]->kival->of->name << "." <<
                    mainStack[ui]->fval->name << "*:f)";
                    break;
            }
        }
#ifndef IRC
        cout << dso.str();
#else
        IRC_o += dso.str();
#endif
    }
}