base_structure.xml
| 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 > prog.begin_functypes and
|
| 219 |
ref.type < prog.end_functypes and
|
| 220 |
ref.isAnnotation("builtin") and
|
| 221 |
#(java.lang.Boolean) ref.getAnnotation("builtin")) or
|
| 222 |
(ref.type > prog.begin_meth and
|
| 223 |
ref.type < 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 > prog.begin_attr and |
| 623 |
this.type < 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 > 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>
|