Skip to content

Commit

Permalink
feat: add variables scopes in the form of trees of symboltables
Browse files Browse the repository at this point in the history
  • Loading branch information
sillydan1 committed Oct 11, 2022
1 parent d3df7d1 commit 8f5ec2b
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 69 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ option(ENABLE_Z3 "Enables the download and compilation of the expr::z3_driver dr

# DEPENDENCIES
CPMAddPackage("gh:yalibs/[email protected]")
CPMAddPackage("gh:yalibs/yatree@1.0.1")
CPMAddPackage("gh:yalibs/yatree#feature/parent")
CPMAddPackage("gh:yalibs/[email protected]")
CPMAddPackage("gh:yalibs/[email protected]")
CPMAddPackage("gh:sillydan1/[email protected]")
Expand Down Expand Up @@ -74,6 +74,7 @@ add_library(${PROJECT_NAME} SHARED
${BISON_expr_parser_OUTPUTS}
${FLEX_expr_lexer_OUTPUTS}
src/drivers/interpreter.cpp
src/drivers/tree_interpreter.cpp
src/drivers/compiler.cpp

src/clock.cpp
Expand Down
5 changes: 3 additions & 2 deletions include/drivers/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ namespace expr {
virtual auto get_symbol(const std::string &identifier) -> syntax_tree_t = 0;
virtual void add_tree(const syntax_tree_t& tree) = 0;
virtual void add_tree(const std::string& identifier, const syntax_tree_t& tree) = 0;
auto contains(const std::string& identifier) const -> bool {
virtual auto contains(const std::string& identifier) const -> bool {
return find(identifier) != end;
}
auto find(const std::string& identifier) const -> expr::symbol_table_t::const_iterator {
virtual auto find(const std::string& identifier) const -> expr::symbol_table_t::const_iterator {
// TODO: Tree of environments
for(auto& env : environments) {
auto env_it = env.get().find(identifier);
if(env_it != env.get().end())
Expand Down
51 changes: 51 additions & 0 deletions include/drivers/generic_symbol_operator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* MIT License
*
* Copyright (c) 2022 Asger Gitz-Johansen
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPR_GENERIC_SYMBOL_OPERATOR_H
#define EXPR_GENERIC_SYMBOL_OPERATOR_H
#include "operations.h"

namespace expr {
struct generic_symbol_operator : public arithmetic_operator, boolean_operator, compare_operator {
auto add(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return ::operator+(a,b); };
auto sub(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a - b; };
auto mul(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a * b; };
auto div(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a / b; };
auto mod(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a % b; };
auto pow(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a ^ b; };

auto _not(const symbol_value_t &a) const -> symbol_value_t override { return not_(a); }
auto _and(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return and_(a,b); }
auto _or(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return or_(a,b); }
auto _xor(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return xor_(a,b); }
auto _implies(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return implies_(a,b); }

auto gt(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return gt_(a,b); }
auto ge(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return ge_(a,b); }
auto ee(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return ee_(a,b); }
auto ne(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return ne_(a,b); }
auto le(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return le_(a,b); }
auto lt(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return lt_(a,b); }
};
}

#endif //EXPR_GENERIC_SYMBOL_OPERATOR_H
23 changes: 2 additions & 21 deletions include/drivers/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@
#include "operations.h"
#include "drivers/driver.h"
#include "compiler.h"
#include "generic_symbol_operator.h"

namespace expr {
struct interpreter : public driver, arithmetic_operator, boolean_operator, compare_operator {
struct interpreter : public driver, generic_symbol_operator {
interpreter(std::initializer_list<symbol_table_ref_t> environments);
~interpreter() override = default;

Expand All @@ -38,26 +39,6 @@ namespace expr {
void add_tree(const syntax_tree_t& tree) override;
void add_tree(const std::string& identifier, const syntax_tree_t& tree) override;

auto add(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return ::operator+(a,b); };
auto sub(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a - b; };
auto mul(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a * b; };
auto div(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a / b; };
auto mod(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a % b; };
auto pow(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return a ^ b; };

auto _not(const symbol_value_t &a) const -> symbol_value_t override { return not_(a); }
auto _and(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return and_(a,b); }
auto _or(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return or_(a,b); }
auto _xor(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return xor_(a,b); }
auto _implies(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return implies_(a,b); }

auto gt(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return gt_(a,b); }
auto ge(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return ge_(a,b); }
auto ee(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return ee_(a,b); }
auto ne(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return ne_(a,b); }
auto le(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return le_(a,b); }
auto lt(const symbol_value_t &a, const symbol_value_t &b) const -> symbol_value_t override { return lt_(a,b); }

symbol_table_t result{};
symbol_value_t expression_result{};

Expand Down
47 changes: 47 additions & 0 deletions include/drivers/tree_driver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* MIT License
*
* Copyright (c) 2022 Asger Gitz-Johansen
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPR_TREE_DRIVER_H
#define EXPR_TREE_DRIVER_H
#include "driver.h"

namespace expr {
struct tree_driver : public driver {
tree_driver(const symbol_table_tree_t::_left_df_iterator& it) : driver{}, it{it} {}
auto find(const std::string& identifier) const -> expr::symbol_table_t::const_iterator override {
auto* x = &(*it);
while(x) {
auto i = x->node.find(identifier);
if(i != x->node.end())
return i;
if(!x->parent().has_value())
return end;
x = x->parent().value();
}
return end;
}
private:
symbol_table_tree_t::_left_df_iterator it;
};
}

#endif //EXPR_TREE_DRIVER_H
27 changes: 27 additions & 0 deletions include/drivers/tree_interpreter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef EXPR_TREE_INTERPRETER_H
#define EXPR_TREE_INTERPRETER_H
#include "tree_driver.h"
#include "compiler.h"
#include "generic_symbol_operator.h"

namespace expr {
struct tree_interpreter : public tree_driver, generic_symbol_operator {
tree_interpreter(const symbol_table_tree_t::_left_df_iterator& it);
~tree_interpreter() override = default;

auto parse(const std::string &f) -> int override;
auto interpret_declarations(const std::string& f) -> symbol_table_t;
auto interpret_expression(const std::string& f) -> symbol_value_t;
auto get_symbol(const std::string& identifier) -> syntax_tree_t override;
void add_tree(const syntax_tree_t& tree) override;
void add_tree(const std::string& identifier, const syntax_tree_t& tree) override;

symbol_table_t result{};
symbol_value_t expression_result{};

auto evaluate(const syntax_tree_t& tree) -> symbol_value_t;
auto evaluate(const compiler::compiled_expr_collection_t& tree) -> symbol_table_t;
};
}

#endif //EXPR_TREE_INTERPRETER_H
7 changes: 4 additions & 3 deletions include/symbol_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace expr {
return *this;
}

symbol_value_t &interpret(const std::string &s) {
auto interpret(const std::string &s) -> symbol_value_t& {
std::stringstream ss{s};
int i;
float f;
Expand Down Expand Up @@ -87,6 +87,8 @@ namespace expr {
std::optional<expr::symbol_value_t> delay_amount{};
};

using symbol_table_tree_t = ya::tree<symbol_table_t>;

auto operator+(const symbol_table_t &a, const symbol_table_t &b) -> symbol_table_t;
auto operator<<(std::ostream &os, const symbol_value_t &v) -> std::ostream&;
auto operator<<(std::ostream &os, const symbol_table_t &m) -> std::ostream&;
Expand All @@ -100,7 +102,6 @@ namespace expr {

struct operator_t {
operator_type_t operator_type;

explicit operator_t(operator_type_t t) : operator_type{t} {}
};

Expand All @@ -123,7 +124,7 @@ namespace expr {
}
};

using syntax_tree_t = tree<syntax_node_t>;
using syntax_tree_t = ya::tree<syntax_node_t>;

auto operator<<(std::ostream &o, const operator_t &p) -> std::ostream &;
auto operator<<(std::ostream &o, const root_t &r) -> std::ostream &;
Expand Down
42 changes: 21 additions & 21 deletions src/drivers/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,32 +89,32 @@ namespace expr {
},
[&](const operator_t& o) {
switch (o.operator_type) {
case operator_type_t::minus: return sub(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::plus: return add(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::star: return mul(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::slash: return div(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::percent: return mod(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::hat: return pow(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::_and: return _and(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::_or: return _or(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::_xor: return _xor(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::_not: return _not(evaluate(tree.children[0]));
case operator_type_t::_implies: return _implies(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::gt: return gt(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::ge: return ge(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::ne: return ne(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::ee: return ee(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::le: return le(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::lt: return lt(evaluate(tree.children[0]), evaluate(tree.children[1]));
case operator_type_t::parentheses: return evaluate(tree.children[0]);
case operator_type_t::minus: return sub(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::plus: return add(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::star: return mul(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::slash: return div(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::percent: return mod(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::hat: return pow(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::_and: return _and(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::_or: return _or(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::_xor: return _xor(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::_not: return _not(evaluate(tree.children()[0]));
case operator_type_t::_implies: return _implies(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::gt: return gt(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::ge: return ge(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::ne: return ne(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::ee: return ee(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::le: return le(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::lt: return lt(evaluate(tree.children()[0]), evaluate(tree.children()[1]));
case operator_type_t::parentheses: return evaluate(tree.children()[0]);
}
throw std::logic_error("unsupported operator type");
},
[](const symbol_value_t& o){ return o; },
[&](const root_t& r){
if(!tree.children.empty())
return evaluate(tree.children[0]);
throw std::logic_error("ROOT has no children");
if(!tree.children().empty())
return evaluate(tree.children()[0]);
throw std::logic_error("ROOT has no children()");
},
[](auto&&){ throw std::logic_error("operator type not recognized"); }
), static_cast<const underlying_syntax_node_t&>(tree.node));
Expand Down
Loading

0 comments on commit 8f5ec2b

Please sign in to comment.