struct->classes
Environment now has destructor
This commit is contained in:
parent
7733f5b3c2
commit
8dd2e789c0
13 changed files with 167 additions and 150 deletions
|
@ -4,8 +4,10 @@
|
||||||
#define STATEMENT 200
|
#define STATEMENT 200
|
||||||
#define CALLFUNC 201
|
#define CALLFUNC 201
|
||||||
|
|
||||||
|
class Node;
|
||||||
|
|
||||||
// Share the line number between files
|
// Share the line number between files
|
||||||
extern int linenum;
|
extern int linenum;
|
||||||
extern struct Node* result;
|
extern Node* result;
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -6,7 +6,7 @@
|
||||||
void interpret_file(char* fileName);
|
void interpret_file(char* fileName);
|
||||||
|
|
||||||
/* the result variable */
|
/* the result variable */
|
||||||
struct Node* result;
|
Node* result;
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
|
@ -35,10 +35,8 @@ void interpret_file(char* fileName) {
|
||||||
|
|
||||||
// Interpret the AST
|
// Interpret the AST
|
||||||
// print_tree(result, 0); // For debugging
|
// print_tree(result, 0); // For debugging
|
||||||
struct Environment* env = new Environment();
|
Environment* env = new Environment();
|
||||||
eval_statement(result, env);
|
eval_statement(result, env);
|
||||||
delete_environment(env);
|
delete env;
|
||||||
// delete env;
|
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
|
@ -8,20 +8,20 @@
|
||||||
#include "../variables/variable.hpp"
|
#include "../variables/variable.hpp"
|
||||||
|
|
||||||
/* attach an existing node onto a parent */
|
/* 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 */
|
/* connect it */
|
||||||
parent->children[parent->num_children] = child;
|
parent->children[parent->num_children] = child;
|
||||||
parent->num_children++;
|
parent->num_children++;
|
||||||
if (parent->num_children > MAX_CHILDREN) { std::cerr << "Error, max children attached to a node" << std::endl; }
|
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) {
|
if (node && node->num_children != num_children) {
|
||||||
std::cerr << "Error, " << error << std::endl;
|
std::cerr << "Error, " << error << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_tree(struct Node* node, uint tabs) {
|
void print_tree(Node* node, uint tabs) {
|
||||||
uint i;
|
uint i;
|
||||||
/* base case */
|
/* base case */
|
||||||
if(!node) {
|
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 */
|
/* base case */
|
||||||
if(!node) {
|
if(!node) {
|
||||||
fprintf(stderr, "Error: No tree structure to evaluate\n");
|
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
|
// Needed if we are going to take input from the user
|
||||||
double temp;
|
double temp;
|
||||||
struct Variable* var = nullptr;
|
Variable* var = nullptr;
|
||||||
struct Environment* local_env = nullptr;
|
Environment* local_env = nullptr;
|
||||||
struct Node* tempNode = nullptr;
|
Node* tempNode = nullptr;
|
||||||
struct Value* tempVal = nullptr;
|
Value* tempVal = nullptr;
|
||||||
|
|
||||||
// Evaluate subexpressions if existent and node is not a lambda expression
|
// Evaluate subexpressions if existent and node is not a lambda expression
|
||||||
struct Value* val1 = nullptr;
|
Value* val1 = nullptr;
|
||||||
struct Value* val2 = nullptr;
|
Value* val2 = nullptr;
|
||||||
// struct Value* val3 = nullptr;
|
// struct Value* val3 = nullptr;
|
||||||
if (node->num_children > 0 && node->type != LAMBDATAG) {
|
if (node->num_children > 0 && node->type != LAMBDATAG) {
|
||||||
val1 = eval_expression(node->children[0], env);
|
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
|
new Variable(tempNode->children[0]->id, // Get the name of the variable needed for the lambda expression
|
||||||
eval_expression(node->children[1], env)));
|
eval_expression(node->children[1], env)));
|
||||||
tempVal = eval_expression(tempNode->children[1], local_env);
|
tempVal = eval_expression(tempNode->children[1], local_env);
|
||||||
delete_environment(local_env);
|
delete local_env;
|
||||||
// delete local_env;
|
|
||||||
return tempVal;
|
return tempVal;
|
||||||
break;
|
break;
|
||||||
case PLUS:
|
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 */
|
/* base case */
|
||||||
if(!node) {
|
if(!node) {
|
||||||
fprintf(stderr, "Error: No tree structure to evaluate\n");
|
fprintf(stderr, "Error: No tree structure to evaluate\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* tempVal;
|
Value* tempVal;
|
||||||
|
|
||||||
switch(node->type) {
|
switch(node->type) {
|
||||||
case ASSIGN:
|
case ASSIGN:
|
||||||
|
|
|
@ -3,33 +3,38 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
#include "../variables/value.hpp"
|
#include "../variables/value.hpp"
|
||||||
#include "../variables/environment.hpp"
|
#include "../variables/environment.hpp"
|
||||||
|
|
||||||
#define MAX_CHILDREN 3
|
#define MAX_CHILDREN 3
|
||||||
|
|
||||||
|
class Value;
|
||||||
|
class Environment;
|
||||||
|
|
||||||
/* a tree node definition */
|
/* a tree node definition */
|
||||||
struct Node {
|
class Node {
|
||||||
|
public:
|
||||||
int type;
|
int type;
|
||||||
struct Value* value;
|
Value* value;
|
||||||
|
|
||||||
/* the id of the node (used for identifiers only) */
|
/* the id of the node (used for identifiers only) */
|
||||||
std::string id;
|
std::string id;
|
||||||
|
|
||||||
/* at most three children nodes */
|
/* at most three children nodes */
|
||||||
uint num_children;
|
uint num_children;
|
||||||
std::array<struct Node*, MAX_CHILDREN> children;
|
std::array<Node*, MAX_CHILDREN> children;
|
||||||
|
|
||||||
Node(int t, struct Value* v, std::string s) {
|
Node(int t, Value* v, std::string s) {
|
||||||
type = t;
|
type = t;
|
||||||
value = v;
|
value = v;
|
||||||
id = s;
|
id = s;
|
||||||
|
num_children = 0;
|
||||||
for (uint i = 0; i < MAX_CHILDREN; i++) {
|
for (uint i = 0; i < MAX_CHILDREN; i++) {
|
||||||
children[i] = nullptr;
|
children[i] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~Node() {
|
~Node() {
|
||||||
if (value) { delete value; }
|
|
||||||
// delete value;
|
// delete value;
|
||||||
for (uint i = 0; i < num_children; i++) {
|
for (uint i = 0; i < num_children; i++) {
|
||||||
delete children[i];
|
delete children[i];
|
||||||
|
@ -39,11 +44,11 @@ struct Node {
|
||||||
|
|
||||||
// Abstract Syntax Tree Functions
|
// Abstract Syntax Tree Functions
|
||||||
// struct Node* make_node(int type, struct Value* value, std::string id);
|
// struct Node* make_node(int type, struct Value* value, std::string id);
|
||||||
void attach_node(struct Node* parent, struct Node* child);
|
void attach_node(Node* parent, Node* child);
|
||||||
void print_tree(struct Node* node, int tabs);
|
void print_tree(Node* node, int tabs);
|
||||||
|
|
||||||
// Interpreting AST
|
// Interpreting AST
|
||||||
void eval_statement(struct Node* node, struct Environment* env);
|
void eval_statement(Node* node, Environment* env);
|
||||||
struct Value* eval_expression(struct Node* node, struct Environment* env);
|
Value* eval_expression(Node* node, Environment* env);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
#include "operators.hpp"
|
#include "operators.hpp"
|
||||||
#include "../variables/value.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 || !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 == 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)) {
|
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;
|
std::cerr << "Error, cannot add a string with another data type." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
Value* ans;
|
||||||
|
|
||||||
// Destruct all four cases
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -27,12 +27,12 @@ struct Value* add(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !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 == 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; }
|
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
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -48,12 +48,12 @@ struct Value* subtract(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !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 == 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; }
|
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
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -69,12 +69,12 @@ struct Value* division(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !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 == 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; }
|
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
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -90,14 +90,14 @@ struct Value* multiplication(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !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 == 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)) {
|
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;
|
std::cerr << "Error, cannot compare a string with another data type." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
Value* ans;
|
||||||
|
|
||||||
// Destruct all four cases
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -115,14 +115,14 @@ struct Value* less(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !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 == 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)) {
|
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;
|
std::cerr << "Error, cannot compare a string with another data type." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
Value* ans;
|
||||||
|
|
||||||
// Destruct all four cases
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -140,14 +140,14 @@ struct Value* greater(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !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 == 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)) {
|
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;
|
std::cerr << "Error, cannot compare a string with another data type." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
Value* ans;
|
||||||
|
|
||||||
// Destruct all four cases
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -165,14 +165,14 @@ struct Value* less_equal(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !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 == 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)) {
|
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;
|
std::cerr << "Error, cannot compare a string with another data type." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
Value* ans;
|
||||||
|
|
||||||
// Destruct all four cases
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -190,13 +190,13 @@ struct Value* greater_equal(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !y) { std::cerr << "Error, uninitialized values being used in ==." << std::endl; }
|
||||||
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
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;
|
std::cerr << "Error, cannot compare a string with another data type." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* ans = nullptr;
|
Value* ans = nullptr;
|
||||||
|
|
||||||
// Destruct all four cases
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -218,13 +218,13 @@ struct Value* equals(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !y) { std::cerr << "Error, uninitialized values being used in !=." << std::endl; }
|
||||||
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
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;
|
std::cerr << "Error, cannot compare a string with another data type." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* ans= nullptr;
|
Value* ans= nullptr;
|
||||||
|
|
||||||
// Destruct all four cases
|
// Destruct all four cases
|
||||||
if (x->type == LONG && y->type == LONG) {
|
if (x->type == LONG && y->type == LONG) {
|
||||||
|
@ -246,7 +246,7 @@ struct Value* not_equals(struct Value* x, struct Value* y) {
|
||||||
return ans;
|
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 || !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 != 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; }
|
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));
|
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 || !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 != 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; }
|
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));
|
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) { 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 != BOOLEAN) { std::cerr << "Error, cannot NOT a non-boolean." << std::endl; }
|
||||||
if (x->type == STRING) { std::cerr << "Error, cannot negate a string." << std::endl; }
|
if (x->type == STRING) { std::cerr << "Error, cannot negate a string." << std::endl; }
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
#define OPERATORS_H
|
#define OPERATORS_H
|
||||||
#include "../variables/value.hpp"
|
#include "../variables/value.hpp"
|
||||||
|
|
||||||
struct Value* add(struct Value* x, struct Value* y);
|
Value* add(Value* x, Value* y);
|
||||||
struct Value* subtract(struct Value* x, struct Value* y);
|
Value* subtract(Value* x, Value* y);
|
||||||
struct Value* division(struct Value* x, struct Value* y);
|
Value* division(Value* x, Value* y);
|
||||||
struct Value* multiplication(struct Value* x, struct Value* y);
|
Value* multiplication(Value* x, Value* y);
|
||||||
struct Value* less(struct Value* x, struct Value* y);
|
Value* less(Value* x, Value* y);
|
||||||
struct Value* greater(struct Value* x, struct Value* y);
|
Value* greater(Value* x, Value* y);
|
||||||
struct Value* less_equal(struct Value* x, struct Value* y);
|
Value* less_equal(Value* x, Value* y);
|
||||||
struct Value* greater_equal(struct Value* x, struct Value* y);
|
Value* greater_equal(Value* x, Value* y);
|
||||||
struct Value* equals(struct Value* x, struct Value* y);
|
Value* equals(Value* x, Value* y);
|
||||||
struct Value* not_equals(struct Value* x, struct Value* y);
|
Value* not_equals(Value* x, Value* y);
|
||||||
struct Value* and_value(struct Value* x, struct Value* y);
|
Value* and_value(Value* x, Value* y);
|
||||||
struct Value* or_value(struct Value* x, struct Value* y);
|
Value* or_value(Value* x, Value* y);
|
||||||
struct Value* not_value(struct Value* x);
|
Value* not_value(Value* x);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -48,7 +48,7 @@ void start_shell() {
|
||||||
printf("Welcome to SLOTH Version 0.0.1\n");
|
printf("Welcome to SLOTH Version 0.0.1\n");
|
||||||
printf("Press CTRL+C to Exit\n");
|
printf("Press CTRL+C to Exit\n");
|
||||||
|
|
||||||
struct Environment* env = new Environment();
|
Environment* env = new Environment();
|
||||||
while (1) {
|
while (1) {
|
||||||
// Read line from user and input it into the history
|
// Read line from user and input it into the history
|
||||||
char* input = readline("sloth> ");
|
char* input = readline("sloth> ");
|
||||||
|
@ -69,7 +69,6 @@ void start_shell() {
|
||||||
eval_statement(result, env);
|
eval_statement(result, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_environment(env);
|
delete env;
|
||||||
// delete env;
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
#include "environment.hpp"
|
#include "environment.hpp"
|
||||||
#include "variable.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(),
|
auto result = std::find_if(env->vars.begin(), env->vars.end(),
|
||||||
[id](const Variable* element) {
|
[id](const Variable* element) {
|
||||||
return element->id == id;
|
return element->id == id;
|
||||||
|
@ -17,9 +17,9 @@ struct Variable* find_variable(struct Environment* env, std::string id) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_variable(struct Environment* env, struct Variable* var) {
|
void add_variable(Environment* env, Variable* var) {
|
||||||
// If variable exists, replace it
|
// 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) {
|
if (temp_var != nullptr) {
|
||||||
temp_var->value = var->value;
|
temp_var->value = var->value;
|
||||||
free(var);
|
free(var);
|
||||||
|
@ -30,9 +30,3 @@ void add_variable(struct Environment* env, struct Variable* var) {
|
||||||
env->vars.push_back(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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,19 +5,21 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct Environment {
|
class Variable;
|
||||||
std::vector<struct Variable*> vars;
|
|
||||||
|
class Environment {
|
||||||
|
public:
|
||||||
|
std::vector<Variable*> vars;
|
||||||
Environment() { }
|
Environment() { }
|
||||||
// ~Environment() {
|
~Environment() {
|
||||||
// for (uint i = 0; i < size(vars); i++) {
|
for (uint i = 0; i < size(vars); i++) {
|
||||||
// delete vars[i];
|
delete vars[i];
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variable Lookup Functions
|
// Variable Lookup Functions
|
||||||
void delete_environment(struct Environment* env);
|
Variable* find_variable(Environment* env, std::string id);
|
||||||
struct Variable* find_variable(struct Environment* env, std::string id);
|
void add_variable(Environment* env, Variable* var);
|
||||||
void add_variable(struct Environment* env, struct Variable* var);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,65 +2,74 @@
|
||||||
#include "value.hpp"
|
#include "value.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <variant>
|
||||||
#include "../parser/parser.tab.h"
|
#include "../parser/parser.tab.h"
|
||||||
|
|
||||||
struct Value* make_long(long num) {
|
Value* make_long(long num) {
|
||||||
return new Value(LONG, num, 0, nullptr, "");
|
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, "");
|
return new Value(DOUBLE, 0, dec, nullptr, "");
|
||||||
}
|
}
|
||||||
struct Value* make_true() {
|
Value* make_true() {
|
||||||
return new Value(BOOLEAN, 1, 0, nullptr, "");
|
return new Value(BOOLEAN, 1, 0, nullptr, "");
|
||||||
}
|
}
|
||||||
struct Value* make_false() {
|
Value* make_false() {
|
||||||
return new Value(BOOLEAN, 0, 0, nullptr, "");
|
return new Value(BOOLEAN, 0, 0, nullptr, "");
|
||||||
}
|
}
|
||||||
struct Value* make_boolean(int x) {
|
Value* make_boolean(int x) {
|
||||||
return (x)? make_true() : make_false();
|
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, "");
|
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);
|
return new Value(STRING, 0, 0, nullptr, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_value(struct Value* val) {
|
void delete_value(Value* val) {
|
||||||
free(val);
|
free(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
long get_long(struct Value* val) {
|
long get_long(Value* val) {
|
||||||
return val->value.num;
|
// return val->value.num;
|
||||||
|
return std::get<long>(val->val);
|
||||||
}
|
}
|
||||||
double get_double(struct Value* val) {
|
double get_double(Value* val) {
|
||||||
return val->value.dec;
|
// return val->value.dec;
|
||||||
|
return std::get<double>(val->val);
|
||||||
}
|
}
|
||||||
struct Node* get_expression(struct Value* val) {
|
Node* get_expression(Value* val) {
|
||||||
return val->value.expr;
|
// return val->value.expr;
|
||||||
|
return std::get<Node*>(val->val);
|
||||||
}
|
}
|
||||||
std::string get_string(struct Value* val) {
|
std::string get_string(Value* val) {
|
||||||
return val->value.str;
|
// 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->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->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->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->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 (val->type == BOOLEAN) {
|
||||||
if (get_long(val)) {
|
if (get_long(val)) {
|
||||||
std::cout << "true";
|
std::cout << "true";
|
||||||
|
|
|
@ -1,36 +1,38 @@
|
||||||
#ifndef VALUE_H
|
#ifndef VALUE_H
|
||||||
#define VALUE_H
|
#define VALUE_H
|
||||||
|
|
||||||
|
#include "../operations/node.hpp"
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
class Node;
|
||||||
|
|
||||||
enum TypeTag { DOUBLE, LONG, BOOLEAN, STRING, LAMBDA };
|
enum TypeTag { DOUBLE, LONG, BOOLEAN, STRING, LAMBDA };
|
||||||
|
|
||||||
union TypeVal {
|
class Value {
|
||||||
long num;
|
public:
|
||||||
double dec;
|
|
||||||
struct Node* expr;
|
|
||||||
std::string str;
|
|
||||||
TypeVal() { new(&str) std::string(); new(expr) struct Node*; }
|
|
||||||
~TypeVal() { free(&str); free(expr); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Value {
|
|
||||||
enum TypeTag type;
|
enum TypeTag type;
|
||||||
TypeVal value;
|
std::variant<long, double, Node*, std::string> val;
|
||||||
// Broken implemenation of constructor below
|
|
||||||
Value(TypeTag t, long n, double d, struct Node* e, std::string s) {
|
Value(TypeTag t, long n, double d, Node* e, std::string s) {
|
||||||
/* set properties */
|
/* set properties */
|
||||||
type = t;
|
type = t;
|
||||||
|
|
||||||
if (type == LONG || type == BOOLEAN) {
|
if (type == LONG || type == BOOLEAN) {
|
||||||
value.num = n;
|
val = n;
|
||||||
} else if (type == DOUBLE){ // Assume DOUBLE
|
} else if (type == DOUBLE){ // Assume DOUBLE
|
||||||
value.dec = d;
|
val = d;
|
||||||
} else if (type == STRING) {
|
} else if (type == STRING) {
|
||||||
value.str = s;
|
val = s;
|
||||||
} else { // Assume lambda expression
|
} else { // Assume lambda expression
|
||||||
value.expr = e;
|
val = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Value() {
|
||||||
|
std::cout << "VALUE DESTROYED" << std::endl;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "variable.hpp"
|
#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; }
|
if (!var) { std::cerr << "Error: Invalid Variable" << std::endl; return; }
|
||||||
var->value = value;
|
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; }
|
if (!var) { std::cerr << "Error: Invalid Variable" << std::endl; return 0; }
|
||||||
return var->value;
|
return var->value;
|
||||||
}
|
}
|
|
@ -2,26 +2,33 @@
|
||||||
#define VARIABLE_H
|
#define VARIABLE_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../operations/node.hpp"
|
#include "../variables/value.hpp"
|
||||||
|
|
||||||
struct Variable {
|
class Value;
|
||||||
|
class Node;
|
||||||
|
|
||||||
|
class Variable {
|
||||||
|
public:
|
||||||
std::string id;
|
std::string id;
|
||||||
struct Value* value;
|
Value* value;
|
||||||
|
|
||||||
Variable(std::string s, struct Value* val) {
|
Variable(std::string s, Value* val) {
|
||||||
id = s;
|
id = s;
|
||||||
value = val;
|
value = val;
|
||||||
}
|
}
|
||||||
|
~Variable() {
|
||||||
|
delete value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variable Functions
|
// Variable Functions
|
||||||
void set_value(struct Variable* var, struct Value* value);
|
void set_value(Variable* var, Value* value);
|
||||||
struct Value* get_value(struct Variable* var);
|
Value* get_value(Variable* var);
|
||||||
struct Value* make_long(long num);
|
Value* make_long(long num);
|
||||||
struct Value* make_double(double dec);
|
Value* make_double(double dec);
|
||||||
struct Value* make_true();
|
Value* make_true();
|
||||||
struct Value* make_false();
|
Value* make_false();
|
||||||
struct Value* make_boolean(int x);
|
Value* make_boolean(int x);
|
||||||
struct Value* make_expression(struct Node* expr);
|
Value* make_expression(Node* expr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Reference in a new issue