Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/interpreter/expressions/expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "interpreter/expressions/assignment_expression.hpp"
#include "interpreter/expressions/binary_expression.hpp"
#include "interpreter/expressions/literal_expression.hpp"
#include "interpreter/expressions/member_expression.hpp"
#include "interpreter/expressions/unary_expression.hpp"

class Expression {
Expand Down
19 changes: 19 additions & 0 deletions include/interpreter/expressions/member_expression.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef MEMBER_EXPRESSION_HPP
#define MEMBER_EXPRESSION_HPP

#include "interpreter/expressions/expression.hpp"
#include "interpreter/storage.hpp"
#include "parser/ast_nodes.hpp"

class MemberExpression {
public:
MemberExpression(MemberExpr *expressionNode,
std::vector<std::shared_ptr<Storage>> storage);
Storage::DataWrapper execute();

private:
MemberExpr *expressionNode;
std::vector<std::shared_ptr<Storage>> storage;
};

#endif // MEMBER_EXPRESSION_HPP
3 changes: 2 additions & 1 deletion include/interpreter/statements/declaration_statement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ class DeclarationStatement {
DeclarationStatement(VarDeclaration *declarationNode,
std::vector<std::shared_ptr<Storage>> storage);
void execute();
std::vector<std::string> declareLoopVariables();

private:
std::variant<VarDeclaration *, FunctionDeclaration *> declarationNode;
std::vector<std::shared_ptr<Storage>> storage;

void executeVarDeclaration();
std::vector<std::string> executeVarDeclaration();
void executeFunctionDeclaration();
};

Expand Down
2 changes: 1 addition & 1 deletion include/interpreter/statements/log_statement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class LogStatement {
private:
LogStmt *logNode;
std::vector<std::shared_ptr<Storage>> storage;
std::string getPrintableValue();
std::string getPrintableValue(Storage::DataWrapper value);
void hexToRGB(const std::string &hex, int &r, int &g, int &b);
};

Expand Down
2 changes: 1 addition & 1 deletion include/interpreter/statements/loop_statement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class LoopStatement {
void executeWhileLoop();
void executeDoWhileLoop();
void executeForLoop();
void executeForInLoop();
void executeForOfLoop();
void executeForInLoop();
};

#endif // LOOP_STATEMENT_HPP
19 changes: 18 additions & 1 deletion include/interpreter/storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "parser/ast_nodes.hpp"
#include <any>
#include <map>
#include <memory>
#include <stdexcept>
#include <string>
Expand All @@ -11,21 +12,37 @@
class Storage {
public:
enum class WrapperType { VALUE, VARIABLE, CONSTANT };
enum DataType { INTEGER, DOUBLE, BOOLEAN, CHAR, STRING, HEXCODE, _NULL };
enum DataType {
INTEGER,
DOUBLE,
BOOLEAN,
CHAR,
STRING,
HEXCODE,
ARRAY,
OBJECT,
_NULL
};

struct DataWrapper;

union Data {
int _int;
double _double;
bool _bool;
char _char;
std::string *_string;
std::vector<DataWrapper> *_array;
std::map<std::string, DataWrapper> *_object;

Data();
Data(int value);
Data(double value);
Data(bool value);
Data(char value);
Data(std::string *value);
Data(std::vector<DataWrapper> *value);
Data(std::map<std::string, DataWrapper> *value);
~Data();
};

Expand Down
3 changes: 3 additions & 0 deletions src/interpreter/expressions/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ Storage::DataWrapper Expression::execute() {
case NodeType::UnaryExpr:
return UnaryExpression(dynamic_cast<UnaryExpr *>(exprNode), storage)
.execute();
case NodeType::MemberExpr:
return MemberExpression(dynamic_cast<MemberExpr *>(exprNode), storage)
.execute();
default:
return LiteralExpression(exprNode, storage).execute();
}
Expand Down
17 changes: 17 additions & 0 deletions src/interpreter/expressions/literal_expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@ Storage::DataWrapper LiteralExpression::execute() {
throw std::logic_error("Variable not declared.");
}
return storage[keyIndex]->getEntry(expr->identifier.value);
} else if (auto expr = dynamic_cast<ArrayLiteral *>(expressionNode)) {
std::vector<Storage::DataWrapper> elements;
for (const auto &element : expr->elements) {
elements.push_back(Expression(element.get(), storage).execute());
}
return Storage::DataWrapper(
Storage::WrapperType::VALUE, Storage::DataType::ARRAY,
new std::vector<Storage::DataWrapper>(elements));
} else if (auto expr = dynamic_cast<ObjectLiteral *>(expressionNode)) {
std::map<std::string, Storage::DataWrapper> elements;
for (const auto &property : expr->properties) {
elements[property.get()->key.value] =
Expression(property.get()->value.get(), storage).execute();
}
return Storage::DataWrapper(
Storage::WrapperType::VALUE, Storage::DataType::OBJECT,
new std::map<std::string, Storage::DataWrapper>(elements));
} else if (auto expr = dynamic_cast<IntegerLiteral *>(expressionNode)) {
return Storage::DataWrapper(Storage::WrapperType::VALUE,
Storage::DataType::INTEGER, expr->value);
Expand Down
35 changes: 35 additions & 0 deletions src/interpreter/expressions/member_expression.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "interpreter/expressions/member_expression.hpp"

MemberExpression::MemberExpression(
MemberExpr *expressionNode, std::vector<std::shared_ptr<Storage>> storage)
: expressionNode(expressionNode), storage(std::move(storage)) {}

Storage::DataWrapper MemberExpression::execute() {
Storage::DataWrapper object =
Expression(dynamic_cast<Expr *>(expressionNode->object.get()), storage)
.execute();
if (object.dataType != Storage::DataType::OBJECT) {
throw std::logic_error("Object expected!");
}
std::string property = "";
if (expressionNode->computed) {
Storage::DataWrapper propertyStr =
Expression(dynamic_cast<Expr *>(expressionNode->property.get()),
storage)
.execute();
if (propertyStr.dataType != Storage::DataType::STRING) {
throw std::logic_error("Property name must be a string!");
}
property = *propertyStr.data._string;
} else {
if (expressionNode->property->kind != NodeType::Identifier) {
throw std::logic_error("Property name must be an identifier!");
}
property = dynamic_cast<Identifier *>(expressionNode->property.get())
->identifier.value;
}
if (object.data._object->find(property) == object.data._object->end()) {
throw std::logic_error("Property not found!");
}
return object.data._object->at(property);
}
1 change: 1 addition & 0 deletions src/interpreter/statements/conditional_statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ void ConditionalStatement::execute() {
Statement(stmt.get(), storage).execute();
}
}
storage.pop_back();
}
26 changes: 17 additions & 9 deletions src/interpreter/statements/declaration_statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,27 @@ void DeclarationStatement::execute() {
}
}

