Merge pull request 'v0.0.1' (#1) from dev into main

Reviewed-on: https://codeberg.org/ProgramSnail/lang-interpreter/pulls/1
This commit is contained in:
ProgramSnail 2023-05-22 19:05:06 +00:00
commit e3d1a758df
64 changed files with 14500 additions and 0 deletions

18
.clang_tidy Normal file
View file

@ -0,0 +1,18 @@
Checks: "*,
-abseil-*,
-altera-*,
-android-*,
-fuchsia-*,
-google-*,
-llvm*,
-modernize-use-trailing-return-type,
-zircon-*,
-readability-else-after-return,
-readability-static-accessed-through-instance,
-readability-avoid-const-params-in-decls,
-cppcoreguidelines-non-private-member-variables-in-classes,
-misc-non-private-member-variables-in-classes,
"
WarningsAsErrors: ''
HeaderFilterRegex: ''
FormatStyle: none

2
.clangd Normal file
View file

@ -0,0 +1,2 @@
CompileFlags:
Add: [-std=c++17]

6
.gitignore vendored
View file

@ -11,3 +11,9 @@ compile_commands.json
CTestTestfile.cmake
_deps
build
build_make
cmake-build-debug
.idea

6
.gitmodules vendored Normal file
View file

@ -0,0 +1,6 @@
[submodule "lang-parser"]
path = lang-parser
url = https://codeberg.org/ProgramSnail/lang-parser.git
[submodule "tree-sitter"]
path = tree-sitter
url = https://github.com/tree-sitter/tree-sitter.git

35
CMakeLists.txt Normal file
View file

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.10)
project(LangInterpreter)
set(CMAKE_CXX_STANDARD 17)
# find_package(Catch2 2 REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
include_directories(include
tree-sitter/lib/src
tree-sitter/lib/include)
# add_executable(interpreter_tests tests/tests.cpp)
# target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)
add_executable(lang_interpreter src/main.cpp
src/types.cpp
src/values.cpp
src/utils.cpp
src/global_info.cpp
src/typeclass_graph.cpp
src/visitor.cpp
src/build_visitor.cpp
src/print_visitor.cpp
src/find_symbols_visitor.cpp
src/link_symbols_visitor.cpp
src/type_check_visitor.cpp
src/typed_print_visitor.cpp
src/execute_visitor.cpp
lang-parser/src/parser.c
lang-parser/src/tree_sitter/parser.h
tree-sitter/lib/src/lib.c)

View file

@ -1,2 +1,9 @@
# lang-interpreter
Build steps:
- clone submodules
- cd lang-parser/ && tree-sitter generate
- mkdir build && cd build/ && cmake .. && make
**lang_interpreter** is interpreter

View file

@ -0,0 +1,73 @@
#pragma once
#include <string>
#include <vector>
#include <optional>
#include <unordered_map>
// for clangd
#include "utils.hpp"
namespace info {
class AbstractTypesContextManager {
public:
void EnterContext() {
contexts_.emplace_back();
}
void ExitContext() {
if (contexts_.empty()) {
// error
}
contexts_.pop_back();
}
void ExitFromAllContexts() {
contexts_.clear();
}
bool DefineType(const std::string& type, utils::IdType id) {
return contexts_.back().DefineType(type, id);
}
std::optional<utils::IdType> GetTypeId(const std::string& type) {
for (ssize_t i = contexts_.size() - 1; i >= 0; --i) {
auto maybe_type = contexts_[i].GetTypeId(type);
if (maybe_type.has_value()) {
return maybe_type.value();
}
}
return std::nullopt;
}
private:
class Context {
public:
bool DefineType(const std::string& type, utils::IdType id) {
if (types_.count(type) > 0) {
return false;
}
types_[type] = id;
return true;
}
std::optional<utils::IdType> GetTypeId(const std::string& type) {
auto type_iter = types_.find(type);
if (type_iter == types_.end()) {
return std::nullopt;
}
return type_iter->second;
}
private:
std::unordered_map<std::string, utils::IdType> types_;
};
std::vector<Context> contexts_;
};
} // namespace info

118
archived/symbols_info.hpp Normal file
View file

@ -0,0 +1,118 @@
#pragma once
#include "interpreter_tree.hpp"
#include <string>
#include <variant>
#include <vector>
#include <optional>
#include <unordered_map>
#include <memory>
// for clangd
#include "utils.hpp"
namespace interpreter {
class Node;
} // namespace interpreter
namespace info {
struct VariantTypeInfo;
struct TupleTypeInfo;
struct AliasTypeInfo;
struct TypeInfo;
struct TypeclassInfo;
enum class BuiltInTypeInfo {
StringT,
IntT,
FloatT,
UnitT,
};
struct TypeUsageInfo {
interpreter::tokens::TypeExpression* node;
TypeInfo* info = nullptr;
};
struct ParameterInfo {
std::string type;
std::vector<interpreter::tokens::TypeclassExpression*> typeclass_nodes;
std::vector<TypeclassInfo*> typeclass_types;
};
struct AbstractTypeInfo {
enum { Basic, Abstract } modifier;
ParameterInfo type;
};
struct AliasTypeInfo {
enum {Alias, Type, Let} modifier;
std::vector<std::string> parameters;
TypeUsageInfo value;
};
struct AnyTypeInfo {
ParameterInfo type;
std::vector<ParameterInfo> parameters;
interpreter::tokens::AnyType* value;
};
struct TypeInfo {
std::variant<AbstractTypeInfo, AliasTypeInfo, AnyTypeInfo> type;
};
struct ConstructorInfo {
std::string name;
size_t order;
utils::IdType type_id;
};
struct FunctionDeclarationInfo {
std::vector<ParameterInfo> parameters;
std::vector<interpreter::tokens::AnyType*> argument_type_nodes;
std::vector<AnyTypeInfo*> argument_types;
interpreter::tokens::FunctionDeclaration* node = nullptr;
};
struct FunctionDefinitionInfo {
std::vector<ParameterInfo> parameters;
std::vector<std::string> argument_names;
interpreter::tokens::FunctionDefinitionStatement* node = nullptr;
};
struct FunctionInfo {
size_t argument_count = 0;
std::optional<FunctionDeclarationInfo> declaration;
std::optional<FunctionDefinitionInfo> definition;
};
struct TypeclassInfo {
std::vector<ParameterInfo> parameters;
std::vector<FunctionDeclarationInfo> requirements;
};
struct ImportInfo {
std::string module_name;
std::vector<std::string> symbols;
};
struct NamespaceInfo {
enum Modifier { Const, Var };
std::unordered_map<std::string, utils::IdType> types;
std::unordered_map<std::string, utils::IdType> typeclasses;
std::unordered_map<std::string, utils::IdType> functions;
std::unordered_map<std::string, utils::IdType> constructors;
std::unordered_map<std::string, NamespaceInfo> namespaces;
std::unordered_map<std::string, std::vector<NamespaceInfo>> variable_namespaces;
std::optional<Modifier> modifier;
std::optional<std::string> variable;
std::string type_name;
TypeInfo* type_info = nullptr;
};
} // namespace info

235
archived/type_graph.hpp Normal file
View file

@ -0,0 +1,235 @@
////////////////////////////////////////////////////////////////////////////////////////
// Temporary frozen, TODO
////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <optional>
#include <string>
// for clangd
#include "utils.hpp"
namespace info {
// TODO: fix dfs, etc.
// TODO: optimize recalc
class TypeGraph {
public:
size_t AddVertex(const std::vector<std::string>& methods = {},
const std::vector<std::string>& typeclasses = {}) {
is_calculated_ = false;
Vertex vertex;
for (auto& method : methods) {
vertex.new_requirements.methods.insert(storage_.GetId(method));
}
for (auto& typeclass : typeclasses) {
vertex.new_requirements.typeclasses.insert(storage_.GetId(typeclass));
}
verticles_.push_back(vertex);
edges_.emplace_back();
back_edges_.emplace_back();
groups_.AddElement();
return verticles_.size() - 1;
}
std::vector<std::string> VertexMethods(size_t id) {
if (!is_calculated_) {
// error
return {};
}
size_t cluster_id = verticles_[id].cluster.value();
std::vector<std::string> methods;
methods.reserve(cluster_requirements_[cluster_id].methods.size());
for (auto& method : cluster_requirements_[cluster_id].methods) {
methods.push_back(std::move(storage_.GetValue(method)));
}
return methods;
}
std::vector<utils::IdType> VertexTypeclasses(size_t id) {
if (!is_calculated_) {
// error
return {};
}
size_t cluster_id = verticles_[id].cluster.value();
typeclasses_[id].methods[method.first].definition = method.second.definition;
std::vector<utils::IdType> typeclasses;
typeclasses.reserve(cluster_requirements_[cluster_id].typeclasses.size());
for (auto& typeclass : cluster_requirements_[cluster_id].typeclasses) {
typeclasses.push_back(typeclass);
}
return typeclasses;
}
void AddMethod(size_t id, const std::string& method) {
is_calculated_ = false;
verticles_[id].new_requirements.methods.insert(storage_.GetId(method));
}
void AddTypeclass(size_t id, utils::IdType typeclass) {
is_calculated_ = false;
verticles_[id].new_requirements.typeclasses.insert(typeclass);
}
void AddEdge(size_t from, size_t to) {
is_calculated_ = false;
edges_[from].push_back(to);
back_edges_[to].push_back(from);
}
void SetEqual(size_t u, size_t v) {
AddEdge(u, v);
AddEdge(v, u);
groups_.Unite(u, v);
}
void Calculate() {
if (is_calculated_) {
return;
}
auto clusters = FindClusters();
std::vector<RequirementsData> cluster_requirements(clusters.size());
std::vector<std::unordered_set<size_t>> cluster_edges(clusters.size());
for (size_t i = 0; i < clusters.size(); ++i) {
for (auto& vertex_id : clusters[i]) {
for (auto& method : verticles_[vertex_id].new_requirements.methods) {
cluster_requirements[i].methods.insert(method);
}
verticles_[vertex_id].new_requirements.methods.clear();
for (auto& typeclass : verticles_[vertex_id].new_requirements.typeclasses) {
cluster_requirements[i].typeclasses.insert(typeclass);
}
verticles_[vertex_id].new_requirements.methods.clear();
for (auto& edge : edges_[vertex_id]) {
cluster_edges[i].insert(edge);
}
}
}
// TODO: check, that clusters are top sorted
for (size_t i = 0; i < clusters.size(); ++i) {
for (auto& edge : cluster_edges[i]) {
for (auto& method : cluster_requirements[edge].methods) {
cluster_requirements[i].methods.insert(method);
}
for (auto& typeclass : cluster_requirements[edge].typeclasses) {
cluster_requirements[i].typeclasses.insert(typeclass);
}
}
}
for (size_t i = 0; i < clusters.size(); ++i) {
for (auto& vertex_id : clusters[i]) {
verticles_[vertex_id].cluster = i;
}
}
clusters_ = std::move(clusters);
cluster_requirements_ = std::move(cluster_requirements);
is_calculated_ = true;
}
private:
struct RequirementsData {
std::unordered_set<utils::IdType> methods;
std::unordered_set<utils::IdType> typeclasses;
};
struct Vertex {
RequirementsData new_requirements;
std::optional<size_t> cluster;
};
std::vector<std::vector<size_t>> FindClusters() {
std::vector<std::vector<size_t>> clusters;
auto sorted_verticles = BackTopSort();
std::vector<size_t> marks(sorted_verticles.size(), 0);
for (size_t i = 0; i < sorted_verticles.size(); ++i) {
if (marks[i] == 0) {
clusters.emplace_back();
BackVisitDfs(i, clusters[i], marks, back_edges_, clusters.size());
}
}
return clusters;
}
void BackVisitDfs(size_t id,
std::vector<size_t>& verticles,
std::vector<size_t>& marks,
const std::vector<std::vector<size_t>>& edges,
size_t mark) {
if (marks[id] != 0) {
return;
}
marks[id] = mark;
for (size_t i = 0; i < edges[id].size(); ++i) {
BackVisitDfs(id, verticles, marks, edges, mark);
}
verticles.push_back(id);
}
std::vector<size_t> BackTopSort() {
std::vector<size_t> sorted_verticles;
std::vector<size_t> marks(verticles_.size(), 0);
for (size_t i = 0; i < marks.size(); ++i) {
BackVisitDfs(i, sorted_verticles, marks, edges_, 1);
}
return sorted_verticles;
}
private:
std::vector<std::vector<size_t>> edges_;
std::vector<std::vector<size_t>> back_edges_;
std::vector<Vertex> verticles_;
std::vector<std::vector<size_t>> clusters_;
std::vector<RequirementsData> cluster_requirements_;
utils::Storage<std::string> storage_;
utils::GroupsManager groups_;
bool is_calculated_ = false;
};
} // namespace info

151
include/build_visitor.hpp Normal file
View file

@ -0,0 +1,151 @@
#pragma once
// for clangd
#include "interpreter_tree.hpp"
#include "visitor.hpp"
#include "parse_tree.hpp"
namespace interpreter {
class BuildVisitor : public Visitor {
public:
explicit BuildVisitor(const parser::ParseTree& parse_tree) : parse_tree_(parse_tree) {}
void VisitSourceFile(SourceFile* source_file) override {
current_node_ = parse_tree_.GetRoot();
Visit(source_file);
}
private:
// Sources -----------------
void Visit(SourceFile* node) override;
// Namespaces, partitions -----------------
void Visit(NamespaceSources* node) override;
void Visit(Namespace* node) override;
// Definitions -----------------
void Visit(ImportStatement* node) override;
void Visit(AliasDefinitionStatement* node) override;
void Visit(VariableDefinitionStatement* node) override;
void Visit(FunctionDeclaration* node) override;
void Visit(FunctionDefinitionStatement* node) override;
void Visit(TypeDefinitionStatement* node) override;
void Visit(AbstractTypeDefinitionStatement* node) override;
void Visit(TypeclassDefinitionStatement* node) override;
void Visit(PartitionStatement* node) override;
void Visit(NamespaceStatement& node) override; // variant
void Visit(SourceStatement& node) override; // variant
// Definition parts
void Visit(FunctionDefinition* node) override;
void Visit(TypeDefinition* node) override;
void Visit(AnyAnnotatedType* node) override;
// Flow control -----------------
void Visit(TypeConstructorPatternParameter* node) override;
void Visit(TypeConstructorPattern* node) override;
void Visit(MatchCase* node) override;
void Visit(Match* node) override;
void Visit(Condition* node) override;
void Visit(DoWhileLoop* node) override;
void Visit(WhileLoop* node) override;
void Visit(ForLoop* node) override;
void Visit(LoopLoop* node) override;
void Visit(Pattern& node) override; // variant
void Visit(FlowControl& node) override; // variant
// Statements, expressions, blocks, etc. -----------------
void Visit(BlockStatement& node) override; // variant
void Visit(Block* node) override;
void Visit(SubExpressionToken& node) override; // variant
void Visit(SubExpression& node) override; // variant
void Visit(PrefixedExpression& node) override; // variant
void Visit(Expression& node) override; // variant
void Visit(SuperExpression& node) override; // variant
void Visit(ScopedStatement* node) override;
// Operators
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;
// Other expressions
void Visit(FunctionCallExpression* node) override;
void Visit(TupleExpression* node) override;
void Visit(VariantExpression* node) override;
void Visit(ReturnExpression* node) override;
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum
// Name
void Visit(PartitionName* node) override;
void Visit(NameExpression* node) override;
void Visit(TupleName* node) override;
void Visit(VariantName* node) override;
void Visit(AnnotatedName* node) override;
void Visit(AnyName& node) override; // variant
// Type, typeclass, etc. -----------------
// Type
void Visit(FunctionType* node) override;
void Visit(TupleType* node) override;
void Visit(VariantType* node) override;
void Visit(TypeExpression* node) override;
void Visit(AnyType& node) override; // variant
void Visit(ExtendedScopedAnyType* node) override;
// Typeclass
void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
void Visit(ParametrizedType* node) override;
// Identifiers, constants, etc. -----------------
// // void Visit(AnyIdentifier* node) override; // std::string
void Visit(FloatNumberLiteral* node) override;
void Visit(NumberLiteral* node) override;
void Visit(StringLiteral* node) override;
void Visit(CharLiteral* node) override;
void Visit(UnitLiteral* node) override;
void Visit(BoolLiteral* node) override;
void Visit(Literal& node) override; // variant
//
void VisitBinaryOperatorExpression(FunctionCallExpression* node);
private:
const parser::ParseTree& parse_tree_;
parser::ParseTree::Node current_node_;
};
} // namespace interpreter

View file

@ -0,0 +1,25 @@
#pragma once
#include <string>
#include <iostream>
// for clangd
namespace info::builtin {
template<typename T>
inline void Print(const T& value) { // only for strings ??
std::cout << "\x1b[1;32mOutput:\x1b[0m ";
std::cout << value;
std::cout << '\n';
}
template<typename T>
inline T Read() {
T value;
std::cout << "\x1b[1;32mInput:\x1b[0m ";
std::cin >> value;
return value;
}
} // namespace info

275
include/contexts.hpp Normal file
View file

@ -0,0 +1,275 @@
#pragma once
#include <string>
#include <utility>
#include <vector>
#include <optional>
#include <unordered_map>
// for clangd
#include "error_handling.hpp"
#include "utils.hpp"
namespace info {
template<typename Value, typename ValueManager>
class ContextManager {
public:
ContextManager() {
contexts_.emplace_back(true); // no difference ??
}
size_t ContextCount() {
return contexts_.size();
}
template<typename T>
utils::IdType AddValue(const T& value, utils::ValueType value_type) {
return value_manager_.AddValue(value, value_type);
}
utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) {
return value_manager_.AddAnyValue(std::move(value), value_type);
}
template<typename T>
std::optional<T*> GetValue(utils::IdType value_id) {
return value_manager_.template GetValue<T>(value_id);
}
Value* GetAnyValue(utils::IdType value_id) {
return value_manager_.GetAnyValue(value_id);
}
bool AddValueRequirement(utils::IdType type, utils::IdType requrement) {
return value_manager_.AddValueRequirement(type, requrement);
}
bool EqualValues(utils::IdType first_type, utils::IdType second_type) {
return value_manager_.EqualValues(first_type, second_type);
}
utils::ValueType GetValueType(utils::IdType value_id) {
return value_manager_.GetValueType(value_id);
}
void ModifiyValue(utils::IdType value_id, utils::ValueType new_value_type) {
value_manager_.SetValueType(value_id, new_value_type);
}
utils::IdType ToModifiedValue(utils::IdType value_id, utils::ValueType new_value_type) {
Value value = *GetAnyValue(value_id);
return AddAnyValue(std::move(value), new_value_type);
}
utils::IdType ToModifiedValueCopy(utils::IdType value_id,
utils::ValueType new_value_type) {
Value* value = GetAnyValue(value_id);
return value->DeepCopy(&value_manager_, new_value_type);
}
// make deep copy if not temporary
utils::IdType ToTemporaryValue(utils::IdType value_id) {
if (GetValueType(value_id) == utils::ValueType::Tmp) {
return value_id;
}
return ToModifiedValueCopy(value_id, utils::ValueType::Tmp);
}
ValueManager* GetValueManager() {
return &value_manager_;
}
void EnterContext(bool is_hiding_previous = false) {
contexts_.emplace_back(is_hiding_previous);
}
void ExitContext() {
if (contexts_.empty()) {
error_handling::HandleInternalError("contexts_ is empty",
"ContextManager.ExitContext",
std::nullopt);
}
contexts_.pop_back();
}
void ChangeHidingOfCurrentContextTo(bool is_hiding_previous) {
contexts_.back().ChangeHidingTo(is_hiding_previous);
}
bool DefineVariable(const std::string& name, utils::IdType value_id) {
return contexts_.back().DefineVariable(name, value_id);
}
bool DefineLocalType(const std::string& name, utils::IdType type_id) {
return contexts_.back().DefineLocalType(name, type_id);
}
bool AssignVariable(const std::string& name, utils::IdType value_id) {
for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) {
if (contexts_[i].AssignVariable(name, value_id)) {
return true;
}
if (contexts_[i].IsHidingPrevious()) {
break;
}
}
return false;
}
bool AssignLocalType(const std::string& name, utils::IdType type_id) {
for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) {
if (contexts_[i].AssignLocalType(name, type_id)) {
return true;
}
if (contexts_[i].IsHidingPrevious()) {
break;
}
}
return false;
}
bool RemoveVariable(const std::string& name) {
for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) {
if (contexts_[i].RemoveVariable(name)) {
return true;
}
if (contexts_[i].IsHidingPrevious()) {
break;
}
}
return false;
}
void EnterVariableContext(const std::string& name,
utils::IdType value_id,
bool is_hiding_previous = false) {
EnterContext(is_hiding_previous);
DefineVariable(name, value_id);
}
std::optional<utils::IdType> FindVariable(const std::string& name) {
for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) {
auto maybe_variable = contexts_[i].FindVariable(name);
if (maybe_variable.has_value()) {
return maybe_variable.value();
}
if (contexts_[i].IsHidingPrevious()) {
break;
}
}
return std::nullopt;
}
std::optional<utils::IdType> FindLocalType(const std::string& name) {
for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) {
auto maybe_type = contexts_[i].FindLocalType(name);
if (maybe_type.has_value()) {
return maybe_type.value();
}
if (contexts_[i].IsHidingPrevious()) {
break;
}
}
return std::nullopt;
}
private:
class Context {
public:
explicit Context(bool is_hiding_previous) : is_hiding_previous_(is_hiding_previous) {}
bool DefineVariable(const std::string& name, utils::IdType value_id) {
if (name == "_") { // placeholder
return true;
}
if (variables_.count(name) != 0) {
return false;
}
variables_[name] = value_id;
return true;
}
bool DefineLocalType(const std::string& name, utils::IdType type_id) {
if (local_types_.count(name) != 0) {
return false;
}
local_types_[name] = type_id;
return true;
}
bool AssignVariable(const std::string& name, utils::IdType value_id) {
if (name == "_") { // placeholder
return true;
}
auto variable_iter = variables_.find(name);
if (variable_iter == variables_.end()) {
return false;
}
variable_iter->second = value_id;
return true;
}
bool AssignLocalType(const std::string& name, utils::IdType type_id) {
auto local_type_iter = local_types_.find(name);
if (local_type_iter == local_types_.end()) {
return false;
}
local_type_iter->second = type_id;
return true;
}
bool RemoveVariable(const std::string& name) {
return variables_.erase(name);
}
std::optional<utils::IdType> FindVariable(const std::string& name) {
auto variable_iter = variables_.find(name);
if (variable_iter == variables_.end()) {
return std::nullopt;
}
return variable_iter->second;
}
std::optional<utils::IdType> FindLocalType(const std::string& name) {
auto local_abstract_type_iter = local_types_.find(name);
if (local_abstract_type_iter == local_types_.end()) {
return std::nullopt;
}
return local_abstract_type_iter->second;
}
bool IsHidingPrevious() {
return is_hiding_previous_;
}
void ChangeHidingTo(bool is_hiding_previous) {
is_hiding_previous_ = is_hiding_previous;
}
private:
std::unordered_map<std::string, utils::IdType> variables_;
std::unordered_map<std::string, utils::IdType> local_types_;
bool is_hiding_previous_ = false;
};
std::vector<Context> contexts_;
ValueManager value_manager_;
};
} // namespace info

114
include/definitions.hpp Normal file
View file

@ -0,0 +1,114 @@
#pragma once
#include <string>
#include <variant>
#include <vector>
#include <optional>
#include <unordered_map>
#include <memory>
// for clangd
#include "interpreter_tree.hpp"
#include "utils.hpp"
namespace interpreter {
class Node;
} // namespace interpreter
namespace info::definition {
struct Namespace;
struct TypeUsage {
interpreter::tokens::TypeExpression* node;
};
struct Parameter {
std::string type;
std::vector<interpreter::tokens::ParametrizedTypeclass*> typeclass_nodes;
interpreter::tokens::AnyAnnotatedType* node = nullptr;
};
struct AbstractType {
utils::AbstractTypeModifier modifier;
Parameter type;
interpreter::tokens::AbstractTypeDefinitionStatement* node = nullptr;
};
struct AliasType {
utils::AliasModifier modifier;
std::vector<std::string> parameters;
TypeUsage value;
interpreter::tokens::AliasDefinitionStatement* node = nullptr;
};
struct AnyType {
Parameter type;
std::vector<Parameter> parameters;
utils::ClassModifier modifier;
interpreter::tokens::TypeDefinitionStatement* node = nullptr;
utils::IdType parent_namespace = 0;
};
struct Type {
std::variant<AliasType, AnyType> type;
};
struct Constructor {
std::string name;
std::optional<size_t> order; // no order for tuple types
utils::IdType type_id = 0;
std::optional<interpreter::tokens::TupleType*> constructor_tuple_node;
};
struct FunctionDeclaration {
std::vector<Parameter> parameters;
std::vector<interpreter::tokens::AnyType*> argument_types;
interpreter::tokens::FunctionDeclaration* node = nullptr;
};
struct FunctionDefinition {
std::vector<std::string> argument_names;
interpreter::tokens::FunctionDefinitionStatement* node = nullptr;
};
struct Function {
size_t argument_count = 0;
std::optional<FunctionDeclaration> declaration;
std::optional<FunctionDefinition> definition;
};
struct Typeclass {
std::vector<Parameter> parameters;
interpreter::tokens::TypeclassDefinitionStatement* node;
utils::IdType parent_namespace = 0;
utils::IdType graph_id_ = 0; // TODO: make safe??
};
struct Import {
std::string module_name;
std::vector<std::string> symbols; // size == 0 => all symbols imported
};
struct Namespace {
std::unordered_map<std::string, utils::IdType> types;
std::unordered_map<std::string, utils::IdType> functions;
std::unordered_map<std::string, utils::IdType> constructors;
std::unordered_map<std::string, utils::IdType> namespaces;
std::unordered_map<std::string, utils::IdType> var_namespaces;
std::unordered_map<std::string, utils::IdType> const_namespaces;
utils::IdType parent_namespace = 0;
utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static;
std::string type_name;
// all nodes have same info
std::optional<interpreter::tokens::Namespace*> any_node;
};
} // namespace info::definition

View file

@ -0,0 +1,78 @@
#pragma once
#include "interpreter_tree.hpp"
#include <iostream>
#include <pthread.h>
namespace error_handling {
inline void PrintPosition(std::ostream& out,
std::pair<size_t, size_t> start_position,
std::pair<size_t, size_t> end_position) {
out << '['
<< start_position.first + 1
<< ", "
<< start_position.second + 1
<< "] - ["
<< end_position.first + 1
<< ", "
<< end_position.second + 1
<< ']';
}
inline void HandleParsingError(const std::string& message,
std::pair<size_t, size_t> start_position,
std::pair<size_t, size_t> end_position) {
std::cerr << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at ";
PrintPosition(std::cerr, start_position, end_position);
std::cerr << ".\n";
exit(1);
}
inline void HandleGeneralError(const std::string& message) {
std::cerr << "\x1b[1;31mGeneral Error:\x1b[0m " << message << ".\n";
exit(1);
}
inline void HandleInternalError(const std::string& message,
const std::string& place,
std::optional<const interpreter::tokens::BaseNode*> node) {
std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at " << place;
if (node.has_value()) {
std::cerr << ", at ";
PrintPosition(std::cerr, node.value()->start_position, node.value()->end_position);
}
std::cerr << ".\n";
exit(1);
}
inline void HandleTypecheckError(const std::string& message,
const interpreter::tokens::BaseNode& node) {
std::cerr << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at ";
PrintPosition(std::cerr, node.start_position, node.end_position);
std::cerr << ".\n";
exit(1);
}
inline void HandleRuntimeError(const std::string& message,
const interpreter::tokens::BaseNode& node) {
std::cerr << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at ";
PrintPosition(std::cerr, node.start_position, node.end_position);
std::cerr << ".\n";
exit(1);
}
inline void HandleNamesError(const std::string& message,
const interpreter::tokens::BaseNode& node) {
std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at ";
PrintPosition(std::cerr, node.start_position, node.end_position);
std::cerr << ".\n";
exit(1);
}
template<typename T>
inline void DebugPrint(const T& value) {
std::cerr << "\x1b[1;33mDebug:\x1b[0m " << value << '\n';
}
} // namespace error_handling

193
include/execute_visitor.hpp Normal file
View file

@ -0,0 +1,193 @@
#pragma once
#include <ostream>
// for clangd
#include "contexts.hpp"
#include "global_info.hpp"
#include "interpreter_tree.hpp"
#include "types.hpp"
#include "utils.hpp"
#include "values.hpp"
#include "visitor.hpp"
#include "error_handling.hpp"
namespace interpreter {
class ExecuteVisitor : public Visitor {
public:
explicit ExecuteVisitor(info::GlobalInfo& global_info,
info::ContextManager<info::type::Type, info::type::TypeManager>& type_context_manager,
info::ContextManager<info::value::Value, info::value::ValueManager>& context_manager)
: global_info_(global_info),
typeclass_graph_(*global_info.GetTypeclassGraph()),
type_context_manager_(type_context_manager),
context_manager_(context_manager) {}
void VisitSourceFile(SourceFile* node) override {
error_handling::HandleInternalError("VisitSourceFile unavailible",
"ExecuteVisitor.VisitSourceFile",
&node->base);
};
void ExecutePartition(interpreter::tokens::PartitionStatement* partition) {
Visit(partition);
}
private:
// Sources -----------------
void Visit(SourceFile* node) override;
// Namespaces, partitions -----------------
void Visit(NamespaceSources* node) override;
void Visit(Namespace* node) override;
// Definitions -----------------
void Visit(ImportStatement* node) override;
void Visit(AliasDefinitionStatement* node) override;
void Visit(VariableDefinitionStatement* node) override;
void Visit(FunctionDeclaration* node) override;
void Visit(FunctionDefinitionStatement* node) override;
void Visit(TypeDefinitionStatement* node) override;
void Visit(AbstractTypeDefinitionStatement* node) override;
void Visit(TypeclassDefinitionStatement* node) override;
void Visit(PartitionStatement* node) override;
// Definition parts
// // void Visit(FunctionDefinition* node) override;
// // void Visit(TypeDefinition* node) override;
// // void Visit(AnyAnnotatedType* node) override;
// Flow control -----------------
void Visit(TypeConstructorPatternParameter* node) override;
void Visit(TypeConstructorPattern* node) override;
void Visit(MatchCase* node) override;
void Visit(Match* node) override;
void Visit(Condition* node) override;
void Visit(DoWhileLoop* node) override;
void Visit(WhileLoop* node) override;
void Visit(ForLoop* node) override;
void Visit(LoopLoop* node) override;
// Statements, expressions, blocks, etc. -----------------
void Visit(Block* node) override;
void Visit(ScopedStatement* node) override;
// Operators
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;
// Simple Expressions
void Visit(FunctionCallExpression* node) override;
void Visit(TupleExpression* node) override;
void Visit(VariantExpression* node) override;
void Visit(ReturnExpression* node) override;
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum
// Name
// // void Visit(PartitionName* node) override;
void Visit(NameExpression* node) override;
void Visit(TupleName* node) override;
void Visit(VariantName* node) override;
void Visit(AnnotatedName* node) override;
// Type, typeclass, etc. -----------------
// Type
void Visit(FunctionType* node) override;
void Visit(TupleType* node) override;
void Visit(VariantType* node) override;
void Visit(TypeExpression* node) override;
void Visit(ExtendedScopedAnyType* node) override;
// Typeclass
void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
void Visit(ParametrizedType* node) override;
// Identifiers, constants, etc. -----------------
// // void Visit(std::string* node) override; // std::string
void Visit(FloatNumberLiteral* node) override;
void Visit(NumberLiteral* node) override;
void Visit(StringLiteral* node) override;
void Visit(CharLiteral* node) override;
void Visit(UnitLiteral* node) override;
void Visit(BoolLiteral* node) override;
bool HandleCondition(Expression& condition, const BaseNode& base_node);
void CollectTypeContext(const ParametrizedType& type);
void CheckPattern(Pattern& node, const BaseNode& base_node);
template<typename T>
T* ExtractValue(utils::IdType value, const BaseNode& base_node) {
std::optional<T*> maybe_value_info = context_manager_.GetValue<T>(value);
if (!maybe_value_info.has_value()) {
error_handling::HandleRuntimeError("Value has value class that is different from exprected one", base_node);
}
return maybe_value_info.value();
}
template<typename T>
T* ExtractInternalValue(utils::IdType value, const BaseNode& base_node) {
info::value::InternalValue* value_info = ExtractValue<info::value::InternalValue>(value, base_node);
std::optional<T*> maybe_internal_value_info = value_info->GetValue<T>();
if (!maybe_internal_value_info.has_value()) {
error_handling::HandleRuntimeError("Value has internal value class that is different from exprected one", base_node);
}
return maybe_internal_value_info.value();
}
utils::IdType GraphIdByTypeId(utils::IdType type_id) {
auto maybe_any_type = global_info_.GetTypeInfo<info::definition::AnyType>(type_id);
if (!maybe_any_type.has_value()) {
error_handling::HandleInternalError("Only AnyType implemented",
"ExecuteVisitor.ExtractInternalValue",
std::nullopt);
}
return maybe_any_type.value()->node->definition->type->graph_id_;
}
//
bool HandleBuiltinFunctionCall(FunctionCallExpression* node);
bool HandleBuiltinTypeFunctionCall(FunctionCallExpression* node,
info::type::InternalType type);
private:
info::GlobalInfo& global_info_;
info::TypeclassGraph& typeclass_graph_;
info::ContextManager<info::type::Type, info::type::TypeManager>& type_context_manager_;
info::ContextManager<info::value::Value, info::value::ValueManager>& context_manager_;
// local types store types graph ids
utils::IdType current_value_;
std::optional<LoopControlExpression> active_loop_control_expression_;
std::optional<utils::IsConstModifier> is_const_definition_;
bool case_matched_;
};
} // namespace interpreter

View file

@ -0,0 +1,127 @@
#pragma once
#include <ostream>
#include <any>
// for clangd
#include "interpreter_tree.hpp"
#include "visitor.hpp"
#include "global_info.hpp"
namespace interpreter {
class FindSymbolsVisitor : public Visitor {
public:
explicit FindSymbolsVisitor(info::GlobalInfo& global_info)
: namespace_visitor_(global_info.CreateVisitor()) {}
private:
// Sources -----------------
// void Visit(SourceFile* node) override; // default
// Namespaces, partitions -----------------
// void Visit(NamespaceSources* node) override; // default
void Visit(Namespace* node) override;
// Definitions -----------------
void Visit(ImportStatement* node) override;
void Visit(AliasDefinitionStatement* node) override;
// // void Visit(VariableDefinitionStatement* node) override;
void Visit(FunctionDeclaration* node) override;
void Visit(FunctionDefinitionStatement* node) override;
void Visit(TypeDefinitionStatement* node) override;
void Visit(AbstractTypeDefinitionStatement* node) override;
void Visit(TypeclassDefinitionStatement* node) override;
void Visit(PartitionStatement* node) override;
// Definition parts
// // void Visit(FunctionDefinition* node) override;
// // void Visit(TypeDefinition* node) override;
void Visit(AnyAnnotatedType* node) override;
// Flow control -----------------
// // void Visit(TypeConstructorPatternParameter* node) override;
// // void Visit(TypeConstructorPattern* node) override;
// // void Visit(MatchCase* node) override;
// // void Visit(Match* node) override;
// // void Visit(Condition* node) override;
// // void Visit(DoWhileLoop* node) override;
// // void Visit(WhileLoop* node) override;
// // void Visit(ForLoop* node) override;
// // void Visit(LoopLoop* node) override;
// Statements, expressions, blocks, etc. -----------------
// // void Visit(Block* node) override;
// //
// // void Visit(ScopedStatement* node) override;
// Operators
// // void Visit(ReferenceExpression* node) override;
// // void Visit(AccessExpression* node) override;
// Simple Expressions
// // void Visit(FunctionCallExpression* node) override;
// // void Visit(TupleExpression* node) override;
// // void Visit(VariantExpression* node) override;
// // void Visit(ReturnExpression* node) override;
// // void Visit(TypeConstructorParameter* node) override;
// // void Visit(TypeConstructor* node) override;
// // void Visit(LambdaFunction* node) override;
// // void Visit(ArrayExpression* node) override;
// // void Visit(LoopControlExpression& node) override; // enum
// Name
// // void Visit(PartitionName* node) override;
// // void Visit(NameExpression* node) override;
// // void Visit(TupleName* node) override;
// // void Visit(VariantName* node) override;
// // void Visit(AnnotatedName* node) override;
// Type, typeclass, etc. -----------------
// Type
// // void Visit(FunctionType* node) override;
// // void Visit(TupleType* node) override;
// // void Visit(VariantType* node) override;
// // void Visit(TypeExpression* node) override;
// // void Visit(ExtendedScopedAnyType* node) override;
// Typeclass
// // void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
// // void Visit(ParametrizedType* node) override;
// Identifiers, constants, etc. -----------------
// // void Visit(std::string* node) override; // std::string
// // void Visit(FloatNumberLiteral* node) override;
// // void Visit(NumberLiteral* node) override;
// // void Visit(StringLiteral* node) override;
// // void Visit(CharLiteral* node) override;
// // void Visit(UnitLiteral* node) override;
// // void Visit(BoolLiteral* node) override;
private:
info::GlobalInfo::NamespaceVisitor namespace_visitor_;
std::any current_info_;
};
} // namespace interpreter

401
include/global_info.hpp Normal file
View file

@ -0,0 +1,401 @@
#pragma once
#include <string>
#include <functional>
#include <unordered_map>
#include <unordered_set>
// for clangd
#include "definitions.hpp"
#include "interpreter_tree.hpp"
#include "typeclass_graph.hpp"
#include "utils.hpp"
namespace info {
// TODO: add classes / structs and functions module interface
class GlobalInfo {
friend class NamespaceVisitor;
public:
GlobalInfo() {
namespaces_.emplace_back(); // global namespace
}
struct PartitionInfo {
std::vector<std::string> path;
interpreter::tokens::PartitionStatement* node = nullptr;
};
class NamespaceVisitor {
friend GlobalInfo;
NamespaceVisitor() = delete;
public:
struct Path {
std::vector<std::optional<utils::IdType>> path_types;
definition::Namespace* result;
};
void AddImport(definition::Import&& import_info, const std::optional<std::string>& name = std::nullopt);
void AddEnterNamespace(const std::string& name,
utils::ClassInternalsModifier modifier,
std::optional<interpreter::tokens::Namespace*> node,
const interpreter::tokens::BaseNode& base_node);
void EnterNamespace(const std::string& name,
utils::ClassInternalsModifier modifier);
void ExitNamespace();
void ToGlobalNamespace();
utils::IdType AddFunctionDeclaration(const std::string& name,
definition::FunctionDeclaration&& function_declaration_info,
const interpreter::tokens::BaseNode& base_node);
utils::IdType AddFunctionDefinition(const std::string& name,
definition::FunctionDefinition&& function_definition_info,
const interpreter::tokens::BaseNode& base_node);
utils::IdType AddType(const std::string& type,
definition::Type&& type_info,
const interpreter::tokens::BaseNode& base_node);
utils::IdType AddAbstractType(const std::string& abstract_type,
definition::AbstractType&& abstract_type_info,
const interpreter::tokens::BaseNode& base_node);
utils::IdType AddTypeclass(const std::string& typeclass,
definition::Typeclass&& typeclass_info,
const interpreter::tokens::BaseNode& base_node);
utils::IdType AddConstructor(const std::string& constructor,
definition::Constructor&& constructor_info,
const interpreter::tokens::BaseNode& base_node);
utils::IdType AddPartition(const std::vector<std::string>& path,
interpreter::tokens::PartitionStatement* node,
const interpreter::tokens::BaseNode& base_node);
std::optional<utils::IdType> FindNamespaceId(const std::optional<std::vector<std::string>>& path);
std::optional<utils::IdType> FindFunctionId(const std::optional<std::vector<std::string>>& path,
const std::string& name);
std::optional<utils::IdType> FindMethodId(const std::optional<std::vector<std::string>>& path,
const std::string& type,
const std::string& name,
utils::IsConstModifier modifier);
std::optional<utils::IdType> FindTypeId(const std::optional<std::vector<std::string>>& path,
const std::string& type);
std::optional<utils::IdType> FindLocalTypeId(const std::string& type);
std::optional<utils::IdType> FindAbstractTypeId(const std::string& abstract_type);
std::optional<utils::IdType> FindTypeclassId(const std::string& typeclass);
std::optional<utils::IdType> FindConstructorId(const std::optional<std::vector<std::string>>& path,
const std::string& constructor);
std::optional<definition::Namespace*> FindNamespace(const std::optional<std::vector<std::string>>& path) {
std::optional<utils::IdType> id = FindNamespaceId(path);
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetNamespaceInfo(id.value());
}
std::optional<definition::Function*> FindFunction(const std::optional<std::vector<std::string>>& path,
const std::string& name) {
std::optional<utils::IdType> id = FindFunctionId(path, name);
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetFunctionInfo(id.value());
}
std::optional<definition::Function*> FindMethod(const std::optional<std::vector<std::string>>& path,
const std::string& type,
const std::string& name,
utils::IsConstModifier modifier) {
std::optional<utils::IdType> id = FindMethodId(path, type, name, modifier);
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetFunctionInfo(id.value());
}
std::optional<definition::Type*> FindAnyType(const std::optional<std::vector<std::string>>& path,
const std::string& type) {
std::optional<utils::IdType> id = FindTypeId(path, type);
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetAnyTypeInfo(id.value());
}
template<typename T>
std::optional<T*> FindType(const std::optional<std::vector<std::string>>& path,
const std::string& type) {
std::optional<utils::IdType> id = FindTypeId(path, type);
if (!id.has_value()) {
return std::nullopt;
}
return global_info_.GetTypeInfo<T>(id.value());
}
std::optional<definition::Type*> FindAnyLocalType(const std::string& type) {
std::optional<utils::IdType> id = FindLocalTypeId(type);
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetAnyTypeInfo(id.value());
}
template<typename T>
std::optional<T*> FindLocalType(const std::string& type) {
std::optional<utils::IdType> id = FindLocalTypeId(type);
if (!id.has_value()) {
return std::nullopt;
}
return global_info_.GetTypeInfo<T>(id.value());
}
std::optional<definition::AbstractType*> FindAbstractType(const std::string& abstract_type) {
std::optional<utils::IdType> id = FindAbstractTypeId(abstract_type);
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetAbstractTypeInfo(id.value());
}
std::optional<definition::Typeclass*> FindTypeclass(const std::string& typeclass) {
std::optional<utils::IdType> id = FindTypeclassId(typeclass);
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetTypeclassInfo(id.value());
}
std::optional<definition::Constructor*> FindConstructor(const std::optional<std::vector<std::string>>& path,
const std::string& constructor) {
std::optional<utils::IdType> id = FindConstructorId(path, constructor);
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetConstructorInfo(id.value());
}
NamespaceVisitor CreateVisitor() {
return global_info_.CreateVisitor();
}
GlobalInfo* GetGlobalInfo() {
return &global_info_;
}
TypeclassGraph* GetTypeclassGraph() {
return global_info_.GetTypeclassGraph();
}
const std::vector<std::string>& GetCurrentPath() {
return current_path_;
}
const std::vector<utils::IdType>& GetCurrentPathNamespaces() {
return namespace_stack_;
}
// use only after LinkSymbolsVisitor
std::vector<std::optional<utils::IdType>> GetCurrentPathTypes() {
std::vector<std::optional<utils::IdType>> types;
types.reserve(namespace_stack_.size());
for (auto& namespace_id : namespace_stack_) {
definition::Namespace& namespace_info = global_info_.GetNamespaceInfo(namespace_id);
if (namespace_info.any_node.has_value() && namespace_info.any_node.value()->link_type_id_.has_value()) {
types.push_back(namespace_info.any_node.value()->link_type_id_.value());
} else {
types.push_back(std::nullopt);
}
}
return types;
}
utils::IdType GetCurrentNamespaceId() {
return namespace_stack_.back();
}
definition::Namespace* GetCurrentNamespace() {
return &global_info_.namespaces_[GetCurrentNamespaceId()];
}
std::optional<utils::IdType> GetCurrentNamespaceTypeId() {
if (!GetCurrentNamespace()->any_node.has_value()) {
return std::nullopt;
}
return GetCurrentNamespace()->any_node.value()->link_type_id_;
}
std::optional<definition::Type*> GetCurrentNamespaceAnyType() {
std::optional<utils::IdType> id = GetCurrentNamespaceTypeId();
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetAnyTypeInfo(id.value());
}
template<typename T>
std::optional<T*> GetCurrentNamespaceType() {
std::optional<utils::IdType> id = GetCurrentNamespaceTypeId();
if (!id.has_value()) {
return std::nullopt;
}
return global_info_.GetTypeInfo<T>(id.value());
}
std::optional<utils::IdType> GetCurrentNamespaceTypeclassId() {
if (!GetCurrentNamespace()->any_node.has_value()) {
return std::nullopt;
}
return GetCurrentNamespace()->any_node.value()->link_typeclass_id_;
}
std::optional<definition::Typeclass*> GetCurrentNamespaceTypeclass() {
std::optional<utils::IdType> id = GetCurrentNamespaceTypeclassId();
if (!id.has_value()) {
return std::nullopt;
}
return &global_info_.GetTypeclassInfo(id.value());
}
bool IsInGlobalNamespace() {
return namespace_stack_.size() == 1;
}
private:
NamespaceVisitor(GlobalInfo& global_info) : global_info_(global_info),
namespace_stack_ {global_info.GlobalNamespaceId} {}
template<typename T>
std::optional<T> FindSomething(
const std::optional<std::vector<std::string>>& path,
std::function<std::optional<T>(utils::IdType)> search_func);
std::optional<utils::IdType> FindNamespaceIn(
utils::IdType current_namespace,
const std::vector<std::string>& path);
private:
GlobalInfo& global_info_;
std::vector<utils::IdType> namespace_stack_;
std::vector<std::string> current_path_;
};
NamespaceVisitor CreateVisitor() {
return NamespaceVisitor(*this);
}
definition::Function& GetFunctionInfo(utils::IdType id) {
return functions_.at(id);
}
definition::Type& GetAnyTypeInfo(utils::IdType id) {
return types_.at(id);
}
template<typename T>
std::optional<T*> GetTypeInfo(utils::IdType id) {
if (!std::holds_alternative<T>(types_.at(id).type)) {
return std::nullopt;
}
return &std::get<T>(types_[id].type);
}
definition::AbstractType& GetAbstractTypeInfo(utils::IdType id) {
return abstract_types_.at(id);
}
definition::Typeclass& GetTypeclassInfo(utils::IdType id) {
return typeclasses_.at(id);
}
definition::Constructor& GetConstructorInfo(utils::IdType id) {
return constructors_.at(id);
}
definition::Namespace& GetNamespaceInfo(utils::IdType id) {
return namespaces_.at(id);
}
PartitionInfo& GetPartitionInfo(utils::IdType id) {
return partitions_.at(id);
}
std::optional<utils::IdType> FindPartition(const std::vector<std::string>& path) {
auto trie_ans = partitions_trie_.Find(path);
return trie_ans.has_value() ? std::optional<utils::IdType>(*trie_ans.value()) : std::nullopt;
}
std::vector<utils::IdType> FindPartitionsByPrefix(const std::vector<std::string>& path) { // optimize ??
auto trie_ans = partitions_trie_.FindByPrefix(path);
std::vector<utils::IdType> ans(trie_ans.size());
for (size_t i = 0; i < ans.size(); ++i) {
ans[i] = *trie_ans[i];
}
return ans;
}
TypeclassGraph* GetTypeclassGraph() {
return &typeclass_graph_;
}
std::optional<definition::Namespace*> GetTypeNamespace(utils::IdType id,
utils::ClassInternalsModifier modifier);
std::unordered_map<std::string, utils::IdType>* ChooseNamespaces(
utils::ClassInternalsModifier modifier,
definition::Namespace* current_namespace);
std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass);
// function declarations & definitions should be added latter
std::optional<utils::IdType> AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node);
private:
void CollectFunctionInfo(
utils::IdType current_namespace,
utils::ClassInternalsModifier modifier,
std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions);
private:
const utils::IdType GlobalNamespaceId = 0;
std::vector<definition::Function> functions_;
std::vector<definition::Type> types_;
std::vector<definition::AbstractType> abstract_types_;
std::vector<definition::Typeclass> typeclasses_;
std::vector<definition::Constructor> constructors_;
std::vector<definition::Namespace> namespaces_;
std::unordered_map<std::string, utils::IdType> name_to_typeclass_;
std::unordered_map<std::string, utils::IdType> name_to_abstract_type_;
std::vector<PartitionInfo> partitions_;
utils::Trie<std::string, utils::IdType> partitions_trie_;
std::vector<definition::Import> imports_;
std::unordered_map<std::string, definition::Import> usages_;
TypeclassGraph typeclass_graph_;
};
} // namespace info

View file

@ -0,0 +1,717 @@
#pragma once
#include <string>
#include <vector>
#include <variant>
#include <optional>
#include <memory>
// for clangd
#include "utils.hpp"
namespace interpreter::tokens {
struct BaseNode {
std::pair<size_t, size_t> start_position;
std::pair<size_t, size_t> end_position;
std::optional<utils::IdType> type_;
};
// ----------------- Declarations -----------------
using AnyIdentifier = std::string;
using NameOrOperatorIdentifier = std::string;
using NameIdentifier = std::string;
using AnyTypeIdentifier = std::string;
using TypeIdentifier = std::string;
using AbstractTypeIdentifier = std::string;
using OperatorIdentifier = std::string;
using TypeclassIdentifier = std::string;
// Sources -----------------
struct SourceFile;
// Namespaces, partitions -----------------
struct Namespace;
struct NamespaceSources;
// Definitions -----------------
struct ImportStatement;
struct AliasDefinitionStatement;
struct VariableDefinitionStatement;
struct FunctionDeclaration;
struct FunctionDefinitionStatement;
struct TypeDefinitionStatement;
struct AbstractTypeDefinitionStatement;
struct TypeclassDefinitionStatement;
struct PartitionStatement;
//
using NamespaceStatement = std::variant<
std::unique_ptr<AliasDefinitionStatement>,
std::unique_ptr<FunctionDeclaration>,
std::unique_ptr<FunctionDefinitionStatement>,
std::unique_ptr<TypeDefinitionStatement>,
std::unique_ptr<PartitionStatement>,
std::unique_ptr<Namespace>>;
//
using SourceStatement = std::variant<
std::unique_ptr<ImportStatement>,
std::unique_ptr<AbstractTypeDefinitionStatement>,
std::unique_ptr<TypeclassDefinitionStatement>,
std::unique_ptr<NamespaceStatement>>;
//
// Definition parts
using ImportSymbol = AnyIdentifier; // can be extended name
struct FunctionDefinition;
struct TypeDefinition;
struct AnyAnnotatedType;
// TypeIdentifier <-> AbstractTypeIdentifier <-> std::string
using AnnotatedType = AnyAnnotatedType;
using AnnotatedAbstractType = AnyAnnotatedType;
// Flow control -----------------
struct TypeConstructorPatternParameter;
struct TypeConstructorPattern;
struct Match;
struct Condition;
struct DoWhileLoop;
struct WhileLoop;
struct ForLoop;
struct LoopLoop;
using FlowControl = std::variant<
std::unique_ptr<Match>,
std::unique_ptr<Condition>,
std::unique_ptr<DoWhileLoop>,
std::unique_ptr<WhileLoop>,
std::unique_ptr<ForLoop>,
std::unique_ptr<LoopLoop>>;
// Statements, expressions, blocks, etc. -----------------
struct Block;
struct FloatNumberLiteral;
struct NumberLiteral;
struct StringLiteral;
struct CharLiteral;
struct UnitLiteral;
struct BoolLiteral;
using Literal = std::variant<
std::unique_ptr<FloatNumberLiteral>,
std::unique_ptr<NumberLiteral>,
std::unique_ptr<StringLiteral>,
std::unique_ptr<CharLiteral>,
std::unique_ptr<UnitLiteral>,
std::unique_ptr<BoolLiteral>>;
//
struct NameExpression;
struct ScopedStatement;
struct AccessExpression;
struct ReferenceExpression;
using SubExpressionToken = std::variant<
std::unique_ptr<NameExpression>,
std::unique_ptr<ScopedStatement>,
std::unique_ptr<AccessExpression>,
std::unique_ptr<Literal>,
std::unique_ptr<ReferenceExpression>>;
//
struct FunctionCallExpression;
struct ArrayExpression;
using SubExpression = std::variant< // BiaryOperatorExpression is FunctionCallExpression
std::unique_ptr<FunctionCallExpression>,
std::unique_ptr<SubExpressionToken>>;
//
enum class LoopControlExpression {
Break,
Continue,
};
//
struct ReturnExpression;
using PrefixedExpression = std::variant<
std::unique_ptr<ReturnExpression>,
std::unique_ptr<LoopControlExpression>,
std::unique_ptr<Block>>;
//
struct LambdaFunction;
struct TypeConstructor;
using Expression = std::variant<
std::unique_ptr<LambdaFunction>,
std::unique_ptr<TypeConstructor>,
std::unique_ptr<PrefixedExpression>,
std::unique_ptr<SubExpression>>;
//
struct TupleExpression;
struct VariantExpression;
using SuperExpression = std::variant<
std::unique_ptr<FlowControl>,
std::unique_ptr<TupleExpression>,
std::unique_ptr<VariantExpression>,
std::unique_ptr<ArrayExpression>,
std::unique_ptr<Expression>>;
//
struct ScopedStatement;
// Operators
struct ReferenceExpression;
// Other expressions
struct FunctionCallExpression;
struct TupleExpression;
struct VariantExpression;
struct ReturnExpression;
struct TypeConstructorParameter;
struct TypeConstructor;
struct LambdaFunction;
struct ArrayExpression;
// Name
struct PartitionName {
BaseNode base;
std::vector<AnyIdentifier> path; // name is last element of path
};
struct NameExpression;
struct TupleName;
struct VariantName;
struct AnnotatedName;
// // ScopedAnyName <-> AnyName
using AnyName = std::variant<
std::unique_ptr<AnnotatedName>,
std::unique_ptr<TupleName>,
std::unique_ptr<VariantName>>;
using ScopedAnyName = AnyName;
// Type, typeclass, etc. -----------------
// Type
struct FunctionType;
struct TupleType;
struct VariantType;
struct TypeExpression;
struct TypeExpression;
using Constructor = std::string;
// // ScopedAnyType <-> AnyType
using AnyType = std::variant<
std::unique_ptr<TypeExpression>,
std::unique_ptr<TupleType>,
std::unique_ptr<VariantType>,
std::unique_ptr<FunctionType>>;
using ScopedAnyType = AnyType;
struct ExtendedScopedAnyType;
// Typeclass
struct ParametrizedTypeclass;
// TypeclassSubExpression -> ParametrizedTypeclass
// Typeclass & Type
struct ParametrizedType;
// Identifiers, constants, etc. -----------------
using Pattern = std::variant<
std::unique_ptr<NameIdentifier>,
std::unique_ptr<Literal>,
std::unique_ptr<TypeConstructorPattern>>;
using ScopedPattern = Pattern;
////////////////////////////////////////////////////////////////////////////////////////////
// ----------------- Sources -----------------
struct SourceFile {
BaseNode base;
std::vector<SourceStatement> statements;
};
// ----------------- Namespaces, partittions -----------------
struct NamespaceSources {
BaseNode base;
std::vector<NamespaceStatement> statements;
};
struct Namespace {
BaseNode base;
utils::ClassInternalsModifier modifier;
TypeIdentifier type;
NamespaceSources scope;
std::optional<utils::IdType> link_type_id_;
std::optional<utils::IdType> link_typeclass_id_;
};
// ----------------- Definitions -----------------
struct ImportStatement {
BaseNode base;
std::optional<TypeIdentifier> name;
std::string module_name;
std::vector<ImportSymbol> symbols;
};
struct AliasDefinitionStatement {
BaseNode base;
utils::AliasModifier modifier;
TypeIdentifier type;
std::vector<AbstractTypeIdentifier> parameters;
std::unique_ptr<TypeExpression> value;
utils::IdType type_id_ = 0;
};
struct VariableDefinitionStatement {
BaseNode base;
utils::IsConstModifier modifier;
utils::AssignmentModifier assignment_modifier;
AnyName name;
SuperExpression value;
};
struct FunctionDeclaration {
BaseNode base;
bool is_in_interface = false;
NameOrOperatorIdentifier name;
std::vector<std::unique_ptr<AnnotatedAbstractType>> parameters;
std::unique_ptr<FunctionType> type;
utils::IdType function_id_ = 0;
};
struct FunctionDefinitionStatement {
BaseNode base;
std::unique_ptr<FunctionDefinition> definition;
SuperExpression value;
utils::IdType function_id_ = 0;
};
struct TypeDefinitionStatement {
BaseNode base;
bool is_in_interface = false;
utils::ClassModifier modifier;
std::unique_ptr<TypeDefinition> definition;
AnyType value;
utils::IdType type_id_ = 0;
};
struct AbstractTypeDefinitionStatement {
BaseNode base;
utils::AbstractTypeModifier modifier;
std::unique_ptr<AnnotatedType> type;
utils::IdType type_id_ = 0;
};
struct TypeclassDefinitionStatement {
BaseNode base;
std::unique_ptr<TypeDefinition> definition;
std::vector<std::pair<utils::ClassInternalsModifier,
std::unique_ptr<FunctionDeclaration>>> requirements;
utils::IdType typeclass_id_ = 0;
};
struct PartitionStatement {
BaseNode base;
utils::PartitionModifier modifier;
PartitionName name;
SuperExpression value;
utils::IdType executable_id_ = 0;
};
// Definition parts -----------------
struct FunctionDefinition {
BaseNode base;
NameOrOperatorIdentifier name;
std::vector<NameIdentifier> arguments;
};
struct TypeDefinition {
BaseNode base;
std::unique_ptr<AnnotatedType> type;
std::vector<std::unique_ptr<AnnotatedAbstractType>> parameters;
};
struct AnyAnnotatedType {
BaseNode base;
AnyTypeIdentifier type;
std::vector<std::unique_ptr<ParametrizedTypeclass>> typeclasses;
utils::IdType graph_id_ = 0; // for types
};
// ----------------- Flow control -----------------
struct TypeConstructorPatternParameter {
BaseNode base;
std::optional<NameIdentifier> name;
ScopedPattern value;
};
struct TypeConstructorPattern {
BaseNode base;
std::unique_ptr<TypeExpression> constructor;
std::vector<TypeConstructorPatternParameter> parameters;
};
struct MatchCase {
BaseNode base;
Pattern value;
std::optional<Expression> condition;
std::optional<Expression> statement;
};
struct Match {
BaseNode base;
Expression value;
std::vector<MatchCase> matches;
bool is_consuming_value = false;
};
struct Condition {
BaseNode base;
std::vector<Expression> conditions; // if, elif
std::vector<Expression> statements; // if, elif, else
};
struct DoWhileLoop {
BaseNode base;
Expression condition;
Expression statement;
};
struct WhileLoop {
BaseNode base;
Expression condition;
Expression statement;
};
struct ForLoop {
BaseNode base;
utils::IsConstModifier variable_modifier;
AnyName variable;
Expression interval;
Expression statement;
};
struct LoopLoop {
BaseNode base;
Expression statement;
};
// ----------------- Statements, expressions, blocks, etc. -----------------
using BlockStatement = std::variant<
std::unique_ptr<Expression>,
std::unique_ptr<VariableDefinitionStatement>,
std::unique_ptr<FlowControl>,
std::unique_ptr<PrefixedExpression>>;
struct Block {
BaseNode base;
std::vector<BlockStatement> statements;
};
struct ScopedStatement {
BaseNode base;
SuperExpression statement;
};
// Operators -----------------
// struct BinaryOperatorExpression {
// BaseNode base;
//
// OperatorIdentifier operator_name;
// SubExpression left_expression;
// SubExpression right_expression;
// size_t precedence = utils::MaxOperatorPrecedence;
//
// utils::IdType function_id_;
// bool is_method_ = false;
// };
struct ReferenceExpression {
BaseNode base;
utils::ReferenceModifier reference;
std::unique_ptr<ScopedStatement> expression;
};
struct AccessExpression {
BaseNode base;
std::unique_ptr<NameExpression> name;
SubExpressionToken id;
bool is_string_access_ = false;
};
// Other Expressions -----------------
struct FunctionCallExpression {
BaseNode base;
std::optional<std::variant<std::unique_ptr<SubExpressionToken>,
std::unique_ptr<TypeExpression>>> prefix;
NameOrOperatorIdentifier name;
std::vector<std::unique_ptr<TypeExpression>> parameters;
std::vector<SubExpression> arguments;
std::optional<size_t> precedence; // for operators
bool is_binary_operator_expression = false; // for operators
// only one from two is present
std::optional<utils::IdType> function_id_;
std::optional<utils::IdType> graph_id_; // for type or typeclass
std::optional<std::string> abstract_type_name_; // for typeclasses
bool is_method_of_first_argument_ = false;
};
struct TupleExpression {
BaseNode base;
std::vector<SubExpression> expressions;
};
struct VariantExpression {
BaseNode base;
std::vector<SubExpression> expressions;
};
struct ReturnExpression {
BaseNode base;
Expression expression;
bool is_from_definition = false; // from definition or from current block
};
struct TypeConstructorParameter {
BaseNode base;
std::optional<NameIdentifier> name;
std::optional<utils::AssignmentModifier> asignment_modifier;
SubExpression value;
};
struct TypeConstructor {
BaseNode base;
std::unique_ptr<TypeExpression> constructor;
std::vector<TypeConstructorParameter> parameters;
bool is_allocated_on_heap = false;
};
struct LambdaFunction {
BaseNode base;
std::vector<std::unique_ptr<AnnotatedAbstractType>> parameters;
std::vector<NameIdentifier> arguments;
Expression expression;
std::vector<utils::IdType> argument_graph_ids_;
utils::IdType return_type_graph_id_ = 0;
};
struct ArrayExpression {
BaseNode base;
std::vector<SubExpression> elements;
};
// Name -----------------
struct NameExpression {
BaseNode base;
std::vector<NameIdentifier> names;
};
struct TupleName {
BaseNode base;
std::vector<ScopedAnyName> names;
};
struct VariantName {
BaseNode base;
std::vector<ScopedAnyName> names;
};
struct AnnotatedName {
BaseNode base;
NameIdentifier name;
std::optional<ScopedAnyType> type;
};
// ----------------- Type, typeclass, etc. -----------------
// Type -----------------
struct FunctionType {
BaseNode base;
std::vector<ScopedAnyType> types;
};
struct TupleType {
BaseNode base;
std::optional<Constructor> type;
std::vector<std::pair<std::optional<NameIdentifier>, std::unique_ptr<ExtendedScopedAnyType>>> entities;
};
struct VariantType {
BaseNode base;
std::optional<Constructor> type;
std::vector<std::variant<Constructor, std::unique_ptr<TupleType>>> constructors;
};
struct ParametrizedType {
BaseNode base;
AnyTypeIdentifier type;
std::vector<std::unique_ptr<TypeExpression>> parameters;
std::optional<utils::IdType> type_id_; // std::nullopt, if it is namespace without type
};
struct TypeExpression {
BaseNode base;
std::vector<ParametrizedType> path;
ParametrizedType type;
std::optional<size_t> array_size; // if array; 0 - dynamic size
std::optional<utils::IdType> type_id_;
std::optional<utils::IdType> constructor_id_;
};
struct ExtendedScopedAnyType {
BaseNode base;
std::vector<utils::ReferenceModifier> references;
AnyType type;
};
// Typeclass -----------------
struct ParametrizedTypeclass {
BaseNode base;
TypeclassIdentifier typeclass;
std::vector<std::unique_ptr<TypeExpression>> parameters;
utils::IdType typeclass_id_ = 0;
};
// ----------------- Comments [IGNORE] -----------------
// ----------------- Identifiers, constants, etc. -----------------
struct FloatNumberLiteral {
BaseNode base;
double value;
};
struct NumberLiteral {
BaseNode base;
int64_t value;
};
struct StringLiteral {
BaseNode base;
std::string value;
};
struct CharLiteral {
BaseNode base;
char value;
};
struct UnitLiteral {
BaseNode base;
};
struct BoolLiteral {
BaseNode base;
bool value;
};
} // namespace interpereter::tokens

View file

@ -0,0 +1,142 @@
#pragma once
#include <ostream>
// for clangd
#include "definitions.hpp"
#include "error_handling.hpp"
#include "typeclass_graph.hpp"
#include "utils.hpp"
#include "visitor.hpp"
#include "global_info.hpp"
namespace interpreter {
// TODO, (maybe add VisitSourceFile?)
class LinkSymbolsVisitor : public Visitor {
public:
explicit LinkSymbolsVisitor(info::GlobalInfo& global_info)
: namespace_visitor_(global_info.CreateVisitor()),
global_info_(global_info),
typeclass_graph_(*global_info.GetTypeclassGraph()) {}
void VisitSourceFile(SourceFile* source_file) override {
Visitor::Visit(source_file);
namespace_visitor_.GetTypeclassGraph()->CalculateGraph();
}
private:
// Sources -----------------
// // void Visit(SourceFile* node) override;
// Namespaces, partitions -----------------
// // void Visit(NamespaceSources* node) override;
void Visit(Namespace* node) override;
// Definitions -----------------
// // void Visit(ImportStatement* node) override;
// // void Visit(AliasDefinitionStatement* node) override;
// // void Visit(VariableDefinitionStatement* node) override;
// // void Visit(FunctionDeclaration* node) override;
// // void Visit(FunctionDefinitionStatement* node) override;
void Visit(TypeDefinitionStatement* node) override;
// // void Visit(AbstractTypeDefinitionStatement* node) override;
void Visit(TypeclassDefinitionStatement* node) override;
// // void Visit(PartitionStatement* node) override;
// Definition parts
// // void Visit(FunctionDefinition* node) override;
// // void Visit(TypeDefinition* node) override;
// // void Visit(AnyAnnotatedType* node) override;
// Flow control -----------------
// // void Visit(TypeConstructorPatternParameter* node) override;
// // void Visit(TypeConstructorPattern* node) override;
// // void Visit(MatchCase* node) override;
// // void Visit(Match* node) override;
// // void Visit(Condition* node) override;
// // void Visit(DoWhileLoop* node) override;
// // void Visit(WhileLoop* node) override;
// // void Visit(ForLoop* node) override;
// // void Visit(LoopLoop* node) override;
// Statements, expressions, blocks, etc. -----------------
// // void Visit(Block* node) override;
// // void Visit(ScopedStatement* node) override;
// Operators
// // void Visit(ReferenceExpression* node) override;
// // void Visit(AccessExpression* node) override;
// Simple Expressions
// // void Visit(FunctionCallExpression* node) override;
// // void Visit(TupleExpression* node) override;
// // void Visit(VariantExpression* node) override;
// // void Visit(ReturnExpression* node) override;
// // void Visit(TypeConstructorParameter* node) override;
// // void Visit(TypeConstructor* node) override;
// // void Visit(LambdaFunction* node) override;
// // void Visit(ArrayExpression* node) override;
// // void Visit(LoopControlExpression& node) override; // enum
// Name
// // void Visit(PartitionName* node) override;
// // void Visit(NameExpression* node) override;
// // void Visit(TupleName* node) override;
// // void Visit(VariantName* node) override;
// // void Visit(AnnotatedName* node) override;
// Type, typeclass, etc. -----------------
// Type
// // void Visit(FunctionType* node) override;
// // void Visit(TupleType* node) override;
// // void Visit(VariantType* node) override;
void Visit(TypeExpression* node) override;
// // void Visit(ExtendedScopedAnyType* node) override;
// Typeclass
void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
// // void Visit(ParametrizedType* node) override;
// Identifiers, constants, etc. -----------------
// // void Visit(std::string* node) override; // std::string
// // void Visit(FloatNumberLiteral* node) override;
// // void Visit(NumberLiteral* node) override;
// // void Visit(StringLiteral* node) override;
// // void Visit(CharLiteral* node) override;
// // void Visit(BoolLiteral* node) override;
//
void AddTypeFunctionsToTypeclassGraph(utils::IdType type_id,
utils::IdType graph_id,
utils::ClassInternalsModifier namespace_modifier,
const BaseNode& base_node);
private:
info::GlobalInfo::NamespaceVisitor namespace_visitor_;
info::GlobalInfo& global_info_;
info::TypeclassGraph& typeclass_graph_;
};
} // namespace interpreter

36
include/node.hpp Normal file
View file

@ -0,0 +1,36 @@
#pragma once
#include <cstddef>
// for clangd
#include "parse_tree.hpp"
namespace info {
class GlobalInfo;
class Context;
} // namespace info
namespace interpreter {
class Visitor;
struct Node {
//public:
//Node(info::GlobalInfo& global_info) : global_info_(global_info) {}
// ?? not needed ?? virtual void Accept(Visitor* visitor);
/* ------------ use visitor instead ------------
virtual void build(parser::ParseTree::Cursor& cursor) = 0; // build tree from parse tree
virtual void find_symbols() = 0; // find types, typeclasses, namespaces, ..
virtual void assign_types() = 0; // typecheck
virtual void execute(info::Context& context) = 0; // execute part of tree
*/
/*private:
size_t start_position_; // ??
size_t end_position_; // ??
Node* parent_; // ??
info::GlobalInfo& global_info_;*/
};
} // namespace interpreter

View file

@ -0,0 +1,132 @@
#pragma once
#include <string>
namespace parser::tokens {
// Sources -----------------
const std::string SourceFile = "source_file";
const std::string SourceStatement = "source_statement";
const std::string NamespaceSources = "namespace_sources";
const std::string NamespaceStatement = "namespace_statement";
// Namespaces, partitions -----------------
const std::string Namespace = "namespace";
// Definitions -----------------
const std::string ImportStatement = "import_statement";
const std::string AliasDefinitionStatement = "alias_definition_statement";
const std::string VariableDefinitionStatement = "variable_definition_statement";
const std::string FunctionDeclaration = "function_declaration";
const std::string FunctionDefinitionStatement = "function_definition_statement";
const std::string TypeDefinitionStatement = "type_definition_statement";
const std::string AbstractTypeDefinitionStatement = "abstract_type_definition_statement";
const std::string TypeclassDefinitionStatement = "typeclass_definition_statement";
const std::string PartitionStatement = "partition_statement";
// Definition parts
const std::string ImportSymbol = "import_symbol";
const std::string FunctionDefinition = "function_definition";
const std::string TypeDefinition = "type_definition";
const std::string AnnotatedAbstractType = "annotated_abstract_type";
const std::string AnnotatedType = "annotated_type";
// Flow control -----------------
const std::string TypeConstructorPatternParameter = "type_constructor_pattern_parameter";
const std::string TypeConstructorPattern = "type_constructor_pattern";
const std::string ScopedPattern = "scoped_pattern";
const std::string Pattern = "pattern";
const std::string MatchCase = "match_case";
const std::string Match = "match";
const std::string Condition = "condition";
const std::string DoWhileLoop = "do_while_loop";
const std::string WhileLoop = "while_loop";
const std::string ForLoop = "for_loop";
const std::string LoopLoop = "loop_loop";
const std::string FlowControl = "flow_control";
// Statements, expressions, blocks, etc. -----------------
const std::string BlockStatement = "block_statement";
const std::string Block = "block";
const std::string SubExpressionToken = "subexpression_token";
const std::string SubExpression = "subexpression";
const std::string PrefixedExpression = "prefixed_expression";
const std::string Expression = "expression";
const std::string SuperExpression = "superexpression";
const std::string ScopedStatement = "scoped_statement";
// Operators
const std::string BinaryOperatorExpression = "binary_operator_expression";
const std::string ReferenceExpression = "reference_expression";
const std::string AccessExpression = "access_expression";
// Other expressions
const std::string FunctionArgument = "function_argument";
const std::string FunctionCallExpression = "function_call_expression";
const std::string TupleExpression = "tuple_expression";
const std::string VariantExpression = "variant_expression";
const std::string ReturnExpression = "return_expression";
const std::string TypeConstructorParameter = "type_constructor_parameter";
const std::string TypeConstructor = "type_constructor";
const std::string LambdaFunction = "lambda_function";
const std::string ArrayExpression = "array_expression";
const std::string LoopControlExpression = "loop_control_expression";
// Name
const std::string PartitionName = "partition_name";
const std::string NameExpression = "name_expression";
const std::string TupleName = "tuple_name";
const std::string VariantName = "variant_name";
const std::string AnnotatedName = "annotated_name";
const std::string AnyName = "any_name";
const std::string ScopedAnyName = "scoped_any_name";
// Type, typeclass, etc. -----------------
// Type
const std::string FunctionType = "function_type";
const std::string TupleType = "tuple_type";
const std::string VariantType = "variant_type";
const std::string TypeExpression = "type_expression";
const std::string Constructor = "constructor";
const std::string AnyType = "any_type";
const std::string ScopedAnyType = "scoped_any_type";
const std::string ExtendedScopedAnyType = "extended_scoped_any_type";
// Typeclass
const std::string ParametrizedTypeclass = "parametrized_typeclass";
// Typeclass & Type
const std::string ParametrizedType = "parametrized_type";
// Identifiers, constants, etc. -----------------
const std::string TypeclassIdentifier = "typeclass_identifier";
const std::string NameIdentifier = "name_identifier";
const std::string TypeIdentifier = "type_identifier";
const std::string AbstractTypeIdentifier = "abstract_type_identifier";
const std::string OperatorIdentifier = "operator";
const std::string FloatNumberLiteral = "float_number_literal";
const std::string NumberLiteral = "number_literal";
const std::string StringLiteral = "string_literal";
const std::string CharLiteral = "char_literal";
const std::string UnitLiteral = "unit_literal";
const std::string BoolLiteral = "bool_literal";
const std::string Literal = "literal";
} // namespace parser::tokens

142
include/parse_tree.hpp Normal file
View file

@ -0,0 +1,142 @@
#pragma once
#include <string>
// for clangd
#include "tree_sitter/api.h"
extern "C" const TSLanguage* tree_sitter_LANG();
namespace parser {
class ParseTree {
public:
class Node {
public:
Node() : uninitialized_(true) {
for (unsigned int& i : node_.context) {
i = 0;
}
node_.id = nullptr;
node_.tree = nullptr;
source_ = nullptr;
};
Node(const TSNode& node, const std::string* source) : uninitialized_(false), node_(node), source_(source) {}
std::string GetType() {
return ts_node_type(node_);
}
std::pair<size_t, size_t> GetStartPoint() {
TSPoint point = ts_node_start_point(node_);
return {point.row, point.column};
}
std::pair<size_t, size_t> GetEndPoint() {
TSPoint point = ts_node_end_point(node_);
return {point.row, point.column};
}
std::string GetAsSExpression() {
return ts_node_string(node_);
}
std::string GetValue() { // from source
size_t start = ts_node_start_byte(node_);
size_t end = ts_node_end_byte(node_);
return source_->substr(start, end - start);
}
bool IsNull() {
return ts_node_is_null(node_);
}
bool IsNamed() {
return ts_node_is_named(node_);
}
bool IsMissing() {
return ts_node_is_missing(node_);
}
bool IsExtra() { // comments, etc.
return ts_node_is_extra(node_);
}
bool HasError() {
return ts_node_has_error(node_);
}
Node NthChild(size_t n) {
return Node(ts_node_child(node_, n), source_);
}
size_t ChildCount() {
return ts_node_child_count(node_);
}
Node NthNamedChild(size_t n) {
return Node(ts_node_named_child(node_, n), source_);
}
size_t NamedChildCount() {
return ts_node_named_child_count(node_);
}
Node ChildByFieldName(const std::string& name) {
return Node(ts_node_child_by_field_name(node_, name.c_str(), name.size()), source_);
}
Node PreviousSibling() {
return Node(ts_node_prev_sibling(node_), source_);
}
Node PreviousNamedSibling() {
return Node(ts_node_prev_named_sibling(node_), source_);
}
Node NextSibling() {
return Node(ts_node_next_sibling(node_), source_);
}
Node NextNamedSibling() {
return Node(ts_node_next_named_sibling(node_), source_);
}
private:
bool uninitialized_;
TSNode node_;
const std::string* source_;
};
ParseTree(const std::string& source) : source_(source) {
TSParser* parser = ts_parser_new();
ts_parser_set_language(parser, tree_sitter_LANG());
tree_ = ts_parser_parse_string(
parser,
nullptr,
source_.c_str(),
source_.size());
ts_parser_delete(parser);
}
ParseTree(const ParseTree& parse_tree) : tree_(ts_tree_copy(parse_tree.tree_)), source_(parse_tree.source_) {}
Node GetRoot() const {
return Node(ts_tree_root_node(tree_), &source_);
}
~ParseTree() {
ts_tree_delete(tree_);
}
bool IsProperlyParsed() { // TODO: check
return !GetRoot().HasError();
}
private:
TSTree* tree_;
std::string source_; // for token value extraction
};
} // namespace parser

123
include/print_visitor.hpp Normal file
View file

@ -0,0 +1,123 @@
#pragma once
#include <ostream>
// for clangd
#include "interpreter_tree.hpp"
#include "visitor.hpp"
namespace interpreter {
class PrintVisitor : public Visitor {
public:
explicit PrintVisitor(std::ostream& out) : out_(out) {}
private:
// Sources -----------------
void Visit(SourceFile* node) override;
// Namespaces, partitions -----------------
void Visit(NamespaceSources* node) override;
void Visit(Namespace* node) override;
// Definitions -----------------
void Visit(ImportStatement* node) override;
void Visit(AliasDefinitionStatement* node) override;
void Visit(VariableDefinitionStatement* node) override;
void Visit(FunctionDeclaration* node) override;
void Visit(FunctionDefinitionStatement* node) override;
void Visit(TypeDefinitionStatement* node) override;
void Visit(AbstractTypeDefinitionStatement* node) override;
void Visit(TypeclassDefinitionStatement* node) override;
void Visit(PartitionStatement* node) override;
// Definition parts
void Visit(FunctionDefinition* node) override;
void Visit(TypeDefinition* node) override;
void Visit(AnyAnnotatedType* node) override;
// Flow control -----------------
void Visit(TypeConstructorPatternParameter* node) override;
void Visit(TypeConstructorPattern* node) override;
void Visit(MatchCase* node) override;
void Visit(Match* node) override;
void Visit(Condition* node) override;
void Visit(DoWhileLoop* node) override;
void Visit(WhileLoop* node) override;
void Visit(ForLoop* node) override;
void Visit(LoopLoop* node) override;
// Statements, expressions, blocks, etc. -----------------
void Visit(Block* node) override;
void Visit(ScopedStatement* node) override;
// Operators
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;
// Simple Expressions
void Visit(FunctionCallExpression* node) override;
void Visit(TupleExpression* node) override;
void Visit(VariantExpression* node) override;
void Visit(ReturnExpression* node) override;
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum
// Name
void Visit(PartitionName* node) override;
void Visit(NameExpression* node) override;
void Visit(TupleName* node) override;
void Visit(VariantName* node) override;
void Visit(AnnotatedName* node) override;
// Type, typeclass, etc. -----------------
// Type
void Visit(FunctionType* node) override;
void Visit(TupleType* node) override;
void Visit(VariantType* node) override;
void Visit(TypeExpression* node) override;
void Visit(ExtendedScopedAnyType* node) override;
// Typeclass
void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
void Visit(ParametrizedType* node) override;
// Identifiers, constants, etc. -----------------
void Visit(std::string* node) override; // std::string
void Visit(FloatNumberLiteral* node) override;
void Visit(NumberLiteral* node) override;
void Visit(StringLiteral* node) override;
void Visit(CharLiteral* node) override;
void Visit(UnitLiteral* node) override;
void Visit(BoolLiteral* node) override;
private:
std::ostream& out_;
};
} // namespace interpreter

View file

@ -0,0 +1,246 @@
#pragma once
// for clangd
#include "interpreter_tree.hpp"
#include "typeclass_graph.hpp"
#include "types.hpp"
#include "contexts.hpp"
#include "utils.hpp"
#include "visitor.hpp"
#include "global_info.hpp"
#include <unordered_set>
// TODO: class fields and constructors can't be accessed not from associated namespace
namespace interpreter {
class TypeCheckVisitor : public Visitor {
public:
explicit TypeCheckVisitor(info::GlobalInfo& global_info,
info::ContextManager<info::type::Type, info::type::TypeManager>& context_manager)
: namespace_visitor_(global_info.CreateVisitor()),
global_info_(global_info),
typeclass_graph_(*global_info.GetTypeclassGraph()),
context_manager_(context_manager) {}
void VisitSourceFile(SourceFile* source_file) override {
// init internal type abstrac types
for (size_t i = 0; i < info::type::InternalTypesCount; ++i) {
info::type::InternalType type = static_cast<info::type::InternalType>(i);
Visit(namespace_visitor_.FindAbstractType(info::type::ToString(type)).value()->node);
}
Visit(source_file);
}
private:
// Sources -----------------
void Visit(SourceFile* node) override;
// Namespaces, partitions -----------------
void Visit(NamespaceSources* node) override;
void Visit(Namespace* node) override;
// Definitions -----------------
void Visit(ImportStatement* node) override;
void Visit(AliasDefinitionStatement* node) override;
void Visit(VariableDefinitionStatement* node) override;
void Visit(FunctionDeclaration* node) override;
void Visit(FunctionDefinitionStatement* node) override;
void Visit(TypeDefinitionStatement* node) override;
void Visit(AbstractTypeDefinitionStatement* node) override;
void Visit(TypeclassDefinitionStatement* node) override;
void Visit(PartitionStatement* node) override;
// Definition parts
void Visit(FunctionDefinition* node) override;
void Visit(TypeDefinition* node) override;
void Visit(AnyAnnotatedType* node) override;
// Flow control -----------------
void Visit(TypeConstructorPatternParameter* node) override;
void Visit(TypeConstructorPattern* node) override;
void Visit(MatchCase* node) override;
void Visit(Match* node) override;
void Visit(Condition* node) override;
void Visit(DoWhileLoop* node) override;
void Visit(WhileLoop* node) override;
void Visit(ForLoop* node) override;
void Visit(LoopLoop* node) override;
// Statements, expressions, blocks, etc. -----------------
void Visit(Block* node) override;
void Visit(ScopedStatement* node) override;
// Operators
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;
// Simple Expressions
void Visit(FunctionCallExpression* node) override;
void Visit(TupleExpression* node) override;
void Visit(VariantExpression* node) override;
void Visit(ReturnExpression* node) override;
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum
// Name
void Visit(PartitionName* node) override;
void Visit(NameExpression* node) override;
void Visit(TupleName* node) override;
void Visit(VariantName* node) override;
void Visit(AnnotatedName* node) override;
// Type, typeclass, etc. -----------------
// Type
void Visit(FunctionType* node) override;
void Visit(TupleType* node) override;
void Visit(VariantType* node) override;
void Visit(TypeExpression* node) override;
void Visit(ExtendedScopedAnyType* node) override;
// Typeclass
void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
void Visit(ParametrizedType* node) override;
// Identifiers, constants, etc. -----------------
// // void Visit(std::string* node) override; // std::string
void Visit(FloatNumberLiteral* node) override;
void Visit(NumberLiteral* node) override;
void Visit(StringLiteral* node) override;
void Visit(CharLiteral* node) override;
void Visit(UnitLiteral* node) override;
void Visit(BoolLiteral* node) override;
//
void CollectTypeContext(const ParametrizedType& type,
std::unordered_map<std::string, utils::IdType>& context);
void CollectTypeExpressionContext(const TypeExpression& type_expression,
std::unordered_map<std::string, utils::IdType>& context);
utils::IdType TypeInContext(utils::IdType type,
const std::unordered_map<std::string, utils::IdType>& context);
void CheckPattern(Pattern& node, const BaseNode& base_node);
std::optional<FunctionDeclaration*>
FindExpressionMethodAndUpdate(FunctionCallExpression* node,
utils::IdType expression_type);
std::optional<FunctionDeclaration*>
FindTypeFunctionAndUpdate(FunctionCallExpression* node,
TypeExpression* type_node,
std::unordered_map<std::string, utils::IdType>& context);
std::optional<FunctionDeclaration*> FindFunctionAndUpdate(FunctionCallExpression* node);
std::optional<FunctionDeclaration*>
FindAbstractTypeTypeclassFunctionAndUpdate(
FunctionCallExpression* node,
info::type::AbstractType* abstract_type,
bool is_method);
std::optional<FunctionDeclaration*>
FindDefinedTypeFunctionAndUpdate(
FunctionCallExpression* node,
info::definition::AnyType* defined_type,
utils::IdType type,
bool is_method);
void ResetReturnedAndBroughtTypes() {
if (returned_type_.has_value()) {
all_branches_returned_value_ = false;
}
if (brought_type_.has_value()) {
all_branches_brought_value_ = false;
}
}
void AddGraphIdLocalTypes(utils::IdType graph_id, utils::IdType type) {
std::unordered_set<utils::IdType> requirement_graph_ids = typeclass_graph_.GetDependenciesSet(graph_id);
requirement_graph_ids.insert(graph_id);
for (auto& requirement_graph_id : requirement_graph_ids) {
context_manager_.DefineLocalType(typeclass_graph_.GetVertex(requirement_graph_id).name, type);
}
}
utils::IdType AddGraphIdLocalAbstractTypes(utils::IdType graph_id) {
std::unordered_set<utils::IdType> requirement_graph_ids = typeclass_graph_.GetDependenciesSet(graph_id);
requirement_graph_ids.insert(graph_id);
utils::IdType abstract_type = context_manager_.AddValue(
info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
graph_id,
typeclass_graph_),
utils::ValueType::Tmp);
for (auto& requirement_graph_id : requirement_graph_ids) {
context_manager_.DefineLocalType(typeclass_graph_.GetVertex(requirement_graph_id).name, abstract_type);
}
return abstract_type;
}
void VisitDefinedType(info::definition::AnyType* defined_type,
const std::unordered_map<std::string, utils::IdType>& context) {
Visitor::Visit(defined_type->node->value);
current_type_ = TypeInContext(current_type_, context);
current_type_ =
context_manager_.AddValue(info::type::DefinedType(defined_type->node->type_id_,
current_type_,
defined_type->modifier,
context_manager_.GetValueManager()),
utils::ValueType::Tmp);
}
private:
info::GlobalInfo::NamespaceVisitor namespace_visitor_;
info::GlobalInfo& global_info_;
info::TypeclassGraph& typeclass_graph_;
info::ContextManager<info::type::Type, info::type::TypeManager>& context_manager_;
std::unordered_set<utils::IdType> type_namespaces_;
utils::IdType current_type_;
std::optional<utils::IdType> returned_type_;
bool all_branches_returned_value_ = true;
std::optional<utils::IdType> brought_type_;
bool all_branches_brought_value_ = true;
std::unordered_map<info::type::InternalType, utils::IdType> internal_to_abstract_type_;
std::optional<utils::IsConstModifier> is_const_definition_;
bool is_in_statement_ = false;
};
} // namespace interpreter

View file

@ -0,0 +1,91 @@
#pragma once
#include <algorithm>
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>
// for clangd
#include "utils.hpp"
#include "interpreter_tree.hpp"
namespace info {
// move constructor parameters ??
class TypeclassGraph {
public:
enum class Modifier {
Typeclass = 0,
Type = 1,
};
struct FunctionInfo {
utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static;
interpreter::tokens::FunctionDeclaration* declaration = nullptr;
std::optional<interpreter::tokens::FunctionDefinitionStatement*> definition;
bool is_defined_in_owner = false;
};
struct Vertex { // make constructor ??
std::string name;
std::unordered_map<std::string, FunctionInfo> functions;
std::unordered_set<std::string> dependencies; // TODO: parameters
interpreter::tokens::BaseNode* base_node; // for error handling
std::optional<utils::IdType> type_id; // for defined types
Modifier modifier;
};
utils::IdType AddVertex(
const std::string& name,
const std::vector<std::string>& dependencies,
const std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions,
interpreter::tokens::BaseNode* base_node,
Modifier modifier);
std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name);
bool IsFunctionInVertex(const std::string& name, utils::IdType vertex_id) {
return verticles_[vertex_id].functions.count(name) != 0;
}
// if vertex_id == std::nullopt, info can be not complete
std::optional<FunctionInfo*> GetFunctionInfo(const std::string& name,
std::optional<utils::IdType> vertex_id);
const Vertex& GetVertex(utils::IdType id) {
return verticles_.at(id);
}
std::optional<Vertex*> GetTypeVertex(utils::IdType id) {
if (verticles_.at(id).modifier == Modifier::Type) {
return &verticles_[id];
}
return std::nullopt;
}
// cache ??
std::unordered_set<utils::IdType> GetDependenciesSet(utils::IdType id);
std::vector<utils::IdType> GetDependenciesVector(utils::IdType id);
const std::unordered_map<std::string, FunctionInfo>& GetVertexFunctions(utils::IdType id) {
return verticles_.at(id).functions;
}
bool IsCalculated() {
return is_calculated_;
}
// can exit by typecheck error
void CalculateGraph();
private:
std::unordered_map<std::string, utils::IdType> method_to_vertex_;
std::unordered_map<std::string, utils::IdType> name_to_typeclass_;
std::vector<Vertex> verticles_;
bool is_calculated_ = true;
};
} // namespace info

View file

@ -0,0 +1,126 @@
#pragma once
#include <ostream>
// for clangd
#include "visitor.hpp"
#include "types.hpp"
#include "contexts.hpp"
namespace interpreter {
class TypedPrintVisitor : public Visitor {
public:
explicit TypedPrintVisitor(std::ostream& out,
info::ContextManager<info::type::Type, info::type::TypeManager>& context_manager)
: out_(out), context_manager_(context_manager) {}
private:
// Sources -----------------
void Visit(SourceFile* node) override;
// Namespaces, partitions -----------------
void Visit(NamespaceSources* node) override;
void Visit(Namespace* node) override;
// Definitions -----------------
void Visit(ImportStatement* node) override;
void Visit(AliasDefinitionStatement* node) override;
void Visit(VariableDefinitionStatement* node) override;
void Visit(FunctionDeclaration* node) override;
void Visit(FunctionDefinitionStatement* node) override;
void Visit(TypeDefinitionStatement* node) override;
void Visit(AbstractTypeDefinitionStatement* node) override;
void Visit(TypeclassDefinitionStatement* node) override;
void Visit(PartitionStatement* node) override;
// Definition parts
void Visit(FunctionDefinition* node) override;
void Visit(TypeDefinition* node) override;
void Visit(AnyAnnotatedType* node) override;
// Flow control -----------------
void Visit(TypeConstructorPatternParameter* node) override;
void Visit(TypeConstructorPattern* node) override;
void Visit(MatchCase* node) override;
void Visit(Match* node) override;
void Visit(Condition* node) override;
void Visit(DoWhileLoop* node) override;
void Visit(WhileLoop* node) override;
void Visit(ForLoop* node) override;
void Visit(LoopLoop* node) override;
// Statements, expressions, blocks, etc. -----------------
void Visit(Block* node) override;
void Visit(ScopedStatement* node) override;
// Operators
void Visit(ReferenceExpression* node) override;
void Visit(AccessExpression* node) override;
// Simple Expressions
void Visit(FunctionCallExpression* node) override;
void Visit(TupleExpression* node) override;
void Visit(VariantExpression* node) override;
void Visit(ReturnExpression* node) override;
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum
// Name
void Visit(PartitionName* node) override;
void Visit(NameExpression* node) override;
void Visit(TupleName* node) override;
void Visit(VariantName* node) override;
void Visit(AnnotatedName* node) override;
// Type, typeclass, etc. -----------------
// Type
void Visit(FunctionType* node) override;
void Visit(TupleType* node) override;
void Visit(VariantType* node) override;
void Visit(TypeExpression* node) override;
void Visit(ExtendedScopedAnyType* node) override;
// Typeclass
void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
void Visit(ParametrizedType* node) override;
// Identifiers, constants, etc. -----------------
void Visit(std::string* node) override; // std::string
void Visit(FloatNumberLiteral* node) override;
void Visit(NumberLiteral* node) override;
void Visit(StringLiteral* node) override;
void Visit(CharLiteral* node) override;
void Visit(UnitLiteral* node) override;
void Visit(BoolLiteral* node) override;
private:
std::ostream& out_;
info::ContextManager<info::type::Type, info::type::TypeManager>& context_manager_;
};
} // namespace interpreter

401
include/types.hpp Normal file
View file

@ -0,0 +1,401 @@
#pragma once
#include <optional>
#include <string>
#include <variant>
#include <memory>
#include <unordered_set>
#include <unordered_map>
// for clangd
#include "error_handling.hpp"
#include "typeclass_graph.hpp"
#include "utils.hpp"
namespace info::type {
// TODO: move in constructors
class TypeManager;
class AbstractType { // latter will be found in context
public:
AbstractType(utils::AbstractTypeModifier modifier,
utils::IdType graph_id,
info::TypeclassGraph& typeclass_graph)
: modifier_(modifier),
graph_id_(graph_id),
typeclass_graph_(typeclass_graph) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const AbstractType& type) const;
bool operator<(const AbstractType& type) const;
bool operator>(const AbstractType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
utils::IdType GetGraphId() {
return graph_id_;
}
bool HasTypeclass(utils::IdType graph_id) { // TODO: cache dependencies set
return graph_id == graph_id_ || typeclass_graph_.GetDependenciesSet(graph_id_).count(graph_id) != 0;
}
std::string ToString() {
return "Abstract " + std::to_string(graph_id_);
}
private:
utils::AbstractTypeModifier modifier_;
utils::IdType graph_id_;
info::TypeclassGraph& typeclass_graph_;
};
class DefinedType {
public:
DefinedType() = default;
DefinedType(utils::IdType type_id,
utils::IdType type,
utils::ClassModifier class_modifier,
TypeManager* type_manager)
: type_id_(type_id), type_(type), class_modifier_(class_modifier), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const DefinedType& type) const;
bool operator<(const DefinedType& type) const;
bool operator>(const DefinedType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
utils::IdType GetTypeId() const {
return type_id_;
}
utils::IdType GetType() const {
return type_;
}
utils::ClassModifier GetClassModifier() const {
return class_modifier_;
}
std::string ToString() {
return "Defined";
}
private:
utils::IdType type_id_; // in defined types
utils::IdType type_; // in types manager, created using context types (if specific type)
utils::ClassModifier class_modifier_;
TypeManager* type_manager_ = nullptr;
};
const size_t InternalTypesCount = 6;
enum class InternalType {
Float = 0,
Int = 1,
String = 2,
Char = 3,
Bool = 4,
Unit = 5,
};
inline std::optional<InternalType> ToInternalType(const std::string& type) {
if (type.empty()) {
return std::nullopt;
}
switch (type[0]) {
case 'F':
if (type == "Float") { return InternalType::Float; }
break;
case 'I':
if (type == "Int") { return InternalType::Int; }
break;
case 'S':
if (type == "String") { return InternalType::String; }
break;
case 'C':
if (type == "Char") { return InternalType::Char; }
break;
case 'B':
if (type == "Bool") { return InternalType::Bool; }
break;
case 'U':
if (type == "Unit") { return InternalType::Unit; }
break;
default:
break;
}
return std::nullopt;
}
inline std::string ToString(InternalType type) {
std::string result;
switch (type) {
case InternalType::Float:
result = "Float";
break;
case InternalType::Int:
result = "Int";
break;
case InternalType::String:
result = "String";
break;
case InternalType::Char:
result = "Char";
break;
case InternalType::Bool:
result = "Bool";
break;
case InternalType::Unit:
result = "Unit";
break;
}
return result;
}
class TupleType {
public:
TupleType() = default;
TupleType(const std::optional<std::string>& name,
const std::vector<std::pair<std::optional<std::string>, utils::IdType>>& fields,
TypeManager* type_manager)
: name_(name), fields_(fields), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const TupleType& type) const;
bool operator<(const TupleType& type) const;
bool operator>(const TupleType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
const std::vector<std::pair<std::optional<std::string>, utils::IdType>>& GetFields() const {
return fields_;
}
std::string ToString();
private:
std::optional<std::string> name_;
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields_;
TypeManager* type_manager_ = nullptr;
};
class VariantType {
public:
VariantType() = default;
VariantType(const std::optional<std::string>& name,
const std::vector<TupleType>& constructors,
std::optional<size_t> current_constructor)
: name_(name), constructors_(constructors), current_constructor_(current_constructor) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const VariantType& type) const;
bool operator<(const VariantType& type) const;
bool operator>(const VariantType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
const std::vector<TupleType>& GetConstructors() const {
return constructors_;
}
void SetCurrentConstructor(size_t constructor) {
current_constructor_ = constructor;
}
std::string ToString();
private:
std::optional<std::string> name_;
std::vector<TupleType> constructors_;
std::optional<size_t> current_constructor_;
};
class OptionalType {
public:
OptionalType() = default;
OptionalType(utils::IdType type,
TypeManager* type_manager)
: type_(type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const OptionalType& type) const;
bool operator<(const OptionalType& type) const;
bool operator>(const OptionalType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString();
private:
utils::IdType type_;
TypeManager* type_manager_ = nullptr;
};
class ReferenceToType {
public:
ReferenceToType() = default;
ReferenceToType(const std::vector<utils::ReferenceModifier>& references,
utils::IdType type,
TypeManager* type_manager)
: references_(references), type_(type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const ReferenceToType& type) const;
bool operator<(const ReferenceToType& type) const;
bool operator>(const ReferenceToType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString();
private:
std::vector<utils::ReferenceModifier> references_;
utils::IdType type_;
TypeManager* type_manager_ = nullptr;
};
/////////////////////////////
class FunctionType {
public:
FunctionType() = default;
FunctionType(const std::vector<utils::IdType>& argument_types,
utils::IdType return_type,
TypeManager* type_manager)
: argument_types_(argument_types), return_type_(return_type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const FunctionType& type) const;
bool operator<(const FunctionType& type) const;
bool operator>(const FunctionType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string ToString();
private:
std::vector<utils::IdType> argument_types_;
utils::IdType return_type_;
TypeManager* type_manager_ = nullptr;
};
class ArrayType {
public:
ArrayType() = default;
ArrayType(size_t size,
utils::IdType elements_type,
TypeManager* type_manager)
: size_(size), elements_type_(elements_type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const ArrayType& type) const;
bool operator<(const ArrayType& type) const;
bool operator>(const ArrayType& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
utils::IdType GetElementsType() {
return elements_type_;
}
std::string ToString();
private:
size_t size_; // = 0 for dynamic
utils::IdType elements_type_;
TypeManager* type_manager_ = nullptr;
};
class Type {
public:
template<typename T>
explicit Type(const T& type) : type_(type) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const Type& type) const;
bool operator<(const Type& type) const; // TODO: rule exceptions
bool operator>(const Type& type) const;
std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const;
std::string GetTypeName() const;
std::variant<AbstractType,
DefinedType,
InternalType,
TupleType,
VariantType,
ReferenceToType,
FunctionType,
ArrayType,
OptionalType>& GetType() {
return type_;
}
std::string ToString();
private:
std::variant<AbstractType,
DefinedType,
InternalType,
TupleType,
VariantType,
ReferenceToType,
FunctionType,
ArrayType,
OptionalType> type_;
};
class TypeManager {
public:
template<typename T>
utils::IdType AddValue(const T& type, utils::ValueType value_type) {
types_.push_back(std::pair<Type, utils::ValueType> {type, value_type});
return types_.size() - 1;
}
utils::IdType AddAnyValue(Type&& type, utils::ValueType value_type) {
types_.push_back(std::pair<Type, utils::ValueType> {std::move(type), value_type});
return types_.size() - 1;
}
template<typename T>
std::optional<T*> GetValue(utils::IdType type_id) {
if (!std::holds_alternative<T>(types_.at(type_id).first.GetType())) {
return std::nullopt;
}
return &std::get<T>(types_.at(type_id).first.GetType());
}
Type* GetAnyValue(utils::IdType type_id) {
return &types_.at(type_id).first;
}
utils::ValueType GetValueType(utils::IdType type_id) {
return types_.at(type_id).second;
}
void SetValueType(utils::IdType type_id, utils::ValueType value_type) {
types_.at(type_id).second = value_type;
}
bool EqualValues(utils::IdType first_type, utils::IdType second_type) {
return GetAnyValue(first_type)->Same(*GetAnyValue(second_type));
}
bool AddValueRequirement(utils::IdType type, utils::IdType requrement) {
return *GetAnyValue(requrement) < *GetAnyValue(type);
}
private:
std::vector<std::pair<Type, utils::ValueType>> types_;
};
} // namespace info::type

225
include/utils.hpp Normal file
View file

@ -0,0 +1,225 @@
#pragma once
#include <cstdlib>
#include <unordered_set>
#include <vector>
#include <string>
#include <memory>
#include <optional>
#include <unordered_map>
namespace utils {
using std::size_t;
using IdType = size_t;
const std::string ClassInternalVarName = "self";
const size_t MaxOperatorPrecedence = 4;
struct ValueReturnedMarker {};
struct ValueBroughtMarker {};
enum class ReferenceModifier { Reference = 0, UniqueReference = 1, Dereference = 2 };
enum class IsConstModifier { Const = 0, Var = 1 };
enum class ClassInternalsModifier { Static = 0, Const = 1, Var = 2};
enum class ClassModifier { Struct = 0, Class = 1 };
enum class AssignmentModifier { Assign = 0, Move = 1 };
enum class AliasModifier { Alias = 0, Type = 1, Let = 2 };
enum class AbstractTypeModifier { Basic = 0, Abstract = 1 };
enum class PartitionModifier { Exec = 0, Test = 1 };
enum class ValueType { Const = 0, Var = 1, Tmp = 2 };
ValueType IsConstModifierToValueType(IsConstModifier modifier);
ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier);
bool IsBuiltinFunction(const std::string& name);
template<typename T>
class Storage {
public:
Storage() = default;
IdType GetId(const T& value) {
IdType id = 0;
auto value_position = value_to_id_.find(value);
if (value_position == value_to_id_.end()) {
id = id_to_value_.size();
value_to_id_[value] = id;
id_to_value_.push_back(value);
} else {
id = value_position->second;
}
return id;
}
const T& GetValue(IdType id) {
return id_to_value_[id];
}
private:
std::vector<T> id_to_value_;
std::unordered_map<T, IdType> value_to_id_;
};
template<typename Key, typename Value>
class Trie { // optimize ??
public:
Trie() {
verticles_.emplace_back();
}
bool Insert(const std::vector<Key>& path, const Value& value) {
return RecursiveInsert(verticles_[0], path, 0, value);
}
std::optional<Value*> Find(const std::vector<Key>& path) {
return RecursiveFind(verticles_[0], path, 0);
}
std::vector<Value*> FindByPrefix(const std::vector<Key>& path) {
return RecursiveFindByPrefix(verticles_[0], path, 0);
}
private:
struct Vertex {
std::unordered_map<Key, size_t> children_;
std::optional<Value> value;
};
bool RecursiveInsert(Vertex& vertex,
const std::vector<Key>& path,
size_t path_position,
const Value& value) {
if (path_position == path.size()) {
if (vertex.value.has_value()) {
return false;
}
vertex.value = value;
return true;
}
auto child_iter = vertex.children_.find(path[path_position]);
if (child_iter != vertex.children_.end()) {
return RecursiveInsert(verticles_[child_iter->second], path, path_position + 1, value);
}
vertex.children_[path[path_position]] = verticles_.size();
verticles_.emplace_back();
return RecursiveInsert(verticles_.back(), path, path_position + 1, value);
}
std::optional<Value*> RecursiveFind(Vertex& vertex,
const std::vector<Key>& path,
size_t path_position) {
if (path_position == path.size()) {
if (!vertex.value.has_value()) {
return std::nullopt;
}
return &vertex.value.value();
}
auto child_iter = vertex.children_.find(path[path_position]);
if (child_iter != vertex.children_.end()) {
return RecursiveFind(verticles_[child_iter->second], path, path_position + 1);
}
return std::nullopt;
}
std::vector<Value*> RecursiveFindByPrefix(Vertex& vertex,
const std::vector<Key>& path,
size_t path_position) {
if (path_position == path.size()) {
std::vector<Value*> ans;
RecursiveGetAll(vertex, ans);
return ans;
}
auto child_iter = vertex.children_.find(path[path_position]);
if (child_iter != vertex.children_.end()) {
return RecursiveFindByPrefix(verticles_[child_iter->second], path, path_position + 1);
}
return {};
}
void RecursiveGetAll(Vertex& vertex, std::vector<Value*>& accumulator) {
std::vector<Value*> ans;
if (vertex.value.has_value()) {
accumulator.push_back(&vertex.value.value());
}
for (auto& child : vertex.children_) {
RecursiveGetAll(verticles_[child.second], accumulator);
}
}
private:
std::vector<Vertex> verticles_;
};
class GroupsManager { // TODO: recall right algorithm name
public:
GroupsManager() = default;
explicit GroupsManager(size_t n) {
edges_.resize(n);
ranks_.resize(n);
for (size_t i = 0; i < n; ++i) {
edges_[i] = i;
ranks_[i] = 1;
}
}
void Unite(size_t u, size_t v) { // TODO: recall choice algorithm
u = GetGroupRoot(u);
v = GetGroupRoot(v);
if (ranks_[v] >= ranks_[u]) {
edges_[u] = v;
ranks_[v] = std::max(ranks_[u] + 1, ranks_[v]);
} else {
edges_[v] = u;
// always ranks_[u] > ranks_[v]
}
}
bool IsInOneGroup(size_t u, size_t v) {
return GetGroupRoot(u) == GetGroupRoot(v);
}
size_t AddElement() {
size_t id = edges_.size();
edges_.push_back(id);
ranks_.push_back(1);
return id;
}
size_t GetGroupRoot(size_t v) {
if (edges_[v] == v) {
return v;
}
return edges_[v] = GetGroupRoot(edges_[v]);
}
private:
std::vector<size_t> edges_;
std::vector<size_t> ranks_;
};
void BackVisitDfs(size_t id,
std::vector<size_t>& verticles,
std::vector<size_t>& marks,
const std::vector<std::vector<size_t>>& edges,
size_t mark);
std::vector<size_t> BackTopSort(const std::vector<std::vector<size_t>>& edges_);
} // namespace utils

244
include/values.hpp Normal file
View file

@ -0,0 +1,244 @@
#pragma once
#include <iterator>
#include <string>
#include <variant>
#include <optional>
#include <unordered_map>
// for clangd
#include "interpreter_tree.hpp"
#include "utils.hpp"
namespace info::value {
struct ValueManager;
struct Unit {};
struct InternalValue {
public:
InternalValue() = default;
template<typename T>
explicit InternalValue(const T& value) : value(value) {} // move ??
template<typename T>
std::optional<T*> GetValue() {
if (!std::holds_alternative<T>(value)) {
return std::nullopt;
}
return &std::get<T>(value);
}
bool Same(const InternalValue& value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type);
public:
std::variant<double,
int64_t,
std::string,
char,
bool,
Unit> value;
};
struct TupleValue { /// no need to store strings (only store associated type) ??
public:
TupleValue() = default;
TupleValue(std::vector<std::pair<std::optional<std::string>, utils::IdType>>&& fields,
ValueManager* value_manager)
: fields(std::move(fields)), value_manager_(value_manager) {}
bool Same(const TupleValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); // TODO
public:
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
private:
ValueManager* value_manager_ = nullptr;
};
struct VariantValue {
public:
explicit VariantValue() = default;
VariantValue(TupleValue&& value, size_t current_constructor)
: value(std::move(value)), current_constructor(current_constructor) {}
bool Same(const VariantValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type);
public:
TupleValue value;
size_t current_constructor;
};
struct ReferenceToValue {
public:
ReferenceToValue() = default;
ReferenceToValue(const std::vector<utils::ReferenceModifier>& references,
utils::IdType value,
ValueManager* value_manager)
: references(references), value(value), value_manager_(value_manager) {}
bool Same(const ReferenceToValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type);
public:
std::vector<utils::ReferenceModifier> references;
utils::IdType value;
private:
ValueManager* value_manager_ = nullptr;
};
struct FunctionValue {
public:
FunctionValue() = default;
template<typename T>
FunctionValue(const T& function, ValueManager* value_manager)
: function(function), value_manager_(value_manager) {}
bool Same(const FunctionValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type);
public:
std::variant<interpreter::tokens::FunctionDeclaration*,
interpreter::tokens::LambdaFunction*> function;
private:
ValueManager* value_manager_ = nullptr;
};
struct ArrayValue {
public:
ArrayValue() = default;
ArrayValue(std::vector<utils::IdType>&& elements,
bool is_constant_size,
ValueManager* value_manager)
: elements(std::move(elements)), is_constant_size(is_constant_size), value_manager_(value_manager) {}
bool Same(const ArrayValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type);
public:
std::vector<utils::IdType> elements;
bool is_constant_size = false;
private:
ValueManager* value_manager_ = nullptr;
};
struct OptionalValue {
public:
OptionalValue() = default;
OptionalValue(std::optional<utils::IdType> value, ValueManager* value_manager)
: value(value), value_manager_(value_manager) {}
bool Same(const OptionalValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type);
public:
std::optional<utils::IdType> value;
private:
ValueManager* value_manager_ = nullptr;
};
struct Value { // DefinedValue ??
public:
Value() = default;
template<typename T>
explicit Value(const T& value) : value(value) {} // move ??
bool Same(const Value& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type);
public:
std::variant<InternalValue,
TupleValue,
VariantValue,
ReferenceToValue,
FunctionValue, // ??
ArrayValue,
OptionalValue> value;
};
class ValueManager {
public:
template<typename T>
utils::IdType ExplicitAddValue(const T& value, utils::ValueType value_type) {
values_.push_back(std::pair<Value, utils::ValueType> {Value(value), value_type});
return values_.size() - 1;
}
utils::IdType ExplicitAddAnyValue(Value&& value, utils::ValueType value_type) {
values_.push_back(std::pair<Value, utils::ValueType> {std::move(value), value_type});
return values_.size() - 1;
}
template<typename T>
utils::IdType AddValue(const T& value, utils::ValueType value_type) {
return ExplicitAddValue(std::move(value), value_type);
}
utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) {
return ExplicitAddAnyValue(std::move(value), value_type);
}
template<typename T>
std::optional<T*> GetValue(utils::IdType value_id) {
if (!std::holds_alternative<T>(values_.at(value_id).first.value)) {
return std::nullopt;
}
return &std::get<T>(values_.at(value_id).first.value);
}
Value* GetAnyValue(utils::IdType value_id) {
return &values_.at(value_id).first;
}
utils::ValueType GetValueType(utils::IdType value_id) {
return values_.at(value_id).second;
}
void SetValueType(utils::IdType value_id, utils::ValueType value_type) {
values_.at(value_id).second = value_type;
}
bool EqualValues(utils::IdType first_value, utils::IdType second_value) {
return GetAnyValue(first_value)->Same(*GetAnyValue(second_value));
}
bool AddValueRequirement(utils::IdType value, utils::IdType requrement) = delete;
private:
std::vector<std::pair<Value, utils::ValueType>> values_;
};
} // namespace info::value

141
include/visitor.hpp Normal file
View file

@ -0,0 +1,141 @@
#pragma once
// for clangd
#include "interpreter_tree.hpp"
namespace interpreter {
using namespace tokens;
class Visitor {
public:
virtual void VisitSourceFile(SourceFile* source_file) {
Visit(source_file);
}
protected:
// Sources -----------------
virtual void Visit(SourceFile* node);
// Namespaces, partitions -----------------
virtual void Visit(NamespaceSources* node);
virtual void Visit(Namespace* node);
// Definitions -----------------
virtual void Visit(ImportStatement* node);
virtual void Visit(AliasDefinitionStatement* node);
virtual void Visit(VariableDefinitionStatement* node);
virtual void Visit(FunctionDeclaration* node);
virtual void Visit(FunctionDefinitionStatement* node);
virtual void Visit(TypeDefinitionStatement* node);
virtual void Visit(AbstractTypeDefinitionStatement* node);
virtual void Visit(TypeclassDefinitionStatement* node);
virtual void Visit(PartitionStatement* node);
virtual void Visit(NamespaceStatement& node); // variant
virtual void Visit(SourceStatement& node); // variant
// Definition parts
virtual void Visit(FunctionDefinition* node);
virtual void Visit(TypeDefinition* node);
virtual void Visit(AnyAnnotatedType* node);
// Flow control -----------------
virtual void Visit(TypeConstructorPatternParameter* node);
virtual void Visit(TypeConstructorPattern* node);
virtual void Visit(MatchCase* node);
virtual void Visit(Match* node);
virtual void Visit(Condition* node);
virtual void Visit(DoWhileLoop* node);
virtual void Visit(WhileLoop* node);
virtual void Visit(ForLoop* node);
virtual void Visit(LoopLoop* node);
virtual void Visit(Pattern& node); // variant
virtual void Visit(FlowControl& node); // variant
// Statements, expressions, blocks, etc. -----------------
virtual void Visit(BlockStatement& node); // variant
virtual void Visit(Block* node);
virtual void Visit(SubExpressionToken& node); // variant
virtual void Visit(SubExpression& node); // variant
virtual void Visit(PrefixedExpression& node); // variant
virtual void Visit(Expression& node); // variant
virtual void Visit(SuperExpression& node); // variant
virtual void Visit(ScopedStatement* node);
// Operators
virtual void Visit(ReferenceExpression* node);
virtual void Visit(AccessExpression* node);
// Other expressions
virtual void Visit(FunctionCallExpression* node);
virtual void Visit(TupleExpression* node);
virtual void Visit(VariantExpression* node);
virtual void Visit(ReturnExpression* node);
virtual void Visit(TypeConstructorParameter* node);
virtual void Visit(TypeConstructor* node);
virtual void Visit(LambdaFunction* node);
virtual void Visit(ArrayExpression* node);
virtual void Visit(LoopControlExpression& node); // enum
// Name
virtual void Visit(PartitionName* node);
virtual void Visit(NameExpression* node);
virtual void Visit(TupleName* node);
virtual void Visit(VariantName* node);
virtual void Visit(AnnotatedName* node);
virtual void Visit(AnyName& node); // variant
// Type, typeclass, etc. -----------------
// Type
virtual void Visit(FunctionType* node);
virtual void Visit(TupleType* node);
virtual void Visit(VariantType* node);
virtual void Visit(TypeExpression* node);
virtual void Visit(AnyType& node); // variant
virtual void Visit(ExtendedScopedAnyType* node);
// Typeclass
virtual void Visit(ParametrizedTypeclass* node);
// Typeclass & Type
virtual void Visit(ParametrizedType* node);
// Identifiers, constants, etc. -----------------
virtual void Visit(AnyIdentifier* node); // std::string
virtual void Visit(FloatNumberLiteral* node);
virtual void Visit(NumberLiteral* node);
virtual void Visit(StringLiteral* node);
virtual void Visit(CharLiteral* node);
virtual void Visit(UnitLiteral* node);
virtual void Visit(BoolLiteral* node);
virtual void Visit(Literal& node); // variant
};
} // namespace interpreter

1
lang-parser Submodule

@ -0,0 +1 @@
Subproject commit ddb08e9b65123324800d1126d38764764363c0e5

1585
src/build_visitor.cpp Normal file

File diff suppressed because it is too large Load diff

1262
src/execute_visitor.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,218 @@
#include <iostream>
// for clangd
#include "../include/error_handling.hpp"
#include "../include/find_symbols_visitor.hpp"
namespace interpreter {
// Sources -----------------
// Namespaces, partitions -----------------
void FindSymbolsVisitor::Visit(Namespace* node) {
if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) {
// other type of error??
error_handling::HandleParsingError("Can't use const /var namespace inside const / var namespace",
node->base.start_position,
node->base.end_position);
}
namespace_visitor_.AddEnterNamespace(node->type, node->modifier, node, node->base);
Visitor::Visit(&node->scope);
namespace_visitor_.ExitNamespace();
}
// Definitions -----------------
// TODO: add imported symbols to symbol table (global info)
void FindSymbolsVisitor::Visit(ImportStatement* node) {
info::definition::Import info;
info.module_name = node->module_name;
info.symbols = node->symbols;
namespace_visitor_.AddImport(std::move(info), node->name);
}
void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) {
info::definition::Type info;
info::definition::AliasType alias_info;
alias_info.modifier = node->modifier;
alias_info.parameters = node->parameters;
alias_info.value.node = node->value.get();
alias_info.node = node;
info.type = std::move(alias_info);
node->type_id_ = namespace_visitor_.AddType(node->type, std::move(info), node->base);
Visitor::Visit(node->value.get()); // to visit all tree
}
void FindSymbolsVisitor::Visit(FunctionDeclaration* node) {
info::definition::FunctionDeclaration info;
info.parameters.resize(node->parameters.size());
for (size_t i = 0; i < node->parameters.size(); ++i) {
Visit(node->parameters[i].get());
info.parameters[i] = std::move(std::any_cast<info::definition::Parameter>(current_info_));
current_info_.reset();
}
info.argument_types.resize(node->type->types.size());
for (size_t i = 0; i < node->type->types.size(); ++i) {
info.argument_types[i] = &node->type->types[i];
}
info.node = node;
node->function_id_ = namespace_visitor_.AddFunctionDeclaration(node->name, std::move(info), node->base);
Visitor::Visit(node->type.get()); // to visit all tree
}
void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) {
info::definition::FunctionDefinition info;
auto definition = node->definition.get();
info.argument_names.resize(definition->arguments.size());
for (size_t i = 0; i < definition->arguments.size(); ++i) {
info.argument_names[i] = definition->arguments[i];
}
info.node = node;
node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info), node->base);
Visitor::Visit(definition); // to visit all tree
Visitor::Visit(node->value); // to visit all tree
}
void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
info::definition::Type info;
auto definition = node->definition.get();
info::definition::AnyType any_type_info;
Visit(definition->type.get());
any_type_info.type = std::move(std::any_cast<info::definition::Parameter>(current_info_));
current_info_.reset();
any_type_info.parameters.resize(definition->parameters.size());
for (size_t i = 0; i < definition->parameters.size(); ++i) {
Visit(definition->parameters[i].get());
any_type_info.parameters[i] = std::move(std::any_cast<info::definition::Parameter>(current_info_));
current_info_.reset();
}
any_type_info.node = node;
any_type_info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId();
any_type_info.modifier = node->modifier;
std::string type = any_type_info.type.type;
info.type = std::move(any_type_info);
node->type_id_ = namespace_visitor_.AddType(type, std::move(info), node->base);
auto maybe_graph_type_vertex = namespace_visitor_.GetTypeclassGraph()->GetTypeVertex(node->definition->type->graph_id_);
if (!maybe_graph_type_vertex.has_value()) {
error_handling::HandleInternalError("Type vertex in TypeclassGraph is not type vertex",
"FindSymbolsVisitor.FunctionDefinitionStatement",
&node->base);
}
maybe_graph_type_vertex.value()->type_id = node->type_id_;
// definition visited earlier
Visitor::Visit(node->value); // to visit all tree
}
void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
info::definition::AbstractType info;
Visit(node->type.get());
info.type = std::move(std::any_cast<info::definition::Parameter>(current_info_));
current_info_.reset();
info.modifier = node->modifier;
info.node = node;
std::string type = info.type.type;
node->type_id_ = namespace_visitor_.AddAbstractType(type, std::move(info), node->base);
}
void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
info::definition::Typeclass info;
auto definition = node->definition.get();
std::string& typeclass_name = definition->type.get()->type;
info.parameters.resize(definition->parameters.size());
for (size_t i = 0; i < definition->parameters.size(); ++i) {
Visit(definition->parameters[i].get());
info.parameters[i] = std::move(std::any_cast<info::definition::Parameter>(current_info_));
current_info_.reset();
}
for (size_t i = 0; i < node->requirements.size(); ++i) {
namespace_visitor_.AddEnterNamespace(typeclass_name, node->requirements[i].first, std::nullopt, node->base);
Visit(node->requirements[i].second.get());
namespace_visitor_.ExitNamespace();
}
info.node = node;
info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId();
node->typeclass_id_ = namespace_visitor_.AddTypeclass(typeclass_name, std::move(info), node->base);
// no need to visit definition->type, because it is typeclass
}
void FindSymbolsVisitor::Visit(PartitionStatement* node) {
node->executable_id_ = namespace_visitor_.AddPartition(node->name.path, node, node->base);
Visitor::Visit(node->value); // to visit all tree
}
// Definition parts
void FindSymbolsVisitor::Visit(AnyAnnotatedType* node) {
info::definition::Parameter info;
info.type = node->type;
info.typeclass_nodes.resize(node->typeclasses.size());
for (size_t i = 0; i < node->typeclasses.size(); ++i) {
info.typeclass_nodes[i] = node->typeclasses[i].get();
}
for (auto& typeclass : node->typeclasses) {
Visitor::Visit(typeclass.get()); // to visit all tree
}
info.node = node;
auto maybe_typeclass_graph_id = namespace_visitor_.GetGlobalInfo()->AddAnnotatedTypeToGraph(node); // definitions and declarations should be added latter
if (!maybe_typeclass_graph_id.has_value()) {
error_handling::HandleInternalError("Can't add annotated type to typeclass graph",
"FindSymbolsVisitor.AnyAnnotatedType",
&node->base);
}
node->graph_id_ = maybe_typeclass_graph_id.value();
current_info_ = std::move(info);
}
} // namespace interpreter

601
src/global_info.cpp Normal file
View file

@ -0,0 +1,601 @@
#include <variant>
// for clangd
#include "../include/global_info.hpp"
#include "../include/types.hpp"
#include "../include/error_handling.hpp"
namespace info {
void GlobalInfo::NamespaceVisitor::AddImport(definition::Import&& import_info,
const std::optional<std::string>& name) {
if (name.has_value()) {
global_info_.usages_[name.value()] = std::move(import_info);
} else {
global_info_.imports_.push_back(std::move(import_info));
}
}
void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name,
utils::ClassInternalsModifier modifier,
std::optional<interpreter::tokens::Namespace*> node,
const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(name).has_value()) {
error_handling::HandleNamesError("Can't define basic type namespace", base_node);
}
auto current_namespaces =
global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[namespace_stack_.back()]);
utils::IdType id = 0;
auto namespace_iter = current_namespaces->find(name);
if (namespace_iter == current_namespaces->end()) {
id = global_info_.namespaces_.size();
(*current_namespaces)[name] = id;
global_info_.namespaces_.emplace_back();
global_info_.namespaces_.back().modifier = modifier;
} else {
id = namespace_iter->second;
}
definition::Namespace* namespace_info = &global_info_.namespaces_[id];
if (!namespace_info->any_node.has_value()) { // ??
namespace_info->any_node = node;
}
namespace_info->parent_namespace = namespace_stack_.back();
namespace_info->type_name = name;
namespace_stack_.push_back(id);
current_path_.push_back(name);
}
void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name,
utils::ClassInternalsModifier modifier) {
for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) {
auto current_namespaces =
global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[i]);
auto namespace_iter = current_namespaces->find(name);
if (namespace_iter != current_namespaces->end()) {
namespace_stack_.push_back(namespace_iter->second);
current_path_.push_back(name);
return;
}
}
error_handling::HandleInternalError("Can't find namespace " + name,
"GlobalInfo.NamespaceVisitor.EnterNamespace",
std::nullopt);
}
void GlobalInfo::NamespaceVisitor::ExitNamespace() {
if (namespace_stack_.size() <= 1) {
error_handling::HandleInternalError("Can't exit from global namespace",
"GlobalInfo.NamespaceVisitor.ExitNamespace",
std::nullopt);
return;
}
namespace_stack_.pop_back();
current_path_.pop_back();
}
void GlobalInfo::NamespaceVisitor::ToGlobalNamespace() {
namespace_stack_.clear();
current_path_.clear();
namespace_stack_.push_back(global_info_.GlobalNamespaceId);
}
utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration(
const std::string& name,
definition::FunctionDeclaration&& function_declaration_info,
const interpreter::tokens::BaseNode& base_node) {
utils::IdType id = 0;
auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name);
if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) {
id = global_info_.functions_.size();
global_info_.namespaces_[namespace_stack_.back()].functions[name] = id;
global_info_.functions_.emplace_back();
global_info_.functions_.back().argument_count = function_declaration_info.argument_types.size(); // add return type
} else {
id = function_id_iter->second;
if (global_info_.functions_[id].argument_count != function_declaration_info.argument_types.size()) {
error_handling::HandleNamesError("Function declaration: not same argument count in function definition and declaration", base_node);
}
}
if (global_info_.functions_[id].declaration.has_value()) {
error_handling::HandleNamesError("Second function declaration", base_node);
}
global_info_.functions_[id].declaration = std::move(function_declaration_info);
return id;
}
utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(
const std::string& name,
definition::FunctionDefinition&& function_definition_info,
const interpreter::tokens::BaseNode& base_node) {
utils::IdType id = 0;
auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name);
if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) {
id = global_info_.functions_.size();
global_info_.namespaces_[namespace_stack_.back()].functions[name] = id;
global_info_.functions_.emplace_back();
global_info_.functions_.back().argument_count = function_definition_info.argument_names.size() + 1;
} else {
id = function_id_iter->second;
if (global_info_.functions_[id].argument_count != function_definition_info.argument_names.size() + 1) {
error_handling::HandleNamesError("Function definition: not same argument count in function definition and declaration", base_node);
}
}
if (global_info_.functions_[id].definition.has_value()) {
error_handling::HandleNamesError("Second function definition", base_node);
}
global_info_.functions_[id].definition = std::move(function_definition_info);
return id;
}
// TODO: internal types, etc.
// TODO: extended constructor names (point separated names)
utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
definition::Type&& type_info,
const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(type).has_value()) {
error_handling::HandleNamesError("Can't redefine basic type", base_node);
}
utils::IdType id = 0;
auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type);
if (type_id_iter == global_info_.namespaces_[namespace_stack_.back()].types.end()) {
id = global_info_.types_.size();
global_info_.namespaces_[namespace_stack_.back()].types[type] = id;
global_info_.types_.push_back(std::move(type_info));
} else {
error_handling::HandleNamesError("More then one type with the same name in namespace", base_node);
}
definition::Type& moved_type_info = global_info_.types_.back();
if (!std::holds_alternative<definition::AnyType>(moved_type_info.type)) {
error_handling::HandleInternalError("Not AnyType constructor search is not implemented yet",
"GlobalInfo.NamespaceVisitor.AddType",
&base_node);
}
definition::AnyType& any_type_info = std::get<definition::AnyType>(moved_type_info.type);
if (std::holds_alternative<std::unique_ptr<interpreter::tokens::VariantType>>(any_type_info.node->value)) {
interpreter::tokens::VariantType& variant_type_info = *std::get<std::unique_ptr<interpreter::tokens::VariantType>>(any_type_info.node->value);
for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) {
std::string constructor_name;
definition::Constructor constructor_info;
constructor_info.type_id = id;
constructor_info.order = i;
if (std::holds_alternative<interpreter::tokens::Constructor>(variant_type_info.constructors[i])) {
constructor_name = std::get<interpreter::tokens::Constructor>(variant_type_info.constructors[i]);
} else if (std::holds_alternative<
std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i])) {
constructor_info.constructor_tuple_node =
std::get<std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i]).get();
auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type;
if (maybe_constructor_name.has_value()) {
constructor_name = maybe_constructor_name.value();
} else {
constructor_name = type;
}
} else {
error_handling::HandleInternalError("Unexprected VariantType constructor node type",
"GlobalInfo.NamespaceVisitor.AddType",
&base_node);
}
constructor_info.name = constructor_name;
AddConstructor(constructor_name, std::move(constructor_info), base_node);
}
} else if (std::holds_alternative<std::unique_ptr<interpreter::tokens::TupleType>>(any_type_info.node->value)) {
definition::Constructor constructor_info;
constructor_info.type_id = id;
// constructor_info.order = std::nullopt;
constructor_info.name = type;
constructor_info.constructor_tuple_node = std::get<std::unique_ptr<interpreter::tokens::TupleType>>(any_type_info.node->value).get();
AddConstructor(type, std::move(constructor_info), base_node);
} else {
// TODO: constructors for function types (??), array types (??), ...
error_handling::HandleInternalError("Not VariantType constructor search is not implemented yet",
"GlobalInfo.NamespaceVisitor.AddType",
&base_node);
}
return id;
}
// TODO: link abstract type with let definitions
utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& abstract_type,
definition::AbstractType&& abstract_type_info,
const interpreter::tokens::BaseNode& base_node) {
// if (type::ToInternalType(abstract_type).has_value()) {
// error_handling::HandleNamesError("Can't redefine basic type as abstract type", base_node);
// }
if (FindAbstractType(abstract_type).has_value()) {
error_handling::HandleNamesError("More then one abstract type with the same name in namespace", base_node);
}
utils::IdType id = global_info_.abstract_types_.size();
global_info_.name_to_abstract_type_[abstract_type] = id;
global_info_.abstract_types_.push_back(std::move(abstract_type_info));
return id;
}
// TODO: which info needed ??
utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass,
definition::Typeclass&& typeclass_info,
const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(typeclass).has_value()) {
error_handling::HandleNamesError("Can't redefine basic type as typeclass", base_node);
}
if (FindTypeclass(typeclass).has_value()) {
error_handling::HandleNamesError("More then one typeclass with the same name", base_node);
}
utils::IdType id = global_info_.typeclasses_.size();
global_info_.name_to_typeclass_[typeclass] = id;
global_info_.typeclasses_.push_back(std::move(typeclass_info));
return id;
}
utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& constructor,
definition::Constructor&& constructor_info,
const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(constructor).has_value()) {
error_handling::HandleNamesError("Can't redefine basic type as constructor", base_node);
}
auto constructor_id_iter = global_info_.namespaces_[namespace_stack_.back()].constructors.find(constructor);
if (constructor_id_iter != global_info_.namespaces_[namespace_stack_.back()].constructors.end()) {
error_handling::HandleNamesError("More then one constructor with the same name in namespace", base_node);
}
utils::IdType id = global_info_.constructors_.size();
global_info_.namespaces_[namespace_stack_.back()].constructors[constructor] = id;
global_info_.constructors_.push_back(std::move(constructor_info));
return id;
}
utils::IdType GlobalInfo::NamespaceVisitor::AddPartition(const std::vector<std::string>& path,
interpreter::tokens::PartitionStatement* node,
const interpreter::tokens::BaseNode& base_node) {
PartitionInfo partition;
partition.path.reserve(current_path_.size() + path.size());
partition.path = current_path_;
for (auto& path_name : path) {
partition.path.push_back(path_name);
}
partition.node = node;
utils::IdType id = global_info_.partitions_.size();
global_info_.partitions_.push_back(partition);
if (!global_info_.partitions_trie_.Insert(partition.path, id)) {
error_handling::HandleNamesError("Partition with this name already exists", base_node);
}
return id;
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindNamespaceId(const std::optional<std::vector<std::string>>& path) {
return FindSomething<utils::IdType>(path,
[] (utils::IdType current_namespace) -> std::optional<utils::IdType> {
return current_namespace;
});
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindFunctionId(
const std::optional<std::vector<std::string>>& path,
const std::string& name) {
return FindSomething<utils::IdType>(path,
[name, this] (utils::IdType current_namespace) -> std::optional<utils::IdType> {
auto function_info_iter = global_info_.namespaces_[current_namespace].functions.find(name);
if (function_info_iter == global_info_.namespaces_[current_namespace].functions.end()) {
return std::nullopt;
}
return function_info_iter->second;
});
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindMethodId(
const std::optional<std::vector<std::string>>& path,
const std::string& type,
const std::string& name,
utils::IsConstModifier modifier) {
return GlobalInfo::NamespaceVisitor::FindSomething<utils::IdType>(path,
[type, name, modifier, this] (utils::IdType current_namespace) -> std::optional<utils::IdType> {
auto variable_namespace_iter =
(modifier == utils::IsConstModifier::Const
? global_info_.namespaces_[current_namespace].const_namespaces.find(type)
: global_info_.namespaces_[current_namespace].var_namespaces.find(type));
if (variable_namespace_iter ==
(modifier == utils::IsConstModifier::Const
? global_info_.namespaces_[current_namespace].const_namespaces.end()
: global_info_.namespaces_[current_namespace].var_namespaces.end())) {
return std::nullopt;
}
auto method_iter = global_info_.namespaces_[variable_namespace_iter->second].functions.find(name);
if (method_iter == global_info_.namespaces_[variable_namespace_iter->second].functions.end()) {
return std::nullopt;
}
return method_iter->second;
});
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindTypeId(
const std::optional<std::vector<std::string>>& path,
const std::string& type) {
return FindSomething<utils::IdType>(path,
[type, this] (utils::IdType current_namespace) -> std::optional<utils::IdType> {
auto type_info_iter = global_info_.namespaces_[current_namespace].types.find(type);
if (type_info_iter == global_info_.namespaces_[current_namespace].types.end()) {
return std::nullopt;
}
return type_info_iter->second;
});
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindLocalTypeId(const std::string& type) {
auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type);
if (type_id_iter != global_info_.namespaces_[namespace_stack_.back()].types.end()) {
return type_id_iter->second;
}
return std::nullopt;
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindAbstractTypeId(const std::string& abstract_type) {
auto abstract_type_id_iter = global_info_.name_to_abstract_type_.find(abstract_type);
if (abstract_type_id_iter != global_info_.name_to_abstract_type_.end()) {
return abstract_type_id_iter->second;
}
return std::nullopt;
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindTypeclassId(const std::string& typeclass) {
auto typeclass_id_iter = global_info_.name_to_typeclass_.find(typeclass);
if (typeclass_id_iter != global_info_.name_to_typeclass_.end()) {
return typeclass_id_iter->second;
}
return std::nullopt;
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindConstructorId(
const std::optional<std::vector<std::string>>& path,
const std::string& constructor) {
return FindSomething<utils::IdType>(path,
[constructor, this] (utils::IdType current_namespace) -> std::optional<utils::IdType> {
auto constructor_info_iter = global_info_.namespaces_[current_namespace].constructors.find(constructor);
if (constructor_info_iter == global_info_.namespaces_[current_namespace].constructors.end()) {
return std::nullopt;
}
return constructor_info_iter->second;
});
}
template<typename T>
std::optional<T> GlobalInfo::NamespaceVisitor::FindSomething(
const std::optional<std::vector<std::string>>& path,
std::function<std::optional<T>(utils::IdType)> search_func) {
for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) {
utils::IdType current_namespace = 0;
if (path.has_value()) {
auto maybe_namespace = FindNamespaceIn(namespace_stack_[i], path.value());
if (!maybe_namespace.has_value()) {
continue;
}
current_namespace = maybe_namespace.value();
} else {
current_namespace = namespace_stack_[i];
}
std::optional<T> result = search_func(current_namespace);
if (result.has_value()) {
return result.value();
}
}
return std::nullopt;
}
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindNamespaceIn(
utils::IdType current_namespace,
const std::vector<std::string>& path) {
utils::IdType next_namespace = current_namespace;
for (auto& name : path) {
auto next_namespace_iter = global_info_.namespaces_[next_namespace].namespaces.find(name);
if (next_namespace_iter == global_info_.namespaces_[next_namespace].namespaces.end()) {
return std::nullopt;
}
next_namespace = next_namespace_iter->second;
}
return next_namespace;
}
//
std::optional<definition::Namespace*> GlobalInfo::GetTypeNamespace(utils::IdType id,
utils::ClassInternalsModifier modifier) {
auto maybe_type_info = GetTypeInfo<definition::AnyType>(id);
if (!maybe_type_info.has_value()) {
error_handling::HandleInternalError("Only AnyType is supported now",
"GlobalInfo.GetTypeNamespace",
std::nullopt);
}
std::string& name = maybe_type_info.value()->type.type;
auto namespaces = ChooseNamespaces(modifier, &GetNamespaceInfo(maybe_type_info.value()->parent_namespace));
auto namespace_iter = namespaces->find(name);
return namespace_iter == namespaces->end() ? std::optional<definition::Namespace*>(std::nullopt) : &GetNamespaceInfo(namespace_iter->second);
}
std::unordered_map<std::string, utils::IdType>*
GlobalInfo::ChooseNamespaces(utils::ClassInternalsModifier modifier,
definition::Namespace* current_namespace) {
std::unordered_map<std::string, utils::IdType>* current_namespaces = nullptr;
switch (modifier) {
case utils::ClassInternalsModifier::Const:
current_namespaces = &current_namespace->const_namespaces;
break;
case utils::ClassInternalsModifier::Var:
current_namespaces = &current_namespace->var_namespaces;
break;
case utils::ClassInternalsModifier::Static:
current_namespaces = &current_namespace->namespaces;
break;
}
return current_namespaces;
}
std::optional<utils::IdType> GlobalInfo::AddTypeclassToGraph(utils::IdType typeclass) {
definition::Typeclass* typeclass_info = &GetTypeclassInfo(typeclass);
definition::Namespace* parent_namespace = &GetNamespaceInfo(typeclass_info->parent_namespace);
std::string name = typeclass_info->node->definition->type->type;
interpreter::tokens::BaseNode* base_node = &typeclass_info->node->base;
std::vector<std::string> dependencies;
std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>> function_declarations;
std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>> function_definitions;
for (auto& dependency_node : typeclass_info->node->definition->type->typeclasses) {
std::string dependency = dependency_node->typeclass;
if (dependency_node->parameters.size() > 0) {
error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet",
"GlobalInfo.AddTypeclassToGraph",
std::nullopt);
}
dependencies.push_back(dependency);
}
auto namespace_iter = parent_namespace->namespaces.find(name);
if (namespace_iter != parent_namespace->namespaces.end()) {
CollectFunctionInfo(namespace_iter->second,
utils::ClassInternalsModifier::Static,
function_declarations,
function_definitions);
}
auto const_namespace_iter = parent_namespace->const_namespaces.find(name);
if (const_namespace_iter != parent_namespace->const_namespaces.end()) {
CollectFunctionInfo(const_namespace_iter->second,
utils::ClassInternalsModifier::Const,
function_declarations,
function_definitions);
}
auto var_namespace_iter = parent_namespace->var_namespaces.find(name);
if (var_namespace_iter != parent_namespace->var_namespaces.end()) {
CollectFunctionInfo(var_namespace_iter->second,
utils::ClassInternalsModifier::Var,
function_declarations,
function_definitions);
}
return typeclass_graph_.AddVertex(name,
dependencies,
function_declarations,
function_definitions,
base_node,
TypeclassGraph::Modifier::Typeclass);
}
std::optional<utils::IdType> GlobalInfo::AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node) {
std::string name = node->type;
interpreter::tokens::BaseNode* base_node = &node->base;
std::vector<std::string> dependencies;
for (auto& dependency_node : node->typeclasses) {
std::string dependency = dependency_node->typeclass;
if (dependency_node->parameters.size() > 0) {
error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet",
"GlobalInfo.AddAnnotatedTypeToGraph",
&node->base);
}
dependencies.push_back(dependency);
}
return typeclass_graph_.AddVertex(name,
dependencies,
{},
{},
base_node,
TypeclassGraph::Modifier::Type);
}
void GlobalInfo::CollectFunctionInfo(
utils::IdType current_namespace,
utils::ClassInternalsModifier modifier,
std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions) {
for (auto& function : GetNamespaceInfo(current_namespace).functions) {
definition::Function function_info = GetFunctionInfo(function.second);
if (function_info.declaration.has_value()) {
function_declarations.push_back(
{function.first,
{modifier, function_info.declaration.value().node}});
}
if (function_info.definition.has_value()) {
function_definitions.push_back({function.first, function_info.definition.value().node});
}
}
}
} // namespace info

View file

@ -0,0 +1,218 @@
#include <bits/types/error_t.h>
#include <optional>
// for clangd
#include "../include/link_symbols_visitor.hpp"
#include "../include/error_handling.hpp"
#include "../include/types.hpp"
namespace interpreter {
// Namespaces, partitions -----------------
void LinkSymbolsVisitor::Visit(Namespace* node) {
// Visitor::Visit(&node->type); // not needed
std::optional<utils::IdType> maybe_type = namespace_visitor_.FindLocalTypeId(node->type);
std::optional<utils::IdType> maybe_typeclass;
if (namespace_visitor_.IsInGlobalNamespace()) {
maybe_typeclass = namespace_visitor_.FindTypeclassId(node->type);
}
if (maybe_type.has_value() && maybe_typeclass.has_value()) {
error_handling::HandleNamesError("Ambigious namespace name (typeclass or type)", node->base);
}
if (maybe_type.has_value()) {
node->link_type_id_ = maybe_type.value();
}
if (maybe_typeclass.has_value()) {
node->link_typeclass_id_ = maybe_typeclass.value();
if (!namespace_visitor_.IsInGlobalNamespace()) {
// other type of error??
error_handling::HandleParsingError("Can't use typeclass namespace in other namespace",
node->base.start_position,
node->base.end_position);
}
}
namespace_visitor_.EnterNamespace(node->type, node->modifier);
Visitor::Visit(&node->scope);
namespace_visitor_.ExitNamespace();
}
// Definitions -----------------
void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
Visitor::Visit(node->definition.get());
Visitor::Visit(node->value);
utils::IdType graph_id = node->definition->type->graph_id_;
AddTypeFunctionsToTypeclassGraph(node->type_id_,
graph_id,
utils::ClassInternalsModifier::Static,
node->base);
AddTypeFunctionsToTypeclassGraph(node->type_id_,
graph_id,
utils::ClassInternalsModifier::Const,
node->base);
AddTypeFunctionsToTypeclassGraph(node->type_id_,
graph_id,
utils::ClassInternalsModifier::Var,
node->base);
}
void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
Visitor::Visit(node->definition.get());
for (auto& function_requirement : node->requirements) {
namespace_visitor_.EnterNamespace(node->definition->type->type, function_requirement.first);
Visitor::Visit(function_requirement.second.get());
namespace_visitor_.ExitNamespace();
}
auto maybe_graph_id = global_info_.AddTypeclassToGraph(node->typeclass_id_);
if (!maybe_graph_id.has_value()) {
error_handling::HandleNamesError("Can't add typeclass to graph", node->base);
}
global_info_.GetTypeclassInfo(node->typeclass_id_).graph_id_ = maybe_graph_id.value();
}
// Type, typeclass, etc. -----------------
// Type
void LinkSymbolsVisitor::Visit(TypeExpression* node) {
std::vector<std::string> path;
path.reserve(node->path.size());
for (auto& path_type : node->path) {
path.push_back(path_type.type);
}
node->type_id_ = namespace_visitor_.FindTypeId(path, node->type.type);
node->constructor_id_ = namespace_visitor_.FindConstructorId(path, node->type.type);
// internal type
if (info::type::ToInternalType(node->type.type).has_value()) {
if (!node->path.empty()) {
error_handling::HandleNamesError("Internal type is not in namespace", node->base);
}
if (!node->type.parameters.empty()) {
error_handling::HandleNamesError("Can't parametrize internal type", node->base);
}
return;
}
if (!node->type_id_.has_value() && !node->constructor_id_.has_value()) {
// check made in typecheck visitor
return;
}
if (node->constructor_id_.has_value()) {
utils::IdType constructor_type_id = global_info_.GetConstructorInfo(node->constructor_id_.value()).type_id;
if (node->type_id_.has_value() && node->type_id_.value() != constructor_type_id) {
error_handling::HandleNamesError("Contructor and type with same name have different types", node->base);
}
node->type_id_ = constructor_type_id;
}
if (node->type_id_.has_value()) {
node->type.type_id_ = node->type_id_.value();
}
std::optional<info::definition::Namespace*> maybe_type_namespace = namespace_visitor_.FindNamespace(path);
if (maybe_type_namespace.has_value()) {
info::definition::Namespace* type_namespace = maybe_type_namespace.value();
for (ssize_t i = (ssize_t)node->path.size(); i >= 0; --i) {
info::definition::Namespace* parent_namespace = &global_info_.GetNamespaceInfo(type_namespace->parent_namespace);
auto type_iter = parent_namespace->types.find(type_namespace->type_name);
if (type_iter != parent_namespace->types.end()) {
node->path[i].type_id_ = type_iter->second;
}
type_namespace = parent_namespace;
}
}
}
// Typeclass
void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) {
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclassId(node->typeclass);
if (maybe_typeclass.has_value()) {
node->typeclass_id_ = maybe_typeclass.value();
} else {
error_handling::HandleNamesError("Typeclass not found", node->base);
}
if (node->parameters.size() > 0) {
error_handling::HandleNamesError("Parametrized typeclasses not implemented yet", node->base);
}
}
//
void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id,
utils::IdType graph_id,
utils::ClassInternalsModifier namespace_modifier,
const BaseNode& base_node) {
auto maybe_type_graph_info = typeclass_graph_.GetTypeVertex(graph_id);
if (!maybe_type_graph_info.has_value()) {
error_handling::HandleInternalError("Type in typeclass graph is not marked as type",
"LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph",
&base_node);
}
auto type_graph_info = maybe_type_graph_info.value();
auto maybe_namespace =
global_info_.GetTypeNamespace(type_id, namespace_modifier);
if (maybe_namespace.has_value()) {
for (auto& function : maybe_namespace.value()->functions) {
auto function_info = global_info_.GetFunctionInfo(function.second);
auto function_graph_iter = type_graph_info->functions.find(function.first);
if (function_graph_iter == type_graph_info->functions.end()) {
info::TypeclassGraph::FunctionInfo function_graph_info;
// can be found after graph calculation
if (function_info.declaration.has_value()) {
function_graph_info.declaration = function_info.declaration.value().node;
}
// can be found after graph calculation
if (function_info.definition.has_value()) {
function_graph_info.definition = function_info.definition.value().node;
function_graph_info.is_defined_in_owner = true;
}
function_graph_info.modifier = namespace_modifier;
type_graph_info->functions[function.first] = function_graph_info;
} else {
if (namespace_modifier != function_graph_iter->second.modifier) {
error_handling::HandleTypecheckError("Type function \"" + function.first + "\" has definitions / declarations with different modifiers (static / const /var)", base_node);
}
error_handling::HandleInternalError("This code should be unreachable",
"LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph",
&base_node);
}
}
}
}
} // namespace interpreter

85
src/main.cpp Normal file
View file

@ -0,0 +1,85 @@
#include <fstream>
#include <iostream>
#include <sstream>
// for clangd
#include "../include/parse_tree.hpp"
#include "../include/global_info.hpp"
#include "../include/interpreter_tree.hpp"
#include "../include/build_visitor.hpp"
#include "../include/print_visitor.hpp"
#include "../include/find_symbols_visitor.hpp"
#include "../include/link_symbols_visitor.hpp"
#include "../include/type_check_visitor.hpp"
#include "../include/typed_print_visitor.hpp"
#include "../include/execute_visitor.hpp"
#include "../include/error_handling.hpp"
int main(int argc, char** argv) { // TODO, only test version
if (argc < 2 || argc > 2) {
std::cout << "Wrong argument count (provide one argument - source file)\n";
return 0;
}
std::string filename = argv[1];
std::ifstream in;
in.open(filename); // TODO handle errors
std::stringstream source_stream;
source_stream << in.rdbuf();
in.close();
std::string source = source_stream.str();
parser::ParseTree parse_tree(source);
if (!parse_tree.IsProperlyParsed()) {
error_handling::HandleParsingError("There are some parsing errors in file", {0, 0}, {0, 0});
}
std::unique_ptr<interpreter::tokens::SourceFile> source_file =
std::make_unique<interpreter::tokens::SourceFile>();
info::GlobalInfo global_info;
info::ContextManager<info::type::Type, info::type::TypeManager> type_context_manager;
info::ContextManager<info::value::Value, info::value::ValueManager> context_manager;
interpreter::BuildVisitor build_visitor(parse_tree);
// interpreter::PrintVisitor print_visitor(std::cout);
interpreter::FindSymbolsVisitor find_symbols_visitor(global_info);
interpreter::LinkSymbolsVisitor link_symbols_visitor(global_info);
interpreter::TypeCheckVisitor type_check_visitor(global_info, type_context_manager);
// interpreter::TypedPrintVisitor typed_print_visitor(std::cout, type_context_manager);
build_visitor.VisitSourceFile(source_file.get());
// std::cout << "\n---------------------------------- Untyped -------------------------------------\n\n";
// print_visitor.VisitSourceFile(source_file.get());
find_symbols_visitor.VisitSourceFile(source_file.get());
link_symbols_visitor.VisitSourceFile(source_file.get());
type_check_visitor.VisitSourceFile(source_file.get());
std::optional<utils::IdType> maybe_main_partition_id = global_info.FindPartition({"main"});
if (!maybe_main_partition_id.has_value()) {
error_handling::HandleGeneralError("No main partition found");
}
const info::GlobalInfo::PartitionInfo& main_partition =
global_info.GetPartitionInfo(maybe_main_partition_id.value());
std::cout << "\n---------------------------------- Execution -------------------------------------\n\n";
interpreter::ExecuteVisitor execute_visitor(global_info,
type_context_manager,
context_manager);
execute_visitor.ExecutePartition(main_partition.node);
// std::cout << "\n---------------------------------- Typed -------------------------------------\n\n";
// typed_print_visitor.VisitSourceFile(source_file.get());
}

746
src/print_visitor.cpp Normal file
View file

@ -0,0 +1,746 @@
// for clangd
#include "../include/print_visitor.hpp"
namespace interpreter {
// Sources -----------------
void PrintVisitor::Visit(SourceFile* node) {
out_ << "[SourceFile] (\n\n";
for (auto& statement : node->statements) {
Visitor::Visit(statement);
}
out_ << "\n)\n";
}
// Namespaces, partitions -----------------
void PrintVisitor::Visit(NamespaceSources* node) {
out_ << "[NamespaceSources](\n";
for (auto& statement : node->statements) {
Visitor::Visit(statement);
}
out_ << ")\n";
}
void PrintVisitor::Visit(Namespace* node) {
out_ << "[Namespace] ";
switch (node->modifier) {
case utils::ClassInternalsModifier::Const:
out_ << "const ";
break;
case utils::ClassInternalsModifier::Var:
out_ << "var ";
break;
case utils::ClassInternalsModifier::Static:
break;
}
Visit(&node->type);
out_ << "{\n";
Visit(&node->scope);
out_ << "}\n";
}
// Definitions -----------------
void PrintVisitor::Visit(ImportStatement* node) {
if (node->name.has_value()) {
out_ << "[Use " << node->name.value() << "] = ";
}
out_ << "[Import " << node->module_name << "]";
if (!node->symbols.empty()) {
out_ << " (\n";
for (auto& symbol : node->symbols) {
Visit(&symbol);
out_ << '\n';
}
out_ << ')';
}
out_ << '\n';
}
void PrintVisitor::Visit(AliasDefinitionStatement* node) {
out_ << "[Alias ";
switch (node->modifier) {
case utils::AliasModifier::Alias:
out_ << "alias";
break;
case utils::AliasModifier::Type:
out_ << "type";
break;
case utils::AliasModifier::Let:
out_ << "let";
break;
}
out_ << ' ';
Visit(&node->type);
out_ << "] = (";
Visit(node->value.get());
out_ << ")\n";
}
void PrintVisitor::Visit(VariableDefinitionStatement* node) {
out_ << "[Variable ";
switch (node->modifier) {
case utils::IsConstModifier::Const:
out_ << "const";
break;
case utils::IsConstModifier::Var:
out_ << "var";
break;
}
out_ << ' ';
Visitor::Visit(node->name);
out_ << "] = (";
Visitor::Visit(node->value);
out_ << ")\n";
}
void PrintVisitor::Visit(FunctionDeclaration* node) {
out_ << "[FunctionDeclaration ";
if (node->is_in_interface) {
out_ << "interface ";
}
Visit(&node->name);
out_ << "] (";
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
out_ << ") : (";
Visit(node->type.get());
out_ << ")\n";
}
void PrintVisitor::Visit(FunctionDefinitionStatement* node) {
out_ << "[Function] (";
Visit(node->definition.get());
out_ << ") = (";
Visitor::Visit(node->value);
out_ << ")\n";
}
void PrintVisitor::Visit(TypeDefinitionStatement* node) {
out_ << "[Type ";
switch (node->modifier) {
case utils::ClassModifier::Struct:
out_ << "struct";
break;
case utils::ClassModifier::Class:
out_ << "class";
break;
}
if (node->is_in_interface) {
out_ << " interface";
}
out_ << "] (";
Visit(node->definition.get());
out_ << ") = (";
Visitor::Visit(node->value);
out_ << ")\n";
}
void PrintVisitor::Visit(AbstractTypeDefinitionStatement* node) {
out_ << "[AbstractType ";
switch (node->modifier) {
case utils::AbstractTypeModifier::Basic:
out_ << "basic";
break;
case utils::AbstractTypeModifier::Abstract:
out_ << "abstract";
break;
}
out_ << "] (";
Visit(node->type.get());
out_ << ")\n";
}
void PrintVisitor::Visit(TypeclassDefinitionStatement* node) {
out_ << "[Typeclass] (";
Visit(node->definition.get());
if (!node->requirements.empty()) {
out_ << ") : (\n";
}
for (auto& requirement : node->requirements) {
out_ << "& ";
switch (requirement.first) {
case utils::ClassInternalsModifier::Const:
out_ << "const ";
break;
case utils::ClassInternalsModifier::Var:
out_ << "var ";
break;
case utils::ClassInternalsModifier::Static:
break;
}
Visit(requirement.second.get());
out_ << "\n";
}
out_ << ")\n";
}
void PrintVisitor::Visit(PartitionStatement* node) {
out_ << "[Partition ";
switch (node->modifier) {
case utils::PartitionModifier::Exec:
out_ << "exec ";
break;
case utils::PartitionModifier::Test:
out_ << "test ";
break;
}
Visit(&node->name);
out_ << "] = (";
Visitor::Visit(node->value);
out_ << ")\n";
}
// Definition parts
void PrintVisitor::Visit(FunctionDefinition* node) {
out_ << "[FunctionDefinition ";
Visit(&node->name);
out_ << "]";
if (!node->arguments.empty()) {
out_ << " : (";
for (auto& argument : node->arguments) {
Visit(&argument);
}
out_ << ')';
}
out_ << ' ';
}
void PrintVisitor::Visit(TypeDefinition* node) {
out_ << "[TypeDefinition] (";
Visit(node->type.get());
out_ << ')';
if (!node->parameters.empty()) {
out_ << '(';
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
out_ << ')';
}
out_ << ' ';
}
void PrintVisitor::Visit(AnyAnnotatedType* node) {
out_ << "[Annotated (Abstract) Type ";
Visit(&node->type);
out_ << ']';
if (!node->typeclasses.empty()) {
out_ << " (";
for (auto& typeclass : node->typeclasses) {
Visit(typeclass.get());
}
out_ << ')';
}
out_ << ' ';
}
// Flow control -----------------
void PrintVisitor::Visit(TypeConstructorPatternParameter* node) {
out_ << "[TypeConstructorPatternParameter ";
if (node->name.has_value()) {
Visit(&node->name.value());
out_ << " = ";
}
Visitor::Visit(node->value);
out_ << "]";
}
void PrintVisitor::Visit(TypeConstructorPattern* node) {
out_ << "[TypeConstructorPattern ";
Visit(node->constructor.get());
out_ << "]\n(";
bool is_first = true;
for (auto& parameter : node->parameters) {
if (!is_first) {
out_ << ")\n";
}
is_first = false;
out_ << '(';
Visit(&parameter);
}
out_ << ")\n";
}
void PrintVisitor::Visit(MatchCase* node) {
out_ << "[MatchCase | ";
Visitor::Visit(node->value);
if (node->condition.has_value()) {
out_ << " ? ";
Visitor::Visit(node->condition.value());
}
if (node->statement.has_value()) {
out_ << " -> ";
Visitor::Visit(node->statement.value());
}
out_ << "]\n";
}
void PrintVisitor::Visit(Match* node) {
out_ << "[Match";
if (node->is_consuming_value) {
out_ << " <- ";
}
out_ << "] (";
Visitor::Visit(node->value);
out_ << ") [with] (\n";
for (auto& match_case : node->matches) {
Visit(&match_case);
}
out_ << ")\n";
}
void PrintVisitor::Visit(Condition* node) {
out_ << "[If] (";
Visitor::Visit(node->conditions[0]);
out_ << ") [then] (\n";
Visitor::Visit(node->statements[0]);
out_ << ')';
for (size_t i = 1; i < node->conditions.size(); ++i) {
out_ << " [elif] (";
Visitor::Visit(node->conditions[i]);
out_ << ") [then] (\n";
Visitor::Visit(node->statements[i]);
out_ << ')';
}
if (node->statements.size() > node->conditions.size()) {
out_ << " [else] (\n";
Visitor::Visit(node->statements[node->conditions.size()]);
out_ << ')';
}
out_ << '\n';
}
void PrintVisitor::Visit(DoWhileLoop* node) {
out_ << "[Do] (\n";
Visitor::Visit(node->statement);
out_ << ") [while] (";
Visitor::Visit(node->condition);
out_ << ")\n";
}
void PrintVisitor::Visit(WhileLoop* node) {
out_ << "[While] (";
Visitor::Visit(node->condition);
out_ << ") [do] (\n";
Visitor::Visit(node->statement);
out_ << ")\n";
}
void PrintVisitor::Visit(ForLoop* node) {
out_ << "[For ";
switch (node->variable_modifier) {
case utils::IsConstModifier::Const:
break;
case utils::IsConstModifier::Var:
out_ << "var";
break;
}
out_ << "] (";
Visitor::Visit(node->variable);
out_ << ") [in] (";
Visitor::Visit(node->interval);
out_ << ") [do] (\n";
Visitor::Visit(node->statement);
out_ << ")\n";
}
void PrintVisitor::Visit(LoopLoop* node) {
out_ << "[Loop] (\n";
Visitor::Visit(node->statement);
out_ << ")\n";
}
// Statements, expressions, blocks, etc. -----------------
void PrintVisitor::Visit(Block* node) {
out_ << "[Block] {\n";
for (auto& statement : node->statements) {
Visitor::Visit(statement);
}
out_ << "}\n";
}
void PrintVisitor::Visit(ScopedStatement* node) {
out_ << "[Scoped] ( ";
Visitor::Visit(node->statement);
out_ << ")\n";
}
void PrintVisitor::Visit(LoopControlExpression& node) { // enum
switch (node) {
case LoopControlExpression::Break:
out_ << "[Break]\n";
break;
case LoopControlExpression::Continue:
out_ << "[Continue]\n";
break;
}
}
// Operators
void PrintVisitor::Visit(ReferenceExpression* node) {
out_ << "[ReferenceExpression ";
switch (node->reference) {
case utils::ReferenceModifier::Reference:
out_ << '^';
break;
case utils::ReferenceModifier::UniqueReference:
out_ << '@';
break;
case utils::ReferenceModifier::Dereference:
out_ << '~';
break;
}
out_ << "] (";
Visit(node->expression.get());
out_ << ')';
}
void PrintVisitor::Visit(AccessExpression* node) {
out_ << "[AccessExpression] (";
Visit(node->name.get());
out_ << ") ` (";
Visitor::Visit(node->id);
out_ << ')';
}
// Other Expressions
void PrintVisitor::Visit(FunctionCallExpression* node) {
out_ << "[FunctionCall ";
if (node->is_binary_operator_expression) {
out_ << "(binary operation) ";
}
if (node->prefix.has_value()) {
out_ << '(';
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
Visit(std::get<std::unique_ptr<TypeExpression>>(node->prefix.value()).get());
} else {
// error
}
out_ << ").";
}
Visit(&node->name);
out_ << "] (";
bool is_first = true;
for (auto& parameter : node->parameters) {
if (!is_first) {
out_ << ", ";
}
is_first = false;
Visit(parameter.get());
}
out_ << ") : (";
is_first = true;
for (auto& argument : node->arguments) {
if (!is_first) {
out_ << ", ";
}
is_first = false;
Visitor::Visit(argument);
}
out_ << ")";
}
void PrintVisitor::Visit(TupleExpression* node) {
out_ << "[TupleExpression] (";
for (auto& expression : node->expressions) {
out_ << "&";
Visitor::Visit(expression);
}
out_ << ")";
}
void PrintVisitor::Visit(VariantExpression* node) {
out_ << "[VariantExpression] (";
for (auto& expression : node->expressions) {
out_ << "|";
Visitor::Visit(expression);
}
out_ << ")";
}
void PrintVisitor::Visit(ReturnExpression* node) {
if (node->is_from_definition) {
out_ << "[Return] (";
} else {
out_ << "[Bring] (";
}
Visitor::Visit(node->expression);
out_ << ")\n";
}
void PrintVisitor::Visit(TypeConstructorParameter* node) {
out_ << "[TypeConstructorParameter ";
if (node->name.has_value()) {
Visit(&node->name.value());
switch (node->asignment_modifier.value()) {
case utils::AssignmentModifier::Assign:
out_ << " = ";
break;
case utils::AssignmentModifier::Move:
out_ << " <- ";
break;
}
}
Visitor::Visit(node->value);
out_ << "]";
}
void PrintVisitor::Visit(TypeConstructor* node) {
out_ << "[TypeConstructor ";
Visit(node->constructor.get());
out_ << "]\n(";
bool is_first = true;
for (auto& parameter : node->parameters) {
if (!is_first) {
out_ << ")\n";
}
is_first = false;
out_ << '(';
Visit(&parameter);
}
out_ << ")\n";
}
void PrintVisitor::Visit(LambdaFunction* node) {
out_ << "[LambdaFunction] (";
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
if (!node->parameters.empty()) {
out_ << ") : (";
}
for (auto& argument : node->arguments) {
Visit(&argument);
}
out_ << ") -> (\n";
Visitor::Visit(node->expression);
out_ << ")\n";
}
void PrintVisitor::Visit(ArrayExpression* node) {
out_ << "[ArrayExpression] ( ,";
for (auto& element : node->elements) {
Visitor::Visit(element);
out_ << " ,";
}
out_ << ")";
}
// Name
void PrintVisitor::Visit(PartitionName* node) {
out_ << "[PartitionName] (";
for (size_t i = 0; i < node->path.size(); ++i) {
Visit(&node->path[i]);
if (i + 1 < node->path.size()) {
out_ << "::";
}
}
out_ << ')';
}
void PrintVisitor::Visit(NameExpression* node) {
out_ << "[NameExpression] (";
for (size_t i = 0; i < node->names.size(); ++i) {
Visit(&node->names[i]);
if (i + 1 < node->names.size()) {
out_ << "::";
}
}
out_ << ')';
}
void PrintVisitor::Visit(TupleName* node) {
out_ << "[TupleName] (";
for (auto& name : node->names) {
out_ << "& ";
Visitor::Visit(name);
}
out_ << ')';
}
void PrintVisitor::Visit(VariantName* node) {
out_ << "[VariantName] (";
for (auto& name : node->names) {
out_ << "| ";
Visitor::Visit(name);
}
out_ << ')';
}
void PrintVisitor::Visit(AnnotatedName* node) {
out_ << "[AnnotatedName ";
Visit(&node->name);
out_ << ']';
if (node->type.has_value()) {
out_ << " : (";
Visitor::Visit(node->type.value());
out_ << ')';
}
}
// Type, typeclass, etc. -----------------
// Type
void PrintVisitor::Visit(FunctionType* node) {
out_ << "[FunctionType] (";
bool is_first = true;
for (auto& type : node->types) {
if (!is_first || node->types.size() == 1) {
out_ << " -> ";
}
is_first = false;
Visitor::Visit(type);
}
out_ << ')';
}
void PrintVisitor::Visit(TupleType* node) {
out_ << "[TupleType ";
if (node->type.has_value()) {
Visit(&node->type.value());
}
out_ << "] (";
for (auto& entity : node->entities) {
out_ << "& ";
if (entity.first.has_value()) {
Visit(&entity.first.value());
out_ << " : ";
}
Visit(entity.second.get());
}
out_ << ')';
}
void PrintVisitor::Visit(VariantType* node) {
out_ << "[VariantType ";
if (node->type.has_value()) {
Visit(&node->type.value());
}
out_ << "] (";
for (auto& constructor : node->constructors) {
out_ << "| ";
if (std::holds_alternative<Constructor>(constructor)) {
Visit(&std::get<Constructor>(constructor));
} else if (std::holds_alternative<std::unique_ptr<TupleType>>(constructor)) {
Visit(std::get<std::unique_ptr<TupleType>>(constructor).get());
} else {
// error
}
}
out_ << ')';
}
void PrintVisitor::Visit(TypeExpression* node) {
out_ << "[TypeExpression ";
if (node->array_size.has_value()) {
out_ << "[array size: " << node->array_size.value() << ']';
}
out_ << "] (";
for (auto& type : node->path) {
Visit(&type);
out_ << "::";
}
Visit(&node->type);
out_ << ')';
}
void PrintVisitor::Visit(ExtendedScopedAnyType* node) {
out_ << "[ExtendedScopedAnyType ";
for (auto& reference : node->references) {
switch (reference) {
case utils::ReferenceModifier::Reference:
out_ << '^';
break;
case utils::ReferenceModifier::UniqueReference:
out_ << '@';
break;
case utils::ReferenceModifier::Dereference:
out_ << '~';
break;
}
}
out_ << "] (";
Visitor::Visit(node->type);
out_ << ')';
}
// Typeclass
void PrintVisitor::Visit(ParametrizedTypeclass* node) {
out_ << "[ParametrizedTypeclass] (";
Visit(&node->typeclass);
for (auto& parameter : node->parameters) {
out_ << ' ';
Visit(parameter.get());
}
out_ << ')';
}
// Typeclass & Type -----------------
void PrintVisitor::Visit(ParametrizedType* node) {
out_ << "[ParametrizedType] (";
Visit(&node->type);
for (auto& parameter : node->parameters) {
out_ << ' ';
Visit(parameter.get());
}
out_ << ')';
}
// Identifiers, constants, etc. -----------------
void PrintVisitor::Visit(std::string* node) { // std::string
out_ << "[Identifier " << *node << "] ";
}
void PrintVisitor::Visit(FloatNumberLiteral* node) {
out_ << "[FloatNumber " << node->value << "] ";
}
void PrintVisitor::Visit(NumberLiteral* node) {
out_ << "[Number " << node->value << "] ";
}
void PrintVisitor::Visit(StringLiteral* node) {
out_ << "[String " << node->value << "] ";
}
void PrintVisitor::Visit(CharLiteral* node) {
out_ << "[Char " << node->value << "] ";
}
void PrintVisitor::Visit(UnitLiteral*) {
out_ << "[Unit ()] ";
}
void PrintVisitor::Visit(BoolLiteral* node) {
out_ << "[Bool " << (node->value ? "true" : "false") << "] ";
}
} // namespace interpreter

1685
src/type_check_visitor.cpp Normal file

File diff suppressed because it is too large Load diff

162
src/typeclass_graph.cpp Normal file
View file

