1
0
Fork 0
mirror of https://gitlab.com/niansa/pilang3.git synced 2025-03-06 20:49:20 +01:00

Implemented basic functions

This commit is contained in:
niansa 2021-02-01 15:24:40 +01:00
parent 0b4aa7cc31
commit 303c5f828b
5 changed files with 108 additions and 49 deletions

View file

@ -17,13 +17,17 @@ namespace Pilang3 {
class BadArgs : public langException {};
class NoSuchCommand : public langException {};
class NoSuchVariable : public langException {};
class UnexpectedEndOfExpression : public langException {};
}
class Environment;
class Evaluation;
class Function;
struct Variable;
using SharedEnvironment = std::shared_ptr<Environment>;
using SharedVariable = std::shared_ptr<Variable>;
using SharedEvaluation = std::shared_ptr<Evaluation>;
using SharedFunction = std::shared_ptr<Function>;
struct Variable {
enum Type {
@ -31,17 +35,19 @@ namespace Pilang3 {
id_integer,
id_reference,
id_evaluation,
id_function,
id_type [[maybe_unused]],
id_retval [[maybe_unused]],
id_any [[maybe_unused]],
id_null [[maybe_unused]]
} type;
using Data = std::variant<std::string, integer_type, SharedVariable, Type, SharedEvaluation>;
using Data = std::variant<std::string, integer_type, SharedVariable, SharedEvaluation, SharedFunction, Type>;
Data data;
};
using Cmdargs = std::vector<Variable>;
using Cmdfnc = std::function<Variable (Environment&, Cmdargs&)>;
using Cmdfnc = std::function<Variable (SharedEnvironment, Cmdargs&)>;
using Cmddesc = std::tuple<Cmdfnc, uint16_t, std::vector<Variable::Type>, bool>;
extern std::unordered_map<std::string, Cmddesc> builtinCmds;
@ -57,10 +63,17 @@ namespace Pilang3 {
Cmdargs arguments;
Cmdfnc command = nullptr;
std::string command_name;
ssize_t exprlen;
ssize_t exprlen = -1;
Evaluation(Environment& env, const std::string &expression, const bool autoeval = true);
Evaluation(SharedEnvironment env, const std::string& expression, const bool autoeval = true);
Variable execute(Environment& env);
Variable execute(SharedEnvironment env);
};
class Function {
public:
std::vector<SharedEvaluation> evalChain;
Variable execute(SharedEnvironment env);
};
};

View file

