Wiki

Ticket #275: java-jvm-part3.patch

File java-jvm-part3.patch, 21.5 KB (added by hopscc, 7 years ago)
  • Source/Cobra.Lang/Java/mkjar

     
    44# copy them and std sig files to Source dir  
    55 
    66[ -d classes ] || mkdir classes 
    7 javac -d classes CobraImp.java CobraCore.java 
     7javac -d classes CobraImp.java CobraCore.java Delegate.java 
    88[ $? == 0 ] || exit 
    99jar cvf CobraLang.jar -C classes . 
    1010[ $? == 0 ] || exit 
  • Source/Cobra.Lang/Java/Delegate.java

     
     1/* 
     2 * Start of a Delegate baseclass for Cobra implemented for Java 
     3 * The cobra compiler java backend will be reponsible for mapping the construction, initialisation and  
     4 *  invocation of a Delegate to the API below 
     5 *  construct sig delName(param as paramType0,...) as retType   -> d = new Delegate(retType, paramType0, ...) 
     6 *  assign    myDelegate as delName = ref inst.method             -> d.init(inst, "method") 
     7 *  call      myDelegate(arg0,...)                                -> d.invoke(arg0,...)   
     8 * 
     9 * Doesnt support Generics. 
     10 * 
     11 * TODO: write some Tests exercising this implementation api 
     12 */ 
     13 
     14package cobra.lang; 
     15 
     16import java.lang.*; 
     17import java.util.*; 
     18import java.lang.reflect.*; 
     19 
     20public class Delegate { 
     21    Class returnType;   //  method returnType 
     22    Class[] paramTypes;  // Types of the method parameters  
     23     
     24    Class targetClass; 
     25    Object target; 
     26    String methodName; 
     27    Method method; 
     28     
     29    protected List<Delegate> multiCastList; 
     30     
     31    /* 
     32     * A Delegate is a Type describing a method signature (returnType and ParamTypes) that can hold a 
     33     * method and target to invoke it on (instance or static). Start with recording the signature 
     34     */ 
     35    public Delegate(Class returnType, Class... paramTypes) { 
     36        this.returnType = returnType; 
     37        this.paramTypes = paramTypes; 
     38    } 
     39     
     40    /* 
     41     * Initialise to a instance method on a particular target object 
     42     */ 
     43    public void init(Object target, String methodName){ 
     44        this.target = target; 
     45        this.targetClass = target.getClass(); 
     46        this.methodName = methodName; 
     47        matchMethod(); 
     48    } 
     49 
     50    /* 
     51     * initialise to a static method (on a target class) 
     52     */ 
     53    public void init(Class targetClass, String methodName){ 
     54        this.targetClass = targetClass; 
     55        this.methodName = methodName; 
     56        matchMethod(); 
     57    } 
     58     
     59     
     60    /* 
     61     * Ensure that there is a match for the given method name, return type and paramtypes on the target given. 
     62     * Record the Method and make accessible for later invocation 
     63     */ 
     64    @SuppressWarnings("unchecked")  
     65    void matchMethod() { 
     66        Class mclass = this.targetClass; 
     67        for(;;) { 
     68            try { 
     69                this.method = mclass.getDeclaredMethod(this.methodName, this.paramTypes); 
     70                this.method.setAccessible(true); 
     71                this.targetClass = mclass;               
     72                break; 
     73            } catch(NoSuchMethodException e) { 
     74                if (mclass == Object.class) { 
     75                    throw new RuntimeException(e); 
     76                } else { 
     77                    mclass = mclass.getSuperclass(); 
     78                } 
     79            } 
     80        } 
     81        Class methodType =  this.method.getReturnType(); 
     82        if ( ! isCompatibleType(this.returnType, methodType)) { 
     83             String msg = "NoSuchMethodException "+this.methodName + ":" ; 
     84             msg += "method returnType" + methodType.getName() + " not compatible with Delegate returnType " + this.returnType.getName(); 
     85             throw new RuntimeException(new NoSuchMethodException(msg)); 
     86        } 
     87    } 
     88     
     89    /** Maps primitives to their corresponding wrappers and vice versa. */ 
     90    private static final Map<Class,Class> PRIMITIVES_MAP = new HashMap<Class,Class>(); 
     91   
     92    static { 
     93        PRIMITIVES_MAP.put(boolean.class, Boolean.class); 
     94        PRIMITIVES_MAP.put(byte.class, Byte.class); 
     95        PRIMITIVES_MAP.put(char.class, Character.class); 
     96        PRIMITIVES_MAP.put(double.class, Double.class); 
     97        PRIMITIVES_MAP.put(float.class, Float.class); 
     98        PRIMITIVES_MAP.put(int.class, Integer.class); 
     99        PRIMITIVES_MAP.put(long.class, Long.class); 
     100        PRIMITIVES_MAP.put(short.class, Short.class); 
     101        PRIMITIVES_MAP.put(Boolean.class, boolean.class); 
     102        PRIMITIVES_MAP.put(Byte.class, byte.class); 
     103        PRIMITIVES_MAP.put(Character.class, char.class); 
     104        PRIMITIVES_MAP.put(Double.class, double.class); 
     105        PRIMITIVES_MAP.put(Float.class, float.class); 
     106        PRIMITIVES_MAP.put(Integer.class, int.class); 
     107        PRIMITIVES_MAP.put(Long.class, long.class); 
     108        PRIMITIVES_MAP.put(Short.class, short.class);     
     109    } 
     110     
     111    private boolean isCompatibleType(Class<?> c1, Class<?> c2) { 
     112        return c1 == c2 || c1 == PRIMITIVES_MAP.get(c2) || c1.isAssignableFrom(c2)  
     113              || c2.isAssignableFrom(c1); 
     114    } 
     115     
     116     /** 
     117     * Executes the method synchronously on the calling thread and returns the  
     118     * result value. 
     119     * @param arguments Values to pass to the method. 
     120     * @return Result of calling the method. 
     121     */ 
     122    public Object invoke(Object... arguments) { 
     123        assert this.method != null; 
     124        Object result = null; 
     125        try {             
     126            result = this.method.invoke(this.target, arguments); 
     127        } catch(IllegalAccessException e) { 
     128            throw new RuntimeException(e); 
     129        } catch(InvocationTargetException e) { 
     130            throw new RuntimeException(e.getCause()); 
     131        } 
     132        if ( !this.multiCastList.isEmpty()) { 
     133            for (Delegate d : this.multiCastList) { 
     134                result = d.invoke(arguments); 
     135            } 
     136        } 
     137        return result;       
     138    } 
     139     
     140    /* 
     141     * Add an additional Delegate to make a multicast invocation List on a single Delegate. 
     142     * The original Delegate is not inserted in the multicast List 
     143     */ 
     144    public void add(Object target, String methodName){ 
     145        Delegate d = new Delegate(this.returnType, this.paramTypes); 
     146        if (target instanceof Class) 
     147            d.init((Class)target, methodName); 
     148        else 
     149            d.init(target, methodName); 
     150 
     151        if (this.multiCastList == null) { 
     152            this.multiCastList = new ArrayList<Delegate>(); 
     153        } 
     154        this.multiCastList.add(d); 
     155    } 
     156     
     157    /* 
     158     * Remove an entry from a multicast invocation List. 
     159     */ 
     160    public void remove(Object target, String methodName){ 
     161        if (this.multiCastList == null || this.multiCastList.isEmpty()) { 
     162            return; 
     163        } 
     164        Delegate found = null; 
     165        for (Delegate d : this.multiCastList) { 
     166            if (d.target == target && d.methodName == methodName) { 
     167                found = d; 
     168                break; 
     169            } 
     170        } 
     171        if (found != null) { 
     172            this.multiCastList.remove(found); 
     173        } 
     174             
     175    } 
     176}     
  • Source/Cobra.Lang/Java/CobraImp.java

     
    77package cobra.lang; 
    88 
    99import java.lang.*; 
     10import java.util.*; 
    1011 
    1112  
    1213public class CobraImp { 
  • Source/Cobra.Lang/Java/mkjarAll

     
    55 
    66echo 'making RTL from java sources' 
    77[ -d classes ] || mkdir classes 
    8 javac -d classes CobraImp.java CobraCore.java 
     8javac -d classes CobraImp.java CobraCore.java Delegate.java 
    99[ $? == 0 ] || exit 
    1010jar cvf CobraLang.jar -C classes . 
    1111[ $? == 0 ] || exit 
  • Source/BackEndJvm/to-do.text

     
    2424    DONE 31-Jan-2011 
    2525    Unworkable  Jul-2011 - cobra assumptions in code 
    2626    Change to cobra casing  8-Jul-2011 
    27      
     27        revisit later (all lowcase) - backend variances on .canBeUndottedMemberName?? 
    2828 
    2929java names lowcase  
    3030    method Names  - DONE 31-Jan-2011 
     
    4343 
    4444properties - pro/get/set 
    4545    - auto convert to java getters/setters and map calls 
    46     - Whats the equiv for indexers 
     46    - Whats the equiv for indexers? 
    4747        Look at Beans spec but otherwise use/convert to {get,set}Indexer method call. 
    4848            <indexedT> getIndexer<T, indexedT>(T) and  
    4949                       setIndexer<T, indexedT>(T, indexedT) 
    5050      DONE  
    5151        
    52      codegen for props: 'propName' -> getPropName  and setPropName 
     52     codegen for props: 'propName' -> getPropName  (DONE) 
     53                                      setPropName   convert propName = a.b.c -> setPropName(a.b.c) (DONE - minimally at least) 
    5354 
    5455    AutoMap map indexers '[]' to methods X.get(idx) v = X[idx] , X.set(idx,val) and X.put(idx,val) -> X[idx] = val 
    5556        - unworkable - too many false positives 
     
    260261     
    261262 
    262263Delegates  
     264    Need some sort of placeholder for setProperties 
     265        Drop something into CobraCore - Cobra.Lang.Delegate? (DONE) 
     266     
     267    Delegate - dcl - returnType and paramList   d = new Delegate( Class ret, Class... paramList) 
     268                                                    - store ret and paramList types 
     269             - init (assign) method ref         d.init( Object target, String methodName) 
     270                                                d.init( Class target, String methodName) 
     271                                                    lookup target MethodName chk param types match, 
     272                                                    get and store its Method m and Object target 
     273             - call                             d.invoke(Object... paramList) 
     274                                                    m.invoke(target, paramList) 
     275              
    263276 
    264277Events 
    265     wot to do 
     278    wot to do? 
    266279 
    267280 
    268281Exception Adaption 
  • Source/BackEndJvm/JvmBackEnd.cobra

     
    1919            'String'    :       'Java.Lang.String', 
    2020            'Exception' :       'Java.Lang.RuntimeException', 
    2121 
    22             'Delegate'  :       'System.Delegate', #cobra.lang.Delegate 
     22            'Delegate'  :       'Cobra.Lang.Delegate', 
    2323            'Attribute' :       'Java.Lang.Annotation.Annotation', 
    2424            'ICloneable':       'Java.Lang.Cloneable',  
    2525            'IEnumerable':      'Java.Lang.Iterable', 
  • Source/BackEndJvm/JavaGenerator.cobra

     
    8181            outName = .computeOutNameJava 
    8282             
    8383            # compute backEndOptions 
    84             backEndOptions = '-d .'     # Put namespaced classfiles in own hierarchy 
     84            backEndOptions = '-d . '            # Put namespaced classfiles in own hierarchy 
     85            backEndOptions += ' -Xlint:all '    # warn about everything (non std option) 
    8586 
    8687            # -optimize isn't supported by JVM, but it could potentially be used by Cobra itself 
    8788             
     
    648649        return 'null' 
    649650 
    650651    get javaRef as String is override 
    651         return _wrappedType.javaRef + if(not _wrappedType.isReference, '?', '') 
     652        return _wrappedType.javaRef + if(not _wrappedType.isReference, ' /*?*/ ', '') 
    652653 
    653654 
    654655class NilType is partial 
     
    13991400                if not local.isImplicit 
    14001401                    sw.write('[local.type.javaRef] [local.javaName]') 
    14011402                    init = local.type.javaInit 
    1402                     if init.length, sw.write(' = [init]') 
     1403                    if init.length 
     1404                        if not local.type.isReference and init == 'null' 
     1405                            pass 
     1406                        else 
     1407                            sw.write(' = [init]') 
    14031408                    sw.write(';\n') 
     1409            sw.write('// end locals\n\n') 
    14041410 
    14051411    def writeJavaRequireParamDecls(sw as CurlyWriter) 
    14061412        sep = '' 
     
    16351641# efforts to correct this stupidity seem to be mired in language navel gazing plus associated  
    16361642# belly button lint picking followed by mastubatory dick waving to find the most obscure and difficult  
    16371643# corner cases which then leads to it being then dropped in the 'too hard' basket 
    1638 # Historically and currently it instead uses a convention which leads to a whole lot of obfuscating boilerplate code 
    1639 #   Its obviously too difficult to just copy C# (turnabout is fair play), accept and then evolve any edge misses  
     1644# Historically and currently it instead uses a convention on paired methodNames which leads to a whole lot of obfuscating boilerplate code 
     1645# Its obviously too difficult to just copy C# (turnabout is fair play), accept and then evolve any edge misses  
    16401646 
    16411647class ProperDexer is partial 
    16421648    # AbstractBaseClass for Property and Indexer 
     
    18791885        _expr.writeJavaDef(sw) 
    18801886        #_expr.writeJavaBreakdown(sw) 
    18811887        #sw.write('[.javaThis]') 
     1888        sw.write(' : ') 
    18821889        if _info 
    1883             sw.write(' : ') 
     1890            sw.write('"') 
    18841891            _info.writeJavaDef(sw) 
    1885         else        # Tmp till get java asserts 
    1886             sw.write(' : ') 
    1887             sw.write('" assert ') 
    1888             _expr.writeJavaDef(sw) 
     1892            sw.write('"') 
     1893        else 
     1894            sw.write('"assertion ') 
     1895            tmpsw = CurlyWriter(StringWriter(), sw.curlyLineNumberTreatment) 
     1896            _expr.writeJavaDef(tmpsw) 
     1897            sw.write(tmpsw.toString.replace('"', r'\"')) 
    18891898            sw.write(' FAILED"') 
    1890              
    18911899        sw.write(';\n') 
    18921900        sw.dedent 
    18931901 
     
    29722980 
    29732981 
    29742982class AssignExpr is partial 
    2975  
     2983     
     2984    var isJavaSetProperty = false 
     2985     
    29762986    def _writeJavaDef(sw as CurlyWriter) is override 
    29772987        # TODO: 
    29782988        # if trackLocal: 
     
    30193029            # for something like "p.total = 0", cannot generate "(p.Total)=0" because then C# sees 
    30203030            # the left hand side as an r-value instead an l-value/target. hence the false below. 
    30213031            _left.writeJavaDef(sw, false) 
    3022         sw.write('=') 
    3023         _right.writeJavaDefInContext(sw) 
     3032        if .isJavaSetProperty # set in MemberExpr.writeJavaDef 
     3033            sw.write('(') 
     3034            _right.writeJavaDefInContext(sw) 
     3035            sw.write(')') 
     3036        else 
     3037            sw.write('=') 
     3038            _right.writeJavaDefInContext(sw) 
    30243039        # handle the case where a type got backed up because of assignment inside of an if-inherits 
    30253040        if _backUpIfInheritsStack 
    30263041            assert _left.definition inherits IVar 
     
    33133328 
    33143329    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
    33153330        assert .superNode inherits DotExpr 
    3316         if _definition inherits BoxMember 
    3317             name = _definition.binaryName 
    3318         #if name is nil 
    3319         #   name = _name.capitalized 
    3320         if name is nil 
    3321             name = _name 
     3331        if _definition inherits BoxMember, name = _definition.binaryName 
     3332        if name is nil, name = _name 
    33223333        #print 'Dbg: MemberExpr::', name 
    33233334        if _definition inherits Property 
    3324             xet='get' 
    3325             if _isLValue, xet = 'set' 
    3326             sw.write(xet+name) 
    3327             sw.write('()') 
     3335            lValue = _setPropInAssignExpr 
     3336            if lValue 
     3337                # TODO chk for use of 'is' prefixed props 
     3338                xet = 'set' 
     3339                sw.write(xet+name) 
     3340                lValue.isJavaSetProperty = true # flag assignExpr for remainder of setProp handling 
     3341            else 
     3342                xet = 'get' 
     3343                sw.write(xet+name) 
     3344                sw.write('()') 
    33283345        else 
    33293346            sw.write(name) 
    3330             if _definition and (_definition.isMethod or _name=='toString') and not _isReference  # TODO: axe the 'toString' check 
     3347            if _definition and (_definition.isMethod or _name=='toString') and not _isReference  
    33313348                sw.write('()') 
    33323349 
    3333     def _isLValue as bool 
     3350    def _setPropInAssignExpr as AssignExpr? 
     3351        """ Return ancestor assignExpr if member is the lvalue in an AssignExpr, nil otherwise.""" 
    33343352        if not (.superNode and .superNode inherits BinaryOpExpr) 
    3335             return false 
     3353            return nil 
    33363354        bsn0 = this to INode 
    33373355        bsn  = .binarySuperNode 
    33383356        while true 
    33393357            if bsn inherits AssignExpr and bsn0 is bsn.left 
    3340                 return true 
     3358                return bsn to AssignExpr 
    33413359            if not (bsn.superNode and bsn.superNode inherits BinaryOpExpr) 
    3342                 return false 
     3360                return nil 
    33433361            bsn0 = bsn 
    33443362            bsn = bsn.binarySuperNode 
    33453363             
    33463364    def writeJavaBreakdownItems(sw as CurlyWriter) is override 
    33473365        pass 
    33483366 
     3367 
     3368class OldExpr 
     3369    is partial 
     3370 
     3371    var _javaVarName as String? 
     3372    pro javaVarName from var 
     3373 
     3374    def writeJavaAssignment(sw as CurlyWriter) 
     3375        require 
     3376            .didBindImp 
     3377            .javaVarName 
     3378            .type 
     3379        body 
     3380            sw.write('[.type.javaRef] [_javaVarName] = ') 
     3381            _expr.writeJavaDef(sw) 
     3382            sw.write(';\n') 
     3383 
     3384    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     3385        assert _javaVarName 
     3386        # this gets called when generating the `ensure` code 
     3387        sw.write(_javaVarName) 
     3388         
     3389 
     3390class PostCallExpr 
     3391    is partial 
     3392 
     3393    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     3394        if _helperMethod 
     3395            sw.write(_helperMethod.name + '(') 
     3396            sep = '' 
     3397            for arg in _args 
     3398                sw.write(sep) 
     3399                if arg inherits AssignExpr 
     3400                    arg = arg.right 
     3401                arg.writeJavaDefInContext(sw, false) 
     3402                sep = ',' 
     3403            sw.write(')') 
     3404        else 
     3405            if parens, sw.write('(') 
     3406            expr = _expr 
     3407            isMethodSig = false 
     3408            isDynamic = false 
     3409            if expr inherits TypeExpr 
     3410                if expr.containedType inherits ArrayType 
     3411                    # arrays 
     3412                    sw.write('new ') 
     3413                    sw.write((expr.containedType to ArrayType).theWrappedType.javaRef) 
     3414                    sw.write(r'[') 
     3415                    .writeJavaArgs(sw) 
     3416                    sw.write(r']') 
     3417                else 
     3418                    sw.write('new ') 
     3419                    expr.writeJavaDef(sw) 
     3420                    sw.write('(') 
     3421                    .writeJavaArgs(sw) 
     3422                    sw.write(')') 
     3423            else if expr inherits IdentifierExpr 
     3424                if expr.isTypeReference 
     3425                    sw.write('new ') 
     3426                    expr.writeJavaDef(sw) 
     3427                    sw.write('(') 
     3428                    .writeJavaArgs(sw) 
     3429                    sw.write(')') 
     3430                else if expr.receiverType inherits GenericParam # TODO: shouldn't expr.isTypeReference above have caught this? 
     3431                    sw.write('new [expr.receiverType.javaRef](') 
     3432                    .writeJavaArgs(sw) 
     3433                    sw.write(')') 
     3434                else if expr.type.nonNil.isDescendantOf(.compiler.delegateType) 
     3435                    isMethodSig = true 
     3436                else if expr.type.isSystemTypeClass or _type.isDynamic 
     3437                    isDynamic = true 
     3438                else 
     3439                    assert false, expr 
     3440            else if expr inherits IndexExpr 
     3441                if expr.type.nonNil.isDescendantOf(.compiler.delegateType) 
     3442                    isMethodSig = true 
     3443                else if expr.type.isSystemTypeClass or _type.isDynamic 
     3444                    isDynamic = true 
     3445                else 
     3446                    assert false, expr 
     3447            else 
     3448                assert false, expr 
     3449            if isMethodSig 
     3450                expr.writeJavaDef(sw, false) 
     3451                sw.write('.invoke(') 
     3452                .writeJavaArgs(sw) 
     3453                sw.write(')') 
     3454            else if isDynamic 
     3455                defi = expr.definition 
     3456                assert not defi inherits Box, expr  # TODO: just curious 
     3457                what = if(defi inherits IType, '([defi.javaName].class)', defi.javaName to String) 
     3458                whatType  = defi.javaName to String 
     3459                if defi inherits IVar 
     3460                    if defi.type.isDynamic 
     3461                        what = '(java.lang.Class)' + what 
     3462                #sw.write('System.Activator.CreateInstance([what]') 
     3463 
     3464                if _args.count  # maybe 
     3465                    sw.write('(<Constructor([whatType]>[what].getConstructor(') 
     3466                    .writeJavaArgs(sw, ', ') 
     3467                    sw.write(')).newInstance(') 
     3468                    .writeJavaArgs(sw, ', ') 
     3469                    sw.write(')') 
     3470                else     
     3471                    sw.write('[what].newInstance()') 
     3472                # maybe better do this 
     3473                #sw.write('cobra.lang.CobraImp.newInstance<[whatType]>([what],') 
     3474                #.writeJavaArgs(sw, ', ') 
     3475                #sw.write(')') 
     3476            if parens, sw.write(')') 
     3477 
     3478    def writeJavaArgs(sw as CurlyWriter) 
     3479        .writeJavaArgs(sw, '') 
     3480 
     3481    def writeJavaArgs(sw as CurlyWriter, sep as String) 
     3482        for arg in _args 
     3483            sw.write(sep) 
     3484            arg.writeJavaDefInContext(sw, false) 
     3485            sep = ',' 
     3486         
     3487    def writeJavaBreakdownItems(sw as CurlyWriter) 
     3488        base.writeJavaBreakdownItems(sw) 
     3489        sw.write(', +1') 
     3490        _expr.writeJavaBreakdownItems(sw) 
     3491        for expr in _args 
     3492            expr.writeJavaBreakdownItems(sw) 
     3493        sw.write(', -1') 
     3494 
     3495 
     3496class RefExpr 
     3497    is partial 
     3498 
     3499    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     3500        if parens 
     3501            sw.write('(') 
     3502        _expr.writeJavaDef(sw, false) 
     3503        if parens 
     3504            sw.write(')') 
     3505 
     3506    def writeJavaBreakdownItems(sw as CurlyWriter) 
     3507        base.writeJavaBreakdownItems(sw) 
     3508        # TODO 
     3509 
    33493510class SharpExpr 
    33503511    is partial 
    33513512 
     
    33813542    get javaInvariantVisibility as String is override 
    33823543        return '' 
    33833544 
    3384 class OldExpr is partial 
    3385  
    3386     def writeJavaAssignment(args as vari dynamic) 
    3387         pass 
    3388  
    3389     get javaVarName as String 
    3390         return '' 
    3391          
    33923545class Utils is partial 
    33933546 
    33943547    shared 
  • Tests/100-basics/034j-set-property.cobra

     
     1# .require. jvm 
     2namespace Test 
     3    class Test 
     4        def main is shared 
     5            # this would be ideal but its deprecated 
     6            # maybe use to test Attributes/Annotations when add handling for them 
     7            #d = Date() 
     8            #minutes = d.minutes    # d.getMinute 
     9            #d.minutes = minutes    # d.setMinute 
     10            #print d 
     11             
     12            fd = Java.Beans.FeatureDescriptor() 
     13            fd.name = 'Polly' 
     14            fd.shortDescription = 'Polly wolly Doodle' 
     15            #print 'FeatureDescriptor: [fd.getName], [fd.getShortDescription]' 
     16            name = fd.name 
     17            fd.name = '[name]nu' 
     18            #print 'FeatureDescriptor: [fd.getName], [fd.getShortDescription]' 
     19            assert fd.name == 'Pollynu' 
     20            assert fd.shortDescription == 'Polly wolly Doodle' 
     21