<?xml version="1.0"?>

<!-- 
/*
** Module   : ui_statements.rules
** Abstract : user interface language statements 
**
** Copyright (c) 2005-2020, Golden Code Development Corporation.
**
** _#_ _I_ __Date__ __JPRM__ __________________________ Description ___________________________
** 001 GES 20051101   @23199 First version which converts Progress
**                           user interface statements and emits the
**                           core processing.
** 002 GES 20051109   @23297 Added major support for all static lang
**                           statements and many supporting data
**                           structures.
** 003 GES 20051112   @23318 Added major support for all frame and widget
**                           forms of language statements and supporting
**                           parms.
** 004 GES 20051114   @23328 Added more complete support for update, set,
**                           prompt-for, enable, disable.
** 005 GES 20051116   @23361 Added trigger block support.
** 006 GES 20051117   @23371 Added editing block support.
** 007 GES 20051119   @23412 Added validation expression support.
** 008 GES 20051121   @23429 Added field validation support (implicit and
**                           as overrides).
** 009 GES 20051122   @23434 Added choose statement.
** 010 GES 20051124   @23456 Added when clause processing.
** 011 GES 20051127   @23515 Runtime UI options processing.
** 012 GES 20051128   @23545 Added put-screen and terminal lang stmts.
** 013 GES 20051208   @23675 Added go-on support to editing blocks.
** 014 GES 20060111   @23856 Fix to add display() in to update stmts.
** 015 GES 20060112   @23891 Fix to runtime frame options.
** 016 GES 20060113   @23893 Fix for CLEAR.
** 017 GES 20060113   @23900 Message stmt by itself needs UI pkg import.
** 018 GES 20060116   @23929 Fixed visibility of SET/PROMPT-FOR.
** 019 GES 20060117   @23956 Support for NO-MESSAGE form of PAUSE.
** 020 GES 20060202   @24232 Add an import on any static method call to
**                           LogicalTerminal.
** 021 GES 20060205   @24287 Major rework to handle the new higher level
**                           display/update/set/prompt-for APIs.
** 022 GES 20060206   @24309 Finished message stmt with set/update.
** 023 GES 20060208   @24377 Minor updates to support stream parms in
**                           display/update/set/prompt-for APIs.
** 024 GES 20060211   @24566 Minor fix for message set/update with an
**                           embedded var def.
** 025 GES 20060214   @24593 Moved enable/disable out of logical terminal
**                           and into the frame specific code.
** 026 SIY 20060222   @24648 Fixed generation of CHOOSE statement.
** 027 GES 20060224   @24733 Fixed remapKey support.
** 028 GES 20060228   @24778 Added prompt-for support to editing blocks.
** 029 GES 20060301   @24808 Changed explicit ASSIGN stmt processing.
** 030 ECF 20060228   @24828 Added field-level validation support. Added
**                           changed, or removed rules to handle implicit
**                           validation cases.
** 031 GES 20060310   @24960 Fixed no-message pause parameter gen.
** 032 SIY 20060309   @25029 BROWSE support.
** 033 GES 20060317   @25091 Form header support.
** 034 GES 20060322   @25188 Added special case for terminal statement.
** 035 GES 20060401   @25302 Added safety code for empty content arrays.
** 036 GES 20060404   @25336 Text clause support for set, update, 
**                           prompt-for and enable.  Rework for enable
**                           and disable to have frame element support.
** 037 GES 20060404   @25350 Clear some state on ascent to the statement 
**                           node.
** 038 GES 20060404   @25351 WAIT-FOR needs a frame reference.
** 039 GES 20060404   @25361 Fix for put cursor and put screen parms.
** 040 GES 20060410   @25449 Fix for hide parms when an explicit stream
**                           if provided.
** 041 GES 20060412   @25519 Fixed frame apply case and added some safety 
**                           code for message box.
** 042 GES 20060425   @25703 Message stmt format string fixes.
** 043 GES 20060425   @25706 Avoid empty registerHeader() calls.
** 044 GES 20060426   @25735 Kinder, gentler underline support.
** 045 GES 20060426   @25738 Add support for casting handle dereferences
**                           in an apply stmt.
** 046 GES 20060426   @25743 Message stmt auto-return parent ID calc fix.
** 047 GES 20060428   @25873 Support for aggregate phrases in the display
**                           stmt.
** 048 NVS 20060504   @25976 Dynamic setTitle() call is now emitted as
**                           setDynamicTitle() to be different from the
**                           frame definition call setTitle().
** 049 NVS 20060522   @26427 Not all possible variations of CLEAR
**                           statement were covered. Fixed.
** 050 GES 20060526   @26556 Don't unwrap when clauses that have boolean
**                           literals as the condition.
** 051 GES 20060705   @27808 setColors() is now called on a frame instead
**                           of LogicalTerminal since the color stmt
**                           always operates on a set of widgets from the
**                           same frame.
** 052 GES 20060707   @27904 Dynamic titles are emitted just after the
**                           frame scope opens. This ensures that all
**                           usage of the frame will honor the given
**                           expression.
** 053 GES 20060915   @29634 Added support for emitting format string
**                           overrides in the usage of @ fbase fields.
** 054 GES 20061120   @31300 More correct support for dynamic options
**                           row/column and down.
** 055 GES 20061128   @31424 Move header registration up to the area just
**                           after the open scope call.  This is needed
**                           since form header stmts can appear in 
**                           conditional blocks in Progress but in such
**                           cases they are still honored because the 4GL
**                           handles such processing at compile time, not
**                           at runtime.
** 056 NVS 20070118   @31894 Changed the conversion rules so that a new 
**                           EventList class is used instead of WaitList.
** 057 GES 20070306   @32274 Fix to only create bypass elements when
**                           a CARET is used in a SET/UPDATE/PROMPT-FOR.
** 058 GES 20080623   @38953 Fixed editing block go-on support which was
**                           using the wrong template name.
** 059 GES 20080819   @39516 Compact mode support for editing and trigger
**                           blocks.
** 060 GES 20080826   @39587 Simplification/improvements for skip
**                           insertion.
** 061 CA  20080911   @39804 Set the browse widget title if it wasn't 
**                           emitted during frame definition (i.e. it was
**                           non-literal value).
** 062 CA  20080925   @39959 Support for dynamic browse title.
** 063 GES 20081003   @40028 Increased use of static imports. Support for
**                           avoiding logical unwrapping in specific
**                           cases.
** 064 CA  20081006   @40053 Add a frame.registerAccumulators(...) call
**                           for all the frame's aggregator elements, just
**                           after the frame.openScope() call.
** 065 GES 20081017   @40159 Trigger registration for full transaction
**                           cases is fixed.  It now uses a setter
**                           to force the proper transaction level.
** 066 CA  20081201   @40719 Allow the 'anywhere' trigger option to emit
**                           as a parameter for the addEvent call.
** 067 GES 20081217   @40923 Rework of trigger registration to pass the
**                           necessary metadata to allow trigger
**                           instantiation to be delegated to the runtime.
**                           This is needed to allow a "fresh" trigger to
**                           be created for every invocation. That allows
**                           the trigger's data members to be set to the
**                           proper default values each time.
** 068 GES 20090422   @41878 Converted format specs into standard J2SE form.
** 069 GES 20090518   @42327 Import change.
** 070 GES 20100423   @44834 Honor format strings defined in the schema for
**                           fields in a message set/update when there is no
**                           explicit format string specified in the msg stmt
**                           itself.
** 071 CA  20100914          VALIDATE clauses will emit at the begining of the
**                           external procedure's body() method. This fixes a
**                           bug when the VALIDATE clauses are not defined in
**                           a compact way (i.e. at FORM definition), but are  
**                           dispersed through the program in various places  
**                           with the UPDATE, SET, FORM, DEFINE FRAME, etc 
**                           statements.
** 072 SVL 20101004          Added support for CREATE WIDGET-POOL statement.
** 073 SIY 20101004          Changes related to CREATE widget statements.
** 074 SIY 20101005          Added support for DELETE widget statements and
**                           handling of UNLESS-HIDDEN option.
** 075 SVL 20101006          Added support for SYSTEM-HELP statement.
** 076 SIY 20101012          HIDE and VIEW now handled as other frame element
**                           based statements.
** 077 SIY 20101029          Fixes to HIDE/VIEW support.
** 078 GES 20110201          Fixed WHEN clause processing for ASSIGN stmt.
** 079 GES 20111017          Fixed CARET processing (it was regressed at some
**                           point, which meant that BypassElement instances
**                           were no longer generated).
** 080 CA  20130115          APPLY statement used with handles must convert to
**                           handle.unwrapWidget(<handle>).apply calls.
** 081 CA  20130131          Added support for ON ... PERSISTENT RUN triggers.
**                           Moved CREATE WIDGET-POOL support in 
**                           language_statements.rules, as non-ui resources
**                           can be pooled.
** 082 CS  20130204          Added conversion support for socket and 
**                           server-socket.
** 083 CA  20130215          DELETE WIDGET converts to HandleOps.delete.
** 084 SVL 20130213          Added support for session triggers.
** 085 GES 20130219          Added a qualifier to constant references.
** 086 CA  20130222          Fixed APPLY ... TO SELF conversion, as SELF now acts as a real handle.
** 087 CA  20130222          Added CREATE WIDGET conversion support.
** 088 CA  20130224          Fixed conversion of APPLY TO ... <window sys handle>.
** 089 GES 20130224          Bypass validation processing for buffer validation cases.
** 090 CA  20130307          Fixed ui package import, for DEF [SHARED] FRAME statements.
** 091 GES 20130312          Removed use of the compact flag since we are always compact now.
**                           Added support for wrapping indeterminate _POLY expressions (which
**                           return BDT or _POLY expressions that return non-logical values)
**                           as logical when parented at a WHEN clause.
** 092 CA  20130317          Fixed registration of schema validation expressions with widgets.
** 093 OM  20130319          Fixed VIEW/HIDE code generation when only sub-node is a stream
**                           (the frame was not emited under view/hide method).
** 094 CA  20130822          Socket events are handled by LT.waitFor, no separate API is needed.
** 095 CA  20131115          Annotate a trigger's block with the default c'tor ID.
** 096 OM  20131128          Improved/fixed trigger generation.
** 097 OM  20140107          Fixed assign trigger for database-unrealated parameter (NEW form).
** 098 GES 20140228          Fixed SKIP that has no numeric qualifier in a message stmt.
** 099 CA  20140313          Show an ERROR message if there are ON ... PERSISTENT RUN library-ref.
**                           RUN library-ref will convert to ControlFlowOps APIs, which will 
**                           disambugate the target expression at runtime.
** 100 EVL 20140507          Fix for "empty" underline statement if widgets are not listed. 
** 101 CA  20140526          handle unwrap APIs were switched to instance method calls.
** 102 EVL 20140522          Adding hadnling the UNLESS-HIDDEN option for statements: DISABLE,
**                           PROMPT-FOR, SET and UPDATE.
** 103 GES 20140626          Renamed color attributes to match naming standards.
** 104 CA  20140701          Added support for the SYSTEM-DIALOG FONT statement.
** 105 MAG 20140814          Added support for the SYSTEM-DIALOG COLOR statement.
** 106 GES 20141126          Fixed variable initialization NPE. Added cast to string for null
**                           literal when used as 6th parm of messageBox() since there are now
**                           both String and character variants.
** 107 CA  20150122          APPLY TO ... <handle> needs to convert to LT.apply(handle, event).
** 108 CA  20150127          Fixed some problems related to H107: import static LT in case of 
**                           APPLY TO and any child of a trigger phrase with a frame-id is 
**                           assumed a widget.
** 109 ECF 20150506          Moved validation inner class to inner class of closest top-level,
**                           anonymous inner Block subclass to ensure it can reference buffers
**                           scoped to that level.
** 109 IAS 20150604          Added support for the ENABLE UNLESS-HIDDEB EXCEPT clause
** 110 CA  20150729          Added support for FRAME_LOCK and FRAME_UNLOCK nodes (needed by 
**                           CREATE .. ASSIGN statements, to lock the frame and process all 
**                           assignments in batch).
** 111 SVL 20150804          Added conversion for CREATE BROWSE.
** 112 VIG 20150715          Fixed emission of menu widgets for widget lists (for triggers)
** 113 OM  20150918          Created minimum stub for SYSTEM-DIALOG GET-FILE.
** 114 CA  20151030          Allow support for undocumented ON ... PERSISTENT RUN ... IN handle
**                           triggers.
** 115 GES 20160525          Convert validation expressions as lambdas instead of inner classes.
** 116 IAS 20160829          Conversion support for the displayAndDown operation.
** 117 GES 20160830          Reworked default c'tor in all block inner class defs to be a pre()
**                           method definition.
**         20160831          Fixed editing block support. Created a placeholder node in the
**                           calling context for the local variables that were previously
**                           instance vars of the anon inner class.
**         20160901          Emit editing blocks with lambdas instead of method defs.
** 118 GES 20160930          Emit event list instances as an inline constructor for the common
**                           case where there is a single mapping for events to widgets.
**         20161004          Emit UI triggers as lambdas when possible.
** 119 OM  20161124          Added support for emitting setHelpStatic similar to setValidation.
** 120 GES 20170313          Minor changes for SYSTEM-HELP.
** 121 OM  20170719          System dialogs rewritten to be constructed by a set of chained
**                           primitives that configures the dialog as 4GL programmer desired.
** 122 HC  20170829          Improved conversion of color-specification in frame phrase: COLOR [
**                           DISPLAY ] color-phrase [ PROMPT ] color-phrase.
** 123 CA  20171009          color-phrase in COLOR statement may be a quoted string.
** 124 CA  20180528          Added UNLESS-HIDDEN to the UPDATE/SET/PROMPT-FOR ... EDITING blocks.
** 125 GES 20181108          Added OO_METH_* support.
** 126 HC  20181124          Implemented TREEVIEW widget and related changes.
** 127 GES 20181213          Added OO block support.
**     HC  20181212          Implemented conversion of multiple Windows API functions.
** 128 HC  20190206          Added very early stage of TABSET widget implementation only
**                           providing public interface and to allow conversion of legacy code.
**     OM  20190302          Added conversion for ComServer.delete().
**     CA  20190309          Added CREATE HTML-BROWSER support.
**     HC  20190313          Initial implementation of TREELIST widget. TREEVIEW widget
**                           refactored to make it the base for the TREELIST widget.
**     CA  20190328          Triggers are emitted as anon inner classes, instantiated via a lambda 
**                           expression.
** 129 OM  20190327          Extracted addChainNode() and initializeChain() to common_progress.
** 130 CA  20190423          Better approach for H128 - triggers are either emitted as singleton 
**                           or as an anon inner class, and always inline where they are defined.
** 131 CA  20190528          Fixed MESSAGE statement with no text.
** 132 HC  20191120          Extended SYSTEM-DIALOG GET-FILE with AT-WEB-BROWSER and MULTIPLE
**                           options.
** 133 HC  20190614          Initial implementation of IMAGELIST widget.
**     MAG 20191105          Replaced KW_IMG_LIST with KW_IL_IMG to create IMAGE-LIST widget.
** 134 MAG 20190919          Added CREATE PROGRESS-BAR support.
** 135 SBI 20200225          Added Calendar widget support.
** 136 RFB 20200221          Added CREATE BUTTON-LIST support.
**     GES 20191213          Emit try in converted triggers for catch statements that reference
**                           Java exceptions.
**     CA  20200304          Added CREATE CHART and CREATE SIGNATURE support.
** 137 CA  20200503          Fixed a typo for a WAIT-FOR with multiple system handles.
**     RFB 20200616          Added scoping for frame element name. This prevents a hide within an edit block
**                           from adding a reference to a frame element, when the frame is to be hidden.
*/
 -->
 
<!--
** 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.
-->

<rule-set>

   <!-- register worker objects -->
   <worker class="com.goldencode.p2j.uast.ProgressPatternWorker"         namespace="prog" />
   <worker class="com.goldencode.p2j.uast.JavaPatternWorker"             namespace="java" />
   <worker class="com.goldencode.p2j.convert.ExpressionConversionWorker" namespace="ecw" />
   <worker class="com.goldencode.p2j.pattern.TemplateWorker"             namespace="tw" />
   <worker class="com.goldencode.p2j.convert.ConverterHelper"            namespace="help" />
   
   <!-- expression libraries -->
   <include name="common-progress" />
   
   <func-library access="private">
   
      <function name="is_display_and_down">
         <parameter name="disp" type="com.goldencode.ast.Aast" />
         <parameter name="down" type="com.goldencode.ast.Aast" />
         <variable  name="aast" type="com.goldencode.ast.Aast" />
         <return    name="ok"  type="java.lang.Boolean" />

         <rule>ok = false</rule>
         
         <rule> evalLib("no_expression", down) and
                disp.getAnnotation("frame-id").equals(down.getAnnotation("frame-id"))
                <action>ok = evalLib("is_same stream", disp, down)</action>
         </rule>
      </function> 

      <function name="no_expression">
         <parameter name="down" type="com.goldencode.ast.Aast" />
         <variable  name="aast0" type="com.goldencode.ast.Aast" />
         <variable  name="aast1" type="com.goldencode.ast.Aast" />
         <return    name="ok"  type="java.lang.Boolean" />

         <rule> down.type == prog.kw_down
            <action>aast0 = down.getChildAt(0)</action>
            <action>aast1 = down.getChildAt(1)</action>
            <action>ok = 
                  (aast0 == null or aast0.type != prog.expression) and
                  (aast1 == null or aast1.type != prog.expression)
            </action>
         </rule>
      </function> 

      <function name="is_same stream">
         <parameter name="disp" type="com.goldencode.ast.Aast" />
         <parameter name="down" type="com.goldencode.ast.Aast" />
         <variable  name="stream" type="com.goldencode.ast.Aast" />
         <variable  name="disp_stream" type="java.lang.Long" />
         <variable  name="disp_stream_type" type="java.lang.Integer" />
         <variable  name="down_stream" type="java.lang.Long" />
         <return    name="ok"  type="java.lang.Boolean" />

         <rule>ok = false</rule>
         <rule>disp_stream = null</rule>
         <rule>down_stream = null</rule>

         <rule>stream = disp.firstChild</rule>
         <rule>stream != null and 
               (stream.type == prog.kw_stream or stream.type == prog.kw_strm_hnd) 
            <action>disp_stream = #(long)stream.getAnnotation("refid")</action>
            <action>disp_stream_type = stream.type</action> 
         </rule>
         
         <rule>stream = down.firstChild</rule>
         <rule>stream != null and stream.type == disp_stream_type
            <action>down_stream = #(long)stream.getAnnotation("refid")</action> 
         </rule>

         <rule>(disp_stream == null and down_stream == null) or
               (disp_stream != null and disp_stream.equals(down_stream))
            <action>ok = true</action>
          </rule>
      </function> 

      <function name="apply_to_handle">
         <parameter name="ref"    type="com.goldencode.ast.Aast" />
         <return    name="match"  type="java.lang.Boolean" />

         <rule>match = false</rule>

         <rule>ref.type == prog.kw_apply and ref.downPath("KW_TO")
            
            <action>ref = copy.getImmediateChild(prog.kw_to, null)</action>
            <action>ref = ref.getChildAt(0)</action>
            
            <action>
               match = ref.type == prog.var_handle      or
                       ref.type == prog.field_handle    or
                       ref.type == prog.func_handle     or
                       ref.type == prog.meth_handle     or
                       ref.type == prog.oo_meth_handle  or
                       ref.type == prog.attr_handle     or
                       evalLib("converted_to_handle", ref)
            </action>
         </rule>

      </function>

      <function name="match_widget_type">
         <parameter name="widgetType" type="java.lang.String" />
         <return    name="match"      type="java.lang.Boolean" />
         <variable  name="ref"        type="com.goldencode.ast.Aast" />

         <expression>match = false</expression>
         <rule>downPath("KW_VALUE/EXPRESSION/STRING") and 
               copy.getFirstChild().type == prog.kw_value
            <action>ref = copy.getFirstChild()</action>
            <action>ref = ref.getFirstChild()</action>
            <action>ref = ref.getFirstChild()</action>

            <rule>widgetType.equals(removeQuotes(ref.text.toLowerCase()))
               <!-- if the string literal matches the expected widget type, the remove the literal
                    and emit the dedicated API -->
               <action>match = true</action>
               <action>ref = copy.getFirstChild()</action>
               <action>ref.remove()</action>
            </rule>
         </rule>
      </function>
      
      <function name="gen_single_event_list">
         <parameter  name="clsname"  type="java.lang.String" />
         <parameter  name="ref"      type="com.goldencode.ast.Aast" />
         
         <rule>multiMode = false</rule>
         <rule>waitloc = createJavaAst(java.constructor, clsname, closestPeerId)</rule>
         <rule>ref.putAnnotation("peerid", waitloc)</rule>
      </function>

      <function name="gen_separate_event_list">
         
         <rule>multiMode = true</rule>
         
         <!-- generate a temp name -->
         <rule>true
            <action>listname = sprintf("list%d", nextNum)</action>
            <action>nextNum = nextNum + 1</action>
            
            <!-- place to attach the EventList and subsequent setters -->
            <action>waitloc = closestPeerId</action>
            
            <!-- add a skip before the EventList -->
            <action>createJavaAst(java.skip, "", closestPeerId)</action>
            
            <!-- create a EventList instance and instantiated before the wait-for -->
            <action>
               waitref = tw.graft("variable_def_default", null, closestPeerId,
                                  "javaname", listname,
                                  "wrapper", "EventList")
            </action>
            
            <!-- remember the index position at which to attach subsequent setters -->
            <action>waitidx = waitref.indexPos + 1</action>
         </rule>
      </function>
   
      <function name="gen_choose">
         <!-- generate a temp name -->
         <expression>choosename = sprintf("choose%d", chooseNum)</expression>
         <expression>chooseNum = chooseNum + 1</expression>
         
         <!-- place to attach the Choose and subsequent setters -->
         <expression>chooseloc = closestPeerId</expression>
         
         <!-- create a Choose instance and instantiated before the
              choose() -->
         <expression>
            chooseref = tw.graft("variable_def_default",
                                 null,
                                 closestPeerId,
                                 "javaname",
                                 choosename,
                                 "wrapper",
                                 "Choose")
         </expression>
         
         <!-- remember the index position at which to attach subsequent 
              setters -->
         <expression>chooseidx = chooseref.indexPos + 1</expression>
      </function>   
   
      <!-- generate widget accessor name -->
      <function name="gen_wacc">
         <parameter name="name" type="java.lang.String" />
         <return name="res"     type="java.lang.String" />
         
         <rule>name.length() != 1 and name.indexOf("Array") != 1
            <action on="true">
               res = sprintf("widget%s%s",
                              name.substring(0, 1).toUpperCase(),
                              name.substring(1))
            </action>
            <action on="false">
               res = sprintf("widget%s", name)
            </action>
         </rule>
      </function>

      <!-- set browse widget title -->
      <function name="generate_browse_title">
         <parameter name="ref"       type="com.goldencode.ast.Aast" />
         
         <variable  name="bref"      type="com.goldencode.ast.Aast" />
         <variable  name="fname"     type="java.lang.String" />
         <variable  name="wname"     type="java.lang.String" />
         <variable  name="parent"    type="com.goldencode.ast.Aast" />
         <variable  name="frame_ref" type="com.goldencode.ast.Aast" />
         <variable  name="parentid"  type="java.lang.Long" />
         <variable  name="idx"       type="java.lang.Integer" />
         <variable  name="lastid"    type="java.lang.Long" />
         
         <rule>true
            <action>
               bref = ref.getAncestor(-1, prog.statement)
            </action>
            <action>
               bref = bref.getImmediateChild(prog.define_browse, null)
            </action>
            
            <action>parentid = closestPeerId</action>
            <action>idx = -1</action>

            <action>
               parent = bref.getImmediateChild(prog.wid_browse, null)
            </action>
            <action>fname = execLib("get_framename", parent)</action>
            <action>
               frame_ref = getAst(#(java.lang.Long) 
                                  parent.getAnnotation("frame-id"))
            </action>
            
            <action>wname = bref.getAnnotation("javaname")</action>
            <action>wname = execLib("gen_wacc", wname)</action>
            
            <!-- emit setTitle call -->
            <action>            
               parentid = createJavaAst(java.method_call, "setDynamicTitle",
                                        parentid, idx)
            </action>
            <!-- emit widget accessor -->
            <action>            
               lastid = createJavaAst(java.method_call, wname, parentid)
            </action>
            <!-- emit frame reference -->
            <action>            
               lastid = createJavaAst(java.reference, fname, lastid)
            </action>
            
            <!-- the expression referenced by the 'ref' AST must be emitted
                 as a child for the setTitle method call -->
            <action>
               ref.putAnnotation("peerid", parentid)
            </action>
         </rule>
      </function>
      
      <!-- Determine if this is a non-aggregate node -->
      <function name="non_aggregate">
         <return    name="res"  type="java.lang.Boolean" />
         
         <rule>res = false</rule>
         
         <rule>getNoteBoolean("aggr_special") == null  or 
               getNoteBoolean("aggr_special") == false
             <action>res = true</action>
         </rule>
      </function>
      
   </func-library>
   
   <!-- variables -->
   <variable name="scoperef"    type="com.goldencode.ast.Aast" />
   <variable name="ref"         type="com.goldencode.ast.Aast" />
   <variable name="ref2"        type="com.goldencode.ast.Aast" />
   <variable name="ref3"        type="com.goldencode.ast.Aast" />
   <variable name="childref"    type="com.goldencode.ast.Aast" />
   <variable name="tempref"     type="com.goldencode.ast.Aast" />
   <variable name="waitref"     type="com.goldencode.ast.Aast" />
   <variable name="chooseref"   type="com.goldencode.ast.Aast" />
   <variable name="trigref"     type="com.goldencode.ast.Aast" />
   <variable name="onref"       type="com.goldencode.ast.Aast" />
   <variable name="editref"     type="com.goldencode.ast.Aast" />
   <variable name="implref"     type="com.goldencode.ast.Aast" />
   <variable name="ternref"     type="com.goldencode.ast.Aast" />
   <variable name="condref"     type="com.goldencode.ast.Aast" />
   <variable name="thenref"     type="com.goldencode.ast.Aast" />
   <variable name="varref"      type="com.goldencode.ast.Aast" />
   <variable name="lvalref"     type="com.goldencode.ast.Aast" />
   <variable name="fldref"      type="com.goldencode.ast.Aast" />
   <variable name="hlpref"      type="com.goldencode.ast.Aast" />
   <variable name="osref"       type="com.goldencode.ast.Aast" />
   <variable name="exprRef"     type="com.goldencode.ast.Aast" />
   <variable name="blockRef"    type="com.goldencode.ast.Aast" />
   <variable name="parSib"      type="com.goldencode.ast.Aast" />
   <variable name="chld"        type="com.goldencode.ast.Aast" />
   <variable name="tryid"       type="java.lang.Long" />
   <variable name="refid0"      type="java.lang.Long" />
   <variable name="castid"      type="java.lang.Long" />
   <variable name="explicitw"   type="java.lang.String" />
   <variable name="methodText"  type="java.lang.String" />
   <variable name="methodType"  type="java.lang.Integer" />
   <variable name="toktype"     type="java.lang.Integer" />
   <variable name="errmsg"      type="java.lang.String" />
   <variable name="txt"         type="java.lang.String" />
   <variable name="cls"         type="java.lang.String" />
   <variable name="shimCls"     type="java.lang.String" />
   <variable name="trigCls"     type="java.lang.String" />
   <variable name="refName"     type="java.lang.String" />
   <variable name="fename"      type="java.lang.String" />
   <variable name="listname"    type="java.lang.String" />
   <variable name="choosename"  type="java.lang.String" />
   <variable name="raytype"     type="java.lang.String" />
   <variable name="java_label"  type="java.lang.String" />
   <variable name="cname"       type="java.lang.String" />
   <variable name="javaname"    type="java.lang.String" />
   <variable name="optype"      type="java.lang.String" />
   <variable name="fmtstr"      type="java.lang.String" />
   <variable name="frname"      type="java.lang.String" />
   <variable name="jname"       type="java.lang.String" />
   <variable name="baseClass"   type="java.lang.String" />
   <variable name="legacyname"  type="java.lang.String" />
   <variable name="frmid"       type="java.lang.Long" />
   <variable name="lastid"      type="java.lang.Long" />
   <variable name="nonpeerid"   type="java.lang.Long" />
   <variable name="varid"       type="java.lang.Long" />
   <variable name="tempid"      type="java.lang.Long" />
   <variable name="parentid"    type="java.lang.Long" />
   <variable name="parmtype"    type="java.lang.Long" />
   <variable name="waitloc"     type="java.lang.Long" />
   <variable name="chooseloc"   type="java.lang.Long" />
   <variable name="valId"       type="java.lang.Long" />
   <variable name="loc"         type="java.lang.Long" />
   <variable name="streamid"    type="java.lang.Long" />
   <variable name="feref"       type="java.lang.Long" />
   <variable name="blockId"     type="java.lang.Long" />
   <variable name="blockParId"  type="java.lang.Long" />
   <variable name="shimid"      type="java.lang.Long" />
   <variable name="instvarid"   type="java.lang.Long" />
   <variable name="skipid"      type="java.lang.Long" />
   <variable name="trigid"      type="java.lang.Long" />
   <variable name="chooseidx"   type="java.lang.Integer" />
   <variable name="waitidx"     type="java.lang.Integer" />
   <variable name="nextNum"     type="java.lang.Integer" />
   <variable name="chooseNum"   type="java.lang.Integer" />
   <variable name="ttype"       type="java.lang.Integer" />
   <variable name="idx"         type="java.lang.Integer" />
   <variable name="ennum"       type="java.lang.Integer" />
   <variable name="parentIdx"   type="java.lang.Integer" />
   <variable name="multiMode"   type="java.lang.Boolean" />
   <variable name="peeremit"    type="java.lang.Boolean" />
   <variable name="needswait"   type="java.lang.Boolean" />
   <variable name="importUI"    type="java.lang.Boolean" />
   <variable name="importLT"    type="java.lang.Boolean" />
   <variable name="importFunc"  type="java.lang.Boolean" />
   <variable name="fullTrans"   type="java.lang.Boolean" />
   <variable name="lambdaBlock" type="java.lang.Boolean" />
   <variable name="iter"        type="java.util.Iterator" />
   <variable name="aggrMap"     type="java.util.HashMap" />
   <variable name="aggrMap2"    type="java.util.HashMap" />
   <variable name="dbEventType" type="java.lang.Integer" />
   <variable name="paramName"   type="java.lang.String" />
   <variable name="frameOpt"    type="com.goldencode.ast.Aast" />

   <!-- main processing (once per tree) -->
   
   <init-rules>
   
      <rule>tw.load("convert/java_templates")</rule>
      <rule>nextNum = 0</rule>
      <rule>chooseNum = 0</rule>
      <rule>ennum = 0</rule>
      <rule>importUI = false</rule>
      <rule>importLT = false</rule>
      <rule>importFunc = false</rule>
      <rule>aggrMap = create("java.util.HashMap")</rule>
      <rule>aggrMap2 = create("java.util.HashMap")</rule>
      <rule>baseClass = sprintf("%s.this", getNoteString("classname"))</rule>
      <rule>lambdaBlock = evalLib("isLambdaBlockEnabled")</rule>
      <rule>deleteDictionary("frame_element_name")</rule>

   </init-rules>
   
   <descent-rules>
      <rule>type == prog.content_array and parent.type == prog.statement
         <action>addScope("frame_element_name")</action>
         
         <action>fename = null</action>
         <rule>numImmediateChildren > 0
            <rule>evalLib("non_aggregate")
               <action>lastid = closestPeerId</action>
               <!-- Dealing with an aggregate, so reach to the peer node -->
               <action on="false">
                  scoperef = getAst(#(long) copy.getAnnotation("scope-id"))
               </action>
               
               <rule on="false">
                  scoperef.getAnnotation("aggr-id") == null
                  <action>
                     lastid = getAst(#(long) scoperef.getAnnotation("peerid")).parent.id
                  </action>
                  
                  <action on="false">
                     lastid = null
                  </action>
               </rule>
            </rule>

            <rule>lastid != null
               <!-- determine the instance name -->
               <action>fename = getNoteString("javaname")</action>
               <action>addDictionaryObject("frame_element_name", "fename", fename)</action>
            </rule>  
         </rule>
      </rule>
   </descent-rules>
      
   
   <walk-rules>
      <!-- convert SYSTEM-DIALOG FONT -->
      <rule>type == prog.system_dialog_font
         <action>importUI = true</action>
         
         <action>evalLib("initializeChain", copy, closestPeerId,
                         "execute",                           java.method_call,
                         "FontTable.createFontChooserDialog", java.static_method_call)</action>
      </rule>
      <rule>parent.type == prog.system_dialog_font
         <rule>type == prog.kw_ansi_onl
            <action>execLib("addChainNode", copy.parent, "ansiOnly", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_fixd_onl
            <action>execLib("addChainNode", copy.parent, "fixedOnly", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_max_sz
            <action>execLib("addChainNode", copy.parent, "setMaxSize", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_min_sz
            <action>execLib("addChainNode", copy.parent, "setMinSize", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_in <!-- previous sibling is prog.kw_window -->
            <action>execLib("addChainNode", copy.parent, "setWindow", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_update
            <action>execLib("addChainNode", copy.parent, "update", java.method_call)</action>
         </rule>
      </rule>
      
      <!-- convert SYSTEM-DIALOG COLOR -->
      <rule>type == prog.system_dialog_color
         <action>importUI = true</action>
         
         <action>evalLib("initializeChain", copy,  closestPeerId,
                         "execute",                             java.method_call,
                         "ColorTable.createColorChooserDialog", java.static_method_call)</action>
      </rule>
      <rule>parent.type == prog.system_dialog_color
         <rule>type == prog.kw_in <!-- previous sibling is prog.kw_window -->
            <action>execLib("addChainNode", copy.parent, "setWindow", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_update
            <action>execLib("addChainNode", copy.parent, "update", java.method_call)</action>
         </rule>
      </rule>
      
      <!-- convert SYSTEM-DIALOG GET-FILE -->
      <rule>type == prog.system_dialog_get_file
         <action>importUI = true</action>
         
         <action>evalLib("initializeChain", copy, closestPeerId,
                         "execute",                           java.method_call, 
                         "FileDialog.createFileSearchDialog", java.static_method_call)</action>
      </rule>
      <rule>type == prog.system_dialog_get_dir
         <action>importUI = true</action>
         
         <action>evalLib("initializeChain", copy, closestPeerId,
                         "execute",                          java.method_call, 
                         "FileDialog.createDirSearchDialog", java.static_method_call)</action>
      </rule>
      <rule>parent.type == prog.system_dialog_get_file or
            parent.type == prog.system_dialog_get_dir
         <rule>type == prog.kw_creat_tf
            <action>
               execLib("addChainNode", copy.parent, "createTestFile", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_ask_over
            <action>
               execLib("addChainNode", copy.parent, "askOverwrite", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_save_as
            <action>execLib("addChainNode", copy.parent, "saveAs", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_ret_2sd
            <action>
               execLib("addChainNode", copy.parent, "returnToStartDir", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_must_exi
            <action>execLib("addChainNode", copy.parent, "mustExist", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_use_fil
            <action>execLib("addChainNode", copy.parent, "useFilename", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_init_dir
            <action>
               execLib("addChainNode", copy.parent, "setInitialDir", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_def_extn
            <action>
               execLib("addChainNode", copy.parent, "setDefaultExtension", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_update
            <action>execLib("addChainNode", copy.parent, "update", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_title
            <action>execLib("addChainNode", copy.parent, "setTitle", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_filters
            <action>execLib("addChainNode", copy.parent, "setFilters", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_in <!-- previous sibling is prog.kw_window -->
            <action>execLib("addChainNode", copy.parent, "setWindow", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_at_w_brw
            <action>execLib("addChainNode", copy.parent, "atWebBrowser", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_multiple
            <action>execLib("addChainNode", copy.parent, "multiple", java.method_call)</action>
         </rule>
      </rule>
      <rule>type == prog.kw_upload
         <action>execLib("addChainNode", copy.parent.parent, "upload", java.method_call)</action>
      </rule>
      <rule>type == prog.kw_init_flt       and
            parent.type == prog.kw_filters and 
            parent.parent.type == prog.system_dialog_get_file
         <action>
            execLib("addChainNode", copy.parent.parent, "setInitialFilter", java.method_call)
         </action>
      </rule>
      
      <rule>type == prog.system_dialog_printer_setup
         <action>importUI = true</action>
         <action>
            evalLib("initializeChain", copy, closestPeerId,
                    "execute",                           java.method_call,
                    "PrintingService.createSetupDialog", java.static_method_call)
         </action>
      </rule>
      <rule>parent.type == prog.system_dialog_printer_setup
         <rule>type == prog.kw_num_copy
            <action>
               execLib("addChainNode", copy.parent, "setCopyCount", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_landscap
            <action>
               ref = execLib("addChainNode", copy.parent, "setOrientation", java.method_call)
            </action>
            <rule>ref != null
               <action>createJavaAst(java.reference, "PrintingService.LANDSCAPE", ref)</action>
            </rule>
         </rule>
         <rule>type == prog.kw_portrait
            <action>
               ref = execLib("addChainNode", copy.parent, "setOrientation", java.method_call)
            </action>
            <rule>ref != null
               <action>createJavaAst(java.reference, "PrintingService.PORTRAIT", ref)</action>
            </rule>
         </rule>
         <rule>type == prog.kw_update
            <action>
               ref = execLib("addChainNode", copy.parent, "update", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_in
            <action>
               execLib("addChainNode", copy.parent, "setWindow", java.method_call)
            </action>
         </rule>
      </rule>
      
      <!-- SYSTEM-HELP statement -->
      <rule>type == prog.kw_sys_help
         <action>importUI = true</action>
         <action>evalLib("initializeChain", copy, closestPeerId,
                         "execute",             java.method_call,
                         "HelpService.prepare", java.static_method_call)</action>
      </rule>
      <rule>parent.type == prog.kw_sys_help
         <rule>type == prog.kw_win_name
            <action>
               execLib("addChainNode", copy.parent, "setWindowName", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_contents
            <action>execLib("addChainNode", copy.parent, "contents", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_ctx
            <action>execLib("addChainNode", copy.parent, "setContext", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_help_top
            <action>execLib("addChainNode", copy.parent, "setTopic", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_key
            <action>execLib("addChainNode", copy.parent, "setKey", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_alt_key
            <action>
               execLib("addChainNode", copy.parent, "setAlternateKey", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_pos
            <rule>this.getFirstChild().type == prog.kw_maximize
               <action>
                  execLib("addChainNode", copy.parent, "maximized", java.method_call)
               </action>
               <action on="false">
                  execLib("addChainNode", copy.parent, "setPosition", java.method_call)
               </action>
            </rule>
         </rule>
         <rule>type == prog.kw_quit
            <action>execLib("addChainNode", copy.parent, "quit", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_set_cont
            <action>
               execLib("addChainNode", copy.parent, "setContents", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_ctx_pop
            <action>
               execLib("addChainNode", copy.parent, "setContextPopup", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_part_key
            <action>
               execLib("addChainNode", copy.parent, "setPartialKey", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_mult_key <!-- + prog.kw_text-->
            <action>
               execLib("addChainNode", copy.parent, "setMultipleKey", java.method_call)
            </action>
         </rule>
         <rule>type == prog.kw_command
            <action>execLib("addChainNode", copy.parent, "setCommand", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_finder
            <action>execLib("addChainNode", copy.parent, "finder", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_force_f
            <action>execLib("addChainNode", copy.parent, "forceFile", java.method_call)</action>
         </rule>
         <rule>type == prog.kw_help
            <action>execLib("addChainNode", copy.parent, "help", java.method_call)</action>
         </rule>
      </rule>
      
      <!-- convert FRAME_LOCK and FRAME_UNLOCK helpers -->
      <rule>type == prog.frame_lock
         <action>
            createPeerAst(java.static_method_call,
                          "DynamicWidgetFactory.pushScreenLock",
                           closestPeerId)
         </action> 
      </rule>
      <rule>type == prog.frame_unlock
         <action>
            createPeerAst(java.static_method_call,
                          "DynamicWidgetFactory.pushScreenUnlock",
                           closestPeerId)
         </action> 
      </rule>

      <!-- convert CREATE widget statements -->
      <rule>type == prog.create_widget
         <action>importUI = true</action>
         <action>explicitw = null</action>
         <action>methodText = null</action>
         <action>methodType = java.static_method_call</action>

         <rule>explicitw == null and 
               (downPath("KW_BUTTON") or evalLib("match_widget_type", "button"))
            <action>explicitw = "Button"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_CHART") or evalLib("match_widget_type", "chart"))
            <action>explicitw = "Chart"</action>
         </rule>
         <rule>explicitw == null and 
              (downPath("KW_COMBO_BX") or evalLib("match_widget_type", "combo-box"))
            <action>explicitw = "ComboBox"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_CNTRL_FR") or evalLib("match_widget_type", "control-frame"))
            <action>explicitw = "ControlFrame"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_DIALOG") or evalLib("match_widget_type", "dialog-box"))
            <action>explicitw = "DialogBox"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_CALENDAR") or evalLib("match_widget_type", "calendar"))
            <action>explicitw = "Calendar"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_EDITOR") or evalLib("match_widget_type", "editor"))
            <action>explicitw = "Editor"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_FILL_IN") or evalLib("match_widget_type", "fill-in"))
            <action>explicitw = "FillIn"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_FRAME") or evalLib("match_widget_type", "frame"))
            <action>explicitw = "Frame"</action>
         </rule>
         <rule>explicitw == null and
            (downPath("KW_HTML_BWS") or evalLib("match_widget_type", "html-browser"))
            <action>explicitw = "HtmlBrowser"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_IMAGE") or evalLib("match_widget_type", "image"))
            <action>explicitw = "Image"</action>
         </rule>
         <rule>explicitw == null and
            (downPath("KW_IL_IMG") or evalLib("match_widget_type", "imagelist"))
            <action>explicitw = "ImageList"</action>
         </rule>
         <rule>explicitw == null and
               (downPath("KW_MENU") or evalLib("match_widget_type", "menu"))
            <action>explicitw = "Menu"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_MENU_ITM") or evalLib("match_widget_type", "menu-item"))
            <action>explicitw = "MenuItem"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_PROG_BAR") or evalLib("match_widget_type", "progress-bar"))
            <action>explicitw = "ProgressBar"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_RADIO_S") or evalLib("match_widget_type", "radio-set"))
            <action>explicitw = "RadioSet"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_RECT") or evalLib("match_widget_type", "rectangle"))
            <action>explicitw = "Rectangle"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_SEL_LST") or evalLib("match_widget_type", "selection-list"))
            <action>explicitw = "SelectionList"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_SIGNATUR") or evalLib("match_widget_type", "signature"))
            <action>explicitw = "Signature"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_SLIDER") or evalLib("match_widget_type", "slider"))
            <action>explicitw = "Slider"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_SUB_MENU") or evalLib("match_widget_type", "sub-menu"))
            <action>explicitw = "SubMenu"</action>
         </rule>
         <rule>explicitw == null and
            (downPath("KW_TABSET") or evalLib("match_widget_type", "tabset"))
            <action>explicitw = "TabSet"</action>
         </rule>
         <rule>explicitw == null and
               (downPath("KW_TEXT") or evalLib("match_widget_type", "text"))
            <action>explicitw = "Text"</action>
         </rule>
         <rule>explicitw == null and
               (downPath("KW_TOGGL_BX") or evalLib("match_widget_type", "toggle-box"))
            <action>explicitw = "ToggleBox"</action>
         </rule>
         <rule>explicitw == null and
            (downPath("KW_TREELIST") or evalLib("match_widget_type", "treelist"))
            <action>explicitw = "TreeList"</action>
         </rule>
         <rule>explicitw == null and
            (downPath("KW_TREEVIEW") or evalLib("match_widget_type", "treeview"))
            <action>explicitw = "TreeView"</action>
         </rule>
         <rule>explicitw == null and
               (downPath("KW_WINDOW") or evalLib("match_widget_type", "window"))
            <action>explicitw = "Window"</action>
         </rule>
         <rule>explicitw == null and 
               (downPath("KW_BTN_LIST") or evalLib("match_widget_type", "button-list"))
            <action>explicitw = "ButtonList"</action>
         </rule>

         <rule>explicitw != null
            <action>methodText = sprintf("DynamicWidgetFactory.create%s", explicitw)</action>

            <rule on="false">downPath("KW_VALUE")
               <action>methodText = "DynamicWidgetFactory.create"</action>
            </rule>
         </rule>

         <rule>methodText != null
            <action>
               createPeerAst(methodType, methodText, closestPeerId)
            </action>

            <action on="false">
               throwException(sprintf("Unsupported CREATE WIDGET statement clause [%s]", 
                                      this.getFirstChild().text))
            </action>
         </rule>
      </rule>

       <!-- convert CREATE BROWSE statement -->
      <rule>type == prog.create_browse
         <action>importUI = true</action>
         <action>
            createPeerAst(java.static_method_call,
                          "DynamicWidgetFactory.createBrowse",
                          closestPeerId)
         </action>
      </rule>

      <!-- locate form header registration just after open scope (if
           possible), this is needed since Progress handles the equivalent
           registration at compile-time instead of runtime (in particular
           if the form header stmt appears in a conditional block then the
           runtime approach used in Java would fail so we have to move the
           registration to a location that is unconditional relative to
           the use of the frame) -->
      <rule>
         type == prog.statement          and
         downPath("KW_FORM/KW_HEADER")   and
         descendant(prog.content_array, 1)
         
         <!-- defaults -->
         <action>parentid = closestPeerId</action>
         <action>idx = -1</action>
         
         <!-- try to find the location of the open scope call -->
         <action>
            osref = copy.getImmediateChild(prog.kw_form, null)
         </action>
         <action>
            osref = getAst(#(java.lang.Long) osref.getAnnotation("frame-id"))
         </action>
         <action>
            osref = getAst(#(java.lang.Long)
                           osref.getAnnotation("scope_peer"))
         </action>
         
         <!-- it is possible that this reference appears before the scope
              opens, if so we bypass this code and emit in place
              (closestPeerId) -->
         <rule>osref != null
            <!-- override the location to be just after the open scope -->
            <action>parentid = osref.parent.id</action>
            <action>idx = osref.indexPos + 1</action>
         </rule>
         
         <!-- create a container for all subsequent creation -->
         <action>createPeerAst(java.bogus, "", parentid, idx)</action>
      </rule>

      <!-- emit browse widget complex title, if any -->
      <rule>parent.type == prog.runtime_browse_options and
            copy.type == prog.kw_title
         <action>
            execLib("generate_browse_title", copy)
         </action>
      </rule>

      <rule>parent.type == prog.statement
      
         <action>methodText = null</action>
         <action>methodType = java.method_call</action>
         <action>refName = null</action>
         <action>peeremit = true</action>
      
         <!-- process the frame reference prep in fewer places -->
         <rule>
            type == prog.kw_choose     or
            type == prog.kw_color      or
            type == prog.kw_disable    or
            type == prog.kw_disp       or
            type == prog.kw_down       or
            type == prog.kw_enable     or
            type == prog.kw_next_pmt   or
            type == prog.kw_prmt_for   or
            type == prog.kw_scroll     or
            type == prog.kw_set        or
            type == prog.kw_up         or
            type == prog.kw_update     or
            ((type == prog.kw_hide or type == prog.kw_view) and 
             isNote("frame-id") and !isNote("single-element")) or
            (type == prog.kw_form and descendant(prog.kw_header, 1))
            
            <action>
               refName = #(java.lang.String) execLib("get_framename", this)
            </action>
         </rule>
      
         <!-- emit apply -->
         <rule>type == prog.kw_apply and !evalLib("apply_to_handle", this)

            <!-- this works for frame and widget forms (not for the global
                 form), if the widget form is used, the widget will emit
                 automatically downstream) -->
            <action>methodText = "apply"</action>
         
            <rule>
               numImmediateChildren == 1            or
               downPath("KW_TO/KW_FRAME/WID_FRAME") or
               downPath("KW_TO/WID_FRAME")
            
               <rule>isNote("frame-id")   
               
                  <!-- frame form (the "TO FRAME frame" has been hidden by
                       now), force an artificial frame reference to be 
                       emitted below -->
                  <action>
                     refName = #(java.lang.String)
                               execLib("get_framename", this)
                  </action>
                  
                  <!-- global form with no widget phrase -->
                  <action on="false">methodText = "apply"</action>
                  <action on="false">importLT = true</action>
                  <action on="false">methodType = java.static_method_call</action>
                  
               </rule>
            </rule>
         </rule>
         
         <!-- bell -->
         <rule>type == prog.kw_bell
            <action>methodText = "bell"</action>
            <action>importLT = true</action>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- choose -->
         <rule>type == prog.kw_choose
            <action>methodType = java.method_call</action>
            <action>methodText = "choose"</action>
            <action>peeremit = false</action>
            <action>execLib("gen_choose")</action>
         </rule>
         
         <!-- clear -->
         <rule>type == prog.kw_clear
         
            <action>methodText = "clear"</action>
            <action>methodType = java.method_call</action>
            
            <rule>descendant(prog.kw_all, 1)
               <action>methodText = "clearAll"</action>
            </rule>
            
            <rule>descendant(prog.kw_frame, 1)
               <!-- frame form is handled here, otherwise this is the
                    terminal form and is static -->
               <action>
                  refName = #(java.lang.String) execLib("get_framename", this)
               </action>
               
               <action on="false">importLT = true</action>
               <action on="false">
                  methodType = java.static_method_call
               </action>
            </rule>
         </rule>

         <!-- define browse -->
         <rule>type == prog.define_browse
            <action>methodText = "registerQuery"</action>
         </rule>

         <!-- color -->
         <rule>type == prog.kw_color
            <action>methodText = "setColors"</action>
         </rule>
         
         <!-- disable (frame form for ALL or multiple widget mode, otherwise
              this is a widget form and the widget refs emit directly) -->
         <rule>type == prog.kw_disable
            <action>methodText = "disable"</action>
            <rule>downPath("KW_ALL/KW_EXCEPT")
               <action>methodText = "disableExcept"</action>
            </rule>
            <!-- adding UNLESS-HIDDEN option handling -->
            <rule>downPath("KW_UNL_HID")
               <action>methodText = "disableUnlessHidden"</action>
            </rule>
            <!-- if there is only a single child, then the instance method
                 name above will be used but not the frame referent -->
            <action>
               ref = this.getImmediateChild(prog.content_array, null)
            </action>
            <rule>ref.numImmediateChildren == 1
               <action>refName = null</action>
            </rule>
         </rule>
         
         <rule> 
            type == prog.kw_disp and parent.type == prog.statement
            <action>parSib =  parent.nextSibling</action>
            <rule>
               parSib != null and parSib.type == prog.statement
               <action>chld = parSib.firstChild</action>
               <rule>
                  chld != null and 
                  evalLib("is_display_and_down", this, chld)
                  <action>this.putAnnotation("followed-by-down", true)</action>
                  <action>chld.remove()</action>
               </rule>
            </rule>
         </rule>

         <!-- display -->
         <rule>type == prog.kw_disp
            <action>methodText = "display"</action>
            <rule>downPath("KW_UNL_HID")
               <action>methodText = "displayUnlessHidden"</action>
            </rule>
            <rule>#(boolean)this.getAnnotation("followed-by-down") == true
               <action>methodText = methodText.concat("AndDown")</action>
            </rule> 
         </rule>
         
         <!-- down -->
         <rule>type == prog.kw_down
            <action>methodText = "down"</action>
          </rule>
         
         <!-- delete a handle or comhandle -->
         <rule>type == prog.delete_widget
            <rule>this.getFirstChild().type == prog.var_com_handle
               <action>methodText = "ComServer.delete"</action>
               <action on="false">methodText = "HandleOps.delete"</action>
           </rule>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- enable (frame form for ALL or multiple widget mode, otherwise
              this is a widget form and the widget refs emit directly) -->
         <rule>type == prog.kw_enable
            <action>methodText = "enable"</action>
            <rule>downPath("KW_ALL/KW_EXCEPT")
               <action>methodText = "enableExcept"</action>
            </rule>
            
            <rule>downPath("KW_UNL_HID")
               <action>methodText = "enableUnlessHidden"</action>
               <rule>downPath("KW_ALL/KW_EXCEPT")
                  <action>methodText = "enableUnlessHiddenExcept"</action> 
               </rule>
            </rule>
            
            <!-- if there is only a single child, then the instance method
                 name above will be used but not the frame referent -->
            <action>
               ref = this.getImmediateChild(prog.content_array, null)
            </action>
            <rule>ref.numImmediateChildren == 1
               <action>refName = null</action>
            </rule>
         </rule>
         
         <!-- form header (only emit if there are non-space, non-skip
              elements) -->
         <rule>type == prog.kw_form and descendant(prog.kw_header, 1)
            <action>
               ref = copy.parent.getImmediateChild(prog.content_array, null)
            </action>
            <rule>ref != null and ref.numImmediateChildren > 0
               <action>methodText = "registerHeader"</action>
            </rule>
         </rule>
         
         <!-- hide -->
         <rule>type == prog.kw_hide
            <rule>descendant(prog.kw_msg, 1)
               <action>methodText = "hideMessage"</action>
               <action>importLT = true</action>
            </rule>
            <rule>descendant(prog.kw_all, 1)
               <action>methodText = "hideAll"</action>
               <action>importLT = true</action>
            </rule>
            <rule>methodText == null
               <action>methodText = "hide"</action>
               
               <!-- frame form is handled here, otherwise this is a widget
                    form and the widget refs emit directly OR this is a
                    terminal form and is static -->
               <rule>isNote("frame-id") and 
                     (!isNote("single-element") or
                      (this.numImmediateChildren == 1 and 
                       this.getImmediateChild(prog.kw_stream, null) != null))

                  <action>refName = #(java.lang.String) execLib("get_framename", this)</action>

                  <rule on="false">not isNote("frame-id") and
                                   not (this.firstChild != null and 
                                        evalLib("handle_type", this.firstChild.type))
                     <action>methodText = null</action>
                     <action>refName = null</action>
                  </rule>
               </rule>
               
               <!-- handle type for msg and all cases here -->
               <action on="false">methodType = java.static_method_call</action>
            </rule>
         </rule>
         
         <!-- input clear -->
         <rule>type == prog.input_clear
            <action>methodText = "inputClear"</action>
            <action>importLT = true</action>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- message statement -->
         <rule>type == prog.kw_msg
            <rule>descendant(prog.kw_view_as, 1)
               <action>methodText = "messageBox"</action>
               <action on="false">methodText = "message"</action>
            </rule>
            <action>importLT = true</action>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- next-prompt (widget parm will emit naturally) -->
         <rule>type == prog.kw_next_pmt
            <action>methodText = "nextPrompt"</action>
         </rule>

         <!-- ON statement -->
         <rule>type == prog.kw_on
            
            <rule>!descendant(prog.db_event, 1)
               <action>needswait = true</action>
            </rule>

            <action>methodType = java.static_method_call</action>
            
            <rule>
               numImmediateChildren == 2              and
               this.getChildAt(0).type == prog.event  and
               this.getChildAt(1).type == prog.key_function
               
               <action>needswait = false</action>
               <action>methodText = "remapKey"</action>
               <action>importLT = true</action>
               
               <rule on="false">descendant(prog.db_event, 1)
                  <!-- is database trigger ? -->
                  <action>needswait = false</action>

                  <rule>descendant(prog.kw_revert, 1)
                     <action>methodText = "deregisterDatabaseTrigger"</action>
                     <action on="false">methodText = "registerDatabaseTrigger"</action>
                  </rule>
                  <action>createStaticImport("com.goldencode.p2j.persist.trigger.DatabaseTriggerManager.*")</action>
                  <action>createImport("com.goldencode.p2j.persist.trigger.*")</action>

                  <!-- non-database triggers -->
                  <rule on="false">descendant(prog.kw_revert, 1)
                     <action>methodText = "deregisterTrigger"</action>
                     <action>importLT = true</action>

                     <rule on="false">descendant(prog.kw_persist, 1)
                        <!-- emit dedicated APIs when ON ... PERSISTENT RUN .. [IN handle]
                             clause is used -->
                        <rule>downPath("KW_PERSIST/KW_RUN/KW_IN")
                           <action>methodText = "registerTriggerPersistentIn"</action>
                           <action on="false">methodText = "registerTriggerPersistent"</action>
                        </rule>

                        <action>importLT = true</action>

                        <rule>descendant(prog.library_ref, 3)
                           <action>
                              errmsg = sprintf("ERROR: Unsupported RUN mode %s in %d.", 
                                               this.lookupTokenName(prog.library_ref), this.id)
                           </action>
                           <action>printfln(errmsg)</action>
                        </rule>

                        <!-- normal trigger definition -->
                        <action on="false">methodText = "registerTrigger"</action>
                        <action on="false">importLT = true</action>
                        
                        <!-- create the container for instance variables -->
                        <action on="false">trigid = closestPeerId</action>
                        <action on="false">
                           instvarid = createJavaAst(java.bogus, "", closestPeerId)
                        </action> 
                        <action on="false">
                           skipid = createJavaAst(java.skip, "", closestPeerId)
                        </action> 
                        
                     </rule>
                  </rule>

                  <!-- for non-database triggers, if there are multiple OF clauses, then we
                       must generate a standalone EventList instance -->
                  <rule on="false">copy.getNumImmediateChildren(prog.kw_of) &gt; 1
                     <action>execLib("gen_separate_event_list")</action>
                     
                     <!-- single OF clause emits inline below -->
                     <action on="false">multiMode = false</action>
                  </rule>
               </rule>
            </rule>
         </rule>
                  
         <!-- pause statement -->
         <rule>type == prog.kw_pause
            <rule>descendant(prog.kw_b4_hide, 1)
               <action>methodText = "pauseBeforeHide"</action>
               <action on="false">methodText = "pause"</action>
            </rule>
            <action>importLT = true</action>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- process events -->
         <rule>type == prog.process_events
            <action>methodText = "processEvents"</action>
            <action>importLT = true</action>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- put cursor -->
         <rule>type == prog.put_cursor
            <action>methodText = "putCursor"</action>
            <action>importLT = true</action>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- put screen -->
         <rule>type == prog.put_screen
            <action>methodText = "putScreen"</action>
            <action>importLT = true</action>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- scroll -->
         <rule>type == prog.kw_scroll
            <action>methodText = "scroll"</action>
         </rule>
         
         <!-- status (the single, optional parameter automatically emits) -->
         <rule>type == prog.kw_status
            <action>methodType = java.static_method_call</action>
            <action>importLT = true</action>
            
            <rule>descendant(prog.kw_default, 1)
            
               <!-- default mode -->
               <action>methodText = "statusDefault"</action>
               
               <!-- must be input mode so we don't test for kw_input -->
               <rule on="false">descendant(prog.kw_off, 1)
                  <action>methodText = "statusInputOff"</action>
                  <action on="false">methodText = "statusInput"</action>
               </rule>
            </rule>
         </rule>
         
         <!-- terminal -->
         <rule>type == prog.kw_term
            <rule>descendant(prog.kw_term, 1)
            
               <!-- special case of resetting the terminal without changing the type -->
               <action>methodText = "resetTerminal"</action>
               
               <!-- common case, the parameter will emit naturally -->
               <action on="false">methodText = "setTerminalType"</action>
               
            </rule>
            <action>importLT = true</action>
            <action>methodType = java.static_method_call</action>
         </rule>
         
         <!-- underline, excluding "empty" underline cases -->
         <rule>type == prog.kw_underlin and
               copy.numImmediateChildren &gt; 0 and
               copy.getChildAt(0).type != prog.frame_phrase
            <action>methodText = "underline"</action>
            
            <!-- if there is only a single child, then the instance method
                 name above will be used, find the root for the field list
                 -->
            <action>
               ref = this.getImmediateChild(prog.content_array, null)
            </action>
            
            <!-- check if we use the frame form or not -->
            <rule>ref.numImmediateChildren > 1
               <action>
                  refName = #(java.lang.String) execLib("get_framename", this)
               </action>
            </rule>
         </rule>
         
         <!-- up -->
         <rule>type == prog.kw_up
            <action>methodText = "up"</action>
         </rule>
         
         <!-- update, set and prompt-for -->
         <rule>
            type == prog.kw_update  or
            type == prog.kw_set     or
            type == prog.kw_prmt_for
            
            <!-- non-EDITING block case using go-on emits inline below -->
            <action>multiMode = false</action>
            
            <rule>descendant(prog.editing_block, 1)
               
               <!-- bypass normal processing on editing block and emit below -->
               <action>refName = null</action>
               
               <!-- EDITING block case will generate a separate EventList instance if needed -->
               <rule>descendant(prog.kw_go_on, 1)
                  <action>execLib("gen_separate_event_list")</action>
               </rule>
               
               <!-- calc the correct method name -->
               <rule on="false">type == prog.kw_update
               
                  <action>methodText = "update"</action>
                  
                  <rule on="false">type == prog.kw_set
                     <action>methodText = "set"</action>
                     <action on="false">methodText = "promptFor"</action>
                  </rule>
                  
               </rule>
            
               <!-- adding UNLESS-HIDDEN option handling -->
               <rule on="false">downPath("KW_UNL_HID")
                  <action>methodText = methodText.concat("UnlessHidden")</action>
               </rule>
            </rule>
         </rule>
      
         <!-- view -->
         <rule>type == prog.kw_view
            <action>methodText = "view"</action>
            
            <!-- frame form is handled here, otherwise this is a widget
                 form and the widget refs emit directly -->
            <rule>isNote("frame-id") and 
                  (!isNote("single-element") or
                   (this.numImmediateChildren == 1 and 
                    this.getImmediateChild(prog.kw_stream, null) != null))

               <action>refName = #(java.lang.String) execLib("get_framename", this)</action>
            </rule>
         </rule>
         
         <!-- wait-for -->
         <rule>type == prog.kw_wait_for
            <action>methodType = java.static_method_call</action>
            <action>methodText = "LogicalTerminal.waitFor"</action>
            <action>importLT = true</action>
            <!-- if there are multiple OF clauses, then we must generate a standalone
                 EventList instance -->
            <rule>copy.getNumImmediateChildren(prog.kw_of) &gt; 1
               <action>execLib("gen_separate_event_list")</action>
               <!-- single OF clause emits inline below -->
               <action on="false">multiMode = false</action>
            </rule>
         </rule>
         
         <!-- separate the widget lists from the statement -->
         <rule>type == prog.kw_update   or
               type == prog.kw_set      or
               type == prog.kw_prmt_for or
               type == prog.kw_disp     or
               type == prog.kw_disable  or
               type == prog.kw_enable   or
               type == prog.kw_view     or
               type == prog.kw_hide     or
               type == prog.kw_choose   or
               type == prog.kw_color    or
               type == prog.kw_underlin or
               type == prog.kw_wait_for
            <!-- insert a blank line for readability (duplicates will be removed downstream) -->
            <action>createJavaAst(java.skip, "", closestPeerId)</action> 
            
            <!-- save this off for downstream (ascent rules), this has to be outside of the
                 processing below because there are valid cases (e.g. editing blocks) where
                 the methodTxt is null but this must be saved -->
            <action>putNote("block_par_id", closestPeerId)</action>
         </rule>
         
         <!-- create the peer node -->
         <rule>methodText != null and methodText.length() != 0
            
            <!-- create our method call node -->
            <rule>peeremit
               <action>
                  lastid = createPeerAst(methodType,
                                         methodText,
                                         closestPeerId)
               </action>
               <action on="false">
                  lastid = createJavaAst(methodType,
                                         methodText,
                                         closestPeerId)
               </action>
               <action on="false">
                  nonpeerid = lastid
               </action>
            </rule>
            
            <!-- create the method referent (a frame) if needed -->
            <rule>methodType == java.method_call and refName != null
               <action>createJavaAst(java.reference, refName, lastid)</action>
            </rule>   
            
            <!-- static use of LogicalTerminal must create an import
                 in case it is the only access in the given class -->
            <rule>methodType == java.static_method_call
               <action>importUI = true</action>
            </rule>
            
         </rule>
      </rule>
      
      <rule>
         type == prog.statement  and
         downPath("DEFINE_VARIABLE/KW_AS/KW_WID_HAND")
         <action>importUI = true</action>
      </rule>

      <!-- add an import stmt if there is any node that references a frame
           or if a language statement was executed that uses LogicalTerminal
           directly -->
      <rule>isNote("frame-id") or importUI or type == prog.frame_alloc
         <rule>createImport("com.goldencode.p2j.ui.*")</rule>
      </rule>
            
      <!-- emit manufactured when clauses as assignments to generated
           temporary condition vars of type boolean -->
      <rule>type == prog.kw_when and parent.type == prog.when_list
         <rule>
            downPath("EXPRESSION/BOOL_TRUE") or
            downPath("EXPRESSION/BOOL_FALSE")
            
            <!-- literal case -->
            <action>
               tw.graft("unfinished_var_def",
                        copy,
                        closestPeerId,
                        "classname",
                        "boolean",
                        "javaname",
                        getNoteString("javaname"))
            </action>
            
            <!-- non-literal -->
            <action on="false">exprRef = copy.getChildAt(0)</action>
            <rule on="false">exprRef != null
               <action>exprRef = exprRef.getChildAt(0)</action>
            </rule>
            <rule on="false">exprRef != null and evalLib("childCanAvoidUnwrap", exprRef)
               
               <!-- create the var but don't unwrap -->
               <action>
                  tw.graft("init_var_full_no_wrap",
                           copy,
                           closestPeerId,
                           "wrapper",
                           "boolean",
                           "javaname",
                           getNoteString("javaname"))
               </action>
               
               <!-- create the var and unwrap it as a boolean -->
               <action on="false">
                  shimid = tw.graft("init_var_full",
                                    copy,
                                    closestPeerId,
                                    "wrapper",
                                    "boolean",
                                    "javaname",
                                    getNoteString("javaname"),
                                    "type",
                                    "METHOD_CALL",
                                    "text",
                                    "booleanValue").id
               </action>
               
               <!-- check if the expression is one that is an indeterminate _POLY which
                    returns a BDT or which returns a type that is not logical; in these
                    cases we coerce to a logical by wrapping -->
               <action on="false">shimCls = expressionType(exprRef, false)</action>
               <rule on="false">shimCls == null or !shimCls.equals("logical")
                  <!-- wrap the result first (before it is unwrapped) -->
                  <action>shimid = createJavaAst(java.constructor, "logical", shimid)</action>
                  <action>copy.putAnnotation("peerid", shimid)</action>
               </rule>
               
            </rule>
         </rule>
      </rule>
            
      <!-- emit content for message statements and widget arrays -->
      <rule>
         type == prog.content_array    and
         parent.type != prog.statement and
         numImmediateChildren > 1
      
         <!-- determine the classname -->
         <rule>parent.type == prog.kw_msg
            <action>cls = "Object"</action>
            <action on="false">cls = "GenericWidget"</action>
         </rule>
         
         <!-- emit the object array initializer node -->
         <action>
            tw.graft("anon_array",
                     copy,
                     closestPeerId,
                     "classname",
                     cls,
                     "extent",
                     string(numImmediateChildren))
         </action>
         
      </rule>
      
      <!-- emit content for frame element arrays -->
      <rule>type == prog.content_array and parent.type == prog.statement
         
         <action>fename = null</action>
         
         <!-- only emit for non-empty arrays -->
         <rule>numImmediateChildren > 0

            <rule>evalLib("non_aggregate")

               <action>lastid = closestPeerId</action>

               <!-- Dealing with an aggregate, so reach to the peer node -->
               <action on="false">
                  scoperef = getAst(#(long) copy.getAnnotation("scope-id"))
               </action>
               
               <rule on="false">
                  scoperef.getAnnotation("aggr-id") == null
                  <action>
                     lastid = getAst(#(long) scoperef.getAnnotation("peerid")).parent.id
                  </action>
                  
                  <action on="false">
                     lastid = null
                  </action>
               </rule>
            </rule>

            <rule>
               lastid != null
               
               <!-- add a spacer before the array emits -->
               <action>createJavaAst(java.skip, "", lastid)</action>
         
               <!-- determine the instance name -->
               <action>fename = lookupDictionaryObject("frame_element_name", "fename")</action>
               <rule>fename == null
                  <action>fename = getNoteString("javaname")</action>
               </rule>
               
               <!-- emit the object array initializer node -->
               <action>
                  lastid = tw.graft("named_array",
                                    copy,
                                    lastid,
                                    "classname",
                                    "FrameElement",
                                    "javaname",
                                    fename,
                                    "extent",
                                    string(numImmediateChildren)).id
               </action>
               
               <rule>evalLib("non_aggregate")               

                  <action on="false">
                     aggrMap.put(scoperef, getAst(lastid).parent.parent)
                  </action>
                  <action on="false">
                     aggrMap2.put(scoperef, copy.getAnnotation("javaname"))
                  </action>
                       
                  <action on="false">
                     scoperef.putAnnotation("aggr-id", lastid)
                  </action>
                  
                  <action on="false">
                     copy.putAnnotation("peerid", lastid)
                  </action>
                  
               </rule>
               
               <rule on="false">evalLib("non_aggregate")               

                  <action on="false">
                     copy.putAnnotation("peerid", 
                        #(java.lang.Long) scoperef.getAnnotation("aggr-id"))
                  </action>
               </rule>
            </rule>  
         </rule>
      </rule>
      
      <!-- conditional processing (additional processing below) -->
      <rule>type == prog.kw_when and parent.type == prog.content_array
         <action>
            ternref = createPeerAst(java.tern_if_else,
                                    "", 
                                    getAst(closestPeerId))
         </action>
         <!-- handle the special case where this is a manufactured WHEN
              and there is no first expression -->
         <rule>isNote("refid")
            <action>
               javaname = #(java.lang.String) execLib("get_javaname", this)
            </action>
            <action>createJavaAst(java.reference, javaname, ternref)</action>
         </rule>
      </rule>
      
      <!-- build frame elements for display/update/set/prompt-for/assign and
           enable/disable -->
      <rule>type == prog.frame_element
      
         <action>feref = closestPeerId</action>
      
         <!-- some forms of assign stmts (with a var or field that is NOT a
              child of an ASSIGN operator) use a special assignment -->
         <rule>
            (parent.type == prog.kw_assign and 
             parent.parent.type == prog.statement) or
            upPath("STATEMENT/KW_ASSIGN/KW_IF/KW_THEN/BLOCK/")
      
            <action>
               feref = createJavaAst(java.method_call,
                                     "assignScreenValue",
                                     feref)
            </action>
            <action>
               frname = #(java.lang.String) execLib("get_framename", this)
            </action>
            <action>createJavaAst(java.reference, frname, feref)</action>
         </rule>
         
         <!-- determine the frame element type -->
         <rule>numImmediateChildren == 1
         
            <!-- widget references (versus normal data representation 
                 elements) have only a single child node -->
            <action>cls = "WidgetElement"</action>
            
            <!-- form headers -->
            <rule on="false">
               isNote("form_header") and getNoteBoolean("form_header")
               
               <action>cls = "HeaderElement"</action>
               
               <!-- widgets in the text clause need word wrap -->
               <rule on="false">
                  isNote("word_wrap") and getNoteBoolean("word_wrap")
                  
                  <action>cls = "WordWrapElement"</action>
                  
                  <!-- aggregate phrases -->
                  <rule on="false">descendant(prog.aggregate, 1)
                  
                     <action>cls = "AggregatorElement"</action>
                  
                     <!-- common case -->
                     <action on="false">cls = "Element"</action>
                  </rule>
                  
               </rule>
            </rule>
         </rule>
         
         <!-- create the element -->
         <action>
            createPeerAst(java.constructor, cls, feref)
         </action>
      
      </rule>
      
      <!-- emit the reference to the Accumulator instance -->
      <rule>type == prog.aggregate and parent.type == prog.frame_element
         <action>
            javaname = #(java.lang.String) execLib("get_javaname", this)
         </action>
         <action>
            createJavaAst(java.reference, javaname, closestPeerId)
         </action>
      </rule>
      
      <!-- handle references need special call -->
      <rule>evalLib("apply_to_handle", this)
         <action>importLT = true</action>
         <action>
            createPeerAst(java.static_method_call, "apply", closestPeerId)
         </action>
      </rule>
      
      <!-- build embeddable assignments for update/set -->
      <rule>type == prog.embedded_assignment

         <!-- create the element -->
         <action>
            createPeerAst(java.constructor,
                          "EmbeddedAssignment",
                          closestPeerId)
         </action>
      
      </rule>
      
      <!-- build bypass elements for update/set/prompt-for (prompt-for is
           undocumented but does work in the 4GL) -->
      <rule>type == prog.caret and parent.type == prog.content_array

         <!-- create the element -->
         <action>
            createPeerAst(java.constructor, "BypassElement", closestPeerId)
         </action>
      
      </rule>
      
      <!-- emit a boolean and a variable reference (if needed) for a set
           or update in a message statement -->
      <rule>
         (type == prog.kw_set or type == prog.kw_update) and
         parent.type == prog.kw_msg
      
         <!-- calc the peer id if this was a var definition -->
         <rule>isNote("vardef") and getNoteBoolean("vardef")
            <action>
               parentid = #(long) copy.parent.getAnnotation("peerid")
            </action>
            <action on="false">parentid = closestPeerId</action>
         </rule>
      
         <!-- emit the boolean -->
         <rule>type == prog.kw_set
            <action>createJavaAst(java.bool_true, "", parentid)</action>
            <action on="false">
               createJavaAst(java.bool_false, "", parentid) 
            </action>
         </rule>
      
         <!-- emit the var reference if this was a var definition -->
         <rule>isNote("vardef") and getNoteBoolean("vardef")
            <!-- create the wrapper constructor -->
            <action>
               varid = createJavaAst(java.constructor,
                                     "AccessorWrapper",
                                     parentid)
            </action>
            <action>
               createJavaAst(java.reference,
                             getNoteString("javaname"),
                             varid) 
            </action>
         </rule>
         
         <!-- convert variables into Accessor instances to emit -->
         <action>varref = copy.getChildAt(0)</action>
         <rule>evalLib("vartype", varref.type)
            <!-- create the wrapper constructor -->
            <action>
               varid = createJavaAst(java.constructor,
                                     "AccessorWrapper",
                                     closestPeerId)
            </action>
            <!-- temporary peerid put into the variable reference -->
            <action>varref.putAnnotation("peerid", varid)</action>
         </rule>
      </rule>
      
      <!-- emit other parms for set or update in a message (the string child
           of kw_format will emit naturally) -->
      <rule>
         (parent.type == prog.kw_set or parent.type == prog.kw_update) and
         parent.parent.type == prog.kw_msg
         
         <!-- emit the auto-return boolean if it exists AND handle the
              case for a missing format string (note that if auto-return
              doesn't exist AND there is no format string, that case is
              handled in ascent-rules) -->
         <rule>type == prog.kw_auto_ret
         
            <!-- calc the peer id if this was a var definition -->
            <rule>
               copy.parent.isAnnotation("vardef") and
               #(java.lang.Boolean) copy.parent.getAnnotation("vardef")
               <action>
                  parentid = #(long) 
                             copy.parent.parent.getAnnotation("peerid")
               </action>
               <action on="false">parentid = closestPeerId</action>
            </rule>
         
            <!-- emit the auto-return flag -->
            <action>createJavaAst(java.bool_true, "", parentid)</action>
            
            <!-- if there is no explicit format string but there is one
                 explicitly defined for the variable OR field, honor it
                 (the output must be emitted after the auto-return
                 flag) -->
            <rule>!parent.descendant(1, prog.kw_format)
                
               <!-- find the variable or field ref -->
               <action>lvalref = copy.parent.getChildAt(0)</action>
               
               <rule>evalLib("vartype", lvalref.type)
                  <action>
                     fmtstr = execLib("get_format_varname", lvalref)
                  </action>
                  <action>toktype = java.reference</action>
               </rule>
               
               <rule>evalLib("fieldtype", lvalref.type)
                  <action>fmtstr = execLib("get_format_field", lvalref)</action>
                  <action>toktype = java.string</action>
               </rule>
                  
               <rule>fmtstr != null
                  <!-- we have a string constant member -->
                  <action>
                     createJavaAst(toktype, fmtstr, parentid)
                  </action>
               </rule>
            </rule>
         </rule>
         
         <!-- format string processing -->
         <rule>
            type == prog.kw_format and
            parent.isAnnotation("vardef") and
            #(java.lang.Boolean) parent.getAnnotation("vardef")
            
            <!-- calculate the location to emit into the message() call -->
            <action>
               parentid = #(long) copy.parent.parent.getAnnotation("peerid")
            </action>
            
            <action>fmtstr = null</action>
            
            <!-- new constant must emit as a constant reference here and as
                 a new constant definition in variable_definitions.rules 
                 (make sure we don't override the peerid here) -->
            <rule>
               isNote("define_constant") and
               getNoteBoolean("define_constant")
            
               <!-- lookup the name -->
               <action>fmtstr = getNoteString("define_constant")</action>
               
               <!-- this may still be a reference to a format constant -->
               <rule on="false">copy.parent.isAnnotation("format_constant")
               
                  <!-- lookup the name -->
                  <action>
                     fmtstr = copy.parent.getAnnotation("format_constant")
                  </action>
                  
                  <!-- OK, this is a hard coded format string that is not
                       a duplicate of a constant, set the peer id so that the
                       format string emits directly into the proper message()
                       location -->
                  <action on="false">putNote("peerid", parentid)</action>
                  
               </rule>
            </rule>
            
            <!-- emit the named constant ref if needed -->
            <rule>fmtstr != null
               <action>
                  createJavaAst(java.reference, fmtstr, parentid)
               </action>
            </rule>
         </rule>
      </rule>
      
      <!-- message stmt view-as support (more defaults are handled in
           next-child and ascent rules below) -->
      <rule>
         type == prog.kw_view_as and
         parent.type == prog.kw_msg
         
         <!-- create a default alert-box type if not specified or if the
              specification is "message" -->
         <rule> 
            !descendant(prog.kw_quest, 1) and
            !descendant(prog.kw_info, 1) and
            !descendant(prog.kw_error, 1) and
            !descendant(prog.kw_warn, 1)
            
            <action>txt = "ALERT_MESSAGE"</action>
            <action>importLT = true</action>
            <action>createJavaAst(java.reference, txt, closestPeerId)</action>
         </rule>
         
      </rule>
      
      <!-- create an alert-box type for non-default choices -->
      <rule>
         parent.type == prog.kw_view_as and
         parent.parent.type == prog.kw_msg
         
         <action>txt = null</action>
         
         <rule>type == prog.kw_quest
            <action>txt = "ALERT_QUESTION"</action>
         </rule>
      
         <rule>type == prog.kw_info
            <action>txt = "ALERT_INFO"</action>
         </rule>
         
         <rule>type == prog.kw_error
            <action>txt = "ALERT_ERROR"</action>
         </rule>
         
         <rule>type == prog.kw_warn
            <action>txt = "ALERT_WARNING"</action>
         </rule>
         
         <rule>txt != null
            <action>importLT = true</action>
            <action>createJavaAst(java.reference, txt, closestPeerId)</action>
         </rule>
      </rule>
      
      <!-- emit button set type -->
      <rule>
         parent.type == prog.kw_button and
         parent.parent.type == prog.kw_view_as
         
         <action>txt = null</action>
         
         <rule>type == prog.kw_yes_no
            <action>txt = "BTN_YES_NO"</action>
         </rule>
      
         <rule>type == prog.kw_yes_no_c
            <action>txt = "BTN_YES_NO_CANCEL"</action>
         </rule>
         
         <rule>type == prog.kw_ok
            <action>txt = "BTN_OK"</action>
         </rule>
         
         <rule>type == prog.kw_ok_can
            <action>txt = "BTN_OK_CANCEL"</action>
         </rule>
         
         <rule>type == prog.kw_retry_c
            <action>txt = "BTN_RETRY_CANCEL"</action>
         </rule>
         
         <rule>txt != null
            <action>importLT = true</action>
            <action>createJavaAst(java.reference, txt, closestPeerId)</action>
         </rule>         
      </rule>
      
      <!-- color stmt 1st parm -->
      <rule>type == prog.kw_color and parent.type == prog.statement
      
         <action>ref = this.getChildAt(0)</action>
      
         <!-- detect if there is no display spec (or just the display keyword
              and no following spec), emit null -->
         <rule>
            ref.type == prog.kw_prompt or
            (ref.type == prog.kw_disp and ref.numImmediateChildren == 0)
            <action>
               createJavaAst(java.null_literal, "", closestPeerId)
            </action>
         </rule>
      
      </rule>
      
      <!-- color phrase processing -->
      <rule>type == prog.color_phrase
         <action>
            createPeerAst(java.constructor, "ColorSpec", closestPeerId)
         </action>
      </rule>
      <rule>type == prog.kw_normal and parent.type == prog.color_phrase
         <action>
            createPeerAst(java.reference,
                          "ColorSpec.COLOR_NORMAL",
                          closestPeerId)
         </action>
      </rule>
      <rule>type == prog.kw_input and parent.type == prog.color_phrase
         <action>
            createPeerAst(java.reference,
                          "ColorSpec.COLOR_INPUT",
                          closestPeerId)
         </action>
      </rule>
      <rule>type == prog.kw_messages and parent.type == prog.color_phrase
         <action>
            createPeerAst(java.reference,
                          "ColorSpec.COLOR_MESSAGES",
                          closestPeerId)
         </action>
      </rule>
      <rule>type == prog.symbol and parent.type == prog.color_phrase
         <action>txt = removeQuotes(text)</action>
         <action>txt = ecw.progressToJavaString(sprintf('"%s"', txt))</action>
         <action>createPeerAst(java.string, txt, closestPeerId)</action>
      </rule>
      
      <!-- dynamic/runtime expression support for frame phrase constructs -->
      <rule>parent.type == prog.runtime_frame_options or
            upPath("RUNTIME_FRAME_OPTIONS/KW_COLOR"))

         <action>txt = null</action>
         <action>parentid = closestPeerId</action>
         <action>idx = -1</action>
         <action>frameOpt = parent</action>

         <rule>type == prog.kw_col
            <action>txt = "setColumn"</action>
         </rule>
         
         <rule>type == prog.kw_down
            <action>txt = "setDown"</action>
         </rule>
         
         <rule>type == prog.kw_row
            <action>txt = "setRow"</action>
         </rule>
         
         <rule>type == prog.kw_title
            <action>txt = "setDynamicTitle"</action>
         </rule>
         
         <!-- some (most) runtime options need to be registered just after
              the open scope call, no matter where the original frame phrase
              actually was specified -->
         <rule>
            type == prog.kw_col    or
            type == prog.kw_down   or
            type == prog.kw_row   or
            type == prog.kw_title
            
            <!-- try to find the location of the open scope call, insert 
                 our set call there (just after the open scope) -->
            <action>
               osref = getAst(#(java.lang.Long)
                              parent.getAnnotation("frame-id"))
            </action>
            <action>
               osref = getAst(#(java.lang.Long)
                              osref.getAnnotation("scope_peer"))
            </action>
            <!-- it is possible that this reference appears before the scope
                 opens, if so we bypass this code and emit in place
                 (closestPeerId) -->
            <rule>osref != null
               <!-- override the location to be just after the open scope -->
               <action>parentid = osref.parent.id</action>
               <action>idx = osref.indexPos + 1</action>
            </rule>
         </rule>
         
         <rule>type == prog.kw_color
            <action>txt = "setDColor"</action>
            <action>this.putAnnotation("color-peerid", parentid)</action>
         </rule>
         
         <!-- handle KW_COLOR/KW_PROMPT -->
         <rule>type == prog.kw_prompt
            <action>frameOpt = parent.parent</action>
            <action>parentid = parent.getAnnotation("color-peerid")</action>
            <action>txt = "setPfColor"</action>
         </rule>

         <rule>txt != null
            <action>
               lastid = createPeerAst(java.method_call, txt, parentid, idx)
            </action>
            <action>
               createJavaAst(java.reference, 
                             #(java.lang.String)
                             execLib("get_framename", frameOpt),
                             lastid)
            </action>
         </rule>

         <!-- the error is not expected when handling KW_COLOR/KW_PROMPT -->
         <rule>txt == null and parent.type == prog.runtime_frame_options
            <action>
               errmsg = sprintf("Unrecognized runtime UI option for %s.",
                                this.getSymbolicTokenType())
            </action>
            <action>throwException(errmsg)</action>
         </rule>
         
      </rule>
      
      <!-- hide/clear always needs a single parameter for no-pause (defaults
           to false), in the hide case only emit the parm if there are no
           children (otherwise we wait for the ascent rule since any stream
           parm must emit first) -->
      <rule>
         (type == prog.kw_clear or
          (type == prog.kw_hide and numImmediateChildren == 0)) and
         parent.type == prog.statement                          and
         methodText != null
         <action>ttype = java.bool_false</action>
         <rule>descendant(prog.kw_no_pause, 1)
            <action>ttype = java.bool_true</action>
         </rule>
         <action>createJavaAst(ttype, "", closestPeerId)</action>
      </rule>
   
      <!--enable/disable form of put cursor (only parameter) -->
      <rule>
         type == prog.kw_off and
         parent.type == prog.put_cursor
         
         <action>createPeerAst(java.bool_false, "", closestPeerId)</action>
      </rule>   
      
      <!-- some lang stmts need a FrameElement reference as the first parm
           (this is created above but needs to be emitted here) -->
      <rule>
         (type == prog.kw_disp      or
          type == prog.kw_update    or
          type == prog.kw_set       or
          type == prog.kw_prmt_for  or
          type == prog.kw_enable    or
          type == prog.kw_disable   or
          ((type == prog.kw_view or type == prog.kw_hide) and 
           isNote("frame-id") and !isNote("single-element"))  or
          (type == prog.kw_form and descendant(prog.kw_header, 1)))    and
         parent.type == prog.statement and
         !descendant(prog.editing_block, 1) and
         methodText != null

         <rule>descendant(prog.kw_stream, 1)
         
            <!-- defer emit of this reference, save the attach point -->
            <action>streamid = closestPeerId</action>
         
            <!-- no reason to wait, emit now (will be the first parm) -->
            <action>fename = lookupDictionaryObject("frame_element_name", "fename")</action>
            <rule on="false">fename != null
               <action>createJavaAst(java.reference, fename, closestPeerId)</action>
            </rule>
         </rule>
      </rule>
      
      <!-- stream case must emit the FrameElement reference as the second
           parm -->
      <rule>
         (parent.type == prog.kw_disp   or
          parent.type == prog.kw_update or
          parent.type == prog.kw_set    or
          parent.type == prog.kw_prmt_for)    and
         parent.parent.type == prog.statement and
         !parent.descendant(1, prog.editing_block)
         
         <!-- since the input_output.rules is run first, this should 
              always follow the stream reference -->
         <action>fename = lookupDictionaryObject("frame_element_name", "fename")</action>
         <rule>type == prog.kw_stream and fename != null         
            <action>createJavaAst(java.reference, fename, streamid)</action>
         </rule>
      </rule>      

      <!-- wait-for is a static method that always needs a frame reference
           as the first parm -->
      <rule>type == prog.kw_wait_for and parent.type == prog.statement
         
         <rule>isNote("frame-id")
         
            <!-- emit the referenced frame -->
            <action>
               refName = #(java.lang.String) execLib("get_framename", this)
            </action>
            <action>
               createJavaAst(java.reference, refName, closestPeerId)
            </action>
            
            <!-- use the current frame -->
            <action on="false">
               createJavaAst(java.null_literal, "", closestPeerId)
            </action>
         </rule>
         
      </rule>
      
      <!-- some lang stmts need a EventList reference as a parm (this
           is created above but needs to be emitted here) -->
      <rule>
         (type == prog.kw_wait_for                                  or
          (type == prog.kw_on and needswait != null and needswait)) and
         parent.type == prog.statement
         
         <rule>multiMode
            <action>
               createJavaAst(java.reference, listname, closestPeerId)
            </action>
            <!-- when there is only 1 OF clause, it is emitted inline -->
            <action on="false">waitref = copy.getImmediateChild(prog.kw_of, null)</action>
            <action on="false">execLib("gen_single_event_list", "EventList", waitref)</action>
            
         </rule>
      </rule>
      
      <!-- GO-ON for PROMPT-FOR/SET/UPDATE (not EDITING) creates an EventList instance as a
           parm -->
      <rule>
         ((type == prog.kw_update or
            type == prog.kw_set    or
            type == prog.kw_prmt_for)   and
           descendant(prog.kw_go_on, 1) and
           descendant(prog.editing_block, 1) == false) and
         parent.type == prog.statement
         
         <!-- non-EDITING block case is done inline -->
         <action>waitref = copy.getImmediateChild(prog.kw_go_on, null)</action>
         <action>execLib("gen_single_event_list", "GoOn", waitref)</action>
      </rule>
      
      <!-- 3rd parm to a WAIT-FOR is the focus widget; when this is specified as a handle
           then we need to unwrap it and pass it as a GenericWidget;
           TODO: should we handle frame instances as CommonFrame? -->
      <rule>type == prog.kw_focus and parent.type == prog.kw_wait_for
         <variable name="focchld" type="com.goldencode.ast.Aast" />
         <action>focchld = copy.getFirstChild()</action>
         <rule>focchld != null and evalLib("handle_type", focchld.type)
            <action>castid = createJavaAst(java.cast, "GenericWidget", closestPeerId)</action>
            <action>createPeerAst(java.method_call, "unwrapWidget", castid)</action>
         </rule>
      </rule>
      
      <!-- emit the procedure's name, for ON ... PERSISTENT RUN case -->
      <rule>type == prog.kw_on and downPath("KW_PERSIST/KW_RUN")
         <action>legacyname = null</action>
         <action>
            childref = copy.getImmediateChild(prog.kw_persist,null)
                           .getFirstChild()
                           .getFirstChild()
         </action>
         <rule>childref.type == prog.filename or childref.type == prog.library_ref
            <action>legacyname = childref.text</action>
         </rule>
         <rule>childref.type == prog.int_proc
            <action>legacyname = childref.text</action>
         </rule>
         <rule>legacyname != null
            <action>
               createJavaAst(java.string, legacyname, closestPeerId)
            </action>
         </rule>
      </rule>

      <!-- choose stmt needs a Choose reference as the first parm (this
           is created above but needs to be emitted here) -->
      <rule>type == prog.kw_choose and parent.type == prog.statement
         <action>
            createJavaAst(java.reference, choosename, nonpeerid)
         </action>
      </rule>
      
      <!-- emit the method call to add the event/widgets to the EventList -->
      <rule>type == prog.kw_of and descendant(prog.event_list, 1)
         <!-- single OF mode emits without this method call -->
         <rule>multiMode
            <action>
               lastid = createPeerAst(java.method_call, "addEvent", waitloc, waitidx)
            </action>
            <action>waitidx = waitidx + 1</action>
            <action>createJavaAst(java.reference, listname, lastid)</action>
         </rule>
      </rule>
               
      <!-- emit object array for event lists and widget lists that have multiple children -->
      <rule>
         (type == prog.event_list or type == prog.widget_list) and
         numImmediateChildren > 1
         
         <rule>type == prog.event_list
            <action>raytype = "String"</action>

            <!-- mixed cases -->
            <rule on="false">true
               <variable name="htarget"  type="java.lang.Boolean"/>
               <variable name="wtarget"  type="java.lang.Boolean"/>
               <variable name="onRef"    type="com.goldencode.ast.Aast"/>
               <variable name="oldtype" type="java.lang.Long" />

               <action>htarget = false</action>
               <action>wtarget = false</action>

               <action>onRef = this.getChildAt(0)</action>
               <while>onRef != null and !(htarget and wtarget)

                  <!-- check if this is a widget -->                  
                  <rule>
                     onRef.isAnnotation("frame-id") or
                     (onRef.type &gt;= prog.begin_widgets and 
                      onRef.type &lt;= prog.end_widgets)

                     <action>wtarget = true</action>

                     <!-- must be a handle - check if is a system widget handle -->
                     <rule on="false">onRef.type == prog.sys_handle
                        <action>oldtype = #(java.lang.Long) onRef.getAnnotation("oldtype")</action>
                        
                        <!-- check for handles which always refer to a widget -->
                        <rule>oldtype == prog.kw_focus    or
                              oldtype == prog.kw_cur_win  or
                              oldtype == prog.kw_def_win  or
                              oldtype == prog.kw_act_win
                           <action>wtarget = true</action>
   
                           <!-- all other cases are assumed always handle -->
                           <action on="false">htarget = true</action>
                        </rule>
 
                        <!-- menu widgets are assumed as widgets --> 
                        <rule on="false">onRef.type == prog.kw_menu_itm or
                                         onRef.type == prog.kw_sub_menu or
                                         onRef.type == prog.kw_menu
                           <action>wtarget = true</action>
                           <!-- everything else is assumed as handle -->
                           <action on="false">htarget = true</action>
                        </rule> 
                     </rule>
                  </rule>

                  <rule>onRef = onRef.getNextSibling()</rule>
               </while>

               <action>raytype = "Object"</action>
               <rule>htarget and !wtarget
                  <!-- only handles -->
                  <action>raytype = "handle"</action>

                  <!-- only widgets -->
                  <rule on="false">!htarget and wtarget
                     <action>raytype = "GenericWidget"</action>
                  </rule>  
               </rule>
            </rule>
         </rule>
         
         <!-- emit the string/object array initializer node -->
         <action>
            tw.graft("anon_array", copy, closestPeerId,
                     "classname", raytype,
                     "extent", string(numImmediateChildren))
         </action>      
      </rule>
            
      <!-- emit method call and string array parm for go-on event lists -->
      <rule>type == prog.kw_go_on
         
         <rule>parent.type != prog.kw_choose
            <rule>multiMode
               <action>loc = waitloc</action>
               <action>idx = waitidx</action>
               <action>cname = listname</action>
            </rule>
            <action on="false">loc = chooseloc</action>
            <action on="false">idx = chooseidx</action>
            <action on="false">cname = choosename</action>
         </rule>
         
         <rule>multiMode or parent.type == prog.kw_choose
            <action>lastid = createPeerAst(java.method_call, "addGoOn", loc, idx)</action>
            <action>createJavaAst(java.reference, cname, lastid)</action>
            <action on="false">lastid = closestPeerId</action>
         </rule>
         
         <!-- emit the string/object array initializer node if needed -->
         <rule>numImmediateChildren > 1
            <action>
               tw.graft("anon_array", copy, lastid,
                        "classname", "String",
                        "extent", string(numImmediateChildren))
            </action>      
         </rule>
         
      </rule>
      
      <!-- choose statement options -->
      <rule>
         parent.type == prog.kw_choose          and
         parent.parent.type == prog.statement
         
         <action>txt = null</action>
         
         <rule>type == prog.kw_row
            <action>txt = "addRow"</action>
         </rule>
      
         <rule>type == prog.kw_field
            <action>this.setHidden(true)</action>
            <action>fldref = this.getFirstChild()</action>
            <while>fldref != null
               <rule>fldref.type != prog.kw_help
                  <action>
                     lastid = createJavaAst(java.method_call,
                                            "addField",
                                            chooseloc, chooseidx)
                  </action>
                  <action>
                     chooseidx = chooseidx + 1
                  </action>
                  <action>
                     createJavaAst(java.reference, choosename, lastid)
                  </action>
                  <action>
                     frmid = createJavaAst(java.method_call,
                                   #(java.lang.String) 
                                   fldref.getAnnotation('accessor'), lastid)
                  </action>
                  <action>
                     createJavaAst(java.reference,
                                            #(java.lang.String)
                                            execLib("get_framename", fldref),
                                            frmid)
                  </action>

                  <action>hlpref = fldref.getFirstChild()</action>
                  
                  <rule>hlpref != null
                     <action>hlpref.setHidden(true)</action>
                  </rule>
               </rule>
               
               <rule>fldref.type == prog.kw_help
                  <action>hlpref = fldref.getFirstChild()</action> 
                  <action>hlpref.setHidden(true)</action>
                  <action>
                     createJavaAst(java.string, 
                                   progressToJavaString(hlpref.text), lastid)
                  </action>
               </rule>
               
               <action>fldref.setHidden(true)</action>
               <action>fldref = fldref.getNextSibling()</action>
            </while>
         </rule>
         
         <rule>type == prog.kw_no_error
            <action>txt = "setNoError"</action>
         </rule>
         
         <rule>type == prog.kw_pause
            <action>txt = "setPause"</action>
         </rule>
         
         <rule>type == prog.kw_color
            <action>txt = "setColor"</action>
         </rule>
         
         <rule>type == prog.kw_keys
            <action>txt = "setKeys"</action>
         </rule>
         
         <rule>type == prog.kw_auto_ret
            <action>txt = "setAutoReturn"</action>
         </rule>
         
         <rule>txt != null
            <action>
               lastid = createPeerAst(java.method_call, txt, chooseloc, chooseidx)
            </action>
            <action>
               createJavaAst(java.reference, choosename, lastid)
            </action>
         </rule>
      </rule>
            
      <!-- emit key label or key function for key remapping -->
      <rule>type == prog.event or type == prog.key_function
         <action>createPeerAst(java.string, text, closestPeerId)</action>
      </rule>
         
      <!-- emit skip for message stmts -->
      <rule>type == prog.kw_skip and parent.type == prog.content_array
         <action>
            lastid = createPeerAst(java.constructor, "SkipEntity", closestPeerId)
         </action>
         <!-- if no number was specified, then we must force this into SKIP mode instead of
              the default which is SPACE mode -->
         <rule>numImmediateChildren == 0
            <action>createJavaAst(java.bool_true, "", lastid)</action>
         </rule>
      </rule>
      
      <!-- trigger blocks -->
      <rule>type == prog.trigger_block
         <action>fullTrans = false</action>
      
         <!-- detect if this block has transaction properties -->
         <rule>!isNote("database_trigger") or !getNoteBoolean("database_trigger")
            <action>blockRef = copy.getImmediateChild(prog.block, null)</action>
            
            <!-- only emit the transaction type when it is different
                 from the default (which is sub-trans) -->
            <rule>
               blockRef != null and
               #(java.lang.Long) blockRef.getAnnotation("transLevel") == prog.transaction
               
               <action>fullTrans = true</action>
            </rule>
            
         </rule>

         <!-- session triggers only -->
         <rule>getNoteBoolean("database_trigger")
            <action>
               dbEventType = parent.getImmediateChild(prog.db_event, null).getChildAt(0).type
            </action>

            <!-- emit database event type parameter -->
            <action>txt = execLib("get_db_event_type", parent)</action>
            <action>createJavaAst(java.reference, txt, closestPeerId)</action>

            <!-- emit bufClass for first found buffer -->
            <action>ref = execLib("get_first_db_trigger_buffer", copy.parent)</action>
            <action>
               createJavaAst(java.reference,
                             sprintf("%s.class",
                                     #(java.lang.String) ref.getAnnotation("bufclassname")),
                             closestPeerId)
            </action>

            <!-- for ASSIGN triggers the property name is needed -->
            <rule>dbEventType == prog.kw_assign
               <action>ref = execLib("get_field_immediate_child", copy.parent, null)</action>
               <action>
                  createJavaAst(java.string,
                                #(java.lang.String) ref.getAnnotation("fieldname"),
                                closestPeerId)
               </action>
            </rule>
         </rule>
         
         <action>trigCls = getNoteString("classname")</action>
         
         <!-- inner class mode requires the class name to be emitted into the registration -->
         <rule>trigCls != null
            <!-- emit a reference to the trigger's class into the parent's registration call -->
            <action>
               createJavaAst(java.reference, sprintf("%s.class", trigCls), closestPeerId)
            </action>
         </rule>
         
         <!-- emit a reference to the trigger's containing class into the
              parent's registration call -->
         <action>createJavaAst(java.reference, baseClass, closestPeerId)</action>
         
         <!-- optionally emit the 4th parameter to set the transaction level -->
         <rule>fullTrans and (!isNote("database_trigger") or !getNoteBoolean("database_trigger"))
            <action>createJavaAst(java.bool_true, "", closestPeerId)</action>
         </rule>

         <!-- session triggers only -->
         <rule>getNoteBoolean("database_trigger")
            <!-- optionally emit "override" boolean parameter -->
            <rule>parent.descendant(1, prog.kw_override)
               <action>createJavaAst(java.bool_true, "", closestPeerId)</action>

               <rule on="false">parent.descendant(1, prog.kw_old)
                  <action>createJavaAst(java.bool_false, "", closestPeerId)</action>
               </rule>
            </rule>

            <!-- optionally emit "hasOldBuffer" boolean parameter -->
            <rule>parent.descendant(1, prog.kw_old)
               <action>createJavaAst(java.bool_true, "", closestPeerId)</action>
            </rule>
         </rule>
         
         <!-- create the inner class definition as the peer for this node
              (so all contents emit naturally) -->
         <rule>getNoteBoolean("database_trigger")
            <action>
               dbEventType = parent.getImmediateChild(prog.db_event, null).getChildAt(0).type
            </action>

            <action>ref = execLib("get_first_db_trigger_buffer", parent)</action>

            <action>
               ref = tw.graft("database_trigger_inner_class_def", copy,
                              getSectionAnchor(java.cs_inner_classes),
                              "classname", getNoteString("classname"),
                              "bufclass",  #(java.lang.String) ref.getAnnotation("bufclassname"),
                              "funcname",  getNoteString("funcname"))
            </action>

            <!-- link the assigning of local-parameter to container variable -->
            <action>tw.attach(ref, tw.removeFromDepot("trigassign"))</action>

            <!-- emit input buffer parameters at LPARENS of write/create/delete/find/assign method -->
            <action>ref2 = ref.getAncestor(6).getChildAt(0)</action>
            <action>tw.attach(ref2, tw.removeFromDepot("trigparm").getChildAt(0))</action>

            <!-- check if there is a old value for assign field -->
            <rule>dbEventType == prog.kw_assign and parent.descendant(1, prog.kw_old)
               <action>ref3 = copy.parent.getImmediateChild(prog.kw_old, null)</action>

               <action>
                  refid0 = createJavaAst(java.reference_def, "BaseDataType", ref2.id)
                  <!-- alternately we could write as below but we weren't overriding of base class
                     refid0 = createJavaAst(java.reference_def,
                                 #(java.lang.String) ref3.getAnnotation("classname"),
                                 ref2.id)-->
               </action>
               <action>ref2 = getAst(refid0)</action>
               <action>ref2.putAnnotation("final", true)</action>
               <action>
                  ref2.putAnnotation("name", #(java.lang.String) ref3.getAnnotation("param_name"))
               </action>

               <!-- emit the register undo if needed -->
               <rule>tw.isInDepot("trig_init")
                  <!-- 'init' is the 1st sibling of 'body' (which is 2nd) (so 2 up/2 down) -->
                  <action>ref2 = ref.getAncestor(2).getChildAt(0).getChildAt(0)</action>

                  <action>tw.attach(ref2, tw.removeFromDepot("trig_init").getChildAt(0))</action>
               </rule>

            </rule>

            <!-- all other UI triggers -->
            <rule on="false">trigCls == null
            
               <rule>isNote("singleton") and getNoteBoolean("singleton")
                  <!-- singleton mode -->
                  <action>
                     ref = tw.graft("block_lambda_def", copy, closestPeerId, "parent", "Trigger")
                  </action>
                  
                  <!-- trigger_block try block 1 -->
                  <action>tryid = execLib("insert_try_block_if_needed", ref.id)</action>
                  <rule>tryid != ref.id
                     <action>ref = getAst(tryid)</action>
                  </rule>
                  
                  <action>execLib("save_control_point_ids", ref, instvarid, true)</action>
                  
                  <!-- lambda plus anon-class mode -->
                  <action on="false">getAst(instvarid).remove()</action>
                  <action on="false">getAst(skipid).remove()</action>
                  <action on="false">
                     ref = tw.graft("trigger_anon_class_def", copy, closestPeerId)
                  </action>
                  
                  <!-- trigger_block try block 2 -->
                  <action on="false">tryid = execLib("insert_try_block_if_needed", ref.id)</action>
                  <rule on="false">tryid != ref.id
                     <action>ref = getAst(tryid)</action>
                  </rule>
                  
               </rule>
               
               <!-- inner class mode -->
               <action on="false">getAst(instvarid).remove()</action>
               <action on="false">getAst(skipid).remove()</action>
               <action on="false">
                  ref = tw.graft("trigger_inner_class_def",
                                 copy,
                                 getSectionAnchor(java.cs_inner_classes),
                                 "classname",
                                 trigCls)
               </action>
               <!-- trigger_block try block 3 -->
               <action on="false">tryid = execLib("insert_try_block_if_needed", ref.id)</action>
               <rule on="false">tryid != ref.id
                  <action>ref = getAst(tryid)</action>
               </rule>
               
            </rule>
         </rule>
         
         <!-- for inner class mode, we calculate and save the preid and controlid in
              control_flow.rules -->
      </rule>

      <!-- emit parameters for deregisterDatabaseTrigger -->
      <rule>type == prog.kw_on and descendant(prog.db_event, 1) and descendant(prog.kw_revert, 1)

         <!-- emit database event type parameter -->
         <action>txt = execLib("get_db_event_type", this)</action>
         <action>createJavaAst(java.reference, txt, closestPeerId)</action>

         <!-- emit buffer class parameter -->
         <action>ref = this.getImmediateChild(prog.symbol, null)</action>

         <action>
            createJavaAst(java.reference,
                          sprintf("%s.class",
                                  #(java.lang.String) ref.getAnnotation("bufclassname")),
                          closestPeerId)
         </action>

         <action>
            createImport(sprintf("%s.*", #(java.lang.String) ref.getAnnotation("pkgname")))
         </action>
      </rule>

      <!-- editing blocks -->
      <rule>type == prog.editing_block
      
         <!-- get the java label -->
         <action>
            java_label = #(java.lang.String) execLib("get_current_block_label")
         </action>
      
         <!-- get the frame name -->
         <action>refName = #(java.lang.String) execLib("get_framename", parent)</action>
         
         <!-- calculate the optype parm -->
         <rule>parent.type == prog.kw_prmt_for
            <action>optype = "promptForEditing"</action>
            <rule on="false">parent.type == prog.kw_set
               <action>optype = "setEditing"</action>
               <action on="false">optype = "updateEditing"</action>
            </rule>
         </rule>
         
         <!-- adding UNLESS-HIDDEN option handling -->
         <rule>parent.downPath("KW_UNL_HID")
            <action>optype = optype.concat("UnlessHidden")</action>
         </rule>
      
         <!-- insert a blank line for readability (duplicates will be
              removed downstream) -->
         <action>ref = getAst(closestPeerId)</action>
         <action>parentIdx = ref.numImmediateChildren - 1</action>
         <action>createJavaAst(java.skip, "", closestPeerId)</action> 
         
         <!-- save this off for downstream (ascent rules) -->
         <action>putNote("block_par_id", closestPeerId)</action>
         
         <!-- create the container for instance variables -->
         <action>instvarid = createJavaAst(java.bogus, "", closestPeerId)</action> 
         <action>createJavaAst(java.skip, "", closestPeerId)</action> 
         
         <!-- emit the static method call to the BlockManager -->
         <action>
            blockId = createJavaAst(java.static_method_call, optype, closestPeerId)
         </action>
      
         <!-- 1st parameter is the frame reference -->
         <action>createJavaAst(java.reference, refName, blockId)</action>
         
         <!-- 2nd parameter is the widget list -->
         <action>fename = lookupDictionaryObject("frame_element_name", "fename")</action>
         <action>createJavaAst(java.reference, fename, blockId)</action>
         
         <!-- 3rd parameter is an optional GO-ON (the EventList was already emitted
              separately -->
         <rule>parent.descendant(1, prog.kw_go_on)
            <action>createJavaAst(java.reference, listname, blockId)</action>
         </rule>
         
         <!-- 4th parameter is the optional enclosing array of unmanaged
              block labels -->
         <rule>isNote("enclosing")
            <action>jname = sprintf("enclBlk%d", ennum)</action>
            <action>ennum = ennum + 1</action>
            <action>
               execLib("emitLabels", closestPeerId, parentIdx, blockId, copy, jname)
            </action>
         </rule>
         
         <!-- 5th parameter is the label -->
         <action>createJavaAst(java.string, java_label, blockId)</action>
         
         <!-- emit the LAST parameter -->
         <rule>lambdaBlock
            <!-- lambda version -->
            <action>
               editref = tw.graft("block_lambda_def", copy, blockId, "parent", "Block")
            </action>
            <!-- inner class version -->
            <action on="false">
               editref = tw.graft("block_inner_class_def", copy, blockId)
            </action>
         </rule>
         
         <!-- editing_block which CAN'T HAVE CATCH BLOCKS in 4GL; we deliberately do NOT call
              insert_try_block_if_needed; -->
         
         <action>execLib("save_control_point_ids", editref, instvarid, lambdaBlock)</action>
      </rule>
      
      <!-- process explicit field/variable validation expressions and static help attributes -->
      <rule>(type == prog.kw_validate or type == prog.kw_help) and 
            parent.type == prog.validation 
         
         <!-- register the validator instance (the widget will emit naturally)
              all the setValidatable calls will emit at the beginning of the
              body() method for the external procedure, internal entry or trigger -->
         <action>
            ref = execLib("getTopLevelInternalNodeAncestor")
         </action> 
         
         <rule>ref == null
            <action>ref = copy.getAncestor(-1)</action>
            
            <rule on="false">ref.type != prog.trigger_block
               <action>ref = ref.getImmediateChild(prog.block, null)</action>
            </rule>
         </rule>
         
         <action>ref = getAst(#(long) ref.getAnnotation("peerid"))</action>
         
         <!-- using the 0 index will result in the expressions being registered in "reverse"
              order -->
         <!-- the lvalue which is the first child will emit downstream as the widget reference
              on which the setValidation call is made, the valexp and valmsg will emit
              naturally as the parameters -->
         <rule>type == prog.kw_validate
            <action>createPeerAst(java.method_call, "setValidation", ref.id, 0)</action>
            <action>importFunc = true</action>
            
            <!-- else: kw_help-->
            <action on="false">
               createPeerAst(java.method_call, "setHelpStatic", ref.id, 0)
            </action>
         </rule>
      </rule>
      
      <!-- emit scroll parms -->
      <rule>
         type == prog.kw_scroll and
         parent.type == prog.statement
         
         <!-- from-current -->
         <action>ttype = java.bool_false</action>
         <rule>descendant(prog.kw_from_cur, 1)
            <action>ttype = java.bool_true</action>
         </rule>
         <action>createJavaAst(ttype, "", closestPeerId)</action>
         
         <!-- up/down -->
         <action>ttype = java.bool_true</action>
         <rule>descendant(prog.kw_down, 1)
            <action>ttype = java.bool_false</action>
         </rule>
         <action>createJavaAst(ttype, "", closestPeerId)</action>
         
      </rule>
      
      <!-- pause parameters -->
      <rule>type == prog.kw_no_msg and parent.type == prog.kw_pause
         <action>
            tw.graft("specific_null", 
                     copy,
                     closestPeerId,
                     "classname",
                     "String")
         </action>
      </rule>
      
      <!-- emit a blank line for readability (this location is used when
           all child nodes are hidden so the version of this in the ascent
           rules won't get called), note that any duplicates will be
           removed downstream -->
      <rule>
         (type == prog.kw_update   or
          type == prog.kw_set      or
          type == prog.kw_prmt_for or
          type == prog.kw_disp     or
          type == prog.kw_disable  or
          type == prog.kw_enable)         and
         parent.type == prog.statement
         
         <action>blockParId = getNoteLong("block_par_id")</action>
         <rule>blockParId != null
            <action>createJavaAst(java.skip, "", blockParId)</action>
         </rule>
      </rule>
      
   </walk-rules>
   
   <next-child-rules>
   
      <!-- color stmt 2nd parm -->
      <rule>type == prog.kw_color and parent.type == prog.statement
      
         <!-- detect if there is no prompt spec, emit null -->
         <rule>
            !descendant(prog.kw_prompt, 1) and nextChildIndex == 1
            <action>
               createJavaAst(java.null_literal, "", closestPeerId)
            </action>
         </rule>
      
      </rule>   
   
      <!-- message stmt view-as default parm support (button set) -->
      <rule>
         type == prog.kw_view_as and
         parent.type == prog.kw_msg
         
         <!-- create a default button set if not specified AND there is a
              title specified -->
         <rule>
            !descendant(prog.kw_button, 1) and 
            this.getChildAt(nextChildIndex).type == prog.kw_title
            <action>txt = "BTN_OK"</action>
            <action>importLT = true</action>
            <action>createJavaAst(java.reference, txt, closestPeerId)</action>
         </rule>
         
      </rule>
   
      <!-- manufacture default parms for put cursor and put screen -->
      <rule>
         type == prog.put_cursor or type == prog.put_screen
         
         <!-- manufacture a default row node for put cursor or put_screen
              if there is no row spec and this is either a column spec -->
         <rule>
            !descendant(prog.kw_row, 1) and
            this.getChildAt(nextChildIndex).type == prog.kw_col
         
            <action>
               createJavaAst(java.num_literal, "1", closestPeerId)
            </action>
         </rule>
         
         <!-- manufacture a default column node for put_screen if there is
              a row but no column spec AND this is a color spec -->
         <rule>
            descendant(prog.kw_row, 1) and
            !descendant(prog.kw_col, 1) and
            this.getChildAt(nextChildIndex).type == prog.kw_color
            
            <action>
               createJavaAst(java.num_literal, "1", closestPeerId)
            </action>
         </rule>      
         
      </rule>   
      
      <!-- emit the temporary format string if needed (used in some cases
           by override expressions that are being set into @ base fields) -->
      <rule>
         type == prog.frame_element   and
         nextChildIndex == 1          and
         isNote("tempfmt")
      
         <action>
            createJavaAst(java.string,
                          getNoteString("tempfmt"),
                          closestPeerId)
         </action>
      </rule>
      
   </next-child-rules>
   
   <ascent-rules>
      <rule>this.type == prog.kw_msg and this.numImmediateChildren &gt; 1
         <action>ref = this.getImmediateChild(prog.content_array, null)</action>
         <rule>ref.numImmediateChildren == 0
            <action>createJavaAst(java.string, "", closestPeerId, 0)</action>
         </rule>
      </rule>
      
      <!-- build our format string if no explicit one exists AND if there
           was no kw_auto_ret option AND this isn't a message box -->
      <rule>
         (type == prog.kw_set or type == prog.kw_update) and
         parent.type == prog.kw_msg                      and
         !parent.descendant(1, prog.kw_view_as)
         
         <!-- if there is no explicit format string but there is one
              defined for the variable, honor it -->
         <rule>
            !descendant(prog.kw_format, 1) and
            !descendant(prog.kw_auto_ret, 1)
             
            <!-- only do this for variables or fields -->
            <action>lvalref = copy.getChildAt(0)</action>
            
            <rule>evalLib("vartype", lvalref.type)
               <action>
                  fmtstr = execLib("get_format_varname", lvalref)
               </action>
               <action>toktype = java.reference</action>
            </rule>
            
            <rule>evalLib("fieldtype", lvalref.type)
               <action>fmtstr = execLib("get_format_field", lvalref)</action>
               <action>toktype = java.string</action>
            </rule>
            
            <rule>fmtstr != null
               <!-- we have a string constant member -->
               <action>
                  createJavaAst(toktype, fmtstr, closestPeerId)
               </action>
            </rule>
         </rule>
      </rule>
   
      <!-- message stmt view-as default parm support (title) -->
      <rule>
         type == prog.kw_view_as and
         parent.type == prog.kw_msg
         
         <!-- create a default button set if not specified AND there is no
              specified title -->
         <rule>
            !descendant(prog.kw_button, 1) and !descendant(prog.kw_title, 1)
            <action>txt = "BTN_OK"</action>
            <action>importLT = true</action>
            <action>createJavaAst(java.reference, txt, closestPeerId)</action>
         </rule>
         
         <!-- null out the title parm if not specified, force use of the variant where the
              6th parm is a String; without the cast this will be ambiguous with the one that
              is a character -->
         <rule>!descendant(prog.kw_title, 1)
            <action>castid = createPeerAst(java.cast, "String", closestPeerId)</action>
            <action>createJavaAst(java.null_literal, "", castid)</action>
         </rule>
      </rule>
   
      <!-- manufacture a default column node for put cursor or put_screen
           if there is a row but no column spec and no color spec -->
      <rule>
         (type == prog.put_cursor or type == prog.put_screen) and
         descendant(prog.kw_row, 1)                           and
         !descendant(prog.kw_col, 1)                          and
         !descendant(prog.kw_color, 1)
         
         <action>createJavaAst(java.num_literal, "1", closestPeerId)</action>
      </rule>
      
      <!-- emit the optional boolean parm to addEntrySet(), this supports
           both the global and widget_list forms of anywhere -->
      <rule>
         type == prog.kw_of             and
         descendant(prog.event_list, 1) and
         parent.type == prog.kw_on      and
         descendant(prog.kw_anywhere, 1)
         
         <action>createJavaAst(java.bool_true, "", closestPeerId)</action>
      </rule>
      
      <!-- add a skip after the last addEvent() -->
      <rule>type == prog.kw_of and descendant(prog.event_list, 1)
         <rule>multiMode
            <rule>copy.nextSibling.type != prog.kw_of
               <action>createJavaAst(java.skip, "", waitloc, waitidx)</action>
            </rule>
         </rule>
      </rule>
      
      <!-- add a skip after the trigger registration in lambda mode -->
      <rule>type == prog.trigger_block and !isNote("classname")
         <action>createJavaAst(java.skip, "", trigid)</action>
      </rule>
      
      <!-- emit second parameter in registerQuery call -->
      <rule>type == prog.define_browse
         <action>fename = lookupDictionaryObject("frame_element_name", "fename")</action>
         <action>createJavaAst(java.reference, fename, lastid)</action>
      </rule>

      <!-- finish off the processing -->
      <rule>type == prog.kw_when and parent.type == prog.content_array
         <action>createJavaAst(java.null_literal, "", closestPeerId)</action>
      </rule>
      
      <!-- clear state -->
      <rule>type == prog.content_array and parent.type == prog.statement
         <action>deleteScope("frame_element_name")</action>
         <action>fename = null</action>
      </rule>
      
      <!-- emit the hide single parameter for no-pause (defaults
           to false) -->
      <rule>methodText != null and type == prog.kw_hide and parent.type == prog.statement
         <action>ttype = java.bool_false</action>
         <rule>descendant(prog.kw_no_pause, 1)
            <action>ttype = java.bool_true</action>
         </rule>
         <action>createJavaAst(ttype, "", closestPeerId)</action>
      </rule>
         
      <!-- some word wrap elements need a manufactured index parm as the
           last parameter -->
      <rule>
         type == prog.frame_element and
         isNote("word_wrap_idx")
         
         <action>
            createJavaAst(java.num_literal,
                          string(getNoteLong("word_wrap_idx")),
                          closestPeerId)
         </action>
      </rule>
      
      <!-- emit the deferred LEAVE or NEXT processing after the block has
           emitted -->
      <rule>type == prog.editing_block and isNote("enclosing")
         <action>blockParId = copy.parent.getAnnotation("block_par_id")</action>
         <action>execLib("emitDeferred", blockParId, copy)</action>
      </rule>
      
      <!-- insert a blank line for readability (duplicates will be
           removed downstream) -->
      <!-- note that some of these (like DISPLAY) may have all of their
           children hidden, so the common path in those cases is a similar
           rule in the walk rules section -->
      <rule>
         type == prog.editing_block or
         ((type == prog.kw_update   or
           type == prog.kw_set      or
           type == prog.kw_prmt_for or
           type == prog.kw_disp     or
           type == prog.kw_disable  or
           type == prog.kw_enable   or
           type == prog.kw_view     or
           type == prog.kw_hide     or
           type == prog.kw_choose   or
           type == prog.kw_color    or
           type == prog.kw_underlin)         and
          parent.type == prog.statement)
         
         <action>blockParId = getNoteLong("block_par_id")</action>
         <rule>blockParId != null
            <action>createJavaAst(java.skip, "", blockParId)</action>
         </rule>
      </rule>
      
      <!-- remove empty pre(), init(), enter(), body() or fini() method defs -->
      <rule>type == prog.editing_block
         <action>execLib("remove_empty_emitted_sections", lambdaBlock, false)</action>
      </rule>

      <!-- TODO: maybe this is not best location, but this is needed on descent of core_conversion
            so the parameter added to be last -->
      <rule>this.type == prog.trigger_procedure and
            this.descendant(1, prog.kw_assign)  and
            this.descendant(1, prog.kw_new)
         <!-- we need to add the new value to trigger method parameter list -->
         <!-- look for the 1st lparens of 1st method of CS_INSTANCE_METHODS -->

         <action>xref = getSectionAnchor(java.cs_instance_methods)</action>
         <action>xref = xref.getImmediateChild(java.method_def, null)</action>
         <rule>xref.getImmediateChild(java.lparens, null) == null
            <!-- expect that the LPARENS is not yet created, create it now, as 1st child (index = 0) -->
            <action>lastid = createJavaAst(java.lparens, "(", xref.id, 0)</action>
            <action>xref = getAst(lastid)</action>

            <!-- less expected, if the lparens is already in place link to it -->
            <action on="false">xref.getImmediateChild(java.lparens, null)</action>
         </rule>

         <!-- now create the parameter for the trigger -->
         <action>lastid = createJavaAst(java.reference_def, "Undoable", xref.id)</action>
         <action>xref = getAst(lastid)</action>
         <action>
            paramName = #(java.lang.String) this.getImmediateChild(prog.kw_new, null)
                                 .getAnnotation("javaname")
         </action>
         <action>xref.putAnnotation("name", sprintf("_%s", paramName))</action>
         <action>xref.putAnnotation("final", true)</action>
      </rule>

      <rule>this.type == prog.trigger_procedure and
            this.descendant(1, prog.kw_assign)  and
            this.descendant(1, prog.kw_old)

         <!-- we need to add the old value to trigger method parameter list -->
         <!-- look for the 1st lparens of 1st method of CS_INSTANCE_METHODS -->
         <variable name="xref"      type="com.goldencode.ast.Aast" />
         <action>xref = getSectionAnchor(java.cs_instance_methods)</action>
         <action>xref = xref.getImmediateChild(java.method_def, null)</action>
         <action>xref = xref.getImmediateChild(java.lparens, null)</action>
         <rule>xref != null
            <action>
               paramName = #(java.lang.String) this.getImmediateChild(prog.kw_old, null)
                                 .getAnnotation("javaname")
            </action>
            <action>lastid = createJavaAst(java.reference_def, "BaseDataType", xref.id)</action>
            <action>xref = getAst(lastid)</action>
            <action>xref.putAnnotation("name", sprintf("_%s", paramName))</action>
            <action>xref.putAnnotation("final", true)</action>
         </rule>
      </rule>
   </ascent-rules>
   
   <post-rules>
      <rule>importLT
         <action>help.createStaticImport("com.goldencode.p2j.ui.LogicalTerminal.*")</action>
      </rule>

      <rule>importFunc
         <action>help.createImport("java.util.function.*")</action>
      </rule>

      <rule>iter = aggrMap.keySet().iterator()</rule>
      <while>iter.hasNext()
         <action>scoperef = iter.next()</action>
         <action>ref = aggrMap.get(scoperef)</action>
         <action>javaname = aggrMap2.get(scoperef)</action>

         <action>lastid = getAst(#(long) scoperef.getAnnotation("peerid")).parent.id</action>
         <action>idx = ref.getIndexPos()</action>
         
         <!-- emit a frame.registerAccumulators(...) call-->
         <action>frname = #(java.lang.String) execLib("get_framename", scoperef)</action>

         <action>
            lastid = createJavaAst(java.method_call, "registerAccumulators", lastid, idx + 1)
         </action>

         <action>createJavaAst(java.reference, frname, lastid)</action>
         <action>createJavaAst(java.reference, javaname, lastid)</action>
      </while>
   </post-rules>
   
</rule-set>
