SmallCore-1.0/
object $root;

var $root name = "Root Class";

public method .name() {
    arg @args;
    
    if (args)
        name = args[1];
    return name || "(unnamed)";
};

public method .add_var(): nooverride {
    arg @args;
    
    return (> add_var(@args) <);
};

public method .clear_var() {
    arg @args;
    
    return (> clear_var(@args) <);
};

public method .del_var(): nooverride {
    arg name;
    var n, obj;
    
    (> del_var(name) <);
};

public method .variables() {
    return variables();
};

public method .add_method() {
    arg @args;
    
    return (> add_method(@args) <);
};

public method .list_method() {
    arg @args;
    
    return (> list_method(@args) <);
};

public method .del_method() {
    arg name;
    
    (> del_method(name) <);
};

public method .find_method(): nooverride {
    arg name;
    
    return (> find_method(name) <);
};

public method .find_next_method(): nooverride {
    arg name, after;
    
    return (> find_next_method(name, after) <);
};

public method .method_bytecode() {
    arg method;
    
    return (> method_bytecode(method) <);
};

public method .method_access(): nooverride {
    arg method;
    
    return (> method_access(method) <);
};

public method .method_info(): nooverride {
    arg @args;
    
    return (> method_info(@args) <);
};

public method .method_flags(): nooverride {
    arg method;
    
    return (> method_flags(method) <);
};

public method .methods() {
    return methods();
};

public method .rename_method() {
    arg now, new;
    
    return (> rename_method(now, new) <);
};

public method .set_method_access(): nooverride {
    arg method, state;
    
    return (> set_method_access(method, state) <);
};

public method .set_method_flags(): nooverride {
    arg method, flags;
    
    return set_method_flags(method, flags);
};

public method .ancestors(): nooverride {
    arg @args;
    
    return ancestors(@args);
};

public method .chparents() {
    arg parents;
    
    chparents(parents);
};

public method .create() {
    arg @name;
    var what, pname, n;
    
    what = (> create([this()]) <);
    if ((!name) || (type((| what.set_objname(name[1]) |)) == 'error)) {
        pname = tostr((what.parents())[1]).subrange(2);
        n = 1;
        while ((| lookup(tosym((pname + "_") + n)) |))
            n = n + 1;
        what.set_objname(tosym((pname + "_") + n));
    }
    return what;
};

public method .data() {
    arg @args;
    
    return (> data(@args) <);
};

public method .del_objname() {
    arg @args;
    
    return (> del_objname(@args) <);
};

public method .destroy() {
    arg @args;
    
    return (> destroy(@args) <);
};

public method .children(): nooverride {
    return children();
};

public method .has_ancestor() {
    arg @args;
    
    return (> has_ancestor(@args) <);
};

public method .lookup() {
    arg @args;
    
    return (> lookup(@args) <);
};

public method .objname(): nooverride {
    arg @args;
    
    return (> objname(@args) <);
};

public method .objnum(): nooverride {
    return objnum();
};

public method .parents(): nooverride {
    arg @args;
    
    return parents();
};

public method .set_objname() {
    arg objname;
    
    objname = tosym(tostr(objname).lowercase());
    if (objname == (| objname() |))
        return;
    return (> set_objname(objname) <);
};

public method .object_size() {
    return size();
};

public method .task_info() {
    arg info;
    
    return task_info(info);
};

public method .cancel() {
    arg args;
    
    return cancel(args);
};


object $sys: $root;

var $root name = "System Object";
var $sys bindings = [['bind_port, $network], ['chparents, $root], ['unbind_function, $sys], ['atomic, $sys], ['task_info, $root], ['set_heartbeat, $sys], ['cancel, $root], ['set_user, $sys], ['user, $sys], ['shutdown, $sys], ['dblog, $sys], ['backup, $sys], ['destroy, $root], ['create, $root], ['add_var, $root], ['del_var, $root], ['variables, $root], ['list_method, $root], ['add_method, $root], ['del_method, $root], ['method_bytecode, $root], ['methods, $root], ['rename_method, $root], ['set_method_access, $root], ['set_method_flags, $root], ['data, $root], ['del_objname, $root], ['set_objname, $root], ['bind_function, $sys]];

driver method .startup() {
    arg args;
    var x;
    
    //
    // SmallCore v1.0
    // Created by:
    // Robert Bradley
    // bradleyr1@iname.com
    //
    set_heartbeat(1);
    for x in (bindings)
        (| bind_function(@x) |);
    $network.startup();
};

public method .log() {
    arg line;
    
    dblog(((ctime().subrange(5)) + " ") + line);
};

driver method .signal() {
    arg @args;
    
};

public method .next_objnum(): native;

public method .status(): native;

public method .version(): native;

public method .user() {
    return user();
};

public method .set_user() {
    return set_user();
};

public method .heartbeat();

public method .suspend() {
    return suspend();
};

public method .shutdown() {
    var x;
    
    for x in ($incoming_conn.children())
        (| x.cleanup() |);
    shutdown();
};

public method .backup() {
    backup();
};

public method .backup_done();

public method .bind_function() {
    var x;
    
    for x in (bindings)
        bind_function(x[1], x[2]);
};


new object $libraries: $root;

var $root name = "System Libraries";


new object $string: $libraries;

var $root name = "String Library";

public method .capitalize(): native;

public method .str_to_buf() {
    arg @args;
    
    return (> str_to_buf(@args) <);
};

public method .trim(): native;

public method .subrange(): native;

public method .crypt(): native;

public method .explode(): native;

public method .lowercase(): native;

public method .match_begin(): native;

public method .match_pattern(): native;

public method .match_regexp(): native;

public method .match_template(): native;

public method .pad(): native;

public method .regexp(): native;

public method .strcmp() {
    arg @args;
    
    return (> strcmp(@args) <);
};

public method .strfmt() {
    arg @args;
    
    return (> strfmt(@args) <);
};

public method .strgraft() {
    arg @args;
    
    return (> strgraft(@args) <);
};

public method .strlen() {
    arg @args;
    
    return (> strlen(@args) <);
};

public method .strsed() {
    arg @args;
    
    return (> strsed(@args) <);
};

public method .strsub() {
    arg @args;
    
    return (> strsub(@args) <);
};

public method .substr() {
    arg @args;
    
    return (> substr(@args) <);
};

public method .uppercase(): native;

public method .length(): native;

public method .sed(): native;

public method .replace(): native;

public method .compare(): native;

public method .format(): native;

public method .split(): native;

public method .word(): native;

public method .dbquote_explode(): native;

public method .buffer() {
    arg line;
    var x;
    
    x = strings_to_buf([line]);
    return x.subrange(1, (x.length()) - 2);
};

public method .symbol() {
    arg line;
    
    return tosym(line);
};

public method .integer() {
    arg line;
    
    return toint(line);
};

public method .html_escape(): native;

public method .stridx() {
    arg @args;
    
    return stridx(@args);
};


new object $list: $libraries;

var $root name = "List Library";

public method .delete(): native;

public method .insert(): native;

public method .listlen() {
    arg @args;
    
    return (> listlen(@args) <);
};

public method .listgraft() {
    arg @args;
    
    return (> listgraft(@args) <);
};

public method .replace(): native;

public method .setadd(): native;

public method .setremove(): native;

public method .sublist() {
    arg @args;
    
    return (> sublist(@args) <);
};

public method .union(): native;

public method .length(): native;

public method .subrange(): native;

public method .join(): native;

public method .sort(): native;

public method .strings_to_buf() {
    var s;
    
    return strings_to_buf(s);
};

public method .random() {
    arg list;
    
    return list[(list.length()).random()];
};

public method .compile_traceback() {
    arg tb;
    var x, s, y, rdat;
    
    s = [];
    rdat = "";
    for x in [1 .. tb.length()] {
        y = tb[x];
        if (x == 1) {
            s += [(((("- Error " + (y[1])) + " (") + (y[2])) + ") - ") + toliteral(y[3])];
            rdat += (y[1]) + (y[2]);
        } else if (x == 2) {
            if ((y[1]) == 'method) {
                s += [(((((("- method " + (y[3])) + " (on ") + (y[4])) + ").") + (y[2])) + ", line ") + (y[5])];
                rdat += (("" + (y[4])) + (y[2])) + (y[5]);
            } else {
                s += [(("- " + (y[1])) + ": ") + (y[2])];
                rdat += y[2];
            }
        } else {
            s += [((((((((("- ..from " + (y[3])) + " (on ") + (y[4])) + ").") + (y[2])) + ", line ") + (y[5])) + " (") + (y[1])) + ")"];
        }
    }
    return s + ["End of traceback."];
};


new object $integer: $libraries;

var $root name = "Integer Library";

public method .abs() {
    arg @args;
    
    return (> abs(@args) <);
};

public method .max() {
    arg @args;
    
    return (> max(@args) <);
};

public method .min() {
    arg @args;
    
    return (> min(@args) <);
};

public method .random() {
    arg num;
    
    return random(num);
};

public method .sin() {
    arg @args;
    
    return (> sin(@args) <);
};

public method .exp() {
    arg @args;
    
    return (> exp(@args) <);
};

public method .log() {
    arg @args;
    
    return (> log(@args) <);
};

public method .cos() {
    arg @args;
    
    return (> cos(@args) <);
};

public method .tan() {
    arg @args;
    
    return (> tan(@args) <);
};

public method .sqrt() {
    arg @args;
    
    return (> sqrt(@args) <);
};

public method .asin() {
    arg @args;
    
    return (> asin(@args) <);
};

public method .acos() {
    arg @args;
    
    return (> acos(@args) <);
};

public method .atan() {
    arg @args;
    
    return (> atan(@args) <);
};

public method .pow() {
    arg a1, a2;
    
    return toint(tofloat(a1).pow(tofloat(a2)));
};

public method .atan2() {
    arg @args;
    
    return (> atan2(@args) <);
};

public method .and(): native;

public method .or(): native;

public method .xor(): native;

public method .shleft(): native;

public method .shright(): native;

public method .not(): native;

public method .string() {
    arg string;
    
    return tostr(string);
};


new object $float: $libraries;

var $root name = "Floatation Library";

public method .abs() {
    arg @args;
    
    return (> abs(@args) <);
};

public method .max() {
    arg @args;
    
    return (> max(@args) <);
};

public method .min() {
    arg @args;
    
    return (> min(@args) <);
};

public method .random() {
    arg @args;
    
    return (> random(@args) <);
};

public method .sin() {
    arg @args;
    
    return (> sin(@args) <);
};

public method .exp() {
    arg @args;
    
    return (> exp(@args) <);
};

public method .log() {
    arg @args;
    
    return (> log(@args) <);
};

public method .cos() {
    arg @args;
    
    return (> cos(@args) <);
};

public method .tan() {
    arg @args;
    
    return (> tan(@args) <);
};

public method .sqrt() {
    arg @args;
    
    return (> sqrt(@args) <);
};

public method .asin() {
    arg @args;
    
    return (> asin(@args) <);
};

public method .acos() {
    arg @args;
    
    return (> acos(@args) <);
};

public method .atan() {
    arg @args;
    
    return (> atan(@args) <);
};

public method .pow() {
    arg @args;
    
    return (> pow(@args) <);
};

public method .atan2() {
    arg @args;
    
    return (> atan2(@args) <);
};


new object $dictionary: $libraries;

var $root name = "Dictionary Library";

public method .dict_add() {
    arg @args;
    
    return (> dict_add(@args) <);
};

public method .dict_contains() {
    arg @args;
    
    return (> dict_contains(@args) <);
};

public method .dict_del() {
    arg @args;
    
    return (> dict_del(@args) <);
};

public method .dict_keys() {
    arg @args;
    
    return (> dict_keys(@args) <);
};

public method .keys(): native;

public method .add(): native;

public method .union(): native;

public method .del(): native;

public method .contains(): native;

public method .values(): native;

public method .length() {
    arg dict;
    
    return (dict.keys()).length();
};


new object $buffer: $libraries;

var $root name = "Buffer Library";

public method .subrange(): native;

public method .buflen() {
    arg @args;
    
    return (> buflen(@args) <);
};

public method .bufgraft() {
    arg @args;
    
    return (> bufgraft(@args) <);
};

public method .buf_replace() {
    arg @args;
    
    return (> buf_replace(@args) <);
};

public method .buf_to_str() {
    arg @args;
    
    return (> buf_to_str(@args) <);
};

public method .strings_to_buf() {
    arg @args;
    
    return (> strings_to_buf(@args) <);
};

public method .subbuf() {
    arg @args;
    
    return (> subbuf(@args) <);
};

public method .length(): native;

public method .replace(): native;

public method .to_string(): native;

public method .to_strings(): native;

public method .from_string(): native;

public method .from_strings(): native;

public method .string() {
    arg buf;
    
    return buf_to_strings(buf + `[13, 10])[1];
};


new object $symbol: $libraries;

var $root name = "Symbol Library";

public method .string() {
    arg sym;
    
    return tostr(sym);
};


new object $math: $libraries;

var $root name = "Math Library";

public method .minor(): native;

public method .major(): native;

public method .add(): native;

public method .sub(): native;

public method .dot(): native;

public method .distance(): native;

public method .cross(): native;

public method .scale(): native;

public method .is_lower(): native;

public method .transpose(): native;


new object $error: $libraries;

var $root name = "Error Handling Library";


new object $file: $libraries;

var $root name = "File Library";


new object $http: $libraries;

var $root name = "HTTP Library";

public method .decode(): native;

public method .encode(): native;


new object $time: $libraries;

var $root name = "Time Library";

public method .format(): native;


new object $network: $root;

var $root name = "Network Module";

public method .bind_port() {
    arg p;
    
    bind_port(p);
};

public method .reassign_connection() {
    arg c;
    
    reassign_connection(c);
};

public method .startup() {
    var x;
    
    for x in ($incoming_port.children())
        x.bind_port(x.port());
    for x in ($incoming_conn.children())
        (| x.cleanup() |);
};

public method .hostname(): native;

public method .ip(): native;


new object $incoming_port: $network;

var $root name = "Incoming Connection Handler";
var $incoming_port port = 0;

public method .port() {
    arg @args;
    
    if (args)
        port = args[1];
    return port;
};


new object $prog_port: $incoming_port;

var $root name = "Programmer Port Connection Handler";
var $incoming_port port = 5005;

public method .connect() {
    arg ip, server_ip, socket, @args;
    var c;
    
    c = $prog_conn.create();
    c.state(['login]);
    .reassign_connection(c);
    c.name(ip);
    c.startup();
};


new object $incoming_conn: $network;

var $root name = "Incomming Connection Holders";
var $incoming_conn state = 0;
var $incoming_conn pstate = 0;

public method .state() {
    arg @args;
    
    if (args)
        state = args[1];
    return state;
};

public method .pstate() {
    arg @args;
    
    if (args)
        pstate = args[1];
    return pstate;
};

public method .write() {
    arg text;
    
    cwrite(str_to_buf(text) + `[10, 13]);
};

public method .cwrite() {
    arg text;
    
    cwrite(str_to_buf(text));
};


new object $prog_conn: $incoming_conn;

var $root name = "Programmer Connection Holders";
var $prog_conn programmer = 0;
var $prog_conn input = 0;
var $prog_conn lines = 0;
var $prog_conn state = 0;
var $prog_conn pstate = 0;

public method .programmer() {
    arg @args;
    
    if (args)
        programmer = args[1];
    return programmer;
};

public method .parse() {
    arg line, @args;
    var st, r, i;
    
    catch any {
        i = buf_to_strings((input || `[]) + line);
        input = i[listlen(i)];
        lines = (lines || []) + (i.delete(listlen(i)));
        while (lines) {
            line = lines[1];
            lines = lines.delete(1);
            st = (.state())[1];
            if (st == 'connected) {
                if (!line)
                    return;
                r = (.programmer()).parse_line(line);
                if (!r)
                    .write("Invalid Command.");
            } else if (st == 'login) {
                if (valid(fromliteral("$programmer_" + line))) {
                    .state(['password, fromliteral("$programmer_" + line)]);
                    .cwrite("Password: ");
                } else {
                    .write("Invalid user name, please try again.");
                    .cwrite("Username: ");
                }
            } else if (st == 'password) {
                if (line == (((.state())[2]).password())) {
                    .programmer((.state())[2]);
                    (.programmer()).connection(this());
                    .state(['connected]);
                } else {
                    .write("Invalid password, please try again.");
                    .cwrite("Username: ");
                    .state(['login]);
                }
            } else if (st == 'reading) {
                r = (.state())[2];
                .state(.pstate());
                resume(r, line);
            }
        }
    } with {
        r = traceback().compile_traceback();
        for i in (r)
            .write(i);
    }
};

public method .startup() {
    .write("Welcome to minimal core.");
    .write("First time login as root, password root.");
    .write("");
    .cwrite("Username: ");
};

public method .disconnect() {
    close_connection();
    if (this() != $prog_conn)
        .destroy();
};

public method .cleanup() {
    var x;
    
    for x in (.children())
        x.disconnect();
};

public method .read() {
    var rv;
    
    if (lines) {
        rv = lines[1];
        lines = lines.delete(1);
        return rv;
    }
    .pstate(.state());
    .state(['reading, task_id()]);
    rv = suspend();
    if (rv == 0)
        throw(~read, "User logged off.");
    return rv;
};

public method .state() {
    arg @args;
    
    if (args)
        state = args[1];
    return state;
};


new object $prog_conn_1: $prog_conn;

var $incoming_conn state = ['connected];
var $root name = "127.0.0.1";
var $prog_conn input = `[];
var $prog_conn lines = ["arg @args;", "", "if (args)", "    state = args[1];", "return state;", ".", ""];
var $prog_conn programmer = $programmer_root;


new object $programmer: $root;

var $root name = "Programmer User Profiles";
var $programmer password = 0;
var $programmer commands = [["say *", 'say_cmd], [";*", 'eval_cmd], ["program *.*", 'program_cmd], ["list *.*", 'list_cmd], ["quit*", 'quit_cmd]];
var $programmer connection = 0;

public method .commands() {
    arg @args;
    
    if (args)
        commands = args[1];
    return commands;
};

public method .connection() {
    arg @args;
    
    if (args)
        connection = args[1];
    return connection;
};

public method .password() {
    arg @args;
    
    if (args)
        password = args[1];
    return password;
};

public method .name() {
    arg @args;
    
    if (args)
        .set_objname(tosym("programmer_" + (args[1])));
    return toliteral(this()).subrange(13);
};

public method .notify() {
    arg text;
    
    (.connection()).write(text);
};

public method .say_cmd() {
    arg msg;
    var x;
    
    for x in ($prog_conn.children())
        x.write((((.name()) + " says, \"") + msg) + "\"");
};

public method .eval_cmd() {
    arg line;
    var r, evaltemp, t, x;
    
    catch any {
        evaltemp = tosym("evaltemp_" + random(2000000000));
        if (!(";" in line))
            line = "return " + line;
        r = .add_method([line + ";"], evaltemp);
        if (r) {
            .notify(r[1]);
            (| .del_method(evaltemp) |);
        } else {
            r = .(evaltemp)();
            .notify("=> " + toliteral(r));
            .del_method(evaltemp);
        }
    } with {
        t = traceback().compile_traceback();
        for x in (t)
            .notify(x);
        .del_method(evaltemp);
    }
};

public method .program_cmd() {
    arg obj, method;
    var line, code, cc;
    
    if ((obj[1]) == "$")
        obj = (| lookup(tosym(obj.subrange(2))) |);
    else if ((obj[1]) == "#")
        obj = toobjnum(toint(obj.subrange(2)));
    if (!valid(obj)) {
        .notify("Could not find object, please check spelling.");
        return;
    }
    .notify(((("(Programming " + obj) + ".") + method) + ")");
    .notify("Enter method code, type . to end.");
    cc = .connection();
    code = [];
    while ((line = cc.read()) != ".")
        code = [@code, line];
    .notify((| (obj.add_method(code, tosym(method)))[1] |) || "Method programmed.");
};

public method .parse_line() {
    arg line;
    var x, p, r;
    
    for x in ($programmer.commands()) {
        if ((p = line.match_pattern(x[1])))
            r = .(x[2])(@p);
    }
    return r;
};

public method .list_cmd() {
    arg obj, method;
    var x;
    
    if ((obj[1]) == "$")
        obj = (| lookup(tosym(obj.subrange(2))) |);
    else if ((obj[1]) == "#")
        obj = toobjnum(toint(obj.subrange(2)));
    if (!valid(obj)) {
        .notify("Could not find object, please check spelling.");
        return;
    }
    if (!(tosym(method) in (obj.methods()))) {
        .notify("Could not find method, please check spelling.");
        return;
    }
    .notify(((("Code for " + toliteral(obj)) + ".") + method) + " --");
    .notify((("program " + toliteral(obj)) + ".") + method);
    for x in (obj.list_method(tosym(method)))
        .notify(x);
    .notify(".");
};

public method .quit_cmd() {
    arg none;
    
    .notify("Goodbye.");
    (.connection()).disconnect();
};


new object $programmer_root: $programmer;

var $programmer password = "root";
var $programmer connection = $prog_conn_1;