diff --git a/src/Scope.cpp b/src/Scope.cpp new file mode 100644 index 0000000..db9b6fe --- /dev/null +++ b/src/Scope.cpp @@ -0,0 +1,36 @@ +#include "Scope.h" + +#include + +bool Scope::varExists(Context& ctx, std::string name) { + if (vars.find(name) == vars.end()) { + if (parentScope.get() == nullptr) { + return false; + } else { + return parentScope.get()->varExists(ctx, name); + } + } else { + return true; + } +} + +std::any& Scope::getVar(Context& cxt, std::string name) { + if (vars.find(name) == vars.end()) { + if (varExists(cxt, name)) { + return parentScope.get()->getVar(cxt, name); + } else { + // doesn't exist at all + throw new std::exception(); + } + } + return vars.at(name); +} + +void Scope::writeVar(Context& cxt, std::string name, std::any& var) { + if (vars.find(name) == vars.end()) { + if (varExists(cxt, name)) { + parentScope.get()->writeVar(cxt, name, var); + } + } + vars.insert_or_assign(name, var); +} \ No newline at end of file diff --git a/src/Scope.h b/src/Scope.h new file mode 100644 index 0000000..7d4dc9e --- /dev/null +++ b/src/Scope.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include + +class Context; + +// Scope - parent scope, local variables, return handler, continue handler, break handler +class Scope { +public: + std::shared_ptr parentScope; + std::unordered_map vars; + // std::function returnHandler; + // std::function breakHandler; + // std::function continueHandler; + +public: + Scope(std::shared_ptr parentScope) : parentScope(parentScope) { + } + + bool varExists(Context& ctx, std::string name); + + /** + * Looks up var and creates it in the current scope if it doesn't exist + */ + std::any& getVar(Context& cxt, std::string name); + + void writeVar(Context& cxt, std::string name, std::any& var); +}; \ No newline at end of file diff --git a/src/context.cpp b/src/context.cpp new file mode 100644 index 0000000..97b8b91 --- /dev/null +++ b/src/context.cpp @@ -0,0 +1,7 @@ +#include "context.h" + +#include + +void Context::error(std::string_view msg) { + std::cout << "Error! " << msg << std::endl; +} \ No newline at end of file diff --git a/src/context.h b/src/context.h new file mode 100644 index 0000000..5d1aabd --- /dev/null +++ b/src/context.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include + +#include "Scope.h" +#include "util.h" + +class Context { +public: + std::unordered_map builtins; + std::shared_ptr currentScope; +public: + void error(std::string_view msg); +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 480d2cc..ddc4df2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,7 +2,9 @@ #include #include #include -#include + +#include "context.h" +#include "util.h" using peg::SemanticValues; using std::any_cast; @@ -54,137 +56,6 @@ int main_old(void) { return 0; } -class Func; -class Scope; -class Identifier; - -// represents the 'nil' type -class Nil { -}; - -class Context { -public: - std::unordered_map builtins; - std::shared_ptr currentScope; -public: - void error(std::string_view msg) { - std::cout << "Error! " << msg << std::endl; - } -}; - -class Identifier { -public: - std::string identifier; - Identifier(std::string id) : identifier(id) {} -}; - -// table, function, number, string -// enum Type { -// Type_Table, -// Type_Function, -// Type_Number, -// Type_String, -// }; - -// Scope - parent scope, local variables, return handler, continue handler, break handler -class Scope { -public: - std::shared_ptr parentScope; - std::unordered_map vars; - // std::function returnHandler; - // std::function breakHandler; - // std::function continueHandler; - -public: - Scope(std::shared_ptr parentScope) : parentScope(parentScope) { - } - - bool varExists(Context& ctx, std::string_view name) { - if (vars.find(name) == vars.end()) { - if (parentScope.get() == nullptr) { - return false; - } else { - return parentScope.get()->varExists(ctx, name); - } - } else { - return true; - } - } - - /** - * Looks up var and creates it in the current scope if it doesn't exist - */ - std::any& getVar(Context& cxt, std::string_view name) { - if (vars.find(name) == vars.end()) { - if (varExists(cxt, name)) { - return parentScope.get()->getVar(cxt, name); - } else { - // doesn't exist at all - throw new std::exception(); - } - } - return vars.at(name); - } - - void writeVar(Context& cxt, std::string_view name, std::any& var) { - if (vars.find(name) == vars.end()) { - if (varExists(cxt, name)) { - parentScope.get()->writeVar(cxt, name, var); - } - } - vars.insert_or_assign(name, var); - } -}; - -/** - * Arguments passed to a function and also results returned from a function - */ -class Args { -public: - std::vector args; - static Args toArgs(Context& cxt, std::any input) { - Args args; - if (input.type() == typeid(Identifier)) { - auto id = any_cast(input); - auto value = cxt.currentScope->getVar(cxt, id.identifier); - args.args.push_back(value); - } - return args; - } -}; - -// Function - captured scope, ast ptr OR native function -class Func { -public: - std::shared_ptr capturedScope; - // ast ptr - std::function nativeFunction; - -public: - Func(std::function nativeFunction) - : capturedScope(nullptr), nativeFunction(nativeFunction) {} - - void execute(Context& cxt, Args& args) { - // TODO implement AST executer - nativeFunction(cxt, args); - } -}; - -class BuiltinFunctions { -public: - static void print(Context& cxt, Args& args) { - for (int i=0; i(var) << '\t'; - } else { - cxt.error("Attempt to print unsupported type"); - } - } - std::cout << std::endl; - } -}; - std::any eval(Context &cxt, peg::Ast& ast) { const auto &nodes = ast.nodes; if (ast.name == "Root") { @@ -198,7 +69,7 @@ std::any eval(Context &cxt, peg::Ast& ast) { cxt.currentScope->writeVar(cxt, identifier.identifier, value); return Nil(); } else if (ast.name == "IDENTIFIER" || ast.name == "BUILTINIDENTIFIER") { - return Identifier(ast.token_to_string()); + return Identifier(std::string(ast.token_to_string())); } else if (ast.name == "INTEGER") { // TODO parse hex, oct, and binary return ast.token_to_number(); @@ -206,6 +77,8 @@ std::any eval(Context &cxt, peg::Ast& ast) { auto identifier = any_cast(eval(cxt, *nodes[0])); auto args = Args::toArgs(cxt, eval(cxt, *nodes[1])); cxt.builtins.at(identifier.identifier).execute(cxt, args); + // TODO: handle returns + return Nil(); } std::cout << "AST Name: " << ast.name << std::endl; diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..040468d --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,27 @@ +#include "util.h" + +#include "context.h" + +#include + +Args Args::toArgs(Context& cxt, std::any input) { + Args args; + if (input.type() == typeid(Identifier)) { + auto id = std::any_cast(input); + auto value = cxt.currentScope->getVar(cxt, id.identifier); + args.args.push_back(value); + } + return args; +} + +void BuiltinFunctions::print(Context& cxt, Args& args) { + for (int i=0; i(var) << '\t'; + } else { + cxt.error("Attempt to print unsupported type"); + } + } + std::cout << std::endl; +} \ No newline at end of file diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..9f6d364 --- /dev/null +++ b/src/util.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +class Context; +class Scope; + +// 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 args; + static Args toArgs(Context& cxt, std::any input); +}; + +// Function - captured scope, ast ptr OR native function +class Func { +public: + std::shared_ptr capturedScope; + // ast ptr + std::function nativeFunction; + +public: + Func(std::function nativeFunction) + : capturedScope(nullptr), nativeFunction(nativeFunction) {} + + void execute(Context& cxt, Args& args) { + // TODO implement AST executer + nativeFunction(cxt, args); + } +}; + +class BuiltinFunctions { +public: + static void print(Context& cxt, Args& args); +}; \ No newline at end of file