@ -0,0 +1,162 @@
// for clangd
#include "../include/typeclass_graph.hpp"
#include "../include/error_handling.hpp"
namespace info {
utils::IdType TypeclassGraph::AddVertex(
const std::string& name,
const std::vector<std::string>& dependencies, // TODO: parameters
const std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions,
interpreter::tokens::BaseNode* base_node,
Modifier modifier) {
if (name_to_typeclass_.count(name) != 0) {
error_handling::HandleTypecheckError("Typeclass \"" + name + "\" already defined (other type / typeclass can't have this name)", *base_node);
}
if (modifier == Modifier::Typeclass) {
for (auto& method : function_declarations) {
if (method_to_vertex_.count(method.first) != 0) {
error_handling::HandleTypecheckError("Typeclass \"" + name + "\" method \"" + method.first + "\" already declaret in another typeclass", *base_node);
}
}
}
is_calculated_ = false;
utils::IdType id = verticles_.size();
verticles_.emplace_back();
Vertex& vertex = verticles_.back();
vertex.name = name;
vertex.base_node = base_node;
vertex.modifier = modifier;
for (auto& dependency : dependencies) {
vertex.dependencies.insert(dependency);
}
for (auto& method : function_declarations) {
FunctionInfo function_info;
function_info.modifier = method.second.first;
function_info.declaration = method.second.second;
vertex.functions[method.first] = function_info;
if (modifier == Modifier::Typeclass) {
method_to_vertex_[method.first] = id;
}
}
if (modifier == Modifier::Typeclass) {
name_to_typeclass_[name] = id;
}
for (auto& method : function_definitions) {
FunctionInfo& function_info = vertex.functions[method.first];
function_info.definition = method.second;
function_info.is_defined_in_owner = true;
}
return id;
}
std::optional<utils::IdType> TypeclassGraph::FindFunctionTypeclass(const std::string& name) {
auto function_iter = method_to_vertex_.find(name);
if (function_iter == method_to_vertex_.end()) {
return std::nullopt;
}
return function_iter->second;
}
std::optional<TypeclassGraph::FunctionInfo*> TypeclassGraph::GetFunctionInfo(const std::string& name,
std::optional<utils::IdType> vertex_id) {
if (vertex_id.has_value()) {
auto function_info_iter = verticles_[vertex_id.value()].functions.find(name);
return function_info_iter !=
verticles_[vertex_id.value()].functions.end()
? std::optional<TypeclassGraph::FunctionInfo*>(&function_info_iter->second)
: std::nullopt;
}
auto maybe_function_typeclass_id = FindFunctionTypeclass(name);
if (!maybe_function_typeclass_id.has_value()) {
return std::nullopt;
}
return &verticles_[maybe_function_typeclass_id.value()].functions[name];
}
std::unordered_set<utils::IdType> TypeclassGraph::GetDependenciesSet(utils::IdType id) {
std::unordered_set<utils::IdType> dependencies;
dependencies.reserve(verticles_.at(id).dependencies.size());
for (auto& dependency : verticles_[id].dependencies) {
dependencies.insert(name_to_typeclass_[dependency]);
}
return dependencies;
}
std::vector<utils::IdType> TypeclassGraph::GetDependenciesVector(utils::IdType id) {
std::vector<utils::IdType> dependencies;
dependencies.reserve(verticles_.at(id).dependencies.size());
for (auto& dependency : verticles_[id].dependencies) {
dependencies.push_back(name_to_typeclass_[dependency]);
}
return dependencies;
}
void TypeclassGraph::CalculateGraph() {
if (is_calculated_) {
return;
}
std::vector<std::vector<size_t>> edges(verticles_.size());
for (size_t i = 0; i < verticles_.size(); ++i) {
edges[i].reserve(verticles_[i].dependencies.size());
for (auto& dependency : verticles_[i].dependencies) {
auto dependency_iter = name_to_typeclass_.find(dependency);
if (dependency_iter == name_to_typeclass_.end()) {
error_handling::HandleTypecheckError("Dependency typeclass \"" + dependency + "\" not found", *verticles_[i].base_node);
}
edges[i].push_back(dependency_iter->second);
}
}
std::vector<size_t> sorted_verticles = utils::BackTopSort(edges);
// std::reverse(sorted_verticles.begin(), sorted_verticles.end());
for (auto& id : sorted_verticles) {
for (auto& dependency : verticles_[id].dependencies) {
for (auto& method : verticles_[name_to_typeclass_[dependency]].functions) {
auto function_iter = verticles_[id].functions.find(method.first);
if (function_iter == verticles_[id].functions.end()) {
verticles_[id].functions[method.first] = method.second;
} else {
if (!function_iter->second.definition.has_value()) {
function_iter->second.definition = method.second.definition;
} else {
if (!function_iter->second.is_defined_in_owner) {
error_handling::HandleTypecheckError("Method \"" + method.first + "\" defined in more then one dependency of type / typeclass \"" + verticles_[id].name + "\"", *verticles_[id].base_node);
}
}
}
}
for (auto& inherited_dependency : verticles_[name_to_typeclass_[dependency]].dependencies) {
verticles_[id].dependencies.insert(inherited_dependency);
}
}
}
is_calculated_ = true;
}
} // namespace info

1059
src/typed_print_visitor.cpp Normal file

File diff suppressed because it is too large Load diff

588
src/types.cpp Normal file
View file

@ -0,0 +1,588 @@
// for clangd
#include "../include/types.hpp"
#include <variant>
namespace info::type {
std::optional<utils::IdType> AbstractType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
auto type_iter = context.find(typeclass_graph_.GetVertex(graph_id_).name);
if (type_iter != context.end()) {
return type_iter->second;
}
return std::nullopt;
}
bool AbstractType::Same(const AbstractType& type) const {
return graph_id_ == type.graph_id_;
}
bool AbstractType::operator<(const AbstractType& type) const { // TODO: cache DependenciesSet
return typeclass_graph_.GetDependenciesSet(graph_id_).count(type.graph_id_) != 0 || graph_id_ == type.graph_id_;
}
bool AbstractType::operator>(const AbstractType& type) const {
return type < *this;
}
std::optional<utils::IdType> AbstractType::GetFieldType(const std::string&,
const std::unordered_set<utils::IdType>&) const {
return std::nullopt;
}
//
std::optional<utils::IdType> DefinedType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool DefinedType::Same(const DefinedType& type) const {
return type_id_ == type.type_id_
&& type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_));
}
bool DefinedType::operator<(const DefinedType& type) const {
return type_id_ == type.type_id_
&& *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_);
}
bool DefinedType::operator>(const DefinedType& type) const {
return type < *this;
}
std::optional<utils::IdType> DefinedType::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const {
if (class_modifier_ == utils::ClassModifier::Struct || type_namespaces.count(type_id_) != 0) {
return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces);
}
return std::nullopt;
}
//
std::optional<utils::IdType> TupleType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < fields_.size(); ++i) {
std::optional<utils::IdType> maybe_field_replacement = type_manager_->GetAnyValue(fields_[i].second)->InContext(context);
if (maybe_field_replacement.has_value()) {
fields_[i].second = maybe_field_replacement.value();
}
}
return std::nullopt;
}
bool TupleType::Same(const TupleType& type) const {
if (fields_.size() != type.fields_.size()) {
return false;
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (!type_manager_->GetAnyValue(fields_[i].second)->Same(*type_manager_->GetAnyValue(type.fields_[i].second))) {
return false;
}
}
return true;
}
bool TupleType::operator<(const TupleType& type) const {
if (fields_.size() != type.fields_.size()) {
return false;
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (!(*type_manager_->GetAnyValue(fields_[i].second) < *type_manager_->GetAnyValue(type.fields_[i].second))) {
return false;
}
}
return true;
}
bool TupleType::operator>(const TupleType& type) const {
return type < *this;
}
std::optional<utils::IdType> TupleType::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>&) const {
for (size_t i = 0; i < fields_.size(); ++i) { // TODO: optimize??
if (fields_[i].first.has_value() && fields_[i].first.value() == name) {
return fields_[i].second;
}
}
return std::nullopt;
}
std::string TupleType::ToString() {
std::string result;
result += "(";
for (auto& field : fields_) {
result += "& ";
result += type_manager_->GetAnyValue(field.second)->ToString();
}
result += ")";
return result;
}
//
std::optional<utils::IdType> VariantType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < constructors_.size(); ++i) {
constructors_[i].InContext(context);
}
return std::nullopt;
}
bool VariantType::Same(const VariantType& type) const {
if (constructors_.size() != type.constructors_.size()) {
return false;
}
for (size_t i = 0; i < constructors_.size(); ++i) {
if (!constructors_[i].Same(constructors_[i])) {
return false;
}
}
return true;
}
bool VariantType::operator<(const VariantType& type) const {
if (constructors_.size() != type.constructors_.size()) {
return false;
}
for (size_t i = 0; i < constructors_.size(); ++i) {
if (!(constructors_[i] < constructors_[i])) {
return false;
}
}
return true;
}
bool VariantType::operator>(const VariantType& type) const {
return type < *this;
}
std::optional<utils::IdType> VariantType::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const {
if (current_constructor_.has_value()) {
return constructors_.at(current_constructor_.value()).GetFieldType(name, type_namespaces);
}
return std::nullopt;
}
std::string VariantType::ToString() {
std::string result;
result += "(";
for (auto& constructor : constructors_) {
result += "& ";
result += constructor.ToString();
}
result += ")";
return result;
}
//
std::optional<utils::IdType> OptionalType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool OptionalType::Same(const OptionalType& type) const {
return type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_));
}
bool OptionalType::operator<(const OptionalType& type) const {
return *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_);
}
bool OptionalType::operator>(const OptionalType& type) const {
return type < *this;
}
std::optional<utils::IdType> OptionalType::GetFieldType(const std::string&,
const std::unordered_set<utils::IdType>&) const {
return std::nullopt;
}
std::string OptionalType::ToString() {
return "Optional " + type_manager_->GetAnyValue(type_)->ToString();
}
//
std::optional<utils::IdType> ReferenceToType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool ReferenceToType::Same(const ReferenceToType& type) const {
return references_ == type.references_ && type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_));
}
bool ReferenceToType::operator<(const ReferenceToType& type) const {
return references_ == type.references_ && *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_);
}
bool ReferenceToType::operator>(const ReferenceToType& type) const {
return type < *this;
}
std::optional<utils::IdType> ReferenceToType::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const {
return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces);
}
std::string ReferenceToType::ToString() {
std::string result;
for (auto& reference : references_) {
switch (reference) {
case utils::ReferenceModifier::Dereference:
result += '~';
break;
case utils::ReferenceModifier::Reference:
result += '^';
break;
case utils::ReferenceModifier::UniqueReference:
result += '@';
break;
}
}
result += type_manager_->GetAnyValue(type_)->ToString();
return result;
}
//
std::optional<utils::IdType> FunctionType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < argument_types_.size(); ++i) {
std::optional<utils::IdType> maybe_argument_type_replacement =
type_manager_->GetAnyValue(argument_types_[i])->InContext(context);
if (maybe_argument_type_replacement.has_value()) {
argument_types_[i] = maybe_argument_type_replacement.value();
}
}
return std::nullopt;
}
bool FunctionType::Same(const FunctionType& type) const {
if (argument_types_.size() != type.argument_types_.size()) {
return false;
}
for (size_t i = 0; i < argument_types_.size(); ++i) {
if (!type_manager_->GetAnyValue(argument_types_[i])->Same(*type_manager_->GetAnyValue(type.argument_types_[i]))) {
return false;
}
}
return true;
}
bool FunctionType::operator<(const FunctionType& type) const {
if (argument_types_.size() != type.argument_types_.size()) {
return false;
}
for (size_t i = 0; i < argument_types_.size(); ++i) {
if (!(*type_manager_->GetAnyValue(argument_types_[i]) < *type_manager_->GetAnyValue(type.argument_types_[i]))) {
return false;
}
}
return true;
}
bool FunctionType::operator>(const FunctionType& type) const {
return type < *this;
}
std::optional<utils::IdType> FunctionType::GetFieldType(const std::string&,
const std::unordered_set<utils::IdType>&) const {
return std::nullopt;
}
std::string FunctionType::ToString() {
std::string result;
result += "(";
bool is_first_argument = true;
for (auto& argument_type : argument_types_) {
if (is_first_argument) {
is_first_argument = false;
} else {
result += " -> ";
}
result += type_manager_->GetAnyValue(argument_type)->ToString();
}
result += " -> " + type_manager_->GetAnyValue(return_type_)->ToString() + ")";
return result;
}
//
std::optional<utils::IdType> ArrayType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_elements_type_replacement =
type_manager_->GetAnyValue(elements_type_)->InContext(context);
if (maybe_elements_type_replacement.has_value()) {
elements_type_ = maybe_elements_type_replacement.value();
}
return std::nullopt;
}
bool ArrayType::Same(const ArrayType& type) const {
return size_ == type.size_ && type_manager_->GetAnyValue(elements_type_)->Same(*type_manager_->GetAnyValue(type.elements_type_));
}
bool ArrayType::operator<(const ArrayType& type) const {
return size_ == type.size_ && *type_manager_->GetAnyValue(elements_type_) < *type_manager_->GetAnyValue(type.elements_type_);
}
bool ArrayType::operator>(const ArrayType& type) const {
return type < *this;
}
std::optional<utils::IdType> ArrayType::GetFieldType(const std::string&,
const std::unordered_set<utils::IdType>&) const {
return std::nullopt;
}
std::string ArrayType::ToString() {
return "Array (" + std::to_string(size_) + ") " + type_manager_->GetAnyValue(elements_type_)->ToString();
}
//
std::optional<utils::IdType> Type::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
size_t this_index = type_.index();
switch (this_index) {
case 0:
return std::get<AbstractType>(type_).InContext(context);
case 1:
return std::get<DefinedType>(type_).InContext(context);
case 2:
return std::nullopt;
case 3:
return std::get<TupleType>(type_).InContext(context);
case 4:
return std::get<VariantType>(type_).InContext(context);
case 5:
return std::get<ReferenceToType>(type_).InContext(context);
case 6:
return std::get<FunctionType>(type_).InContext(context);
case 7:
return std::get<ArrayType>(type_).InContext(context);
case 8:
return std::get<OptionalType>(type_).InContext(context);
default:
// error
break;
}
return std::nullopt;
}
bool Type::Same(const Type& type) const {
size_t this_index = type_.index();
size_t type_index = type.type_.index();
if (this_index == type_index) {
switch (this_index) {
case 0:
return std::get<AbstractType>(type_).Same(std::get<AbstractType>(type.type_));
case 1:
return std::get<DefinedType>(type_).Same(std::get<DefinedType>(type.type_));
case 2:
return std::get<InternalType>(type_) == std::get<InternalType>(type.type_);
case 3:
return std::get<TupleType>(type_).Same(std::get<TupleType>(type.type_));
case 4:
return std::get<VariantType>(type_).Same(std::get<VariantType>(type.type_));
case 5:
return std::get<ReferenceToType>(type_).Same(std::get<ReferenceToType>(type.type_));
case 6:
return std::get<FunctionType>(type_).Same(std::get<FunctionType>(type.type_));
case 7:
return std::get<ArrayType>(type_).Same(std::get<ArrayType>(type.type_));
case 8:
return std::get<OptionalType>(type_).Same(std::get<OptionalType>(type.type_));
default:
// error
break;
}
}
return false;
}
bool Type::operator<(const Type& type) const {
size_t this_index = type_.index();
size_t type_index = type.type_.index();
if (this_index == type_index) {
switch (this_index) {
case 0:
return std::get<AbstractType>(type_) < std::get<AbstractType>(type.type_);
case 1:
return std::get<DefinedType>(type_) < std::get<DefinedType>(type.type_);
case 2:
return std::get<InternalType>(type_) == std::get<InternalType>(type.type_);
case 3:
return std::get<TupleType>(type_) < std::get<TupleType>(type.type_);
case 4:
return std::get<VariantType>(type_) < std::get<VariantType>(type.type_);
case 5:
return std::get<ReferenceToType>(type_) < std::get<ReferenceToType>(type.type_);
case 6:
return std::get<FunctionType>(type_) < std::get<FunctionType>(type.type_);
case 7:
return std::get<ArrayType>(type_) < std::get<ArrayType>(type.type_);
case 8:
return std::get<OptionalType>(type_) < std::get<OptionalType>(type.type_);
default:
// error
break;
}
}
return false;
}
bool Type::operator>(const Type& type) const {
return type < *this;
}
std::optional<utils::IdType> Type::GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const {
size_t index = type_.index();
switch (index) {
case 0:
return std::get<AbstractType>(type_).GetFieldType(name, type_namespaces);
case 1:
return std::get<DefinedType>(type_).GetFieldType(name, type_namespaces);
case 2:
return std::nullopt;
case 3:
return std::get<TupleType>(type_).GetFieldType(name, type_namespaces);
case 4:
return std::get<VariantType>(type_).GetFieldType(name, type_namespaces);
case 5:
return std::get<ReferenceToType>(type_).GetFieldType(name, type_namespaces);
case 6:
return std::get<FunctionType>(type_).GetFieldType(name, type_namespaces);
case 7:
return std::get<ArrayType>(type_).GetFieldType(name, type_namespaces);
case 8:
return std::get<OptionalType>(type_).GetFieldType(name, type_namespaces);
default:
// error
break;
}
return std::nullopt;
}
std::string Type::GetTypeName() const {
size_t index = type_.index();
switch (index) {
case 0:
return "AbstractType";
case 1:
return "DefinedType";
case 2:
return "Builtin";
case 3:
return "TupleType";
case 4:
return "VariantType";
case 5:
return "ReferenceToType";
case 6:
return "FunctionType";
case 7:
return "ArrayType";
case 8:
return "OptionalType";
default:
// error
break;
}
return ""; // ??
}
std::string Type::ToString() {
size_t index = type_.index();
switch (index) {
case 0:
return std::get<AbstractType>(type_).ToString();
case 1:
return std::get<DefinedType>(type_).ToString();
case 2:
return ::info::type::ToString(std::get<InternalType>(type_));
case 3:
return std::get<TupleType>(type_).ToString();
case 4:
return std::get<VariantType>(type_).ToString();
case 5:
return std::get<ReferenceToType>(type_).ToString();
case 6:
return std::get<FunctionType>(type_).ToString();
case 7:
return std::get<ArrayType>(type_).ToString();
case 8:
return std::get<OptionalType>(type_).ToString();
default:
// error
break;
}
return "";
}
} // namespace info::type

92
src/utils.cpp Normal file
View file

@ -0,0 +1,92 @@
// for clangd
#include "../include/utils.hpp"
#include"../include/error_handling.hpp"
namespace utils {
using std::size_t;
using IdType = size_t;
ValueType IsConstModifierToValueType(IsConstModifier modifier) {
switch (modifier) {
case IsConstModifier::Const:
return ValueType::Const;
case IsConstModifier::Var:
return ValueType::Var;
}
exit(1); // unreachable
}
ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier) {
switch (modifier) {
case ClassInternalsModifier::Const:
return ValueType::Const;
case ClassInternalsModifier::Var:
return ValueType::Var;
case ClassInternalsModifier::Static:
throw std::bad_cast(); // ??
}
exit(1); // unreachable
}
bool IsBuiltinFunction(const std::string& name) { // optimize ??
std::unordered_set<std::string> builtin_functions;
builtin_functions.insert("="); // TODO: for all types
// builtin_functions.insert("<-"); // TODO
builtin_functions.insert("==");
builtin_functions.insert("<");
builtin_functions.insert("+=");
builtin_functions.insert("-=");
builtin_functions.insert("*=");
builtin_functions.insert("div");
builtin_functions.insert("mod");
builtin_functions.insert("/=");
builtin_functions.insert("size");
builtin_functions.insert("random");
builtin_functions.insert("print");
builtin_functions.insert("scan");
builtin_functions.insert("zero");
builtin_functions.insert("one");
builtin_functions.insert("show");
builtin_functions.insert("read");
// builtin_functions.insert("debug_show"); // TODO
return builtin_functions.count(name) != 0;
}
void BackVisitDfs(size_t id,
std::vector<size_t>& verticles,
std::vector<size_t>& marks,
const std::vector<std::vector<size_t>>& edges,
size_t mark) {
if (marks[id] != 0) {
return;
}
marks[id] = mark;
for (size_t i = 0; i < edges[id].size(); ++i) {
BackVisitDfs(edges[id][i], verticles, marks, edges, mark);
}
verticles.push_back(id);
}
std::vector<size_t> BackTopSort(const std::vector<std::vector<size_t>>& edges_) {
std::vector<size_t> sorted_verticles;
std::vector<size_t> marks(edges_.size(), 0);
for (size_t i = 0; i < edges_.size(); ++i) {
if (marks[i] == 0) {
BackVisitDfs(i, sorted_verticles, marks, edges_, 1);
}
}
return sorted_verticles;
}
} // namespace utils

308
src/values.cpp Normal file
View file

@ -0,0 +1,308 @@
#include <optional>
// for clangd
#include "../include/values.hpp"
#include "../include/error_handling.hpp"
namespace info::value {
bool InternalValue::Same(const InternalValue& other_value) const {
size_t this_index = value.index();
size_t other_index = other_value.value.index();
if (this_index == other_index) {
switch (this_index) {
case 0:
return std::get<double>(value) == std::get<double>(other_value.value);
case 1:
return std::get<int64_t>(value) == std::get<int64_t>(other_value.value);
case 2:
return std::get<std::string>(value) == std::get<std::string>(other_value.value);
case 3:
return std::get<char>(value) == std::get<char>(other_value.value);
case 4:
return std::get<bool>(value) == std::get<bool>(other_value.value);
case 5: // Unit
return true;
default:
// error
break;
}
}
return false;
}
std::optional<utils::IdType> InternalValue::GetFieldValue(const std::string&) const {
return std::nullopt;
}
utils::IdType InternalValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) {
return value_manager->ExplicitAddValue(InternalValue(value), new_value_type);
}
//
bool TupleValue::Same(const TupleValue& other_value) const {
// TODO: check, that type is same ?? (checked in typecheck ??)
if (fields.size() != other_value.fields.size()) {
return false;
}
for (size_t i = 0; i < fields.size(); ++i) { // compare field names ?? (checked in typecheck ??)
if (!value_manager_->GetAnyValue(fields[i].second)->Same(*value_manager_->GetAnyValue(other_value.fields[i].second))) {
return false;
}
}
return true;
}
std::optional<utils::IdType> TupleValue::GetFieldValue(const std::string& name) const {
for (size_t i = 0; i < fields.size(); ++i) { // TODO: optimize??
if (fields[i].first.has_value() && fields[i].first.value() == name) {
return fields[i].second;
}
}
return std::nullopt;
}
utils::IdType TupleValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) {
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields_copy(fields.size());
for (size_t i = 0; i < fields.size(); ++i) {
fields_copy[i] = {fields[i].first, value_manager_->GetAnyValue(fields[i].second)->DeepCopy(value_manager, new_value_type)};
}
return value_manager->ExplicitAddValue(
TupleValue(std::move(fields_copy), value_manager),
new_value_type);
}
//
bool VariantValue::Same(const VariantValue& other_value) const {
// TODO: check, that type is same ?? (checked in typecheck ??)
if (current_constructor != other_value.current_constructor) {
return false;
}
return value.Same(other_value.value);
}
std::optional<utils::IdType> VariantValue::GetFieldValue(const std::string& name) const {
return value.GetFieldValue(name);
}
utils::IdType VariantValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) {
auto maybe_tuple_deep_copy = value_manager->GetValue<TupleValue>(value.DeepCopy(value_manager, new_value_type));
if (!maybe_tuple_deep_copy) {
error_handling::HandleInternalError("Deep copied TupleType in not TupleType",
"VariantValue.DeepCopy",
std::nullopt);
}
return value_manager->ExplicitAddValue(
VariantValue(TupleValue(*maybe_tuple_deep_copy.value()), current_constructor),
new_value_type);
}
//
bool ReferenceToValue::Same(const ReferenceToValue& other_value) const {
if (references.size() != other_value.references.size()) {
return false;
}
for (size_t i = 0; i < references.size(); ++i) {
if (references[i] != other_value.references[i]) {
return false;
}
}
return value_manager_->GetAnyValue(value)->Same(*value_manager_->GetAnyValue(other_value.value));
}
std::optional<utils::IdType> ReferenceToValue::GetFieldValue(const std::string& name) const {
return value_manager_->GetAnyValue(value)->GetFieldValue(name);
}
utils::IdType ReferenceToValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) {
return value_manager->ExplicitAddValue(
ReferenceToValue(references, value_manager_->GetAnyValue(value)->DeepCopy(value_manager, new_value_type), value_manager),
new_value_type);
}
//
bool FunctionValue::Same(const FunctionValue& other_value) const {
size_t this_index = function.index();
size_t other_index = other_value.function.index();
if (this_index == other_index) {
switch (this_index) {
case 0:
return std::get<interpreter::tokens::FunctionDeclaration*>(function) == std::get<interpreter::tokens::FunctionDeclaration*>(other_value.function);
case 1:
return std::get<interpreter::tokens::LambdaFunction*>(function) == std::get<interpreter::tokens::LambdaFunction*>(other_value.function);
default:
// error
break;
}
}
return false;
}
std::optional<utils::IdType> FunctionValue::GetFieldValue(const std::string&) const {
return std::nullopt;
}
utils::IdType FunctionValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) {
return value_manager->ExplicitAddValue(
FunctionValue(function, value_manager),
new_value_type);
}
//
bool ArrayValue::Same(const ArrayValue& other_value) const {
if (is_constant_size != other_value.is_constant_size
|| elements.size() != other_value.elements.size()) {
return false;
}
for (size_t i = 0; i < elements.size(); ++i) {
if (!value_manager_->GetAnyValue(elements[i])->Same(*value_manager_->GetAnyValue(other_value.elements[i]))) {
return false;
}
}
return true;
}
std::optional<utils::IdType> ArrayValue::GetFieldValue(const std::string&) const {
return std::nullopt;
}
utils::IdType ArrayValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) {
std::vector<utils::IdType> elements_copy(elements.size());
for (size_t i = 0; i < elements.size(); ++i) {
elements_copy[i] = value_manager_->GetAnyValue(elements[i])->DeepCopy(value_manager, new_value_type);
}
return value_manager->ExplicitAddValue(
ArrayValue(std::move(elements_copy), is_constant_size, value_manager),
new_value_type);
}
//
bool OptionalValue::Same(const OptionalValue& other_value) const {
if (value.has_value() != other_value.value.has_value()) {
return false;
}
if (value.has_value()) { // => other_value.value.has_value()
return value_manager_->GetAnyValue(value.value())->Same(*value_manager_->GetAnyValue(other_value.value.value()));
}
return true;
}
std::optional<utils::IdType> OptionalValue::GetFieldValue(const std::string&) const {
return std::nullopt;
}
utils::IdType OptionalValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) {
if (!value.has_value()) {
return value_manager->ExplicitAddValue(
OptionalValue(std::nullopt, value_manager),
utils::ValueType::Tmp);
}
return value_manager->ExplicitAddValue(
OptionalValue(value_manager_->GetAnyValue(value.value())->DeepCopy(value_manager, new_value_type), value_manager),
new_value_type);
}
//
bool Value::Same(const Value& other_value) const {
size_t this_index = value.index();
size_t other_index = other_value.value.index();
if (this_index == other_index) {
switch (this_index) {
case 0:
return std::get<InternalValue>(value).Same(std::get<InternalValue>(other_value.value));
case 1:
return std::get<TupleValue>(value).Same(std::get<TupleValue>(other_value.value));
case 2:
return std::get<VariantValue>(value).Same(std::get<VariantValue>(other_value.value));
case 3:
return std::get<ReferenceToValue>(value).Same(std::get<ReferenceToValue>(other_value.value));
case 4:
return std::get<FunctionValue>(value).Same(std::get<FunctionValue>(other_value.value));
case 5:
return std::get<ArrayValue>(value).Same(std::get<ArrayValue>(other_value.value));
case 6:
return std::get<OptionalValue>(value).Same(std::get<OptionalValue>(other_value.value));
default:
// error
break;
}
}
return false;
}
std::optional<utils::IdType> Value::GetFieldValue(const std::string& name) const {
size_t index = value.index();
switch (index) {
case 0:
return std::get<InternalValue>(value).GetFieldValue(name);
case 1:
return std::get<TupleValue>(value).GetFieldValue(name);
case 2:
return std::get<VariantValue>(value).GetFieldValue(name);
case 3:
return std::get<ReferenceToValue>(value).GetFieldValue(name);
case 4:
return std::get<FunctionValue>(value).GetFieldValue(name);
case 5:
return std::get<ArrayValue>(value).GetFieldValue(name);
case 6:
return std::get<OptionalValue>(value).GetFieldValue(name);
default:
// error
break;
}
return std::nullopt;
}
utils::IdType Value::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) {
size_t index = value.index();
switch (index) {
case 0:
return std::get<InternalValue>(value).DeepCopy(value_manager, new_value_type);
case 1:
return std::get<TupleValue>(value).DeepCopy(value_manager, new_value_type);
case 2:
return std::get<VariantValue>(value).DeepCopy(value_manager, new_value_type);
case 3:
return std::get<ReferenceToValue>(value).DeepCopy(value_manager, new_value_type);
case 4:
return std::get<FunctionValue>(value).DeepCopy(value_manager, new_value_type);
case 5:
return std::get<ArrayValue>(value).DeepCopy(value_manager, new_value_type);
case 6:
return std::get<OptionalValue>(value).DeepCopy(value_manager, new_value_type);
default:
// error
break;
}
exit(1); // better error handling ??
}
}; // namespace info::value

663
src/visitor.cpp Normal file
View file

@ -0,0 +1,663 @@
// for clangd
#include "../include/visitor.hpp"
namespace interpreter {
// Definitions -----------------
void Visitor::Visit(NamespaceStatement& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<AliasDefinitionStatement>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<FunctionDeclaration>>(node).get());
break;
case 2:
Visit(std::get<std::unique_ptr<FunctionDefinitionStatement>>(node).get());
break;
case 3:
Visit(std::get<std::unique_ptr<TypeDefinitionStatement>>(node).get());
break;
case 4:
Visit(std::get<std::unique_ptr<PartitionStatement>>(node).get());
break;
case 5:
Visit(std::get<std::unique_ptr<Namespace>>(node).get());
break;
default:
// error
break;
}
}
void Visitor::Visit(SourceStatement& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<ImportStatement>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<AbstractTypeDefinitionStatement>>(node).get());
break;
case 2:
Visit(std::get<std::unique_ptr<TypeclassDefinitionStatement>>(node).get());
break;
case 3:
Visit(*std::get<std::unique_ptr<NamespaceStatement>>(node));
break;
default:
// error
break;
}
}
// Flow control -----------------
void Visitor::Visit(Pattern& node) { // <-> ScopedPattern
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<NameIdentifier>>(node).get());
break;
case 1:
Visit(*std::get<std::unique_ptr<Literal>>(node));
break;
case 2:
Visit(std::get<std::unique_ptr<TypeConstructorPattern>>(node).get());
break;
default:
// error
break;
}
}
void Visitor::Visit(FlowControl& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<Match>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<Condition>>(node).get());
break;
case 2:
Visit(std::get<std::unique_ptr<DoWhileLoop>>(node).get());
break;
case 3:
Visit(std::get<std::unique_ptr<WhileLoop>>(node).get());
break;
case 4:
Visit(std::get<std::unique_ptr<ForLoop>>(node).get());
break;
case 5:
Visit(std::get<std::unique_ptr<LoopLoop>>(node).get());
break;
default:
// error
break;
}
}
// Statements, expressions, blocks, etc. -----------------
void Visitor::Visit(BlockStatement& node) {
switch (node.index()) {
case 0:
Visit(*std::get<std::unique_ptr<Expression>>(node));
break;
case 1:
Visit(std::get<std::unique_ptr<VariableDefinitionStatement>>(node).get());
break;
case 2:
Visit(*std::get<std::unique_ptr<FlowControl>>(node));
break;
case 3:
Visit(*std::get<std::unique_ptr<PrefixedExpression>>(node));
break;
default:
// error
break;
}
}
//
void Visitor::Visit(SubExpressionToken& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<NameExpression>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<ScopedStatement>>(node).get());
break;
case 2:
Visit(std::get<std::unique_ptr<AccessExpression>>(node).get());
break;
case 3:
Visit(*std::get<std::unique_ptr<Literal>>(node));
break;
case 4:
Visit(std::get<std::unique_ptr<ReferenceExpression>>(node).get());
break;
default:
// error
break;
}
}
void Visitor::Visit(SubExpression& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<FunctionCallExpression>>(node).get());
break;
case 1:
Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node));
break;
default:
// error
break;
}
}
void Visitor::Visit(PrefixedExpression& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<ReturnExpression>>(node).get());
break;
case 1:
Visit(*std::get<std::unique_ptr<LoopControlExpression>>(node));
break;
case 2:
Visit(std::get<std::unique_ptr<Block>>(node).get());
break;
default:
// error
break;
}
}
void Visitor::Visit(Expression& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<LambdaFunction>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<TypeConstructor>>(node).get());
break;
case 2:
Visit(*std::get<std::unique_ptr<PrefixedExpression>>(node));
break;
case 3:
Visit(*std::get<std::unique_ptr<SubExpression>>(node));
break;
default:
// error
break;
}
}
void Visitor::Visit(SuperExpression& node) {
switch (node.index()) {
case 0:
Visit(*std::get<std::unique_ptr<FlowControl>>(node));
break;
case 1:
Visit(std::get<std::unique_ptr<TupleExpression>>(node).get());
break;
case 2:
Visit(std::get<std::unique_ptr<VariantExpression>>(node).get());
break;
case 3:
Visit(std::get<std::unique_ptr<ArrayExpression>>(node).get());
break;
case 4:
Visit(*std::get<std::unique_ptr<Expression>>(node));
break;
default:
// error
break;
}
}
// Name
void Visitor::Visit(AnyName& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<AnnotatedName>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<TupleName>>(node).get());
break;
case 2:
Visit(std::get<std::unique_ptr<VariantName>>(node).get());
break;
default:
// error
break;
}
}
// Type, typeclass, etc. -----------------
// Type
void Visitor::Visit(AnyType& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<TypeExpression>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<TupleType>>(node).get());
break;
case 2:
Visit(std::get<std::unique_ptr<VariantType>>(node).get());
break;
case 3:
Visit(std::get<std::unique_ptr<FunctionType>>(node).get());
break;
default:
// error
break;
}
}
// Identifiers, constants, etc. -----------------
void Visitor::Visit(Literal& node) {
switch (node.index()) {
case 0:
Visit(std::get<std::unique_ptr<FloatNumberLiteral>>(node).get());
break;
case 1:
Visit(std::get<std::unique_ptr<NumberLiteral>>(node).get());
break;
case 2:
Visit(std::get<std::unique_ptr<StringLiteral>>(node).get());
break;
case 3:
Visit(std::get<std::unique_ptr<CharLiteral>>(node).get());
break;
case 4:
Visit(std::get<std::unique_ptr<UnitLiteral>>(node).get());
break;
case 5:
Visit(std::get<std::unique_ptr<BoolLiteral>>(node).get());
break;
default:
// error
break;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sources -----------------
void Visitor::Visit(SourceFile* node) {
for (auto& statement : node->statements) {
Visit(statement);
}
}
// Namespaces, partitions -----------------
void Visitor::Visit(NamespaceSources* node) {
for (auto& statement : node->statements) {
Visit(statement);
}
}
void Visitor::Visit(Namespace* node) {
Visit(&node->type);
Visit(&node->scope);
}
// Definitions -----------------
void Visitor::Visit(ImportStatement* node) {
for (auto& symbol : node->symbols) {
Visit(&symbol);
}
}
void Visitor::Visit(AliasDefinitionStatement* node) {
Visit(&node->type);
Visit(node->value.get());
}
void Visitor::Visit(VariableDefinitionStatement* node) {
Visit(node->name);
Visit(node->value);
}
void Visitor::Visit(FunctionDeclaration* node) {
Visit(&node->name);
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
Visit(node->type.get());
}
void Visitor::Visit(FunctionDefinitionStatement* node) {
Visit(node->definition.get());
Visit(node->value);
}
void Visitor::Visit(TypeDefinitionStatement* node) {
Visit(node->definition.get());
Visit(node->value);
}
void Visitor::Visit(AbstractTypeDefinitionStatement* node) {
Visit(node->type.get());
}
void Visitor::Visit(TypeclassDefinitionStatement* node) {
Visit(node->definition.get());
for (auto& function_requirement : node->requirements) {
Visit(function_requirement.second.get());
}
}
void Visitor::Visit(PartitionStatement* node) {
Visit(&node->name);
Visit(node->value);
}
// Definition parts
void Visitor::Visit(FunctionDefinition* node) {
Visit(&node->name);
for (auto& argument : node->arguments) {
Visit(&argument);
}
}
void Visitor::Visit(TypeDefinition* node) {
Visit(node->type.get());
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
}
void Visitor::Visit(AnyAnnotatedType* node) {
Visit(&node->type);
for (auto& typeclass : node->typeclasses) {
Visit(typeclass.get());
}
}
// Flow control -----------------
void Visitor::Visit(TypeConstructorPatternParameter* node) {
if (node->name.has_value()) {
Visit(&node->name.value());
}
Visit(node->value);
}
void Visitor::Visit(TypeConstructorPattern* node) {
Visit(node->constructor.get());
for (auto& parameter : node->parameters) {
Visit(&parameter);
}
}
void Visitor::Visit(MatchCase* node) {
Visit(node->value);
if (node->condition.has_value()) {
Visit(node->condition.value());
}
if (node->statement.has_value()) {
Visit(node->statement.value());
}
}
void Visitor::Visit(Match* node) {
Visit(node->value);
for (auto& match_case : node->matches) {
Visit(&match_case);
}
}
void Visitor::Visit(Condition* node) {
for (size_t i = 0; i < node->conditions.size(); ++i) {
Visit(node->conditions[i]);
Visit(node->statements[i]);
}
if (node->statements.size() > node->conditions.size()) {
Visit(node->statements[node->conditions.size()]);
}
}
void Visitor::Visit(DoWhileLoop* node) {
Visit(node->statement);
Visit(node->condition);
}
void Visitor::Visit(WhileLoop* node) {
Visit(node->condition);
Visit(node->statement);
}
void Visitor::Visit(ForLoop* node) {
Visit(node->variable);
Visit(node->interval);
Visit(node->statement);
}
void Visitor::Visit(LoopLoop* node) {
Visit(node->statement);
}
// Statements, expressions, blocks, etc. -----------------
void Visitor::Visit(Block* node) {
for (auto& statement : node->statements) {
Visit(statement);
}
}
void Visitor::Visit(ScopedStatement* node) {
Visit(node->statement);
}
void Visitor::Visit(LoopControlExpression&) {} // enum
// Operators
void Visitor::Visit(ReferenceExpression* node) {
Visit(node->expression.get());
}
void Visitor::Visit(AccessExpression* node) {
Visit(node->name.get());
Visit(node->id);
}
// Other Expressions
void Visitor::Visit(FunctionCallExpression* node) {
if (node->prefix.has_value()) {
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
Visit(std::get<std::unique_ptr<TypeExpression>>(node->prefix.value()).get());
} else {
// error
}
}
Visit(&node->name);
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
for (auto& argument : node->arguments) {
Visit(argument);
}
}
void Visitor::Visit(TupleExpression* node) {
for (auto& expression : node->expressions) {
Visit(expression);
}
}
void Visitor::Visit(VariantExpression* node) {
for (auto& expression : node->expressions) {
Visit(expression);
}
}
void Visitor::Visit(ReturnExpression* node) {
Visit(node->expression);
}
void Visitor::Visit(TypeConstructorParameter* node) {
if (node->name.has_value()) {
Visit(&node->name.value());
}
Visit(node->value);
}
void Visitor::Visit(TypeConstructor* node) {
Visit(node->constructor.get());
for (auto& parameter : node->parameters) {
Visit(&parameter);
}
}
void Visitor::Visit(LambdaFunction* node) {
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
for (auto& argument : node->arguments) {
Visit(&argument);
}
Visit(node->expression);
}
void Visitor::Visit(ArrayExpression* node) {
for (auto& element : node->elements) {
Visit(element);
}
}
// Name
void Visitor::Visit(PartitionName* node) {
for (auto& path_namespace : node->path) {
Visit(&path_namespace);
}
}
void Visitor::Visit(NameExpression* node) {
for (auto& name : node->names) {
Visit(&name);
}
}
void Visitor::Visit(TupleName* node) {
for (auto& name : node->names) {
Visit(name);
}
}
void Visitor::Visit(VariantName* node) {
for (auto& name : node->names) {
Visit(name);
}
}
void Visitor::Visit(AnnotatedName* node) {
Visit(&node->name);
if (node->type.has_value()) {
Visit(node->type.value());
}
}
// Type, typeclass, etc. -----------------
// Type
void Visitor::Visit(FunctionType* node) {
for (auto& type : node->types) {
Visit(type);
}
}
void Visitor::Visit(TupleType* node) {
if (node->type.has_value()) {
Visit(&node->type.value());
}
for (auto& entity : node->entities) {
if (entity.first.has_value()) {
Visit(&entity.first.value());
}
Visit(entity.second.get());
}
}
void Visitor::Visit(VariantType* node) {
if (node->type.has_value()) {
Visit(&node->type.value());
}
for (auto& constructor : node->constructors) {
if (std::holds_alternative<Constructor>(constructor)) {
Visit(&std::get<Constructor>(constructor));
} else if (std::holds_alternative<std::unique_ptr<TupleType>>(constructor)) {
Visit(std::get<std::unique_ptr<TupleType>>(constructor).get());
} else {
// error
}
}
}
void Visitor::Visit(TypeExpression* node) {
for (auto& type : node->path) {
Visit(&type);
}
Visit(&node->type);
}
void Visitor::Visit(ExtendedScopedAnyType* node) {
Visit(node->type);
}
// Typeclass
void Visitor::Visit(ParametrizedTypeclass* node) {
Visit(&node->typeclass);
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
}
// Typeclass & Type -----------------
void Visitor::Visit(ParametrizedType* node) {
Visit(&node->type);
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
}
// Identifiers, constants, etc. -----------------
void Visitor::Visit(std::string*) {} // std::string
void Visitor::Visit(FloatNumberLiteral*) {}
void Visitor::Visit(NumberLiteral*) {}
void Visitor::Visit(StringLiteral*) {}
void Visitor::Visit(CharLiteral*) {}
void Visitor::Visit(UnitLiteral*) {}
void Visitor::Visit(BoolLiteral*) {}
} // namespace interpreter

21
tests/arrays.lang Normal file
View file

@ -0,0 +1,21 @@
decl test_arrays : -> Unit
def test_arrays = {
var arr1 = ,1 ,2 ,3
const arr2 = Int._array: 32
var arr3 = String._array: 11
const arr4 = 'a'--'z'
const n = 100
var arr5 <- Int._new_array: 10
var arr6 <- String._new_array: 10
var arr6_reference = ^arr6
const elem1 = arr1`0
var elem2 = arr1`2
const ref1 = ^arr1`1
var ref2 = ^arr1`3
; arr1`1 = 123
; ~ref1 = arr1`2 // set value
; ref1 = ref2 // set pointer / reference
}

59
tests/classes.lang Normal file
View file

@ -0,0 +1,59 @@
struct Fruit =
| Apple
| Orange
| Banana
struct Optional 'A =
| Some & 'A
| None
struct (Result : #Move) 'A 'B =
| & 'A
| Error & 'B
struct (Complex : #Value) =
& Float
& Float
struct Task =
& name : String
& duration : Float
class Employee =
& name : String
& role :
( | Director
& importance : Float
& share : Float
| Manager
& productivity :
( Productivity
| .Low
| .Average
| .High
& duration : Float
& sleep_on_work :
(SleepOnWork
| ..Yes
| ..No
))
& salary : Int
| Programmer
& skills : Float
& current_task : (Optional Task)
& salary : Int)
class Bag =
&
( | Apple
| Orange
| Banana)
& bag_type :
( | Small
| Medium
& weight_kg : Int
& weight_g : Int
& weight_g : Int
| Big)
& other_things : (Array Something)

View file

@ -0,0 +1,44 @@
namespace Employee {
decl gen_employee : Unit -> Employee
def gen_employee = {
var x = $@Complex & 11.3 & 15.87 // construct on heap
return
$Employee // construct on stack
& name = "John"
& role =
($Manager
& "John"
& productivity =
($Productivity::High
& duration = 10.3
& sleep_on_work = ($Productivity::SleepOnWork::No))
& salary = 123)
}
}
/*
class Employee =
& name : String
& role :
( | Director
& importance : Float
& share : Float
| Manager
& productivity :
( Productivity
| .Low
| .Average
| .High
& duration : Float
& sleep_on_work :
(SleepOnWork
| ..Yes
| ..No
))
& salary : Int
| Programmer
& skills : Float
& current_task : Optional Task
& salary : Int)
*/

33
tests/flow_control.lang Normal file
View file

@ -0,0 +1,33 @@
decl flow_control_test : -> Unit
def flow_control_test = {
if (a < b ||. a == b) && (b < c) then IO.print: x
elif x < 0 then {
; x += 1
; IO.print: y
} else {
return {}
}
while (a > 0) && not: (array.is_empty:) do {
; a -= 1
; array.pop:
}
while x < 10 do x +=. x + 3
for i in 0--y do {
; IO.print: i
}
for & i & j in (& 0--y & 0--k) do { // ??
; IO.print: 1
; IO.print: 2
; IO.print: 128
}
loop {
; y += 1
if y > 100 then
break
}
}

62
tests/functions.lang Normal file
View file

@ -0,0 +1,62 @@
decl sum ('A : #Add) : 'A -> 'A -> 'A
def sum : a b = a + b
decl fib : Int -> Int
def fib : n =
match n with
| 0 | 1 -> 1
| n ? n > 1 -> fib: (n - 1) + fib: n
| _ -> error: "n must be positive"
decl fact : Int -> Int
def fact : n =
match n with
| 0 -> 1
| n ? n > 0 -> n * fact: (n - 1)
| _ -> error: "n must be positive"
decl find_prefix_hashes ('H : (#AccHash Char)) : String -> (Array 'H)
def find_prefix_hashes : str = {
var hashes = (Array 'H).new: (str.size: + 1)
; hashes`0 = 'H.of: str`0
for i in 1--hashes.size: do {
; hashes`i = hashes`(i - 1)
; hashes`i.append: str`i
}
return hashes
}
alias Hash = (AccHash Char)
decl find_substring : String -> String -> (Array Index)
def find_substring : str substr = {
var result = (Array Index).empty:
const str_hashes = find_prefix_hashes Hash: str
const substr_hash = Hash.of: substr
for i in 0--(str_hashes.size: - substr.size:) do {
const part_hash = Hash.diff: str_hashes`(i + substr.size:) str_hashes`i
if part_hash == substr_hash then {
; result.push: i
}
}
return result
}
decl is_empty : -> Bool
def is_empty = 0
decl do_something : -> Unit
def do_something =
IO.print: "Hello World!"
decl mul : Int -> Int -> Int
def mul : x y = x * y
decl mul_10 : Int -> Int
def mul_10 = mul: 10

16
tests/import.lang Normal file
View file

@ -0,0 +1,16 @@
import "module"
import "module" : func
import "module" :
Type1
func1
func2
func3
func4
use ModuleNamespace = import "module"
use PartOfModuleNamespace =
import "module" :
func1
func2
func3

12
tests/lambdas.lang Normal file
View file

@ -0,0 +1,12 @@
decl test_lambdas : -> Unit
def test_lambdas = {
const lambda1 = \x -> x * x
const lambda2 = \x -> x.hash:
const lambda3 = \x y -> x + y
const lambda4 = \x -> {
; IO.print: x
const y = x + x
return y
}
}

18
tests/match.lang Normal file
View file

@ -0,0 +1,18 @@
decl fruit_cost : Fruit -> Int
def fruit_cost : fruit = {
var fruit_copy = fruit
return (match <- fruit_copy with // consuming match
| $Banana -> 11
| $Apple | $Orange -> 7)
}
decl amount_to_string : Int -> Bool -> String
def amount_to_string : x is_zero_separated = {
const ans = match x with
| 0 ? is_zero_separated -> "Zero"
| 0 | 1 | 2 | 3 | 4 -> "Few"
| x ? (5--9).contains: x -> "Several"
| x ? (10--19).contains: x -> "Pack"
| _ -> "Lots"
return ans
}

8
tests/memory.lang Normal file
View file

@ -0,0 +1,8 @@
struct StructWithRef =
& @Int_0
decl test_memory : -> Unit
def test_memory = {
const unique_ref1 <- Int._new: 5
var unique_ref2 <- Array.of: 1 2 3
}

19
tests/namespaces.lang Normal file
View file

@ -0,0 +1,19 @@
namespace Namespace {
decl something : -> Unit
}
namespace Array {
decl something : -> Unit
}
namespace Array {
decl something : -> Unit
}
namespace var Array {
decl something : -> Unit
}
namespace const Array {
decl something : -> Unit
}

10
tests/partitions.lang Normal file
View file

@ -0,0 +1,10 @@
test All::Dev::Syntax::testing {
const a = 31
; do_something: a
}
exec App::exe {
const b = true
const c = false
; do_something_different: b b c
}

0
tests/stdlib.lang Normal file
View file

229
tests/test_code.lang Normal file
View file

@ -0,0 +1,229 @@
basic (Float : #Ord #Div #Str)
basic (Int : #Ord #IDiv #Str)
basic (String : #Ord #Str #CharContainer #Copy)
basic (Char : #Ord #Str #Copy)
basic (Bool : #Ord #Str #Copy)
basic (Unit : #Str #Copy)
//
decl not : Bool -> Bool
def not : x =
(match x with
| true -> false
| false -> true)
decl ( && ) : Bool -> Bool -> Bool
def ( && ) : x y =
match x with
| true -> (
match y with
| true -> true
| false -> false
)
| false -> false
decl ( || ) : Bool -> Bool -> Bool
def ( || ) : x y =
match x with
| true -> true
| false -> (
match y with
| true -> true
| false -> false
)
//
typeclass CharContainer =
& var size : -> Int
& var at : Int -> Char
//
typeclass Move =
& var ( <- ) : Move -> Unit // TODO
typeclass Copy =
& var ( = ) : Copy -> Unit
//
typeclass (Sum : #Copy) =
& var ( += ) : Sum -> Unit
& var ( -= ) : Sum -> Unit
& var ( + ) : Sum -> Sum
& var ( - ) : Sum -> Sum
& zero : -> Sum
namespace var Sum {
def ( + ) : x = {
var ans = self
; ans += x
return ans
}
def ( - ) : x = {
var ans = self
; ans -= x
return ans
}
}
typeclass (Mult : #Sum) =
& var ( *= ) : Mult -> Unit
& var ( * ) : Mult -> Mult
namespace var Mult {
def ( * ) : x = {
var ans = self
; ans *= x
return ans
}
}
typeclass (IDiv : #Mult) =
& var div : IDiv -> IDiv
& var mod : IDiv -> IDiv
namespace var IDiv {
def mod : x = self -. x * self.div: x
}
typeclass (Div : #Mult) =
& var ( /= ) : Div -> Unit
& var ( / ) : Div -> Div
namespace var Div {
def ( / ) : x = {
var ans = self
; ans /= x
return ans
}
}
//
typeclass Eq =
& var ( == ) : Eq -> Bool
& var ( != ) : Eq -> Bool
namespace var Eq {
def ( != ) : x = not: (self == x)
}
//
struct Order =
| EQ
| LT
| GT
typeclass (Ord : #Eq) =
& var compare : Ord -> Order
& var ( < ) : Ord -> Bool
& var ( >= ) : Ord -> Bool
& var ( > ) : Ord -> Bool
& var ( <= ) : Ord -> Bool
decl min ('A : #Ord) : 'A -> 'A -> 'A
def min : x y = if x < y then x else y
decl max ('A : #Ord) : 'A -> 'A -> 'A
def max : x y = if x < y then y else x
namespace var Ord {
def compare : x =
if self == x then $EQ
elif self < x then $LT
else $GT
def ( >= ) : x = not: (self < x)
def ( > ) : x = x < self
def ( <= ) : x = not: (x < self)
}
//
typeclass Show =
& var show : -> String
typeclass Read =
& var read : String -> Read
typeclass (Str : #Show #Read)
// typeclass DebugShow = // TODO
// & debug_show : -> String
//
typeclass Default =
& default : -> Default
//
typeclass Bounded =
& min_bound : -> Bounded
& max_bound : -> Bounded
& var is_max_bound : -> Bool
& var is_min_bound : -> Bool
//
typeclass Enum =
& var succ : -> (Optional Enum)
& var pred : -> (Optional Enum)
& to_enum : Int -> Enum
& var from_enum : -> Int
//
decl print : String -> Unit
decl scan : -> String
decl random : -> Int // TODO
//
// // bad
// typeclass Functor 'A =
// & fmap 'B ('F : (#Functor 'B)) : ('A -> 'B) -> Functor -> 'F
// typeclass (Iterator : #Eq) =
// & next : -> Unit
// & prev : -> Unit
//
// typeclass Iterable ('Iter : #Iterable) =
// & begin : -> 'Iter
// & end : -> 'Iter
//
decl ret_one : -> Int
def ret_one = 1
decl ( -- ) : Int -> Int -> Int_0
def ( -- ) : begin end = {
var current = begin
return (while current < end do {
; current += 1
bring current - 1
})
}
decl func : String -> Int -> Int
def func : s i = {
; print: s
var x = s
; print: (i.show:)
return 5
}
exec main {
for i in 0--19 do func: "a" (i * 2 +. 3)
; print: ({
if true then bring scan: else { ; print: "aaa" }
bring "nothing"
; print: "aaa"
})
}

8
tests/tuples.lang Normal file
View file

@ -0,0 +1,8 @@
decl test_tuples : -> Unit
def test_tuples = {
var tuple1 = & "a" & 2 & "hello"
const & t1 & t2 & t3 = f: x
; tuple1`0 = "b"
}

5
tests/type_casting.lang Normal file
View file

@ -0,0 +1,5 @@
decl test_type_casting : -> Unit
def test_type_casting = {
var x = y.as Int:
var k = (f: y x).as Float:
}

29
tests/typeclasses.lang Normal file
View file

@ -0,0 +1,29 @@
typeclass Default =
& default : -> Copy
typeclass (Ord : #Eq) =
& var is_less_then : Ord -> Bool
typeclass (D : #A #B #C) 'A 'B =
& var do_something : -> (& 'A & 'B)
typeclass E 'A =
& var do_something : -> 'A
decl ( == ) ('A : #Ord) : 'A -> 'A -> Bool
def ( == ) : a b = a.is_equal_to: b
decl ( != ) ('A : #Ord) : 'A -> 'A -> Bool
def ( != ) : a b = not: (a == b)
decl ( < ) ('A : #Ord) : 'A -> 'A -> Bool
def ( < ) : a b = a.is_less_then: b
decl ( > ) ('A : #Ord) : 'A -> 'A -> Bool
def ( > ) : a b = not: (a <= b)
decl ( <= ) ('A : #Ord) : 'A -> 'A -> Bool
def ( <= ) : a b = a < b ||. a == b
decl ( >= ) ('A : #Ord) : 'A -> 'A -> Bool
def ( >= ) : a b = not: (a < b)

8
tests/types.lang Normal file
View file

@ -0,0 +1,8 @@
alias T1 = Int
abstract (T2 : #A #B #C)
// Used to pre-compile module for some types
let T2 = Int
let T2 = Float
let T2 = Complex

15
tests/variants.lang Normal file
View file

@ -0,0 +1,15 @@
decl test_variants : -> Unit
def test_variants = {
var variant1 = | 'a' | 2 | "hello"
var | val | err = f: x
; val -?> "something" // open variant as value in expr
; val -!> "nothing" // open variant as None in expr
match variant1 with
| 'a' -> "something"
| 2 -> "nothing"
| "hello" -> "nothing"
| 11 -> "nothing"
}

1
tree-sitter Submodule

@ -0,0 +1 @@
Subproject commit 1b1c3974f789a9bfaa31f493e6eaa212f13bdfb9