Project

General

Profile

base_structure.xml

Modified base_structure - Paul Bodale, 03/10/2025 09:24 AM

Download (61.1 KB)

 
1
<?xml version="1.0"?>
2

    
3
<!-- 
4
/*
5
** Module   : base_structure.xml
6
** Abstract : creates the stub of a class file and determines the class name
7
**            (which forms the root structure upon which the Java AST will be built)
8
**
9
** Copyright (c) 2005-2023, Golden Code Development Corporation.
10
**
11
** _#_ _I_ __Date__ __JPRM__ ___________________________________Description___________________________________
12
** 001 GES 20050721   @21755 Good working version which converts the core
13
**                           Progress AST structure into an equivalent  Java AST structure.
14
** 002 GES 20050729   @21917 Added the progressSourceName constant to
15
**                           enable the program-name() built-in.
16
** 003 GES 20050819   @22179 Save off the converted classname in source AST.
17
** 004 GES 20050825   @22250 Modifications to unnamed stream init.
18
** 005 SIY 20051103   @23184 Using annotations "pkgname" and "classname".
19
** 006 GES 20051109   @23291 Removed lastKey instance var.
20
** 007 GES 20060123   @24029 Removed returnValue instance var.
21
** 008 GES 20060125   @24057 Removed source filename static var.
22
** 009 GES 20060131   @24168 Added full package name annotation to the kw_class node of the JAST.
23
** 010 GES 20060201   @24179 Handle annotation of target classname for run filename.
24
**                           This must be done after annotations and before core conversion.
25
** 011 GES 20060207   @24347 Removed unnamed stream instance vars.
26
** 012 GES 20060319   @25111 Fixup parameter types for RUN of external
27
**                           procs, internal procs and function calls.
28
** 013 GES 20060410   @25450 Exclude builtin funcs from func signature processing.
29
** 014 GES 20060412   @25495 Safety code for RUN VALUE() cases.
30
** 015 GES 20080701   @39042 Add static imports in compact mode.
31
** 016 GES 20081003   @40021 Only BlockManager is statically imported for
32
**                           all programs. Others are added elsewhere as needed.
33
** 017 GES 20090518   @42310 Import change.
34
** 018 GES 20111213          Added bogus hack to support missing filenames for
35
**                           RUN statements.
36
** 019 EVL 20121101          Fixing the filename file separator value for statements like RUN 
37
**                           FILENAME in Windows OS conversion environment. Merged with recent
38
**                           code base.
39
** 020 CA  20121207          Added support for persistent procedures, procedure handles and super
40
**                           procedures. All RUN statements are now converted using ControlFlowOps
41
**                           APIs, so explicit Java code is not emitted for them anymore.
42
** 021 CA  20130129          Added longchar support.
43
** 022 SVL 20130213          Implemented naming of schema triggers main functions.
44
** 023 GES 20130219          Added a qualifier to constant references.
45
** 024 CA  20130309          Convert the unknown vals passed as a parameter to builtin functions
46
**                           or methods to the appropriate wrapper instance. Also: all literals 
47
**                           passed as parameters will be marked with the "wrap" annotation, if
48
**                           the function/method is registered with common-progress.rules's 
49
**                           needs_wrapped_literals function; all undeteremined, _POLY, 
50
**                           expressions are wrapped using the parameter type.
51
** 025 CA  20130313          Fixed conversion of "RUN ... IN _POLY" stateemnt (_POLY needs to be
52
**                           wrapped using handle).
53
** 026 GES 20130313          Rework to move to generic ECW.expressionType() instead of the
54
**                           ECW.parameterTypeName().
55
** 027 VMN 20130314          "needs_wrapped_literals", second parameter added
56
** 028 CA  20130315          As the HANDLE attribute is converted to the resource instance, when
57
**                           set as a parameter to a function/method call it needs to be wrapped
58
**                           in a handle instance.
59
** 029 CA  20130316          Any _POLY-evaluated expression used as a parameter for a simple
60
**                           user-defined function call needs to be wrapped.
61
** 030 OM  20130322          Removed wrapping BaseDataType values in a BaseDataType.
62
** 031 GES 20130323          Removed some unnecessary wrapping with BDT types that actually have
63
**                           known return values AND with the op2/op3 of the ternary function.
64
** 032 OM  20130325          Replaced lock_type_literals with compiler_constants.
65
** 033 OM  20130405          Added wrappers for numerical types function/procedure parameters.
66
** 034 CA  20130611          Do not process the parameter modes emitted when calling functions
67
**                           defined IN handle or IN SUPER.
68
** 035 OM  20130520          Added wrappers for date-types function/procedure parameters.
69
** 036 CA  20130924          Fixed a regression related to parameter modes for functions.
70
** 037 OM  20130925          Moved 'chp_wrapper' annotation to first operator in if it is enclosed
71
**                           into one or more superfluous pairs of parenthesis.
72
** 038 CA  20131024          Added conditional rule-set processing flags for dynamic query
73
**                           conversion.
74
** 039 OM  20131128          Fixed trigger procedure generation and annotation using data
75
**                           previously saved in schema-triggers.xml.
76
** 040 OM  20140107          Fixed schema trigger generation when buffer declarations are required
77
**                           to appear before the TRIGGER_PROCEDURE statement.
78
** 041 SVL 20140320          Do not load name_map.cache and schema-triggers.xml in runtime mode.
79
** 042 OM  20140711          Wrote back schema-triggers.xml with additional information needed
80
**                           for loading the triggers at runtime.
81
** 043 OM  20151019          Dropped wrapping where parent node accepts _POLY arguments.
82
** 044 GES 20160519          Removed compact mode support (non-compact mode no longer exists).
83
** 045 CA  20170827          Wrap literals in a FOR ... KW_BY expression.
84
** 046 CA  20171024          Unknown literal can't be wrapped using BaseDataType.
85
** 047 OM  20180118          Dropped intermediary schema-triggers.xml file.
86
** 048 OM  20180209          Do not drop the intermediary schema triggers file.
87
** 049 CA  20180512          Unknown values for PUT-KEY-VALUE and SET-KEY-VALUE must be wrapped.
88
**                           SUBSTRING statement POLY argument support.
89
**     CA  20180514          Fixes for COPY-LOB: FROM STARTING/FOR, CONVERT SOURCE/TARGET code-page.
90
** 050 CA  20181113          Fixed UNKNOWN_VAL for SET-DB-CLIENT's second parameter.
91
** 051 GES 20181208          Added class and interface support.
92
**     CA  20181213          Fixed NEW arguments processing (as they are parented by a LPARENS).
93
**     CA  20181218          If a attribute setter's rvalue is POLY, then wrap it in a c'tor 
94
**                           accordingly to the attribute's type.
95
** 052 CA  20190423          Fixed some issues with OO method calls arguments (the argument index
96
**                           was not computed correct).
97
** 053 CA  20190509          For DYNAMIC-NEW ... NO-ERROR, the NO-ERROR is emitted as same level
98
**                           as parameters, so needs to be ignored.
99
**     ECF 20190511          Removed wrapping for COPY-LOB option expressions.
100
**     CA  20190520          Fixed POLY rvalue for attribute assignment and ENTRY function.
101
** 054 CA  20190611          Save a 'class_def_peerid' annotation at the root AST, to know where 
102
**                           to attach legacy annotations.
103
** 055 IAS 20190604          Wrapping UNKNOWN literal as CLIENT-PRINCIPAL:INITIALIZE args
104
** 056 CA  20190706          PUBLISH can have the event from a POLY expression.
105
** 057 AIL 20190722          Trigger information is no longer provided by schema-triggers.xml, 
106
**                           but by the AST itself. Removed override proprety of a trigger procedure.
107
**     AIL 20190821          Assign Triggers with new value have a reference towards EmptyBuffer.
108
** 058 CA  20190927          Added support for direct Java access from 4GL code.
109
** 059 CA  20200412          Added incremental conversion support.
110
** 060 CA  20200428          Legacy DEFINE ENUM conversion support.
111
**                           Do not throw exception if a function/method call can't be resolved 
112
**                           (no type-list annotation).
113
**     CA  20200429          Legacy DEFINE ENUM conversion support.
114
**     GES 20200430          Modifications to match new enum approach.
115
**     CA  20200503          Always wrap the literal in a CASE statement.
116
**                           A fix for property setter calls, where the type must be checked.
117
**     CA  20200508          OO class references are qualified only if 4GL qualifies them.
118
**     GES 20200515          Properly implemented implicitly added methods (fixed GetEnum to have the correct
119
**                           annotations, added SetFlag/ToggleFlag/UnsetFlag).
120
**     GES 20200603          Fixed incorrect wrapping case for virtual method enum processing of typelist.
121
**     CA  20210203          Fixed conversion issues with OUTPUT/INPUT-OUTPUT for extent or scalar parameters,
122
**                           involved in dynamic or static OO calls, functions or procedure calls.  This 
123
**                           includes mostly cases for OO properties/variables (static and non-static).
124
**     CA  20210216          Fix for the 'cast-to-object' case for a single extent argument in a dynamic call,
125
**                           when INPUT modifier exists or not.
126
**     OM  20210312          Avoid incorrectly wrapping parameters as character for methods which support
127
**                           runtime _poly parameter to 
128
**     CA  20210428          For function/OO calls passed as an argument to another call, evaluate them via a
129
**                           lambda expression so that the 'output parameter assigner' is not corrupted.
130
**     OM  20210430          Dropped incorrectly wrapping for parameters of GET-CODEPAGE (kw_get_codp).
131
**                           Avoid wrapping warning for methods/function supporting _poly parameters.
132
**     CA  20210528          Save the class_def_peerid for the trigger procedures, too - so they can have the
133
**                           DatabaseReferences annotation emitted.
134
**     CA  20210609          Reworked INPUT/INPUT-OUTPUT parameters to a new approach, where they are explicitly 
135
**                           initialized at the method's execution, and not at the caller's arguments.
136
**                           (backed out CA/20210428).
137
**     HC  20211001          Implementation of i18n support.
138
**     CA  20220516          Emit a @LegacySerializable annotation for SERIALIZABLE legacy classes.
139
** 061 OM  20230115          Replaced absolutePath(), relativePath(), upPath() and downPath() with faster
140
**                           versions, based on node types rather on string paths.
141
** 062 OM  20230921          Moved DatabaseTrigger to com.goldencode.p2j.persist.trigger package.
142
*/
143
-->
144

    
145
<!--
146
** This program is free software: you can redistribute it and/or modify
147
** it under the terms of the GNU Affero General Public License as
148
** published by the Free Software Foundation, either version 3 of the
149
** License, or (at your option) any later version.
150
**
151
** This program is distributed in the hope that it will be useful,
152
** but WITHOUT ANY WARRANTY; without even the implied warranty of
153
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
154
** GNU Affero General Public License for more details.
155
**
156
** You may find a copy of the GNU Affero GPL version 3 at the following
157
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
158
** 
159
** Additional terms under GNU Affero GPL version 3 section 7:
160
** 
161
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
162
**   terms apply to the works covered under the License.  These additional terms
163
**   are non-permissive additional terms allowed under Section 7 of the GNU
164
**   Affero GPL version 3 and may not be removed by you.
165
** 
166
**   0. Attribution Requirement.
167
** 
168
**     You must preserve all legal notices or author attributions in the covered
169
**     work or Appropriate Legal Notices displayed by works containing the covered
170
**     work.  You may not remove from the covered work any author or developer
171
**     credit already included within the covered work.
172
** 
173
**   1. No License To Use Trademarks.
174
** 
175
**     This license does not grant any license or rights to use the trademarks
176
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
177
**     of Golden Code Development Corporation. You are not authorized to use the
178
**     name Golden Code, FWD, or the names of any author or contributor, for
179
**     publicity purposes without written authorization.
180
** 
181
**   2. No Misrepresentation of Affiliation.
182
** 
183
**     You may not represent yourself as Golden Code Development Corporation or FWD.
184
** 
185
**     You may not represent yourself for publicity purposes as associated with
186
**     Golden Code Development Corporation, FWD, or any author or contributor to
187
**     the covered work, without written authorization.
188
** 
189
**   3. No Misrepresentation of Source or Origin.
190
** 
191
**     You may not represent the covered work as solely your work.  All modified
192
**     versions of the covered work must be marked in a reasonable way to make it
193
**     clear that the modified work is not originating from Golden Code Development
194
**     Corporation or FWD.  All modified versions must contain the notices of
195
**     attribution required in this license.
196
-->
197

    
198
<cfg>
199
   <!-- register worker objects -->
