remove std::any
This commit is contained in:
parent
f2b4a53176
commit
186cab9ac9
@ -14,7 +14,7 @@ bool Scope::varExists(Context& ctx, std::string name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any& Scope::getVar(Context& cxt, std::string name) {
|
Value& Scope::getVar(Context& cxt, std::string name) {
|
||||||
if (vars.find(name) == vars.end()) {
|
if (vars.find(name) == vars.end()) {
|
||||||
if (varExists(cxt, name)) {
|
if (varExists(cxt, name)) {
|
||||||
return parentScope.get()->getVar(cxt, name);
|
return parentScope.get()->getVar(cxt, name);
|
||||||
@ -26,7 +26,7 @@ std::any& Scope::getVar(Context& cxt, std::string name) {
|
|||||||
return vars.at(name);
|
return vars.at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scope::writeVar(Context& cxt, std::string name, std::any& var) {
|
void Scope::writeVar(Context& cxt, std::string name, const Value& var) {
|
||||||
if (vars.find(name) == vars.end()) {
|
if (vars.find(name) == vars.end()) {
|
||||||
if (varExists(cxt, name)) {
|
if (varExists(cxt, name)) {
|
||||||
parentScope.get()->writeVar(cxt, name, var);
|
parentScope.get()->writeVar(cxt, name, var);
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <any>
|
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ class Context;
|
|||||||
class Scope {
|
class Scope {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<Scope> parentScope;
|
std::shared_ptr<Scope> parentScope;
|
||||||
std::unordered_map<std::string, std::any> vars;
|
std::unordered_map<std::string, Value> vars;
|
||||||
// std::function<bool(Context&,Args&)> returnHandler;
|
// std::function<bool(Context&,Args&)> returnHandler;
|
||||||
// std::function<bool(Context&)> breakHandler;
|
// std::function<bool(Context&)> breakHandler;
|
||||||
// std::function<bool(Context&)> continueHandler;
|
// std::function<bool(Context&)> continueHandler;
|
||||||
@ -25,7 +26,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Looks up var and creates it in the current scope if it doesn't exist
|
* Looks up var and creates it in the current scope if it doesn't exist
|
||||||
*/
|
*/
|
||||||
std::any& getVar(Context& cxt, std::string name);
|
Value& getVar(Context& cxt, std::string name);
|
||||||
|
|
||||||
void writeVar(Context& cxt, std::string name, std::any& var);
|
void writeVar(Context& cxt, std::string name, const Value& var);
|
||||||
};
|
};
|
111
src/context.cpp
111
src/context.cpp
@ -1,39 +1,38 @@
|
|||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
|
||||||
|
#include <cpp-peglib/peglib.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
void Context::error(std::string_view msg) {
|
void Context::error(std::string_view msg) {
|
||||||
std::cout << "Error! " << msg << std::endl;
|
std::cout << "Error! " << msg << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
using std::any_cast;
|
Value Context::readIdentifier(Value val) {
|
||||||
|
return currentScope->getVar(*this, val.getIdentifier(*this).identifier);
|
||||||
std::any Context::readIdentifier(std::any val) {
|
|
||||||
assert(val.type() == typeid(Identifier));
|
|
||||||
return currentScope->getVar(*this, any_cast<Identifier>(val).identifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the input (reads the value if it is a refers to a variable)
|
* Returns the value of the input (reads the value if it is a refers to a variable)
|
||||||
*/
|
*/
|
||||||
std::any Context::getValue(std::any input) {
|
Value Context::getValue(Value input) {
|
||||||
if (input.type() == typeid(Identifier))
|
if (input.isIdentifier())
|
||||||
return readIdentifier(input);
|
return readIdentifier(input);
|
||||||
else
|
else
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any Context::eval(peg::Ast& ast) {
|
Value Context::eval(peg::Ast& ast) {
|
||||||
const auto &nodes = ast.nodes;
|
const auto &nodes = ast.nodes;
|
||||||
|
Context &cxt = *this;
|
||||||
if (ast.name == "Root") {
|
if (ast.name == "Root") {
|
||||||
for (int i=0; i<ast.nodes.size(); i++) {
|
for (int i=0; i<ast.nodes.size(); i++) {
|
||||||
eval(*nodes[i]);
|
eval(*nodes[i]);
|
||||||
}
|
}
|
||||||
return Nil();
|
return Nil();
|
||||||
} else if (ast.name == "VarDecl") {
|
} else if (ast.name == "VarDecl") {
|
||||||
auto identifier = any_cast<Identifier>(eval(*nodes[0]));
|
std::string identifier = eval(*nodes[0]).getIdentifier(cxt).identifier;
|
||||||
auto value = eval(*nodes[1]);
|
Value value = eval(*nodes[1]);
|
||||||
currentScope->writeVar(*this, identifier.identifier, value);
|
currentScope->writeVar(cxt, identifier, value);
|
||||||
return Nil();
|
return Nil();
|
||||||
} else if (ast.name == "IDENTIFIER" || ast.name == "BUILTINIDENTIFIER") {
|
} else if (ast.name == "IDENTIFIER" || ast.name == "BUILTINIDENTIFIER") {
|
||||||
return Identifier(std::string(ast.token_to_string()));
|
return Identifier(std::string(ast.token_to_string()));
|
||||||
@ -41,68 +40,66 @@ std::any Context::eval(peg::Ast& ast) {
|
|||||||
// TODO parse hex, oct, and binary
|
// TODO parse hex, oct, and binary
|
||||||
return ast.token_to_number<long>();
|
return ast.token_to_number<long>();
|
||||||
} else if (ast.name == "BUILTINCALL" ) {
|
} else if (ast.name == "BUILTINCALL" ) {
|
||||||
auto identifier = any_cast<Identifier>(eval(*nodes[0]));
|
std::string identifier = eval(*nodes[0]).getIdentifier(cxt).identifier;
|
||||||
auto args = Args::toArgs(*this, eval(*nodes[1]));
|
Args args = eval(*nodes[1]).getArgs(cxt);
|
||||||
builtins.at(identifier.identifier).execute(*this, args);
|
return builtins.at(identifier).execute(cxt, args);
|
||||||
// TODO: handle returns
|
|
||||||
return Nil();
|
|
||||||
} else if (ast.name == "STRINGLITERALSINGLE")
|
} else if (ast.name == "STRINGLITERALSINGLE")
|
||||||
{
|
{
|
||||||
return ast.token_to_string();
|
return ast.token_to_string();
|
||||||
} else if (ast.name == "ExprList") {
|
} else if (ast.name == "ExprList") {
|
||||||
std::vector<std::any> exprs;
|
Args exprs;
|
||||||
for (int i=0; i<ast.nodes.size(); i++) {
|
for (int i=0; i<ast.nodes.size(); i++) {
|
||||||
exprs.push_back(getValue(eval(*nodes[i])));
|
exprs.args.push_back(getValue(eval(*nodes[i])));
|
||||||
}
|
}
|
||||||
return exprs;
|
return Value(exprs);
|
||||||
} else if (ast.name == "AdditionExpr") {
|
} else if (ast.name == "AdditionExpr") {
|
||||||
auto value = getValue(eval(*nodes[0]));
|
Value value = getValue(eval(*nodes[0]));
|
||||||
for (int i=1; i<nodes.size(); i+=2) {
|
for (int i=1; i<nodes.size(); i+=2) {
|
||||||
int op = (*nodes[i]).choice;
|
int op = (*nodes[i]).choice;
|
||||||
auto v2 = getValue(eval(*nodes[i+1]));
|
Value v2 = getValue(eval(*nodes[i+1]));
|
||||||
// TODO: floats
|
// TODO: floats
|
||||||
if (op == 0) {
|
if (op == 0) {
|
||||||
value = any_cast<long>(value) + any_cast<long>(v2);
|
value = Value(value.getInt(cxt) + v2.getInt(cxt));
|
||||||
} else {
|
} else {
|
||||||
value = any_cast<long>(value) - any_cast<long>(v2);
|
value = Value(value.getInt(cxt) - v2.getInt(cxt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
} else if (ast.name == "MultiplyExpr") {
|
} else if (ast.name == "MultiplyExpr") {
|
||||||
auto value = getValue(eval(*nodes[0]));
|
Value value = getValue(eval(*nodes[0]));
|
||||||
for (int i=1; i<nodes.size(); i+=2) {
|
for (int i=1; i<nodes.size(); i+=2) {
|
||||||
int op = (*nodes[i]).choice;
|
int op = (*nodes[i]).choice;
|
||||||
auto v2 = getValue(eval(*nodes[i+1]));
|
Value v2 = getValue(eval(*nodes[i+1]));
|
||||||
// TODO: floats
|
// TODO: floats
|
||||||
if (op == 0) {
|
if (op == 0) {
|
||||||
value = any_cast<long>(value) * any_cast<long>(v2);
|
value = Value(value.getInt(cxt) * v2.getInt(cxt));
|
||||||
} else {
|
} else {
|
||||||
value = any_cast<long>(value) / any_cast<long>(v2);
|
value = Value(value.getInt(cxt) / v2.getInt(cxt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
} else if (ast.name == "AssignExpr") {
|
} else if (ast.name == "AssignExpr") {
|
||||||
std::string name = any_cast<Identifier>(eval(*nodes[0])).identifier;
|
std::string name = eval(*nodes[0]).getIdentifier(cxt).identifier;
|
||||||
// TODO arrays, dot operator, etc.
|
// TODO arrays, dot operator, etc.
|
||||||
auto v1 = currentScope->getVar(*this, name);
|
auto v1 = currentScope->getVar(*this, name);
|
||||||
int op = (*nodes[1]).choice;
|
int op = (*nodes[1]).choice;
|
||||||
auto v2 = getValue(eval(*nodes[2]));
|
auto v2 = getValue(eval(*nodes[2]));
|
||||||
std::any result;
|
Value result = Value(Nil());
|
||||||
// TODO: floats
|
// TODO: floats
|
||||||
if (op == 0) {
|
if (op == 0) {
|
||||||
result = any_cast<long>(v1) * any_cast<long>(v2);
|
result = Value(v1.getInt(cxt) * v2.getInt(cxt));
|
||||||
} else if (op == 1) {
|
} else if (op == 1) {
|
||||||
result = any_cast<long>(v1) % any_cast<long>(v2);
|
result = Value(v1.getInt(cxt) % v2.getInt(cxt));
|
||||||
} else if (op == 2) {
|
} else if (op == 2) {
|
||||||
result = any_cast<long>(v1) + any_cast<long>(v2);
|
result = Value(v1.getInt(cxt) + v2.getInt(cxt));
|
||||||
} else if (op == 3) {
|
} else if (op == 3) {
|
||||||
result = any_cast<long>(v1) - any_cast<long>(v2);
|
result = Value(v1.getInt(cxt) - v2.getInt(cxt));
|
||||||
} else if (op == 4) {
|
} else if (op == 4) {
|
||||||
result = any_cast<long>(v1) & any_cast<long>(v2);
|
result = Value(v1.getInt(cxt) & v2.getInt(cxt));
|
||||||
} else if (op == 5) {
|
} else if (op == 5) {
|
||||||
result = any_cast<long>(v1) ^ any_cast<long>(v2);
|
result = Value(v1.getInt(cxt) ^ v2.getInt(cxt));
|
||||||
} else if (op == 6) {
|
} else if (op == 6) {
|
||||||
result = any_cast<long>(v1) | any_cast<long>(v2);
|
result = Value(v1.getInt(cxt) | v2.getInt(cxt));
|
||||||
} else if (op == 7) {
|
} else if (op == 7) {
|
||||||
result = v2;
|
result = v2;
|
||||||
}
|
}
|
||||||
@ -118,58 +115,62 @@ std::any Context::eval(peg::Ast& ast) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (ast.name == "CompareExpr") {
|
} else if (ast.name == "CompareExpr") {
|
||||||
auto v1 = getValue(eval(*nodes[0]));
|
Value v1 = getValue(eval(*nodes[0]));
|
||||||
int op = (*nodes[1]).choice;
|
int op = (*nodes[1]).choice;
|
||||||
auto v2 = getValue(eval(*nodes[2]));
|
Value v2 = getValue(eval(*nodes[2]));
|
||||||
// TODO: floats, bool, etc.
|
// TODO: floats, bool, etc.
|
||||||
if (op == 0) {
|
if (op == 0) {
|
||||||
return (bool)(any_cast<long>(v1) == any_cast<long>(v2));
|
return (bool)(v1.getInt(cxt) == v2.getInt(cxt));
|
||||||
} else if (op == 1) {
|
} else if (op == 1) {
|
||||||
return (bool)(any_cast<long>(v1) != any_cast<long>(v2));
|
return (bool)(v1.getInt(cxt) != v2.getInt(cxt));
|
||||||
} else if (op == 2) {
|
} else if (op == 2) {
|
||||||
return (bool)(any_cast<long>(v1) < any_cast<long>(v2));
|
return (bool)(v1.getInt(cxt) < v2.getInt(cxt));
|
||||||
} else if (op == 3) {
|
} else if (op == 3) {
|
||||||
return (bool)(any_cast<long>(v1) > any_cast<long>(v2));
|
return (bool)(v1.getInt(cxt) > v2.getInt(cxt));
|
||||||
} else if (op == 4) {
|
} else if (op == 4) {
|
||||||
return (bool)(any_cast<long>(v1) <= any_cast<long>(v2));
|
return (bool)(v1.getInt(cxt) <= v2.getInt(cxt));
|
||||||
} else if (op == 5) {
|
} else if (op == 5) {
|
||||||
return (bool)(any_cast<long>(v1) >= any_cast<long>(v2));
|
return (bool)(v1.getInt(cxt) >= v2.getInt(cxt));
|
||||||
}
|
}
|
||||||
} else if (ast.name == "IfStatement") {
|
} else if (ast.name == "IfStatement") {
|
||||||
auto val = getValue(eval(*nodes[0]));
|
Value val = getValue(eval(*nodes[0]));
|
||||||
if (any_cast<bool>(val)) {
|
if (val.getBoolean(cxt)) {
|
||||||
return eval(*nodes[1]);
|
return eval(*nodes[1]);
|
||||||
} else {
|
} else {
|
||||||
return eval(*nodes[2]);
|
return eval(*nodes[2]);
|
||||||
}
|
}
|
||||||
} else if (ast.name == "Block") {
|
} else if (ast.name == "Block") {
|
||||||
// TODO create new scope
|
// TODO create new scope
|
||||||
std::any result = Nil();
|
Value result = Value(Nil());
|
||||||
for (int i=0; i<ast.nodes.size(); i++) {
|
for (int i=0; i<ast.nodes.size(); i++) {
|
||||||
result = eval(*nodes[i]);
|
result = eval(*nodes[i]);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else if (ast.name == "WhileStatement") {
|
} else if (ast.name == "WhileStatement") {
|
||||||
std::any result = Nil();
|
Value result = Nil();
|
||||||
while (any_cast<bool>(getValue(eval(*nodes[0])))) {
|
while (getValue(eval(*nodes[0])).getBoolean(cxt)) {
|
||||||
result = eval(*nodes[1]);
|
result = eval(*nodes[1]);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else if (ast.name == "Fn") {
|
} else if (ast.name == "Fn") {
|
||||||
auto identifiers = any_cast<std::vector<Identifier>>(eval(*nodes[0]));
|
Args args = eval(*nodes[0]).getArgs(cxt);
|
||||||
|
std::vector<Identifier> identifiers;
|
||||||
|
for (int i=0; i<args.args.size(); i++) {
|
||||||
|
identifiers.push_back(args.args[i].getIdentifier(cxt));
|
||||||
|
}
|
||||||
return Func(nodes[1], identifiers);
|
return Func(nodes[1], identifiers);
|
||||||
} else if (ast.name == "ParamDeclList") {
|
} else if (ast.name == "ParamDeclList") {
|
||||||
std::vector<Identifier> identifiers;
|
Args identifiers;
|
||||||
for (int i=0; i<nodes.size(); i++) {
|
for (int i=0; i<nodes.size(); i++) {
|
||||||
identifiers.push_back(any_cast<Identifier>(eval(*nodes[i])));
|
identifiers.args.push_back(Value(eval(*nodes[i]).getIdentifier(cxt)));
|
||||||
}
|
}
|
||||||
return identifiers;
|
return identifiers;
|
||||||
} else if (ast.name == "SuffixExpr") {
|
} else if (ast.name == "SuffixExpr") {
|
||||||
// TODO handle other PrimaryTypeExpr types
|
// TODO handle other PrimaryTypeExpr types
|
||||||
auto val = getValue(eval(*nodes[0]));
|
Value val = getValue(eval(*nodes[0]));
|
||||||
auto func = any_cast<Func>(val);
|
Func func = val.getFunction(cxt);
|
||||||
for (int i=1; i<nodes.size(); i++) {
|
for (int i=1; i<nodes.size(); i++) {
|
||||||
auto args = Args::toArgs(*this, eval(*nodes[i]));
|
Args args = eval(*nodes[i]).getArgs(cxt);
|
||||||
return func.execute(*this, args);
|
return func.execute(*this, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <cpp-peglib/peglib.h>
|
||||||
|
|
||||||
#include "Scope.h"
|
#include "Scope.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -13,8 +14,8 @@ public:
|
|||||||
std::shared_ptr<Scope> currentScope;
|
std::shared_ptr<Scope> currentScope;
|
||||||
public:
|
public:
|
||||||
void error(std::string_view msg);
|
void error(std::string_view msg);
|
||||||
std::any eval(peg::Ast& ast);
|
Value eval(peg::Ast& ast);
|
||||||
protected:
|
protected:
|
||||||
std::any readIdentifier(std::any val);
|
Value readIdentifier(Value val);
|
||||||
std::any getValue(std::any input);
|
Value getValue(Value input);
|
||||||
};
|
};
|
12
src/main.cpp
12
src/main.cpp
@ -5,7 +5,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "util.h"
|
#include "types.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
peg::parser parser(
|
peg::parser parser(
|
||||||
@ -26,11 +26,11 @@ int main(void) {
|
|||||||
} else {
|
} else {
|
||||||
@print("neigh");
|
@print("neigh");
|
||||||
}
|
}
|
||||||
a = 10;
|
// a = 10000000;
|
||||||
while(a > 0) {
|
// while(a > 0) {
|
||||||
a -= 1;
|
// a -= 1;
|
||||||
@print(a);
|
// // @print(a);
|
||||||
}
|
// }
|
||||||
var hello = fn(abc) {
|
var hello = fn(abc) {
|
||||||
@print(abc);
|
@print(abc);
|
||||||
};
|
};
|
||||||
|
221
src/types.cpp
Normal file
221
src/types.cpp
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
|
|
||||||
|
// Args Args::toArgs(Context& cxt, Value input) {
|
||||||
|
// Args args;
|
||||||
|
// if (input.type() == typeid(std::vector<std::any>)) {
|
||||||
|
// args.args = std::any_cast<std::vector<std::any>>(input);
|
||||||
|
// } else {
|
||||||
|
// cxt.error("Unimplemented toArgs");
|
||||||
|
// }
|
||||||
|
// return args;
|
||||||
|
// }
|
||||||
|
|
||||||
|
Value Func::execute(Context& cxt, Args& args) {
|
||||||
|
if (ast == nullptr) {
|
||||||
|
return nativeFunction(cxt, args);
|
||||||
|
} else {
|
||||||
|
// TODO create scope
|
||||||
|
Value result = Value(Nil());
|
||||||
|
for (int i=0; i<args.args.size(); i++) {
|
||||||
|
cxt.currentScope->writeVar(cxt, argNames[i].identifier, args.args[i]);
|
||||||
|
}
|
||||||
|
result = cxt.eval(*ast);
|
||||||
|
// TODO tear down scope
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::Value(Nil nil) : type(TypeNil) {
|
||||||
|
value.nil = Nil();
|
||||||
|
}
|
||||||
|
Value::Value(long int_) : type(TypeInt) {
|
||||||
|
value.int_ = int_;
|
||||||
|
}
|
||||||
|
Value::Value(double float_) : type(TypeFloat) {
|
||||||
|
value.float_ = float_;
|
||||||
|
}
|
||||||
|
Value::Value(bool bool_) : type(TypeBoolean) {
|
||||||
|
value.bool_ = bool_;
|
||||||
|
}
|
||||||
|
Value::Value(const std::string &string) : type(TypeString) {
|
||||||
|
value.string = new std::string(string);
|
||||||
|
}
|
||||||
|
Value::Value(const Func &function) : type(TypeFunction) {
|
||||||
|
value.function = new Func(function);
|
||||||
|
}
|
||||||
|
Value::Value(const Args &args) : type(TypeArgs) {
|
||||||
|
value.args = new Args(args);
|
||||||
|
}
|
||||||
|
Value::Value(const Identifier &identifier) : type(TypeIdentifier) {
|
||||||
|
value.identifier = new Identifier(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::Value(const Value &val) {
|
||||||
|
type = val.type;
|
||||||
|
if (isNil()) {
|
||||||
|
value.nil = Nil();
|
||||||
|
} else if (isInt()) {
|
||||||
|
value.int_ = val.value.int_;
|
||||||
|
} else if (isFloat()) {
|
||||||
|
value.float_ = val.value.float_;
|
||||||
|
} else if (isBoolean()) {
|
||||||
|
value.bool_ = val.value.bool_;
|
||||||
|
} else if (isString()) {
|
||||||
|
value.string = new std::string(*val.value.string);
|
||||||
|
} else if (isFunction()) {
|
||||||
|
value.function = new Func(*val.value.function);
|
||||||
|
} else if (isArgs()) {
|
||||||
|
value.args = new Args(*val.value.args);
|
||||||
|
} else if (isIdentifier()) {
|
||||||
|
value.identifier = new Identifier(*val.value.identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Value& Value::operator=(const Value &rhs) {
|
||||||
|
type = rhs.type;
|
||||||
|
if (isNil()) {
|
||||||
|
value.nil = Nil();
|
||||||
|
} else if (isInt()) {
|
||||||
|
value.int_ = rhs.value.int_;
|
||||||
|
} else if (isFloat()) {
|
||||||
|
value.float_ = rhs.value.float_;
|
||||||
|
} else if (isBoolean()) {
|
||||||
|
value.bool_ = rhs.value.bool_;
|
||||||
|
} else if (isString()) {
|
||||||
|
value.string = new std::string(*rhs.value.string);
|
||||||
|
} else if (isFunction()) {
|
||||||
|
value.function = new Func(*rhs.value.function);
|
||||||
|
} else if (isArgs()) {
|
||||||
|
value.args = new Args(*rhs.value.args);
|
||||||
|
} else if (isIdentifier()) {
|
||||||
|
value.identifier = new Identifier(*rhs.value.identifier);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::~Value() {
|
||||||
|
if (isString()) {
|
||||||
|
delete value.string;
|
||||||
|
} else if (isFunction()) {
|
||||||
|
delete value.function;
|
||||||
|
} else if (isArgs()) {
|
||||||
|
delete value.args;
|
||||||
|
} else if (isIdentifier()) {
|
||||||
|
delete value.identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Value::isNil() {
|
||||||
|
return type == TypeNil;
|
||||||
|
}
|
||||||
|
bool Value::isInt() {
|
||||||
|
return type == TypeInt;
|
||||||
|
}
|
||||||
|
bool Value::isFloat() {
|
||||||
|
return type == TypeFloat;
|
||||||
|
}
|
||||||
|
bool Value::isNumber() {
|
||||||
|
return isInt() || isFloat();
|
||||||
|
}
|
||||||
|
bool Value::isBoolean() {
|
||||||
|
return type == TypeBoolean;
|
||||||
|
}
|
||||||
|
bool Value::isString() {
|
||||||
|
return type == TypeString;
|
||||||
|
}
|
||||||
|
bool Value::isFunction() {
|
||||||
|
return type == TypeFunction;
|
||||||
|
}
|
||||||
|
bool Value::isArgs() {
|
||||||
|
return type == TypeArgs;
|
||||||
|
}
|
||||||
|
bool Value::isIdentifier() {
|
||||||
|
return type == TypeIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::assertNil(Context &cxt) {
|
||||||
|
if (!isNil()) {
|
||||||
|
cxt.error("value is not nil");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Value::assertInt(Context &cxt) {
|
||||||
|
if (!isInt()) {
|
||||||
|
cxt.error("value is not an integer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Value::assertFloat(Context &cxt) {
|
||||||
|
if (!isFloat()) {
|
||||||
|
cxt.error("value is not a float");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Value::assertNumber(Context &cxt) {
|
||||||
|
if (!isNumber()) {
|
||||||
|
cxt.error("value is not a number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Value::assertBoolean(Context &cxt) {
|
||||||
|
if (!isBoolean()) {
|
||||||
|
cxt.error("value is not a boolean");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Value::assertString(Context &cxt) {
|
||||||
|
if (!isString()) {
|
||||||
|
cxt.error("value is not a string");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Value::assertFunction(Context &cxt) {
|
||||||
|
if (!isFunction()) {
|
||||||
|
cxt.error("value is not a function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Value::assertArgs(Context &cxt) {
|
||||||
|
if (!isArgs()) {
|
||||||
|
cxt.error("value is not arguments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Value::assertIdentifier(Context &cxt) {
|
||||||
|
if (!isIdentifier()) {
|
||||||
|
cxt.error("value is not identifier");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Nil Value::getNil(Context &cxt) {
|
||||||
|
assertNil(cxt);
|
||||||
|
return value.nil;
|
||||||
|
}
|
||||||
|
long Value::getInt(Context &cxt) {
|
||||||
|
assertNumber(cxt);
|
||||||
|
if (isFloat())
|
||||||
|
return (long)value.float_;
|
||||||
|
else
|
||||||
|
return value.int_;
|
||||||
|
}
|
||||||
|
double Value::getFloat(Context &cxt) {
|
||||||
|
assertNumber(cxt);
|
||||||
|
if (isInt())
|
||||||
|
return (double)value.int_;
|
||||||
|
else
|
||||||
|
return value.float_;
|
||||||
|
}
|
||||||
|
bool Value::getBoolean(Context &cxt) {
|
||||||
|
assertBoolean(cxt);
|
||||||
|
return value.bool_;
|
||||||
|
}
|
||||||
|
std::string Value::getString(Context &cxt) {
|
||||||
|
assertString(cxt);
|
||||||
|
return *value.string;
|
||||||
|
}
|
||||||
|
Func Value::getFunction(Context &cxt) {
|
||||||
|
assertFunction(cxt);
|
||||||
|
return *value.function;
|
||||||
|
}
|
||||||
|
Args Value::getArgs(Context &cxt) {
|
||||||
|
assertArgs(cxt);
|
||||||
|
return *value.args;
|
||||||
|
}
|
||||||
|
Identifier Value::getIdentifier(Context &cxt) {
|
||||||
|
assertIdentifier(cxt);
|
||||||
|
return *value.identifier;
|
||||||
|
}
|
127
src/types.h
Normal file
127
src/types.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <cpp-peglib/peglib.h>
|
||||||
|
|
||||||
|
class Context;
|
||||||
|
class Identifier;
|
||||||
|
class Value;
|
||||||
|
class Scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arguments passed to a function and also results returned from a function
|
||||||
|
*/
|
||||||
|
class Args {
|
||||||
|
public:
|
||||||
|
std::vector<Value> args;
|
||||||
|
// static Args toArgs(Context& cxt, Value input);
|
||||||
|
};
|
||||||
|
|
||||||
|
// represents the 'nil' type
|
||||||
|
class Nil {
|
||||||
|
};
|
||||||
|
|
||||||
|
class Identifier {
|
||||||
|
public:
|
||||||
|
std::string identifier;
|
||||||
|
Identifier(std::string id) : identifier(id) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function - captured scope, ast ptr OR native function
|
||||||
|
class Func {
|
||||||
|
public:
|
||||||
|
std::shared_ptr<Scope> capturedScope;
|
||||||
|
|
||||||
|
std::shared_ptr<peg::Ast> ast = nullptr;
|
||||||
|
std::vector<Identifier> argNames;
|
||||||
|
|
||||||
|
std::function<Value(Context&,Args&)> nativeFunction;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create a native function
|
||||||
|
*/
|
||||||
|
Func(std::function<Value(Context&,Args&)> nativeFunction)
|
||||||
|
: capturedScope(nullptr), nativeFunction(nativeFunction) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an interpreted function
|
||||||
|
*/
|
||||||
|
Func(std::shared_ptr<peg::Ast> ast, std::vector<Identifier> argNames)
|
||||||
|
: ast(ast), argNames(argNames) {}
|
||||||
|
|
||||||
|
Value execute(Context& cxt, Args& args);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Value {
|
||||||
|
protected:
|
||||||
|
enum Type {
|
||||||
|
TypeNil,
|
||||||
|
TypeInt,
|
||||||
|
TypeFloat,
|
||||||
|
TypeBoolean,
|
||||||
|
TypeString,
|
||||||
|
TypeFunction,
|
||||||
|
|
||||||
|
// Internal types
|
||||||
|
TypeArgs,
|
||||||
|
TypeIdentifier,
|
||||||
|
};
|
||||||
|
union TypeValues {
|
||||||
|
Nil nil;
|
||||||
|
long int_;
|
||||||
|
double float_;
|
||||||
|
bool bool_;
|
||||||
|
std::string *string;
|
||||||
|
Func *function;
|
||||||
|
Args *args;
|
||||||
|
Identifier *identifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
TypeValues value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Value(Nil nil);
|
||||||
|
Value(long int_);
|
||||||
|
Value(double float_);
|
||||||
|
Value(bool bool_);
|
||||||
|
Value(const std::string &string);
|
||||||
|
Value(const Func &function);
|
||||||
|
Value(const Args &args);
|
||||||
|
Value(const Identifier &identifier);
|
||||||
|
|
||||||
|
Value(const Value &value);
|
||||||
|
Value& operator=(const Value &rhs);
|
||||||
|
~Value();
|
||||||
|
|
||||||
|
bool isNil();
|
||||||
|
bool isInt();
|
||||||
|
bool isFloat();
|
||||||
|
bool isNumber();
|
||||||
|
bool isBoolean();
|
||||||
|
bool isString();
|
||||||
|
bool isFunction();
|
||||||
|
bool isArgs();
|
||||||
|
bool isIdentifier();
|
||||||
|
|
||||||
|
void assertNil(Context &cxt);
|
||||||
|
void assertInt(Context &cxt);
|
||||||
|
void assertFloat(Context &cxt);
|
||||||
|
void assertNumber(Context &cxt);
|
||||||
|
void assertBoolean(Context &cxt);
|
||||||
|
void assertString(Context &cxt);
|
||||||
|
void assertFunction(Context &cxt);
|
||||||
|
void assertArgs(Context &cxt);
|
||||||
|
void assertIdentifier(Context &cxt);
|
||||||
|
|
||||||
|
Nil getNil(Context &cxt);
|
||||||
|
long getInt(Context &cxt);
|
||||||
|
double getFloat(Context &cxt);
|
||||||
|
bool getBoolean(Context &cxt);
|
||||||
|
std::string getString(Context &cxt);
|
||||||
|
Func getFunction(Context &cxt);
|
||||||
|
Args getArgs(Context &cxt);
|
||||||
|
Identifier getIdentifier(Context &cxt);
|
||||||
|
};
|
46
src/util.cpp
46
src/util.cpp
@ -1,48 +1,24 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
Args Args::toArgs(Context& cxt, std::any input) {
|
Value BuiltinFunctions::print(Context& cxt, Args& args) {
|
||||||
Args args;
|
|
||||||
if (input.type() == typeid(std::vector<std::any>)) {
|
|
||||||
args.args = std::any_cast<std::vector<std::any>>(input);
|
|
||||||
} else {
|
|
||||||
cxt.error("Unimplemented toArgs");
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::any Func::execute(Context& cxt, Args& args) {
|
|
||||||
if (ast == nullptr) {
|
|
||||||
return nativeFunction(cxt, args);
|
|
||||||
} else {
|
|
||||||
// TODO create scope
|
|
||||||
std::any result;
|
|
||||||
for (int i=0; i<args.args.size(); i++) {
|
|
||||||
cxt.currentScope->writeVar(cxt, argNames[i].identifier, args.args[i]);
|
|
||||||
}
|
|
||||||
result = cxt.eval(*ast);
|
|
||||||
// TODO tear down scope
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::any BuiltinFunctions::print(Context& cxt, Args& args) {
|
|
||||||
for (int i=0; i<args.args.size(); i++) {
|
for (int i=0; i<args.args.size(); i++) {
|
||||||
std::any var = args.args[i];
|
Value var = args.args[i];
|
||||||
if (var.type() == typeid(long)) {
|
if (var.isInt()) {
|
||||||
std::cout << std::any_cast<long>(var) << '\t';
|
std::cout << var.getInt(cxt) << '\t';
|
||||||
} else if (var.type() == typeid(std::string)) {
|
} else if (var.isString()) {
|
||||||
std::cout << std::any_cast<std::string>(var) << '\t';
|
std::cout << var.getString(cxt) << '\t';
|
||||||
} else if (var.type() == typeid(bool)) {
|
} else if (var.isBoolean()) {
|
||||||
bool v = std::any_cast<bool>(var);
|
if (var.getBoolean(cxt))
|
||||||
if (v)
|
|
||||||
std::cout << "true" << '\t';
|
std::cout << "true" << '\t';
|
||||||
else
|
else
|
||||||
std::cout << "false" << '\t';
|
std::cout << "false" << '\t';
|
||||||
} else if (var.type() == typeid(Nil)) {
|
} else if (var.isNil()) {
|
||||||
std::cout << "nil" << '\t';
|
std::cout << "nil" << '\t';
|
||||||
} else {
|
} else {
|
||||||
cxt.error("Attempt to print unsupported type");
|
cxt.error("Attempt to print unsupported type");
|
||||||
|
59
src/util.h
59
src/util.h
@ -1,63 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cpp-peglib/peglib.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <any>
|
|
||||||
#include <vector>
|
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
class Scope;
|
class Value;
|
||||||
|
class Args;
|
||||||
// represents the 'nil' type
|
|
||||||
class Nil {
|
|
||||||
};
|
|
||||||
|
|
||||||
class Identifier {
|
|
||||||
public:
|
|
||||||
std::string identifier;
|
|
||||||
Identifier(std::string id) : identifier(id) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Arguments passed to a function and also results returned from a function
|
|
||||||
*/
|
|
||||||
class Args {
|
|
||||||
public:
|
|
||||||
std::vector<std::any> args;
|
|
||||||
static Args toArgs(Context& cxt, std::any input);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function - captured scope, ast ptr OR native function
|
|
||||||
class Func {
|
|
||||||
public:
|
|
||||||
std::shared_ptr<Scope> capturedScope;
|
|
||||||
|
|
||||||
std::shared_ptr<peg::Ast> ast = nullptr;
|
|
||||||
std::vector<Identifier> argNames;
|
|
||||||
|
|
||||||
std::function<std::any(Context&,Args&)> nativeFunction;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a native function
|
|
||||||
*/
|
|
||||||
Func(std::function<std::any(Context&,Args&)> nativeFunction)
|
|
||||||
: capturedScope(nullptr), nativeFunction(nativeFunction) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an interpreted function
|
|
||||||
*/
|
|
||||||
Func(std::shared_ptr<peg::Ast> ast, std::vector<Identifier> argNames)
|
|
||||||
: ast(ast), argNames(argNames) {}
|
|
||||||
|
|
||||||
std::any execute(Context& cxt, Args& args);
|
|
||||||
};
|
|
||||||
|
|
||||||
class BuiltinFunctions {
|
class BuiltinFunctions {
|
||||||
public:
|
public:
|
||||||
static std::any print(Context& cxt, Args& args);
|
static Value print(Context& cxt, Args& args);
|
||||||
};
|
};
|
Loading…
x
Reference in New Issue
Block a user