Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (16)
Showing
with 1444 additions and 0 deletions
File added
File added
File added
#include "Compiler.h"
// Prints warning and
// returns false if
// ptr == NULL
bool Compiler::nullCheck(SyntaxTree* ptr, std::string warning)
{
if (ptr == NULL)
{
std::cout << "Warnig: NULL pointer:\t" << warning << '\n';
return false;
}
return true;
}
// Extrctors
SyntaxTree* Compiler::extract(SyntaxTree* ptr, int index, std::string warning)
{
if (!nullCheck(ptr, warning))
return NULL;
if (ptr->children_num <= index)
{
std::cout << "Warnig: Children nuber is " << ptr->children_num << ", and index is " << index << ":\t" << warning << '\n';
return NULL;
}
return ptr->children[index];
}
SyntaxTree* Compiler::getElement(SyntaxTree* ptr, Type from, Type get)
{
std::string warning = (std::string)getTypeName(get) + " from " + (std::string)getTypeName(from);
if (!nullCheck(ptr, warning))
return NULL;
if (ptr->type != from)
{
std::cout << "Warnig: Node type is " << getTypeName(ptr->type) << ", and should be " << getTypeName(from) << '\n';
return NULL;
}
for (int i = 0; i < ptr->children_num; i++)
if (ptr->children[i]->type == get)
return ptr->children[i];
std::cout << "Warnig: Not found " << getTypeName(get) << " in " << getTypeName(from) << '\n';
return NULL;
}
SyntaxTree* Compiler::getSingleElement(SyntaxTree* ptr, Type from)
{
std::string warning = "single from " + (std::string)getTypeName(from);
if (!nullCheck(ptr, warning))
return NULL;
if (ptr->type != from)
{
std::cout << "Warnig: Node type is " << getTypeName(ptr->type) << ", and should be " << getTypeName(from) << '\n';
return NULL;
}
if (ptr->children_num != 1)
{
std::cout << "Warnig: While extracting sinle element " << getTypeName(ptr->type) << " has " << getTypeName(from) << " children and should have 1\n";
return NULL;
}
return ptr->children[0];
}
SyntaxTree* Compiler::get_STATE_from_GAME(SyntaxTree* game)
{
return extract(game, 1, "STATE from GAME");
}
SyntaxTree* Compiler::get_DATA_SET_from_STATE(SyntaxTree* state)
{
return extract(state, 0, "DATA_SET from STATE");
}
SyntaxTree* Compiler::get_INSTRUCTION_BLOCK_from_STATE(SyntaxTree* state)
{
return extract(state, 1, "INSTRUCTION_BLOCK from STATE");
}
SyntaxTree* Compiler::get_VAR_LIST_from_DATA_SET(SyntaxTree* data_set)
{
return extract(data_set, 0, "VAR_LIST from DATA_SET");
}
SyntaxTree* Compiler::get_VAR_DECLARATION_from_VAR_LIST(SyntaxTree* var_list)
{
return extract(var_list, 0, "VAR_DECLARATION from VAR_LIST");
}
SyntaxTree* Compiler::get_VAR_LIST_from_VAR_LIST(SyntaxTree* var_list)
{
return extract(var_list, 1, "VAR_LIST from VAR_LIST");
}
// Extract VAR_DECLARATION
std::string Compiler::get_type_from_VAR_DECLARATION(SyntaxTree* var_declaration)
{
SyntaxTree* var_type = extract(var_declaration, 0, "type from VAR_DECLARATION");
return extract(var_type, 0, "type from VAR_DECLARATION")->text;
}
std::string Compiler::get_identifier_from_VAR_DECLARATION(SyntaxTree* var_declaration)
{
return extract(var_declaration, 1, "type from VAR_DECLARATION")->text;
}
std::string Compiler::get_value_from_VAR_DECLARATION(SyntaxTree* var_declaration)
{
SyntaxTree* var_definition = extract(var_declaration, 2, "type from VAR_DECLARATION");
return extract(var_definition, 0, "type from VAR_DECLARATION")->text;
}
// Data functions
void Compiler::setVariable(DataSet* data_set, std::string type, std::string name, std::string value)
{
if (type == "INT")
{
int val = std::stoi(value);
int* value_ptr = (int*)(data_set->getValuePtr(name));
*value_ptr = val;
}
else if (type == "BOOL")
{
bool val = value == "true";
bool* value_ptr = (bool*)(data_set->getValuePtr(name));
*value_ptr = val;
}
else std::cout << "Error: unknown type:\t" << type << '\n';
}
// Main components
Game* Compiler::createGame(SyntaxTree* input_game)
{
SyntaxTree* state_st = get_STATE_from_GAME(input_game);
DataSet* state = createDataSet(get_DATA_SET_from_STATE(state_st));
InstructionBlock* IB = createInstructionBlock(get_INSTRUCTION_BLOCK_from_STATE(state_st), state, NULL, VAR_TYPE::VOID);
IB->RunBlock();
state->print();
Game* game = new Game(state);
return game;
}
DataSet* Compiler::createDataSet(SyntaxTree* input_data_set)
{
SyntaxTree* var_list = get_VAR_LIST_from_DATA_SET(input_data_set);
std::list<SyntaxTree*> declaration_list;
while (var_list->children_num == 2)
{
declaration_list.push_back(get_VAR_DECLARATION_from_VAR_LIST(var_list));
var_list = get_VAR_LIST_from_VAR_LIST(var_list);
}
int size = 0;
for (SyntaxTree* var : declaration_list)
{
std::string type = get_type_from_VAR_DECLARATION(var);
size += getTypeSize(type);
}
DataSet* data_set = new DataSet(size);
for (SyntaxTree* var : declaration_list)
{
std::string type = get_type_from_VAR_DECLARATION(var);
VAR_TYPE var_type = stringToVarType(type);
std::string name = get_identifier_from_VAR_DECLARATION(var);
std::string value = get_value_from_VAR_DECLARATION(var);
int var_size = getTypeSize(type);
data_set->defineVariable(name, var_type, var_size);
setVariable(data_set, type, name, value);
}
return data_set;
}
InstructionBlock* Compiler::createInstructionBlock(SyntaxTree* input_instruction_block, DataSet* state, DataSet* move, VAR_TYPE return_type)
{
SyntaxTree* local_data = getElement(input_instruction_block, Type::instruction_block, Type::data_set);
SyntaxTree* instruction_list = extract(input_instruction_block, 1, "INSTRUCTION_LIST from INSTRUCTION_BLOCK"); // REFACTOR
// Create local DataSet
DataSet* local = createDataSet(local_data);
InstructionBlock* instruction_block = new InstructionBlock(NULL, return_type);
// Create Instruction graph
std::list<Instruction*> last_instructions;
Instruction* entry = createInstructionGraph(instruction_list, local, state, move, instruction_block->getReturnVariable(), last_instructions);
instruction_block->setEntryPoint(entry);
return instruction_block;
}
Instruction* Compiler::createInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move, Variable* return_var, std::list<Instruction*>& last_instructions)
{
SyntaxTree* typed_instruction = getSingleElement(input_instruction, Type::instruction);
switch (typed_instruction->type)
{
case Type::assign_instr: {
Instruction* instr = createAssignInstruction(typed_instruction, local, state, move);
last_instructions.push_back(instr);
return instr;
}
case Type::return_instr: return createReturnInstruction(typed_instruction, local, state, move, return_var);
case Type::if_instr: return createIfInstruction(typed_instruction, local, state, move, return_var, last_instructions);
case Type::while_instr: return createWhileInstruction(typed_instruction, local, state, move, return_var, last_instructions);
default: break;
}
return nullptr;
}
Instruction* Compiler::createAssignInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move)
{
SyntaxTree* variable_reference_st = getElement(input_instruction, Type::assign_instr, Type::var_reference);
SyntaxTree* expression_st = extract(input_instruction, 1, "EXPR from ASSIGN_INSTR"); // REFACTOR
SyntaxTree* scope_st = extract(variable_reference_st, 0, "SCOPE from VARIABLE_REFERENCE"); // REFACTOR
SyntaxTree* identifier_st = extract(variable_reference_st, 1, "IDENTIFIER from VARIABLE_REFERENCE"); // REFACTOR
DataSet* data_set_to = getScope(scope_st->type, local, state, move);
if (!data_set_to) return NULL;
void* to = data_set_to->getValuePtr(identifier_st->text);
VAR_TYPE type_to = data_set_to->getValueType(identifier_st->text);
if (!to) std::cout << "Warnig: Not found identifier \"" << identifier_st->text << "\" in scope: " << getTypeName(scope_st->type) << '\n';
switch (type_to)
{
case VAR_TYPE::INT:
{
ExpressionInt* expr = createIntExpression(expression_st, local, state, move);
return new InstructionAssignInt(to, expr);
}
case VAR_TYPE::BOOL:
{
ExpressionBool* expr = createBoolExpression(expression_st, local, state, move);
return new InstructionAssignBool(to, expr);
}
default: {
std::cout << "Warnig: Unknown value type\n";
return NULL;
}
}
return nullptr;
}
Instruction* Compiler::createReturnInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move, Variable* return_var)
{
bool returns_value = input_instruction->children_num == 1;
SyntaxTree* expression_st = NULL;
if(returns_value)
expression_st = extract(input_instruction, 0, "EXPR from RETURN_INSTR"); // REFACTOR
switch (return_var->getType())
{
case VAR_TYPE::VOID: {
if (returns_value)
{
std::cout << "Warnig: Wrong return type, should be VOID\n";
return NULL;
}
return new InstructionReturnVoid();
}
case VAR_TYPE::INT: {
if (!returns_value)
{
std::cout << "Warnig: No return value, should be VOID\n";
return NULL;
}
ExpressionInt* expr = createIntExpression(expression_st, local, state, move);
return new InstructionReturnInt(expr, return_var);
}
case VAR_TYPE::BOOL: {
if (!returns_value)
{
std::cout << "Warnig: No return value, should be VOID\n";
return NULL;
}
ExpressionBool* expr = createBoolExpression(expression_st, local, state, move);
return new InstructionReturnBool(expr, return_var);
}
default: break;
}
return nullptr;
}
Instruction* Compiler::createIfInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move, Variable* return_var, std::list<Instruction*>& last_instructions)
{
SyntaxTree* condition_st = extract(input_instruction, 0, "EXPR from IF_INSTR"); // REFACTOR
SyntaxTree* instruction_list_st = extract(input_instruction, 1, "INSTRUCTION_LIST from IF_INSTR"); // REFACTOR
ExpressionBool* condition = createBoolExpression(condition_st, local, state, move);
Instruction* first = createInstructionGraph(instruction_list_st, local, state, move, return_var, last_instructions);
InstructionConditionalJump* instr = new InstructionConditionalJump(condition, first);
last_instructions.push_back(instr);
return instr;
}
Instruction* Compiler::createWhileInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move, Variable* return_var, std::list<Instruction*>& last_instructions)
{
SyntaxTree* condition_st = extract(input_instruction, 0, "EXPR from WHILE_INSTR"); // REFACTOR
SyntaxTree* instruction_list_st = extract(input_instruction, 1, "INSTRUCTION_LIST from WHILE_INSTR"); // REFACTOR
ExpressionBool* condition = createBoolExpression(condition_st, local, state, move);
Instruction* first = createInstructionGraph(instruction_list_st, local, state, move, return_var, last_instructions);
InstructionConditionalJump* while_instr = new InstructionConditionalJump(condition, first);
for (Instruction* instr : last_instructions)
instr->setNext(while_instr);
last_instructions.clear();
last_instructions.push_back(while_instr);
return while_instr;
}
Instruction* Compiler::createInstructionGraph(SyntaxTree* input_instruction_list, DataSet* local, DataSet* state, DataSet* move, Variable* return_variable, std::list<Instruction*>& predecessors)
{
Instruction* entry = NULL;
//Instruction* previous_instr = NULL;
std::list<Instruction*> last_instructions;
while (input_instruction_list->type == Type::instruction_list)
{
SyntaxTree* instruction_st = getElement(input_instruction_list, Type::instruction_list, Type::instruction);
input_instruction_list = extract(input_instruction_list, 1, "INSTRUCTION_LIST from INSTRUCTION_LIST"); // REFACTOR
last_instructions.clear();
Instruction* next_instr = createInstruction(instruction_st, local, state, move, return_variable, last_instructions);
if (entry == NULL)
{
entry = next_instr;
//previous_instr = next_instr;
predecessors = last_instructions;
}
else
{
//previous_instr->setNext(next_instr);
//previous_instr = next_instr;
for (Instruction* instr : predecessors)
instr->setNext(next_instr);
predecessors.clear();
predecessors = last_instructions;
}
}
return entry;
}
ExpressionInt* Compiler::createIntExpression(SyntaxTree* input_expression, DataSet* local, DataSet* state, DataSet* move)
{
switch (input_expression->type)
{
case Type::expr:
{
SyntaxTree* next_expr = extract(input_expression, 0, "EXPR from EXPR"); // REFACTOR
return createIntExpression(next_expr, local, state, move);
}
case Type::expr_ref:
{
SyntaxTree* variable_reference_st = extract(input_expression, 0, "VARIABLE_REFERENCE from EXPR"); // REFACTOR
void* from = getIdentifierReference(variable_reference_st, VAR_TYPE::INT, local, state, move);
if (!from) return NULL;
return new ExpressionInt_Id((int*)from);
}
case Type::expr_literal:
{
SyntaxTree* var_def = getElement(input_expression, Type::expr_literal, Type::var_definition);
std::string string_val = extract(var_def, 0, "type from VAR_DECLARATION")->text;
return new ExpressionInt_Value(stoi(string_val));
}
case Type::expr_neg:
{
SyntaxTree* arg_st = extract(input_expression, 0, "EXPR A from EXPR");
ExpressionInt* arg = createIntExpression(arg_st, local, state, move);
return new ExpressionInt_Neg(arg);
}
case Type::expr_add:
case Type::expr_sub:
case Type::expr_mul:
case Type::expr_div:
case Type::expr_mod:
{
SyntaxTree* arg_a_st = extract(input_expression, 0, "EXPR A from EXPR");
SyntaxTree* arg_b_st = extract(input_expression, 1, "EXPR B from EXPR");
ExpressionInt* a = createIntExpression(arg_a_st, local, state, move);
ExpressionInt* b = createIntExpression(arg_b_st, local, state, move);
switch (input_expression->type)
{
case Type::expr_add: return new ExpressionInt_Add(a, b);
case Type::expr_sub: return new ExpressionInt_Sub(a, b);
case Type::expr_mul: return new ExpressionInt_Mul(a, b);
case Type::expr_div: return new ExpressionInt_Div(a, b);
case Type::expr_mod: return new ExpressionInt_Mod(a, b);
}
}
default: break;
}
return nullptr;
}
ExpressionBool* Compiler::createBoolExpression(SyntaxTree* input_expression, DataSet* local, DataSet* state, DataSet* move)
{
switch (input_expression->type)
{
case Type::expr:
{
SyntaxTree* next_expr = extract(input_expression, 0, "EXPR from EXPR"); // REFACTOR
return createBoolExpression(next_expr, local, state, move);
}
case Type::expr_ref:
{
SyntaxTree* variable_reference_st = extract(input_expression, 0, "VARIABLE_REFERENCE from EXPR"); // REFACTOR
void* from = getIdentifierReference(variable_reference_st, VAR_TYPE::BOOL, local, state, move);
if (!from) return NULL;
return new ExpressionBool_Id((bool*)from);
}
case Type::expr_literal:
{
SyntaxTree* var_def = getElement(input_expression, Type::expr_literal, Type::var_definition);
std::string string_val = extract(var_def, 0, "type from VAR_DECLARATION")->text;
return new ExpressionBool_Value(string_val == "true");
}
case Type::expr_not:
{
SyntaxTree* arg_st = extract(input_expression, 0, "EXPR from EXPR");
ExpressionBool* arg = createBoolExpression(arg_st, local, state, move);
return new ExpressionBool_Not(arg);
}
case Type::expr_and:
case Type::expr_or:
{
SyntaxTree* arg_a_st = extract(input_expression, 0, "EXPR A from EXPR");
SyntaxTree* arg_b_st = extract(input_expression, 1, "EXPR B from EXPR");
ExpressionBool* a = createBoolExpression(arg_a_st, local, state, move);
ExpressionBool* b = createBoolExpression(arg_b_st, local, state, move);
switch (input_expression->type)
{
case Type::expr_and: return new ExpressionBool_And(a, b);
case Type::expr_or: return new ExpressionBool_Or(a, b);
}
}
case Type::expr_equal:
case Type::expr_not_equal:
case Type::expr_greater_equal:
case Type::expr_less_equal:
case Type::expr_greater:
case Type::expr_less:
{
SyntaxTree* arg_a_st = extract(input_expression, 0, "EXPR A from EXPR");
SyntaxTree* arg_b_st = extract(input_expression, 1, "EXPR B from EXPR");
ExpressionInt* a = createIntExpression(arg_a_st, local, state, move);
ExpressionInt* b = createIntExpression(arg_b_st, local, state, move);
switch (input_expression->type)
{
case Type::expr_equal: return new ExpressionBool_Equal(a, b);
case Type::expr_not_equal: return new ExpressionBool_NotEqual(a, b);
case Type::expr_greater_equal: return new ExpressionBool_GreaterEqual(a, b);
case Type::expr_less_equal: return new ExpressionBool_LessEqual(a, b);
case Type::expr_greater: return new ExpressionBool_Greater(a, b);
case Type::expr_less: return new ExpressionBool_Less(a, b);
}
}
default: break;
}
return nullptr;
}
void* Compiler::getIdentifierReference(SyntaxTree* var_reference, VAR_TYPE required_type, DataSet* local, DataSet* state, DataSet* move)
{
SyntaxTree* scope_st = extract(var_reference, 0, "SCOPE from VARIABLE_REFERENCE"); // REFACTOR
SyntaxTree* identifier_st = extract(var_reference, 1, "IDENTIFIER from VARIABLE_REFERENCE"); // REFACTOR
DataSet* data_set_from = getScope(scope_st->type, local, state, move);
if (!data_set_from) return NULL;
void* from = data_set_from->getValuePtr(identifier_st->text);
VAR_TYPE type_from = data_set_from->getValueType(identifier_st->text);
if (!from) std::cout << "Warnig: Not found identifier \"" << identifier_st->text << "\" in scope: " << getTypeName(scope_st->type) << '\n';
if (type_from != required_type) {
std::cout << "Warnig: Incorrect variable type, should be " << VarTypeToString(required_type) << "\n";
return NULL;
}
return from;
}
DataSet* Compiler::getScope(Type type, DataSet* local, DataSet* state, DataSet* move)
{
switch (type)
{
case Type::local_scope: return local;
case Type::state_scope: return state;
case Type::move_scope: return move;
default: {
std::cout << "Warnig: Unknown scope: " << (std::string)getTypeName(type) << '\n';
return NULL;
}
}
}
#pragma once
#include <list>
#include <string>
#include "../Grammar/Common.h"
#include "Game.h"
class Compiler
{
private:
bool nullCheck(SyntaxTree* ptr, std::string warning);
// Extrctors
SyntaxTree* extract(SyntaxTree* ptr, int index, std::string warning);
SyntaxTree* getElement(SyntaxTree* ptr, Type from, Type get);
SyntaxTree* getSingleElement(SyntaxTree* ptr, Type from);
// Extract GAME
SyntaxTree* get_STATE_from_GAME(SyntaxTree* game);
// Extract STATE
SyntaxTree* get_DATA_SET_from_STATE(SyntaxTree* state);
SyntaxTree* get_INSTRUCTION_BLOCK_from_STATE(SyntaxTree* state);
// Extract DATA_SET
SyntaxTree* get_VAR_LIST_from_DATA_SET(SyntaxTree* data_set);
// Extract VAR_LIST
SyntaxTree* get_VAR_DECLARATION_from_VAR_LIST(SyntaxTree* var_list);
SyntaxTree* get_VAR_LIST_from_VAR_LIST(SyntaxTree* var_list);
// Extract VAR_DECLARATION
std::string get_type_from_VAR_DECLARATION(SyntaxTree* var_declaration);
std::string get_identifier_from_VAR_DECLARATION(SyntaxTree* var_declaration);
std::string get_value_from_VAR_DECLARATION(SyntaxTree* var_declaration);
// Extract INSTRUCTION_BLOCK
SyntaxTree* get_DATA_SET_from_INSTRUCTION_BLOCK(SyntaxTree* state);
SyntaxTree* get_INSTRUCTION_LIST_from_INSTRUCTION_BLOCK(SyntaxTree* state);
// Extract INSTRUCTION_LIST
SyntaxTree* get_INSTRUCTION_LIST_from_INSTRUCTION_LIST(SyntaxTree* state);
SyntaxTree* get_INSTRUCTION_from_INSTRUCTION_LIST(SyntaxTree* state);
// Extract INSTRUCTION
SyntaxTree* get_INSTRUCTION_type_from_INSTRUCTION(SyntaxTree* state);
// Extract ASSIGN_INSTR
SyntaxTree* get_VAR_REFERENCE_from_ASSIGN_INSTR(SyntaxTree* state);
SyntaxTree* get_EXPR_from_ASSIGN_INSTR(SyntaxTree* state);
// Extract VAR_REFERENCE
SyntaxTree* get_SCOPE_from_VAR_REFERENCE(SyntaxTree* state);
SyntaxTree* get_IDENTIFIER_from_VAR_REFERENCE(SyntaxTree* state);
// Extract EXPR
SyntaxTree* get_VAR_REFERENCE_from_EXPR(SyntaxTree* state);
SyntaxTree* get_VAR_DEFINITION_from_EXPR(SyntaxTree* state);
SyntaxTree* get_EXPR_from_EXPR(SyntaxTree* state);
// Data functions
void setVariable(DataSet* data_set, std::string type, std::string name, std::string value);
// Main components //
// Takes STATE part of syntax tree as an input
// Structure of STATE is:
//
// DATA_SET -> VAR_LIST -> VAR_DECLARATION
// |
// -> VAR_DECLARATION
// VAR_LIST
DataSet* createDataSet(SyntaxTree* input_data_set);
// Instructions //
InstructionBlock* createInstructionBlock(SyntaxTree* input_instruction_block, DataSet* state, DataSet* move, VAR_TYPE return_type);
Instruction* createInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move, Variable* return_var, std::list<Instruction*>& last_instructions);
Instruction* createAssignInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move);
Instruction* createReturnInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move, Variable* return_var);
Instruction* createIfInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move, Variable* return_var, std::list<Instruction*>& last_instructions);
Instruction* createWhileInstruction(SyntaxTree* input_instruction, DataSet* local, DataSet* state, DataSet* move, Variable* return_var, std::list<Instruction*>& last_instructions);
Instruction* createInstructionGraph(SyntaxTree* input_instruction_list, DataSet* local, DataSet* state, DataSet* move, Variable* return_variable, std::list<Instruction*>& predecessors);
ExpressionInt* createIntExpression(SyntaxTree* input_expression, DataSet* local, DataSet* state, DataSet* move);
ExpressionBool* createBoolExpression(SyntaxTree* input_expression, DataSet* local, DataSet* state, DataSet* move);
void* getIdentifierReference(SyntaxTree* var_reference, VAR_TYPE required_type, DataSet* local, DataSet* state, DataSet* move);
DataSet* getScope(Type type, DataSet* local, DataSet* state, DataSet* move);
public:
// Takes as an input all syntax tree
// Its main parts are:
//
// MAIN_RULE
// STATE
// MOVES
Game* createGame(SyntaxTree* input_game);
};
#include "DataSet.h"
DataSet::DataSet(int size)
{
data = malloc(size);
if (data == NULL)
{
std::cout << "Memory allocation error\n";
exit(1);
}
data_size = size;
}
DataSet::~DataSet()
{
free(data);
}
bool DataSet::exist(std::string name)
{
return map.find(name) != map.end();
}
bool DataSet::defineVariable(std::string name, VAR_TYPE type, int size)
{
if (bits_taken + size > data_size)
return false;
if (exist(name))
return false;
map[name] = variable(bits_taken, type);
bits_taken += size;
return true;
}
void* DataSet::getValuePtr(std::string name)
{
if (!exist(name))
{
std::cout << "not found\n";
return nullptr;
}
int data_index = map.at(name).pointer;
return (char*)data + data_index;
}
VAR_TYPE DataSet::getValueType(std::string name)
{
if (!exist(name))
{
std::cout << "not found\n";
return VAR_TYPE::UNKNOWN;
}
return map.at(name).type;
}
void DataSet::print()
{
for (std::pair<const std::string, variable>& kv : map)
{
const std::string& name = kv.first;
variable& var = kv.second;
std::cout << VarTypeToString(var.type) << ' ' << name << ' ' << getStringValue(getValuePtr(name), var.type) << '\n';
}
}
Variable::Variable(VAR_TYPE type)
: type(type)
{
switch (type)
{
case VAR_TYPE::INT: value_ptr = malloc(sizeof(int)); break;
case VAR_TYPE::BOOL: value_ptr = malloc(sizeof(bool)); break;
default: value_ptr = NULL;
}
}
bool Variable::setValueInt(int value)
{
if (type != VAR_TYPE::INT)
return false;
*(int*)value_ptr = value;
return true;
}
bool Variable::setValueBool(bool value)
{
if (type != VAR_TYPE::BOOL)
return false;
*(bool*)value_ptr = value;
return true;
}
void* Variable::getValue()
{
return value_ptr;
}
int Variable::getValueInt()
{
if (type != VAR_TYPE::INT)
{
std::cout << "Warnig: Wrong type requested. Current type: " << VarTypeToString(type) << " \tRequested: INT\n";
return 0;
}
return *(int*)value_ptr;
}
bool Variable::getValueBool()
{
if (type != VAR_TYPE::BOOL)
{
std::cout << "Warnig: Wrong type requested. Current type: " << VarTypeToString(type) << " \tRequested: BOOL\n";
return 0;
}
return *(bool*)value_ptr;
}
VAR_TYPE Variable::getType()
{
return type;
}
#pragma once
#include <iostream>
#include <unordered_map>
#include <string>
#include "VarType.h"
// Class contains set of variables,
// they are stored in the main table
// and referenced by name
class DataSet
{
private:
struct variable {
int pointer;
VAR_TYPE type;
variable()
: pointer(0), type(VAR_TYPE::UNKNOWN)
{}
variable(int pointer, VAR_TYPE type)
: pointer(pointer), type(type)
{}
};
// Stores mixed data of set
void* data = NULL;
int data_size = 0;
int bits_taken = 0;
// Maps data in 'data' table with its name
std::unordered_map<std::string, variable> map;
bool exist(std::string name);
public:
// Allocates memory for 'data' table
DataSet(int size);
~DataSet();
bool defineVariable(std::string name, VAR_TYPE type, int size);
void* getValuePtr(std::string name);
VAR_TYPE getValueType(std::string name);
void print();
};
class Variable
{
private:
void* value_ptr;
VAR_TYPE type;
public:
Variable(VAR_TYPE type);
bool setValueInt(int value);
bool setValueBool(bool value);
void* getValue();
int getValueInt();
bool getValueBool();
VAR_TYPE getType();
};
#include "VarType.h"
VAR_TYPE stringToVarType(std::string type)
{
if (type == "INT") return VAR_TYPE::INT;
else if (type == "BOOL") return VAR_TYPE::BOOL;
std::cout << "Error: unknown type:\t" << type << '\n';
return VAR_TYPE::UNKNOWN;
}
std::string VarTypeToString(VAR_TYPE type)
{
switch (type)
{
case VAR_TYPE::INT: return "INT";
case VAR_TYPE::BOOL: return "BOOL";
case VAR_TYPE::VOID: return "VOID";
default: return "UNKNOWN";
}
}
int getTypeSize(std::string type)
{
if (type == "INT") return sizeof(int);
else if (type == "BOOL") return sizeof(bool);
else std::cout << "Error: unknown type:\t" << type << '\n';
return 0;
}
std::string getStringValue(void* ptr, VAR_TYPE type)
{
switch (type)
{
case VAR_TYPE::INT: return std::to_string(*(int*)ptr);
case VAR_TYPE::BOOL: return (*(bool*)ptr) ? "true" : "false";
default: return "";
}
}
#pragma once
#include <iostream>
#include <string>
enum class VAR_TYPE
{
INT,
BOOL,
VOID,
UNKNOWN
};
VAR_TYPE stringToVarType(std::string type);
std::string VarTypeToString(VAR_TYPE type);
int getTypeSize(std::string type);
std::string getStringValue(void* ptr, VAR_TYPE type);
\ No newline at end of file
#include "Game.h"
Game::Game(DataSet* state)
{
this->state = state;
}
#pragma once
#include "DataSet/DataSet.h"
#include "Instructions/InstructionBlock.h"
class Game
{
private:
DataSet* state;
public:
Game(DataSet* state);
};
#include "ExpressionBool.h"
// Constructors
ExpressionBool_Id::ExpressionBool_Id(bool* ptr)
{
value_ptr = ptr;
}
ExpressionBool_Value::ExpressionBool_Value(bool val)
{
value = val;
}
ExpressionBool_Not::ExpressionBool_Not(ExpressionBool* expr)
{
this->expr = expr;
}
bool ExpressionBool_Not::evaluate()
{
return !expr->evaluate();
}
ExpressionBool_TwoBoolArgumentsOperation::ExpressionBool_TwoBoolArgumentsOperation(ExpressionBool* a, ExpressionBool* b)
{
expr_a = a;
expr_b = b;
}
ExpressionBool_TwoIntArgumentsOperation::ExpressionBool_TwoIntArgumentsOperation(ExpressionInt* a, ExpressionInt* b)
{
expr_a = a;
expr_b = b;
}
//Evaluators
bool ExpressionBool::evaluate()
{
return false;
}
bool ExpressionBool_Id::evaluate()
{
return *value_ptr;
}
bool ExpressionBool_Value::evaluate()
{
return value;
}
bool ExpressionBool_And::evaluate()
{
return expr_a->evaluate() && expr_b->evaluate();
}
bool ExpressionBool_Or::evaluate()
{
return expr_a->evaluate() || expr_b->evaluate();
}
bool ExpressionBool_Equal::evaluate()
{
return expr_a->evaluate() == expr_b->evaluate();
}
bool ExpressionBool_NotEqual::evaluate()
{
return expr_a->evaluate() != expr_b->evaluate();
}
bool ExpressionBool_GreaterEqual::evaluate()
{
return expr_a->evaluate() >= expr_b->evaluate();
}
bool ExpressionBool_LessEqual::evaluate()
{
return expr_a->evaluate() <= expr_b->evaluate();
}
bool ExpressionBool_Greater::evaluate()
{
return expr_a->evaluate() > expr_b->evaluate();
}
bool ExpressionBool_Less::evaluate()
{
return expr_a->evaluate() < expr_b->evaluate();
}
#pragma once
#include "ExpressionInt.h"
class ExpressionBool
{
public:
virtual bool evaluate();
};
// Subclasses for Bool Expression
// Expression represents a refference
// to DataSet by identifier
class ExpressionBool_Id : public ExpressionBool
{
private:
bool* value_ptr;
public:
ExpressionBool_Id(bool* ptr);
bool evaluate() override;
};
// Expression represents a
// constant value
class ExpressionBool_Value : public ExpressionBool
{
private:
bool value;
public:
ExpressionBool_Value(bool val);
bool evaluate() override;
};
// Expression represents negation
// of BOOL expression
class ExpressionBool_Not : public ExpressionBool
{
private:
ExpressionBool* expr;
public:
ExpressionBool_Not(ExpressionBool* expr);
bool evaluate() override;
};
// Class agregates two Bool argument operations
class ExpressionBool_TwoBoolArgumentsOperation : public ExpressionBool
{
protected:
ExpressionBool* expr_a;
ExpressionBool* expr_b;
public:
ExpressionBool_TwoBoolArgumentsOperation(ExpressionBool* a, ExpressionBool* b);
};
class ExpressionBool_And : public ExpressionBool_TwoBoolArgumentsOperation
{
public:
ExpressionBool_And(ExpressionBool* a, ExpressionBool* b) : ExpressionBool_TwoBoolArgumentsOperation(a, b) {}
bool evaluate() override;
};
class ExpressionBool_Or : public ExpressionBool_TwoBoolArgumentsOperation
{
public:
ExpressionBool_Or(ExpressionBool* a, ExpressionBool* b) : ExpressionBool_TwoBoolArgumentsOperation(a, b) {}
bool evaluate() override;
};
// Class agregates two Int argument operations
class ExpressionBool_TwoIntArgumentsOperation : public ExpressionBool
{
protected:
ExpressionInt* expr_a;
ExpressionInt* expr_b;
public:
ExpressionBool_TwoIntArgumentsOperation(ExpressionInt* a, ExpressionInt* b);
};
class ExpressionBool_Equal : public ExpressionBool_TwoIntArgumentsOperation
{
public:
ExpressionBool_Equal(ExpressionInt* a, ExpressionInt* b) : ExpressionBool_TwoIntArgumentsOperation(a, b) {}
bool evaluate() override;
};
class ExpressionBool_NotEqual : public ExpressionBool_TwoIntArgumentsOperation
{
public:
ExpressionBool_NotEqual(ExpressionInt* a, ExpressionInt* b) : ExpressionBool_TwoIntArgumentsOperation(a, b) {}
bool evaluate() override;
};
class ExpressionBool_GreaterEqual : public ExpressionBool_TwoIntArgumentsOperation
{
public:
ExpressionBool_GreaterEqual(ExpressionInt* a, ExpressionInt* b) : ExpressionBool_TwoIntArgumentsOperation(a, b) {}
bool evaluate() override;
};
class ExpressionBool_LessEqual : public ExpressionBool_TwoIntArgumentsOperation
{
public:
ExpressionBool_LessEqual(ExpressionInt* a, ExpressionInt* b) : ExpressionBool_TwoIntArgumentsOperation(a, b) {}
bool evaluate() override;
};
class ExpressionBool_Greater : public ExpressionBool_TwoIntArgumentsOperation
{
public:
ExpressionBool_Greater(ExpressionInt* a, ExpressionInt* b) : ExpressionBool_TwoIntArgumentsOperation(a, b) {}
bool evaluate() override;
};
class ExpressionBool_Less : public ExpressionBool_TwoIntArgumentsOperation
{
public:
ExpressionBool_Less(ExpressionInt* a, ExpressionInt* b) : ExpressionBool_TwoIntArgumentsOperation(a, b) {}
bool evaluate() override;
};
#include "ExpressionInt.h"
// Expression constructors
ExpressionInt_Id::ExpressionInt_Id(int* ptr)
{
value_ptr = ptr;
}
ExpressionInt_Value::ExpressionInt_Value(int val)
{
value = val;
}
ExpressionInt_Neg::ExpressionInt_Neg(ExpressionInt* expr)
{
this->expr = expr;
}
int ExpressionInt_Neg::evaluate()
{
return -expr->evaluate();
}
ExpressionInt_TwoArgumentsOperation::ExpressionInt_TwoArgumentsOperation(ExpressionInt* a, ExpressionInt* b)
{
expr_a = a;
expr_b = b;
}
// Evaluators
int ExpressionInt::evaluate()
{
return 0;
}
int ExpressionInt_Id::evaluate()
{
return *value_ptr;
}
int ExpressionInt_Value::evaluate()
{
return value;
}
int ExpressionInt_Add::evaluate()
{
return expr_a->evaluate() + expr_b->evaluate();
}
int ExpressionInt_Sub::evaluate()
{
return expr_a->evaluate() - expr_b->evaluate();
}
int ExpressionInt_Mul::evaluate()
{
return expr_a->evaluate() * expr_b->evaluate();
}
int ExpressionInt_Div::evaluate()
{
return expr_a->evaluate() / expr_b->evaluate();
}
int ExpressionInt_Mod::evaluate()
{
return expr_a->evaluate() % expr_b->evaluate();
}
#pragma once
class ExpressionInt
{
public:
virtual int evaluate();
};
// Subclasses for Int Expression
// Expression represents a refference
// to DataSet by identifier
class ExpressionInt_Id : public ExpressionInt
{
private:
int* value_ptr;
public:
ExpressionInt_Id(int* ptr);
int evaluate() override;
};
// Expression represents a
// constant value
class ExpressionInt_Value : public ExpressionInt
{
private:
int value;
public:
ExpressionInt_Value(int val);
int evaluate() override;
};
// Expression represents negation
// of expression
class ExpressionInt_Neg : public ExpressionInt
{
private:
ExpressionInt* expr;
public:
ExpressionInt_Neg(ExpressionInt* expr);
int evaluate() override;
};
// Class agregates two argument operations
class ExpressionInt_TwoArgumentsOperation : public ExpressionInt
{
protected:
ExpressionInt* expr_a;
ExpressionInt* expr_b;
public:
ExpressionInt_TwoArgumentsOperation(ExpressionInt* a, ExpressionInt* b);
};
// Expression represents
// sum
// of two expressions
class ExpressionInt_Add : public ExpressionInt_TwoArgumentsOperation
{
public:
ExpressionInt_Add(ExpressionInt* a, ExpressionInt* b) : ExpressionInt_TwoArgumentsOperation(a, b) {}
int evaluate() override;
};
// Expression represents
// difference
// of two expressions
class ExpressionInt_Sub : public ExpressionInt_TwoArgumentsOperation
{
public:
ExpressionInt_Sub(ExpressionInt* a, ExpressionInt* b) : ExpressionInt_TwoArgumentsOperation(a, b) {}
int evaluate() override;
};
// Expression represents
// multiplication
// of two expressions
class ExpressionInt_Mul : public ExpressionInt_TwoArgumentsOperation
{
public:
ExpressionInt_Mul (ExpressionInt* a, ExpressionInt* b) : ExpressionInt_TwoArgumentsOperation(a, b) {}
int evaluate() override;
};
// Expression represents
// division
// of two expressions
class ExpressionInt_Div : public ExpressionInt_TwoArgumentsOperation
{
public:
ExpressionInt_Div(ExpressionInt* a, ExpressionInt* b) : ExpressionInt_TwoArgumentsOperation(a, b) {}
int evaluate() override;
};
// Expression represents
// mod
// of two expressions
class ExpressionInt_Mod : public ExpressionInt_TwoArgumentsOperation
{
public:
ExpressionInt_Mod(ExpressionInt* a, ExpressionInt* b) : ExpressionInt_TwoArgumentsOperation(a, b) {}
int evaluate() override;
};
#include "Instruction.h"
Instruction::Instruction()
:next(NULL)
{}
Instruction::Instruction(Instruction* next)
: next(next)
{}
void Instruction::setNext(Instruction* next)
{
this->next = next;
}
Instruction* Instruction::Run()
{
return next;
}
#pragma once
#include <iostream>
#include <string>
class Instruction
{
protected:
Instruction* next;
public:
Instruction();
Instruction(Instruction* next);
virtual void setNext(Instruction* next);
virtual Instruction* Run();
};
#include "InstructionAssign.h"
InstructionAssign::InstructionAssign(void* to)
: to(to)
{}
InstructionAssignInt::InstructionAssignInt(void* to, ExpressionInt* expr)
: InstructionAssign(to), expression(expr)
{}
Instruction* InstructionAssignInt::Run()
{
*(int*)to = expression->evaluate();
return next;
}
InstructionAssignBool::InstructionAssignBool(void* to, ExpressionBool* expr)
: InstructionAssign(to), expression(expr)
{}
Instruction* InstructionAssignBool::Run()
{
*(bool*)to = expression->evaluate();
return next;
}
#pragma once
#include "Instruction.h"
#include "Expression/ExpressionInt.h"
#include "Expression/ExpressionBool.h"
class InstructionAssign : public Instruction
{
protected:
void* to;
InstructionAssign(void* to);
};
class InstructionAssignInt : public InstructionAssign
{
private:
ExpressionInt* expression;
public:
InstructionAssignInt(void* to, ExpressionInt* expr);
Instruction* Run() override;
};
class InstructionAssignBool : public InstructionAssign
{
private:
ExpressionBool* expression;
public:
InstructionAssignBool(void* to, ExpressionBool* expr);
Instruction* Run() override;
};
#include "InstructionConditionalJump.h"
InstructionConditionalJump::InstructionConditionalJump(ExpressionBool* condition, Instruction* if_true)
: condition(condition), if_true(if_true)
{}
Instruction* InstructionConditionalJump::Run()
{
bool result = condition->evaluate();
if (result)
return if_true;
return next;
}