diff --git a/modules/builtin.hh b/modules/builtin.hh new file mode 100644 index 0000000..03cc663 --- /dev/null +++ b/modules/builtin.hh @@ -0,0 +1,371 @@ +command_tmpl(cmd_ret) { + std::string retstring; + for (const std::string & arg : args){ + retstring.append(arg); + } + return retstring; +} + +command_tmpl(cmd_catch) { + if (args.size() != 1) { + return badarguments; + } + std::string boolstr = *args.begin(); + if (str_lower(boolstr) == "true") + catcherrs = true; + else if (str_lower(boolstr) == "false") + catcherrs = false; + else + return badarguments; + return success; +} + +command_tmpl(cmd_get) { + if (args.size() != 2) { + return badarguments; + } + auto argsit = args.begin(); + std::string string = *argsit; + argsit++; + long unsigned int position = std::stoi(*argsit); + if (position < string.length()) { + std::string res; + res.push_back(string.at(position)); + return res; + } else { + return badarguments; + } +} + +command_tmpl(cmd_len) { + int result = 0; + for (const std::string & arg : args){ + result += arg.length(); + } + return std::to_string(result); +} + +command_tmpl(cmd_exit) { + //Check amount of arguments + if (args.size() != 1) { + return badarguments; + } + std::string exitcode = *args.begin(); + if (is_float(exitcode)) + _exit(std::stoi(exitcode)); + else + return badarguments; +} + +command_tmpl(cmd_marker) { + // Check amount of arguments + if (args.size() != 2) { + return badarguments; + } + // Get arguments + auto argsit = args.begin(); + std::string action = *argsit; + argsit++; + std::string markername = *argsit; + // Set or goto + if (action == "goto") { + markergotoname = markername; + throw markergoto(); + } else if (action == "set") { + markersetqueue.push_back(markername); + } else { + return badarguments; + } + return success; +} + +command_tmpl(cmd_printnnl) { + std::cout << cmd_ret(args) << std::flush; + return success; +} + +command_tmpl(cmd_print) { + auto result = cmd_printnnl(args); + std::cout << std::endl; + return result; +} + +command_tmpl(cmd_input) { + std::string hint = cmd_ret(args); + cmd_printnnl({hint}); + std::string result; + std::getline(readkbd(hint), result); + return result; +} + +command_tmpl(cmd_set) { + //Check amount of arguments + if (args.size() != 2) { + return badarguments; + } + // Get arguments + auto argsit = args.begin(); + std::string key = *argsit; + argsit++; + std::string value = *argsit; + // Store in environment + variables[key] = value; + // Return success + return success; +} + +command_tmpl(cmd_append) { + //Check amount of arguments + if (args.size() < 2) { + return badarguments; + } + // Get arguments + auto argsit = args.begin(); + std::string variablename = *argsit; + argsit++; + for (; argsit != args.end(); argsit++) + variables[variablename].append(*argsit); + return success; +} + +std::string cmd_incdec(bool type, command_args) { // TODO + bool asint = false; + //Check amount of arguments + if (args.size() < 1 or args.size() > 3) { + return badarguments; + } + // Get arguments + auto argsit = args.begin(); + if (*argsit == "asint") { + asint = true; + argsit++; + } + std::string variablename = *argsit; + float incby; + if (args.size() > 1) { + argsit++; + incby = std::atof((*argsit).c_str()); + } else { + incby = 1; + } + // Modify variable if it exists + if (variables.find(variablename) == variables.end()) { + return nosuchvariable; + } else { + float currval = std::atof(variables[variablename].c_str()); + if (type) + currval += incby; + else + currval -= incby; + if (!asint) + variables[variablename] = std::to_string(currval); + else + variables[variablename] = std::to_string((int)currval); + } + return success; +} +command_tmpl(cmd_inc) { + return cmd_incdec(true, args); +} +command_tmpl(cmd_dec) { + return cmd_incdec(false, args); +} + +command_tmpl(cmd_del) { + if (args.size() < 1) { + return badarguments; + } + for (const std::string & arg : args) { + auto varit = variables.find(arg); + if (varit != variables.end()) { + variables.erase(variables.find(arg)); + } + } + return success; +} + +command_tmpl(cmd_eval) { + if (args.size() < 1) { + return badarguments; + } + std::string result; + for (const std::string & arg : args) { + result = execline(arg); + } + return result; +} + +command_tmpl(cmd_cmp) { + bool matches; + //Check amount of arguments + if (args.size() < 4) { + return badarguments; + } + // Get arguments + auto argsit = args.begin(); + std::string action = *argsit; + argsit++; + std::string var1 = *argsit; + argsit++; + std::string var2 = *argsit; + argsit++; + // Compare + if (action == "equal") + matches = var1 == var2; + else if (action == "nonequal") + matches = var1 != var2; + else if (action == "bigger") + matches = std::atof(var1.c_str()) > std::atof(var2.c_str()); + else if (action == "smaller") + matches = std::atof(var1.c_str()) < std::atof(var2.c_str()); + else if (action == "isnum" or action == "isnotnum") { + matches = is_float(var1) and is_float(var2); + if (action == "isnotnum") + matches = !matches; + } else + return badarguments; + // Eval on match + if (matches) { + std::string result; + while (argsit != args.end()) { + result = execline(*argsit); + argsit++; + } + return result; + } else { + return failed; + } +} + +std::string cmd_lowerupper(bool type, command_args) { + if (args.size() < 1) { + return badarguments; + } + std::string result; + for (auto argsit = args.begin(); argsit != args.end(); argsit++) { + if (type) + result.append(str_upper(*argsit)); + else + result.append(str_lower(*argsit)); + } + return result; +} +command_tmpl(cmd_upper) { + return cmd_lowerupper(true, args); +} +command_tmpl(cmd_lower) { + return cmd_lowerupper(false, args); +} + +std::string cmd_addsub(bool type, command_args) { + //Check amount of arguments + if (args.size() < 2) { + return badarguments; + } + // Initialise variables + bool asint = false; + float numarg; + // Get arguments + auto argsit = args.begin(); + if (*argsit == "asint") { + asint = true; + argsit++; + } + // Initialise initial result + if (!is_float(*argsit)) + return badarguments; + float result = std::atof((*argsit).c_str()); + argsit++; + // Calculate + for (; argsit != args.end(); argsit++) { + if (!is_float(*argsit)) + return badarguments; + numarg = std::atof((*argsit).c_str()); + if (type) + result += numarg; + else + result -= numarg; + } + // Return result + if (asint) + return std::to_string((int) result); + else + return std::to_string(result); +} +command_tmpl(cmd_add) { + return cmd_addsub(true, args); +} +command_tmpl(cmd_sub) { + return cmd_addsub(false, args); +} + +command_tmpl(cmd_sleep) { + // Check amount of arguments + if (args.size() != 1) { + return badarguments; + } + // Check argument + auto argsit = args.begin(); + if (!is_float(*argsit)) + return badarguments; + // Get argument + float sleepsecs = std::atof((*argsit).c_str()); + sleep(sleepsecs); + return success; +} + +command_tmpl(cmd_argv) { + // Check amount of arguments + if (args.size() != 1) { + return badarguments; + } + // Check argument + auto argsit = args.begin(); + if (!is_float(*argsit)) + return badarguments; + long unsigned int argnum = std::atoi((*argsit).c_str()); + if (argnum >= cmdargs.size()) + return badarguments; + // Get argument + return cmdargs[argnum]; +} + +command_tmpl(cmd_argc) { + return std::to_string(cmdargs.size()); +} + +command_tmpl(cmd_commands) { + std::stringstream res; + for (auto it = commands.begin(); it != commands.end(); it++) { + res << &it->first[sizeof("cmd_") - 1] << " "; + } + return res.str(); +} + + +void register_builtin_commands() { + command_register(cmd_argc); + command_register(cmd_argv); + command_register(cmd_sleep); + command_register(cmd_add); + command_register(cmd_sub); + command_register(cmd_upper); + command_register(cmd_lower); + command_register(cmd_eval); + command_register(cmd_cmp); + command_register(cmd_del); + command_register(cmd_append); + command_register(cmd_inc); + command_register(cmd_dec); + command_register(cmd_set); + command_register(cmd_input); + command_register(cmd_print); + command_register(cmd_printnnl); + command_register(cmd_marker); + command_register(cmd_exit); + command_register(cmd_len); + command_register(cmd_get); + command_register(cmd_catch); + command_register(cmd_ret); + command_register(cmd_commands); +} diff --git a/source/pilang2.cpp b/source/pilang2.cpp index 2ee2f56..9fd8048 100644 --- a/source/pilang2.cpp +++ b/source/pilang2.cpp @@ -112,357 +112,33 @@ std::string get_rstring(std::string rstring) { return rstring; } +// Function template +#define command_args std::vector args +#define command_rawtmpl(func) func(command_args) +#define command_tmpl(func) std::string command_rawtmpl(func) +typedef std::function command_type; -// Builtin functions -std::string cmd_ret(std::vector args) { - std::string retstring; - for (const std::string & arg : args){ - retstring.append(arg); - } - return retstring; -} -std::string cmd_catch(std::vector args) { - if (args.size() != 1) { - return badarguments; - } - std::string boolstr = *args.begin(); - if (str_lower(boolstr) == "true") - catcherrs = true; - else if (str_lower(boolstr) == "false") - catcherrs = false; - else - return badarguments; - return success; -} -std::string cmd_get(std::vector args) { - if (args.size() != 2) { - return badarguments; - } - auto argsit = args.begin(); - std::string string = *argsit; - argsit++; - long unsigned int position = std::stoi(*argsit); - if (position < string.length()) { - std::string res; - res.push_back(string.at(position)); - return res; - } else { - return badarguments; - } -} -std::string cmd_len(std::vector args) { - int result = 0; - for (const std::string & arg : args){ - result += arg.length(); - } - return std::to_string(result); -} -std::string cmd_exit(std::vector args) { - //Check amount of arguments - if (args.size() != 1) { - return badarguments; - } - std::string exitcode = *args.begin(); - if (is_float(exitcode)) - _exit(std::stoi(exitcode)); - else - return badarguments; -} -std::string cmd_marker(std::vector args) { - // Check amount of arguments - if (args.size() != 2) { - return badarguments; - } - // Get arguments - auto argsit = args.begin(); - std::string action = *argsit; - argsit++; - std::string markername = *argsit; - // Set or goto - if (action == "goto") { - markergotoname = markername; - throw markergoto(); - } else if (action == "set") { - markersetqueue.push_back(markername); - } else { - return badarguments; - } - return success; -} -std::string cmd_printnnl(std::vector args) { - std::cout << cmd_ret(args) << std::flush; - return success; -} -std::string cmd_print(std::vector args) { - auto result = cmd_printnnl(args); - std::cout << std::endl; - return result; -} -std::string cmd_input(std::vector args) { - std::string hint = cmd_ret(args); - cmd_printnnl({hint}); - std::string result; - std::getline(readkbd(hint), result); - return result; -} -std::string cmd_set(std::vector args) { - //Check amount of arguments - if (args.size() != 2) { - return badarguments; - } - // Get arguments - auto argsit = args.begin(); - std::string key = *argsit; - argsit++; - std::string value = *argsit; - // Store in environment - variables[key] = value; - // Return success - return success; -} -std::string cmd_append(std::vector args) { - //Check amount of arguments - if (args.size() < 2) { - return badarguments; - } - // Get arguments - auto argsit = args.begin(); - std::string variablename = *argsit; - argsit++; - for (; argsit != args.end(); argsit++) - variables[variablename].append(*argsit); - return success; -} -std::string cmd_incdec(bool type, std::vector args) { - bool asint = false; - //Check amount of arguments - if (args.size() < 1 or args.size() > 3) { - return badarguments; - } - // Get arguments - auto argsit = args.begin(); - if (*argsit == "asint") { - asint = true; - argsit++; - } - std::string variablename = *argsit; - float incby; - if (args.size() > 1) { - argsit++; - incby = std::atof((*argsit).c_str()); - } else { - incby = 1; - } - // Modify variable if it exists - if (variables.find(variablename) == variables.end()) { - return nosuchvariable; - } else { - float currval = std::atof(variables[variablename].c_str()); - if (type) - currval += incby; - else - currval -= incby; - if (!asint) - variables[variablename] = std::to_string(currval); - else - variables[variablename] = std::to_string((int)currval); - } - return success; -} -std::string cmd_del(std::vector args) { - if (args.size() < 1) { - return badarguments; - } - for (const std::string & arg : args) { - auto varit = variables.find(arg); - if (varit != variables.end()) { - variables.erase(variables.find(arg)); - } - } - return success; -} -std::string cmd_eval(std::vector args) { - if (args.size() < 1) { - return badarguments; - } - std::string result; - for (const std::string & arg : args) { - result = execline(arg); - } - return result; -} -std::string cmd_cmp(std::vector args) { - bool matches; - //Check amount of arguments - if (args.size() < 4) { - return badarguments; - } - // Get arguments - auto argsit = args.begin(); - std::string action = *argsit; - argsit++; - std::string var1 = *argsit; - argsit++; - std::string var2 = *argsit; - argsit++; - // Compare - if (action == "equal") - matches = var1 == var2; - else if (action == "nonequal") - matches = var1 != var2; - else if (action == "bigger") - matches = std::atof(var1.c_str()) > std::atof(var2.c_str()); - else if (action == "smaller") - matches = std::atof(var1.c_str()) < std::atof(var2.c_str()); - else if (action == "isnum" or action == "isnotnum") { - matches = is_float(var1) and is_float(var2); - if (action == "isnotnum") - matches = !matches; - } else - return badarguments; - // Eval on match - if (matches) { - std::string result; - while (argsit != args.end()) { - result = execline(*argsit); - argsit++; - } - return result; - } else { - return failed; - } -} -std::string cmd_lowerupper(bool type, std::vector args) { - if (args.size() < 1) { - return badarguments; - } - std::string result; - for (auto argsit = args.begin(); argsit != args.end(); argsit++) { - if (type) - result.append(str_upper(*argsit)); - else - result.append(str_lower(*argsit)); - } - return result; -} -std::string cmd_addsub(bool type, std::vector args) { - //Check amount of arguments - if (args.size() < 2) { - return badarguments; - } - // Initialise variables - bool asint = false; - float numarg; - // Get arguments - auto argsit = args.begin(); - if (*argsit == "asint") { - asint = true; - argsit++; - } - // Initialise initial result - if (!is_float(*argsit)) - return badarguments; - float result = std::atof((*argsit).c_str()); - argsit++; - // Calculaté - for (; argsit != args.end(); argsit++) { - if (!is_float(*argsit)) - return badarguments; - numarg = std::atof((*argsit).c_str()); - if (type) - result += numarg; - else - result -= numarg; - } - // Return result - if (asint) - return std::to_string((int) result); - else - return std::to_string(result); -} -std::string cmd_sleep(std::vector args) { - // Check amount of arguments - if (args.size() != 1) { - return badarguments; - } - // Check argument - auto argsit = args.begin(); - if (!is_float(*argsit)) - return badarguments; - // Get argument - float sleepsecs = std::atof((*argsit).c_str()); - sleep(sleepsecs); - return success; -} -std::string cmd_argv(std::vector args) { - // Check amount of arguments - if (args.size() != 1) { - return badarguments; - } - // Check argument - auto argsit = args.begin(); - if (!is_float(*argsit)) - return badarguments; - long unsigned int argnum = std::atoi((*argsit).c_str()); - if (argnum >= cmdargs.size()) - return badarguments; - // Get argument - return cmdargs[argnum]; -} -std::string cmd_argc(std::vector args) { - return std::to_string(cmdargs.size()); +// Function struct and map +std::map commands; +#define command_register(func) commands[#func] = func; + +// Module includes +#include "../modules/builtin.hh" + +// Module loaders +void load_modules() { + // Execute your module registration functions here + register_builtin_commands(); } +// Function executor std::string run_command(std::string command, std::vector args) { //std::cout << "Running command:" << command << "!" << std::endl; - if (command == "ret") - return cmd_ret(args); - else if (command == "catch") - return cmd_catch(args); - else if (command == "get") - return cmd_get(args); - else if (command == "len") - return cmd_len(args); - else if (command == "exit") - return cmd_exit(args); - else if (command == "marker") - return cmd_marker(args); - else if (command == "print") - return cmd_print(args); - else if (command == "printnnl") - return cmd_printnnl(args); - else if (command == "input") - return cmd_input(args); - else if (command == "set") - return cmd_set(args); - else if (command == "append") - return cmd_append(args); - else if (command == "inc") - return cmd_incdec(true, args); - else if (command == "dec") - return cmd_incdec(false, args); - else if (command == "del") - return cmd_del(args); - else if (command == "eval") - return cmd_eval(args); - else if (command == "cmp") - return cmd_cmp(args); - else if (command == "lower") - return cmd_lowerupper(false, args); - else if (command == "upper") - return cmd_lowerupper(true, args); - else if (command == "add") - return cmd_addsub(true, args); - else if (command == "sub") - return cmd_addsub(false, args); - else if (command == "sleep") - return cmd_sleep(args); - else if (command == "argv") - return cmd_argv(args); - else if (command == "argc") - return cmd_argc(args); - else + if (commands.find("cmd_" + command) == commands.end()) { return nosuchcommand; + } else { + return commands["cmd_" + command](args); + } } // Interpreter initialiser @@ -558,6 +234,8 @@ int _main(int argc, char *argv[]) { using namespace std; signal(SIGSEGV, sigsegv_handler); std::string line; + load_modules(); + // Start CLI or run file if (argc < 2) { // Start interactive CLI // Show copyright note cout << "pilang Copyright (C) 2020 niansa" << endl;