remove std::any

This commit is contained in:
zuckerberg 2021-07-12 13:29:30 -04:00
parent f2b4a53176
commit 186cab9ac9
9 changed files with 435 additions and 161 deletions

View File

@ -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);

View File

@ -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);
}; };

View File

@ -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);
} }
} }

View File

@ -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);
}; };

View File

@ -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
View 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
View 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);
};

View File

@ -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");

View File

@ -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);
}; };