Archived
1
0
Fork 0

struct->classes

Environment now has destructor
This commit is contained in:
Brandon Rozek 2018-09-28 21:54:24 -04:00
parent 7733f5b3c2
commit 8dd2e789c0
13 changed files with 167 additions and 150 deletions

View file

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

View file

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

View file

@ -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:

View file

@ -3,33 +3,38 @@
#include <string>
#include <array>
#include <iostream>
#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<struct Node*, MAX_CHILDREN> children;
Node(int t, struct Value* v, std::string s) {
std::array<Node*, MAX_CHILDREN> 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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,19 +5,21 @@
#include <string>
#include <vector>
struct Environment {
std::vector<struct Variable*> vars;
class Variable;
class Environment {
public:
std::vector<Variable*> 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

View file

@ -2,65 +2,74 @@
#include "value.hpp"
#include <string>
#include <iostream>
#include <variant>
#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<long>(val->val);
}
double get_double(struct Value* val) {
return val->value.dec;
double get_double(Value* val) {
// return val->value.dec;
return std::get<double>(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<Node*>(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<std::string>(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";

View file

@ -1,35 +1,37 @@
#ifndef VALUE_H
#define VALUE_H
#include "../operations/node.hpp"
#include <iostream>
#include <string>
#include <variant>
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<long, double, Node*, std::string> 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;
}
};

View file

@ -2,12 +2,12 @@
#include <string>
#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;
}

View file

@ -2,26 +2,33 @@
#define VARIABLE_H
#include <string>
#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