mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-06 23:18:44 +00:00
print & read builtin functions, fixes. execution of programs partially works
This commit is contained in:
parent
27f643dfbc
commit
2556efcaba
16 changed files with 537 additions and 215 deletions
|
|
@ -1,9 +1,11 @@
|
|||
// for clangd
|
||||
#include "../include/execute_visitor.hpp"
|
||||
#include <cwchar>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
// for clangd
|
||||
#include "../include/execute_visitor.hpp"
|
||||
#include "../include/builtin_functions.hpp"
|
||||
|
||||
|
||||
// TODO
|
||||
|
||||
namespace interpreter {
|
||||
|
|
@ -46,7 +48,9 @@ void ExecuteVisitor::Visit(FunctionDeclaration*) {} // no value
|
|||
|
||||
void ExecuteVisitor::Visit(FunctionDefinitionStatement* node) { // visited on function call
|
||||
// Visit(node->definition.get());
|
||||
context_manager_.EnterContext();
|
||||
Visitor::Visit(node->value);
|
||||
context_manager_.ExitContext();
|
||||
}
|
||||
|
||||
void ExecuteVisitor::Visit(TypeDefinitionStatement*) {} // no value
|
||||
|
|
@ -244,8 +248,12 @@ void ExecuteVisitor::Visit(ForLoop* node) {
|
|||
info::value::ArrayValue* interval = ExtractValue<info::value::ArrayValue>(current_value_, node->base);
|
||||
|
||||
for (auto& value : interval->elements) {
|
||||
context_manager_.EnterContext(); // TODO
|
||||
|
||||
current_value_ = value;
|
||||
Visitor::Visit(node->variable);
|
||||
is_const_definition_ = node->variable_modifier;
|
||||
Visitor::Visit(node->variable); // TODO: assign variable, instead of making new
|
||||
is_const_definition_ = std::nullopt;
|
||||
|
||||
Visitor::Visit(node->statement);
|
||||
if (active_loop_control_expression_.has_value()) {
|
||||
|
|
@ -258,6 +266,8 @@ void ExecuteVisitor::Visit(ForLoop* node) {
|
|||
|
||||
}
|
||||
result.push_back(current_value_);
|
||||
|
||||
context_manager_.ExitContext(); // TODO
|
||||
}
|
||||
|
||||
current_value_ = context_manager_.AddValue(
|
||||
|
|
@ -302,10 +312,11 @@ void ExecuteVisitor::Visit(Block* node) {
|
|||
Visitor::Visit(statement);
|
||||
if (returned_value_.has_value()) {
|
||||
current_value_ = returned_value_.value();
|
||||
returned_value_ = std::nullopt; // ??
|
||||
returned_value_ = std::nullopt; // TODO: ?? ("return" exits only from one block)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
context_manager_.ExitContext();
|
||||
|
||||
current_value_ = context_manager_.AddValue(
|
||||
|
|
@ -326,36 +337,6 @@ void ExecuteVisitor::Visit(LoopControlExpression& node) {
|
|||
|
||||
// Operators
|
||||
|
||||
// TODO: function call expression used instead
|
||||
/////////////////////////////////////////////////
|
||||
// void ExecuteVisitor::Visit(BinaryOperatorExpression* node) {
|
||||
// context_manager_.EnterContext();
|
||||
//
|
||||
// auto maybe_function_definition = global_info_.GetFunctionInfo(node->function_id_).definition;
|
||||
//
|
||||
// if (maybe_function_definition.has_value()) {
|
||||
// Visitor::Visit(node->left_expression);
|
||||
// // TODO: custom argument value types, references, etc.
|
||||
// current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
||||
// context_manager_.DefineVariable(
|
||||
// node->is_method_ ? utils::ClassInternalVarName : maybe_function_definition.value().argument_names[0],
|
||||
// current_value_);
|
||||
//
|
||||
// Visitor::Visit(node->left_expression);
|
||||
// // TODO: custom argument value types, references, etc.
|
||||
// current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
||||
// context_manager_.DefineVariable(maybe_function_definition.value().argument_names[node->is_method_ ? 0 : 1], current_value_);
|
||||
//
|
||||
// Visit(maybe_function_definition.value().node);
|
||||
// } else {
|
||||
// // TODO: builtin operators, etc. (imports?)
|
||||
// error_handling::HandleRuntimeError("Binary operator definition not found", node->base);
|
||||
// }
|
||||
//
|
||||
// context_manager_.ExitContext();
|
||||
// }
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
void ExecuteVisitor::Visit(ReferenceExpression* node) {
|
||||
// TODO: check, that there is no references to "Tmp"??
|
||||
Visit(node->expression.get());
|
||||
|
|
@ -385,18 +366,18 @@ void ExecuteVisitor::Visit(AccessExpression* node) {
|
|||
|
||||
// Other Expressions
|
||||
|
||||
// TODO
|
||||
// TODO: typeclass functions
|
||||
// TODO: builtin functions
|
||||
// TODO: binary operator expression
|
||||
// TODO: refactor, separate to several functions
|
||||
// TODO: more builtin functions, better handling (??)
|
||||
void ExecuteVisitor::Visit(FunctionCallExpression* node) {
|
||||
context_manager_.EnterContext();
|
||||
|
||||
if (node->prefix.has_value()) {
|
||||
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
|
||||
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
|
||||
// modify value on const methods, etc. ??
|
||||
context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_);
|
||||
|
||||
if (!context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_)) {
|
||||
error_handling::HandleRuntimeError("Variable redefinition (mathod caller var)", node->base);
|
||||
}
|
||||
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
|
||||
TypeExpression& prefix = *std::get<std::unique_ptr<TypeExpression>>(node->prefix.value());
|
||||
|
||||
|
|
@ -407,46 +388,135 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) {
|
|||
|
||||
CollectTypeContext(prefix.type);
|
||||
} else {
|
||||
// error
|
||||
error_handling::HandleInternalError("Unexpected prefix type",
|
||||
"ExecuteVisitor.FunctionCallExpression",
|
||||
&node->base);
|
||||
}
|
||||
} else {
|
||||
if (node->is_method_of_first_argument_) {
|
||||
Visitor::Visit(node->arguments[0]);
|
||||
context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_);
|
||||
if (!context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_)) {
|
||||
error_handling::HandleRuntimeError("Variable redefinition (mathod caller var)", node->base);
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (!node->function_id_.has_value()) {
|
||||
// TODO: typeclass function
|
||||
error_handling::HandleInternalError("Typeclass functions not implemented yet",
|
||||
"ExecuteVisitor.FunctionCallExpression");
|
||||
}
|
||||
FunctionDeclaration* function_declaration = nullptr;
|
||||
FunctionDefinitionStatement* function_definition = nullptr;
|
||||
|
||||
auto function_declaration = global_info_.GetFunctionInfo(node->function_id_.value()).declaration.value(); // checked in type_check_visitor
|
||||
if (node->function_id_.has_value()) {
|
||||
auto maybe_function_declaration_info = global_info_.GetFunctionInfo(node->function_id_.value()).declaration;
|
||||
|
||||
if (!maybe_function_declaration_info.has_value()) {
|
||||
error_handling::HandleRuntimeError("Function declaration not found (for namespace function)", node->base);
|
||||
// always namespace function ??
|
||||
}
|
||||
|
||||
function_declaration = maybe_function_declaration_info.value().node;
|
||||
|
||||
auto maybe_function_definition_info = global_info_.GetFunctionInfo(node->function_id_.value()).definition;
|
||||
|
||||
if (!maybe_function_definition_info.has_value()) {
|
||||
if (HandleBuiltinFunctionCall(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base);
|
||||
}
|
||||
|
||||
function_definition = maybe_function_definition_info.value().node;
|
||||
|
||||
} else if (node->graph_id_.has_value()) {
|
||||
std::optional<FunctionDefinitionStatement*> maybe_function_definition;
|
||||
|
||||
auto maybe_function_graph_info = typeclass_graph_.GetFunctionInfo(node->name,
|
||||
node->graph_id_.value());
|
||||
|
||||
if (!maybe_function_graph_info.has_value()) {
|
||||
error_handling::HandleRuntimeError("Function info not found (by graph_id_)", node->base);
|
||||
}
|
||||
|
||||
function_declaration = maybe_function_graph_info.value()->declaration;
|
||||
maybe_function_definition = maybe_function_graph_info.value()->definition;
|
||||
|
||||
if (!maybe_function_definition.has_value()) {
|
||||
if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier == info::TypeclassGraph::Modifier::Type) {
|
||||
error_handling::HandleRuntimeError("Type function definition not found (by graph_id_)", node->base);
|
||||
}
|
||||
|
||||
if (!node->abstract_type_name_.has_value()) {
|
||||
error_handling::HandleInternalError("Typeclass function's abstract_type_name_ has no value",
|
||||
"ExecuteVisitor.FunctionCallExpression",
|
||||
&node->base);
|
||||
}
|
||||
|
||||
auto maybe_type_id = context_manager_.FindLocalType(node->abstract_type_name_.value());
|
||||
if (!maybe_type_id.has_value()) {
|
||||
error_handling::HandleRuntimeError("Function's abstract type not found (by abstract_type_name_)", node->base);
|
||||
}
|
||||
|
||||
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(maybe_type_id.value());
|
||||
|
||||
if (!maybe_type_info.has_value()) {
|
||||
error_handling::HandleRuntimeError("Function's abstract type replacement defined type is not AnyType", node->base);
|
||||
}
|
||||
|
||||
maybe_function_graph_info = typeclass_graph_.GetFunctionInfo(node->name, maybe_type_info.value()->type.node->graph_id_);
|
||||
|
||||
if (!maybe_function_graph_info.has_value()) {
|
||||
error_handling::HandleRuntimeError("Function info not found (by abstract type graph_id_)", node->base);
|
||||
}
|
||||
|
||||
maybe_function_definition = maybe_function_graph_info.value()->definition;
|
||||
}
|
||||
|
||||
if (!maybe_function_definition.has_value()) {
|
||||
if (HandleBuiltinTypeclassFunctionCall(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base);
|
||||
}
|
||||
|
||||
function_definition = maybe_function_definition.value();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node->parameters.size(); ++i) {
|
||||
// TODO: local abstract types, absract types, etc.
|
||||
utils::IdType type_id = 0;
|
||||
|
||||
context_manager_.DefineLocalType(function_declaration.parameters[i].type, node->parameters[i]->type_id_.value()); // TODO: check
|
||||
}
|
||||
if (node->parameters[i]->type_id_.has_value()) {
|
||||
type_id = node->parameters[i]->type_id_.value();
|
||||
} else {
|
||||
auto maybe_parameter_type_id = context_manager_.FindLocalType(node->parameters[i]->type.type);
|
||||
|
||||
auto maybe_function_definition = global_info_.GetFunctionInfo(node->function_id_.value()).definition;
|
||||
if (!maybe_parameter_type_id.has_value()) {
|
||||
error_handling::HandleInternalError("Parameter type not found",
|
||||
"ExecuteVisitor.FunctionCallExpression",
|
||||
&node->base);
|
||||
}
|
||||
|
||||
if (maybe_function_definition.has_value()) {
|
||||
for (size_t i = (node->is_method_of_first_argument_ ? 1 : 0); i < node->arguments.size(); ++i) {
|
||||
Visitor::Visit(node->arguments[i]);
|
||||
// TODO: custom argument value types, references, etc.
|
||||
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
||||
context_manager_.DefineVariable(maybe_function_definition.value().argument_names[i], current_value_);
|
||||
type_id = maybe_parameter_type_id.value();
|
||||
}
|
||||
|
||||
Visit(maybe_function_definition.value().node);
|
||||
} else {
|
||||
error_handling::HandleRuntimeError("Function definition not found", node->base);
|
||||
// TODO: functions, defined in typeclasses ??
|
||||
if (!context_manager_.DefineLocalType(function_declaration->parameters[i]->type,
|
||||
type_id)) {
|
||||
error_handling::HandleRuntimeError("Type redefinition (function argument)", node->base);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = (node->is_method_of_first_argument_ ? 1 : 0); i < node->arguments.size(); ++i) {
|
||||
Visitor::Visit(node->arguments[i]);
|
||||
|
||||
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
|
||||
if (!context_manager_.DefineVariable(function_definition->definition->arguments[i],
|
||||
current_value_)) {
|
||||
error_handling::HandleRuntimeError("Variable redefinition (function argument)", node->base);
|
||||
}
|
||||
}
|
||||
|
||||
context_manager_.ChangeHidingOfCurrentContextTo(true);
|
||||
Visit(function_definition);
|
||||
|
||||
context_manager_.ExitContext();
|
||||
}
|
||||
|
||||
|
|
@ -534,9 +604,10 @@ void ExecuteVisitor::Visit(TypeConstructor* node) {
|
|||
}
|
||||
|
||||
// TODO
|
||||
void ExecuteVisitor::Visit(LambdaFunction*) {
|
||||
void ExecuteVisitor::Visit(LambdaFunction* node) {
|
||||
error_handling::HandleInternalError("Lambda function are not implemented yet",
|
||||
"ExecuteVisitor.LambdaFunction");
|
||||
"ExecuteVisitor.LambdaFunction",
|
||||
&node->base);
|
||||
}
|
||||
|
||||
void ExecuteVisitor::Visit(ArrayExpression* node) {
|
||||
|
|
@ -557,11 +628,13 @@ void ExecuteVisitor::Visit(ArrayExpression* node) {
|
|||
|
||||
void ExecuteVisitor::Visit(NameExpression* node) { // TODO: check
|
||||
if (node->names.empty()) {
|
||||
error_handling::HandleInternalError("Names array is empty", "ExecuteVisitor.NameExpression");
|
||||
error_handling::HandleInternalError("Names array is empty",
|
||||
"ExecuteVisitor.NameExpression",
|
||||
&node->base);
|
||||
}
|
||||
|
||||
std::optional<utils::IdType> maybe_variable_value =
|
||||
context_manager_.GetVariableInfo(node->names[0]);
|
||||
context_manager_.FindVariable(node->names[0]);
|
||||
|
||||
if (!maybe_variable_value.has_value()) {
|
||||
error_handling::HandleRuntimeError("Variable not found", node->base);
|
||||
|
|
@ -599,7 +672,9 @@ void ExecuteVisitor::Visit(TupleName* node) { // TODO: check
|
|||
}
|
||||
|
||||
if (!is_const_definition_.has_value()) {
|
||||
error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.TupleName");
|
||||
error_handling::HandleInternalError("No value in is_const_definition_",
|
||||
"TypeCheckVisitor.TupleName",
|
||||
&node->base);
|
||||
}
|
||||
|
||||
utils::ValueType value_type = context_manager_.GetValueType(value);
|
||||
|
|
@ -667,7 +742,8 @@ void ExecuteVisitor::Visit(AnnotatedName* node) { // TODO: check
|
|||
|
||||
if (!is_const_definition_.has_value()) {
|
||||
error_handling::HandleInternalError("No value in is_const_definition_",
|
||||
"TypeCheckVisitor.AnnotatedName");
|
||||
"TypeCheckVisitor.AnnotatedName",
|
||||
&node->base);
|
||||
}
|
||||
|
||||
utils::ValueType value_type = context_manager_.GetValueType(current_value_);
|
||||
|
|
@ -749,16 +825,26 @@ bool ExecuteVisitor::HandleCondition(Expression& node, const BaseNode& base_node
|
|||
return *ExtractInternalValue<bool>(current_value_, base_node);
|
||||
}
|
||||
|
||||
// TODO: handle abstract types, handle local abstract types, etc.
|
||||
// TODO: handle abstract types, handle local abstract types, etc. // partially done (check needed)
|
||||
void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) {
|
||||
utils::IdType type_id = 0;
|
||||
|
||||
if (!type.type_id_.has_value()) {
|
||||
return;
|
||||
auto maybe_local_type_id = context_manager_.FindLocalType(type.type);
|
||||
if (!maybe_local_type_id.has_value()) {
|
||||
return;
|
||||
}
|
||||
type_id = maybe_local_type_id.value(); // TODO: check
|
||||
} else {
|
||||
type_id = type.type_id_.has_value();
|
||||
}
|
||||
|
||||
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(type.type_id_.value());
|
||||
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(type_id);
|
||||
|
||||
if (!maybe_type_info.has_value()) {
|
||||
error_handling::HandleInternalError("CollectTypeContext unimplemented anything except AnyType", "ExecuteVisitor.CollectTYpeContext");
|
||||
error_handling::HandleInternalError("CollectTypeContext implemented only for AnyType",
|
||||
"ExecuteVisitor.CollectTYpeContext",
|
||||
std::nullopt);
|
||||
}
|
||||
|
||||
info::definition::AnyType& type_info = *maybe_type_info.value(); // check, that has value ??
|
||||
|
|
@ -771,7 +857,6 @@ void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
|
||||
utils::IdType value = current_value_;
|
||||
|
||||
|
|
@ -798,5 +883,34 @@ void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) {
|
||||
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]);
|
||||
info::builtin::Print(*ExtractInternalValue<std::string>(current_value_, node->base));
|
||||
|
||||
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()),
|
||||
utils::ValueType::Tmp);
|
||||
return true;
|
||||
} else if (node->name == "read") {
|
||||
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::builtin::Read<std::string>()),
|
||||
utils::ValueType::Tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ExecuteVisitor::HandleBuiltinTypeclassFunctionCall(FunctionCallExpression*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue