/*
** Translated from TRPL:  rules/convert/core_conversion.xml
 
/ *
** Module   : core_conversion.xml
** Abstract : primary "driver" for code conversion
**
** Copyright (c) 2005-2026, Golden Code Development Corporation.
**
** _#_ _I_ __Date__ __JPRM__ ____________________________Description_____________________________
** 001 GES 20050719   @21720 This version supports the conversion of most
**                           common language features including
**                           expressions, variables, procedures,
**                           functions, assignments, control flow,
**                           process launching and I/O.
** 002 GES 20050728   @21903 Added support for honor-hidden during the
**                           primary rule-set so that one can mark nodes
**                           as hidden and they don't get walked.
** 003 GES 20050818   @22170 Added debugging helper to dump the Java
**                           tree before persisting it.  This helps when
**                           the JAST is malformed and persistence fails.
** 004 SIY 20050819   @22172 Integrated name mapping information 
**                           processing.
** 005 GES 20050824   @22229 Added method and attribute support.
** 006 GES 20051005   @22994 Added buffer/database definition support.
** 007 GES 20051101   @23194 Added frame/UI support.
** 008 GES 20051109   @23314 Added widget references.
** 009 ECF 20060111   @23882 Added accumulate support.
** 010 GES 20060120   @23982 Removed the generated main() which was the
**                           next to last rule-set included.
** 011 GES 20060201   @24181 Moved Progress procedure/function to Java
**                           class/method name mapping collection to
**                           annotations.
** 012 GES 20060308   @24930 Added customer specific prep step.
** 013 GES 20080826   @39582 Added post-processing of the JAST to remove
**                           unnecessary SKIP nodes.
** 014 GES 20090518   @42315 Import change.
** 015 GES 20101005          Added comment support.
** 016 CA  20121012          After customer_specific conversion, the standard
**                           set of tools is executed, to handle prog.customer-specific nodes.
** 017 OM  20130121          Added convert/query_definitions into the conversion process flow.
** 018 CA  20130209          Load Progress version variables at startup.
** 019 OM  20130220          Included dereference.rules for conversion :: support.
** 020 ECF 20130405          Backed out #017. Work done by that rule-set is now done in
**                           language_statements.rules.
** 021 CA  20131024          Added conditional rule-set processing flags for dynamic query
**                           conversion.
** 022 VIG 20141111          Added new rule-set for menu generation.
** 023 OM  20150211          Added [convert/methods_attributes] to runtime query conversion.
**                           Added [convert/dereference] to runtime query conversion.
** 023 OM  20150610          Added [convert/variable_references] to runtime query conversion.
** 024 GES 20160519          Removed compact mode support (non-compact mode no longer exists).
** 025 ECF 20170822          Added database_methods.rules.
** 026 OM  20170530          Included support for conversion of com-handles.
** 027 CA  20170827          Added conversion support for dynamic array expansion.
** 028 GES 20171208          Added java tree beautification rules.
** 029 GES 20181213          Added method definitions.
**     HC  20181212          Implemented conversion of multiple Windows API functions.
** 030 ECF 20190214          Added buffer_copy_compare rule set.
** 031 OM  20190327          Added datasets rules.
** 032 ECF 20190511          Added copy_lob rule set.
**     CA  20190520          Track the names of all converted Java method names - these will be 
**                           used to qualify a FWD static import API, to avoid collisions.
** 022 CA  20191002          LegacySignature is emitted for internal procedures and functions, too.
** 023 CA  20200412          Added incremental conversion support.
** 024 HC  20200726          Improved OCX conversion of COM properties.
** 025 CA  20201008          Added generation for legacy open client proxy Java programs.
**     CA  20210203          Fixed conversion issues with OUTPUT/INPUT-OUTPUT for extent or scalar parameters,
**                           involved in dynamic or static OO calls, functions or procedure calls.  This 
**                           includes mostly cases for OO properties/variables (static and non-static).
** 026 VVT 20220913          OEUnit support: convert/unit_test_support added. See #6237.
**     VVT 20220914          Changes in revs. 14243,14241,14239 temporarily reverted until JUnit runtime
**                           support is added to client projects.
**     CA  20220428          Legacy OpenClient proxy conversion must be done for each .xpxg, as a program may
**                           appear in multiple generated (Sub)AppObject programs.
** 027 VVT 20230318          Changes in revs. 14243,14241,14239 restored. See #6237.
** 028 CA  20231213          The synthetic 'execute' methods emitted for legacy classes can be dropped if there
**                           is nothing emitted in them.  These Java methods are also marked with Type.EXECUTE
**                           LegacySignature annotation, and their BlockManager API removed - the FWD runtime
**                           will run this only once.
** 029 AOG 20250818          Added multiThreadAccess flag to the global shared variables between conversion threads.
* /
 

** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.

*/

package com.goldencode.p2j.pattern.trpl

import scala.language.implicitConversions
import com.goldencode.p2j.pattern.*
import com.goldencode.p2j.pattern.Trpl.*
import com.goldencode.ast.Aast
import java.util.Iterator
import java.util.Set

/** rules/convert/core_conversion.xml */
final class convert_core_conversion_xml(c: TrplCtx) extends TrplProfile(c):
  // register worker objects
  worker("com.goldencode.p2j.uast.ProgressPatternWorker", namespace = "progress")
  worker("com.goldencode.p2j.uast.JavaPatternWorker", namespace = "java")
  // expression libraries
  include("common-progress")
  // variables
  val enableJastDebug = variable("enableJastDebug", classOf[JBoolean], init = () => false, shared = true)
  val jRoot = variable("jRoot", classOf[Aast])
  val jNext = variable("jNext", classOf[Aast])
  val jPrev = variable("jPrev", classOf[Aast])
  val jSib = variable("jSib", classOf[Aast])
  val jIter = variable("jIter", classOf[Iterator[?]])
  val isV9 = variable("isV9", classOf[JBoolean], shared = true)
  val isV10 = variable("isV10", classOf[JBoolean], shared = true)
  val sourceCodeVer = variable("sourceCodeVer", classOf[String], shared = true)
  val runtimeQueryMode = variable("runtimeQueryMode", classOf[JBoolean], shared = true)
  val javaMethodNames = variable("javaMethodNames", classOf[Set[?]])
  // pipeline of rule-sets to process
  // global initialization (once per pipeline)
  initRules {
    java.setAutoload(true)
    sourceCodeVer := execLib[String]("getSourceCodeVersion")
    isV9 := execLib[JBoolean]("isProgressV9")
    isV10 := execLib[JBoolean]("isProgressV10")
    runtimeQueryMode := isRuntimeQueryMode()
  }
  // main processing (once per tree)
  ruleSet(input = "tree", honorHidden = true, loadCondition = "runtime-query")(new TrplRuleSet(_):
    // save the entire set of converted Java methods names to be able to look for collisions
    // in FWD APIs which are used unqualified, from static imports.  each collision will need
    // to be manually solved - there is no global approach yet to force the qualify
    initRules {
      javaMethodNames := create("java.util.HashSet", Array[AnyRef]()).asInstanceOf[Set[?]]
      javaMethodNames().asInstanceOf[Set[AnyRef]].add("execute")
    }
    walkRules {
      if getParent() != null && evalLib("isTopLevelNode", getParent()) && isNote("javaname") then
        javaMethodNames().asInstanceOf[Set[AnyRef]].add(getNoteString("javaname"))
    }
  )
  // this rule-set is the central place to "merge" all other conversion
  // rule-sets which collectively form a single massive nested rule-set
  // which takes a fixed-up, annotated Progress source AST (and also
  // uses an existing "stub" Java AST as a target) and converts all
  // Progress source constructs into the equivalent Java constructs
  // rooted in the Java AST
  ruleSet(input = "tree", honorHidden = true, loadCondition = "runtime-query")(new TrplRuleSet(_):
    ruleFile("convert/unit_test_support")
    ruleFile("convert/variable_definitions")
    // the order of the following rules is important - method_definitions' ascent-rules will
    // emit the signature's parameter annotations
    ruleFile("convert/function_definitions")
    ruleFile("convert/procedure_definitions")
    ruleFile("convert/method_definitions")
    ruleFile("convert/buffer_definitions", loadCondition = "runtime-query")
    ruleFile("convert/datasets")
    ruleFile("convert/database_methods")
    ruleFile("convert/frame_construction")
    ruleFile("convert/output_parameters")
    ruleFile("convert/array_expansion")
    ruleFile("convert/expressions", loadCondition = "runtime-query")
    ruleFile("convert/literals", loadCondition = "runtime-query")
    ruleFile("convert/operators", loadCondition = "runtime-query")
    ruleFile("convert/variable_references", loadCondition = "runtime-query")
    ruleFile("convert/buffer_copy_compare")
    ruleFile("convert/copy_lob")
    ruleFile("convert/database_references", loadCondition = "runtime-query")
    ruleFile("convert/widget_references")
    ruleFile("convert/oo_calls")
    ruleFile("convert/builtin_functions", loadCondition = "runtime-query")
    ruleFile("convert/user_functions")
    ruleFile("convert/methods_attributes", loadCondition = "runtime-query")
    ruleFile("convert/com_access", loadCondition = "runtime-query")
    ruleFile("convert/dereference", loadCondition = "runtime-query")
    ruleFile("convert/assignments")
    ruleFile("convert/control_flow", loadCondition = "runtime-query")
    ruleFile("convert/process_launch")
    ruleFile("convert/input_output")
    ruleFile("convert/database_access", loadCondition = "runtime-query")
    ruleFile("convert/accumulate")
    ruleFile("convert/ui_statements")
    ruleFile("convert/language_statements")
    ruleFile("customer_specific_conversion", optional = true)
    ruleFile("convert/standard_customer_specific_tools")
    ruleFile("convert/menu_construction")
  )
  ruleFile("convert/ocx_type")
  // native system api emulation
  ruleFile("convert/native_api")
  ruleSet(input = "tree", honorHidden = true)(new TrplRuleSet(_):
    ruleFile("convert/beautification")
  )
  ruleSet(input = "tree", honorHidden = true)(new TrplRuleSet(_):
    ruleFile("convert/comments")
  )
  ruleSet(input = "tree")(new TrplRuleSet(_):
    val ref = variable("ref", classOf[Aast])
    val chref = variable("chref", classOf[Aast])
    val drop = variable("drop", classOf[JBoolean])
    val iter = variable("iter", classOf[Iterator[?]])
    initRules {
      if descendant(progress.CLASS_DEF, 1) then
        ref := getAst(java.getClosestPeerId())
        // check the non-BLOCK children of the 'execute' synthetic method AST.
        // if there are non, drop it
        iter := ref().iterator()
        drop := true
        loop(drop && iter.?.hasNext()) {
          chref := iter().next().asInstanceOf[Aast]
          drop := chref.?.getType == java.BLOCK
        }
        if drop then
          // remove the 'execute' synthetic method
          ref := ref().getParent
          ref().remove()
          // remove the LegacySignature node
          ref := getAst(getNoteLong("sigrefid"))
          ref().remove()
    }
  )
  // persist both the source and target ASTs since new cross-references
  // exist bidirectionally
  ruleSet(loadCondition = "runtime-query")(new TrplRuleSet(_):
    postRules {
      // save the Progress AST
      persist()
      jRoot := getAst(java.getJavaRootId())
      // post-process the Java AST to remove duplicate or otherwise
      // unnecessary SKIPs
      if jRoot.nonNull then
        jIter := jRoot().iterator()
        loop(jIter().hasNext()) {
          jNext := jIter().next().asInstanceOf[Aast]
          jPrev := jNext().getPrevSibling
          // skip as a first child of a block is not needed
          if jPrev.isNull && jNext.?.getType == 996 && jNext.?.getParent.?.getType == 106 then
            jNext().remove()
            continueLoop()
          // skip as a first child of bogus MAY not be needed
          if jPrev.isNull && jNext.?.getType == 996 && jNext.?.getParent.?.getType == 999 then
            jPrev := jNext().getParent.getPrevSibling
          // duplicate skip
          if jPrev.nonNull && jPrev.?.getType == 996 && jNext.?.getType == 996 then
            jPrev().remove()
          jSib := jNext().getNextSibling.asInstanceOf[Aast]
          // skip as a last child of bogus MAY not be needed
          if jSib.isNull && jNext.?.getType == 996 && jNext.?.getParent.?.getType == 999 then
            jSib := jNext().getParent.getNextSibling.asInstanceOf[Aast]
          // skip as a last child of a block is not needed
          if jSib.isNull && jNext.?.getType == 996 && jNext.?.getParent.?.getType == 106 then
            jNext().remove()
            continueLoop()
        }
      // save the Java AST
      if enableJastDebug then
        printf("%s", Array[AnyRef](jRoot().dumpTree()))
      java.persistJavaFile()
    }
  )
  // global termination (once per pipeline)

  private val java = JavaNs("java")
  private val progress = ProgNs("progress")