200
   <worker class="com.goldencode.p2j.uast.ProgressPatternWorker"           namespace="prog" />
201
   <worker class="com.goldencode.p2j.uast.JavaPatternWorker"               namespace="java" />
202
   <worker class="com.goldencode.p2j.convert.NameConverterWorker"          namespace="names" />
203
   <worker class="com.goldencode.p2j.pattern.TemplateWorker"               namespace="tw" />
204
   <worker class="com.goldencode.p2j.convert.ConverterHelper"              namespace="help" />
205
   <worker class="com.goldencode.p2j.convert.ExpressionConversionWorker"   namespace="ecw" />
206
   <worker class="com.goldencode.p2j.xml.XmlPatternWorker"                 namespace="xml" />
207
   <worker class="com.goldencode.p2j.schema.P2OAccessWorker"               namespace="p2o" />
208

    
209
   <!-- expression libraries -->
210
   <include name="common-progress" />
211
   <include name="i18n" />
212
   <include name="convert/common-convert" />
213
  
214
   <func-library access="private">
215
      <function name="function_or_method_call">
216
         <parameter name="ref" type="com.goldencode.ast.Aast" />
217

    
218
         (ref.type &gt; prog.begin_functypes and 
219
          ref.type &lt; prog.end_functypes   and 
220
          ref.isAnnotation("builtin")        and
221
          #(java.lang.Boolean) ref.getAnnotation("builtin")) or
222
         (ref.type &gt; prog.begin_meth and
223
          ref.type &lt; prog.end_meth))
224
      </function>
225
   </func-library>
226
  
227
   <!-- variables -->
228
   <variable name="parIdx"     type="java.lang.Long" />
229
   <variable name="methDefId"  type="java.lang.Long" />
230
   <variable name="refid"      type="java.lang.Long" />
231
   <variable name="oldtype"    type="java.lang.Long" />
232
   <variable name="classname"  type="java.lang.String" />
233
   <variable name="targetname" type="java.lang.String" />
234
   <variable name="pkgname"    type="java.lang.String" />
235
   <variable name="wrapper"    type="java.lang.String" />
236
   <variable name="needed"     type="java.lang.String" />
