mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-06 06:58:45 +00:00
fixes, optional type name added
This commit is contained in:
parent
d38d75c9d8
commit
0850e6aa6b
14 changed files with 163 additions and 99 deletions
|
|
@ -31,6 +31,11 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void ExecutePartition(interpreter::tokens::PartitionStatement* partition) {
|
void ExecutePartition(interpreter::tokens::PartitionStatement* partition) {
|
||||||
|
for (size_t i = 0; i < info::type::InternalTypesCount; ++i) {
|
||||||
|
info::type::InternalType type = static_cast<info::type::InternalType>(i);
|
||||||
|
std::string type_name = info::type::ToString(type);
|
||||||
|
context_manager_.DefineLocalType(type_name, global_info_.FindAbstractType(type_name).value()->node->type->graph_id_);
|
||||||
|
}
|
||||||
Visit(partition);
|
Visit(partition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,6 @@ public:
|
||||||
|
|
||||||
std::optional<utils::IdType> FindLocalTypeId(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> FindTypeclassId(const std::string& typeclass);
|
||||||
|
|
||||||
std::optional<utils::IdType> FindConstructorId(const std::optional<std::vector<std::string>>& path,
|
std::optional<utils::IdType> FindConstructorId(const std::optional<std::vector<std::string>>& path,
|
||||||
|
|
@ -164,14 +162,6 @@ public:
|
||||||
return global_info_.GetTypeInfo<T>(id.value());
|
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<definition::Typeclass*> FindTypeclass(const std::string& typeclass) {
|
||||||
std::optional<utils::IdType> id = FindTypeclassId(typeclass);
|
std::optional<utils::IdType> id = FindTypeclassId(typeclass);
|
||||||
if (!id.has_value()) {
|
if (!id.has_value()) {
|
||||||
|
|
@ -368,6 +358,16 @@ public:
|
||||||
// function declarations & definitions should be added latter
|
// function declarations & definitions should be added latter
|
||||||
std::optional<utils::IdType> AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node);
|
std::optional<utils::IdType> AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node);
|
||||||
|
|
||||||
|
std::optional<utils::IdType> FindAbstractTypeId(const std::string& abstract_type);
|
||||||
|
|
||||||
|
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 &GetAbstractTypeInfo(id.value());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CollectFunctionInfo(
|
void CollectFunctionInfo(
|
||||||
utils::IdType current_namespace,
|
utils::IdType current_namespace,
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,7 @@ struct TypeExpression {
|
||||||
ParametrizedType type;
|
ParametrizedType type;
|
||||||
|
|
||||||
std::optional<size_t> array_size; // if array; 0 - dynamic size
|
std::optional<size_t> array_size; // if array; 0 - dynamic size
|
||||||
|
bool is_optional = false; // for optionals
|
||||||
|
|
||||||
std::optional<utils::IdType> type_id_;
|
std::optional<utils::IdType> type_id_;
|
||||||
std::optional<utils::IdType> constructor_id_;
|
std::optional<utils::IdType> constructor_id_;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public:
|
||||||
// init internal type abstrac types
|
// init internal type abstrac types
|
||||||
for (size_t i = 0; i < info::type::InternalTypesCount; ++i) {
|
for (size_t i = 0; i < info::type::InternalTypesCount; ++i) {
|
||||||
info::type::InternalType type = static_cast<info::type::InternalType>(i);
|
info::type::InternalType type = static_cast<info::type::InternalType>(i);
|
||||||
Visit(namespace_visitor_.FindAbstractType(info::type::ToString(type)).value()->node);
|
Visit(global_info_.FindAbstractType(info::type::ToString(type)).value()->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
Visit(source_file);
|
Visit(source_file);
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit ddb08e9b65123324800d1126d38764764363c0e5
|
Subproject commit 5346d008497d93d30db4933dc3744b3de35cebf8
|
||||||
BIN
src/.link_symbols_visitor.cpp.kate-swp
Normal file
BIN
src/.link_symbols_visitor.cpp.kate-swp
Normal file
Binary file not shown.
|
|
@ -53,19 +53,11 @@ void BuildVisitor::Visit(Namespace* node) {
|
||||||
|
|
||||||
auto parse_node = current_node_;
|
auto parse_node = current_node_;
|
||||||
|
|
||||||
size_t child_count = parse_node.ChildCount();
|
|
||||||
|
|
||||||
if (child_count > 3) { // "namespace", ["var"/"const",] type, scope
|
|
||||||
std::string modifier = parse_node.NthChild(1).GetValue();
|
std::string modifier = parse_node.NthChild(1).GetValue();
|
||||||
if (modifier == "const") {
|
if (modifier == "const") {
|
||||||
node->modifier = utils::ClassInternalsModifier::Const;
|
node->modifier = utils::ClassInternalsModifier::Const;
|
||||||
} else if (modifier == "var") {
|
} else if (modifier == "var") {
|
||||||
node->modifier = utils::ClassInternalsModifier::Var;
|
node->modifier = utils::ClassInternalsModifier::Var;
|
||||||
} else {
|
|
||||||
error_handling::HandleInternalError("Can't parse namespace modifier",
|
|
||||||
"BuildVisitor.Namespace",
|
|
||||||
&node->base);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
node->modifier = utils::ClassInternalsModifier::Static;
|
node->modifier = utils::ClassInternalsModifier::Static;
|
||||||
}
|
}
|
||||||
|
|
@ -1380,17 +1372,50 @@ void BuildVisitor::Visit(TypeExpression* node) {
|
||||||
Visit(&node->type);
|
Visit(&node->type);
|
||||||
++excluded_child_count;
|
++excluded_child_count;
|
||||||
|
|
||||||
current_node_ = current_node_.NextSibling();
|
auto suffix_node1 = current_node_.NextSibling();
|
||||||
|
|
||||||
|
// TODO: better structure // TODO: check
|
||||||
|
if (!suffix_node1.IsNull()) {
|
||||||
|
auto suffix_node2 = suffix_node1.NextSibling();
|
||||||
|
if (!suffix_node2.IsNull()) {
|
||||||
|
auto suffix_node3 = suffix_node2.NextSibling();
|
||||||
|
if (!suffix_node3.IsNull()) {
|
||||||
|
current_node_ = suffix_node2;
|
||||||
|
|
||||||
|
NumberLiteral literal;
|
||||||
|
Visit(&literal);
|
||||||
|
node->array_size = literal.value;
|
||||||
|
++excluded_child_count;
|
||||||
|
|
||||||
|
node->is_optional = true;
|
||||||
|
} else {
|
||||||
|
if (suffix_node1.GetValue() == "_" && suffix_node2.GetValue() == "!") {
|
||||||
|
node->array_size = 0;
|
||||||
|
|
||||||
|
node->is_optional = true;
|
||||||
|
} else if (suffix_node1.GetValue() == "_") {
|
||||||
|
current_node_ = suffix_node2;
|
||||||
|
|
||||||
if (!current_node_.IsNull()) {
|
|
||||||
current_node_ = current_node_.NextSibling();
|
|
||||||
if (!current_node_.IsNull()) {
|
|
||||||
NumberLiteral literal;
|
NumberLiteral literal;
|
||||||
Visit(&literal);
|
Visit(&literal);
|
||||||
node->array_size = literal.value;
|
node->array_size = literal.value;
|
||||||
++excluded_child_count;
|
++excluded_child_count;
|
||||||
} else {
|
} else {
|
||||||
|
error_handling::HandleInternalError("Undefined suffix (2 elements)",
|
||||||
|
"BuildVisitor.TypeExpression",
|
||||||
|
std::nullopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (suffix_node1.GetValue() == "_") {
|
||||||
node->array_size = 0;
|
node->array_size = 0;
|
||||||
|
} else if (suffix_node1.GetValue() == "!") {
|
||||||
|
node->is_optional = true;
|
||||||
|
} else {
|
||||||
|
error_handling::HandleInternalError("Undefined suffix (1 element)",
|
||||||
|
"BuildVisitor.TypeExpression",
|
||||||
|
std::nullopt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& a
|
||||||
// error_handling::HandleNamesError("Can't redefine basic type as abstract type", base_node);
|
// error_handling::HandleNamesError("Can't redefine basic type as abstract type", base_node);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (FindAbstractType(abstract_type).has_value()) {
|
if (global_info_.FindAbstractType(abstract_type).has_value()) {
|
||||||
error_handling::HandleNamesError("More then one abstract type with the same name in namespace", base_node);
|
error_handling::HandleNamesError("More then one abstract type with the same name in namespace", base_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -385,16 +385,6 @@ std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindLocalTypeId(const
|
||||||
return std::nullopt;
|
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) {
|
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindTypeclassId(const std::string& typeclass) {
|
||||||
auto typeclass_id_iter = global_info_.name_to_typeclass_.find(typeclass);
|
auto typeclass_id_iter = global_info_.name_to_typeclass_.find(typeclass);
|
||||||
|
|
||||||
|
|
@ -578,6 +568,16 @@ std::optional<utils::IdType> GlobalInfo::AddAnnotatedTypeToGraph(interpreter::to
|
||||||
TypeclassGraph::Modifier::Type);
|
TypeclassGraph::Modifier::Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<utils::IdType> GlobalInfo::FindAbstractTypeId(const std::string& abstract_type) {
|
||||||
|
auto abstract_type_id_iter = name_to_abstract_type_.find(abstract_type);
|
||||||
|
|
||||||
|
if (abstract_type_id_iter != name_to_abstract_type_.end()) {
|
||||||
|
return abstract_type_id_iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
void GlobalInfo::CollectFunctionInfo(
|
void GlobalInfo::CollectFunctionInfo(
|
||||||
utils::IdType current_namespace,
|
utils::IdType current_namespace,
|
||||||
utils::ClassInternalsModifier modifier,
|
utils::ClassInternalsModifier modifier,
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) {
|
||||||
if (maybe_type_namespace.has_value()) {
|
if (maybe_type_namespace.has_value()) {
|
||||||
info::definition::Namespace* type_namespace = maybe_type_namespace.value();
|
info::definition::Namespace* type_namespace = maybe_type_namespace.value();
|
||||||
|
|
||||||
for (ssize_t i = (ssize_t)node->path.size(); i >= 0; --i) {
|
for (ssize_t i = (ssize_t)node->path.size() - 1; i >= 0; --i) {
|
||||||
info::definition::Namespace* parent_namespace = &global_info_.GetNamespaceInfo(type_namespace->parent_namespace);
|
info::definition::Namespace* parent_namespace = &global_info_.GetNamespaceInfo(type_namespace->parent_namespace);
|
||||||
|
|
||||||
auto type_iter = parent_namespace->types.find(type_namespace->type_name);
|
auto type_iter = parent_namespace->types.find(type_namespace->type_name);
|
||||||
|
|
|
||||||
|
|
@ -660,6 +660,10 @@ void PrintVisitor::Visit(TypeExpression* node) {
|
||||||
out_ << " [array size: " << node->array_size.value() << ']';
|
out_ << " [array size: " << node->array_size.value() << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->is_optional) {
|
||||||
|
out_ << " [optional]";
|
||||||
|
}
|
||||||
|
|
||||||
out_ << "] (";
|
out_ << "] (";
|
||||||
for (auto& type : node->path) {
|
for (auto& type : node->path) {
|
||||||
Visit(&type);
|
Visit(&type);
|
||||||
|
|
|
||||||
|
|
@ -249,8 +249,6 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
||||||
returned_type_ = current_type_;
|
returned_type_ = current_type_;
|
||||||
}
|
}
|
||||||
if (!context_manager_.EqualValues(returned_type, returned_type_.value())) {
|
if (!context_manager_.EqualValues(returned_type, returned_type_.value())) {
|
||||||
error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type)->ToString());
|
|
||||||
error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type_.value())->ToString());
|
|
||||||
error_handling::HandleTypecheckError("Wrong function return type", node->base);
|
error_handling::HandleTypecheckError("Wrong function return type", node->base);
|
||||||
}
|
}
|
||||||
returned_type_ = std::nullopt;
|
returned_type_ = std::nullopt;
|
||||||
|
|
@ -284,7 +282,7 @@ void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) {
|
||||||
auto function_iter = type_functions.find(function.first);
|
auto function_iter = type_functions.find(function.first);
|
||||||
|
|
||||||
if (function_iter == type_functions.end() || !global_info_.GetFunctionInfo(function_iter->second).definition.has_value()) {
|
if (function_iter == type_functions.end() || !global_info_.GetFunctionInfo(function_iter->second).definition.has_value()) {
|
||||||
error_handling::HandleTypecheckError("Type is not satisfy typeclass requirements: " + function.first + " is not defined", node->base);
|
error_handling::HandleTypecheckError("Type not define all required functions: " + function.first + " is not defined", node->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1281,16 +1279,6 @@ void TypeCheckVisitor::Visit(TypeExpression* node) {
|
||||||
std::unordered_map<std::string, utils::IdType> context;
|
std::unordered_map<std::string, utils::IdType> context;
|
||||||
CollectTypeExpressionContext(*node, context);
|
CollectTypeExpressionContext(*node, context);
|
||||||
|
|
||||||
// TODO: -------- remove, unneeded ------
|
|
||||||
// auto maybe_internal_type = info::type::ToInternalType(node->type.type);
|
|
||||||
//
|
|
||||||
// if (maybe_internal_type.has_value()) { // TODO: ???
|
|
||||||
// // checks made in link_symbols_visitor
|
|
||||||
// current_type_ =
|
|
||||||
// context_manager_.AddValue<info::type::InternalType>(
|
|
||||||
// maybe_internal_type.value(),
|
|
||||||
// utils::ValueType::Tmp);
|
|
||||||
// } else {
|
|
||||||
std::optional<utils::IdType> maybe_local_abstract_type =
|
std::optional<utils::IdType> maybe_local_abstract_type =
|
||||||
context_manager_.FindLocalType(node->type.type);
|
context_manager_.FindLocalType(node->type.type);
|
||||||
if (node->path.empty() && maybe_local_abstract_type.has_value()) {
|
if (node->path.empty() && maybe_local_abstract_type.has_value()) {
|
||||||
|
|
@ -1309,7 +1297,6 @@ void TypeCheckVisitor::Visit(TypeExpression* node) {
|
||||||
} else {
|
} else {
|
||||||
error_handling::HandleTypecheckError("Type not found", node->base);
|
error_handling::HandleTypecheckError("Type not found", node->base);
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
if (node->array_size.has_value()) {
|
if (node->array_size.has_value()) {
|
||||||
current_type_ = context_manager_.AddValue(
|
current_type_ = context_manager_.AddValue(
|
||||||
|
|
@ -1317,6 +1304,12 @@ void TypeCheckVisitor::Visit(TypeExpression* node) {
|
||||||
utils::ValueType::Tmp);
|
utils::ValueType::Tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->is_optional) {
|
||||||
|
current_type_ = context_manager_.AddValue(
|
||||||
|
info::type::OptionalType(current_type_, context_manager_.GetValueManager()),
|
||||||
|
utils::ValueType::Tmp);
|
||||||
|
}
|
||||||
|
|
||||||
node->base.type_ = current_type_;
|
node->base.type_ = current_type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1433,7 +1426,10 @@ void TypeCheckVisitor::CollectTypeExpressionContext(const TypeExpression& type_e
|
||||||
utils::IdType TypeCheckVisitor::TypeInContext(utils::IdType type,
|
utils::IdType TypeCheckVisitor::TypeInContext(utils::IdType type,
|
||||||
const std::unordered_map<std::string, utils::IdType>& context) {
|
const std::unordered_map<std::string, utils::IdType>& context) {
|
||||||
info::type::Type type_in_context = *context_manager_.GetAnyValue(type);
|
info::type::Type type_in_context = *context_manager_.GetAnyValue(type);
|
||||||
type_in_context.InContext(context);
|
auto maybe_new_type = type_in_context.InContext(context);
|
||||||
|
if (maybe_new_type.has_value()) {
|
||||||
|
return maybe_new_type.value();
|
||||||
|
}
|
||||||
return context_manager_.AddValue(std::move(type_in_context), utils::ValueType::Tmp);
|
return context_manager_.AddValue(std::move(type_in_context), utils::ValueType::Tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -925,6 +925,10 @@ void TypedPrintVisitor::Visit(TypeExpression* node) {
|
||||||
out_ << " [array size: " << node->array_size.value() << ']';
|
out_ << " [array size: " << node->array_size.value() << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->is_optional) {
|
||||||
|
out_ << " [optional]";
|
||||||
|
}
|
||||||
|
|
||||||
out_ << "] (";
|
out_ << "] (";
|
||||||
for (auto& type : node->path) {
|
for (auto& type : node->path) {
|
||||||
Visit(&type);
|
Visit(&type);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ struct (Complex : #Value) =
|
||||||
|
|
||||||
struct Task =
|
struct Task =
|
||||||
& name : String
|
& name : String
|
||||||
& duration : Float
|
& duration : Float!
|
||||||
|
|
||||||
class Employee =
|
class Employee =
|
||||||
& name : String
|
& name : String
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ typeclass Show =
|
||||||
& var show : -> String
|
& var show : -> String
|
||||||
|
|
||||||
typeclass Read =
|
typeclass Read =
|
||||||
& var read : String -> Read
|
& read : String -> Read
|
||||||
|
|
||||||
typeclass (Str : #Show #Read)
|
typeclass (Str : #Show #Read)
|
||||||
|
|
||||||
|
|
@ -179,9 +179,11 @@ typeclass Enum =
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
namespace IO {
|
||||||
decl print : String -> Unit
|
decl print : String -> Unit
|
||||||
decl scan : -> String
|
decl scan : -> String
|
||||||
decl random : -> Int // TODO
|
decl random : -> Int // TODO
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
@ -211,19 +213,46 @@ def ( -- ) : begin end = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
decl func : String -> Int -> Int
|
// decl func : String -> Int -> Int
|
||||||
def func : s i = {
|
// def func : s i = {
|
||||||
; print: s
|
// ; print: s
|
||||||
var x = s
|
// var x = s
|
||||||
; print: (i.show:)
|
// ; print: (i.show:)
|
||||||
return 5
|
// 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"
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
decl scan_int : -> Int
|
||||||
|
def scan_int = Int.read: (IO.scan:)
|
||||||
|
|
||||||
|
decl print_int : Int -> Unit
|
||||||
|
def print_int : x = IO.print: (x.show:)
|
||||||
|
|
||||||
|
decl scan_anything ('A : #Read) : -> 'A
|
||||||
|
def scan_anything = 'A.read: (IO.scan:)
|
||||||
|
|
||||||
|
decl print_anything ('A : #Show) : 'A -> Unit
|
||||||
|
def print_anything : x = IO.print: (x.show:)
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct Array 'A = & data : 'A_0
|
||||||
|
|
||||||
|
namespace Array {
|
||||||
|
decl construct : 'A_0 -> Array
|
||||||
|
def construct: x = $(Array 'A) & data = x
|
||||||
|
} // TODO: construct decl + default def -> segfault
|
||||||
|
*/
|
||||||
|
|
||||||
exec main {
|
exec main {
|
||||||
for i in 0--19 do func: "a" (i * 2 +. 3)
|
var n = scan_anything Int:
|
||||||
; print: ({
|
var a = for _ in 0--n do scan_int:
|
||||||
if true then bring scan: else { ; print: "aaa" }
|
; print_anything Int: n
|
||||||
bring "nothing"
|
|
||||||
; print: "aaa"
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue