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:
parent
0b4aa7cc31
commit
303c5f828b
5 changed files with 108 additions and 49 deletions
|
@ -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);
|
||||
};
|
||||
};
|
||||
|
|
3
main.cpp
3
main.cpp
|
@ -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) {
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
82
pilang.cpp
82
pilang.cpp
|
@ -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
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue