part of type checker, type heck result type

This commit is contained in:
ProgramSnail 2023-08-12 14:36:00 +03:00
parent 48c9e200be
commit 17ff590048
13 changed files with 1022 additions and 321 deletions

View file

@ -1,5 +1,6 @@
#pragma once
#include "utils.hpp"
#include <optional>
#include <string>
#include <utility>
@ -24,29 +25,55 @@ enum class Modifier {
IN_OR_REF_OR_OUT, // <-|<>|-> x
IN_OR_CONST_OR_OUT, // <-|--|-> x
IN_OR_REF_OR_CONST, // <-|<>|-- x
REF_OR_CONST_OR_OUT, //<>|--|-> x
REF_OR_CONST_OR_OUT, // <>|--|-> x
//
IN_OR_REF_OR_CONST_OR_OUT, // <-|<>|--|-> x
//
OPTIONAL, // x?
RESULT, // x!
//
IN_OR_REF_OR_CONST_OR_OUT, //<-|<>|--|-> x
OPTIONAL, // x?
RESULT, // x!
NONE,
};
namespace utils {
inline bool is_suffix_modifier(nodes::Modifier modifier) {
return modifier == nodes::Modifier::OPTIONAL ||
modifier == nodes::Modifier::RESULT;
}
} // namespace utils
class Node {
public:
Node() : undefined_(true) {}
Node(std::pair<size_t, size_t> start_position,
std::pair<size_t, size_t> end_position)
: start_position_(start_position), end_position_(end_position) {}
: undefined_(false), start_position_(start_position),
end_position_(end_position) {}
std::pair<size_t, size_t> get_start_position() const {
if (undefined_) {
error_handling::handle_general_error(
"Get start position from undefined node");
}
return start_position_;
}
std::pair<size_t, size_t> get_end_position() const { return end_position_; }
std::pair<size_t, size_t> get_end_position() const {
if (undefined_) {
error_handling::handle_general_error(
"Get end position from undefined node");
}
return end_position_;
}
protected:
std::pair<size_t, size_t> start_position_;
std::pair<size_t, size_t> end_position_;
bool undefined_ = false;
std::pair<size_t, size_t> start_position_ = {0, 0};
std::pair<size_t, size_t> end_position_ = {0, 0};
};
struct unit {};
@ -125,6 +152,11 @@ public:
return !(*this == other_identifier);
}
bool operator<(const Identifier &other_identifier) const {
return type_ < other_identifier.type_ || (type_ == other_identifier.type_ &&
value_ < other_identifier.value_);
}
private:
IdentifierType type_;
std::string value_;

View file

@ -529,11 +529,12 @@ private:
ExpressionProxy expression_;
};
class Expression {
class Expression : public Node {
public:
template <typename T>
Expression(T &&expression, bool is_scoped)
: expression_(std::forward<T>(expression)), is_scoped_(is_scoped) {}
Expression(Node node, T &&expression, bool is_scoped)
: Node(node), expression_(std::forward<T>(expression)),
is_scoped_(is_scoped) {}
template <typename T> std::optional<T *> get() {
if (std::holds_alternative<T>(expression_)) {

View file

@ -94,7 +94,7 @@ public:
: annotation_(annotation), type_(type),
before_modifier_(before_modifier),
after_modifier_(
builtin::builtin_to_modifier(type.get()->to_builtin())) {}
builtin::types::get_modifier(type.get()->to_builtin())) {}
//
@ -146,7 +146,7 @@ public:
}
auto type_after_modifier =
builtin::builtin_to_modifier(type.get()->to_builtin());
builtin::types::get_modifier(type.get()->to_builtin());
if (after_modifier_ != Modifier::NONE &&
after_modifier_ != type_after_modifier) {
@ -397,15 +397,16 @@ private:
std::optional<TypeProxy> type_;
};
class Statement {
class Statement : public Node {
public:
Statement(const Statement &) = default;
Statement(Statement &&) = default;
Statement &operator=(const Statement &) = default;
Statement &operator=(Statement &&) = default;
// Statement(const Statement &) = default;
// Statement(Statement &&) = default;
// Statement &operator=(const Statement &) = default;
// Statement &operator=(Statement &&) = default;
template <typename T>
explicit Statement(T &&statement) : expression_(std::forward<T>(statement)) {}
Statement(Node node, T &&statement)
: Node(node), expression_(std::forward<T>(statement)) {}
template <typename T> std::optional<T *> get() {
if (std::holds_alternative<T>(expression_)) {

View file

@ -2,6 +2,7 @@
#include "basic_nodes.hpp"
#include "builtin_types.hpp"
#include "utils.hpp"
#include <iterator>
#include <memory>
@ -33,30 +34,40 @@ private:
size_t id_;
};
// can't have both optional and result modifiers ??
class Type : public Node {
// // not needed ??
// class TypeNode : public Node {
// public:
// TypeNode(Node node, TypeProxy type) : Node(node), type_(type) {}
//
// Type *get() { return type_.get(); }
//
// const Type *get() const { return type_.get(); }
//
// private:
// TypeProxy type_;
// };
class Type {
public:
Type(Node node, Identifier &&identifier, bool is_on_heap = false,
Type(Identifier &&identifier, bool is_on_heap = false,
const std::optional<std::string> &annotation = std::nullopt)
: Node(node), name_(std::move(identifier)), is_on_heap_(is_on_heap),
: name_(std::move(identifier)), is_on_heap_(is_on_heap),
annotation_(annotation) {}
Type(Node node, const Identifier &identifier, bool is_on_heap = false,
Type(const Identifier &identifier, bool is_on_heap = false,
const std::optional<std::string> &annotation = std::nullopt)
: Node(node), name_(identifier), is_on_heap_(is_on_heap),
annotation_(annotation) {}
: name_(identifier), is_on_heap_(is_on_heap), annotation_(annotation) {}
Type(Node node, Identifier &&identifier, std::vector<TypeProxy> &&parameters,
Type(Identifier &&identifier, std::vector<TypeProxy> &&parameters,
bool is_on_heap = false,
const std::optional<std::string> &annotation = std::nullopt)
: Node(node), name_(std::move(identifier)),
parameters_(std::move(parameters)), is_on_heap_(is_on_heap),
annotation_(annotation) {}
: name_(std::move(identifier)), parameters_(std::move(parameters)),
is_on_heap_(is_on_heap), annotation_(annotation) {}
Type(Node node, const Identifier &identifier,
std::vector<TypeProxy> &&parameters, bool is_on_heap = false,
Type(const Identifier &identifier, std::vector<TypeProxy> &&parameters,
bool is_on_heap = false,
const std::optional<std::string> &annotation = std::nullopt)
: Node(node), name_(identifier), parameters_(std::move(parameters)),
: name_(identifier), parameters_(std::move(parameters)),
is_on_heap_(is_on_heap), annotation_(annotation) {}
//
@ -75,6 +86,8 @@ public:
return parameters_.at(id).get();
}
TypeProxy get_parameter_proxy(size_t id) const { return parameters_.at(id); }
//
bool is_on_heap() const { return is_on_heap_; }
@ -119,36 +132,14 @@ public:
//
bool operator<(const Type &other_type) const {
if (name_ != other_type.name_) {
return *name_.get() < *other_type.name_.get();
}
if (is_on_heap_ != other_type.is_on_heap_) {
return is_on_heap_ < other_type.is_on_heap_;
}
if (parameters_.size() != other_type.parameters_.size()) {
return parameters_.size() < other_type.parameters_.size();
}
for (size_t i = 0; i < parameters_.size(); ++i) {
if (*parameters_[i].get() != *other_type.parameters_[i].get()) {
return false;
}
}
return true;
}
bool operator==(const Type &other_type) const {
if (name_ != other_type.name_ || is_on_heap_ != other_type.is_on_heap_ ||
parameters_.size() != other_type.parameters_.size()) {
bool operator==(const Type &other) const {
if (name_ != other.name_ || is_on_heap_ != other.is_on_heap_ ||
parameters_.size() != other.parameters_.size()) {
return false;
}
for (size_t i = 0; i < parameters_.size(); ++i) {
if (*parameters_[i].get() != *other_type.parameters_[i].get()) {
if (*parameters_[i].get() != *other.parameters_[i].get()) {
return false;
}
}
@ -156,29 +147,52 @@ public:
return true;
}
bool operator!=(const Type &other_type) const {
return !(*this == other_type);
bool operator!=(const Type &other) const { return !(*this == other); }
//
bool operator<(const Type &other) const {
if (name_ != other.name_) {
return *name_.get() < *other.name_.get();
}
if (is_on_heap_ != other.is_on_heap_) {
return is_on_heap_ < other.is_on_heap_;
}
if (parameters_.size() != other.parameters_.size()) {
return parameters_.size() < other.parameters_.size();
}
for (size_t i = 0; i < parameters_.size(); ++i) {
if (*parameters_[i].get() != *other.parameters_[i].get()) {
return false;
}
}
return true;
}
bool operator>(const Type &other) const { return other < *this; }
bool operator<=(const Type &other) const { return !operator>(other); }
bool operator>=(const Type &other) const { return !operator<(other); }
// is parameters count check necessary ??
builtin::BuiltinType to_builtin() {
if (*name_.get() == builtin::TUPLE_IDENTIFIER && parameters_.size() > 0) {
return builtin::BuiltinType::TUPLE;
} else if (*name_.get() == builtin::VARIANT_IDENTIFIER &&
parameters_.size() > 0) {
return builtin::BuiltinType::VARIANT;
} else if (*name_.get() == builtin::ARRAY_IDENTIFIER &&
parameters_.size() == 1) {
return builtin::BuiltinType::ARRAY;
} else if (*name_.get() == builtin::OPTIONAL_IDENTIFIER &&
parameters_.size() == 1) {
return builtin::BuiltinType::OPTIONAL;
} else if (*name_.get() == builtin::RESULT_IDENTIFIER &&
parameters_.size() == 1) {
return builtin::BuiltinType::RESULT;
} else {
return builtin::BuiltinType::NONE;
builtin::types::Type to_builtin() {
auto builtin_type = builtin::types::to_type(*name_.get());
auto builtin_type_parameters_count =
builtin::types::get_parameters_count(builtin_type);
// for fixed parameter counts
if (builtin_type_parameters_count.has_value() &&
builtin_type_parameters_count.value() != parameters_.size()) {
return builtin::types::Type::NONE;
}
return builtin_type;
}
private:
@ -193,6 +207,34 @@ class TypeStorage {
friend TypeProxy;
public:
TypeProxy primitive_type(builtin::types::Type type, Node node = Node()) {
if (unit_type_id.has_value()) {
return TypeProxy(*this, unit_type_id.value());
} else {
unit_type_id = storage_.size();
return add_type(Type(Identifier(node, Identifier::SIMPLE_TYPE,
builtin::types::to_string(type))));
}
}
TypeProxy add_array_of(TypeProxy type, Node node = Node()) {
std::vector<nodes::TypeProxy> parameters;
parameters.push_back(type);
return add_type(Type(Identifier(node, Identifier::SIMPLE_TYPE,
builtin::types::ARRAY_IDENTIFIER),
std::move(parameters)));
}
nodes::TypeProxy add_container_of(std::vector<TypeProxy> &&parameters,
builtin::types::Type container,
Node node = Node()) {
return add_type(
nodes::Type(nodes::Identifier(node, nodes::Identifier::SIMPLE_TYPE,
builtin::types::to_string(container)),
std::move(parameters)));
}
TypeProxy add_type(const Type &type) {
storage_.push_back(type);
return TypeProxy(*this, storage_.size() - 1);
@ -209,89 +251,104 @@ private:
const Type *get_type(size_t id) const { return &storage_.at(id); }
private:
std::optional<size_t> unit_type_id;
std::vector<Type> storage_;
};
// class TupleType : public Node {
// public:
// TupleType(Node node,
// const std::vector<std::pair<std::optional<std::string>,
// TypeProxy>>
// &fields)
// : Node(node) {
// annotations_.reserve(fields.size());
// fields_.reserve(fields.size());
// for (auto &field : fields) {
// if (field.first.has_value()) {
// annotation_fields_[field.first.value()] = fields_.size();
// }
// annotations_.push_back(field.first);
// fields_.push_back(field.second);
// }
// }
//
// size_t size() const { return fields_.size(); }
//
// std::optional<std::string *> get_annotation(size_t id) {
// if (annotations_.at(id).has_value()) {
// return &annotations_[id].value();
// }
// return std::nullopt;
// }
//
// std::optional<const std::string *> get_annotation(size_t id) const {
// if (annotations_.at(id).has_value()) {
// return &annotations_[id].value();
// }
// return std::nullopt;
// }
//
// Type *get(size_t id) { return fields_.at(id).get(); }
//
// const Type *get(size_t id) const { return fields_.at(id).get(); }
//
// Type *get(const std::string &annotation) {
// return fields_.at(annotation_fields_.at(annotation)).get();
// }
//
// const Type *get(const std::string &annotation) const {
// return fields_.at(annotation_fields_.at(annotation)).get();
// }
//
// std::vector<std::string> get_all_annotations() {
// std::vector<std::string> annotations;
//
// annotations.reserve(annotation_fields_.size());
// for (auto &annotation_with_field : annotation_fields_) {
// annotations.push_back(annotation_with_field.first);
// }
//
// return annotations;
// }
//
// private:
// std::unordered_map<std::string, size_t> annotation_fields_;
// std::vector<TypeProxy> fields_;
// std::vector<std::optional<std::string>> annotations_;
// };
//
// class VariantType : public Node {
// public:
// VariantType(Node node, std::vector<TupleType> &&constructors_)
// : Node(node), constructors_(std::move(constructors_)) {}
//
// VariantType(Node node, const std::vector<TupleType> &constructors_)
// : Node(node), constructors_(constructors_) {}
//
// size_t size() const { return constructors_.size(); }
//
// TupleType *get(size_t id) { return &constructors_.at(id); }
//
// const TupleType *get(size_t id) const { return &constructors_.at(id); }
//
// private:
// // named constructors ??
// std::vector<TupleType> constructors_;
// };
class ModifiedTypeProxy {
public:
ModifiedTypeProxy(nodes::TypeProxy type,
nodes::Modifier modifier = nodes::Modifier::NONE)
: type_(type), modifier_(modifier) {}
//
nodes::Modifier get_modifier() const { return modifier_; }
void set_modifier(nodes::Modifier modifier) { modifier_ = modifier; }
//
nodes::Type *get_type() { return type_.get(); }
const nodes::Type *get_type() const { return type_.get(); }
const nodes::TypeProxy get_type_proxy() const { return type_; }
//
bool operator==(const ModifiedTypeProxy &other) const {
return *type_.get() == *other.type_.get() && modifier_ == other.modifier_;
}
bool operator!=(const ModifiedTypeProxy &other) const {
return !(*this == other);
}
//
bool operator<(const ModifiedTypeProxy &other) const {
return *type_.get() < *other.type_.get() ||
(*type_.get() == *other.type_.get() && modifier_ < other.modifier_);
}
bool operator>(const ModifiedTypeProxy &other) const { return other < *this; }
bool operator<=(const ModifiedTypeProxy &other) const {
return !operator>(other);
}
bool operator>=(const ModifiedTypeProxy &other) const {
return !operator<(other);
}
private:
nodes::TypeProxy type_;
nodes::Modifier modifier_;
};
class TypeCheckResult {
public:
// for invalid type
static TypeCheckResult construct_invalid_result() {
return TypeCheckResult();
}
explicit TypeCheckResult(std::optional<ModifiedTypeProxy> type)
: type_(type) {}
//
ModifiedTypeProxy &get() {
if (!type_.has_value()) {
error_handling::handle_general_error(
"Access to invalid type in TypeCheckResult");
}
return type_.value();
}
const ModifiedTypeProxy &get() const {
if (!type_.has_value()) {
error_handling::handle_general_error(
"Access to invalid type in TypeCheckResult");
}
return type_.value();
}
void set(ModifiedTypeProxy type) { type_ = type; }
//
bool is_invalid() const { return !type_.has_value(); }
private:
TypeCheckResult() = default;
private:
std::optional<ModifiedTypeProxy> type_;
};
} // namespace nodes