mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-05 22:48:42 +00:00
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:
commit
e3d1a758df
64 changed files with 14500 additions and 0 deletions
18
.clang_tidy
Normal file
18
.clang_tidy
Normal 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
2
.clangd
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CompileFlags:
|
||||
Add: [-std=c++17]
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -11,3 +11,9 @@ compile_commands.json
|
|||
CTestTestfile.cmake
|
||||
_deps
|
||||
|
||||
|
||||
build
|
||||
build_make
|
||||
cmake-build-debug
|
||||
|
||||
.idea
|
||||
|
|
|
|||
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal 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
35
CMakeLists.txt
Normal 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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
73
archived/abstract_types_contexts.hpp
Normal file
73
archived/abstract_types_contexts.hpp
Normal 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
118
archived/symbols_info.hpp
Normal 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
235
archived/type_graph.hpp
Normal 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
151
include/build_visitor.hpp
Normal 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
|
||||
25
include/builtin_functions.hpp
Normal file
25
include/builtin_functions.hpp
Normal 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
275
include/contexts.hpp
Normal 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
114
include/definitions.hpp
Normal 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
|
||||
78
include/error_handling.hpp
Normal file
78
include/error_handling.hpp
Normal 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
193
include/execute_visitor.hpp
Normal 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
|
||||
127
include/find_symbols_visitor.hpp
Normal file
127
include/find_symbols_visitor.hpp
Normal 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
401
include/global_info.hpp
Normal 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
|
||||
717
include/interpreter_tree.hpp
Normal file
717
include/interpreter_tree.hpp
Normal 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
|
||||
142
include/link_symbols_visitor.hpp
Normal file
142
include/link_symbols_visitor.hpp
Normal 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
36
include/node.hpp
Normal 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
|
||||
132
include/parse_token_types.hpp
Normal file
132
include/parse_token_types.hpp
Normal 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
142
include/parse_tree.hpp
Normal 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
123
include/print_visitor.hpp
Normal 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
|
||||
246
include/type_check_visitor.hpp
Normal file
246
include/type_check_visitor.hpp
Normal 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
|
||||
91
include/typeclass_graph.hpp
Normal file
91
include/typeclass_graph.hpp
Normal 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
|
||||
126
include/typed_print_visitor.hpp
Normal file
126
include/typed_print_visitor.hpp
Normal 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
401
include/types.hpp
Normal 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
225
include/utils.hpp
Normal 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
244
include/values.hpp
Normal 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
141
include/visitor.hpp
Normal 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
1
lang-parser
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ddb08e9b65123324800d1126d38764764363c0e5
|
||||
1585
src/build_visitor.cpp
Normal file
1585
src/build_visitor.cpp
Normal file
File diff suppressed because it is too large
Load diff
1262
src/execute_visitor.cpp
Normal file
1262
src/execute_visitor.cpp
Normal file
File diff suppressed because it is too large
Load diff
218
src/find_symbols_visitor.cpp
Normal file
218
src/find_symbols_visitor.cpp
Normal 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
601
src/global_info.cpp
Normal 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 = ¤t_namespace->const_namespaces;
|
||||
break;
|
||||
case utils::ClassInternalsModifier::Var:
|
||||
current_namespaces = ¤t_namespace->var_namespaces;
|
||||
break;
|
||||
case utils::ClassInternalsModifier::Static:
|
||||
current_namespaces = ¤t_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
|
||||
218
src/link_symbols_visitor.cpp
Normal file
218
src/link_symbols_visitor.cpp
Normal 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
85
src/main.cpp
Normal 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
746
src/print_visitor.cpp
Normal 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(¶meter);
|
||||
}
|
||||
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(¶meter);
|
||||
}
|
||||
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
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
162
src/typeclass_graph.cpp
Normal 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
1059
src/typed_print_visitor.cpp
Normal file
File diff suppressed because it is too large
Load diff
588
src/types.cpp
Normal file
588
src/types.cpp
Normal 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
92
src/utils.cpp
Normal 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
308
src/values.cpp
Normal 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
663
src/visitor.cpp
Normal 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(¶meter);
|
||||
}
|
||||
}
|
||||
|
||||
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(¶meter);
|
||||
}
|
||||
}
|
||||
|
||||
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
21
tests/arrays.lang
Normal 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
59
tests/classes.lang
Normal 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)
|
||||
44
tests/default_constructors.lang
Normal file
44
tests/default_constructors.lang
Normal 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
33
tests/flow_control.lang
Normal 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
62
tests/functions.lang
Normal 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
16
tests/import.lang
Normal 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
12
tests/lambdas.lang
Normal 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
18
tests/match.lang
Normal 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
8
tests/memory.lang
Normal 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
19
tests/namespaces.lang
Normal 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
10
tests/partitions.lang
Normal 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
0
tests/stdlib.lang
Normal file
229
tests/test_code.lang
Normal file
229
tests/test_code.lang
Normal 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
8
tests/tuples.lang
Normal 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
5
tests/type_casting.lang
Normal 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
29
tests/typeclasses.lang
Normal 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
8
tests/types.lang
Normal 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
15
tests/variants.lang
Normal 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
1
tree-sitter
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 1b1c3974f789a9bfaa31f493e6eaa212f13bdfb9
|
||||
Loading…
Add table
Add a link
Reference in a new issue