Skip to content

Commit

Permalink
Simplify Value interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
lluiscamino committed Jul 25, 2024
1 parent 0e576fb commit 21e5983
Show file tree
Hide file tree
Showing 17 changed files with 231 additions and 286 deletions.
32 changes: 22 additions & 10 deletions src/em/runtime/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../ast/exprs/VirtualSetExpression.h"
#include "../ast/stmts/ExpressionStatement.h"
#include "../utils/StringUtils.h"
#include "../utils/ValueUtils.h"
#include "../values/LiteralValue.h"
#include "../values/functions/NativeFunction.h"
#include "../values/functions/ProgramFunction.h"
Expand Down Expand Up @@ -75,25 +76,36 @@ ast::NodeVisitor::VisitorRetValue Interpreter::visit(

Interpreter::VisitorRetValue Interpreter::visit(
ast::exprs::OperatorExpression* expr) {
using namespace utils::values;
auto leftValue = expr->leftExpression()->accept(*this);
auto rightValue = expr->rightExpression()->accept(*this);
// todo: study type checking here: require(Set)
const auto& token = expr->operation();
switch (token.type()) {
case TokenType::EQUAL:
return leftValue->isEqualTo(rightValue);
return toValue(*leftValue == *rightValue);
case TokenType::NOT_EQUAL:
return leftValue->isDifferentTo(rightValue);
case TokenType::ELEMENT_OF:
return leftValue->isElementOf(rightValue);
return toValue(*leftValue != *rightValue);
case TokenType::ELEMENT_OF: {
const auto& rightSet = requireType<values::sets::Set>(rightValue, token);
return toValue(rightSet->hasElement(leftValue));
}
case TokenType::UNION:
return leftValue->unionOp(rightValue);
return requireType<values::sets::Set>(leftValue, token)
->unionOp(requireType<values::sets::Set>(rightValue, token));
case TokenType::INTERSECTION:
return leftValue->intersection(rightValue);
case TokenType::SUBSET:
return leftValue->isSubsetOf(rightValue);
case TokenType::NOT_SUBSET:
return leftValue->isNotSubsetOf(rightValue);
return requireType<values::sets::Set>(leftValue, token)
->intersection(requireType<values::sets::Set>(rightValue, token));
case TokenType::SUBSET: {
const auto& leftSet = requireType<values::sets::Set>(leftValue, token);
const auto& rightSet = requireType<values::sets::Set>(rightValue, token);
return toValue(leftSet->isSubsetOf(rightSet));
}
case TokenType::NOT_SUBSET: {
const auto& leftSet = requireType<values::sets::Set>(leftValue, token);
const auto& rightSet = requireType<values::sets::Set>(rightValue, token);
return toValue(!leftSet->isSubsetOf(rightSet));
}
default:
throw std::logic_error("Operation " + TokenTypeToString(token.type()) +
" is not supported for a operator expression at " +
Expand Down
41 changes: 20 additions & 21 deletions src/em/runtime/Interpreter.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>

Expand All @@ -10,38 +9,38 @@
#include "../ast/Program.h"

namespace em::runtime {
class Interpreter : public ast::NodeVisitor {
public:
explicit Interpreter(std::shared_ptr<std::ostream> outputStream);
class Interpreter : public ast::NodeVisitor {
public:
explicit Interpreter(std::shared_ptr<std::ostream> outputStream);

void execute(const std::unique_ptr<ast::Program>& program);
void execute(const std::unique_ptr<ast::Program>& program);

void addVariable(const Token& token, const VisitorRetValue& value);
void addVariable(const Token& token, const VisitorRetValue& value);

void visit(ast::Program* program) override;
void visit(ast::Program* program) override;

void visit(ast::stmts::ExpressionStatement* stmt) override;
void visit(ast::stmts::ExpressionStatement* stmt) override;

VisitorRetValue visit(ast::exprs::FunctionDeclaration* expr) override;
VisitorRetValue visit(ast::exprs::FunctionDeclaration* expr) override;

VisitorRetValue visit(ast::exprs::AssignmentExpression* expr) override;
VisitorRetValue visit(ast::exprs::AssignmentExpression* expr) override;

VisitorRetValue visit(ast::exprs::OperatorExpression* expr) override;
VisitorRetValue visit(ast::exprs::OperatorExpression* expr) override;

VisitorRetValue visit(ast::exprs::MaterialSetExpression* expr) override;
VisitorRetValue visit(ast::exprs::MaterialSetExpression* expr) override;

VisitorRetValue visit(ast::exprs::VirtualSetExpression* expr) override;
VisitorRetValue visit(ast::exprs::VirtualSetExpression* expr) override;

VisitorRetValue visit(ast::exprs::LiteralExpression* expr) override;
VisitorRetValue visit(ast::exprs::LiteralExpression* expr) override;

VisitorRetValue visit(ast::exprs::GroupExpression* expr) override;
VisitorRetValue visit(ast::exprs::GroupExpression* expr) override;

VisitorRetValue visit(ast::exprs::VariableExpression* expr) override;
VisitorRetValue visit(ast::exprs::VariableExpression* expr) override;

VisitorRetValue visit(ast::exprs::FunctionCall* expr) override;
VisitorRetValue visit(ast::exprs::FunctionCall* expr) override;

private:
std::unordered_map<std::wstring, VisitorRetValue> mVariables;
std::shared_ptr<std::ostream> mOutputStream;
};
private:
std::unordered_map<std::wstring, VisitorRetValue> mVariables;
std::shared_ptr<std::ostream> mOutputStream;
};
} // namespace em::runtime
12 changes: 12 additions & 0 deletions src/em/utils/ValueUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "ValueUtils.h"

namespace em::utils::values {
namespace {
const auto TRUE = std::make_shared<em::values::LiteralValue<bool>>(true);
const auto FALSE = std::make_shared<em::values::LiteralValue<bool>>(false);
} // namespace

const std::shared_ptr<em::values::LiteralValue<bool>>& toValue(bool val) {
return val ? TRUE : FALSE;
}
} // namespace em::utils::values
29 changes: 29 additions & 0 deletions src/em/utils/ValueUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include "../Token.h"
#include "../values/LiteralValue.h"
#include "../values/Value.h"

namespace em::utils::values {

const std::shared_ptr<em::values::LiteralValue<bool>>& toValue(bool val);

template <typename T>
std::shared_ptr<T> requireType(const std::shared_ptr<em::values::Value>& value,
const std::string& errorMessage) {
if (auto castedPtr = std::dynamic_pointer_cast<T>(value)) {
return castedPtr;
}
throw std::logic_error(errorMessage);
}

template <typename T>
std::shared_ptr<T> requireType(const std::shared_ptr<em::values::Value>& value,
const Token& token) {
return requireType<T>(value, "Operation " + TokenTypeToString(token.type()) +
" is not supported for operand " +
value->str() + " at " +
token.location().str());
}

} // namespace em::utils::values
66 changes: 24 additions & 42 deletions src/em/values/LiteralValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,36 @@
#include "sets/MaterialSetValue.h"

namespace em::values {
template <class T>
class LiteralValue : public Value {
public:
explicit LiteralValue(T value) : mValue(value) {}

bool operator==(const Value& other) override {
try {
auto& otherLiteralValue = dynamic_cast<const LiteralValue&>(other);
return mValue == otherLiteralValue.mValue;
} catch (const std::bad_cast&) {
return false;
}
template <class T>
class LiteralValue : public Value {
public:
explicit LiteralValue(T value) : mValue(value) {}

bool operator==(const Value& other) override {
try {
auto& otherLiteralValue = dynamic_cast<const LiteralValue&>(other);
return mValue == otherLiteralValue.mValue;
} catch (const std::bad_cast&) {
return false;
}
}

bool operator!=(const Value& other) override { return !(*this == other); }
bool operator!=(const Value& other) override { return !(*this == other); }

explicit operator bool() const override { return mValue; }
explicit operator bool() const { return mValue; }

[[nodiscard]] size_t hash() const override { return std::hash<T>()(mValue); }
[[nodiscard]] bool isTruthy() const { return static_cast<bool>(*this); }

[[nodiscard]] std::unique_ptr<Value> isSubsetOf(const std::shared_ptr<Value>& other) const override {
throw std::logic_error("LiteralValue::isSubsetOf: not supported");
}

[[nodiscard]] std::unique_ptr<Value> hasElement(const std::shared_ptr<Value>& other) const override {
throw std::logic_error("LiteralValue::hasElement: not supported");
}

[[nodiscard]] std::unique_ptr<Value> unionOp(const std::shared_ptr<Value>& other) const override {
throw std::logic_error("LiteralValue::unionOp: not supported");
}

[[nodiscard]] std::unique_ptr<Value> intersection(const std::shared_ptr<Value>& other) const override {
throw std::logic_error("LiteralValue::intersection: not supported");
}

[[nodiscard]] std::unique_ptr<Value> negation() const override {
return std::make_unique<LiteralValue<decltype(mValue)>>(!mValue);
}
[[nodiscard]] size_t hash() const override { return std::hash<T>()(mValue); }

[[nodiscard]] std::string str() const override {
if constexpr (std::is_same_v<decltype(mValue), bool>) {
return mValue ? "" : "";
}
return std::to_string(mValue);
[[nodiscard]] std::string str() const override {
if constexpr (std::is_same_v<decltype(mValue), bool>) {
return mValue ? "" : "";
}
return std::to_string(mValue);
}

private:
T mValue;
};
private:
T mValue;
};
} // namespace em::values
28 changes: 0 additions & 28 deletions src/em/values/Value.cpp

This file was deleted.

39 changes: 8 additions & 31 deletions src/em/values/Value.h
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
#pragma once
#include <memory>

namespace em::values {
class Value : public std::enable_shared_from_this<Value> {
public:
virtual ~Value() = default;
class Value {
public:
virtual ~Value() = default;

virtual bool operator==(const Value& other) = 0;
virtual bool operator==(const Value& other) = 0;

virtual bool operator!=(const Value& other) = 0;
virtual bool operator!=(const Value& other) = 0;

virtual explicit operator bool() const = 0;
[[nodiscard]] virtual size_t hash() const = 0;

[[nodiscard]] virtual size_t hash() const = 0;

[[nodiscard]] bool isTruthy() const;

[[nodiscard]] std::unique_ptr<Value> isEqualTo(const std::shared_ptr<Value>& other);

[[nodiscard]] std::unique_ptr<Value> isDifferentTo(const std::shared_ptr<Value>& other);

[[nodiscard]] virtual std::unique_ptr<Value> isSubsetOf(const std::shared_ptr<Value>& other) const = 0;

[[nodiscard]] virtual std::unique_ptr<Value> hasElement(const std::shared_ptr<Value>& other) const = 0;

[[nodiscard]] std::unique_ptr<Value> isElementOf(const std::shared_ptr<Value>& other);

[[nodiscard]] std::unique_ptr<Value> isNotSubsetOf(const std::shared_ptr<Value>& other) const;

[[nodiscard]] virtual std::unique_ptr<Value> negation() const = 0;

[[nodiscard]] virtual std::unique_ptr<Value> unionOp(const std::shared_ptr<Value>& other) const = 0;

[[nodiscard]] virtual std::unique_ptr<Value> intersection(const std::shared_ptr<Value>& other) const = 0;

[[nodiscard]] virtual std::string str() const = 0;
};
[[nodiscard]] virtual std::string str() const = 0;
};
} // namespace em::values
31 changes: 0 additions & 31 deletions src/em/values/functions/Function.cpp

This file was deleted.

23 changes: 6 additions & 17 deletions src/em/values/functions/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,11 @@

namespace em::values::functions {

class Function : public Value {
public:
[[nodiscard]] virtual ast::NodeVisitor::VisitorRetValue execute(
runtime::Interpreter& interpreter, const std::vector<std::shared_ptr<Value>>& arguments) = 0;

explicit operator bool() const override;

[[nodiscard]] std::unique_ptr<Value> isSubsetOf(const std::shared_ptr<Value>& other) const override;

[[nodiscard]] std::unique_ptr<Value> hasElement(const std::shared_ptr<Value>& other) const override;

[[nodiscard]] std::unique_ptr<Value> negation() const override;

[[nodiscard]] std::unique_ptr<Value> unionOp(const std::shared_ptr<Value>& other) const override;

[[nodiscard]] std::unique_ptr<Value> intersection(const std::shared_ptr<Value>& other) const override;
};
class Function : public Value {
public:
[[nodiscard]] virtual ast::NodeVisitor::VisitorRetValue execute(
runtime::Interpreter& interpreter,
const std::vector<std::shared_ptr<Value>>& arguments) = 0;
};

} // namespace em::values::functions
Loading

0 comments on commit 21e5983

Please sign in to comment.