SpecificationFunction.cpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright (c) 2023-2024, Dan Klishch <danilklishch@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Parser/Lexer.h"
  7. #include "Parser/SpecificationParsing.h"
  8. #include "Parser/XMLUtils.h"
  9. namespace JSSpecCompiler {
  10. bool SpecificationFunction::post_initialize(XML::Node const* element)
  11. {
  12. VERIFY(element->as_element().name == tag_emu_clause);
  13. auto& ctx = context();
  14. auto maybe_id = get_attribute_by_name(element, attribute_id);
  15. if (!maybe_id.has_value()) {
  16. ctx.diag().error(ctx.location_from_xml_offset(element->offset),
  17. "no id attribute");
  18. } else {
  19. m_id = maybe_id.value();
  20. }
  21. m_header.header.visit(
  22. [&](ClauseHeader::AbstractOperation const& abstract_operation) {
  23. auto maybe_abstract_operation_id = get_attribute_by_name(element, attribute_aoid);
  24. if (maybe_abstract_operation_id.has_value())
  25. m_name = MUST(String::from_utf8(maybe_abstract_operation_id.value()));
  26. auto const& [function_name, arguments] = abstract_operation;
  27. m_arguments = arguments;
  28. if (m_name != function_name) {
  29. ctx.diag().warn(ctx.location_from_xml_offset(element->offset),
  30. "function name in header and <emu-clause>[aoid] do not match");
  31. }
  32. },
  33. [&](ClauseHeader::Accessor const& accessor) {
  34. m_name = MUST(String::formatted("%get {}%", MUST(String::join("."sv, accessor.qualified_name))));
  35. },
  36. [&](ClauseHeader::Method const& method) {
  37. m_name = MUST(String::formatted("%{}%", MUST(String::join("."sv, method.qualified_name))));
  38. m_arguments = method.arguments;
  39. },
  40. [&](auto const&) {
  41. VERIFY_NOT_REACHED();
  42. });
  43. Vector<XML::Node const*> algorithm_nodes;
  44. for (auto const& child : element->as_element().children) {
  45. child->content.visit(
  46. [&](XML::Node::Element const& element) {
  47. if (element.name == tag_h1) {
  48. // Processed in SpecificationClause
  49. } else if (element.name == tag_p) {
  50. ctx.diag().warn(ctx.location_from_xml_offset(child->offset),
  51. "prose is ignored");
  52. } else if (element.name == tag_emu_alg) {
  53. algorithm_nodes.append(child);
  54. } else {
  55. ctx.diag().error(ctx.location_from_xml_offset(child->offset),
  56. "<{}> should not be a child of <emu-clause> specifing function"sv, element.name);
  57. }
  58. },
  59. [&](auto const&) {});
  60. }
  61. if (algorithm_nodes.size() != 1) {
  62. ctx.diag().error(ctx.location_from_xml_offset(element->offset),
  63. "<emu-clause> specifing function should have exactly one <emu-alg> child"sv);
  64. return false;
  65. }
  66. auto maybe_algorithm = Algorithm::create(ctx, algorithm_nodes[0]);
  67. if (maybe_algorithm.has_value()) {
  68. m_algorithm = maybe_algorithm.release_value();
  69. return true;
  70. } else {
  71. return false;
  72. }
  73. }
  74. void SpecificationFunction::do_collect(TranslationUnitRef translation_unit)
  75. {
  76. translation_unit->adopt_function(make_ref_counted<FunctionDefinition>(m_name, m_algorithm.tree(), move(m_arguments)));
  77. }
  78. }