237
   <variable name="cls"        type="java.lang.String" />
238
   <variable name="casttype"   type="java.lang.String" />
239
   <variable name="errmsg"     type="java.lang.String" />   
240
   <variable name="modes"      type="java.lang.String" />   
241
   <variable name="pmode"      type="java.lang.String" />   
242
   <variable name="candidate"  type="java.lang.String" />
243
   <variable name="isClass"    type="java.lang.Boolean" />
244
   <variable name="isIface"    type="java.lang.Boolean" />   
245
   <variable name="isEnum"     type="java.lang.Boolean" />
246
   <variable name="flagsEnum"  type="java.lang.Boolean" />   
247
   <variable name="ooLangImp"  type="java.lang.Boolean" />   
248
   <variable name="typelist"   type="java.util.ArrayList" />
249
   <variable name="ref"        type="com.goldencode.ast.AnnotatedAst" />
250
   <variable name="pref"       type="com.goldencode.ast.AnnotatedAst" />
251
   <variable name="lref"       type="com.goldencode.ast.Aast" />
252
   <variable name="iref"       type="com.goldencode.ast.Aast" />
253

    
254
   <variable name="titer"            type="java.lang.Integer"/>
255
   <variable name="trname"           type="java.lang.String"/>
256
   <variable name="crt_tr"           type="com.goldencode.p2j.xml.XmlAst" />
257
   <variable name="runtimeQueryMode" type="java.lang.Boolean" />
258

    
259
   <!-- pipeline of rule-sets to process -->
260
  
261
   <!-- global initialization (once per pipeline) -->
262
   <init-rules>
263
      <rule>setAutoload(true)</rule>
264
      <rule>tw.load("convert/java_templates")</rule>
265
      <rule>runtimeQueryMode = isRuntimeQueryMode()</rule>
266
      <rule>errmsg = "Passing unknown value literal to builtin func!"</rule>
267
   </init-rules>
268
  
269
   <!-- main processing (once per tree) -->
270
   <rule-set input="tree" load-condition="runtime-query">
271
   
272
      <variable name="numparms"   type="java.lang.Long" />
273
      <variable name="lastid"     type="java.lang.Long" />
274
      <variable name="execname"   type="java.lang.String" />
275
      <variable name="is_trigger" type="java.lang.Boolean" />
276
      <variable name="buf_class"  type="java.lang.String" />
277
      <variable name="extends"    type="java.lang.String" />
278
      <variable name="access"     type="java.lang.String" />
279
      <variable name="jname"      type="java.lang.String" />
280
      <variable name="qname"      type="java.lang.String" />
281
      <variable name="qual_oo"    type="java.lang.String" />
282
      <variable name="clsref"     type="com.goldencode.ast.Aast" />
283
      <variable name="parref"     type="com.goldencode.ast.Aast" />
284
      <variable name="jclsdef"    type="com.goldencode.ast.Aast" />
285

    
286
      <init-rules>
287
         <rule>ooLangImp = false</rule>
288
         
289
         <rule>qname = execLib("compute_package", this.getAnnotation("package-base"))</rule>
290
         <rule>qname.isEmpty()
291
            <rule>qname = this.getAnnotation("classname")</rule>
292
            <rule on="false">qname = sprintf("%s.%s", qname, this.getAnnotation("classname"))</rule>
293
         </rule>
294
         <rule>qname = qname.replaceAll("\.", "_")</rule>
295
         
296
         <rule>deleteDictionary("function")</rule>
297
         
298
         <rule>is_trigger = downPath(this, prog.statement, prog.trigger_procedure)</rule>
299
         <rule>isClass = descendant(prog.class_def, 1)</rule>
300
         <rule>isIface = descendant(prog.interface_def, 1)</rule>
301
         <rule>isEnum = descendant(prog.enum_def, 1)</rule>
302
         
303
         <!-- add package name -->   
304
         <rule>pkgname = getNoteString("pkgname")</rule>
305
         <rule>createJavaAst(java.kw_package, pkgname, javaRootId)</rule>
306
         
307
         <!-- import the core runtime package -->   
308
         <rule>createImport("com.goldencode.p2j.util.*")</rule>
309
         
310
         <!-- statically import some of the core runtime package, except for enums -->
311
         <rule>!isEnum
312
            <action>createStaticImport("com.goldencode.p2j.util.BlockManager.*")</action>
313
         </rule>
314
         
315
         <!-- obtain the root of the class and a method definition for the
316
              primary entry point and associate the primary entry point with
317
              the BLOCK that is the external procedure (this is implicit
318
              because the top level node of all Progress source ASTs
319
              is always the same and is the current node in the init
320
              rules) --> 
321
         <rule>classname = getNoteString("classname")</rule>
322
         
323
         <!-- save this name off for the future -->
324
         <rule>putNote("javaname", classname)</rule>
325

    
326
         <variable name="triggerRef"   type="com.goldencode.ast.Aast" />
327
         <variable name="tableRef"     type="com.goldencode.ast.Aast" />
328
         <variable name="oldValueName" type="java.lang.String" />
329
         <variable name="buffer_class" type="java.lang.String" />
330
         <variable name="event_type"   type="java.lang.String" />
331
         <variable name="hasOldBuffer" type="java.lang.Boolean" />
332
         <variable name="eventType"    type="java.lang.String" />
333

    
334
         <variable name="trg_event"    type="java.lang.String" />
335
         <variable name="trg_field"    type="java.lang.String" />
336
         <variable name="trg_table"    type="java.lang.String" />
337

    
338
         <!-- schema trigger case -->
339
         <rule>is_trigger
340
            <!-- analyze information from ast tree: the TRIGGER_PROCEDURE statement might not
341
                 be the first one because one (or more) DEFINE_BUFFER statement and the
342
                 BUFFER_SCOPE declarations can be promoted to external-level
343
                 if they were defined in the trigger body -->
344
            <rule>triggerRef = copy.getImmediateChild(prog.statement, null)</rule>
345
            <while>triggerRef != null
346
               <rule>triggerRef.descendant(1, prog.trigger_procedure)
347
                  <break/>
348
               </rule>
349

    
350
               <rule>triggerRef = copy.getImmediateChild(prog.statement, triggerRef)</rule>
351
            </while>
352
            <rule>triggerRef = triggerRef.getImmediateChild(prog.trigger_procedure, null)</rule>
353
            <!-- at this moment triggerRef should contain the TRIGGER_PROCEDURE node;
354
                 it cannot be null as we are in [is_trigger] case -->
355

    
356
            <action>eventType = execLib("get_db_event_type", triggerRef)</action>
357
            <rule>(triggerRef.descendant(1, prog.kw_write)   or
358
                   triggerRef.descendant(1, prog.kw_repl_wri)) and
359
                  triggerRef.descendant(1, prog.kw_new)
360
               <!-- for write trigger prefer look into KW_NEW for buffer instead -->
361
               <action>tableRef = triggerRef.getImmediateChild(prog.kw_new, null)
362
                                       .getImmediateChild(prog.table, null)</action>
363
               <!-- all other triggers -->
364
               <action on="false">tableRef = triggerRef.getImmediateChild(prog.table, null)</action>
365
            </rule>
366
            <!-- store the buffer to global for declaring the DatabaseTrigger generic class -->
367
            <rule>tableRef != null
368
               <action>buf_class = #(java.lang.String) tableRef.getAnnotation("bufclassname")</action>
369

    
370
               <!-- tableRef is null in the case of SCHEMA/ASSIGN/NEW -->
371
               <action on="false">buf_class = ""</action>
372
            </rule>
373
            <rule>(triggerRef.descendant(1, prog.kw_write)     or
374
                   triggerRef.descendant(1, prog.kw_repl_wri)  or
375
                   triggerRef.descendant(1, prog.kw_assign))   and
376
                   triggerRef.descendant(1, prog.kw_old)
377
               <action>
378
                  oldValueName = #(java.lang.String) triggerRef.getImmediateChild(prog.kw_old, null)
379
                                 .getAnnotation("javaname")
380
               </action>
381
               <action>hasOldBuffer = true</action>
382
               <action on="false">hasOldBuffer = false</action>
383
            </rule>
384
            
385
            <rule>tableRef != null
386
               <action>trg_table = tableRef.getAnnotation("schemaname")</action>
387
               <action>trg_field = ""</action>
388
               <rule>triggerRef.descendant(1, prog.kw_assign)
389
                  <action>trg_field = triggerRef.getChildAt(2).getAnnotation("fieldName")</action>
390
               </rule>
391
               <action on="false">trg_table = ""</action>
392
               <action on="false">trg_field = ""</action>
393
            </rule>
394
         </rule>
395
         
396
         <!-- create the skeleton of the top level trigger class -->
397
         <rule>is_trigger
398
            <action>createImport("com.goldencode.p2j.persist.trigger.*")</action>
399
            <!-- add field property only if we have a field trigger (assign trigger) -->
400
            <rule>trg_field.isEmpty()
401
               <rule> buf_class.isEmpty()
402
                  <action>buf_class = "EmptyBuffer"</action>
403
               </rule>
404
               <action>
405
                  tw.graft("schema_trigger_annotation_record", null, javaRootId,
406
                           "buffer_class",    sprintf("%s.class", buf_class),
407
                           "event_type",      eventType,
408
                           "table_name",      trg_table,
409
                           "old_buffer",      hasOldBuffer.toString())
410
               </action>
411
               <action on="false">
412
                  tw.graft("schema_trigger_annotation_field", null, javaRootId,
413
                           "buffer_class",    sprintf("%s.class", buf_class),
414
                           "event_type",      eventType,
415
                           "field_name",      trg_field,
416
                           "table_name",      trg_table,
417
                           "old_buffer",      hasOldBuffer.toString())
418
               </action>
419
            </rule>
420
            <action>
421
               ref = tw.graft("trigger_class_def", null, javaRootId,
422
                              "bufclass",  buf_class,
423
                              "classname", classname,
424
                              "pkgname",   pkgname)
425
            </action>
426
            <action>putNote("class_def_peerid", ref.id)</action>
427
            
428
            <!--set the name of the trigger class as an attribute.
429
               'crt_tr' must be not null, otherwise is_trigger is false -->
430
            <variable name="xmlUtilNode" type="com.goldencode.p2j.xml.XmlAst"/>
431
            <action>xmlUtilNode = xml.createAst(xml.attribute_node, "class", crt_tr)</action>
432
            <action>xml.createAst(xml.content,
433
                                  sprintf("%s.%s", pkgname, classname),
434
                                  xmlUtilNode)</action>
435
            <action>xmlUtilNode = xml.createAst(xml.attribute_node, "buffer", crt_tr)</action>
436
            <action>xml.createAst(xml.content,
437
                                  sprintf("%s", buf_class),
438
                                  xmlUtilNode)</action>
439
            
440
            <rule>!trg_field.isEmpty()
441
               <action>xmlUtilNode = xml.createAst(xml.attribute_node, "property", crt_tr)</action>
442
               <action>xml.createAst(xml.content,
443
                                     trg_field,
444
                                     xmlUtilNode)</action>
445
            </rule>
446
         </rule>
447

    
448
         <!-- exteral procedure case -->
449
         <rule>!is_trigger and !isClass and !isIface and !isEnum
450
            <action>
451
               ref = tw.graft("class_def", null, javaRootId,
452
                              "classname", classname,
453
                              "pkgname",   pkgname,
454
                              "access",    "public")
455
            </action>
456
            <action>putNote("class_def_peerid", ref.id)</action>
457
         </rule>
458

    
459
         <rule>!isClass and !isIface and !isEnum
460
            <!-- create the root node for the external procedure -->
461
            <rule>methDefId = getSectionAnchor(java.cs_instance_methods).id</rule>
462
            <rule>isNote("execname")
463
               <action>execname = getNoteString("execname")</action>
464
               <action on="false">execname = "execute"</action>
465
            </rule>
466
   
467
            <rule>lastid = createPeerAst(java.method_def, execname, methDefId)</rule>
468
   
469
            <!-- if we have parameters, add an LPARENS to root them and store
470
                 the ID for future use by the define parameter nodes -->
471
            <rule>isNote("numparms")
472
               <action>numparms = getNoteLong("numparms")</action>
473
               <rule>numparms > 0
474
                  <action>lastid = createJavaAst(java.lparens, "(", lastid)</action>
475
                  <action>putNote("parmroot", lastid)</action>
476
               </rule>
477
            </rule>
478
         </rule>
479
         
480
         <!-- OO 4GL cases -->
481
         <rule>isClass or isIface or isEnum
482
         
483
            <action>extends = null</action>
484
            
485
            <!-- there are no private or protected classes or interfaces -->
486
            <action>access = "public"</action>
487
            
488
            <rule>isClass
489
               <action>clsref = this.getImmediateChild(prog.class_def, null)</action>
490
               <action>clsref = clsref.getImmediateChild(prog.kw_class, null)</action>
491
               
492
               <rule on="false">isIface
493
                  <action>
494
                     clsref = this.getImmediateChild(prog.interface_def, null)
495
                  </action>
496
                  <action>
497
                     clsref = clsref.getImmediateChild(prog.kw_interfac, null)
498
                  </action>
499

    
500
                  <action on="false">
501
                     clsref = this.getImmediateChild(prog.enum_def, null)
502
                  </action>
503
                  <action on="false">
504
                     clsref = clsref.getImmediateChild(prog.kw_enum, null)
505
                  </action>
506
               </rule>
507
            </rule>
508
            <action>parref = clsref.getImmediateChild(prog.kw_inherits, null)</action>
509
            <rule>parref != null
510
               <action>parref = parref.getChildAt(0)</action>
511
               <action>extends = execLib("resolveClassReference", parref, null)</action>
512
               <rule on="false">isClass
513
                  <action>extends = "BaseObject"</action>
514
                  <action>ooLangImp = true</action>
515
               </rule>
516
               <rule on="false">isEnum
517
                  <rule>downPath(clsref, prog.kw_flags)
518
                     <action>extends = "FlagsEnum"</action>
519
                     <action>flagsEnum = true</action>
520
                     <action on="false">extends = "LegacyEnum"</action>
521
                     <action on="false">flagsEnum = false</action>
522
                  </rule>
523
                  <action>ooLangImp = true</action>
524
               </rule>
525
            </rule>
526
         </rule>
527
         <rule>isClass or isEnum
528
            <action>
529
               jclsdef = tw.graft("class_def_ext", null, javaRootId,
530
                                                   "classname", classname,
531
                                                   "pkgname",   pkgname,
532
                                                   "extends",   extends,
533
                                                   "access",    access)
534
            </action>
535
            <action>putNote("class_def_peerid", jclsdef.id)</action>
536
            <rule>clsref.descendant(1, prog.kw_abstract)
537
               <action>jclsdef.putAnnotation("abstract", true)</action>
538
            </rule>
539
            <rule>clsref.descendant(1, prog.kw_final) or isEnum
540
               <action>jclsdef.putAnnotation("final", true)</action>
541
            </rule>
542

    
543
            <rule>isClass
544
               <!-- create the root node for the external procedure, where the initialization
545
                    code will reside -->
546
               <action>methDefId = getSectionAnchor(java.cs_instance_methods).id</action>
547
               <action>execname = sprintf("__%s_execute__", qname)</action>
548
               <action>lastid = createPeerAst(java.method_def, execname, methDefId)</action>
549
               
550
               <rule>downPath(clsref, prog.kw_serialab)
551
                  <!-- emit a @LegacySerializable annotation for this class -->
552
                  <action>
553
                     createJavaAst(java.annotation, "LegacySerializable", jclsdef.parent.id, jclsdef.indexPos)
554
                  </action> 
555
               </rule>
556
            </rule>
557
         </rule>
558
         <rule>isIface
559
            <!-- if there is no explicit parent interface, we implicitly inherit from the
560
                 master parent interface that allows references to interfaces to be treated
561
                 as Progress.Lang.Objects -->
562
            <rule>extends == null
563
               <action>extends = "com.goldencode.p2j.oo.lang._BaseObject_"</action>
564
            </rule>
565
            <action>
566
               jclsdef = tw.graft("interface_def_ext", null, javaRootId,
567
                                                       "classname", classname,
568
                                                       "pkgname",   pkgname,
569
                                                       "extends",   extends,
570
                                                       "access",    access)
571
            </action>
572
         </rule>
573

    
574
         <!-- for 4GL classes and external procedures -->
575
         <rule>!isIface and !isEnum and getConfigParameter("i18n-enable", false))
576
            <action>execLib("initClassI18n", pkgname, classname)</action>
577
         </rule>
578

    
579
      </init-rules>
580
      
581
      <descent-rules>
582
         <!-- obtain type list for FUNC_* calls and save it in the dictionary -->
583
         <rule>evalLib("function_calls") or evalLib("oo_call_type", this, null)
584
            <action>addScope("function")</action>
585

    
586
            <action>refid = getNoteLong("refid")</action>
587
            <action>typelist = null</action>
588
            <action>modes = null</action>
589
            
590
            <!-- avoid builtin funcs -->
591
            <rule>refid != null
592
               <action>iref = getAst(refid)</action>
593

    
594
               <action>
595
                  typelist = iref.getAnnotation("typelist")
596
               </action>
597
               <action>modes = iref.getAnnotation("param_modes")</action>
598

    
599
               <rule>typelist == null and 
600
                     isNote("cls-property") and 
601
                     getNoteBoolean("cls-property") and
602
                     "setter" == getNoteString("property-access-type")
603
                  <action>typelist = create("java.util.ArrayList")</action>
604
                  <action>typelist.add(iref.getAnnotation("classname"))</action>
605
                  <action>modes = "I"</action>
606
               </rule>
607
            
608
               <action>
609
                  addDictionaryObject("function", "typelist", typelist)
610
               </action>
611
               <action>
612
                  addDictionaryObject("function", "modes", modes)
613
               </action>
614
            </rule>
615
         </rule>
616
      </descent-rules>
617
      
618
      <walk-rules>
619
      
620
         <!-- all attribute setters for which the expression is POLY must be annotated with
621
              the attribute's type -->
622
         <rule>this.type &gt; prog.begin_attr and 
623
               this.type &lt; prog.end_attr   and
624
               this.indexPos == 1             and
625
               parent.type == prog.colon      and
626
               parent.indexPos == 0           and
627
               upPath(this, prog.assign, prog.colon)
628
            <action>ref = copy.parent.parent.getChildAt(1)</action>
629
            <action>wrapper = ecw.expressionType(ref, false)</action>
630

    
631
            <rule>wrapper == null or wrapper.equals("BaseDataType")
632
               <action>wrapper = ecw.expressionType(copy)</action>
633
               
634
               <rule>!(wrapper == null or wrapper.equals("BaseDataType"))
635
                  <action>ref.putAnnotation("classname", wrapper)</action>
636
                  <action>ref.putAnnotation("wrap_parameter", true)</action>
637
                  
638
                  <!-- there are POLY attributes - we don't know how to wrap these --> 
639
                  <action on="false">
640
                     printfln("WARNING: received a POLY rvalue for POLY attribute assignment %s",
641
                              this.dumpTree(true))
642
                  </action>
643
               </rule>
644
            </rule>
645
         </rule>
646
         
647
         <!-- convert the implements clause for OO classes -->
648
         <rule>relativePath(this, prog.class_def, prog.kw_class, prog.kw_implemts)
649
            <action>createPeerAst(java.kw_implements, "implements", jclsdef.id, 0)</action>
650
         </rule>
651
         <rule>relativePath(this, prog.kw_implemts, prog.class_name)
652
            <action>jname = execLib("resolveClassReference", copy, null)</action>
653
            <action>createPeerAst(java.class_reference, jname, closestPeerId)</action>
654
         </rule>
655
         
656
         <!--  all RUN statement cases will be converted using ControlFlowOps
657
               APIs; explicit Java code is no longer emitted for these cases,
658
               as 4GL allows an internal proc name to have the same name as an
659
               external procedure (and the internal procedures are searched
660
               first) -->
661
               
662
         <!-- TODO: some "virtual" OO method calls (e.g. Progress.Lang.Enum:GetEnum) have no original method
663
                    definition to reference, which means there is no refid; wrapping for these will not work
664
                    right now; to avoid bad behavior we must not try to process the dictionary lookup since
665
                    it will NOT have non-null values for this current call and may return an enclosing method
666
                    or function call's typelist/modes instead; this is why we exclude the missing refid case
667
                    -->
668
         <rule>
669
            parent != null                                                                        and
670
            parent.isAnnotation("refid")                                                          and
671
            ((evalLib("function_call_type", parent.type)                                  and 
672
              (!parent.isAnnotation("param_modes") or copy.indexPos > 0))                      or 
673
             (evalLib("oo_call_type", parent, copy) and !evalLib("is_builtin_cls", parent) and
674
              !evalLib("is_java_cls", parent) and isNote("param_index")))
675
            
676
            <action>
677
               typelist = lookupDictionaryObject("function", "typelist")
678
            </action>
679
            <action>
680
               modes = lookupDictionaryObject("function", "modes")
681
            </action>
682

    
683
            <rule>
684
               !parent.isAnnotation("builtin") or
685
               #(java.lang.Boolean) parent.getAnnotation("builtin") == false
686
                             
687
               <!-- TODO: this test doesn't make sense since it can find enclosing function/method call
688
                          typelists instead of the current call; this happens in the "virtual" method
689
                          cases like GetEnum; we really need a foolproof approach here -->
690
               <rule>typelist != null
691

    
692
                  <action>parIdx = #(long) (-1)</action>
693
                  <rule>copy.isAnnotation("param_index")
694
                     <action>parIdx = #(long) copy.getAnnotation("param_index")</action>
695
                  
696
                     <rule on="false">parent.isAnnotation("param_modes")
697
                        <action>parIdx = #(long) copy.indexPos - 1</action>
698
                        <action on="false">parIdx = #(long) copy.indexPos</action>
699
                     </rule>
700
                  </rule>
701
                  <action>wrapper = typelist.get(parIdx)</action>
702
   
703
                  <!-- mark with the proper wrapper:
704
                       - unknown value literals used in user defined function 
705
                         call parameters types
706
                       - all string literals to their proper types-->
707
                  <rule>type == prog.string or type == prog.unknown_val
708
                     <action>putNote("classname", wrapper)</action>
709
                  </rule>
710
                  
711
                  <!-- longchar and character parameters may need to be
712
                       wrapped, as in 4GL char and longchar are inter-changeble
713
                       int64 also need to be wrapped as integer if the case;
714
                       same case for date/datetime/datetime-tz.
715
                       -->
716
                  <rule>wrapper != null and
717
                        (wrapper.equals("longchar") or wrapper.equals("character")   or 
718
                         wrapper.equals("integer")  or wrapper.equals("decimal")     or
719
                         wrapper.equals("int64"))   or wrapper.equals("datetime")    or
720
                         wrapper.equals("date")     or wrapper.equals("datetimetz"))
721
                     <variable name="nodeRef" type="com.goldencode.ast.Aast" />
722
                     
723
                     <action>nodeRef = copy</action>
724
                     <!-- look for the true node, leaving the superfluos parenthesis away -->
725
                     <while>nodeRef != null and 
726
                            (nodeRef.type == prog.lparens or nodeRef.type == prog.expression)
727
                        <!-- usually there are no extra LPARENS so there will be no iteration -->
728
                        <action>nodeRef = nodeRef.getChildAt(0)</action>
729
                     </while>
730
                     
731
                     <rule>nodeRef != null
732
                        <rule>!(evalLib("type_pair", this, prog.func_poly, prog.kw_dyn_func) or
733
                                evalLib("type_pair", this, prog.func_poly, prog.kw_dyn_invk) or
734
                                evalLib("type_pair", this, prog.func_poly, prog.kw_dyn_prop) or
735
                                evalLib("type_pair", this, prog.attr_poly, prog.kw_buf_val)  or
736
                                this.type == prog.db_ref_non_static)
737
                          <action>nodeRef.putAnnotation("chp_wrapper", wrapper)</action>
738
                        </rule>
739
                     </rule>
740

    
741
                     <action>pmode = modes.substring(parIdx, parIdx + 1)</action>
742
                     <rule>pmode == 'O' or pmode == 'U'
743
                        <action>putNote("output_mode", true)</action>
744
                     </rule>
745
                  </rule>
746
                  
747
                  <rule>wrapper != null
748
                  
749
                     <!-- deal with dynamic-function casttype cases to avoid unnecessary
750
                          wrapping -->
751
                     <rule>
752
                        evalLib("type_pair", copy, prog.func_poly, prog.kw_dyn_func) and
753
                        isNote("casttype")
754
                        <action>casttype = getNoteString("casttype")</action>
755
                        <action on="false">casttype = null</action>
756
                     </rule>
757
                  
758
                     <!-- only process for the indeterminate cases (_POLY) or the HANDLE
759
                          attribute -->
760
                     <action>candidate = ecw.expressionType(copy, false)</action>
761
                     <rule>
762
                        candidate == null                or
763
                        candidate.equals("BaseDataType") or 
764
                        candidate.equals("WrappedResource")
765
                         
766
                        <!-- user defined funcs can't have unknown or BDT types so that this
767
                             point wrapper is a safe coercion target; but we only wrap if the
768
                             casttype is not there OR if the casttype is not assignment
769
                             compatible with what we need to pass as the parameter.
770
                             assignment-compatible can't be used here: the cast may have a common
771
                             super-class with the defined argument (like TextOps for longchar and 
772
                              character), but the caller may not be a sub-class -->
773
                        <rule>casttype == null or !casttype.equals(wrapper)
774
                           <rule>!(evalLib("type_pair", this, prog.func_poly, prog.kw_dyn_func) or
775
                                   evalLib("type_pair", this, prog.func_poly, prog.kw_dyn_invk) or
776
                                   evalLib("type_pair", this, prog.func_poly, prog.kw_dyn_prop) or
777
                                   evalLib("type_pair", this, prog.attr_poly, prog.kw_buf_val)  or
778
                                   this.type == prog.db_ref_non_static)
779

    
780
                              <action>putNote("wrap_parameter", true)</action>
781
                              <action>putNote("classname", wrapper)</action>
782

    
783
                              <!-- Mark the function call as poly witn an annotation -->
784
                              <action on="false">copy.parent.putAnnotation("isPoly", true)</action>
785
                           </rule>
786
                        </rule>
787
                     </rule>
788
                  </rule>
789
                  
790
                  <action on="false">printfln("%s %s", errmsg, parent.dumpTree(true))</action>
791
               </rule>
792
            </rule>
793

    
794
         </rule>
795
         
796
         <rule>parent.type == prog.kw_publish and
797
               this.indexPos == 0             and
798
               this.type == prog.expression
799
            
800
            <rule>cls = ecw.expressionType(this, false)</rule>
801
            
802
            <rule>cls == null || cls.equals("BaseDataType") 
803
               <action>putNote("wrap_parameter", true)</action>
804
               <action>putNote("classname", "character")</action>
805
            </rule>
806
         </rule>
807
         
808
         <!-- check clauses for some special statements -->
809
         <rule>parent.type == prog.kw_run
810
            <rule>ref = null</rule>
811

    
812
            <rule>type == prog.kw_in
813
               <action>ref = copy.getFirstChild()</action>
814
            </rule>
815
            
816
            <rule>ref != null
817
               <rule>cls = ecw.expressionType(ref, false)</rule>
818
   
819
               <rule>cls == null || cls.equals("BaseDataType") 
820
                  <action>wrapper = "handle"</action>
821
                  <!-- mark this node, so that we can wrap it in expressions.rules -->
822
                  <action>ref.putAnnotation("wrap_parameter", true)</action>
823
                  <action>ref.putAnnotation("classname", wrapper)</action>
824
               </rule>
825
            </rule>
826
         </rule>
827
         
828
         <rule>this.type == prog.expression and
829
               copy.firstChild != null      and 
830
               evalLib("literals", copy.firstChild.type)
831
            
832
            <rule>parent.type == prog.kw_by or parent.type == prog.kw_case
833
               <action>putNote("wrap", true)</action>
834
            </rule>
835
            
836
            <rule>(upPath(this, prog.kw_this_obj, prog.lparens, prog.parameter) or 
837
                   upPath(this, prog.kw_super, prog.lparens, prog.parameter)) and
838
                  parent.parent.parent.isAnnotation("javaname")
839
               <action>putNote("wrap", true)</action>
840
            </rule>
841
         </rule>
842
         <rule>evalLib("literals", this.type) and 
843
               (upPath(this, prog.object_invocation) or upPath(this, prog.object_invocation, prog.expression))
844
            <action>putNote("wrap", true)</action>
845
         </rule>
846
         
847
         <rule>this.type == prog.unknown_val and 
848
               (upPath(this, prog.statement, prog.kw_put_k_v, prog.kw_section, prog.expression)           or
849
                upPath(this, prog.statement, prog.kw_put_k_v, prog.kw_key, prog.expression)               or
850
                upPath(this, prog.statement, prog.kw_get_k_v, prog.kw_section, prog.expression)           or
851
                upPath(this, prog.statement, prog.kw_get_k_v, prog.kw_key, prog.expression))
852
            <action>copy.parent.putAnnotation("classname", "character")</action>
853
         </rule>
854
         
855
         <rule>this.indexPos >= 1            and
856
               (upPath(this, prog.statement, prog.kw_substr)                  or
857
                upPath(this, prog.statement, prog.assign, prog.kw_substr)     or
858
                upPath(this, prog.statement, prog.kw_assign, prog.kw_substr)  or
859
                upPath(this, prog.statement, prog.kw_entry)                   or
860
                upPath(this, prog.statement, prog.assign, prog.kw_entry)      or
861
                upPath(this, prog.statement, prog.kw_assign, prog.kw_entry))
862
            <action>candidate = ecw.expressionType(copy, false)</action>
863
            <rule>candidate == null                or
864
                  candidate.equals("BaseDataType") or 
865
                  candidate.equals("WrappedResource")
866
               <action>copy.putAnnotation("wrap_parameter", true)</action>
867
               
868
               <rule>parent.type == prog.kw_substr
869
                  <rule>copy.indexPos == 1
870
                     <action>classname = "character"</action>
871
                     <action on="false">classname = "integer"</action>
872
                  </rule>
873
                  
874
                  <rule on="false">copy.indexPos == 1
875
                     <action>classname = "integer"</action>
876
                     <action on="false">classname = "character"</action>
877
                  </rule>
878
               </rule>
879
               
880
               <action>copy.putAnnotation("classname", classname)</action>
881
            </rule>
882
         </rule> 
883
         
884
         <!-- for builtin functions and for methods, we need to wrap these cases:
885
              - unknown value
886
              - some literals (depending on type and context)
887
              - parameter expressions which don't have a determined type (i.e. _POLY
888
                or other) -->
889
         <rule>this.type != prog.kw_no_error and 
890
               this.type != prog.kw_input    and
891
               this.type != prog.kw_in_out   and
892
               this.type != prog.kw_output   and
893
               this.type != prog.kw_append   and
894
               this.type != prog.kw_bind     and
895
               this.type != prog.kw_by_ref   and
896
               this.type != prog.kw_by_value and
897
               ((evalLib("function_or_method_call", parent)                 and
898
                 !evalLib("type_pair", parent, prog.func_class, prog.kw_new) and  
899
                 !evalLib("supports_poly_argument", copy.parent, copy.indexPos)) or
900
                 (parent.type == prog.lparens and  
901
                  evalLib("type_pair", parent.parent, prog.func_class, prog.kw_new)))
902
            
903
            <action>pref = parent</action>
904
            <rule>pref.type == prog.lparens
905
               <action>pref = pref.parent</action>
906
            </rule>
907
            <action>oldtype = #(long) pref.getAnnotation("oldtype")</action>
908
            <action>wrapper = null</action> 
909

    
910
            <!-- in some cases, the parameter is one level down -->
911
            <action>ref = copy</action>
912
            <while>
913
               ref.type == prog.kw_in      or
914
               ref.type == prog.parameter  or
915
               ref.type == prog.expression or
916
               ref.type == prog.lparens
917
               
918
               <action>ref = ref.getChildAt(0)</action>
919
            </while>
920
            
921
            <!-- if unknown val, the classname is the parameter's type -->
922
            <rule>ref.type == prog.unknown_val or
923
                  (ref.type == prog.expression and downPath(ref, prog.unknown_val))
924
               <action>wrapper = ecw.expressionType(ref)</action>
925
               
926
               <rule>wrapper != null
927
                  <rule>wrapper.equals("unknown") or wrapper.equals("BaseDataType")
928
                     <action>wrapper = null</action>
929
                  </rule>
930
                  <rule>wrapper != null and wrapper.equals("WrappedResource")
931
                     <action>wrapper = "handle"</action>
932
                  </rule>
933
               </rule>
934
               
935
               <!-- SET-DB-CLIENT's second parameter is poly (integer or character) - so force
936
                    a 'character' wrapper for an unknown value -->
937
               <rule>oldtype == prog.kw_set_dbcl and ref.indexPos == 1
938
                  <action>wrapper = "character"</action>
939
               </rule>
940
               
941
               <!--  CLIENT-PRINCIPAL:INITIALIZE --> 
942
               <rule>oldtype == prog.kw_init_c_p and ref.indexPos == 1
943
                  <action>wrapper = "character"</action>
944
               </rule>
945

    
946
               <rule>oldtype == prog.kw_init_c_p and ref.indexPos == 2
947
                  <action>wrapper = "datetimetz"</action>
948
               </rule>
949

    
950
               <!-- use 'rowid' for unknown val -->
951
               <rule>oldtype == prog.kw_repos_2i
952
                  <action>wrapper = "rowid"</action>
953
               </rule>
954

    
955
               <rule>wrapper != null
956
                  <rule>downPath(ref, prog.unknown_val)
957
                     <action>lref = ref.getFirstChild()</action>
958
                     <action on="false">lref = ref</action>
959
                  </rule>
960
                  
961
                  <action>lref.putAnnotation("classname", wrapper)</action>
962
               </rule>
963
            </rule>
964

    
965
            <!-- mark literals which need to be wrapped -->
966
            <rule>wrapper == null
967
               <rule>ref.parent.type == prog.expression
968
                  <action>lref = ref.parent</action>
969
                  <action on="false">lref = ref</action>
970
               </rule>
971

    
972
               <rule>
973
                  evalLib("literals", ref.type) and !evalLib("compiler_constants", ref.type)
974
                  <!-- in this case, the classname annotation will not be set, but change the 
975
                       wrapper so no warning is shown -->
976
                  <action>wrapper = "bogus"</action>
977
                  <rule>evalLib("needs_wrapped_literals", oldtype,  this.indexPos)
978
                     <!-- mark this literal so it will be wrapped. this mustn't use the 
979
                          expected type, as we must get compile errors if wrong literal is 
980
                          passed to a parameter (i.e. integer literal for character parameter)
981
                          -->
982
                     <action>lref.putAnnotation("wrap", true)</action>
983
                  </rule>
984
               </rule>
985
            </rule>
986
            
987
            <!-- all other cases - check if the type of the parameter's expression can be determined -->
988
            <rule>wrapper == null and !pref.isAnnotation("supportsPolyParameter")
989
               <!-- see if we can determine the type without context analysis -->
990
               <action>wrapper = ecw.expressionType(ref, false)</action>
991
               
992
               <!-- if the HANDLE attribute is passed as a parameter to a function or method call,
993
                    then it needs to be wrapped in a handle instance. -->
994
               <rule>wrapper != null and wrapper.equals("WrappedResource")
995
                  <action>ref.putAnnotation("wrap_parameter", true)</action>
996
                  <action>ref.putAnnotation("classname", "handle")</action>
997
               </rule>
998
                  
999
               <!-- indeterminate types need wrapping -->
1000
               <rule>wrapper == null or wrapper.equals("BaseDataType")
1001
               
1002
                  <!-- use our context this time, to get the type -->
1003
                  <action>wrapper = ecw.expressionType(ref, true)</action>
1004
                  
1005
                  <!-- lookup the type that the containing function requires -->
1006
                  <action>needed = parameterTypeName(pref, copy.indexPos, true)</action>
1007
                  
1008
                  <!-- deal with dynamic-function casttype cases to avoid unnecessary wrapping -->
1009
                  <rule>
1010
                     evalLib("type_pair", ref, prog.func_poly, prog.kw_dyn_func) and
1011
                     ref.isAnnotation("casttype")
1012
                     <action>casttype = ref.getAnnotation("casttype")</action>
1013
                     <action on="false">casttype = null</action>
1014
                  </rule>
1015
                  
1016
                  <!-- the wrapper must be assignment compatible with what is needed by the
1017
                       function/method, if not we coerce the type here -->
1018
                  <rule>needed != null and !ecw.isAssignmentCompatible(wrapper, needed)
1019
                     <action>wrapper = needed</action>
1020
                  </rule>
1021
                  
1022
                  <!-- the wrapper has to be something wrappable;  we bypass wrapping for the
1023
                       ternary operands (2 and 3) because we will wrap downstream if needed;
1024
                       we bypass dynamic-function wrapping if the type is known AND is assignment
1025
                       compatible with the wrapper (which must already be known to be assignment
1026
                       compatible with what is needed) -->
1027
                  <rule>
1028
                     wrapper != null                                                       and
1029
                     !wrapper.equals("unknown")                                            and
1030
                     !wrapper.equals("BaseDataType")                                       and
1031
                     (casttype == null or !ecw.isAssignmentCompatible(wrapper, casttype))  and
1032
                     !(evalLib("type_pair", pref, prog.func_poly, prog.kw_if) and copy.indexPos &gt; 0)
1033
                       
1034
                     <!-- mark this node, so that we can wrap it in expressions.rules -->
1035
                     <action>ref.putAnnotation("wrap_parameter", true)</action>
1036
                     <action>ref.putAnnotation("classname", wrapper)</action>
1037
                  </rule>
1038
                  
1039
                  <!-- bypass error below, since this is not an indeterminate case -->
1040
                  <action on="false">wrapper = "bogus"</action>
1041
               </rule>
1042
            </rule>
1043
            
1044
            <!-- do not show warnings for functions which accept unknown or can handle _Poly parameters -->
1045
            <rule>wrapper == null             and 
1046
                  oldtype != prog.kw_dyn_func and 
1047
                  oldtype != prog.kw_super    and
1048
                  !copy.parent.isAnnotation("supportsPolyParameter")
1049
               <action>
1050
                  printfln("WARNING: Could not determine wrapper for parameter %d [%s] for function/method %s [%d] @%d:%d.",
1051
                           copy.indexPos,
1052
                           copy.lookupTokenName(ref.type),
1053
                           copy.lookupTokenName(oldtype),
1054
                           pref.id,
1055
                           pref.line,
1056
                           pref.column)
1057
               </action>
1058
            </rule>
1059
         </rule>
1060

    
1061
      </walk-rules>
1062
      
1063
      <ascent-rules>
1064
         <rule>this.type == prog.enum_def
1065
            <action>lastid = getSectionAnchor(java.cs_instance_vars).id</action>
1066
            <action>pref = this.getAncestor(-1)</action>
1067
            <action>qual_oo = pref.getAnnotation("qualified_oo_name")</action>
1068
            
1069
            <action>createStaticImport("com.goldencode.p2j.report.ReportConstants.*")</action>
1070
            <action>createStaticImport("com.goldencode.p2j.util.InternalEntry.Type")</action>
1071
            
1072
            <!-- emit the GetEnum static methods -->
1073
            <action>ref = getSectionAnchor(java.cs_static_methods)</action>
1074
            <action>
1075
               tw.graftAt("enum_static_getenum_methods", null, ref.parent.id, ref.indexPos,
1076
                          "classname", classname,
1077
                          "qualified", qual_oo.toLowerCase())
1078
            </action>
1079
            <action>ref.remove()</action>
1080

    
1081
            <!-- this is no longer being used -->
1082
            <!-- emit the SetFlag/ToggleFlag/UnsetFlag methods -->
1083
            <!--
1084
            <rule>flagsEnum
1085
               <action>ref = getSectionAnchor(java.cs_instance_methods)</action>
1086
               <action>
1087
                  tw.graftAt("enum_instance_bitflag_methods", null, ref.parent.id, ref.indexPos,
1088
                             "classname", classname,
1089
                             "qualified", qual_oo.toLowerCase())
1090
               </action>
1091
               <action>ref.remove()</action>
1092
            </rule>
1093
            -->
1094
            
1095
            <!-- emit a static constructor -->
1096
            <action>ref = getSectionAnchor(java.cs_constructors)</action>
1097
            <action>ref = createJavaAst(java.block, "", ref)</action>
1098
            <action>ref.putAnnotation("static", true)</action>
1099
            <action>ref.putAnnotation("constructor", true)</action>
1100
            <action>copy.parent.putAnnotation("static_ctor", ref.id)</action>
1101

    
1102
            <!-- register the enum -->
1103
            <action>
1104
               tw.graft("enum_register", null, ref.id, "classname", classname, "name", qual_oo)
1105
            </action>
1106
            <action>createJavaAst(java.skip, "", ref)</action>
1107
            
1108
            <!-- emit a 2-arg private constructor -->
1109
            <action>ref = getSectionAnchor(java.cs_constructors)</action>
1110
            <action>tw.graft("enum_constructor", null, ref.id, "classname", classname)</action>
1111
         </rule>
1112
         
1113
         <rule>this.type == prog.kw_convert and 
1114
               upPath(this, prog.statement, prog.kw_cpy_lob)
1115
            <rule>downPath(this, prog.kw_source) and downPath(this, prog.kw_target)
1116
               <!-- standardize the order -->
1117
               <rule>this.firstChild.type == prog.kw_target
1118
                  <action>ref = copy.firstChild</action>
1119
                  <action>ref.move(copy, 1)</action>
1120
               </rule>
1121
               
1122
               <rule on="false">not downPath(this, prog.kw_source)
1123
                  <!-- create a CONVERT SOURCE ?, which will ignore it -->
1124
                  <action>ref = copy.firstChild</action>
1125
                  <action>ref = ref.duplicateFresh()</action>
1126
                  <action>copy.graftAt(ref, 0)</action>
1127

    
1128
                  <action>ref.type = prog.kw_source</action>
1129
                  <action>ref = ref.getImmediateChild(prog.expression, null)</action>
1130
                  <action>ref.putAnnotation("classname", "character")</action>
1131
                  <action>ref.removeChildren()</action>
1132
                  <action>ref = createProgressAst(prog.unknown_val, "?", ref)</action>
1133
                  <action>ref.putAnnotation("is-literal", true)</action>
1134
                  
1135
               </rule>
1136
            </rule>
1137
         </rule>
1138
         
1139
         <rule>evalLib("function_calls") or evalLib("oo_call_type", this, null)
1140
            <action>deleteScope("function")</action>
1141
         </rule>
1142
      </ascent-rules>
1143
      
1144
   </rule-set>
1145
   
1146
   <!-- persist both the source and target ASTs since new cross-references
1147
        exist bidirectionally -->
1148
   <rule-set load-condition="runtime-query">
1149
      <post-rules>
1150
         <rule>ooLangImp != null and ooLangImp
1151
            <action>createImport("com.goldencode.p2j.oo.lang.*")</action>
1152
         </rule>
1153

    
1154
         <rule>persist()</rule>
1155
         <rule>persistJavaFile()</rule>
1156
      </post-rules>
1157
   </rule-set>
1158
</cfg>