mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-28 17:58:45 +00:00
part of type checker, type heck result type
This commit is contained in:
parent
48c9e200be
commit
17ff590048
13 changed files with 1022 additions and 321 deletions
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_)) {
|
||||
|
|
|
|||
|
|
@ -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_)) {
|
||||
|
|
|
|||
|
|
@ -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> &¶meters,
|
||||
Type(Identifier &&identifier, std::vector<TypeProxy> &¶meters,
|
||||
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> &¶meters, bool is_on_heap = false,
|
||||
Type(const Identifier &identifier, std::vector<TypeProxy> &¶meters,
|
||||
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> &¶meters,
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue