diff --git a/src/constants.hpp b/src/constants.hpp index 06c47ac..4f54aba 100644 --- a/src/constants.hpp +++ b/src/constants.hpp @@ -4,8 +4,10 @@ #define STATEMENT 200 #define CALLFUNC 201 +class Node; + // Share the line number between files extern int linenum; -extern struct Node* result; +extern Node* result; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1cd5110..c1bbddf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ void interpret_file(char* fileName); /* the result variable */ -struct Node* result; +Node* result; int main(int argc, char* argv[]) { if (argc == 1) { @@ -35,10 +35,8 @@ void interpret_file(char* fileName) { // Interpret the AST // print_tree(result, 0); // For debugging - struct Environment* env = new Environment(); + Environment* env = new Environment(); eval_statement(result, env); - delete_environment(env); - // delete env; - + delete env; delete result; } \ No newline at end of file diff --git a/src/operations/node.cpp b/src/operations/node.cpp index b679d46..8258ee1 100644 --- a/src/operations/node.cpp +++ b/src/operations/node.cpp @@ -8,20 +8,20 @@ #include "../variables/variable.hpp" /* attach an existing node onto a parent */ -void attach_node(struct Node* parent, struct Node* child) { +void attach_node(Node* parent, Node* child) { /* connect it */ parent->children[parent->num_children] = child; parent->num_children++; if (parent->num_children > MAX_CHILDREN) { std::cerr << "Error, max children attached to a node" << std::endl; } } -void check_num_nodes(struct Node* node, uint num_children, std::string error) { +void check_num_nodes(Node* node, uint num_children, std::string error) { if (node && node->num_children != num_children) { std::cerr << "Error, " << error << std::endl; } } -void print_tree(struct Node* node, uint tabs) { +void print_tree(Node* node, uint tabs) { uint i; /* base case */ if(!node) { @@ -74,7 +74,7 @@ void print_tree(struct Node* node, uint tabs) { } -struct Value* eval_expression(struct Node* node, struct Environment* env) { +Value* eval_expression(Node* node, Environment* env) { /* base case */ if(!node) { fprintf(stderr, "Error: No tree structure to evaluate\n"); @@ -83,14 +83,14 @@ struct Value* eval_expression(struct Node* node, struct Environment* env) { // Needed if we are going to take input from the user double temp; - struct Variable* var = nullptr; - struct Environment* local_env = nullptr; - struct Node* tempNode = nullptr; - struct Value* tempVal = nullptr; + Variable* var = nullptr; + Environment* local_env = nullptr; + Node* tempNode = nullptr; + Value* tempVal = nullptr; // Evaluate subexpressions if existent and node is not a lambda expression - struct Value* val1 = nullptr; - struct Value* val2 = nullptr; + Value* val1 = nullptr; + Value* val2 = nullptr; // struct Value* val3 = nullptr; if (node->num_children > 0 && node->type != LAMBDATAG) { val1 = eval_expression(node->children[0], env); @@ -112,8 +112,7 @@ struct Value* eval_expression(struct Node* node, struct Environment* env) { new Variable(tempNode->children[0]->id, // Get the name of the variable needed for the lambda expression eval_expression(node->children[1], env))); tempVal = eval_expression(tempNode->children[1], local_env); - delete_environment(local_env); - // delete local_env; + delete local_env; return tempVal; break; case PLUS: @@ -222,14 +221,14 @@ struct Value* eval_expression(struct Node* node, struct Environment* env) { } -void eval_statement(struct Node* node, struct Environment* env) { +void eval_statement(Node* node, Environment* env) { /* base case */ if(!node) { fprintf(stderr, "Error: No tree structure to evaluate\n"); return; } - struct Value* tempVal; + Value* tempVal; switch(node->type) { case ASSIGN: diff --git a/src/operations/node.hpp b/src/operations/node.hpp index 64d18e1..be56618 100644 --- a/src/operations/node.hpp +++ b/src/operations/node.hpp @@ -3,33 +3,38 @@ #include #include +#include #include "../variables/value.hpp" #include "../variables/environment.hpp" #define MAX_CHILDREN 3 +class Value; +class Environment; + /* a tree node definition */ -struct Node { +class Node { + public: int type; - struct Value* value; + Value* value; /* the id of the node (used for identifiers only) */ std::string id; /* at most three children nodes */ uint num_children; - std::array children; - - Node(int t, struct Value* v, std::string s) { + std::array children; + + Node(int t, Value* v, std::string s) { type = t; value = v; id = s; + num_children = 0; for (uint i = 0; i < MAX_CHILDREN; i++) { children[i] = nullptr; } } ~Node() { - if (value) { delete value; } // delete value; for (uint i = 0; i < num_children; i++) { delete children[i]; @@ -39,11 +44,11 @@ struct Node { // Abstract Syntax Tree Functions // struct Node* make_node(int type, struct Value* value, std::string id); -void attach_node(struct Node* parent, struct Node* child); -void print_tree(struct Node* node, int tabs); +void attach_node(Node* parent, Node* child); +void print_tree(Node* node, int tabs); // Interpreting AST -void eval_statement(struct Node* node, struct Environment* env); -struct Value* eval_expression(struct Node* node, struct Environment* env); +void eval_statement(Node* node, Environment* env); +Value* eval_expression(Node* node, Environment* env); #endif diff --git a/src/operations/operators.cpp b/src/operations/operators.cpp index 0da7670..251335f 100644 --- a/src/operations/operators.cpp +++ b/src/operations/operators.cpp @@ -2,14 +2,14 @@ #include "operators.hpp" #include "../variables/value.hpp" -struct Value* add(struct Value* x, struct Value* y) { +Value* add(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in add." << std::endl; } if (x->type == BOOLEAN || y->type == BOOLEAN) { std::cerr << "Error, cannot add a boolean." << std::endl; } if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) { std::cerr << "Error, cannot add a string with another data type." << std::endl; } - struct Value* ans; + Value* ans; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -27,12 +27,12 @@ struct Value* add(struct Value* x, struct Value* y) { return ans; } -struct Value* subtract(struct Value* x, struct Value* y) { +Value* subtract(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in subtract." << std::endl; } if (x->type == BOOLEAN || y->type == BOOLEAN) { std::cerr << "Error, cannot subtract a boolean." << std::endl; } if (x->type == STRING || y->type == STRING) { std::cerr << "Error, cannot subtract a string." << std::endl; } - struct Value* ans; + Value* ans; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -48,12 +48,12 @@ struct Value* subtract(struct Value* x, struct Value* y) { return ans; } -struct Value* division(struct Value* x, struct Value* y) { +Value* division(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in divide." << std::endl; } if (x->type == BOOLEAN || y->type == BOOLEAN) { std::cerr << "Error, cannot divide a boolean." << std::endl; } if (x->type == STRING || y->type == STRING) { std::cerr << "Error, cannot division a string." << std::endl; } - struct Value* ans; + Value* ans; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -69,12 +69,12 @@ struct Value* division(struct Value* x, struct Value* y) { return ans; } -struct Value* multiplication(struct Value* x, struct Value* y) { +Value* multiplication(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in multiply." << std::endl; } if (x->type == BOOLEAN || y->type == BOOLEAN) { std::cerr << "Error, cannot multiply a boolean." << std::endl; } if (x->type == STRING || y->type == STRING) { std::cerr << "Error, cannot multiply a string." << std::endl; } - struct Value* ans; + Value* ans; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -90,14 +90,14 @@ struct Value* multiplication(struct Value* x, struct Value* y) { return ans; } -struct Value* less(struct Value* x, struct Value* y) { +Value* less(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in <." << std::endl; } if (x->type == BOOLEAN || y->type == BOOLEAN) { std::cerr << "Error, cannot numerically compare a boolean." << std::endl; } if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) { std::cerr << "Error, cannot compare a string with another data type." << std::endl; } - struct Value* ans; + Value* ans; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -115,14 +115,14 @@ struct Value* less(struct Value* x, struct Value* y) { return ans; } -struct Value* greater(struct Value* x, struct Value* y) { +Value* greater(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in greater." << std::endl; } if (x->type == BOOLEAN || y->type == BOOLEAN) { std::cerr << "Error, cannot numerically compare a boolean." << std::endl; } if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) { std::cerr << "Error, cannot compare a string with another data type." << std::endl; } - struct Value* ans; + Value* ans; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -140,14 +140,14 @@ struct Value* greater(struct Value* x, struct Value* y) { return ans; } -struct Value* less_equal(struct Value* x, struct Value* y) { +Value* less_equal(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in <=." << std::endl; } if (x->type == BOOLEAN || y->type == BOOLEAN) { std::cerr << "Error, cannot numerically compare a boolean." << std::endl; } if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) { std::cerr << "Error, cannot compare a string with another data type." << std::endl; } - struct Value* ans; + Value* ans; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -165,14 +165,14 @@ struct Value* less_equal(struct Value* x, struct Value* y) { return ans; } -struct Value* greater_equal(struct Value* x, struct Value* y) { +Value* greater_equal(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in >=." << std::endl; } if (x->type == BOOLEAN || y->type == BOOLEAN) { std::cerr << "Error, cannot numerically compare a boolean." << std::endl; } if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) { std::cerr << "Error, cannot compare a string with another data type." << std::endl; } - struct Value* ans; + Value* ans; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -190,13 +190,13 @@ struct Value* greater_equal(struct Value* x, struct Value* y) { return ans; } -struct Value* equals(struct Value* x, struct Value* y) { +Value* equals(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in ==." << std::endl; } if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) { std::cerr << "Error, cannot compare a string with another data type." << std::endl; } - struct Value* ans = nullptr; + Value* ans = nullptr; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -218,13 +218,13 @@ struct Value* equals(struct Value* x, struct Value* y) { return ans; } -struct Value* not_equals(struct Value* x, struct Value* y) { +Value* not_equals(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in !=." << std::endl; } if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) { std::cerr << "Error, cannot compare a string with another data type." << std::endl; } - struct Value* ans= nullptr; + Value* ans= nullptr; // Destruct all four cases if (x->type == LONG && y->type == LONG) { @@ -246,7 +246,7 @@ struct Value* not_equals(struct Value* x, struct Value* y) { return ans; } -struct Value* and_value(struct Value* x, struct Value* y) { +Value* and_value(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in &&." << std::endl; } if (x->type != BOOLEAN || y->type != BOOLEAN) { std::cerr << "Error, cannot use and AND operation with a non-boolean." << std::endl; } if (x->type == STRING || y->type == STRING) { std::cerr << "Error, cannot AND a string." << std::endl; } @@ -254,7 +254,7 @@ struct Value* and_value(struct Value* x, struct Value* y) { return make_boolean(get_long(x) && get_long(y)); } -struct Value* or_value(struct Value* x, struct Value* y) { +Value* or_value(Value* x, Value* y) { if (!x || !y) { std::cerr << "Error, uninitialized values being used in ||." << std::endl; } if (x->type != BOOLEAN || y->type != BOOLEAN) { std::cerr << "Error, cannot use and OR operation with a non-boolean." << std::endl; } if (x->type == STRING || y->type == STRING) { std::cerr << "Error, cannot OR a string." << std::endl; } @@ -262,7 +262,7 @@ struct Value* or_value(struct Value* x, struct Value* y) { return make_boolean(get_long(x) || get_long(y)); } -struct Value* not_value(struct Value* x) { +Value* not_value(Value* x) { if (!x) { std::cerr << "Error, uninitialized values being used in !." << std::endl; } if (x->type != BOOLEAN) { std::cerr << "Error, cannot NOT a non-boolean." << std::endl; } if (x->type == STRING) { std::cerr << "Error, cannot negate a string." << std::endl; } diff --git a/src/operations/operators.hpp b/src/operations/operators.hpp index 9360d7c..3715a19 100644 --- a/src/operations/operators.hpp +++ b/src/operations/operators.hpp @@ -2,18 +2,18 @@ #define OPERATORS_H #include "../variables/value.hpp" -struct Value* add(struct Value* x, struct Value* y); -struct Value* subtract(struct Value* x, struct Value* y); -struct Value* division(struct Value* x, struct Value* y); -struct Value* multiplication(struct Value* x, struct Value* y); -struct Value* less(struct Value* x, struct Value* y); -struct Value* greater(struct Value* x, struct Value* y); -struct Value* less_equal(struct Value* x, struct Value* y); -struct Value* greater_equal(struct Value* x, struct Value* y); -struct Value* equals(struct Value* x, struct Value* y); -struct Value* not_equals(struct Value* x, struct Value* y); -struct Value* and_value(struct Value* x, struct Value* y); -struct Value* or_value(struct Value* x, struct Value* y); -struct Value* not_value(struct Value* x); +Value* add(Value* x, Value* y); +Value* subtract(Value* x, Value* y); +Value* division(Value* x, Value* y); +Value* multiplication(Value* x, Value* y); +Value* less(Value* x, Value* y); +Value* greater(Value* x, Value* y); +Value* less_equal(Value* x, Value* y); +Value* greater_equal(Value* x, Value* y); +Value* equals(Value* x, Value* y); +Value* not_equals(Value* x, Value* y); +Value* and_value(Value* x, Value* y); +Value* or_value(Value* x, Value* y); +Value* not_value(Value* x); #endif diff --git a/src/shell.cpp b/src/shell.cpp index 551509e..f5cec0f 100644 --- a/src/shell.cpp +++ b/src/shell.cpp @@ -48,7 +48,7 @@ void start_shell() { printf("Welcome to SLOTH Version 0.0.1\n"); printf("Press CTRL+C to Exit\n"); - struct Environment* env = new Environment(); + Environment* env = new Environment(); while (1) { // Read line from user and input it into the history char* input = readline("sloth> "); @@ -69,7 +69,6 @@ void start_shell() { eval_statement(result, env); } - delete_environment(env); - // delete env; + delete env; delete result; } \ No newline at end of file diff --git a/src/variables/environment.cpp b/src/variables/environment.cpp index 0fb7c94..6f6c8c6 100644 --- a/src/variables/environment.cpp +++ b/src/variables/environment.cpp @@ -4,7 +4,7 @@ #include "environment.hpp" #include "variable.hpp" -struct Variable* find_variable(struct Environment* env, std::string id) { +Variable* find_variable(Environment* env, std::string id) { auto result = std::find_if(env->vars.begin(), env->vars.end(), [id](const Variable* element) { return element->id == id; @@ -17,9 +17,9 @@ struct Variable* find_variable(struct Environment* env, std::string id) { return nullptr; } -void add_variable(struct Environment* env, struct Variable* var) { +void add_variable(Environment* env, Variable* var) { // If variable exists, replace it - struct Variable* temp_var = find_variable(env, var->id); + Variable* temp_var = find_variable(env, var->id); if (temp_var != nullptr) { temp_var->value = var->value; free(var); @@ -30,9 +30,3 @@ void add_variable(struct Environment* env, struct Variable* var) { env->vars.push_back(var); } -void delete_environment(struct Environment* env) { - for (uint i = 0; i < size(env->vars); i++) { - free(env->vars[i]); - } - free(env); -} diff --git a/src/variables/environment.hpp b/src/variables/environment.hpp index 8650d19..fdeba84 100644 --- a/src/variables/environment.hpp +++ b/src/variables/environment.hpp @@ -5,19 +5,21 @@ #include #include -struct Environment { - std::vector vars; +class Variable; + +class Environment { + public: + std::vector vars; Environment() { } - // ~Environment() { - // for (uint i = 0; i < size(vars); i++) { - // delete vars[i]; - // } - // } + ~Environment() { + for (uint i = 0; i < size(vars); i++) { + delete vars[i]; + } + } }; // Variable Lookup Functions -void delete_environment(struct Environment* env); -struct Variable* find_variable(struct Environment* env, std::string id); -void add_variable(struct Environment* env, struct Variable* var); +Variable* find_variable(Environment* env, std::string id); +void add_variable(Environment* env, Variable* var); #endif diff --git a/src/variables/value.cpp b/src/variables/value.cpp index 991cb2d..d0f7eab 100644 --- a/src/variables/value.cpp +++ b/src/variables/value.cpp @@ -2,65 +2,74 @@ #include "value.hpp" #include #include +#include #include "../parser/parser.tab.h" -struct Value* make_long(long num) { +Value* make_long(long num) { return new Value(LONG, num, 0, nullptr, ""); } -struct Value* make_double(double dec) { +Value* make_double(double dec) { return new Value(DOUBLE, 0, dec, nullptr, ""); } -struct Value* make_true() { +Value* make_true() { return new Value(BOOLEAN, 1, 0, nullptr, ""); } -struct Value* make_false() { +Value* make_false() { return new Value(BOOLEAN, 0, 0, nullptr, ""); } -struct Value* make_boolean(int x) { +Value* make_boolean(int x) { return (x)? make_true() : make_false(); } -struct Value* make_expression(struct Node* expr) { +Value* make_expression(Node* expr) { return new Value(LAMBDA, 0, 0, expr, ""); } -struct Value* make_string(std::string str) { +Value* make_string(std::string str) { return new Value(STRING, 0, 0, nullptr, str); } -void delete_value(struct Value* val) { +void delete_value(Value* val) { free(val); } -long get_long(struct Value* val) { - return val->value.num; +long get_long(Value* val) { + // return val->value.num; + return std::get(val->val); } -double get_double(struct Value* val) { - return val->value.dec; +double get_double(Value* val) { + // return val->value.dec; + return std::get(val->val); } -struct Node* get_expression(struct Value* val) { - return val->value.expr; +Node* get_expression(Value* val) { + // return val->value.expr; + return std::get(val->val); } -std::string get_string(struct Value* val) { - return val->value.str; +std::string get_string(Value* val) { + // return val->value.str; + return std::get(val->val); } -void set_long(struct Value* val, long num) { +void set_long(Value* val, long num) { val->type = LONG; - val->value.num = num; + // val->value.num = num; + val->val = num; } -void set_double(struct Value* val, double dec) { +void set_double(Value* val, double dec) { val->type = DOUBLE; - val->value.dec = dec; + // val->value.dec = dec; + val->val = dec; } -void set_expression(struct Value* val, struct Node* expr) { +void set_expression(Value* val, Node* expr) { val->type = LAMBDA; - val->value.expr = expr; + // val->value.expr = expr; + val->val = expr; } -void set_sring(struct Value* val, std::string str) { +void set_sring(Value* val, std::string str) { val->type = STRING; - val->value.str = str; + // val->value.str = str; + val->val = str; } -void print_value(struct Value* val) { +void print_value(Value* val) { if (val->type == BOOLEAN) { if (get_long(val)) { std::cout << "true"; diff --git a/src/variables/value.hpp b/src/variables/value.hpp index 0aded1b..a008e9a 100644 --- a/src/variables/value.hpp +++ b/src/variables/value.hpp @@ -1,35 +1,37 @@ #ifndef VALUE_H #define VALUE_H +#include "../operations/node.hpp" +#include #include +#include + +class Node; enum TypeTag { DOUBLE, LONG, BOOLEAN, STRING, LAMBDA }; -union TypeVal { - long num; - double dec; - struct Node* expr; - std::string str; - TypeVal() { new(&str) std::string(); new(expr) struct Node*; } - ~TypeVal() { free(&str); free(expr); } -}; +class Value { + public: + enum TypeTag type; + std::variant val; -struct Value { - enum TypeTag type; - TypeVal value; - // Broken implemenation of constructor below - Value(TypeTag t, long n, double d, struct Node* e, std::string s) { - /* set properties */ - type = t; - if (type == LONG || type == BOOLEAN) { - value.num = n; - } else if (type == DOUBLE){ // Assume DOUBLE - value.dec = d; - } else if (type == STRING) { - value.str = s; - } else { // Assume lambda expression - value.expr = e; + Value(TypeTag t, long n, double d, Node* e, std::string s) { + /* set properties */ + type = t; + + if (type == LONG || type == BOOLEAN) { + val = n; + } else if (type == DOUBLE){ // Assume DOUBLE + val = d; + } else if (type == STRING) { + val = s; + } else { // Assume lambda expression + val = e; + } } + + ~Value() { + std::cout << "VALUE DESTROYED" << std::endl; } }; diff --git a/src/variables/variable.cpp b/src/variables/variable.cpp index 55d7a73..430b712 100644 --- a/src/variables/variable.cpp +++ b/src/variables/variable.cpp @@ -2,12 +2,12 @@ #include #include "variable.hpp" -void set_value(struct Variable* var, struct Value* value) { +void set_value(Variable* var, Value* value) { if (!var) { std::cerr << "Error: Invalid Variable" << std::endl; return; } var->value = value; } -struct Value* get_value(struct Variable* var) { +Value* get_value(Variable* var) { if (!var) { std::cerr << "Error: Invalid Variable" << std::endl; return 0; } return var->value; } \ No newline at end of file diff --git a/src/variables/variable.hpp b/src/variables/variable.hpp index 8d5dbb3..7f71e58 100644 --- a/src/variables/variable.hpp +++ b/src/variables/variable.hpp @@ -2,26 +2,33 @@ #define VARIABLE_H #include -#include "../operations/node.hpp" +#include "../variables/value.hpp" -struct Variable { +class Value; +class Node; + +class Variable { + public: std::string id; - struct Value* value; + Value* value; - Variable(std::string s, struct Value* val) { + Variable(std::string s, Value* val) { id = s; value = val; } + ~Variable() { + delete value; + } }; // Variable Functions -void set_value(struct Variable* var, struct Value* value); -struct Value* get_value(struct Variable* var); -struct Value* make_long(long num); -struct Value* make_double(double dec); -struct Value* make_true(); -struct Value* make_false(); -struct Value* make_boolean(int x); -struct Value* make_expression(struct Node* expr); +void set_value(Variable* var, Value* value); +Value* get_value(Variable* var); +Value* make_long(long num); +Value* make_double(double dec); +Value* make_true(); +Value* make_false(); +Value* make_boolean(int x); +Value* make_expression(Node* expr); #endif