void DeclarationStatement::executeVarDeclaration() {
std::vector<std::string> DeclarationStatement::declareLoopVariables() {
return executeVarDeclaration();
}

std::vector<std::string> DeclarationStatement::executeVarDeclaration() {
auto varDeclaration = std::get<VarDeclaration *>(declarationNode);
std::vector<std::string> declaredVariables = {};
for (const auto &declaration : varDeclaration->declarations) {
if (declaration.second) {
if (storageKeyIndex(storage, declaration.first.value) != -1) {
throw std::logic_error("Variable already declared.");
}
storage.back()->setValue(
declaration.first.value,
Expression(static_cast<Expr *>(declaration.second.get()), storage)
.execute());
if (storageKeyIndex(storage, declaration.first.value) != -1) {
throw std::logic_error("Variable already declared.");
}
Storage::DataWrapper value =
declaration.second == nullptr
? Storage::DataWrapper(Storage::WrapperType::VALUE,
Storage::DataType::_NULL, 0)
: Expression(static_cast<Expr *>(declaration.second.get()), storage)
.execute();
storage.back()->setValue(declaration.first.value, value);
declaredVariables.push_back(declaration.first.value);
}
return declaredVariables;
}

void DeclarationStatement::executeFunctionDeclaration() {
Expand Down
70 changes: 43 additions & 27 deletions src/interpreter/statements/log_statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,60 +8,76 @@ void LogStatement::execute() {
if (logNode->logType.tag != Token::TypeTag::LOG) {
throw std::logic_error("Expected log token.");
}
if (!logNode->message) {
return;
}

std::string printableValue = getPrintableValue(
Expression(dynamic_cast<Expr *>(logNode->message.get()), storage)
.execute());

switch (logNode->logType.type.logToken) {
case LogToken::BASIC:
std::cout << getPrintableValue() << std::endl;
std::cout << printableValue << std::endl;
break;

case LogToken::COLORED:
int r, g, b;
if (auto *hexCode = dynamic_cast<HexCodeLiteral *>(logNode->color.get())) {
hexToRGB(hexCode->value, r, g, b);
std::cout << "\033[38;2;" << r << ";" << g << ";" << b << "m"
<< getPrintableValue() << "\033[0m" << std::endl;
<< printableValue << "\033[0m" << std::endl;
} else {
throw std::invalid_argument("Expected hex code for colored log message.");
}
break;

case LogToken::WARN:
std::cout << "\033[33m" << getPrintableValue() << "\033[0m" << std::endl;
std::cout << "\033[33m" << printableValue << "\033[0m" << std::endl;
break;

case LogToken::ERROR:
std::cout << "\033[31m" << getPrintableValue() << "\033[0m" << std::endl;
std::cout << "\033[31m" << printableValue << "\033[0m" << std::endl;
break;

default:
throw std::runtime_error("Unknown log token type.");
}
}

std::string LogStatement::getPrintableValue() {
if (logNode->message) {
Storage::DataWrapper value =
Expression(dynamic_cast<Expr *>(logNode->message.get()), storage)
.execute();
switch (value.dataType) {
case Storage::DataType::INTEGER:
return std::to_string(value.data._int);
case Storage::DataType::DOUBLE:
return std::to_string(value.data._double);
case Storage::DataType::BOOLEAN:
return value.data._bool ? "true" : "false";
case Storage::DataType::CHAR:
return std::string(1, value.data._char);
case Storage::DataType::STRING:
case Storage::DataType::HEXCODE:
return *(value.data._string);
case Storage::DataType::_NULL:
return "null";
default:
throw std::invalid_argument("Unknown data type!");
std::string LogStatement::getPrintableValue(Storage::DataWrapper value) {
std::string result = "";
switch (value.dataType) {
case Storage::DataType::INTEGER:
return std::to_string(value.data._int);
case Storage::DataType::DOUBLE:
return std::to_string(value.data._double);
case Storage::DataType::BOOLEAN:
return value.data._bool ? "true" : "false";
case Storage::DataType::CHAR:
return std::string(1, value.data._char);
case Storage::DataType::STRING:
case Storage::DataType::HEXCODE:
return *(value.data._string);
case Storage::DataType::ARRAY:
result = "[";
for (const auto &element : *(value.data._array)) {
result += getPrintableValue(element) +
(&element != &value.data._array->back() ? ", " : "");
}
} else {
throw std::invalid_argument("No log message provided.");
return result + "]";
case Storage::DataType::OBJECT:
result = "{";
for (auto it = value.data._object->begin(); it != value.data._object->end();
++it) {
result += it->first + ": " + getPrintableValue(it->second) +
(std::next(it) != value.data._object->end() ? ", " : "");
}
return result + "}";
case Storage::DataType::_NULL:
return "null";
default:
throw std::invalid_argument("Unknown data type!");
}
}

Expand Down
Loading
Loading