@ -1,4 +1,5 @@
#include <iostream>
#include <memory>
#include "pilang.hpp"
@ -7,7 +8,7 @@ int main() {
// Initialise
std::string line;
Environment env;
auto env = std::make_shared<Environment>();
// CLI loop
while (true) {

View file

@ -1,20 +1,28 @@
#include <sstream>
#include <memory>
#include "pilang.hpp"
using namespace Pilang3;
class Std {
public:
static Variable set(Environment& env, Cmdargs& args) {
return *env.globalVars[std::get<std::string>(args[0].data)];
static Variable retval(SharedEnvironment, Cmdargs& args) {
return Variable({
Variable::id_retval,
std::make_shared<Variable>(args[0])
});
}
static Variable get(Environment& env, Cmdargs& args) {
env.globalVars[std::get<std::string>(args[0].data)] = std::make_shared<Variable>(args[1]);
static Variable set(SharedEnvironment env, Cmdargs& args) {
env->globalVars[std::get<std::string>(args[0].data)] = std::make_shared<Variable>(args[1]);
return args[1];
}
static Variable concat(Environment&, Cmdargs& args) {
static Variable get(SharedEnvironment env, Cmdargs& args) {
return *env->globalVars[std::get<std::string>(args[0].data)];
}
static Variable concat(SharedEnvironment, Cmdargs& args) {
std::ostringstream fres;
for (const auto& arg : args) {
switch (arg.type) {
@ -32,8 +40,9 @@ public:
}
Std() {
Pilang3::builtinCmds["set"] = {concat, 2, {Variable::id_string, Variable::id_any}, true};
Pilang3::builtinCmds["get"] = {concat, 1, {Variable::id_string}, true};
Pilang3::builtinCmds["return"] = {retval, 1, {Variable::id_any}, false};
Pilang3::builtinCmds["set"] = {set, 2, {Variable::id_string, Variable::id_any}, false};
Pilang3::builtinCmds["get"] = {get, 1, {Variable::id_string}, false};
Pilang3::builtinCmds["concat"] = {concat, 0, {}, true};
}
};

View file

@ -5,7 +5,7 @@ using namespace Pilang3;
class StdIO {
public:
static Variable print(Environment&, Cmdargs& args) {
static Variable print(SharedEnvironment, Cmdargs& args) {
std::cout << std::get<std::string>(args[0].data) << std::endl;
return Variable({
Variable::id_null,

View file

@ -12,26 +12,18 @@
namespace Pilang3 {
std::unordered_map<std::string, std::tuple<Cmdfnc, uint16_t, std::vector<Variable::Type>, bool>> builtinCmds = {
{"concat", {[] (Environment& env, Cmdargs& args) {
std::ostringstream fres;
for (const auto& arg : args) {
switch (arg.type) {
case Variable::id_integer: fres << std::get<integer_type>(arg.data); break;
case Variable::id_string: fres << std::get<std::string>(arg.data); break;
case Variable::id_reference: fres << std::get<SharedVariable>(arg.data).get(); break;
case Variable::id_type: fres << std::get<Variable::Type>(arg.data); break;
default: fres << "<ID" << arg.type << '>'; break;
}
}
return Variable({
Variable::id_string,
fres.str()
});
}, 0, {}, true}}
};
std::unordered_map<std::string, std::tuple<Cmdfnc, uint16_t, std::vector<Variable::Type>, bool>> builtinCmds;
Evaluation::Evaluation(Environment& env, const std::string &expression, const bool autoeval) {
Evaluation::Evaluation(SharedEnvironment env, const std::string& expression, const bool autoeval) {
// Count off trailing spaces
ssize_t tspaces = 0;
for (const auto& character : expression) {
if (character == ' ' or character == '\t') {
tspaces++;
} else {
break;
}
}
// Parse arguments if any
if (not expression.empty()) {
Variable thisarg;
@ -39,7 +31,7 @@ namespace Pilang3 {
bool newarg = false;
bool escapenext = false;
std::string cache;
for (auto characterit = expression.begin(); characterit != expression.end(); characterit++) {
for (auto characterit = expression.begin() + tspaces; characterit != expression.end(); characterit++) {
char character = *characterit;
// Start new command name
if (in_command_name) {
@ -49,6 +41,7 @@ namespace Pilang3 {
command_name = cache;
cache.clear();
if (character == ';') {
exprlen = std::distance(expression.begin(), characterit);
break;
} else {
in_command_name = false;
@ -72,6 +65,9 @@ namespace Pilang3 {
} else if (character == '&') {
// Expression
thisarg.type = Variable::id_evaluation;
} else if (character == '{') {
// Function
thisarg.type = Variable::id_function;
} else {
// Reference
thisarg.type = Variable::id_reference;
@ -112,8 +108,8 @@ namespace Pilang3 {
case Variable::id_reference: {
// Reference
if (maybe_end_of_arg) {
auto res = env.globalVars.find(cache);
if (res == env.globalVars.end()) {
auto res = env->globalVars.find(cache);
if (res == env->globalVars.end()) {
throw exceptions::NoSuchVariable();
}
thisarg = *res->second;
@ -141,6 +137,19 @@ namespace Pilang3 {
character = *(characterit += evaluation->exprlen + 1);
newarg = true;
} break;
case Variable::id_function: {
auto thisfunc = std::make_shared<Function>();
while (character != '}') {
// Evaluate
auto evaluation = std::make_shared<Evaluation>(env, std::string(characterit, expression.end()));
thisfunc->evalChain.push_back(evaluation);
// Skip over expression in iteration
character = *(characterit += evaluation->exprlen + 1);
}
character = *(++characterit);
thisarg.data = thisfunc;
newarg = true;
} break;
}
// Actually end argument if required
if (newarg) {
@ -154,11 +163,23 @@ namespace Pilang3 {
}
}
}
// Check exprlen
if (exprlen < 0) {
throw exceptions::UnexpectedEndOfExpression();
}
// Find command
auto res = Pilang3::builtinCmds.find(command_name);
if (res == Pilang3::builtinCmds.end()) {
// Find function
auto res = env->globalVars.find(command_name);
if (res == env->globalVars.end() or res->second->type != Variable::id_function) {
throw exceptions::NoSuchCommand();
}
// Execute function
command = [res] (SharedEnvironment env, Cmdargs&) {
return std::get<SharedFunction>(res->second->data)->execute(env);
};
} else {
uint16_t argslen;
std::vector<Variable::Type> argstypes;
bool anymoreopts;
@ -174,12 +195,27 @@ namespace Pilang3 {
}
}
}
}
Variable Evaluation::execute(Environment& env) {
Variable Evaluation::execute(SharedEnvironment env) {
if (command) {
return command(env, arguments);
} else {
throw exceptions::NoSuchCommand();
}
}
Variable Function::execute(SharedEnvironment env) {
Variable fres;
for (auto& evaluation : evalChain) {
fres = evaluation->execute(env);
if (fres.type == Variable::id_retval) {
return *std::get<SharedVariable>(fres.data);
}
}
return Variable({
Variable::id_null,
0
});
}
};