From 1df0fa2478a4ad80ef52473f2f6b3c216194bb5e Mon Sep 17 00:00:00 2001 From: slavek-kucera <53339291+slavek-kucera@users.noreply.github.com> Date: Fri, 7 Oct 2022 12:12:12 +0200 Subject: [PATCH] fix: TITLE instruction name field support --- clients/vscode-hlasmplugin/CHANGELOG.md | 1 + parser_library/src/context/hlasm_context.h | 6 +++ parser_library/src/diagnostic.cpp | 8 +++- parser_library/src/diagnostic.h | 2 + .../instruction_sets/asm_processor.cpp | 29 ++++++++++++ .../instruction_sets/asm_processor.h | 1 + .../low_language_processor.cpp | 3 +- parser_library/src/semantics/collector.cpp | 2 +- .../test/processing/asm_instr_test.cpp | 47 +++++++++++++++++++ 9 files changed, 96 insertions(+), 3 deletions(-) diff --git a/clients/vscode-hlasmplugin/CHANGELOG.md b/clients/vscode-hlasmplugin/CHANGELOG.md index 5eb7b9a14..d6290ec5f 100644 --- a/clients/vscode-hlasmplugin/CHANGELOG.md +++ b/clients/vscode-hlasmplugin/CHANGELOG.md @@ -12,6 +12,7 @@ - Implement rest of the changes introduced by APAR PH46868 - Evaluation of subscripted expressions in CA statements - Detection of re-declared global variables with inconsistent types +- TITLE instruction name field support ## [1.4.0](https://github.com/eclipse/che-che4z-lsp-for-hlasm/compare/1.3.0...1.4.0) (2022-08-30) diff --git a/parser_library/src/context/hlasm_context.h b/parser_library/src/context/hlasm_context.h index 91fb1310e..a38386605 100644 --- a/parser_library/src/context/hlasm_context.h +++ b/parser_library/src/context/hlasm_context.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -115,6 +116,8 @@ class hlasm_context processing_frame_tree m_stack_tree; + std::string m_title_name; + public: hlasm_context(utils::resource::resource_location file_loc = utils::resource::resource_location(""), asm_option asm_opts = {}, @@ -331,6 +334,9 @@ class hlasm_context const opcode_t* find_opcode_mnemo(id_index name, opcode_generation gen) const; opcode_generation current_opcode_generation() const { return m_current_opcode_generation; } + + const std::string& get_title_name() const { return m_title_name; } + void set_title_name(std::string name) { m_title_name = std::move(name); } }; bool test_symbol_for_read(const var_sym_ptr& var, diff --git a/parser_library/src/diagnostic.cpp b/parser_library/src/diagnostic.cpp index 93c1b1f91..fb36a75f4 100644 --- a/parser_library/src/diagnostic.cpp +++ b/parser_library/src/diagnostic.cpp @@ -1980,7 +1980,7 @@ diagnostic_op diagnostic_op::error_E056(const range& range) diagnostic_op diagnostic_op::error_E057(const range& range) { - return diagnostic_op(diagnostic_severity::error, "E057", "Symbol not an ordinary or sequence symbol", range); + return diagnostic_op(diagnostic_severity::error, "E057", "Symbol is not an ordinary or a sequence symbol", range); } diagnostic_op diagnostic_op::error_E058(const range& range) @@ -2143,6 +2143,12 @@ diagnostic_op diagnostic_op::warning_W015(const range& range) diagnostic_severity::warning, "W015", "End of source input reached, batch mode is not supported yet", range); } +diagnostic_op diagnostic_op::warning_W016(const range& range) +{ + return diagnostic_op( + diagnostic_severity::warning, "W016", "Multiple TITLE instructions with a non-empty name field", range); +} + diagnostic_op diagnostic_op::error_EQU1(const range& range) { return diagnostic_op(diagnostic_severity::error, "EQU1", "Constant redefinition", range); diff --git a/parser_library/src/diagnostic.h b/parser_library/src/diagnostic.h index 2380b48e6..b013e52e3 100644 --- a/parser_library/src/diagnostic.h +++ b/parser_library/src/diagnostic.h @@ -633,6 +633,8 @@ struct diagnostic_op static diagnostic_op warning_W015(const range& range); + static diagnostic_op warning_W016(const range& range); + static diagnostic_op error_EQU1(const range& range); static diagnostic_op error_EQU2(const range& range); diff --git a/parser_library/src/processing/instruction_sets/asm_processor.cpp b/parser_library/src/processing/instruction_sets/asm_processor.cpp index b8dbd1d2c..63139f567 100644 --- a/parser_library/src/processing/instruction_sets/asm_processor.cpp +++ b/parser_library/src/processing/instruction_sets/asm_processor.cpp @@ -757,6 +757,7 @@ asm_processor::process_table_t asm_processor::create_table(context::hlasm_contex table.emplace(h_ctx.ids().add("POP"), [this](rebuilt_statement stmt) { process_POP(std::move(stmt)); }); table.emplace(h_ctx.ids().add("MNOTE"), [this](rebuilt_statement stmt) { process_MNOTE(std::move(stmt)); }); table.emplace(h_ctx.ids().add("CXD"), [this](rebuilt_statement stmt) { process_CXD(std::move(stmt)); }); + table.emplace(h_ctx.ids().add("TITLE"), [this](rebuilt_statement stmt) { process_TITLE(std::move(stmt)); }); return table; } @@ -1315,4 +1316,32 @@ void asm_processor::process_CXD(rebuilt_statement stmt) hlasm_ctx.ord_ctx.reserve_storage_area(cxd_length, context::no_align, lib_info); } +struct title_label_visitor +{ + std::string operator()(const std::string& v) const { return v; } + std::string operator()(const semantics::ord_symbol_string& v) const { return v.mixed_case; } + std::string operator()(const semantics::concat_chain&) const { return {}; } + std::string operator()(const semantics::seq_sym&) const { return {}; } + std::string operator()(const semantics::vs_ptr&) const { return {}; } +}; + +void asm_processor::process_TITLE(rebuilt_statement stmt) +{ + const auto& label = stmt.label_ref(); + + if (auto label_text = std::visit(title_label_visitor(), label.value); !label_text.empty()) + { + if (hlasm_ctx.get_title_name().empty()) + hlasm_ctx.set_title_name(std::move(label_text)); + else + add_diagnostic(diagnostic_op::warning_W016(label.field_range)); + } + + hlasm_ctx.ord_ctx.symbol_dependencies.add_dependency( + std::make_unique(std::move(stmt), hlasm_ctx.processing_stack()), + context::ordinary_assembly_dependency_solver(hlasm_ctx.ord_ctx, lib_info) + .derive_current_dependency_evaluation_context(), + lib_info); +} + } // namespace hlasm_plugin::parser_library::processing diff --git a/parser_library/src/processing/instruction_sets/asm_processor.h b/parser_library/src/processing/instruction_sets/asm_processor.h index 95ecc39f3..feeea42f6 100644 --- a/parser_library/src/processing/instruction_sets/asm_processor.h +++ b/parser_library/src/processing/instruction_sets/asm_processor.h @@ -73,6 +73,7 @@ class asm_processor : public low_language_processor void process_POP(rebuilt_statement stmt); void process_MNOTE(rebuilt_statement stmt); void process_CXD(rebuilt_statement stmt); + void process_TITLE(rebuilt_statement stmt); template void process_data_instruction(rebuilt_statement stmt); diff --git a/parser_library/src/processing/instruction_sets/low_language_processor.cpp b/parser_library/src/processing/instruction_sets/low_language_processor.cpp index 53d37c434..062b0c38e 100644 --- a/parser_library/src/processing/instruction_sets/low_language_processor.cpp +++ b/parser_library/src/processing/instruction_sets/low_language_processor.cpp @@ -128,7 +128,8 @@ low_language_processor::preprocessed_part low_language_processor::preprocess_inn } break; case label_si_type::MAC: - add_diagnostic(diagnostic_op::error_E057(label_ref.field_range)); + if (*stmt.opcode_ref().value != "TITLE") + add_diagnostic(diagnostic_op::error_E057(label_ref.field_range)); break; case label_si_type::SEQ: branch_provider.register_sequence_symbol( diff --git a/parser_library/src/semantics/collector.cpp b/parser_library/src/semantics/collector.cpp index 5dbbaf15e..341667d1f 100644 --- a/parser_library/src/semantics/collector.cpp +++ b/parser_library/src/semantics/collector.cpp @@ -81,7 +81,7 @@ void collector::set_label_field( // otherwise it is macro label parameter else { - lbl_.emplace(symbol_range, *label, label_si::mac_flag()); + lbl_.emplace(symbol_range, mixed_case_label, label_si::mac_flag()); } } diff --git a/parser_library/test/processing/asm_instr_test.cpp b/parser_library/test/processing/asm_instr_test.cpp index 3e9bd3f33..d670c039e 100644 --- a/parser_library/test/processing/asm_instr_test.cpp +++ b/parser_library/test/processing/asm_instr_test.cpp @@ -267,3 +267,50 @@ C CXD EXPECT_EQ(get_var_value(a.hlasm_ctx(), "S"), 0); EXPECT_EQ(get_var_value(a.hlasm_ctx(), "I"), 0); } + +TEST(asm_instr_processing, TITLE_text_label) +{ + std::string input = R"( +0a0 TITLE 'aaa' +)"; + + analyzer a(input); + a.analyze(); + a.collect_diags(); + + EXPECT_TRUE(a.diags().empty()); + + EXPECT_EQ(a.hlasm_ctx().get_title_name(), "0a0"); +} + +TEST(asm_instr_processing, TITLE_multiple_labels) +{ + std::string input = R"( +000 TITLE 'aaa' +0b0 TITLE 'aaa' +)"; + + analyzer a(input); + a.analyze(); + a.collect_diags(); + + EXPECT_TRUE(matches_message_codes(a.diags(), { "W016" })); + + EXPECT_EQ(a.hlasm_ctx().get_title_name(), "000"); +} + +TEST(asm_instr_processing, TITLE_sequence_does_not_count) +{ + std::string input = R"( +0a0 TITLE 'aaa' +.A TITLE 'aaa' +)"; + + analyzer a(input); + a.analyze(); + a.collect_diags(); + + EXPECT_TRUE(a.diags().empty()); + + EXPECT_EQ(a.hlasm_ctx().get_title_name(), "0a0"); +}