fixes, builtin function fixes, deep copy, string access

This commit is contained in:
ProgramSnail 2023-05-22 16:03:50 +03:00
parent 3af0772da6
commit 9aaac90ef6
13 changed files with 450 additions and 152 deletions

View file

@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 17)
# find_package(Catch2 2 REQUIRED) # find_package(Catch2 2 REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
include_directories(include include_directories(include
tree-sitter/lib/src tree-sitter/lib/src

View file

@ -164,8 +164,8 @@ private:
bool HandleBuiltinFunctionCall(FunctionCallExpression* node); bool HandleBuiltinFunctionCall(FunctionCallExpression* node);
bool HandleBuiltinTypeclassFunctionCall(FunctionCallExpression* node); bool HandleBuiltinTypeFunctionCall(FunctionCallExpression* node,
info::type::InternalType type);
private: private:
info::GlobalInfo& global_info_; info::GlobalInfo& global_info_;
info::TypeclassGraph& typeclass_graph_; info::TypeclassGraph& typeclass_graph_;

View file

@ -506,6 +506,8 @@ struct AccessExpression {
std::unique_ptr<NameExpression> name; std::unique_ptr<NameExpression> name;
SubExpressionToken id; SubExpressionToken id;
bool is_string_access_ = false;
}; };
// Other Expressions ----------------- // Other Expressions -----------------

View file

@ -198,8 +198,8 @@ private:
utils::IdType abstract_type = context_manager_.AddValue( utils::IdType abstract_type = context_manager_.AddValue(
info::type::AbstractType(utils::AbstractTypeModifier::Abstract, info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
typeclass_graph_.GetVertex(graph_id).name, graph_id,
requirement_graph_ids), typeclass_graph_),
utils::ValueType::Tmp); utils::ValueType::Tmp);
for (auto& requirement_graph_id : requirement_graph_ids) { for (auto& requirement_graph_id : requirement_graph_ids) {

View file

@ -9,6 +9,7 @@
// for clangd // for clangd
#include "error_handling.hpp" #include "error_handling.hpp"
#include "typeclass_graph.hpp"
#include "utils.hpp" #include "utils.hpp"
namespace info::type { namespace info::type {
@ -19,23 +20,12 @@ class TypeManager;
class AbstractType { // latter will be found in context class AbstractType { // latter will be found in context
public: public:
AbstractType() = default;
AbstractType(utils::AbstractTypeModifier modifier, AbstractType(utils::AbstractTypeModifier modifier,
const std::string& name, utils::IdType graph_id,
const std::vector<utils::IdType>& requirement_graph_ids) info::TypeclassGraph& typeclass_graph)
: modifier_(modifier), : modifier_(modifier),
name_(name) { graph_id_(graph_id),
for (auto& requirement_graph_id : requirement_graph_ids) { typeclass_graph_(typeclass_graph) {}
requirement_graph_ids_.insert(requirement_graph_id);
}
}
AbstractType(utils::AbstractTypeModifier modifier,
const std::string& name,
const std::unordered_set<utils::IdType>& requirement_graph_ids)
: modifier_(modifier),
name_(name),
requirement_graph_ids_(requirement_graph_ids) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context); std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const AbstractType& type) const; bool Same(const AbstractType& type) const;
@ -45,21 +35,21 @@ public:
std::optional<utils::IdType> GetFieldType(const std::string& name, std::optional<utils::IdType> GetFieldType(const std::string& name,
const std::unordered_set<utils::IdType>& type_namespaces) const; const std::unordered_set<utils::IdType>& type_namespaces) const;
const std::string& GetName() { utils::IdType GetGraphId() {
return name_; return graph_id_;
} }
bool HasTypeclass(utils::IdType graph_id) { bool HasTypeclass(utils::IdType graph_id) { // TODO: cache dependencies set
return requirement_graph_ids_.count(graph_id) != 0; return graph_id == graph_id_ || typeclass_graph_.GetDependenciesSet(graph_id_).count(graph_id) != 0;
} }
std::string ToString() { std::string ToString() {
return "Abstract " + name_; return "Abstract " + std::to_string(graph_id_);
} }
private: private:
utils::AbstractTypeModifier modifier_; utils::AbstractTypeModifier modifier_;
std::string name_; utils::IdType graph_id_;
std::unordered_set<utils::IdType> requirement_graph_ids_; // TODO: all typeclasses from tree info::TypeclassGraph& typeclass_graph_;
}; };
class DefinedType { class DefinedType {
@ -324,8 +314,6 @@ private:
class Type { class Type {
public: public:
Type() = default;
template<typename T> template<typename T>
explicit Type(const T& type) : type_(type) {} explicit Type(const T& type) : type_(type) {}

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <iterator>
#include <string> #include <string>
#include <variant> #include <variant>
#include <optional> #include <optional>
@ -32,16 +33,19 @@ public:
bool Same(const InternalValue& value) const; bool Same(const InternalValue& value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const; std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager);
public: public:
std::variant<double, std::variant<double,
long long, int64_t,
std::string, std::string,
char, char,
bool, bool,
Unit> value; Unit> value;
}; };
struct TupleValue { struct TupleValue { /// TODO: no need to store strings (only store associated type) ??
public: public:
TupleValue() = default; TupleValue() = default;
@ -51,6 +55,9 @@ public:
bool Same(const TupleValue& other_value) const; bool Same(const TupleValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const; std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager); // TODO
public: public:
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields; std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
@ -65,12 +72,14 @@ public:
VariantValue(TupleValue&& value, size_t current_constructor) VariantValue(TupleValue&& value, size_t current_constructor)
: value(std::move(value)), current_constructor(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);
public: public:
TupleValue value; TupleValue value;
size_t current_constructor; size_t current_constructor;
bool Same(const VariantValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
}; };
struct ReferenceToValue { struct ReferenceToValue {
@ -82,13 +91,15 @@ public:
ValueManager* value_manager) ValueManager* value_manager)
: references(references), value(value), value_manager_(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);
public: public:
std::vector<utils::ReferenceModifier> references; std::vector<utils::ReferenceModifier> references;
utils::IdType value; utils::IdType value;
bool Same(const ReferenceToValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
private: private:
ValueManager* value_manager_ = nullptr; ValueManager* value_manager_ = nullptr;
}; };
@ -101,13 +112,15 @@ public:
FunctionValue(const T& function, ValueManager* value_manager) FunctionValue(const T& function, ValueManager* value_manager)
: function(function), value_manager_(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);
public: public:
std::variant<interpreter::tokens::FunctionDeclaration*, std::variant<interpreter::tokens::FunctionDeclaration*,
interpreter::tokens::LambdaFunction*> function; interpreter::tokens::LambdaFunction*> function;
bool Same(const FunctionValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
private: private:
ValueManager* value_manager_ = nullptr; ValueManager* value_manager_ = nullptr;
}; };
@ -122,13 +135,15 @@ public:
ValueManager* value_manager) ValueManager* value_manager)
: elements(std::move(elements)), is_constant_size(is_constant_size), value_manager_(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);
public: public:
std::vector<utils::IdType> elements; std::vector<utils::IdType> elements;
bool is_constant_size = false; bool is_constant_size = false;
bool Same(const ArrayValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
private: private:
ValueManager* value_manager_ = nullptr; ValueManager* value_manager_ = nullptr;
}; };
@ -143,6 +158,8 @@ public:
bool Same(const OptionalValue& other_value) const; bool Same(const OptionalValue& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const; std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager);
public: public:
std::optional<utils::IdType> value; std::optional<utils::IdType> value;
@ -160,6 +177,8 @@ public:
bool Same(const Value& other_value) const; bool Same(const Value& other_value) const;
std::optional<utils::IdType> GetFieldValue(const std::string& name) const; std::optional<utils::IdType> GetFieldValue(const std::string& name) const;
utils::IdType DeepCopy(ValueManager* value_manager);
public: public:
std::variant<InternalValue, std::variant<InternalValue,
TupleValue, TupleValue,
@ -173,16 +192,25 @@ public:
class ValueManager { class ValueManager {
public: public:
template<typename T> template<typename T>
utils::IdType AddValue(const T& value, utils::ValueType value_type) { utils::IdType ExplicitAddValue(const T& value, utils::ValueType value_type) {
values_.push_back(std::pair<Value, utils::ValueType> {Value(value), value_type}); values_.push_back(std::pair<Value, utils::ValueType> {Value(value), value_type});
return values_.size() - 1; return values_.size() - 1;
} }
utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) { utils::IdType ExplicitAddAnyValue(Value&& value, utils::ValueType value_type) {
values_.push_back(std::pair<Value, utils::ValueType> {std::move(value), value_type}); values_.push_back(std::pair<Value, utils::ValueType> {std::move(value), value_type});
return values_.size() - 1; 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> template<typename T>
std::optional<T*> GetValue(utils::IdType value_id) { std::optional<T*> GetValue(utils::IdType value_id) {
if (!std::holds_alternative<T>(values_.at(value_id).first.value)) { if (!std::holds_alternative<T>(values_.at(value_id).first.value)) {

View file

@ -392,20 +392,37 @@ void ExecuteVisitor::Visit(ReferenceExpression* node) {
value_type); value_type);
} }
void ExecuteVisitor::Visit(AccessExpression* node) {
// TODO: extend to other types // TODO: extend to other types
// TODO: string should be array
void ExecuteVisitor::Visit(AccessExpression* node) {
Visit(node->name.get()); Visit(node->name.get());
info::value::ArrayValue* array_value = ExtractValue<info::value::ArrayValue>(current_value_, node->base); utils::IdType array_value = current_value_;
utils::ValueType value_type = context_manager_.GetValueType(current_value_); utils::ValueType value_type = context_manager_.GetValueType(array_value);
Visitor::Visit(node->id); Visitor::Visit(node->id);
long long index = *ExtractInternalValue<long long>(current_value_, node->base); // TODO: size_t int64_t index = *ExtractInternalValue<int64_t>(current_value_, node->base); // TODO: size_t
if (index < 0 || index >= (long long)array_value->elements.size()) { if (index < 0) {
error_handling::HandleRuntimeError("Access index out of range", node->base); error_handling::HandleRuntimeError("Access index is negative", node->base);
} }
current_value_ = context_manager_.ToModifiedValue(array_value->elements[index], value_type); // needed ?? if (node->is_string_access_) {
std::string* string_value_info = ExtractInternalValue<std::string>(current_value_, node->base);
if (index >= (int64_t)string_value_info->size()) {
error_handling::HandleRuntimeError("Access index is out of range (string)", node->base);
}
current_value_ = context_manager_.ToModifiedValue((*string_value_info)[index], value_type);
} else {
info::value::ArrayValue* array_value_info = ExtractValue<info::value::ArrayValue>(current_value_, node->base);
if (index >= (int64_t)array_value_info->elements.size()) {
error_handling::HandleRuntimeError("Access index is out of range (array)", node->base);
}
current_value_ = context_manager_.ToModifiedValue(array_value_info->elements[index], value_type);
}
} }
// Other Expressions // Other Expressions
@ -462,6 +479,7 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) {
if (!maybe_function_definition_info.has_value()) { if (!maybe_function_definition_info.has_value()) {
if (HandleBuiltinFunctionCall(node)) { if (HandleBuiltinFunctionCall(node)) {
context_manager_.ExitContext();
return; return;
} }
@ -485,6 +503,16 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) {
if (!maybe_function_definition.has_value()) { if (!maybe_function_definition.has_value()) {
if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier == info::TypeclassGraph::Modifier::Type) { if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier == info::TypeclassGraph::Modifier::Type) {
auto maybe_internal_type = info::type::ToInternalType(typeclass_graph_.GetVertex(node->graph_id_.value()).name);
if (maybe_internal_type.has_value()) {
if (HandleBuiltinTypeFunctionCall(node, maybe_internal_type.value())) {
context_manager_.ExitContext();
return; // TODO: always return from end of function
}
error_handling::HandleRuntimeError("Type function definition not found (builtin type)", node->base);
}
error_handling::HandleRuntimeError("Type function definition not found (by graph_id_)", node->base); error_handling::HandleRuntimeError("Type function definition not found (by graph_id_)", node->base);
} }
@ -515,10 +543,6 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) {
} }
if (!maybe_function_definition.has_value()) { if (!maybe_function_definition.has_value()) {
if (HandleBuiltinTypeclassFunctionCall(node)) {
return;
}
error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base); error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base);
} }
@ -723,25 +747,9 @@ void ExecuteVisitor::Visit(TupleName* node) { // TODO: check
error_handling::HandleRuntimeError("Mismatched field count in tuple variable definition", node->base); error_handling::HandleRuntimeError("Mismatched field count in tuple variable definition", node->base);
} }
if (!is_const_definition_.has_value()) {
error_handling::HandleInternalError("No value in is_const_definition_",
"TypeCheckVisitor.TupleName",
&node->base);
}
utils::ValueType value_type = context_manager_.GetValueType(value);
if (value_type == utils::ValueType::Const
&& is_const_definition_.value() == utils::IsConstModifier::Var) {
error_handling::HandleRuntimeError("TupleName: value type expression not match variable definition modifier", node->base);
}
for (size_t i = 0; i < node->names.size(); ++i) { for (size_t i = 0; i < node->names.size(); ++i) {
current_value_ = maybe_tuple_value.value()->fields[i].second; current_value_ = maybe_tuple_value.value()->fields[i].second;
if (value_type == utils::ValueType::Tmp) { // TODO: ??
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Tmp);
}
Visitor::Visit(node->names[i]); Visitor::Visit(node->names[i]);
} }
@ -798,11 +806,13 @@ void ExecuteVisitor::Visit(AnnotatedName* node) { // TODO: check
&node->base); &node->base);
} }
utils::ValueType value_type = context_manager_.GetValueType(current_value_); // utils::ValueType value_type = context_manager_.GetValueType(current_value_);
if (value_type == utils::ValueType::Const
&& is_const_definition_.value() == utils::IsConstModifier::Var) { // TODO: only on move
error_handling::HandleRuntimeError("AnnotatedName: value type expression not match variable definition modifier", node->base); // if (value_type == utils::ValueType::Const
} // && is_const_definition_.value() == utils::IsConstModifier::Var) {
// error_handling::HandleRuntimeError("AnnotatedName: value type expression not match variable definition modifier", node->base);
// }
current_value_ = context_manager_.ToModifiedValue(value, utils::IsConstModifierToValueType(is_const_definition_.value())); current_value_ = context_manager_.ToModifiedValue(value, utils::IsConstModifierToValueType(is_const_definition_.value()));
if (!context_manager_.DefineVariable(node->name, current_value_)) { if (!context_manager_.DefineVariable(node->name, current_value_)) {
@ -963,28 +973,189 @@ void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) { bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) {
if (node->name == "print") { if (node->name == "print") {
if (node->arguments.size() < 1) {
error_handling::HandleInternalError("Builtin function \"print\" has 0 arguments",
"ExecuteVisitor.HandleBuiltinFunctionCall",
&node->base);
}
Visitor::Visit(node->arguments[0]); Visitor::Visit(node->arguments[0]);
info::builtin::Print(*ExtractInternalValue<std::string>(current_value_, node->base)); info::builtin::Print(*ExtractInternalValue<std::string>(current_value_, node->base));
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()), current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
return true;
} else if (node->name == "scan") { } else if (node->name == "scan") {
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::builtin::Read<std::string>()), current_value_ = context_manager_.AddValue(info::value::InternalValue(info::builtin::Read<std::string>()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
} else if (node->name == "random") { // TODO
current_value_ = context_manager_.AddValue(info::value::InternalValue(rand()),
utils::ValueType::Tmp);
} else {
return false;
}
return true; return true;
} }
bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node,
info::type::InternalType type) {
const std::string& name = node->name;
if (utils::IsBuiltinFunction(name)) {
std::vector<info::value::InternalValue*> arguments;
arguments.reserve(node->arguments.size());
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
arguments.push_back(ExtractValue<info::value::InternalValue>(current_value_, node->base));
}
for (auto& argument : node->arguments) {
Visitor::Visit(argument);
arguments.push_back(ExtractValue<info::value::InternalValue>(current_value_, node->base));
}
error_handling::DebugPrint(info::type::ToString(type));
switch (type) {
case info::type::InternalType::Float:
if (name == "show") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(std::to_string(*arguments[0]->GetValue<double>().value())),
utils::ValueType::Tmp);
} else if (name == "<") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<double>().value() < *arguments[1]->GetValue<double>().value()),
utils::ValueType::Tmp);
} else if (name == "==") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<double>().value() == *arguments[1]->GetValue<double>().value()),
utils::ValueType::Tmp);
} else if (name == "zero") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(0.0),
utils::ValueType::Tmp);
} else if (name == "one") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(1.0),
utils::ValueType::Tmp);
} else if (name == "+=") {
// TODO
error_handling::HandleInternalError("+= not implemented yet (float)",
"ExecuteVisitor.HandleBuiltinTypeFunctionCall",
&node->base);
current_value_ = context_manager_.AddValue(
info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp);
} else {
return false;
}
break;
case info::type::InternalType::Int:
if (name == "show") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(std::to_string(*arguments[0]->GetValue<int64_t>().value())),
utils::ValueType::Tmp);
} else if (name == "<") {
error_handling::DebugPrint("_");/*
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<int64_t>().value() < *arguments[1]->GetValue<int64_t>().value()),
utils::ValueType::Tmp);*/
error_handling::DebugPrint("aaaaaaaa");
} else if (name == "==") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<int64_t>().value() == *arguments[1]->GetValue<int64_t>().value()),
utils::ValueType::Tmp);
} else if (name == "div") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<int64_t>().value() / *arguments[1]->GetValue<int64_t>().value()),
utils::ValueType::Tmp);
} else if (name == "mod") { // TODO: best implementation of mod (read % specification)
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<int64_t>().value() % *arguments[1]->GetValue<int64_t>().value()),
utils::ValueType::Tmp);
} else if (name == "zero") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(0),
utils::ValueType::Tmp);
} else if (name == "one") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(1),
utils::ValueType::Tmp);
} else if (name == "+=") {
// TODO
error_handling::HandleInternalError("+= not implemented yet (int)",
"ExecuteVisitor.HandleBuiltinTypeFunctionCall",
&node->base);
current_value_ = context_manager_.AddValue(
info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp);
} else {
return false;
}
break;
case info::type::InternalType::String: // TODO: string is array ??
if (name == "show") { // do not copy ??
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<std::string>().value()),
utils::ValueType::Tmp);
} else if (name == "<") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<std::string>().value() < *arguments[1]->GetValue<std::string>().value()),
utils::ValueType::Tmp);
} else if (name == "==") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<std::string>().value() == *arguments[1]->GetValue<std::string>().value()),
utils::ValueType::Tmp);
} else if (name == "size") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(static_cast<int64_t>(arguments[0]->GetValue<std::string>().value()->size())),
utils::ValueType::Tmp);
} else if (name == "at") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue((*arguments[0]->GetValue<std::string>().value())[*arguments[1]->GetValue<int64_t>().value()]),
utils::ValueType::Tmp);
} else {
return false;
}
break;
case info::type::InternalType::Char:
if (name == "show") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(std::string{*arguments[0]->GetValue<char>().value()}),
utils::ValueType::Tmp);
} else if (name == "<") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<char>().value() < *arguments[1]->GetValue<char>().value()),
utils::ValueType::Tmp);
} else if (name == "==") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<char>().value() == *arguments[1]->GetValue<char>().value()),
utils::ValueType::Tmp);
} else {
return false;
}
break;
case info::type::InternalType::Bool:
if (name == "show") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(*arguments[0]->GetValue<bool>().value() ? "true" : "false"),
utils::ValueType::Tmp);
} else {
return false;
}
break;
case info::type::InternalType::Unit:
if (name == "show") {
current_value_ = context_manager_.AddValue(
info::value::InternalValue("()"),
utils::ValueType::Tmp);
} else {
return false;
}
break;
default:
// error
break;
}
return false; return false;
} }
bool ExecuteVisitor::HandleBuiltinTypeclassFunctionCall(FunctionCallExpression*) {
return false; return false;
} }

View file

@ -142,11 +142,10 @@ void TypeCheckVisitor::Visit(FunctionDeclaration* node) {
context_manager_.EnterContext(); context_manager_.EnterContext();
for (auto& parameter : node->parameters) { // declaration correctness check // TODO: needed?? for (auto& parameter : node->parameters) { // declaration correctness check // TODO: needed??
auto requirements = typeclass_graph_.GetDependenciesSet(parameter->graph_id_);
current_type_ = context_manager_.AddValue( current_type_ = context_manager_.AddValue(
info::type::AbstractType(utils::AbstractTypeModifier::Abstract, info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
parameter->type, parameter->graph_id_,
requirements), typeclass_graph_),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.DefineLocalType(parameter->type, current_type_); context_manager_.DefineLocalType(parameter->type, current_type_);
} }
@ -223,10 +222,9 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
} }
for (auto& parameter : declaration->parameters) { for (auto& parameter : declaration->parameters) {
auto requirements = typeclass_graph_.GetDependenciesSet(parameter->graph_id_);
current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
parameter->type, parameter->graph_id_,
requirements), typeclass_graph_),
utils::ValueType::Tmp); utils::ValueType::Tmp);
if (!context_manager_.DefineLocalType(parameter->type, current_type_)) { if (!context_manager_.DefineLocalType(parameter->type, current_type_)) {
error_handling::HandleTypecheckError("Can't define function parameter type: abstract type redefinition", node->base); error_handling::HandleTypecheckError("Can't define function parameter type: abstract type redefinition", node->base);
@ -313,7 +311,9 @@ void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) {
auto requirements = typeclass_graph_.GetDependenciesSet(node->type->graph_id_); auto requirements = typeclass_graph_.GetDependenciesSet(node->type->graph_id_);
current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements), current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier,
node->type->graph_id_,
typeclass_graph_),
utils::ValueType::Tmp); utils::ValueType::Tmp);
if (maybe_internal_type.has_value()) { if (maybe_internal_type.has_value()) {
@ -710,6 +710,8 @@ void TypeCheckVisitor::Visit(ReferenceExpression* node) {
context_manager_.GetValueType(current_type_)); // ?? context_manager_.GetValueType(current_type_)); // ??
} }
// TODO: redifinitions for other types and tuples (with const index) ??
// TODO: string should be array
void TypeCheckVisitor::Visit(AccessExpression* node) { void TypeCheckVisitor::Visit(AccessExpression* node) {
Visitor::Visit(node->id); Visitor::Visit(node->id);
if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Int), current_type_)) { if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Int), current_type_)) {
@ -718,14 +720,20 @@ void TypeCheckVisitor::Visit(AccessExpression* node) {
Visitor::Visit(node->name.get()); Visitor::Visit(node->name.get());
std::optional<info::type::ArrayType*> maybe_type_value = context_manager_.GetValue<info::type::ArrayType>(current_type_); auto maybe_type_value = context_manager_.GetValue<info::type::ArrayType>(current_type_);
if (!maybe_type_value.has_value()) { if (maybe_type_value.has_value()) {
current_type_ = maybe_type_value.value()->GetElementsType();
} else {
auto maybe_internal_type_value = context_manager_.GetValue<info::type::InternalType>(current_type_);
if (!maybe_internal_type_value.has_value() || *maybe_internal_type_value.value() != info::type::InternalType::String) {
error_handling::HandleTypecheckError("Access type is not array", node->base); error_handling::HandleTypecheckError("Access type is not array", node->base);
// TODO: redifinitions for other types and tuples (with const index) ??
} }
current_type_ = maybe_type_value.value()->GetElementsType(); current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Char);
node->is_string_access_ = true;
}
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
@ -1643,22 +1651,16 @@ std::optional<FunctionDeclaration*>
bool is_method) { bool is_method) {
std::optional<FunctionDeclaration*> maybe_function_declaration; std::optional<FunctionDeclaration*> maybe_function_declaration;
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name); utils::IdType graph_id = abstract_type_info->GetGraphId();
if (!maybe_typeclass_graph_id.has_value()) {
if (!typeclass_graph_.IsFunctionInVertex(node->name, graph_id)) {
return std::nullopt; return std::nullopt;
} }
auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, graph_id);
maybe_typeclass_graph_id.value());
if (!abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) {
error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (abstract type)", node->base);
}
if (!maybe_typeclass_function_info.has_value()) { if (!maybe_typeclass_function_info.has_value()) {
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)", error_handling::HandleTypecheckError("Function not present in typeclass (abstract type)", node->base);
"TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate",
&node->base);
} }
// TODO: check that const functions not called on var expressions ?? // TODO: check that const functions not called on var expressions ??
@ -1666,10 +1668,10 @@ std::optional<FunctionDeclaration*>
error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base);
} }
node->graph_id_ = maybe_typeclass_graph_id; node->graph_id_ = graph_id;
AddGraphIdLocalAbstractTypes(node->graph_id_.value()); // check AddGraphIdLocalAbstractTypes(node->graph_id_.value()); // check
node->abstract_type_name_ = abstract_type_info->GetName(); node->abstract_type_name_ = typeclass_graph_.GetVertex(node->graph_id_.value()).name;
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
return maybe_function_declaration; return maybe_function_declaration;

View file

@ -73,7 +73,11 @@ std::optional<utils::IdType> TypeclassGraph::FindFunctionTypeclass(const std::st
std::optional<TypeclassGraph::FunctionInfo*> TypeclassGraph::GetFunctionInfo(const std::string& name, std::optional<TypeclassGraph::FunctionInfo*> TypeclassGraph::GetFunctionInfo(const std::string& name,
std::optional<utils::IdType> vertex_id) { std::optional<utils::IdType> vertex_id) {
if (vertex_id.has_value()) { if (vertex_id.has_value()) {
return &verticles_[vertex_id.value()].functions[name]; 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); auto maybe_function_typeclass_id = FindFunctionTypeclass(name);

View file

@ -5,7 +5,7 @@
namespace info::type { namespace info::type {
std::optional<utils::IdType> AbstractType::InContext(const std::unordered_map<std::string, utils::IdType>& context) { std::optional<utils::IdType> AbstractType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
auto type_iter = context.find(name_); auto type_iter = context.find(typeclass_graph_.GetVertex(graph_id_).name);
if (type_iter != context.end()) { if (type_iter != context.end()) {
return type_iter->second; return type_iter->second;
@ -14,12 +14,15 @@ std::optional<utils::IdType> AbstractType::InContext(const std::unordered_map<st
} }
bool AbstractType::Same(const AbstractType& type) const { bool AbstractType::Same(const AbstractType& type) const {
return name_ == type.name_; return graph_id_ == type.graph_id_;
} }
bool AbstractType::operator<(const AbstractType& type) const { bool AbstractType::operator<(const AbstractType& type) const { // TODO: cache DependenciesSet
for (auto& graph_id : requirement_graph_ids_) { auto requirement_graph_ids = typeclass_graph_.GetDependenciesSet(graph_id_);
if (type.requirement_graph_ids_.count(graph_id) == 0) { auto other_requirement_graph_ids = type.typeclass_graph_.GetDependenciesSet(type.graph_id_);
for (auto& graph_id : requirement_graph_ids) {
if (other_requirement_graph_ids.count(graph_id) == 0) {
return false; return false;
} }
} }

View file

@ -38,29 +38,22 @@ bool IsBuiltinFunction(const std::string& name) { // optimize ??
builtin_functions.insert("="); builtin_functions.insert("=");
builtin_functions.insert("<-"); builtin_functions.insert("<-");
builtin_functions.insert("=="); builtin_functions.insert("==");
// builtin_functions.insert("!=");
builtin_functions.insert("<"); builtin_functions.insert("<");
// builtin_functions.insert(">");
// builtin_functions.insert("<=");
// builtin_functions.insert(">=");
builtin_functions.insert("+="); builtin_functions.insert("+=");
builtin_functions.insert("-="); builtin_functions.insert("-=");
builtin_functions.insert("*="); builtin_functions.insert("*=");
builtin_functions.insert("div"); builtin_functions.insert("div");
builtin_functions.insert("mod"); builtin_functions.insert("mod");
builtin_functions.insert("/="); builtin_functions.insert("/=");
// builtin_functions.insert("+");
// builtin_functions.insert("-");
// builtin_functions.insert("*");
// builtin_functions.insert("/");
builtin_functions.insert("&&");
builtin_functions.insert("||");
builtin_functions.insert("size"); builtin_functions.insert("size");
builtin_functions.insert("random"); builtin_functions.insert("random");
builtin_functions.insert("print"); builtin_functions.insert("print");
builtin_functions.insert("scan"); builtin_functions.insert("scan");
builtin_functions.insert("zero"); builtin_functions.insert("zero");
builtin_functions.insert("one"); builtin_functions.insert("one");
builtin_functions.insert("show");
// builtin_functions.insert("read"); // TODO
// builtin_functions.insert("debug_show"); // TODO
return builtin_functions.count(name) != 0; return builtin_functions.count(name) != 0;
} }

View file

@ -1,5 +1,8 @@
#include <optional>
// for clangd // for clangd
#include "../include/values.hpp" #include "../include/values.hpp"
#include "../include/error_handling.hpp"
namespace info::value { namespace info::value {
@ -12,7 +15,7 @@ bool InternalValue::Same(const InternalValue& other_value) const {
case 0: case 0:
return std::get<double>(value) == std::get<double>(other_value.value); return std::get<double>(value) == std::get<double>(other_value.value);
case 1: case 1:
return std::get<long long>(value) == std::get<long long>(other_value.value); return std::get<int64_t>(value) == std::get<int64_t>(other_value.value);
case 2: case 2:
return std::get<std::string>(value) == std::get<std::string>(other_value.value); return std::get<std::string>(value) == std::get<std::string>(other_value.value);
case 3: case 3:
@ -34,6 +37,10 @@ std::optional<utils::IdType> InternalValue::GetFieldValue(const std::string&) co
return std::nullopt; return std::nullopt;
} }
utils::IdType InternalValue::DeepCopy(ValueManager* value_manager) {
return value_manager->ExplicitAddValue(InternalValue(value), utils::ValueType::Tmp);
}
// //
bool TupleValue::Same(const TupleValue& other_value) const { bool TupleValue::Same(const TupleValue& other_value) const {
@ -58,6 +65,18 @@ std::optional<utils::IdType> TupleValue::GetFieldValue(const std::string& name)
return std::nullopt; return std::nullopt;
} }
utils::IdType TupleValue::DeepCopy(ValueManager* value_manager) {
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)};
}
return value_manager->ExplicitAddValue(
TupleValue(std::move(fields_copy), value_manager),
utils::ValueType::Tmp);
}
// //
bool VariantValue::Same(const VariantValue& other_value) const { bool VariantValue::Same(const VariantValue& other_value) const {
@ -73,6 +92,20 @@ std::optional<utils::IdType> VariantValue::GetFieldValue(const std::string& name
return value.GetFieldValue(name); return value.GetFieldValue(name);
} }
utils::IdType VariantValue::DeepCopy(ValueManager* value_manager) {
auto maybe_tuple_deep_copy = value_manager->GetValue<TupleValue>(value.DeepCopy(value_manager));
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),
utils::ValueType::Tmp);
}
// //
bool ReferenceToValue::Same(const ReferenceToValue& other_value) const { bool ReferenceToValue::Same(const ReferenceToValue& other_value) const {
@ -91,6 +124,13 @@ std::optional<utils::IdType> ReferenceToValue::GetFieldValue(const std::string&
return value_manager_->GetAnyValue(value)->GetFieldValue(name); return value_manager_->GetAnyValue(value)->GetFieldValue(name);
} }
utils::IdType ReferenceToValue::DeepCopy(ValueManager* value_manager) {
return value_manager->ExplicitAddValue(
ReferenceToValue(references, value_manager_->GetAnyValue(value)->DeepCopy(value_manager), value_manager),
utils::ValueType::Tmp);
}
// //
bool FunctionValue::Same(const FunctionValue& other_value) const { bool FunctionValue::Same(const FunctionValue& other_value) const {
@ -116,6 +156,12 @@ std::optional<utils::IdType> FunctionValue::GetFieldValue(const std::string&) co
return std::nullopt; return std::nullopt;
} }
utils::IdType FunctionValue::DeepCopy(ValueManager* value_manager) {
return value_manager->ExplicitAddValue(
FunctionValue(function, value_manager),
utils::ValueType::Tmp);
}
// //
bool ArrayValue::Same(const ArrayValue& other_value) const { bool ArrayValue::Same(const ArrayValue& other_value) const {
@ -135,6 +181,18 @@ std::optional<utils::IdType> ArrayValue::GetFieldValue(const std::string&) const
return std::nullopt; return std::nullopt;
} }
utils::IdType ArrayValue::DeepCopy(ValueManager* value_manager) {
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);
}
return value_manager->ExplicitAddValue(
ArrayValue(std::move(elements_copy), is_constant_size, value_manager),
utils::ValueType::Tmp);
}
// //
bool OptionalValue::Same(const OptionalValue& other_value) const { bool OptionalValue::Same(const OptionalValue& other_value) const {
@ -152,6 +210,18 @@ std::optional<utils::IdType> OptionalValue::GetFieldValue(const std::string&) co
return std::nullopt; return std::nullopt;
} }
utils::IdType OptionalValue::DeepCopy(ValueManager* value_manager) {
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), value_manager),
utils::ValueType::Tmp);
}
// //
bool Value::Same(const Value& other_value) const { bool Value::Same(const Value& other_value) const {
@ -209,4 +279,30 @@ std::optional<utils::IdType> Value::GetFieldValue(const std::string& name) const
return std::nullopt; return std::nullopt;
} }
utils::IdType Value::DeepCopy(ValueManager* value_manager) {
size_t index = value.index();
switch (index) {
case 0:
return std::get<InternalValue>(value).DeepCopy(value_manager);
case 1:
return std::get<TupleValue>(value).DeepCopy(value_manager);
case 2:
return std::get<VariantValue>(value).DeepCopy(value_manager);
case 3:
return std::get<ReferenceToValue>(value).DeepCopy(value_manager);
case 4:
return std::get<FunctionValue>(value).DeepCopy(value_manager);
case 5:
return std::get<ArrayValue>(value).DeepCopy(value_manager);
case 6:
return std::get<OptionalValue>(value).DeepCopy(value_manager);
default:
// error
break;
}
exit(1); // better error handling ??
}
}; // namespace info::value }; // namespace info::value

View file

@ -1,9 +1,9 @@
basic (Float : #Ord #Div) basic (Float : #Ord #Div #Show)
basic (Int : #Ord #IDiv) basic (Int : #Ord #IDiv #Show)
basic (String : #Ord) basic (String : #Ord #Show #CharContainer)
basic (Char : #Ord #Enum) basic (Char : #Ord #Show)
basic (Bool : #Ord) basic (Bool : #Ord #Show)
basic Unit basic (Unit : #Show)
// //
@ -35,6 +35,12 @@ def ( || ) : x y =
// //
typeclass CharContainer =
& var size : -> Int
& var at : Int -> Char
//
typeclass Move = typeclass Move =
& var ( <- ) : Move -> Unit // TODO & var ( <- ) : Move -> Unit // TODO
@ -142,11 +148,11 @@ namespace var Ord {
typeclass Show = typeclass Show =
& var show : -> String & var show : -> String
typeclass Read = // typeclass Read = // TODO
& var read : String -> Read // & var read : String -> Read
typeclass DebugShow = // typeclass DebugShow = // TODO
& debug_show : -> String // & debug_show : -> String
// //
@ -171,6 +177,12 @@ typeclass Enum =
// //
decl print : String -> Unit
decl scan : -> String
decl random : -> Int // TODO
//
// // bad // // bad
// typeclass Functor 'A = // typeclass Functor 'A =
// & fmap 'B ('F : (#Functor 'B)) : ('A -> 'B) -> Functor -> 'F // & fmap 'B ('F : (#Functor 'B)) : ('A -> 'B) -> Functor -> 'F
@ -189,22 +201,21 @@ decl ( -- ) : Int -> Int -> Int_0
def ( -- ) : begin end = { def ( -- ) : begin end = {
var current = begin var current = begin
return (while current < end do { return (while current < end do {
; current += 1 //; current += 1
bring current - 1 //bring current - 1
bring 1
}) })
} }
decl print : String -> Unit decl func : String -> Int -> Int
decl scan : -> String def func : s i = {
decl func : String -> Int
def func : s = {
; print: s ; print: s
; print: (i.show:)
return 5 return 5
} }
exec main { exec main {
for i in 0--9 do func: "abacaba" for i in 0--9 do func: "abacaba" i
; print: ({ ; print: ({
if true then bring scan: else { ; print: "aaa" } if true then bring scan: else { ; print: "aaa" }
bring "nothing" bring "nothing"