Wiki

Ticket #275: java-jvm-part2.patch

File java-jvm-part2.patch, 165.8 KB (added by hopscc, 7 years ago)
  • Source/BackEndJvm/JvmJarSig.cobra

     
     1# Java back end 
     2# Responsible for turning a jarfile name into an object holding a description/signature of 
     3# the jarfile contents suitable for reflecting on - this is roughly similar to a .Net Assembly. 
     4 
     5# Supporting this requires delving through java jar files and obtaining class info which we cant easily  
     6# do in a .Net program 
     7# so until we have a java implementation of the cobra compiler we instead rely on a java helper program 
     8# (see pkgSig.java and pkgSig.class, pkgSig.jar in the cobra distribution) 
     9 
     10# This is expected to have been run and creates what we call a pkgSignature file (pkgSig File) that is  
     11# named the same as a jarfile (or the same as a java package) with a '.sig' extension' and 
     12# contains an easily parseable text description of the classes and interfaces in the jarfile or package 
     13# this sigfile is expected to be in an obvious place, currently the cwd or same place as the cobra compiler executable.... 
     14# 
     15# e.g. 'rt.jar' (java runtime classes) has a sigfile 'rt.jar.sig' 
     16#   'java.lang' (java package) has a sigfile 'java.lang.sig' 
     17 
     18class JarSig 
     19     
     20    var name = '' # jarfile or pkg 
     21    var location = '' # abs pathname of sigFile 
     22    var _javaTypes as List<of JavaClassType> # lists of classes, interfaces or Enums in this jarfile or pkg 
     23     
     24    shared 
     25        var classByNameCache = Dictionary<of String, JavaClassType>() 
     26            """All classes found in all jars keyed by canonical/full name.""" 
     27                 
     28        def lookupClass(fullName as String) as JavaClassType 
     29            """ Lookup class by full/canonicalName.""" 
     30            if not JarSig.classByNameCache.containsKey(fullName) 
     31                if fullName.startsWith(r'['),     .addArrayClass(fullName) 
     32                else if fullName.contains(r'<'),  .addGenericInstClass(fullName) 
     33                else if not fullName.contains('.'), .addGenericParamClass(fullName) 
     34                else 
     35                    print 'Dbg:JarSig.lookupClass - unknown class:[fullName]' 
     36            #print 'Lookup class', fullName 
     37            return JarSig.classByNameCache[fullName] 
     38                     
     39        def addArrayClass(aName as String) 
     40            """Array classes are synthesized on reference assuming element class already exists.""" 
     41            print 'Dbg crt ArrayClass "[aName]"'     
     42            elName = aName.replace(r'[','')  
     43            branch elName 
     44                on 'Z', elName = 'boolean' 
     45                on 'B', elName = 'byte' 
     46                on 'I', elName = 'int' 
     47                on 'S', elName = 'short' 
     48                on 'J', elName = 'long' 
     49                on 'C', elName = 'char' 
     50                on 'D', elName = 'double' 
     51                on 'F', elName = 'float' 
     52                else  
     53                    if elName.startsWith('L') and elName.endsWith(';') 
     54                        elName = elName[1:-1] # e.g. Ljava.lang.Integer; 
     55                    else  
     56                        print 'Unknown arrayName [elName]'   
     57                        assert false, 'arrayName [elName]' 
     58            if not JarSig.classByNameCache.containsKey(elName) 
     59                print 'Dbg: class "[elName]" not in classByNameCache "[aName]"'      
     60            #elType = JarSig.classByNameCache[elName] 
     61            elType = JarSig.lookupClass(elName) 
     62            arrayCls = JavaClassType(aName, elType) # ArrayType 
     63            JarSig.classByNameCache[aName] = arrayCls 
     64            print 'Dbg: added ArrayOf_[elName] "[aName]"'    
     65         
     66        def addGenericInstClass(fullName as String) 
     67            """ 
     68            Generic class being instantiated. 
     69                e.g. com.x.MyClass<com.x.Inst, java.lang.String> 
     70            Synthesized (here) as a result of being referenced. 
     71            """ 
     72            print 'Dbg crt GenericInstClass "[fullName]"'  
     73            assert fullName.contains('<') and fullName.endsWith('>') 
     74            canonName = fullName.beforeL('<') 
     75            assert canonName.contains('.') 
     76            idx = canonName.lastIndexOf('.') 
     77            gName = canonName[idx+1:] 
     78            pkg = canonName[0:idx] 
     79            paramTypes = fullName.afterL('<')[0:-1] # drop end '>' 
     80            print 'Dbg: GenericInstanceClass "[pkg]" "[gName]" "[paramTypes]'    
     81            giCls = JavaClassType(gName, pkg, paramTypes) 
     82            JarSig.classByNameCache[fullName] = giCls 
     83            # JarSig.registerClassType(pkg, giCls)   
     84            print 'Dbg: added GenericInstanceClass "[fullName]"'     
     85                 
     86        def addGenericParamClass(name as String) 
     87            print 'Dbg crt Generic Param Class "[name]"'  
     88            gparamCls = JavaClassType(name, JavaType.GenericParam, '') 
     89            JarSig.classByNameCache[name] = gparamCls 
     90            print 'Dbg: added Generic Parameter Class "[name]"'      
     91                 
     92    def sigFile(name as String) as String is shared 
     93        """  
     94        Check that a sig file exists for the given name (jarfile or pkgname). 
     95        Return the sig filename if found, InvalidOperationException if not 
     96        """ 
     97        assert not name.endsWith('.sig')     
     98        sigFile =  name + '.sig' 
     99        if File.exists(sigFile) 
     100            fileName = sigFile 
     101            #if not Path.IsPathRooted(sigFile) 
     102            #   fileName = Path.getFullPath(sigFile) 
     103        else 
     104            ccPath = Path.getDirectoryName(CobraCore.exePath) to ! 
     105            absName =  Path.combine(ccPath, sigFile) 
     106            if File.exists(absName) 
     107                fileName = absName 
     108            else 
     109                throw InvalidOperationException('Cannot find a PkgSig file for "[name]" ("[sigFile]") in cwd or [ccPath].') 
     110        return fileName 
     111                     
     112    cue init(jarName as String) 
     113        base.init 
     114        .name = jarName 
     115        _javaTypes = List<of JavaClassType>() 
     116        _genTypesList 
     117        _aliasPrimitives 
     118 
     119    def _genTypesList 
     120        jarName = if(.name.endsWith('.sig'), .name[:-4], .name) 
     121        fileName = JarSig.sigFile(jarName) 
     122        .location = fileName 
     123        desc = List<of String>() 
     124        for line in File.readAllLines(fileName) 
     125            if line.trim.startsWith('#'), continue 
     126            if line.length == 0  
     127                if desc.count == 0, continue 
     128                jct = JavaClassType.makeFromDesc(desc) 
     129                _registerClassType(jct) 
     130                desc.clear 
     131                continue 
     132            desc.add(line) 
     133         
     134        if desc.count >0 
     135            jct = JavaClassType.makeFromDesc(desc) 
     136            _registerClassType(jct) 
     137             
     138    def _registerClassType(jct as JavaClassType) 
     139        _javaTypes.add(jct) 
     140        canonName = jct.canonicalName 
     141        if '`' in canonName # jct.isGeneric 
     142            canonName = canonName.beforeL('`') 
     143            #parts = canonName.split('`') 
     144            #canonName = parts[0]    
     145        JarSig.classByNameCache[canonName] = jct 
     146             
     147    def _aliasPrimitives 
     148        if JarSig.classByNameCache.containsKey('void') 
     149            return 
     150        # ['void', 'boolean','byte', 'short', 'int', 'long', 'float', 'double'] 
     151        JarSig.classByNameCache['void']    = JarSig.classByNameCache['java.lang.Void']  
     152        JarSig.classByNameCache['boolean'] = JarSig.classByNameCache['java.lang.Boolean']  
     153        JarSig.classByNameCache['char']    = JarSig.classByNameCache['java.lang.Character']  
     154        JarSig.classByNameCache['byte']    = JarSig.classByNameCache['java.lang.Byte']  
     155        JarSig.classByNameCache['short']   = JarSig.classByNameCache['java.lang.Short']  
     156        JarSig.classByNameCache['int']     = JarSig.classByNameCache['java.lang.Integer']  
     157        JarSig.classByNameCache['long']    = JarSig.classByNameCache['java.lang.Long']  
     158        JarSig.classByNameCache['float']   = JarSig.classByNameCache['java.lang.Float']  
     159        JarSig.classByNameCache['double']  = JarSig.classByNameCache['java.lang.Double']  
     160 
     161         
     162                 
     163    def getExportedTypes as JavaClassType* 
     164        return _javaTypes 
     165         
     166    def toString as String is override 
     167        """ For testing dump rep of jarSig""" 
     168        sb = StringBuilder('[.name]: ') 
     169        sb.append(' [_javaTypes.count] types') 
     170        return sb.toString 
     171     
     172# 
     173# Below are classes describing JavaTypes (class), JavaFields, Java Ctors and JavaMethods     
     174# They are temporary placeholders until can get a native implementation and direct access to Java RTL equivalents. 
     175 
     176enum JavaType 
     177    NoType, JavaClass, JavaInterface, JavaEnum, GenericParam 
     178     
     179 
     180class JavaClassType     # Simplified System Type for java classes, interface, enum 
     181    """ Descriptor for a java class - equivalent of java.lang.Class for cobra in .Net""" 
     182    shared  
     183        var emptyClassList  = List<of JavaClassType>() 
     184        var _emptyFieldList = List<of JavaFieldInfo>()       
     185        var _emptyCtorList  = List<of JavaCtorInfo>()    
     186        var _emptyMethodList = List<of JavaMethodInfo>()         
     187        var _emptyStringList = List<of String>()         
     188     
     189        def genClassTypeList(names as List<of String>)  as List<of JavaClassType> 
     190            """ Generate JavaClassType List for list of names.""" 
     191            classList = List<of JavaClassType>() 
     192            for name in names 
     193                cls = JarSig.lookupClass(name) 
     194                classList.add(cls) 
     195            return classList 
     196     
     197         
     198    var name = '' 
     199    var package = '' 
     200    var type = JavaType.NoType #class,interface, enum 
     201    var superclass = '' 
     202    var modifiers as List<of String> 
     203    var interfaceNames as List<of String> 
     204    var _interfaces as List<of JavaClassType> = JavaClassType.emptyClassList 
     205 
     206    var _fields as List<of JavaFieldInfo> = JavaClassType._emptyFieldList   # JavaFieldInfo* 
     207    var _props as List<of JavaFieldInfo>  = JavaClassType._emptyFieldList   # JavaFieldInfo* 
     208    var _ctors as List<of JavaCtorInfo>   = JavaClassType._emptyCtorList    # JavaCtorInfo* 
     209    var _methods as List<of JavaMethodInfo> = JavaClassType._emptyMethodList # JavaMethodInfo* 
     210 
     211    # TODO split these out as subclass 
     212    var _isGenericDefn = false   
     213    var _isGenericInst = false   
     214    var _isGenericParam = false  
     215    var _genParamNames as List<of String> = JavaClassType._emptyStringList 
     216    var _genParams as List<of JavaClassType> = JavaClassType.emptyClassList # generic params list 
     217    set genParamNames from var 
     218     
     219    var _isArray  = false    
     220    var _arrayDimension = 0  
     221    var _arrayComponentType as JavaClassType? = nil 
     222 
     223    def makeFromDesc(descriptor as List<of String>) as JavaClassType is shared 
     224        """ 
     225        Generate a populated JavaClassType from a string descriptor. 
     226         
     227        Descriptor entry for a Type (as per pkgSig output), single entry per line ( or '-' ), 
     228        entries nl terminated 
     229         
     230            <Type> <absolute classname> 
     231                <Type> # Class, Interface or Enum 
     232                <Pkg> 
     233                <Name> #simple Name 
     234                <absolute superclass name> 
     235                <absolute interface names implemented>  #comma separated 
     236                <modifiers>  # spc separated 'static', 'default', 'public', 'protected' 
     237                var <name>  # 0 or more fields  
     238                    <modifiers> 
     239                    <full TypeName> 
     240                    <attributes> 
     241                ...  
     242                ctor <absClassName> # 0 or more constructors 
     243                    <paramList> # comma sep list of typeNames 
     244                ...  
     245                method name # 0 or more methods 
     246                    modifiers 
     247                    returnType 
     248                    paramList 
     249                    throwsList 
     250                    ...                  
     251        Descriptor is parsed and info and various field, ctor, method and property lists populated. 
     252        """ 
     253         
     254        fieldList = List<of JavaFieldInfo>() 
     255        propList = List<of JavaFieldInfo>() 
     256        props = Dictionary<of String, JavaFieldInfo>() # cache for inferred propertyNames 
     257        ctorList = List<of JavaCtorInfo>() 
     258        methodList = List<of JavaMethodInfo>() 
     259         
     260        lines = descriptor 
     261        assert lines.count >= 7 
     262 
     263        # header - fixed length and format; absName, type, pkg, name, superclass, interfacesList, ModifiersList 
     264        absName  = _popTop(lines)   # absolute class name 
     265        CobraCore.noOp(absName) 
     266        branch _popTop(lines).toLower 
     267            on 'class',     type = JavaType.JavaClass 
     268            on 'interface', type = JavaType.JavaInterface 
     269            on 'enum',      type = JavaType.JavaEnum 
     270            else, type = JavaType.NoType 
     271        pkg  = _popTop(lines) 
     272        name = _popTop(lines) 
     273        isGen = name.contains('`') 
     274        super = _popTop(lines) 
     275        if super == '-', super = '' 
     276        interfaces = _parseList(_popTop(lines), [c',']) 
     277        modifiers  = _parseList(_popTop(lines), [c' ']) 
     278        if isGen, gParamNames = _parseList(_popTop(lines), [c',']) 
     279        while true 
     280            et = _popTop(lines) 
     281            if et.length == 0, break 
     282                 
     283            if et.startsWith('var ') 
     284                varName = et[3:].trim 
     285                field =  JavaFieldInfo() 
     286                field.name = varName 
     287 
     288                assert lines.count >= 2      
     289                # procField(et, subline, field, fieldList) 
     290                field.modifiers = _parseList(_popTop(lines), [c' ']) 
     291                field.typeName = _popTop(lines) 
     292                if type == JavaType.JavaEnum  
     293                    field.value = _popTop(lines)     
     294                #field.attributes = _parseList(_popTop(lines), [c',']) 
     295                fieldList.add(field) 
     296 
     297            else if et.startsWith('ctor ') 
     298                ctorName = et[4:].trim 
     299                ctor = JavaCtorInfo() 
     300                ctor.name = ctorName 
     301                assert lines.count >= 1      
     302                ctor.paramNames = _parseList(_popTop(lines), [c',']) 
     303                # attributes ?? 
     304                ctorList.add(ctor) 
     305                 
     306            else if et.startsWith('method ') 
     307                methodName = et[6:].trim 
     308                if methodName.endsWith(r'[V]') # hack encoding flags 
     309                    methodName = methodName[:-3] 
     310                    isVari = true 
     311                method = JavaMethodInfo() 
     312                method.name = methodName 
     313                method.modifiers = _parseList(_popTop(lines), [c' ']) 
     314                method.returnTypeName = _popTop(lines) 
     315                assert method.returnTypeName <> '-' 
     316                method.paramNames = _parseList(_popTop(lines), [c','])  
     317                method.throwsList = _parseList(_popTop(lines), [c','])  
     318                # attributes ?? 
     319                if isVari,  method.attributes = ['IsVari'] 
     320                methodList.add(method) 
     321 
     322                # map method getters and setters to property 
     323                propName = .chkForProp(methodName, method) 
     324                if propName 
     325                    _genProp(method, propName, propList, props) 
     326            else  
     327                print 'Unknown item in class: [et]' 
     328 
     329        jct = JavaClassType(name, pkg, type, super, interfaces, modifiers) 
     330        if isGen, jct.genParamNames = gParamNames 
     331        jct._fields = fieldList 
     332        jct._props  = propList 
     333        jct._ctors  = ctorList 
     334        jct._methods = methodList 
     335        return jct 
     336             
     337    def _parseList(et as String, seps as List<of char> ) as List<of String> is shared 
     338        if et == '-' 
     339            l = List<of String>() 
     340        else 
     341            l = et.split(seps.toArray).toList    
     342        return l 
     343     
     344    def _popTop(content as List<of String>) as String is shared  
     345        while true 
     346            if content.count == 0 
     347                return '' 
     348            e = content[0] 
     349            content.removeAt(0) 
     350         
     351            if e.trim.startsWith('#')   # commentline 
     352                continue 
     353            idx = e.indexOf('#')    # trailing comment 
     354            if idx >= 0  
     355                e = e[:idx]  
     356                e = e.trimEnd to ! 
     357                if not e.length, continue 
     358            break 
     359        return e.trim 
     360         
     361    # property: get<Propname> and no paramList and returnType is Property Type or 
     362    #           is<PropName> and no paramList and returnType is bool 
     363    #       and  set<PropName> and 1 parameter (value to set)  
     364    def chkForProp(methodName as String, method as JavaMethodInfo) as String? is shared 
     365        tag = methodName[:3]  
     366        if  tag in [ 'get', 'set'] and methodName.length > 3 and method.modifiers.contains('public') 
     367            if tag == 'set' and method.paramNames.count <> 1        # setXXXX without a single param 
     368                return nil 
     369            return methodName[3:] 
     370        if methodName.startsWith('is') and method.paramNames.count == 0 and method.returnTypeName == 'boolean' and method.modifiers.contains('public') 
     371            return methodName[2:] 
     372        return nil   
     373             
     374    # indexer: get<Propname> and has params  -  first param in paramList is index  (retType is Property Type) 
     375    #     or  set<PropName> and more than value in paramList, 1st parameter is index and second is value to set. 
     376    def isIndexer(methodName as String, method as JavaMethodInfo, isSetProp) as bool is shared 
     377        if methodName.startsWith('is') 
     378            return false 
     379        assert methodName.startsWith('get') or methodName.startsWith('set') 
     380        isGetProp = not isSetProp 
     381        return  (isGetProp and method.paramNames.count) or (isSetProp and method.paramNames.count > 1) 
     382 
     383    def _genProp(method as JavaMethodInfo, propName as String, propList as List<of JavaFieldInfo>, props as Dictionary<of String, JavaFieldInfo>) as JavaFieldInfo is shared 
     384        """ Create or update property fm getter/setter method and update given List and Dict. """ 
     385        assert method.name.startsWith('get') or method.name.startsWith('set') or method.name.startsWith('is')    
     386        isSetProp = method.name.startsWith('set') 
     387        isGetProp = not isSetProp 
     388        #print method.name, propName 
     389        if props.containsKey(propName) 
     390            prop = props[propName] 
     391        else # no existing property 
     392            prop = JavaFieldInfo() # JavaPropInfo 
     393            prop.name = propName 
     394            prop.isProp = true 
     395            prop.isIndexer = .isIndexer(method.name, method, isSetProp) 
     396            prop.isReadable = prop.isWritable = false 
     397            props[propName] = prop 
     398            propList.add(prop)   
     399            method.prop = prop 
     400            #print '-- new Prop' 
     401        if isGetProp  
     402            prop.isReadable = true 
     403            prop.getter = method 
     404            if not prop.typeName.length and method.returnTypeName.length, prop.typeName = method.returnTypeName 
     405            #prop.name0 = method.name 
     406            #print '-- isGetProp' 
     407        else #isSetProp  
     408            prop.isWritable = true 
     409            prop.setter = method 
     410            #print '-- isSetProp' 
     411            if not prop.typeName.length and method.paramNames.count, prop.typeName = method.paramNames[0] 
     412        if not prop.modifiers.count or not prop.modifiers[0].length, prop.modifiers = method.modifiers 
     413        if not prop.attributes.count,    prop.attributes = method.attributes 
     414        assert prop.name.length 
     415        assert prop.typeName.length 
     416        return prop 
     417             
     418    cue init(name as String, pkg as String, type as JavaType, super as String, ifcs as List<of String>, modifiers as List<of String> ) 
     419        """Create a normal Class or GenericClass Defn.   MyClass or MyClass<T>""" 
     420        base.init 
     421        assert not name.contains(".") 
     422        .name = name 
     423        .package = pkg 
     424        .type = type 
     425        .superclass = super 
     426        .interfaceNames = ifcs 
     427        .modifiers = modifiers 
     428     
     429        _isGenericDefn = name.contains('`')  # Generic types have name suffix  `<nGenericArgs> 
     430         
     431        #print '[type] [pkg].[name]' 
     432        assert .name.length 
     433        assert .type <> JavaType.NoType 
     434        if .type == JavaType.JavaClass and .canonicalName <> 'java.lang.Object'  
     435            assert '.' in .superclass # canonical form 
     436        assert .package.length 
     437         
     438    cue init(name as String, elementType as JavaClassType) 
     439        """Create an ArrayType.""" 
     440        base.init 
     441        .name = name 
     442        .package = elementType.package 
     443        .type = JavaType.JavaClass 
     444        .superclass = 'java.lang.Object' # not really - closest is javax.openmanagment.mbean.ArrayType 
     445            # maybe should fake up an Abstract ArrayBaseType providing methods, etc synthesized below 
     446        .modifiers = elementType.modifiers 
     447        .interfaceNames = JavaClassType._emptyStringList 
     448         
     449        _isArray = true 
     450        _arrayComponentType = elementType 
     451        _arrayDimension = name.count(c'[') 
     452         
     453        # has properties 'length' and method 'getLength' and indexer for get and set 
     454        methodList = List<of JavaMethodInfo>() 
     455        method = JavaMethodInfo() 
     456        method.name = 'getLength' 
     457        method.modifiers = ['public'] 
     458        method.returnTypeName = 'int' 
     459        method.paramNames =  JavaClassType._emptyStringList 
     460        methodList.add(method) 
     461     
     462        propList = List<of JavaFieldInfo>() 
     463        prop = JavaFieldInfo() 
     464        prop.name = 'length' 
     465        prop.typeName = 'int' 
     466        prop.modifiers = ['public'] 
     467        prop.isProp = true 
     468        prop.isIndexer = false 
     469        prop.isReadable = true 
     470        method.prop = prop 
     471        prop.getter = method 
     472        prop.isWritable = false 
     473        propList.add(prop)   
     474     
     475        idxr = JavaFieldInfo() 
     476        idxr.name = r'[]' 
     477        idxr.typeName = name.replace(r'[', r'') 
     478        idxr.modifiers = ['public'] 
     479        idxr.isProp = true 
     480        idxr.isIndexer = true 
     481        idxr.isReadable = true 
     482        idxr.isWritable = true 
     483        # TODO getter return type same as typeName 
     484        # TODO setter params List 'int'  
     485        propList.add(idxr)   
     486         
     487        _props  = propList 
     488        _methods = methodList 
     489 
     490        assert .name.length 
     491        assert .type <> JavaType.NoType 
     492        if .type == JavaType.JavaClass and .canonicalName <> 'java.lang.Object'  
     493            assert '.' in .superclass # canonical form 
     494        assert .package.length 
     495 
     496        assert _arrayDimension >0 
     497        assert _arrayComponentType 
     498        assert .name.contains(r'[') 
     499     
     500    cue init(name as String, pkg as String, paramTypes as String) 
     501        """Create a Generic Instantiation Type. Like MyClass<java.Lang.String>""" 
     502        base.init 
     503        print 'JavaClassType.init([name])' 
     504        assert not name.contains('.') 
     505        #assert pkg.contains('.') 
     506        gPart = '[pkg].[name]' 
     507        paramList = JavaClassType._parseList(paramTypes, [c',']) 
     508        print 'Looking for Generic Class [gPart]' 
     509        genType = JarSig.lookupClass(gPart) 
     510        assert genType.isGenericTypeDefinition 
     511 
     512        .name = name 
     513        .package   = pkg # genType.package 
     514        .type      = genType.type 
     515        .superclass = genType.canonicalName  # not really but thats how we'll fake it 
     516        #.superclass = 'java.lang.Object'  
     517        .modifiers = genType.modifiers 
     518        .package   = genType.package 
     519        _isGenericInst = true 
     520     
     521        .interfaceNames = JavaClassType._emptyStringList 
     522        _genParamNames= paramList 
     523     
     524        #print '[type] [pkg].[name]' 
     525        assert .name.length 
     526        assert .type <> JavaType.NoType 
     527        assert '`' in .superclass # fake parentage to the Generic Definition 
     528        assert .package.length 
     529     
     530    cue init(name as String, jType as JavaType, pkg as String) 
     531        """Create a Generic Parameter Type. Like the T of MyClass<T>""" 
     532        base.init 
     533        assert jType == JavaType.GenericParam  
     534        assert not name.contains("<") and not name.contains(">") 
     535        assert not name.contains(".") 
     536        #assert name[0].isUpper # ?? 
     537         
     538        .name = name 
     539        .type      = jType 
     540        .superclass = 'java.lang.Object' # not really but thats how we'll fake it 
     541        .package   = pkg 
     542        if not .package.length, .package = 'java.lang' 
     543        .modifiers = ['public'] 
     544             
     545        _isGenericParam = true 
     546     
     547        .interfaceNames = JavaClassType._emptyStringList 
     548     
     549        #print '[type] [pkg].[name]' 
     550        assert .name.length 
     551        assert .type <> JavaType.NoType 
     552        assert 'Object' in .superclass  
     553        assert .package.length 
     554         
     555 
     556    #pro name from var  
     557    #pro package from var 
     558    # ... 
     559 
     560    get canonicalName as String 
     561        """package and name""" 
     562        assert .name.length 
     563        return if(.package.length, '[.package].[.name]', .name) 
     564 
     565    get isClass as bool 
     566        return .type == JavaType.JavaClass 
     567         
     568    get isInterface as bool 
     569        return .type == JavaType.JavaInterface 
     570         
     571    get isEnum as bool 
     572        return .type == JavaType.JavaEnum 
     573         
     574    get isNested as bool 
     575        #return .flags.contains('N') 
     576        return .name.contains('$')  and not .name.startsWith('$') # temporary hack 
     577     
     578    get declaringType as JavaClassType? 
     579        if .isNested 
     580            assert .name.contains('$') 
     581            declName = .name.beforeL('$') 
     582            #idx = .name.indexOf('$')  
     583            #declName = .name[:idx]  
     584            trace declName 
     585            # return JarSig.classByNameCache[declName] 
     586            return JarSig.lookupClass(declName) 
     587        return nil 
     588         
     589    get isPublic 
     590        return .modifiers.contains('public') 
     591    get isProtected 
     592        return .modifiers.contains('protected') 
     593    get isPrivate 
     594        return .modifiers.contains('private') 
     595    get isDefault 
     596        return .modifiers.contains('default')   # = protected + package 
     597    get isStatic 
     598        return .modifiers.contains('static') 
     599    get isFinal # sealed  
     600        return .modifiers.contains('final') 
     601    get isAbstract 
     602        return .modifiers.contains('abstract') 
     603 
     604    def getSuperClass as JavaClassType? 
     605        if not .superclass.length 
     606            return nil 
     607        #return  JvmNativeType(_type.getSuperClass) 
     608        if JarSig.classByNameCache.containsKey(.superclass) 
     609            return JarSig.lookupClass(.superclass) 
     610            #return JarSig.classByNameCache[.superclass] 
     611        else  
     612            #return JarSig.classByNameCache['java.lang.Object'] 
     613            return JarSig.lookupClass('java.lang.Object') 
     614            # e.g. Abstract base classes with default access - java.lang.AbstractStringBuilder   
     615        #else  
     616        #   synth = SyntheticObject(.superclass) 
     617        #   JarSig.classByNameCache[.superclass] = synth 
     618        #   return synth 
     619                 
     620    get isValueType as bool 
     621        return false    # TODO true for unboxed primitives... 
     622 
     623    # TODO hops array handling 
     624    get isArray as bool 
     625        return _isArray  
     626 
     627    get arrayComponentType as JavaClassType? 
     628        #if not .isArray, return nil 
     629        assert .isArray 
     630        print 'JavaClassType Array support NYI [.canonicalName]' 
     631        return _arrayComponentType 
     632 
     633    get arrayDimension as int 
     634        require .isArray 
     635        assert _arrayDimension > 0 
     636        return _arrayDimension 
     637     
     638    # TODO hops Generics handling 
     639    # Two forms of Generic Types: Definition ( MyClass<T>) and Instantiation ( MyClass<java.lang.String>) 
     640    # In java with runtime generic Type instantiation all we see from the jarfile directly are definitions (:-( 
     641    # Walking the classes and getting the class(names) referenced (params, intefaces, returnTypes,...) 
     642    # gives us the names of the instantiations which we synthesize as Types or Params for our purposes... 
     643 
     644    get isGenericType as bool 
     645        return _isGenericDefn or _isGenericInst or _isGenericParam 
     646         
     647    get genericArgsCount as int 
     648        assert .isGenericType 
     649        #return _genArgNames.count # number of Generic args associated with this Generic Type 
     650        # We use dotNet naming here where generic (defn) classes are named with trailing '`<nTypeParams>' 
     651        if _isGenericDefn 
     652            parts = .name.split(c'`') 
     653            return int.parse(parts[1]) 
     654        else if _isGenericInst 
     655            return _genParamNames.count 
     656        else     
     657            return 0 
     658             
     659    get isGenericParameter as bool  
     660        """ 
     661        assumes generic parameters are instantiated as Types. 
     662        Things like T,U,E,.. - basically simple names not package specified - probably 1 Upcase char  
     663        """ 
     664        return _isGenericParam 
     665     
     666    get isGenericTypeDefinition as bool 
     667        """  
     668        Can use this generic type to create new types if this type is a template form. 
     669        e.g myClass<T, U> defn allows creating new type like MyClass<String, int> 
     670        """ 
     671        assert  .isGenericType 
     672        return _isGenericDefn 
     673             
     674    def getGenericArguments as JavaClassType* #List<of JavaClassType> 
     675        assert .genericArgsCount 
     676        if false # tmp pending jarSig gen and loading of generic args list 
     677            assert _genParamNames.count 
     678        if _genParamNames.count and not _genParams.count  
     679            _genParams = JavaClassType.genClassTypeList(_genParamNames)  
     680        return _genParams 
     681     
     682         
     683    def getInterfaces as JavaClassType* #List<of JavaClassType> 
     684        if .interfaceNames.count and not _interfaces.count  
     685            _interfaces = JavaClassType.genClassTypeList(.interfaceNames)    
     686        return _interfaces 
     687         
     688    def getFields as JavaFieldInfo* 
     689        return _fields 
     690 
     691    def getConstructors as JavaCtorInfo* 
     692        return _ctors 
     693         
     694    def getMethods as JavaMethodInfo* 
     695        return _methods 
     696             
     697    def getProperties as JavaFieldInfo* 
     698        return _props 
     699             
     700    def getAnnotations as IList<of dynamic> 
     701        # TODO when store annotations in .sigfile - return as a list of classes 
     702        #return List<of JavaClassType>() 
     703        return @[] to IList<of dynamic> 
     704         
     705         
     706    get fields from var 
     707    get props  from var 
     708    get ctors  from var 
     709    get methods from var 
     710 
     711    #dbg 
     712    def toMinString as String 
     713        return '[.type] [.canonicalName]' 
     714         
     715    def toString as String is override 
     716        sb = StringBuilder() 
     717        sb.append('[.type] [.canonicalName]') 
     718        if _genParamNames.count 
     719            sb.append('<') 
     720            sep = '' 
     721            for pName in _genParamNames 
     722                sb.append(sep) 
     723                sb.append(pName) 
     724                sep = ',' 
     725            sb.append('>') 
     726        sb.append(' ') 
     727        if .modifiers.count      
     728            sb.append('is ') 
     729            sb.append(.modifiers.join(',')) 
     730            sb.append(' ') 
     731        if .superclass.length 
     732            sb.append('inherits [.superclass] ') 
     733        if .interfaceNames.count 
     734            sb.append('implements ') 
     735            sb.append(.interfaceNames.join(',')) 
     736        #sb.append(String.format(' -- {0} fields {1} props {2} ctors {3} methods', _fields.count, _props.count, _ctors.count, _methods.count)) 
     737        return sb.toString 
     738         
     739    def dumpFields 
     740        for field in .getFields 
     741            print field 
     742         
     743    def dumpCtors 
     744        for ctor in .getConstructors 
     745            print 'ctor ', ctor.toString 
     746 
     747    def dumpMethods 
     748        for mthd in .getMethods 
     749            print mthd 
     750             
     751    def dumpProps 
     752        for prop in .getProperties 
     753            print prop 
     754         
     755    def dumpIndexers 
     756        assert false, 'Indexers NYI' 
     757     
     758class JavaMemberInfo 
     759    var name = ''    
     760    var _attributes as List<of String>? 
     761    var modifiers = List<of String>() # public, default (=protected+pkg), protected, private 
     762 
     763    pro attributes 
     764        get  
     765            if not _attributes  
     766                _attributes = List<of String>() 
     767            return _attributes 
     768        set  
     769            _attributes = value 
     770     
     771    get isPublic 
     772        return .modifiers.contains('public') 
     773    get isProtected 
     774        return .modifiers.contains('protected') 
     775    get isPrivate 
     776        return .modifiers.contains('private') 
     777    get isDefault 
     778        return .modifiers.contains('default')   # = protected + package 
     779    get isStatic 
     780        return .modifiers.contains('static') 
     781    get isFinal 
     782        return .modifiers.contains('final') 
     783    get isAbstract 
     784        return .modifiers.contains('abstract') 
     785 
     786    get isOverride 
     787        # in java this is an annotation (at best), - via pkgSig treated as strings       
     788        return .attributes.contains('Override') 
     789 
     790    get isNonNullable 
     791        return .attributes.contains('NotNull') or .attributes.contains('NonNull') or .attributes.contains('Nonnull') 
     792        #for name in .attributes # in java these are annotations, - via pkgSig treated as strings 
     793        #   if name.endsWith == 'NotNull' or name.endsWith == 'NonNull'  or name.endsWith == 'Nonnull'  
     794        #       return true 
     795        #return false 
     796     
     797    get isVari 
     798        """ 
     799        VarArgs arglist to a a method.  
     800        Java sets this as a flag on the method but we convert it to a faked attribute on the methodInfo 
     801        """ 
     802        return .attributes.contains('IsVari')  
     803     
     804class JavaFieldInfo inherits JavaMemberInfo   
     805    """Info for fields and properties.""" 
     806    var typeName = '' 
     807    var value = ''      # pkgsig set value if final and initted 
     808    var isProp = false 
     809    var isIndexer = false 
     810    var isReadable = true 
     811    var isWritable = true 
     812    var getter as JavaMethodInfo? 
     813    var setter as JavaMethodInfo? 
     814    #var name0 = '' # original name before tweaked for propertyname 
     815    var _type as JavaClassType? 
     816     
     817    get type as JavaClassType 
     818        assert .typeName.length 
     819        if .typeName.length and not _type 
     820            #_type = JarSig.classByNameCache[.typeName] 
     821            _type = JarSig.lookupClass(.typeName) 
     822        return _type to !    
     823 
     824    def getValue as Object # ?? 
     825        return .value 
     826     
     827    def getIndexParameters as List<of JavaClassType> 
     828        """ List of Types for indexes for an indexer Property.""" 
     829        if not .isIndexer 
     830            return JavaClassType.emptyClassList 
     831        assert .getter 
     832        return .getter.getParameters     
     833        #if .setter 
     834        #   pars =  List<of JavaClassType(.setter.getParameters) 
     835        #   pars.removeAt(pars.count-1) # last is value to set 
     836        #   return pars 
     837         
     838    def toString as String is override 
     839        prefix = 'var' 
     840        if .isProp 
     841            if .isReadable and .isWritable, prefix = 'pro' 
     842            else if .isReadable, prefix = 'get' 
     843            else if .isWritable, prefix = 'set' 
     844 
     845        sb = StringBuilder('[prefix] [.name]') 
     846        if .typeName.length, sb.append(' as [.type]') 
     847        if .modifiers.count  
     848            sb.append(' is ') 
     849            sep='' 
     850            for mod in .modifiers 
     851                sb.append(sep) 
     852                sep =',' 
     853                sb.append(mod) 
     854        # TODO attributes 
     855        if .isProp 
     856            sb.append(' { ') 
     857            if .getter 
     858                sb.append('getter [.getter.name], ') 
     859            if .setter 
     860                sb.append('setter [.setter.name]') 
     861            sb.append(' }') 
     862        return sb.toString 
     863     
     864class JavaCtorInfo inherits JavaMemberInfo 
     865    var paramNames = List<of String>()  
     866    var _params = JavaClassType.emptyClassList 
     867     
     868    def getParameters as List<of JavaClassType> 
     869        if .paramNames.count and not _params.count  
     870            _params = JavaClassType.genClassTypeList(.paramNames)    
     871        return _params 
     872             
     873         
     874    def toString as String is override 
     875        sb = StringBuilder(.name) 
     876        if .paramNames.count and .paramNames[0].length 
     877            sb.append('(') 
     878            sep='' 
     879            for p in .paramNames 
     880                sb.append(sep) 
     881                sep =', ' 
     882                sb.append(p) 
     883            sb.append(')') 
     884        # TODO attributes 
     885        return sb.toString 
     886         
     887class JavaMethodInfo inherits JavaCtorInfo 
     888    var returnTypeName = '' 
     889    var throwsList = List<of String>() # list of String 
     890    var prop as JavaFieldInfo? # if this is a get or set method for a prop refer to the property 
     891 
     892    def returnType as JavaClassType? 
     893        if not .returnTypeName.length 
     894            return nil 
     895        #return JarSig.classByNameCache[.returnTypeName] 
     896        return JarSig.lookupClass(.returnTypeName) 
     897 
     898    def getGenericArguments as List<of JavaClassType> 
     899        return JavaClassType.emptyClassList # TODO: support generics 
     900                 
     901    def toString as String is override 
     902        nampar = base.toString 
     903        sb = StringBuilder('def [nampar] ') 
     904        if .returnTypeName.length 
     905            sb.append('as [.returnTypeName] ') 
     906        if .modifiers.count  
     907            sb.append('is ') 
     908            sep='' 
     909            for mod in .modifiers 
     910                sb.append(sep) 
     911                sep =',' 
     912                sb.append(mod) 
     913        if .prop 
     914            getset = .name[:3]           
     915            sb.append(" {[getset]ter for prop '[.prop.name]'} ") 
     916        if .throwsList.count 
     917            sb.append(' #throws') 
     918            sep='' 
     919            for thrw in .throwsList 
     920                sb.append(sep) 
     921                sep =',' 
     922                sb.append(thrw) 
     923                 
     924        # TODO attributes 
     925        return sb.toString 
     926     
     927     
  • Source/BackEndJvm/JvmJarSigTest.cobra

     
     1# standalone test for jvmJarSig class 
     2 
     3# compile with      cobra -d JvmJarSigTest.cobra JvmJarSig.cobra 
     4# 
     5class JvmJarSigTest 
     6     
     7    def main 
     8        expect InvalidOperationException 
     9            failPkgFile = JarSig('doWhakkaDay') 
     10            CobraCore.noOp(failPkgFile) 
     11        .simple1 
     12        .simple2 
     13 
     14        .pkgFile 
     15        .cmdline 
     16 
     17    def cmdline 
     18        if CobraCore.commandLineArgs.count > 1 
     19            pkgFile = CobraCore.commandLineArgs[1] 
     20            js = JarSig(pkgFile) 
     21            print js.toString 
     22            #print 'JarSig name:', js.name 
     23            for jc in js.getExportedTypes 
     24                print jc.toMinString 
     25                #print jc.toString 
     26             
     27    def simple1 
     28        #Empty class 
     29        # how about supporting a multiline string??? 
     30        simple = 'com.hops.Mpt\n    Class\n    com.hops\n    Mpt\n    com.hops.AlsoMpT\n    -\npublic static\n\n' 
     31        jc = JavaClassType.makeFromDesc(simple.split(c'\n').toList) 
     32        .chkType(jc, 'com.hops.Mpt', 'Mpt', 'com.hops', 'com.hops.AlsoMpT', JavaType.JavaClass, [ 'public', 'static'], List<of String>()) 
     33         
     34        assert jc.isClass 
     35        assert not jc.isInterface 
     36        assert not jc.isEnum 
     37        assert jc.fields.count == 0 
     38        assert jc.ctors.count == 0 
     39        assert jc.methods.count == 0 
     40        assert jc.props.count == 0 
     41         
     42    def chkType(jc as JavaClassType, canonicalName as String, name as String, pkg as String, superclass as String, type as JavaType, modifiers as List<of String>, interfaces as List<of String>) 
     43        assert jc.canonicalName == canonicalName 
     44        assert jc.name == name 
     45        assert jc.package == pkg 
     46        assert jc.superclass == superclass 
     47        assert jc.type == type 
     48        assert jc.interfaces.count == interfaces.count 
     49        for ifc in jc.interfaces 
     50            assert interfaces.contains(ifc) 
     51        assert jc.modifiers.count == modifiers.count 
     52        for m in jc.modifiers 
     53            assert modifiers.contains(m) 
     54 
     55    def simple2 
     56        # how about supporting a multiline string??? 
     57        desc = [ 
     58            'com.hops.Simple', 
     59            '   Class', 
     60            '   com.hops', 
     61            '   Simple', 
     62            '   com.hops.SimpleBase', 
     63            '    -              # no interfaces', 
     64            '   public', 
     65            '   ctor com.hops.Simple', 
     66            '       java.lang.String', 
     67            '   var count', 
     68            '       default', 
     69            '       int', 
     70            '   method toString', 
     71            '       public                         # modifiers', 
     72            '       java.lang.String               # returnType', 
     73            '       -                              # no parameters', 
     74            '       -                              # no exceptions', 
     75            '   method getNameStr', 
     76            '       public                         # modifiers', 
     77            '       java.lang.String               # returnType', 
     78            '       -                              # no parameters', 
     79            '       -                              # no exceptions', 
     80            '   method setNameStr', 
     81            '       public                         # modifiers', 
     82            '       void                           # returnType', 
     83            '       java.lang.String               # parameters', 
     84            '       -                              # no exceptions', 
     85            '   method setFoo', 
     86            '       public                         # modifiers', 
     87            '       void                           # returnType', 
     88            '       java.lang.String               # parameters', 
     89            '       -                              # no exceptions', 
     90        ] 
     91        jc = JavaClassType.makeFromDesc(desc) 
     92        .chkType(jc, 'com.hops.Simple', 'Simple', 'com.hops', 'com.hops.SimpleBase', JavaType.JavaClass, [ 'public'], List<of String>()) 
     93         
     94        assert jc.isClass 
     95        assert not jc.isInterface 
     96        assert not jc.isEnum 
     97         
     98        assert jc.fields.count == 1 
     99        assert jc.fields[0].name == 'count'  
     100        assert jc.fields[0].type == 'int'    
     101        assert jc.fields[0].modifiers.count == 1 
     102        assert jc.fields[0].modifiers[0] in ['default'] 
     103        #jc.dumpFields 
     104 
     105        assert jc.ctors.count == 1 
     106        assert jc.ctors[0].paramList.count == 1 
     107        assert jc.ctors[0].paramList[0] == 'java.lang.String' 
     108        #jc.dumpCtors 
     109         
     110        assert jc.methods.count == 4 
     111        assert jc.methods[0].name == 'toString'  
     112        assert jc.methods[0].returnType == 'java.lang.String'    
     113        assert jc.methods[0].modifiers[0] == 'public'    
     114        assert jc.methods[1].name == 'getNameStr'    
     115        assert jc.methods[2].name == 'setNameStr'    
     116        assert jc.methods[3].name == 'setFoo'    
     117        #jc.dumpMethods 
     118         
     119        assert jc.props.count == 2 
     120        assert jc.props[0].name =='NameStr' 
     121        assert jc.props[1].name =='Foo' 
     122        #jc.dumpProps 
     123         
     124    def pkgFile 
     125        expect InvalidOperationException 
     126            js = JarSig('noJarSigFile') 
     127             
     128        # requires file 'jarSigTestFile1.sig'  
     129        pkgFile = 'jarSigTestFile1' 
     130        js = JarSig(pkgFile) 
     131        assert js.name == 'jarSigTestFile1' 
     132        assert JarSig.sigFile(js.name) == 'jarSigTestFile1.sig' 
     133         
     134        expTypes = for jct in js.getExportedTypes get jct 
     135        assert expTypes.count == 3 
     136     
     137        for jct in expTypes 
     138            assert jct.name in ['AbstractMethodError','Appendable','Thread$State'] 
     139     
  • Source/BackEndJvm/jarSigTestFile1.sig

     
     1# Class paths and boot paths being searched 
     2#   C:\Program Files\Java\jre6\lib\resources.jar 
     3#   C:\Program Files\Java\jre6\lib\rt.jar 
     4#   C:\Program Files\Java\jre6\lib\sunrsasign.jar 
     5#   C:\Program Files\Java\jre6\lib\jsse.jar 
     6#   C:\Program Files\Java\jre6\lib\jce.jar 
     7#   C:\Program Files\Java\jre6\lib\charsets.jar 
     8#   C:\Program Files\Java\jre6\lib\modules\jdk.boot.jar 
     9#   C:\Program Files\Java\jre6\classes 
     10# jarfile=C:\Program Files\Java\jre6\lib\resources.jar 
     11# jarfile=C:\Program Files\Java\jre6\lib\rt.jar 
     12# jarfile=C:\Program Files\Java\jre6\lib\jsse.jar 
     13# jarfile=C:\Program Files\Java\jre6\lib\jce.jar 
     14 
     15java.lang.AbstractMethodError 
     16    class                          # Type 
     17    java.lang                      # package 
     18    AbstractMethodError            # name 
     19    java.lang.IncompatibleClassChangeError # superclass 
     20    -                              # no interfaces 
     21    public                         # modifiers 
     22    ctor java.lang.AbstractMethodError 
     23        -                              # no parameters 
     24    ctor java.lang.AbstractMethodError 
     25        java.lang.String               # parameters 
     26 
     27java.lang.Appendable 
     28    Interface                      # Type 
     29    java.lang                      # package 
     30    Appendable                     # name 
     31    -                              # superclass 
     32    -                              # no interfaces 
     33    public                         # modifiers 
     34    method append 
     35        public                         # modifiers 
     36        java.lang.Appendable           # returnType 
     37        java.lang.CharSequence         # parameters 
     38        java.io.IOException            # exceptions 
     39    method append 
     40        public                         # modifiers 
     41        java.lang.Appendable           # returnType 
     42        java.lang.CharSequence, int, int # parameters 
     43        java.io.IOException            # exceptions 
     44    method append 
     45        public                         # modifiers 
     46        java.lang.Appendable           # returnType 
     47        char                           # parameters 
     48        java.io.IOException            # exceptions 
     49 
     50java.lang.Thread$State 
     51    Enum                           # Type 
     52    java.lang                      # package 
     53    Thread$State                   # name 
     54    java.lang.Enum                 # superclass 
     55    -                              # no interfaces 
     56    static public                  # modifiers 
     57    var NEW 
     58        static public                  # modifiers 
     59        java.lang.Thread$State 
     60    var RUNNABLE 
     61        static public                  # modifiers 
     62        java.lang.Thread$State 
     63    var BLOCKED 
     64        static public                  # modifiers 
     65        java.lang.Thread$State 
     66    var WAITING 
     67        static public                  # modifiers 
     68        java.lang.Thread$State 
     69    var TIMED_WAITING 
     70        static public                  # modifiers 
     71        java.lang.Thread$State 
     72    var TERMINATED 
     73        static public                  # modifiers 
     74        java.lang.Thread$State 
     75    method values 
     76        static public                  # modifiers 
     77        [Ljava.lang.Thread$State;      # returnType 
     78        -                              # no parameters 
     79        -                              # no exceptions 
     80    method valueOf 
     81        static public                  # modifiers 
     82        java.lang.Thread$State         # returnType 
     83        java.lang.String               # parameters 
     84        -                              # no exceptions 
     85 
  • Source/BackEndJvm/JvmType.cobra

     
     1# NativeType wrapper for Java Classes 
     2 
     3# Eventually will use/handle java native classes but pending that and while cross compiling 
     4# wrap a JavaClassType (declared in JvmJarSig.cobra) 
     5 
     6class JvmNativeType inherits NativeType 
     7 
     8    var _type as JavaClassType 
     9    #var _type as java.lang.Class 
     10     
     11    #cue init(type as java.lang.Class) 
     12    cue init(type as JavaClassType) 
     13        base.init 
     14        _type = type 
     15 
     16    def equals(other as Object?) as bool is override 
     17        if other is this 
     18            return true 
     19        if other inherits JvmNativeType 
     20            return .backEndType == other.backEndType 
     21        else 
     22            return false 
     23 
     24    def getHashCode as int is override 
     25        return .backEndType.getHashCode 
     26 
     27    get backEndType as JavaClassType 
     28        return _type 
     29 
     30    get name as String is override 
     31        #return _type.getSimpleName 
     32        return _type.name 
     33 
     34    get fullName as String is override 
     35        return _type.canonicalName 
     36 
     37    get isValueType as bool is override 
     38        #return _type.isValueType # fix for char, int, bool, long  etc vs Boxed Classes 
     39        return false 
     40         
     41    get baseType as NativeType? is override 
     42        super = _type.getSuperClass 
     43        if not  super, return nil 
     44        return JvmNativeType(super)  # cache? 
     45        #if(_type.superclass.length, JvmNativeType(_type.superclass), nil) 
     46 
     47    def customAttributes as IList<of dynamic> is override 
     48        return .backEndType.getAnnotations #to IList<of dynamic> 
     49         
     50    get isSystemObjectClass as bool is override 
     51        return /#_type and #/ .fullName == 'java.lang.Object' 
     52         
     53    get isSystemTypeClass as bool is override 
     54        return /# _type and #/ .fullName == 'java.lang.Class' 
     55         
     56         
     57class JvmTypeProxy inherits NativeTypeProxy 
     58    """ 
     59    Acts as an ITypeProxy where the Jvm type is known. 
     60    Typically used when scanning DLLs. 
     61    """ 
     62 
     63    shared 
     64        var _cobraNameForJvmGenericNameCache = Dictionary<of String, String>() 
     65 
     66        def cobraNameForJvmType(jvmType as JavaClassType) as String 
     67            """ 
     68            Returns 'Foo' for 'Foo' and 'Foo<of,>' for 'Foo<T,T1>' 
     69            Converts generic and non-generic classes and interfaces. 
     70            Does *not* work for arrays, etc. 
     71            """ 
     72            name = jvmType.name 
     73            if not jvmType.isGenericType or jvmType.isGenericParameter 
     74                return name 
     75            if _cobraNameForJvmGenericNameCache.containsKey(name) 
     76                return _cobraNameForJvmGenericNameCache[name] 
     77            else 
     78                count = jvmType.genericArgsCount 
     79                assert count >0 
     80                cobraName = name + '<of' 
     81                for i in count-1, cobraName += ',' 
     82                cobraName += '>' 
     83                _cobraNameForJvmGenericNameCache[name] = cobraName 
     84                return cobraName 
     85                 
     86        def cobraNameForJvmBoxName(name as String) as String 
     87            """ 
     88            Assunmed we've mangled java generics typenames a la .Net ( i.e TypeName`<nGenericTypeParams>)  
     89            Returns 'Foo' for 'Foo' and 'Foo<of,>' for 'Foo`2' 
     90            Works on generic and non-generic classes, structs and interfaces. 
     91            Does *not* work for arrays etc. 
     92            """ 
     93            if '`' not in name, return name 
     94            if _cobraNameForJvmGenericNameCache.containsKey(name) 
     95                return _cobraNameForJvmGenericNameCache[name] 
     96            else 
     97                parts = name.split(c'`') 
     98                count = int.parse(parts[1]) 
     99                cobraName = parts[0] + '<of' 
     100                for i in count-1, cobraName += ',' 
     101                cobraName += '>' 
     102                _cobraNameForJvmGenericNameCache[name] = cobraName 
     103                return cobraName 
     104             
     105                 
     106    var _jvmType as JavaClassType 
     107 
     108    cue init(nativeType as NativeType) 
     109        .init((nativeType to JvmNativeType).backEndType) 
     110 
     111    cue init(jvmType as JavaClassType) 
     112        base.init 
     113        _jvmType = jvmType 
     114 
     115    def addMinFields 
     116        base.addMinFields 
     117        .addField('jvmType', _jvmType) 
     118 
     119    get realType as IType is override 
     120        return _realTypeWithCache(_jvmType) 
     121 
     122    def _realTypeWithCache(jvmType as JavaClassType) as IType 
     123        t = (.compiler to Compiler).typeForJvmType(jvmType) 
     124        if t is nil 
     125            t = _realTypeWithoutCache(jvmType, 0) 
     126            (.compiler to Compiler).addTypeForJvmType(t to !, jvmType) 
     127        return t to ! 
     128 
     129    def _realTypeWithoutCache(jvmType as JavaClassType, level as int) as IType 
     130        assert .compiler.basicTypes.count > 9   # should have bool, char, all the ints, etc. 
     131         
     132        # Must return the Cobra primitive types in place of System.Boolean, System.Char, System.Int16, etc. 
     133        # because it's the primitives that are used all over the compiler. 
     134        jvmPrimitiveToIType = .compiler.primitiveToITypeCache 
     135        if jvmPrimitiveToIType is nil or jvmPrimitiveToIType.count == 0 
     136            _initPrimToITypeCache 
     137            jvmPrimitiveToIType = .compiler.primitiveToITypeCache 
     138            assert jvmPrimitiveToIType is not nil and jvmPrimitiveToIType.count <> 0 
     139        basicType as IType? 
     140        if jvmPrimitiveToIType.tryGetValue(jvmType, out basicType) 
     141            return basicType to ! 
     142         
     143        # handle wrapped types, like arrays, with recursive calls 
     144        if jvmType.isArray 
     145            #assert jvmType.name.endsWith(r'[]') # could be [,] so TODO: handle multidim arrays 
     146            return .typeProvider.arrayType(_realTypeWithCache(jvmType.arrayComponentType to !)) 
     147        else if jvmType.isNested and not jvmType.isGenericParameter 
     148            declaringType = _realTypeWithCache(jvmType.declaringType to !) 
     149            potential = declaringType.memberForName(jvmType.name) 
     150            if potential is nil 
     151                .throwError('Cannot locate nested Jvm type "[jvmType]" (simple name is "[jvmType.name]").') 
     152            else if potential inherits IType 
     153                return potential 
     154            else 
     155                .throwError('Located Jvm type spec "[jvmType]" but got a [potential.englishName] instead of a type.') 
     156 
     157        # generic parameters 
     158        if jvmType.isGenericParameter 
     159            return GenericParam(JvmNativeType(jvmType)) 
     160 
     161        typeName = _computeCobraTypeName(jvmType) 
     162        missing = false 
     163        curNS = _computeNameSpace(jvmType, level, out missing) 
     164        if missing 
     165            .throwError('Cannot find Jvm type "[jvmType.canonicalName]"  in package "[jvmType.package]".') 
     166            # since the type exists, but cannot be located in our namespaces, 
     167            # it must be pulled from a dependent DLL that was not directly referenced 
     168            # but maybe it was already attempted 
     169            #if level > 0, .throwError('Cannot read Jvm type "[jvmType.fullName]" or its package "[jvmType.package]". Please report to the Cobra discussion forums (http://cobra-language.com/).') 
     170 
     171            #(.compiler to dynamic).jvmReadAssembly(clrType.assembly) 
     172            #return _realTypeWithoutCache(jvmType, level+1) # recurse. guard is just above. 
     173 
     174        # return namespace member 
     175        member as IMember? = curNS.declForName(typeName) 
     176        if member inherits IType 
     177            if member inherits Box 
     178                if jvmType.isGenericType and not jvmType.isGenericTypeDefinition 
     179                    # So we have something like ICollection<of KeyValuePair<of TKey,TValue>> which is all Generic types. 
     180                    # We need the Cobra types of those args so we can construct the Cobra type from the generic cobra type 
     181                    # otherwise, we would just end up returning the generic definition. 
     182                    print 'Dbg: JvmType.realTypeWithoutCache generic type [jvmType.canonicalName] [member.name].' 
     183                    #.throwError('TODO support for Generic Types in JvmType _realTypeWithoutCache') 
     184                    #member = _typeForArgsOfGeneric(jvmType, member) 
     185            return member 
     186        else 
     187            print '[typeName] not in [curNS.name] declsforName' 
     188            msg = 'Cannot locate jvm type "[jvmType]".' 
     189            if jvmType.package.length and jvmType.package.startsWith('java.lang') 
     190                if .compiler and .compiler.verbosity > 1, print msg 
     191                # TODO: .compiler.warning(msg) 
     192                return .compiler.objectType 
     193            else 
     194                .throwError(msg) 
     195        return .compiler.intType  # CC: to make C# code gen happy. 
     196     
     197    def _initPrimToITypeCache 
     198        typeToIType = _makePrimitiveTypesDict 
     199        jvmPrimitiveToIType = Dictionary<of dynamic, IType>() 
     200        for key in typeToIType.keys 
     201            jvmPrimitiveToIType[key] = typeToIType[key] 
     202        (.compiler to Compiler).primitiveCache  = jvmPrimitiveToIType #to ! 
     203 
     204    def _makePrimitiveTypesDict as IDictionary<of JavaClassType, IType> 
     205        primitiveToIType = Dictionary<of JavaClassType, IType>() 
     206        for bt in .compiler.basicTypes 
     207            if bt.systemAliasProxy 
     208                # lookup by qualified name (includes translation) and pull out (jvm) NativeType 
     209                key = (.compiler.nativeType((bt.systemAliasProxy to LibraryTypeProxy).qualifiedName) to JvmNativeType).backEndType 
     210                primitiveToIType[key] = bt 
     211        assert primitiveToIType.count == 0 or primitiveToIType.count >=8 
     212        return primitiveToIType 
     213     
     214         
     215    def _computeCobraTypeName(jvmType as JavaClassType) as String 
     216        typeName = jvmType.name 
     217        if jvmType.isGenericType  
     218            # generic like IComparable`1 
     219            assert r'[' not in typeName 
     220            typeName = .cobraNameForJvmType(jvmType) 
     221        else if not typeName[typeName.length-1].isLetterOrDigit 
     222            .throwError('Cannot locate JVM type "[jvmType.canonicalName]".') 
     223        return typeName 
     224 
     225    def _computeNameSpace(jvmType as JavaClassType, level as int, missing as out bool) as NameSpace 
     226        missing = false 
     227        if not jvmType.package.length, return .compiler.globalNS 
     228        nameParts = jvmType.package.split(c'.') 
     229        member = .compiler.globalNS.symbolForName(nameParts[0]) 
     230        if member inherits NameSpace, curNS = member 
     231        else, missing = true 
     232        if not missing 
     233            i = 1 
     234            while i < nameParts.length 
     235                namePart = nameParts[i] 
     236                possible = curNS.declForName(namePart) 
     237                if possible is nil 
     238                    missing = true 
     239                    break 
     240                else if possible inherits NameSpace 
     241                    curNS = possible 
     242                else 
     243                    .throwError('Found "[namePart]" at component [i+1] of JVM type "[jvmType.canonicalName]", but it is a [possible.englishName].') 
     244                i += 1 
     245        return curNS     
     246 
     247/# 
     248    def _typeForArgsOfGeneric(jvmType as JavaClassType, member as IType) as IType 
     249        args = List<of IType>() 
     250        for genArg in jvmType.getGenericArguments 
     251            args.add(_realTypeWithCache(genArg)) 
     252        boxMember = member to Box 
     253        if boxMember.qualifiedName == 'System.Nullable<of>' 
     254            assert args.count == 1 
     255            member = .typeProvider.nilableType(args[0]) 
     256        else 
     257            member = boxMember.constructedTypeFor(args) 
     258        return member    
     259#/ 
     260    def _typeForArgsOfGeneric(jvmType as JavaClassType, member as IType) as IType 
     261        args = List<of IType>() 
     262        for genArg in jvmType.getGenericArguments 
     263            args.add(_realTypeWithCache(genArg)) 
     264        boxMember = member to Box 
     265        member = boxMember.constructedTypeFor(args) 
     266        return member    
     267         
  • Source/BackEndJvm/TODO

     
     1= Java Backend Gen TODO = 
     2 
     3include-tests:no - remove Test invocation call 
     4 
     5 
     6fixup Object namespace for X-compile so items like System.Object are rooted off 
     7java.lang namespace ( rather than .Net system) 
     8    DONE  June-2011 
     9 
     10passthru compilation of *.java files  
     11    - seems to work for single files But 
     12        - calc of main class fm passthru *.java files 
     13     
     14computeOutName from name of main class (or first/only) class in file rather 
     15than permutation of input name 
     16    DONE 31-Jan-2011 
     17     
     18 
     19cobra namespaces capitalized (as .Net) Java all lowercase 
     20    - convert namespaces in java code to lowcase 
     21    DONE 31-Jan-2011 
     22     
     23 
     24java names lowcase  
     25    method Names  - DONE 31-Jan-2011 
     26    var names - DONE 31-Jan-2011, corrected 10-Feb-2011 BoxField._backendName -> BoxField.{sharp,java}BackEndName 
     27    params 
     28    events 
     29    local variables 
     30    -> remove/reverse cobra conversion to upcase for C#/.Net 
     31        ( look for calls to .capitalized)        
     32        DONE (I think) 
     33 
     34remove all uses of ClrNativeType in core compiler ( ->NativeType??) 
     35    Compiler/Enums/Types.cobra 
     36    DONE 
     37 
     38properties - pro/get/set 
     39    - auto convert to java getters/setters and map calls 
     40    - Whats the equiv for indexers 
     41        Look at Beans spec but otherwise use/convert to {get,set}Indexer method call. 
     42            <indexedT> getIndexer<T, indexedT>(T) and  
     43                       setIndexer<T, indexedT>(T, indexedT) 
     44      DONE  
     45                        
     46Events 
     47    - auto add boiler plate for listener (de)registration 
     48        - event firing 
     49 
     50 
     51partial classes 
     52    Add extra phase to aggregate partial classes together into first Module 
     53    (Chk if cobra is doing sommat like this or relying on C# compiler) 
     54     
     55Extensions 
     56    convert to static classes methods taking instance as first param 
     57    If lookup for name fails see if sig matches extension and remap call to extn static class method 
     58 
     59 
     60Parse error lines fm java giving source line, find (trailing comment) cobra 
     61line number and modify the java error msg line with the cobra lineno 
     62printing  that in any java error mesages so to relate the java error back  
     63to the generating cobra code line. 
     64  - start with just spew the javac lines to output 
     65    - assemble into ErrorMessage Line and 'supporting lines associated with it - keeps error line count in sync 
     66     
     67 
     68 
     69single file: 
     70    generate to java src files in namespace dir hier 
     71    compile to class file ( in class dir hier) 
     72    run class file 
     73  
     74If specify multiple files 
     75    generate thm all to java src in in namespace dir hier 
     76    compile to class files ( in class dir hier) 
     77    generate manifest file and generate classfiles to jar file 
     78    Leave jar file at root of hierarchy 
     79     
     80 
     81ensure support ( as builtin alternative) for jikes compiler. 
     82        https://sourceforge.net/projects/jikes/files/Jikes/     
     83 
     84 
     85add synonym for sharp''/sharp"" -> java''/java"" 
     86    or general be''/be"" (for backend) 
     87 
     88 
     89see http://www.25hoursaday.com/CsharpVsJava.html 
     90 
     91java 'synchronized' (block is exact equivalent of C# 'lock' stmt. 
     92 
     93varargs  
     94    'params' keyword in C# (qualifier to the last argument to the method which should be an array). 
     95    In Java, the same effect is achieved by appending the string "..." to the typename of the last argument to the method. 
     96     
     97Attributes 
     98    C# extend Atttribute - metainfo also ([AttributeUsage(AttributeTargets.Class)]) 
     99    java specify with @interface and Metainfo  
     100        e.g @Documented //we want the annotation to show up in the Javadocs  
     101            @Retention(RetentionPolicy.RUNTIME)) 
     102 
     103Java has Set in its collections framework so use that instead of Cobra lib version. 
     104 
     105Cobra methods nonVirtual (C# not marked virtual) in java mark as final (Cannot redefine or override). 
     106 
     107out and inout (ref) 
     108        x as <Type>?  = nil 
     109        method(...., out x)  # def method(.... out x as <Type>) 
     110        # use X here 
     111     
     112    becomes in java 
     113        Type x = nil 
     114        Object xRef = x 
     115        method(..., xRef)    // void method(..., xRef as Object) - inmethod xRef assigned to whatever x calculated as  
     116        x = xRef 
     117        // use x here 
     118 
     119 
     120Cobra backend targetting stab language (explicitly) ?? 
     121    backend 'stab-jvm' 
     122 
     123 
     124Decimal Type 
     125    Initially wrap it as new type thats is a Double with an associated DecimalFormatter 
     126    (giving same precision as .Net). 
     127    Calcs are all as doubles, toString uses formatter... 
     128     still get rounding error etc... 
     129     Decimal Type internally and emit as BigDecimal, trap math ops and map 
     130 
     131    Maybe easier to just default to Integer and ignore Decimal (initially) 
     132 
     133 
     134Add convenience methods to  
     135    java.io.File for 
     136        remember 
     137            (Buffered)Reader(FileReader(File(path)           - read text  
     138            (Buffered)InputStream(FileInputStream(File(path) - read bytestream 
     139                 
     140        static FileInputStream/FileOutputStream openRead/openWrite(String path)- r/w bytestream 
     141 
     142        static BufferedInputStream createRead(String path)  - open or create - bytes 
     143        static BufferedOutputStream createWrite(String path)  - open+truncate or create - bytes 
     144 
     145        static BufferedWriter createText(String path) - open or create Textfile for writing  
     146        static BufferedReader openText(String path)  - open textfile for reading  
     147 
     148        static byte[] readAllBytes(String path) 
     149        static String readAllText(String path) 
     150        static String[] readAllLines(String path) 
     151        static IEnumerable<of String> readLines(String path) 
     152 
     153 
     154= Issues = 
     155 
     156How support yield and conversion to enumerator/iterator? 
     157------------------------------------------------------------------------- 
     158 
     159Checked to Unchecked exceptions 
     160 
     161Fm http://www.mindview.net/Etc/Discussions/CheckedExceptions 
     162See also ExceptionChaining since JDK1.4 
     163 
     164ExceptionAdapter 
     165 
     166Here's a tool that I developed with the help of Heinz Kabutz.  It 
     167converts any checked exception into a RuntimeException while 
     168preserving all the information from the checked exception. 
     169 
     170import java.io.*; 
     171class ExceptionAdapter extends RuntimeException { 
     172  private final String stackTrace; 
     173  public Exception originalException; 
     174  public ExceptionAdapter(Exception e) { 
     175    super(e.toString()); 
     176    originalException = e; 
     177    StringWriter sw = new StringWriter(); 
     178    e.printStackTrace(new PrintWriter(sw)); 
     179    stackTrace = sw.toString(); 
     180  } 
     181  public void printStackTrace() {  
     182    printStackTrace(System.err); 
     183  } 
     184  public void printStackTrace(java.io.PrintStream s) {  
     185    synchronized(s) { 
     186      s.print(getClass().getName() + ": "); 
     187      s.print(stackTrace); 
     188    } 
     189  } 
     190  public void printStackTrace(java.io.PrintWriter s) {  
     191    synchronized(s) { 
     192      s.print(getClass().getName() + ": "); 
     193      s.print(stackTrace); 
     194    } 
     195  } 
     196  public void rethrow() { throw originalException; } 
     197}  
     198 
     199The original exception is stored in originalException, so you can 
     200always recover it.  In addition, its stack trace information is 
     201extracted into the stackTrace string, which will then be printed using 
     202the usual printStackTrace() if the exception gets all the way out to 
     203the console.  However, you can also put a catch clause at a higher 
     204level in your program to catch an ExceptionAdapter and look for 
     205particular types of exceptions, like this: 
     206 
     207catch(ExceptionAdapter ea) { 
     208  try { 
     209    ea.rethrow(); 
     210  } catch(IllegalArgumentException e) { 
     211    // ... 
     212  } catch(FileNotFoundException e) { 
     213    // ... 
     214  } 
     215  // etc. 
     216} 
     217 
     218Here, you're still able to catch the specific type of exception but 
     219you're not forced to put in all the exception specifications and 
     220try-catch clauses everywhere between the origin of the exception and 
     221the place that it's caught.  An even more importantly, no one writing 
     222code is tempted to swallow the exception and thus erase it.  If you 
     223forget to catch some exception, it will show up at the top level.  If 
     224you want to catch exceptions somewhere in between, you can. 
     225 
     226Or, since originalException is public, you can also use RTTI to look 
     227for particular types of exceptions. 
     228 
     229Here's some test code, just to make sure it works (not the way I 
     230suggest using it, however): 
     231 
     232public class ExceptionAdapterTest { 
     233  public static void main(String[] args) { 
     234    try { 
     235      try { 
     236        throw new java.io.FileNotFoundException("Bla"); 
     237      } catch(Exception ex) { 
     238        ex.printStackTrace(); 
     239        throw new ExceptionAdapter(ex); 
     240      }    
     241    } catch(RuntimeException e) { 
     242      e.printStackTrace(); 
     243    } 
     244    System.out.println("That's all!"); 
     245  } 
     246} 
     247 
     248By using this tool you can get the benefits of the unchecked exception 
     249approach (less code, cleaner code) without losing the core of the 
     250information about the exception. 
     251 
     252If you were writing code where you wanted to throw a particular type 
     253of checked exception, you could use (or modify, if it isn't already 
     254possible) the ExceptionAdapter like this: 
     255 
     256  if(futzedUp) 
     257    throw new ExceptionAdapter(new CloneNotSupportedException()); 
     258 
     259This means you can easily use all the exceptions in their original 
     260role, but with unchecked-style coding. 
     261 
     262------------------------------------------------------------------------- 
     263I've managed to fiddle javac to not check exceptions anymore *evil 
     264grin*. 
     265 
     266Very simple really.  Add a directory java/lang to your project and 
     267copy into that directory Exception.java and RuntimeException.java 
     268 
     269Change Exception to extend RuntimeException and change 
     270RuntimeException to extend Throwable. 
     271 
     272Now the compile-time exception checking is turned off.  
     273 
     274-- hops: Doesnt work unfortunately --- 
     275------------------------------------------------------------------------- 
     276 
     277 
     278 
     279 
     280 
     281------------------------------------------------------------------------- 
     282= Current compile cmd (X-compile) = 
     283 
     284cobra -back-end:jvm Name.cobra 
     285cobc0 -back-end:jvm -kif Name.cobra 
     286 
     287 
     288= MSW Default compiler cmd = 
     289File.cobra (containing class File) 
     290javac -cp '[CobraCore.exePath][pathSep]CobraLang.jar File.java 
     291javac -cp '../wkspace/Source/CobraLang.jar' File.java 
     292 
     293 
     294= MSW run cmd = 
     295java -cp ".;../wkspace/Source/CobraLang.jar" File 
     296 
     297 
     298= Other back ends = 
     299Fantom : compile to jvm or dotNet 
  • Source/BackEndJvm/ScanJvmType.cobra

     
     1# Load Jvm references and libraries 
     2 
     3class Compiler is partial 
     4 
     5    #var _didLoadJars = Set<of String>() 
     6 
     7    var _didReadJars = Set<of String>() 
     8     
     9    var _jvmTypeToType = Dictionary<of JavaClassType, IType>() 
     10     
     11    var _jvmTypeCache = Dictionary<of String, JavaClassType>() 
     12     
     13     
     14    # Java specific Reference loading 
     15    def jvmLoadReference(reference as String) as bool 
     16        try  
     17            return  __jvmLoadReference(reference) 
     18        catch fnfe as System.IO.FileNotFoundException 
     19            throw LoadReferenceException('FileNotFound', fnfe.fileName, fnfe.message) 
     20        catch fle as System.IO.FileLoadException 
     21            throw LoadReferenceException('FileLoadException', fle.fileName ? reference, fle.message) 
     22        catch fiop as InvalidOperationException 
     23            throw LoadReferenceException('InvalidOperationException', reference, fiop.message) 
     24             
     25    def __jvmLoadReference(reference as String) as bool 
     26        # uses reference parameter 
     27        # compiler .referenceVerbosity 
     28        # fills .loadedReferences 
     29     
     30        # Hopefully this is simpler than .Net case, look for reference which devolves to a pkgSig file 
     31        # in cwd or as abspathname or in cobra library-path settings. 
     32        # When running java native would probably also need to check the classpath 
     33        require 
     34            reference.endsWith('.jar') 
     35            reference not in ['.jar'] 
     36        ensure 
     37            result implies .loadedReferences[.loadedReferences.count-1] == reference 
     38            not result implies .loadedReferences.count == old.loadedReferences.count 
     39        body 
     40            jarSig as JarSig? = nil 
     41            rv = .referenceVerbosity 
     42            assert not (reference.startsWith('-r') and '-r' in reference[2:]) 
     43            sigFile =  reference + '.sig' 
     44            if rv, print 'Looking for sigfile("[sigFile]").' 
     45            sigFilePath = _lookForSigFile(sigFile, rv, reference) 
     46            if not sigFilePath 
     47                # eventually may also search CLASSPATH               
     48                if rv, print 'Returning false for __jvmLoadReference("[reference]").' 
     49                return false  
     50 
     51            if rv, print 'Will read jarsig: [sigFilePath]' 
     52            try 
     53                jarSig = JarSig(sigFilePath) 
     54            catch readExc as Exception 
     55                if rv, print 'Caught exception during jarSig creation: [readExc]' 
     56                throw 
     57            if rv 
     58                print 'Did find jarSig: [jarSig]' 
     59                print 'Will read jarsig contents: [jarSig]' 
     60            try 
     61                .javaReadJar(jarSig to !) 
     62            catch readExc as Exception 
     63                if rv, print 'Caught exception during javaReadJar: [readExc]' 
     64                throw 
     65            if rv, print 'Did read jar signature file: [jarSig]' 
     66            .loadedReferences.add(reference) 
     67            if rv, print 'Returning true for __jvmLoadReference("[reference]").' 
     68            return true 
     69         
     70    def _lookForSigFile(sigFile as String, rv as int, reference as String) as String? 
     71        """Pathname to sigfile if found in cwd, abspath or in library-directory paths, nil otherwise.""" 
     72        if File.exists(sigFile) # current directory or abspathname 
     73            if rv, print '"[reference]" found as file in [sigFile].' 
     74            return sigFile   
     75        ccPath = Path.getDirectoryName(CobraCore.exePath) to ! 
     76        absSigFile =  Path.combine(ccPath, sigFile) 
     77        if File.exists(absSigFile) 
     78            if rv, print '"[reference]" found as file in [absSigFile].' 
     79            return absSigFile    
     80             
     81        if rv, print 'File does not exist in std places. Searching library-directory setting' 
     82        searchPaths = .options.getDefault('library-directory', List<of String>()) to List<of String> 
     83        if not searchPaths.count 
     84            if rv, print 'No lib paths to search.' 
     85            return nil 
     86                 
     87        found = false 
     88        for searchPath in searchPaths 
     89            if rv,  print 'Checking lib path: "[searchPath]"' 
     90            combinedPath = Path.combine(searchPath, sigFile) 
     91            if File.exists(combinedPath) 
     92                if rv, print '"[reference]" found as file in [combinedPath].' 
     93                found = true 
     94                break 
     95                 
     96        if not found 
     97            if rv and searchPaths.count, print 'Did not find "[reference]" in lib paths' 
     98            return nil 
     99        return combinedPath 
     100 
     101    def javaReadJar(jSig as JarSig) 
     102        """ 
     103        Reads the contents of a jar (actually JarSig) file so that they are accessible to the program. 
     104        """ 
     105        if jSig.name in _didReadJars, return 
     106        _didReadJars.add(jSig.name) 
     107        verbosity = .verbosity 
     108        if verbosity 
     109            print 'Reading jar(sig):  [jSig.name]'  # extra space lines up with 'Loading reference:' 
     110            print '              at:  [jSig.location]' 
     111        namespaceQualNameToNameSpaceObject = Dictionary<of String, NameSpace>() 
     112        module = AssemblyModule(jSig.location, .globalNS) 
     113        saveModule, _curModule = _curModule, module 
     114        try 
     115            _modules.add(module) 
     116            for type in jSig.getExportedTypes 
     117                if type.isNested #or type.declaringType 
     118                    # these will be scanned by Box._scanNestedTypes 
     119                    # print '### skipping [type.name] in [type.namespace]. isNested=[type.isNested], declaringType=[type.declaringType]' 
     120                    continue 
     121                typeNamespace = type.package 
     122                if typeNamespace.length == 0 
     123                    # happens for classes etc. that are not declared in a namespace 
     124                    curNameSpace = module.topNameSpace 
     125                else 
     126                    namespaceName = typeNamespace 
     127                    if namespaceQualNameToNameSpaceObject.containsKey(namespaceName) 
     128                        curNameSpace = namespaceQualNameToNameSpaceObject[namespaceName] 
     129                    else 
     130                        curNameSpace = module.topNameSpace 
     131                        for name in typeNamespace.split(c'.') 
     132                            curNameSpace = curNameSpace.getOrMakeNameSpaceNamed(Token.empty, name) 
     133                            assert not curNameSpace.isUnified 
     134                        namespaceQualNameToNameSpaceObject[namespaceName] = curNameSpace 
     135                if verbosity >= 4 
     136                    print '  Reading type [type.name] in namespace "[namespaceName]"' 
     137                jvmType = JvmNativeType(type) 
     138                if curNameSpace.unifiedNameSpace.declForName(jvmType.name) 
     139                    .warning(CobraWarning('Already have declaration "[jvmType.name]" in namespace "[curNameSpace.fullName]".')) 
     140                else 
     141                    if type.isClass 
     142                        if type.name.startsWith('Extend_') and type.name.count(c'_') >= 2 
     143                            # e.g.Extend_String - TODO  
     144                            curNameSpace.addDecl(Extension(jvmType, .backEnd)) 
     145                        else 
     146                            curNameSpace.addDecl(Class(jvmType, .backEnd)) 
     147                    else if type.isInterface 
     148                        curNameSpace.addDecl(Interface(jvmType, .backEnd)) 
     149                    else if type.isEnum 
     150                        #print jvmType.name 
     151                        curNameSpace.addDecl(EnumDecl(curNameSpace, jvmType, type.modifiers, ''))  # TODO: isNames; docString? 
     152                    else if type.isValueType 
     153                        curNameSpace.addDecl(Struct(jvmType, .backEnd)) 
     154                    else 
     155                        throw FallThroughException(type) 
     156        finally 
     157            _curModule = saveModule 
     158 
     159    def jvmFixNilableMemberSigs 
     160        # TODO: this really needs to go in a separate file that the compiler reads each time 
     161 
     162        # fix up member sigs regarding methods returning nilable values 
     163        # hard coded below. TODO: read from a Cobra config file 
     164        # _fix is defined in ScanClrType 
     165     
     166        # These are just reflected over from the .Net ones since I dont know what the basis for inclusion is/was 
     167         
     168        _fix('java.lang.Object', 'toString getClass clone') 
     169            # ^ regarding .toString, not technically true, but common enough and life is too painful when the return type is nilable 
     170        #_fix('java.lang.System', 'out') #stdout 
     171        _fix('java.lang.String', 'padLeft padRight remove replace substring toLower toUpper trim') 
     172        #_fix('System.Type', 'assembly name toString') 
     173            # namespace can return nil if the Type is a generic parameter 
     174        #_fix('System.Environment', 'commandLine currentDirectory newLine version') 
     175        _fix('java.lang.Exception', 'message') 
     176        #_fix('System.Collections.Generic.IEnumerable<of>', r'getEnumerator') 
     177        #_fix('java.util.Enumeration<of>', r'getNext') 
     178        _fix('java.util.Iterator<of>', r'next') 
     179        _fix('java.util.ListIterator<of>', r'next previous') 
     180        _fix('java.util.Collection<of>', r'toArray') 
     181         
     182        #_fix('System.Collections.Generic.List<of>', r'[]') 
     183        _fix('java.util.List<of>', r'[] get set remove') 
     184        _fix('java.util.AbstractList<of>', r'[] get set remove') 
     185        _fix('java.util.AbstractSequentialList<of>', r'[] get set remove') 
     186        _fix('java.util.ArrayList<of>', r'[] get set remove') 
     187        #_fix('java.util.CopyOnWriteArrayList<of>', r'[] get set remove') 
     188        #_fix('java.util.LinkedList<of>', r'[] get set remove element getFirst getLast peek peekFirst peekLast poll pollFirst pollLast pop removeFirst removeLast') 
     189        #_fix('java.util.Vector<of>', r'[] get set elementAt firstElement lastElement remove') 
     190        #_fix('java.util.Stack<of>', r'[] peek pop push') 
     191         
     192        #_fix('System.Collections.Generic.IDictionary<of,>', r'[] keys values') 
     193        _fix('java.util.Map<of,>', r'[] get') 
     194        #    _fix('System.Collections.Generic.Dictionary<of,>', r'[]') 
     195        _fix('java.util.AbstractMap<of,>', r'[] get') 
     196        _fix('java.util.HashMap<of,>', r'[] get') 
     197        #_fix('java.util.ConcurrentHashMap<of,>', r'[] get') 
     198        #_fix('java.util.ConcurrentSkipListHashMap<of,>', r'[] get') 
     199        #_fix('java.util.EnumMap<of,>', r'[] get') 
     200        #_fix('java.util.IdentityHash<of,>', r'[] get') 
     201        #_fix('java.util.TreeMap<of,>', r'[] get') 
     202        #_fix('java.util.WeakHashMap<of,>', r'[] get') 
     203        _fix('java.util.Map.Entry<of,>', r'getKey getValue') 
     204        #_fix('java.util.AbstractMap.SimpleEntry<of,>', r'getKey getValue') 
     205        #_fix('java.util.AbstractMap.SimpleImmutableEntry<of,>', r'getKey getValue') 
     206         
     207        #_fix('System.IO.File', 'create createText open openRead openText openWrite readAllBytes readAllLines readAllText') 
     208        #_fix('java.io.File', 'create createText open openRead openText openWrite readAllBytes readAllLines readAllText') 
     209        #_fix('System.IO.FileSystemInfo', 'name fullName') 
     210        #_fix('System.IO.TextWriter', 'newLine') 
     211        #_fix('System.IO.Path', 'combine getFullPath') 
     212        #   combine = File(strA, strB).getPath(), getFullPath = File().getAbsolutePath() 
     213        #_fix('java.lang.StringBuilder', 'toString') # ?? 
     214        _fix('java.lang.Text.RegularExpressions.Regex', 'match replace') 
     215        _fix('System.Diagnostics.Process', 'processName') 
     216         
     217        _fix('System.Reflection.Assembly', 'getEntryAssembly getExecutingAssembly location') 
     218        _fix('System.Reflection.MemberInfo', 'name') 
     219        _fix('System.Reflection.FieldInfo', 'fieldType') 
     220        _fix('System.Reflection.ParameterInfo', 'parameterType') 
     221        _fix('System.Reflection.PropertyInfo', 'propertyType') 
     222 
     223        # TODO: shouldn't need the following. see comment in _fixSubs 
     224        #_fix('System.IO.StringWriter', 'toString') 
     225 
     226     
     227         
     228    # 
     229    # Jvm Type Cache 
     230 
     231    def typeForJvmType(jvmType as JavaClassType) as IType? 
     232        """ 
     233        Returns the Cobra type for a Java type if the Java type was previously scanned. 
     234        i.e this is access to the Java Type/Class cache. 
     235        """ 
     236        return if(_jvmTypeToType.containsKey(jvmType), _jvmTypeToType[jvmType], nil) 
     237 
     238    def addTypeForJvmType(type as IType, jvmType as JavaClassType) 
     239        require .typeForJvmType(jvmType) in [nil, type] 
     240        _jvmTypeToType[jvmType] = type 
     241         
     242    def jvmTypeByName(qualifiedName as String) as JavaClassType 
     243        """ 
     244        Obtain the Jvm Type given by the fully qualified (cobra) name. 
     245        """ 
     246        t as JavaClassType? 
     247        _jvmTypeCache.tryGetValue(qualifiedName, out t) 
     248        if t is nil 
     249            # TODO - lookup the JavaClassType by name. 
     250            t = JarSig.classByNameCache[qualifiedName] 
     251            _jvmTypeCache[qualifiedName] = t to passthrough  # "to passthrough" instead of "to !" to avoid non-nil check 
     252        return t to passthrough 
     253     
     254     
     255    def installJvmNativeMethods(box as Box, nativeType as NativeType)  
     256        print '++ TODO scanJvmType.installJvmNativeMethods' 
     257/# 
     258        meths = List<of Method>() 
     259        _installClrNativeMethodsFrom('System', nativeType, nativeType, box, meths) 
     260        _installClrNativeMethodsFrom('System', ClrNativeType(System.Math.getType), nativeType, box, meths) 
     261 
     262        # the next statement can be problematic in that you have to add new DecimalTools methods in Snapshot just so the compiler can see them 
     263        # ultimately, extensions of primitive types should be supported 
     264        _installClrNativeMethodsFrom('CobraLangInternal', ClrNativeType(Cobra.Lang.DecimalTools.getType), nativeType, box, meths) 
     265 
     266         _printMethods(meths, box) 
     267         
     268    def compareMethodNames(a as Method, b as Method) as int 
     269        return a.name.compareTo(b.name) 
     270         
     271    def _printMethods(meths as IList<of Method>, box as Box) 
     272        # print out the methods, useful for documentation 
     273        print 
     274        print 'type', box.name 
     275        sharedMeths = for meth in meths where meth.isShared 
     276        if sharedMeths.count 
     277            sharedMeths.sort(ref .compareMethodNames) 
     278            print '    shared' 
     279            for meth in sharedMeths 
     280                print '        [meth.cobraSourceSignature(false)]' 
     281        objectMeths = for meth in meths where not meth.isShared 
     282        if objectMeths.count 
     283            objectMeths.sort(ref .compareMethodNames) 
     284            for meth in objectMeths 
     285                print '    [meth.cobraSourceSignature]' 
     286 
     287#/       
     288 
     289 
     290class Box is partial 
     291 
     292    get _jvmType as JavaClassType 
     293        """ 
     294        Returns the Jvm NativeType (System.Class eventually)) boxed in the .nativeType. 
     295        Throws exception rather than return nil. 
     296        """ 
     297        return (.nativeType to JvmNativeType).backEndType 
     298 
     299    def isJvmSystemExceptionClass as bool 
     300        return .name == 'Exception' and .parentNameSpace and .parentNameSpace.fullName == 'java.lang' 
     301 
     302    def _scanNativeTypeJvm 
     303        """ 
     304        Subclasses should invoke base and then invoke the various _scanXXX methods that are appropriate for them. 
     305        """ 
     306        ensure not .needScanNativeType 
     307        _needScanNativeType = false 
     308        # print '<> _scanNativeType for [.name] in [_parentNameSpace.fullName], class is [.getType.name]' 
     309         
     310    def _scanGenericArgsJvm 
     311        if _jvmType.isGenericType 
     312            for genArg in _jvmType.getGenericArguments 
     313                t = (.compiler to Compiler).typeForJvmType(genArg) 
     314                if t is nil 
     315                    t = GenericParam(JvmNativeType(genArg), parentDefinition=this) 
     316                    (.compiler to Compiler).addTypeForJvmType(t to !, genArg) 
     317                _genericParams.add(t) 
     318                 
     319    def _prepSystemObjectClassJvm 
     320        # map method getType to java getClass 
     321        # C#'s typeof(X) is X.getType in Cobra. 
     322        #existing = .declForName('getClass') to BoxMember 
     323        #overload = MemberOverload(existing) 
     324        #.registerOverload(overload) 
     325        meth = Method(TokenFix.empty, TokenFix.empty, this, 'getType', List<of Param>(), .compiler.typeTypeProxy, nil, ['shared'], AttributeList(), 'Returns the Type instance that defines this type.') 
     326        meth.sharedMethodBacking = 'getClass'  
     327        #meth.sharedMethodBackingIsAlias = true # not static 
     328        #overload.addMember(meth) 
     329        .addDecl(meth) 
     330                 
     331    def _scanJvmIsNames 
     332        # TODO 
     333        _isNames.add('extern')  # to make the box like the ones that were in SystemInterfaces.cobra 
     334 
     335    def _scanJvmImplements 
     336        for interf in _jvmType.getInterfaces 
     337            if not _badJvmRelatedType(interf) 
     338                _baseInterfaceProxies.add(JvmTypeProxy(interf)) 
     339 
     340/# 
     341    def _scanJvmNestedTypes 
     342        # TODO: enable and fix resulting bugs 
     343        # for type in .clrType.getNestedTypes(BindingFlags(Instance, Static, DeclaredOnly, Public, NonPublic)) 
     344        for type in _jvmType.getNestedTypes 
     345            _scanJvmNestedType(type) 
     346        #for type in _clrType.getNestedTypes(BindingFlags(Static, DeclaredOnly, NonPublic)) 
     347        for type in _jvmType.getNestedTypes 
     348            if type.isEnum and not type.isPublic 
     349                _scanJvmNestedType(type) 
     350 
     351    def _scanJvmNestedType(type as JavaClassType) 
     352        nativeType = JvmNativeType(type) 
     353        if type.isClass 
     354            .addDecl(Class(nativeType, .compiler.backEnd)) 
     355        else if type.isInterface 
     356            .addDecl(Interface(nativeType, .compiler.backEnd)) 
     357        else if type.isEnum 
     358            isNames = List<of String>() 
     359            docString ='' 
     360            .addDecl(EnumDecl(this, nativeType, isNames, docString))  # TODO: isNames; docString? 
     361        #else if type.isValueType 
     362        #   .addDecl(Struct(clrType, .compiler.backEnd)) 
     363        #else if type.isAnsiClass 
     364        #   # The Enum class is an example that returns false for .isClass but true for .isAnsiClass 
     365        #   .addDecl(Class(clrType, .compiler.backEnd)) 
     366        else 
     367            throw FallThroughException(type) 
     368        lastDecl = .declsInOrder[.declsInOrder.count-1] to dynamic 
     369        if (lastDecl to Object).getType.getProperty('ParentBox')  # CC: if lastDecl responds to (get parentBox as Box?) 
     370            lastDecl.parentBox = this 
     371             
     372#/ 
     373 
     374    def _scanJvmFields 
     375        for fieldInfo in _jvmType.getFields 
     376            #if fieldInfo.declaringType is not _jvmType, continue 
     377            if fieldInfo.isDefault, continue    # pkgprivate 
     378            if fieldInfo.isPrivate, continue 
     379            name = Utils.cobraNameForNativeMemberName(fieldInfo.name) 
     380            type = _jvmMemberTypeResultProxy(fieldInfo, fieldInfo.type) 
     381            attrs = AttributeList() 
     382            if fieldInfo.isProtected 
     383                isNames = ['protected']  # isNames = ['protected' 'internal'] 
     384            #else if  fieldInfo.isDefault # pkgprivate 
     385            #   isNames = ['internal'] #  
     386            else 
     387                isNames = ['public']  # private was guarded against above 
     388 
     389            if fieldInfo.isFinal and fieldInfo.isStatic     # java static final fields are constants  
     390                value = if(fieldInfo.isStatic, fieldInfo.getValue, nil) 
     391                initExpr = SharpExpr(TokenFix.empty, if(value, .toString, 'nil'))  # DocGenerator.cobra uses this 
     392                boxConst = BoxConst(TokenFix.empty, TokenFix.empty, this, name, type, isNames, initExpr, attrs, '') 
     393                boxConst.binaryName = fieldInfo.name 
     394                .addDecl(boxConst) 
     395            else 
     396                if fieldInfo.isStatic, isNames.add('shared') 
     397                if fieldInfo.isFinal, isNames.add('readonly') # final fields are readonly 
     398                varr = BoxVar(TokenFix.empty, TokenFix.empty, this, name, type, isNames, nil, attrs, '') 
     399                varr.binaryName = fieldInfo.name 
     400                .addDecl(varr) 
     401 
     402    def _scanJvmInitializers 
     403        for ctorInfo in _jvmType.getConstructors 
     404            if ctorInfo.isPrivate, continue 
     405            #if ctorInfo.declaringType is not _clrType, continue 
     406            skip = false 
     407            for paramInfo in ctorInfo.getParameters 
     408                if _badJvmRelatedType(paramInfo) 
     409                    skip = true 
     410                    break 
     411            if skip, continue 
     412            params = _scanJvmParams(ctorInfo.getParameters, ctorInfo.isVari) 
     413            isNames = _isNamesForJavaMemberInfo(ctorInfo) 
     414            attribs = _attribsForJavaMemberInfo(ctorInfo) 
     415            docString = ''  # TODO: get doc string for class? 
     416            initer = Initializer(TokenFix.empty, TokenFix.empty, this, params, isNames, attribs, docString) 
     417            overload as MemberOverload? = nil 
     418            other = .declForName('cue.init') 
     419            if other 
     420                if other inherits MemberOverload 
     421                    overload = other 
     422                else if other inherits AbstractMethod 
     423                    overload = MemberOverload(other) 
     424                    .registerOverload(overload to !) 
     425                else 
     426                    throw FallThroughException([this, initer, other]) 
     427            if overload 
     428                overload.addMember(initer) 
     429            else 
     430                .addDecl(initer) 
     431                 
     432    def _scanJvmProperties 
     433        for propInfo in _jvmType.getProperties 
     434            getMethod = propInfo.getter  
     435            setMethod = propInfo.setter 
     436            visible = false 
     437            if getMethod 
     438                if getMethod.isPublic or getMethod.isProtected 
     439                    theMethod = getMethod 
     440                    visible = true 
     441            if not visible and setMethod 
     442                if setMethod.isPublic or setMethod.isProtected 
     443                    theMethod = setMethod to ! 
     444                    visible = true 
     445            if not visible, continue 
     446            #if theMethod.declaringType is not _jvmType, continue 
     447            if propInfo.isIndexer 
     448                _scanJvmIndexer(propInfo) 
     449                continue 
     450                 
     451            if _badJvmRelatedType(propInfo.type),   continue 
     452            attribs = _attribsForJavaMemberInfo(propInfo) 
     453            docString = ''  # TODO: get doc string 
     454            isNames = _isNamesForJavaMemberInfo(theMethod) 
     455            #print propInfo 
     456            propName = Utils.cobraNameForNativeMemberName(propInfo.name) 
     457            #if _declsByName.containsKey(propName), propName = propInfo.name0+'_prop' 
     458            prop = Property(TokenFix.empty, TokenFix.empty, this, propName, _jvmMemberTypeResultProxy(propInfo, propInfo.type), isNames, attribs, docString) 
     459            prop.binaryName = propInfo.name 
     460            if propInfo.isReadable 
     461                prop.makeGetPart(TokenFix.empty) 
     462            if propInfo.isWritable 
     463                prop.makeSetPart(TokenFix.empty) 
     464            if _declsByName.containsKey(prop.name) # for            # Double.naN 
     465                print 'DUP name already exists already for property [prop.name]', _declsByName[prop.name], prop 
     466                return # just drop the property, field or  method still available 
     467            .addDecl(prop) 
     468 
     469 
     470    def _scanJvmIndexer(propInfo as JavaFieldInfo) 
     471        for paramInfo in propInfo.getIndexParameters 
     472            if _badJvmRelatedType(paramInfo) 
     473                return 
     474        params = _scanJvmParams(propInfo.getIndexParameters, false) 
     475        attribs = _attribsForJavaMemberInfo(propInfo) 
     476        docString = '' 
     477        if propInfo.isReadable 
     478            isNames = _isNamesForJavaMemberInfo(propInfo.getter to !) 
     479        else if propInfo.isWritable 
     480            isNames = _isNamesForJavaMemberInfo(propInfo.setter to !) 
     481        else 
     482            throw FallThroughException(propInfo) 
     483        #name = Utils.cobraNameForNativeMemberName(propInfo.name) 
     484        name = r'[]'     
     485        indexer = Indexer(TokenFix.empty, TokenFix.empty, this, name, params, _jvmMemberTypeResultProxy(propInfo, propInfo.type), isNames, attribs, docString) 
     486        overload as MemberOverload? = nil 
     487        other = .declForName(name) 
     488        if other 
     489            if other inherits MemberOverload 
     490                overload = other 
     491            else if other inherits Indexer 
     492                overload = MemberOverload(other) 
     493                .registerOverload(overload to !) 
     494            else 
     495                throw FallThroughException([this, indexer, other]) 
     496        if overload 
     497            overload.addMember(indexer) 
     498        else 
     499            .addDecl(indexer) 
     500 
     501    # In Java  properties are methods with leading is/get/set names 
     502    # Indexers are methods as for properties but with additional indexes in paramList. 
     503    def _scanJvmMethods 
     504        for methInfo in _jvmType.getMethods 
     505            if methInfo.isPrivate, continue 
     506            if methInfo.isDefault, continue # pkgPrivate 
     507            #if methInfo.declaringType is not _clrType, continue 
     508            skip = false 
     509            if _badJvmRelatedType(methInfo.returnType) 
     510                skip = true 
     511            else 
     512                for param in methInfo.getParameters 
     513                    if _badJvmRelatedType(param) 
     514                        skip = true 
     515                        break 
     516            if skip, continue 
     517            name = Utils.cobraNameForNativeMemberName(methInfo.name) 
     518            genericParams = List<of IType>() 
     519            for genArg in methInfo.getGenericArguments 
     520                genericParams.add(GenericParam(JvmNativeType(genArg))) 
     521            params = _scanJvmParams(methInfo.getParameters, methInfo.isVari) 
     522            isNames = _isNamesForJavaMemberInfo(methInfo) 
     523            if methInfo.isOverride,  isNames.add('override')    # only on methods 
     524            attribs = _attribsForJavaMemberInfo(methInfo) 
     525            docString = ''  
     526            implementsTypeNode as ITypeProxy?  # TODO: explicit interface implementation? 
     527            method = Method(TokenFix.empty, TokenFix.empty, this, name, genericParams, params, _jvmMemberTypeResultProxy(methInfo, methInfo.returnType), implementsTypeNode, isNames, attribs, docString) 
     528            method.binaryName = methInfo.name 
     529            overload as MemberOverload? = nil 
     530            other = .declForName(name) 
     531            if other 
     532                if other inherits MemberOverload 
     533                    overload = other 
     534                else if other inherits AbstractMethod 
     535                    overload = MemberOverload(other) 
     536                    .registerOverload(overload to !) 
     537                else 
     538                    print 'Unexpected overload for name:', name, other 
     539                    throw FallThroughException([this, method, other]) 
     540            if overload 
     541                overload.addMember(method) 
     542            else 
     543                .addDecl(method) 
     544 
     545    def _scanJvmParams(jparams as List<of JavaClassType>?, isVariMethod as bool) as List<of Param> 
     546        """ 
     547        Returns a list of Cobra Params given a list of Java ClassTypes (presumably a java parameterList) 
     548        """ 
     549        params = List<of Param>() 
     550        if not jparams or not jparams.count 
     551            return params 
     552         
     553        paramN = 0 
     554        for javaParam in jparams 
     555            paramN +=1   
     556            isVari = paramN == jparams.count and isVariMethod #and javaParam is an array 
     557            # TODO support varags detection. 
     558            #java encodes a variable length paramlist as method.isVarArgs==TRUE and varargs parameter as an array of the the LCD Type ( Object[], String[] ) ( and perhaps args has transient modifier) 
     559             
     560            # TODO: detect nullable on paramlist types ? 
     561            # To support nilable on params need change representation to a javaParamType containing type + attributes (for param) ( + direction possibly) 
     562            # Java not support nilable directly so ignore for moment 
     563            #isNotNull = javaParam.isNonNullable 
     564            isNotNullable = false # can be null 
     565            parameterType = javaParam 
     566            type = _jvmMemberTypeProxy(parameterType, isNotNullable) 
     567            if isVari, type = VariTypeProxy(type) 
     568            name = 'unkname' # java not keep names of given formal parameters 
     569            param = Param(name, type) 
     570            param.direction = Direction.In # Java doesnt have Out or InOut equivs 
     571            params.add(param) 
     572        return params 
     573 
     574                 
     575    def _isNamesForJavaMemberInfo(mi as JavaMemberInfo) as List<of String> 
     576        """ 
     577        Returns the Cobra "is names" such as ['public', 'static'] that correspond to the properties of the JavaMember. 
     578        """ 
     579        isNames = List<of String>(8) 
     580        if mi.isDefault,     isNames.add('internal') # pkgPrivate/internal  and protected  
     581        # actually 
     582        #if mi.isProtected 
     583        #   isNames.add('protected') 
     584        #   isNames.add('internal')     # TODO: address this later 
     585        if mi.isProtected,   isNames.add('protected') 
     586        if mi.isPrivate,     isNames.add('private') 
     587        if mi.isPublic,      isNames.add('public') 
     588        if mi.isStatic,      isNames.add('shared') 
     589        if mi.isAbstract,    isNames.add('abstract') 
     590        if mi.isFinal,       isNames.add('readonly') 
     591        return isNames 
     592             
     593    def _attribsForJavaMemberInfo(mi as JavaMemberInfo) as AttributeList 
     594        return AttributeList()  # TODO: 
     595 
     596 
     597    def _badJvmRelatedType(t as JavaClassType?) as bool 
     598        """ 
     599        Returns true if the given type, which comes from a parameter or return value, is unsupported. 
     600        For example, it's not public or it's nested. Members with bad types are skipped when scanning DLLs. 
     601        """ 
     602        if t is nil  
     603            return false 
     604 
     605        if t.isNested and not (t.isPublic or t.isProtected)and not t.isGenericParameter  # TODO: need the generic param check? 
     606            print 'Type t.name is nested and not public,protected' 
     607            return true 
     608 
     609        # FYI: MS .NET 2.0 (but not Mono 1.2.6) will return true for .isNotPublic for types are "by ref" 
     610        #if t.isByRef # TODO: or t.isArray 
     611        #   return _badJvmRelatedType(t.getElementType) 
     612 
     613        return false 
     614 
     615    def _jvmMemberTypeProxy(jvmType as JavaClassType?) as ITypeProxy 
     616        return _jvmMemberTypeProxy(jvmType, false) 
     617 
     618    def _jvmMemberTypeProxy(jvmType as JavaClassType?, notNull as bool) as ITypeProxy        
     619        """ 
     620        Returns a type proxy for a member type such as a parameter type. 
     621        In Java, reference types are nilable by default, but you can pass `true` for `notNull` to indicate there was a NotNull Annotation in the jar metadata. 
     622        """ 
     623        if jvmType is nil 
     624            return .compiler.voidType 
     625        else if jvmType.isValueType 
     626            return JvmTypeProxy(jvmType) 
     627        else 
     628            # TODO: for generic types, should look at constraints. if constraints don't dictate nilable or not, then need to treat type special during generic construction 
     629            tp = JvmTypeProxy(jvmType) to ITypeProxy 
     630            if not notNull 
     631                tp = NilableTypeProxy(tp) 
     632            return tp 
     633 
     634    def _jvmMemberTypeResultProxy(member as JavaMemberInfo, jvmType as JavaClassType?) as ITypeProxy 
     635        """ 
     636        Returns a type proxy for a member type such as a method return type, property or field. 
     637        In Java, reference types are nilable by default. 
     638        """ 
     639        if jvmType is nil 
     640            return .compiler.voidType 
     641        else if jvmType.isValueType 
     642            return JvmTypeProxy(jvmType) 
     643        else if jvmType.isValueType or jvmType.isGenericParameter 
     644            return JvmTypeProxy(jvmType) 
     645        else 
     646            notNull = member.isNonNullable 
     647            t = JvmTypeProxy(jvmType) to ITypeProxy 
     648            return if(notNull, t, NilableTypeProxy(t)) 
     649 
     650 
     651class Class 
     652    is partial 
     653 
     654    def _scanNativeTypeJvm 
     655        base._scanNativeTypeJvm 
     656        print 'scanJvmNativeType ', .name 
     657        _scanJvmIsNames 
     658        _scanJvmImplements 
     659        #_scanJvmNestedTypes 
     660        _scanJvmFields 
     661        _scanJvmInitializers 
     662        _scanJvmMethods 
     663        _scanJvmProperties  # do props last since they are synthesized 
     664        ##_scanJvmEvents TODO  
     665        # TODO: _scanJvmEnums 
     666        # TODO: scan all other nested types 
     667         
     668     
     669class Interface 
     670    is partial 
     671 
     672    def _scanNativeTypeJvm 
     673        base._scanNativeTypeJvm 
     674        _scanJvmIsNames 
     675        _scanJvmImplements 
     676        #_scanJvmNestedTypes 
     677        _scanJvmFields 
     678        _scanJvmMethods 
     679        _scanJvmProperties 
     680        #_scanJvmEvents #TODO 
     681 
     682 
     683class Struct 
     684    is partial 
     685 
     686    def _scanNativeTypeJvm 
     687        base._scanNativeTypeJvm 
     688        _scanJvmIsNames 
     689        _scanJvmImplements 
     690        #_scanJvmNestedTypes 
     691        _scanJvmFields 
     692        _scanJvmInitializers 
     693        _scanJvmMethods 
     694        _scanJvmProperties 
     695        #_scanJvmEvents 
     696 
     697 
     698class Extension 
     699    is partial 
     700 
     701    def _scanNativeTypeJvm 
     702        # this only for Cobra specific extensions. Example: class Extend_String_1939 
     703        base._scanNativeTypeJvm 
     704        _scanJvmIsNames 
     705        #_scanJvmImplements 
     706        #_scanJvmNestedTypes 
     707        #_scanJvmFields 
     708        #_scanJvmInitializers 
     709        #_scanJvmProperties 
     710        _scanJvmMethods 
     711        #_scanJvmEvents 
     712 
     713    def _scanJvmParams(jparams as List<of JavaClassType>?, isVariMethod as bool) as List<of Param> is override 
     714        # the first argument is implicit in an Extension 
     715        results = base._scanJvmParams(jparams, isVariMethod) 
     716        return results[1:] 
     717         
     718    def jvmExtnNativeType(nativeType as NativeType) as NativeType 
     719        # the real extended type is the type of the first argument of any method 
     720        for methInfo in _jvmType.getMethods  
     721            nativeType = JvmNativeType(methInfo.getParameters[0]) 
     722            break 
     723        return nativeType 
     724 
     725         
     726 
     727class EnumDecl 
     728    is partial 
     729 
     730    def _setUnderlyingTypeJvm 
     731        pass 
     732 
     733    def _scanNativeTypeJvm 
     734        # TODO: read attribs 
     735        _needScanNativeType = false 
     736        _storageType = .compiler.anyIntType # tmp ?? 
     737         
     738        /# Enable when have Enum and JavaEnumType in PkgSig and JarSig 
     739        jvmType = (_nativeType to JvmNativeType).backEndType  
     740        assert jvmType inherits JavaEnumType # temporary 
     741        for name, value in jvmType.getConstantValues    # list of names and values 
     742            intValue = value to int 
     743            member = EnumMember(name, intValue) 
     744            member.enumDecl = this 
     745            .addDecl(member) 
     746        #/ 
     747             
     748        /# 
     749        isByte  = Enum.getUnderlyingType(jvmType).name == 'Byte' 
     750        is64    = Enum.getUnderlyingType(jvmType).name == 'Int64' 
     751        isU32   = Enum.getUnderlyingType(jvmType).name == 'UInt32' 
     752        isU64   = Enum.getUnderlyingType(jvmType).name == 'UInt64' 
     753        values  = Enum.getValues(jvmType) 
     754        i = 0 
     755        for name in Enum.getNames(jvmType) 
     756            value = values.getValue(i) 
     757            # CC: lameness follows 
     758            if isByte 
     759                intValue = int.parse((value to uint8).toString) 
     760            else if is64 
     761                try 
     762                    intValue = int.parse((value to int64).toString) 
     763                catch OverflowException 
     764                    intValue = 999  # CC: omg. but probably doesn't affect anything. we're reading the DLL here, not creating one 
     765            else if isU32 
     766                try 
     767                    intValue = int.parse((value to uint32).toString) 
     768                catch OverflowException 
     769                    intValue = 2147483647 
     770            else if isU64 
     771                try 
     772                    intValue = int.parse((value to uint64).toString) 
     773                catch OverflowException 
     774                    intValue = 2147483647 
     775            else 
     776                intValue = value to int 
     777            member = EnumMember(name, intValue) 
     778            member.enumDecl = this 
     779            .addDecl(member) 
     780            i += 1 
     781#/       
     782 
     783 
     784 
  • Source/BackEndJvm/JvmBackEnd.cobra

     
     1# Backend for generating Java code to run on a JVM - Currently this is cross-compile only fm .net/mono. 
     2use System.Diagnostics 
     3 
    14class JvmBackEnd inherits BackEnd 
    25 
     6    var _objectTypeProxy as AbstractTypeProxy? 
     7    var _typeTypeProxy   as AbstractTypeProxy? 
     8 
    39    cue init(compiler as Compiler) 
    410        base.init(compiler) 
     11        _name = 'java-jvm' 
     12        _rtlName = 'CobraLang.jar' 
     13         
     14        _tagToTypeName = {  
     15            'Object': 'java.lang.Object', 
     16            'Type'  : 'java.lang.Class<of>',    # java.lang.Type is a marker interface 
     17            'String'    :       'java.lang.String', 
     18            'Exception' :       'java.lang.RuntimeException', 
    519 
     20            'Delegate'  :       'System.Delegate', #cobra.lang.Delegate 
     21            'Attribute' :       'java.lang.annotation.Annotation', 
     22            #'ICloneable':      'System.ICloneable', #cobra.lang.ICloneable 
     23            'IEnumerable':      'java.lang.Iterable', 
     24            'IEnumerator':      'java.lang.Iterator', 
     25            'IEnumerable<of>' : 'java.lang.Iterable<of>', 
     26            'IEnumerator<of>' : 'java.lang.Iterator<of>', 
     27            'IDictionaryEnumerator' : 'System.Collections.IDictionaryEnumerator', 
     28            'ICollection':      'java.util.Collection<of Object>',  # non generic collection interface 
     29            'ICollection<of>':  'java.util.Collection<of>', 
     30            'IList' :           'java.util.List<of Object>',    # non generic List interface 
     31            'IList<of>' :       'java.util.List<of>', 
     32            'List<of>':         'java.util.ArrayList<of>', 
     33            'IDictionary':      'java.util.Map<of Object,Object>', # Non Generic Map/Dict interface 
     34            'IDictionary<of,>': 'java.util.Map<of,>', 
     35            'Dictionary<of,>' : 'java.util.HashMap<of,>', 
     36            'Set<of>':          'java.lang.HashSet<of>', 
     37 
     38            'bool'  :  'java.lang.Boolean',  # boolean 
     39            'char'  :  'java.lang.Character',# char 
     40            'decimal': 'java.lang.Double',  # ?? 
     41            'single': 'java.lang.Float',    # float  
     42            'double': 'java.lang.Double',   # double     
     43            'sbyte' : 'java.lang.Byte',     # byte 
     44            'int16' : 'java.lang.Short',    # short  
     45            'int32' : 'java.lang.Integer',  # int        
     46            'int64' : 'java.lang.Long',     # long 
     47            'byte'  : 'java.lang.Short',    # short   # rest are unsigned - use next widest 
     48            'uint16': 'java.lang.Integer',  # int    
     49            'uint32': 'java.lang.Long',     # long 
     50            'uint64': 'java.lang.Long',     # long 
     51             
     52            } 
     53         
    654    def makePhases(phases as IList<of Phase>) is override 
     55        # TODO 
     56        #phases.add(ApplyExtendedClasses(.compiler) # ?? done here or earlier 
     57        #phases.add(AggregatePartialClassesCodePhase(.compiler) 
    758        phases.add(GenerateJavaCodePhase(.compiler)) 
    859        phases.add(CompileJavaCodePhase(.compiler)) 
    960         
    1061    def computeOutName as String is override 
    1162        return .compiler.computeOutNameJava  
    1263         
     64    def genNativeModule(filename as String, verbosity as int) as Module? is override 
     65        m as Module? 
     66        if filename.endsWith('.java') 
     67            if verbosity, print 'Noting  [filename] as JavaModule'  # extra space to line up with 'Parsing [filename]' 
     68            m = JavaModule(filename, verbosity) 
     69        return m 
     70         
     71    def setupRunProcess(baseExe as String, fullExe as String) as Process is override 
     72        p = Process() 
     73        p.startInfo.fileName = 'java' 
     74        clPath = Path.getDirectoryName(CobraCore.exePath) to ! 
     75        clPath = Path.combine(clPath, 'CobraLang.jar') 
     76        classpath = Environment.getEnvironmentVariable('CLASSPATH') 
     77        cpSep = if(CobraCore.isRunningOnUnix, ':', ';') 
     78        classpath = '.[cpSep][clPath][cpSep][classpath]' 
     79        # TODO: additional classpaths for  references  
     80        args = '-ea -cp "[classpath]"' 
     81        args += ' [baseExe]' 
     82     
     83        p.startInfo.arguments = args + ' ' 
     84        #print p.startInfo.fileName, p.startInfo.arguments 
     85        return p         
     86     
     87    def setDefaultUseDirectives(ns as NameSpace) is override 
     88        # java packages available by default 
     89        useToken = Token('(implicit)', 1, 1, 1, 'USE', 'use', nil) 
     90        # java uses lowercase for package names - Should Cobra stay capitalised and we remap it ?? 
     91        ns.addUseDirective(UseDirective(useToken, ['java', 'lang'])) 
     92        #ns.addUseDirective(UseDirective(useToken, ['System', 'Collections', 'Generic'])) # generics built in 
     93        ns.addUseDirective(UseDirective(useToken, ['java', 'io'])) 
     94        ns.addUseDirective(UseDirective(useToken, ['java', 'util'])) 
     95        ns.addUseDirective(UseDirective(useToken, ['java', 'text'])) 
     96        ns.addUseDirective(UseDirective(useToken, ['cobra', 'lang'])) 
     97         
     98    def fixLibExtension(libRef as String) as String is override 
     99        """ 
     100        Augment given lib reference string with .jar backend extension if not already have one 
     101        """ 
     102        or require libRef.length 
     103        and ensure result.endsWith('.jar') 
     104        if not libRef.endsWith('.jar') 
     105            libRef += '.jar' 
     106        return libRef 
     107     
     108    def loadLibReference(reference as String) as bool is override 
     109        """ 
     110        Load referenced library (jar file) 
     111        """ 
     112        # Currently with cross compile fm .Net cant do this (easily) as not in a java environ 
     113        # (can we use Ikvm for this to bootstrap?) 
     114        # so what we will do is test for the existance of the jarfile in some sensible places 
     115        # (cwd, classpath, default install rt and extensions dir) and if it is found return true 
     116        # 
     117        #return .compiler.javaLoadReference(reference) 
     118        # -> reference -> jarFile -> JarSig(jarFile) -> javaReadJar 
     119        assert reference.endsWith('.jar') 
     120        return .compiler.jvmLoadReference(reference)   # in ScanJvmType 
     121     
     122    def readSystemTypes is override 
     123        #pass   # TODO 
     124        # Initially we will rely on a external java tool to have been run to produce a precis 
     125        # file in a known place (same as cobra compiler perhaps) containing exported types for 
     126        # items in a jar file. 
     127         
     128        # JarSig is a holder for jarfile extended with info on contained classes. 
     129        # javaReadJar loads info on contained classes into Cobra 
     130        # rt.jar is only one we need 
     131        .compiler.javaReadJar(JarSig('rt.jar')) 
     132     
     133    def fixNilableMemberSigs is override 
     134        #.compiler.javafixNilableMemberSigs 
     135        print '++ TODO jvmBackEnd.fixNilableMemberSigs' 
     136        pass # TODO 
     137         
     138    def installNativeMethods(box as Box, nativeType as NativeType) is override 
     139        #.compiler.installJvmNativeMethods(box, nativeType) 
     140        print '++ TODO jvmBackEnd.installNativeMethods' 
     141        pass # TODO 
    13142 
     143    def cobraNameForNativeBoxName(nativeBoxName as String) as String is override 
     144        return JvmTypeProxy.cobraNameForJvmBoxName(nativeBoxName) 
     145     
     146    # Types 
     147    get objectTypeProxy as AbstractTypeProxy  is override 
     148        """Type proxy for BE root of Object hierarchy.""" 
     149        if  not _objectTypeProxy 
     150            _objectTypeProxy = JvmTypeProxy(JarSig.classByNameCache['java.lang.Object']) 
     151        return _objectTypeProxy to ! 
     152             
     153    get typeTypeProxy  as AbstractTypeProxy  is override 
     154        """Type proxy for BE notion of a class describing a Type.""" 
     155        if  not _typeTypeProxy 
     156            _typeTypeProxy = JvmTypeProxy(JarSig.classByNameCache['java.lang.Class']) 
     157        return _typeTypeProxy to !   
     158         
     159    def nativeTypeProxy(type as NativeType) as NativeTypeProxy  is override 
     160        return JvmTypeProxy(type) 
     161     
     162    def nativeType(type as dynamic) as NativeType  is override 
     163        return JvmNativeType(type) 
     164     
     165    def nativeTypeByName(qualifiedNameOrTag as String) as NativeType is override 
     166        #map qualified name of .net aliased types  to java equivalents 
     167        # bool, char, decimal, single, double, sbyte, int{16,32,64}, byte, uint{16,32,64},  
     168        qualifiedName = .resolveTypeTag(qualifiedNameOrTag) 
     169        return JvmNativeType(.compiler.jvmTypeByName(qualifiedName)) 
     170        /# 
     171        These are the type tags used directly by the compiler code. 
     172             
     173            bool        'Java.lang.Boolean' 
     174            char        'java.lang.Char' 
     175            decimal     '??System.Decimal'   
     176            decimal     'java.lang.Float'    
     177            single      'java.lang.Float'        
     178            double      'java.lang.Double'       
     179            sbyte       'java.lang.Byte'         
     180            int16       'java.lang.Short'        
     181            int32       'java.lang.Int'      
     182            int64       'java.lang.Long'     
     183            # java not have unsigned types (:-( use next largest signed Type 
     184            byte        'java.lang.Short' #& 0x7f        
     185            uint16      'java.lang.Int'      
     186            uint32      'java.lang.Long'         
     187            uint64      'java.lang.Long'         
     188        #/ 
     189         
     190    def addArrayInterfaces(interfaces as List<of ITypeProxy>) is override 
     191        pass 
     192        #iclone = .compiler.libraryType('ICloneable') # ICloneable not supported 
     193        #interfaces.insert(0, iclone to ITypeProxy) 
     194         
     195         
     196         
    14197class GenerateJavaCodePhase inherits Phase 
    15198 
    16199    cue init(c as Compiler) 
  • Source/BackEndJvm/JavaCompilationMessage.cobra

     
    1111        assert msg.lineNum == 30 
    1212 
    1313    def willSkipMessage(msg as String) as bool is shared 
    14         return not '.java:' in msg 
    15  
     14        #return not '.java:' in msg 
     15        return false  
     16         
    1617    var _fileName as String? 
    1718    var _lineNum as int? 
    1819    var _isError as bool 
     
    2425        line = line.trim 
    2526        _isError = true 
    2627        i = line.indexOf('.java:') 
    27         _fileName = line[:i] 
    28         i += '.java:'.length 
    29         j = line.indexOf(':', i) 
    30         lineStr = line[i:j] 
    31         try 
    32             _lineNum = int.parse(lineStr) 
    33         catch 
    34             pass 
    35         success 
    36             _lineNum = compiler.cobraLineNumForCurly(.fileName, _lineNum to !) 
    37         if compiler.verbosity or Utils.isDevMachine, line += ' (javac)' 
     28        if i >= 0 
     29            _fileName = line[:i] 
     30            i += '.java:'.length 
     31            j = line.indexOf(':', i) 
     32            lineStr = line[i:j] 
     33            try 
     34                _lineNum = int.parse(lineStr) 
     35            catch 
     36                pass 
     37            success  
     38                _lineNum = compiler.cobraLineNumForCurly(.fileName, _lineNum to !) 
     39                if compiler.verbosity or Utils.isDevMachine, line += ' (javac)' 
    3840        _message = _cleanUp(line) 
    3941 
    4042    def _cleanUp(line as String) as String 
  • Source/BackEndJvm/JavaGenerator.cobra

     
    11""" 
     2Generate Java source code file for cobra AST. 
     3     
    24The code in this file should not .throwError, record warnings, etc. 
    35All of that happens during .bindFoo phases. 
    46""" 
     
    1012 
    1113class Compiler is partial 
    1214 
     15    # run prior to compilation to determine an output filename for the java source 
     16    # for testing for need for compilation. 
     17    # Filename used may be determined later post AST generation using the first classname in file 
     18    # see 'fixup output filename' in compileJava below 
    1319    def computeOutNameJava as String 
    1420        outName ='' 
    1521        if .options.boolValue('test') 
     
    4046 
    4147    def writeJavaTestInvocation 
    4248        # TODO 
    43         pass 
     49        print 'TODO: writeJavaTestInvocation' 
    4450 
    4551    def compileJava 
    4652        .compileJava('') 
     
    5359            options = .options 
    5460 
    5561            # locate the Java compiler 
    56             compilerPath = options.getDefault('native-compiler', '') to String 
    57             if compilerPath <> '' 
     62            # TODO: This just does files compilation, augment to also generate manifest and executable jarfile 
     63            # TODO: augment to use Java library compiler when Java native 
     64            compilerPath = options.getDefault('native-compiler', 'auto') to String 
     65            if compilerPath <> 'auto' 
    5866                if File.exists(compilerPath) 
    5967                    pass 
    6068                else if File.exists(compilerPath+'.exe') 
     
    6371                    print 'Cannot find compiler specified by -native-compiler argument: [compilerPath]' 
    6472                    throw StopCompilation(this) 
    6573            else 
     74                # TODO use a javatool - wrap javac and jarfile gen for multiple files        
     75                # javaTool -m MainClass -o outFile file-list 
    6676                compilerPath = if(Utils.isRunningOnUnix, 'javac', 'javac.exe') 
    67              
     77                 
    6878            optChar = '-' 
    6979             
    70             # exeNames 
     80            # exeNames - javaTool 
    7181            outName = .computeOutNameJava 
     82             
     83            # compute backEndOptions 
     84            backEndOptions = '-d .'     # Put namespaced classfiles in own hierarchy 
    7285 
    73             # compute backEndOptions 
    74             backEndOptions = '' 
    7586            # -optimize isn't supported by JVM, but it could potentially be used by Cobra itself 
    7687             
    7788            # TODO: 
    7889#           for refer in .loadedReferences  # don't take the library references from options, because the references can grow 
    79 #               backEndOptions += ' "[optChar]r:[refer]"' 
     90#               backEndOptions += ' "[optChar]r:[refer]"') 
    8091 
    8192            debug = options.getDefault('debug', '') to String 
    8293            if debug.length 
     
    8798            # TODO: not until the java backend is more mature 
    8899            # backEndOptions += ' -nowarn' 
    89100             
    90             backEndOptions += ' ' + extraJavacOptions 
     101            backEndOptions += extraJavacOptions 
    91102             
    92103            nativeArgs = .options.getDefault('native-compiler-args', '') to String 
    93104            if nativeArgs.length 
    94105                if nativeArgs.length > 2 and nativeArgs[0]=="'" and nativeArgs[nativeArgs.length-1]=="'" 
    95                     # on Windows, you should really use double quotes instead of single, but 
    96                     # we try to compensate here. 
     106                    # on Windows, you should really use double quotes instead of single, but we try to compensate here. 
    97107                    nativeArgs = nativeArgs[1:-1] 
    98108                backEndOptions += ' ' + nativeArgs 
    99109 
     110            #sep = if(CobraCore.isRunningOnUnix, ':', ';') # after next snapshot 
     111            cpSep = ';' 
     112            if (Environment.osVersion.platform to int) in [4, 6, 128]  # http://www.mono-project.com/FAQ:_Technical 
     113                cpSep = ':' 
     114 
     115            libclassPath = '' 
    100116            for libPath in .options.getStringList('library-directory') 
    101                 backEndOptions += ' ' + '-classpath "[libPath]"' 
     117                libclassPath += '[cpSep][libPath]"' 
    102118 
    103             # Cobra.Lang.dll is in the same directory as cobra.exe 
    104             libPath = Path.getDirectoryName(CobraCore.exePath) to ! 
    105             backEndOptions += ' ' + '-classpath "[libPath]"' 
    106  
    107             # .java files 
     119            # Cobra.Lang.dll is in the same directory as cobra.exe,  
     120            # explicitly add reference to it until we get setup to install a copy in extdirs 
     121            ccPath = Path.getDirectoryName(CobraCore.exePath) to ! 
     122            ccPath = Path.combine(ccPath, 'CobraLang.jar') 
     123            backEndOptions += ' -classpath "[ccPath][libclassPath]"' 
     124                 
     125            # TODO: add libPaths/classpaths for referenced namespaces 
     126             
     127            # .java files fm first class name in each module 
    108128            javaFileNameList = List<of String>() 
    109129            for module in _modules[1:] 
    110130                if module.javaFileName.length 
    111131                    javaFileNameList.add(module.javaFileName) 
    112132 
     133            # fixup javaMain pkg path all lower case 
     134            # fixup output filename (classfile) to be in sync with Java filename 
     135            javaMain = _getFixedMainType 
     136            if outName <> javaFileNameList[0] 
     137                outName = javaFileNameList[0] 
     138                #_baseExeFileName = Path.changeExtension(outName, nil) to ! # remove any extn 
     139                _baseExeFileName = javaMain 
     140                outName = Utils.forceExtension(outName, '.class') 
     141                _fullExeFileName = outName 
     142                         
    113143            # compilation command 
    114144            if _verbosity 
    115145                print 'Compiling to produce [outName]' 
     146            if _verbosity >= 2 
     147                print 'compiler =', compilerPath 
     148                print '    compilerOptions =', backEndOptions 
     149                print '    nativeArgs =', nativeArgs 
     150                print '    outName =', .fullExeFileName 
     151                print '    baseExeFileName =', .baseExeFileName 
     152                print '    javaFileNameList =', javaFileNameList 
    116153 
    117             # TODO: need to encapsulate this in CobraCore to avoid .NET dependency 
    118             p = System.Diagnostics.Process() 
    119             p.startInfo.fileName = compilerPath 
    120             javaFileNames = (for fileName in javaFileNameList get '"' + fileName + '"').join(' ') 
    121             p.startInfo.arguments = '[backEndOptions] [javaFileNames]' 
    122             if _verbosity >= 2 
    123                 print '[p.startInfo.fileName] [p.startInfo.arguments]' 
    124             output = CobraCore.runAndCaptureAllOutput(p) 
    125             # TODO: check p.exitCode, especially if output is empty 
     154            output = _execAndCapture(compilerPath, backEndOptions, javaFileNameList) 
    126155            _parseJavaCompilerOutput(output) 
    127156 
    128157            if .errors.count 
    129158                _exitFromErrors 
    130159 
    131160            _deleteIntermediateFiles 
    132  
     161             
     162    # Better would be options as optionList as List<of String> but ftm we're stuck with space joined strings 
     163    # coming into caller 
     164    # TODO: move this to CobraCore to avoid .NET dependency 
     165    def _execAndCapture(binaryPath as String, options as String, fileNameList as List<of String>) as String 
     166        p = System.Diagnostics.Process() 
     167        p.startInfo.fileName = binaryPath 
     168        #options = optionList.join(' ') 
     169        fileNames = (for fileName in fileNameList get '"' + fileName + '"').join(' ') # MSW quoting 
     170        p.startInfo.arguments = '[options] [fileNames]' 
     171        if _verbosity >= 2 
     172            print '[p.startInfo.fileName] [p.startInfo.arguments]' 
     173        output = CobraCore.runAndCaptureAllOutput(p) 
     174        # TODO: check p.exitCode, especially if output is empty 
     175        return output        
     176             
    133177    def _parseJavaCompilerOutput(output as String) 
    134178        for line in output.split(c'\n') 
    135179            line = line.trim 
     
    142186                _addMessage(JavaCompilationMessage(line, this)) 
    143187             
    144188 
     189    def _getFixedMainType as String 
     190        """ 
     191        Fixup mainMethodType for java so that any pkg path (namespace) is all lowercase. 
     192        We force this in NameSpace.writeJavaDef. 
     193        """ 
     194        javaMain = .mainMethodTypeName 
     195        exeParts = javaMain.split('.').toList 
     196        if exeParts.count >1 
     197            javaPkg = exeParts[0:-1].join('.').toLower  
     198            javaMain = '[javaPkg].[exeParts.last]'   
     199        #trace .mainMethodTypeName, javaMain 
     200        return javaMain  
    145201## 
    146202## Node 
    147203## 
     
    239295 
    240296    get javaFileName as String is override 
    241297        if _javaFileName == '' and not _fileName.endsWith('SystemInterfaces.cobra') 
    242             _javaFileName = _fileName + '.java' 
     298            #java source files are persnickety about naming wrt classname contents. 
     299            filename = _fileName 
     300            if filename.endsWith('.cobra') or filename.endsWith('.COBRA'), filename = filename[:-6] 
     301 
     302            #use first className in File 
     303            classFileName = _firstClassName 
     304            if classFileName.length 
     305                filename = classFileName     
     306            _javaFileName = filename + '.java' 
    243307        return _javaFileName 
    244  
     308         
     309    def _firstClassName as String 
     310        """Find first class name declared in the Module.""" 
     311        classFileName = '' 
     312        for decl in .topNameSpace.declsInOrder 
     313            if decl inherits Class 
     314                classFileName = decl.name 
     315                break    
     316            if decl inherits NameSpace 
     317                ns = decl 
     318                for decl1 in ns.declsInOrder 
     319                    if decl1 inherits Class 
     320                        classFileName = decl1.name 
     321                        break 
     322        return classFileName 
     323                         
    245324    def writeJavaDef as Dictionary<of int, int>? is override 
    246325        file = File.createText(.javaFileName) 
    247326        using sw = CurlyWriter(file, CurlyLineNumberTreatment.Comment) 
    248327            .compiler.addIntermediateFile(_javaFileName) 
    249328            sw.start(.fileName) 
    250             sw.write('// [_javaFileName]\n') 
    251             sw.write('// Generated by Cobra\n')  # TODO: put version number here 
     329            sw.write('// [_javaFileName] from [_fileName]\n') 
     330            sw.write('// Generated by Cobra-[CommandLine.versionString]\n') 
    252331            sw.write('// on [DateTime.now]\n') 
    253332            # TODO: list op sys 
    254333            sw.write('\n') 
    255334 
    256             # TODO DELME sw.write('using Cobra.Lang = Cobra.Lang[.compiler.embedRunTimeSuffix];\n') 
    257              
    258335            .topNameSpace.writeJavaDef(sw) 
    259336            d = sw.curlyToCobraLineNum 
    260337        return d 
     
    276353class Container<of TMember> is partial 
    277354 
    278355    get javaInit as String  # TODO: is abstract 
     356        """ 
     357        Initial (default) value for a type (in java). 
     358        """ 
    279359        return '' 
    280360         
    281361    get javaNameComponent as String 
     
    300380    get _computeJavaRef as String 
    301381        if .parent 
    302382            s = .parent.javaRef 
    303             # TODO: delme 
    304             #if s.length and not s.endsWith('::')  # C# has weird "global::" name 
    305             #   s += '.' 
    306383            s += .javaName 
    307384        else 
    308385            s = .javaName 
    309386        return s 
    310387 
    311388    def writeJavaIsNames(sw as CurlyWriter) 
    312         # TODO: look up Java access levels 
    313          
     389        # java access levels: 
     390        # static, public, protected, private, (package-private), internal, abstract, final 
    314391        # TODO: cache this somewhere 
    315392        accessLevels = ['public', 'protected', 'internal', 'protected internal', 'private'] 
    316393        # CC: accessLevels = 'public,protected,internal,protected internal,private'.split(c',') 
    317             # same names in both Cobra and C# 
    318394 
    319395        # TODO: 
    320396        # if isNames is nil 
     
    323399        isNames.addRange(_isNames) 
    324400        if .defaultAccessLevel.length 
    325401            found = false 
    326             for level as String in accessLevels  # CC: axe as 
     402            for level in accessLevels   
    327403                if level in isNames 
    328404                    found = true 
    329405            if not found 
    330406                isNames.insert(0, .defaultAccessLevel) 
    331407        isNameJava = { 
    332408            # only have to specify the ones that are different 
    333             'shared': 'static', 
    334             'nonvirtual': '', 
     409            'shared'    : 'static', 
     410            # virtual/override, nonvirtual/new only on methods and props?? 
     411            #'nonvirtual': '',  # n/a - final is similar but cannot override (new) 
     412            #'new'      : '',   # n/a - cant override a final  
     413            #'virtual'   : '',  # default 
     414            #'override'  : '',  # n/a - TODO mark with annotation 
     415            #'readonly' : 'final' # Not applicable to boxes 
     416            # 'public' 
     417            #'protected': '', 
     418            #'private',  
     419            'internal' : '',    # goes to nothing which is protected+package-private which is not quite the same  
     420            # 'abstract' 
     421            # 'partial' : '??'  # wot to do about this ??? 
    335422        } 
    336423        sep = '' 
    337424        for name in isNames 
     
    374461        else 
    375462            return value to String 
    376463 
    377     get javaInit as String is override  # TODO: remove when not a type 
    378         assert false 
    379         return '' 
     464    #get javaInit as String is override  # TODO: remove when not a type 
     465    #   assert false 
     466    #   return '' 
    380467 
    381468    get javaRef as String is override 
    382469        return .fullName + .javaSuffix 
    383470 
    384471    get javaQualifier as String 
    385472        ensure result.endsWith('.') 
    386         return .fullName + .javaSuffix + '.' 
     473        # TODO : Fix this with correct Namespace setup for java 
     474        #if .fullName == 'System' 
     475        #   return 'java.lang.' 
     476        javaName =  .fullName.toLower # java idiom is all lowercase for packages 
     477        return  javaName + .javaSuffix + '.' 
    387478     
    388479    def writeJavaDef(sw as CurlyWriter) is override 
    389480        assert not .isUnified 
    390481        base.writeJavaDef(sw) 
    391         # TODO: how to handle namespaces in Cobra 
    392         #if not .isRoot 
    393         #   sw.writeAndIndent('namespace [.name][.javaSuffix] {\n\n') 
    394         for ud in _useDirectives 
     482        if not .isRoot 
     483            javaName = .name.toLower # java idiom is all lowercase for packages 
     484            sw.write('package [javaName][.javaSuffix]; \n\n') 
     485        for ud in _useDirectives  # imports 
    395486            ud.writeJavaDef(sw) 
    396487        for decl in _declsInOrder 
    397488            if decl inherits Box 
     
    461552        """ 
    462553        # TODO: update doc string to reflect Java accurately 
    463554        Returns a string that refers to this type including any necessary parameter declaration 
    464         specification such as Java 'params' or 'out'. Invoked by Param.writeJavaDef. 
     555        specification such as 'params' or 'out'. Invoked by Param.writeJavaDef. 
    465556        """ 
    466557 
    467558 
     
    482573        return name 
    483574 
    484575    get javaRef as String 
     576        #print 'cobratype - [.javaName]' 
    485577        return .javaName 
    486578 
    487579    get javaParamRef as String 
     
    496588    get javaInit as String is override 
    497589        return 'false' 
    498590 
     591    get javaName as String is override 
     592        #return _nativeType.fullName 
     593        return 'boolean' 
    499594 
    500595class CharType is partial 
    501596 
    502597    get javaInit as String is override 
    503         return '(char)0' 
     598        return '(character)0' 
    504599 
    505600 
    506601class DynamicType is partial 
     
    515610class FloatType is partial 
    516611 
    517612    get javaName as String is override 
    518         return _nativeType.fullName 
     613        #return _nativeType.fullName 
     614        return 'float' 
    519615 
    520616 
    521617class IntType is partial 
    522618 
    523619    get javaName as String is override 
    524         return _nativeType.fullName 
     620        #return _nativeType.fullName 
     621        return 'int'    # java.lang.Integer 
     622        # TODO byte = int8 , short = int16, int = Int32, long = int64 
    525623 
    526  
    527624class NilableType is partial 
    528625 
    529626    get javaInit as String is override 
     
    560657class StreamType is partial 
    561658 
    562659    get javaInit as String is override 
    563         return 'new Cobra.Lang.EmptyStream<[.theWrappedType.javaRef]>()' 
     660        return 'new cobra.lang.EmptyStream<[.theWrappedType.javaRef]>()' 
    564661 
    565662    get javaRef as String is override 
    566663        assert .didBindInh and .didBindInt 
     
    658755        else 
    659756            java = .javaName 
    660757        if .parentNameSpace and not .parentNameSpace.isRoot 
     758            #trace .parentNameSpace.javaQualifier 
    661759            java = .parentNameSpace.javaQualifier + java 
    662760        else if .parentBox 
     761            trace .parentBox.javaRef 
    663762            java = .parentBox.javaRef + '.' + java 
     763        #trace java 
    664764        return java 
    665765 
    666766    def writeJavaDef(sw as CurlyWriter) 
     
    769869            expr.writeJavaDef(sw) 
    770870            sw.write(')\n') 
    771871            sw.indent 
    772             sw.write('throw new Cobra.Lang.InvariantException([expr.javaSourceSite(.name, "invariant", javaThis)], ') 
     872            sw.write('throw new cobra.lang.InvariantException([expr.javaSourceSite(.name, "invariant", javaThis)], ') 
    773873            expr.writeJavaBreakdown(sw) 
    774874            sw.write('[javaThis], null);\n') 
    775875            sw.dedent 
     
    809909    def writeJavaInheritance(sw as CurlyWriter) is override 
    810910        sw.write(' extends ') 
    811911        if _baseClass 
     912            #trace _baseClass 
    812913            sw.write(_baseClass.javaRef) 
    813914            didWrite = true 
    814915        if didWrite 
     
    872973 
    873974 
    874975class Struct is partial 
    875  
     976    # public class, public final fields, public methods? 
    876977    get javaInit as String is override 
    877978        return ''  # blank to indicate there is no valid init 
    878979 
     
    9751076 
    9761077class Param is partial 
    9771078 
    978     def writeJavoDef(sw as CurlyWriter) 
     1079    def writeJavaDef(sw as CurlyWriter) 
    9791080        base.writeJavaDef(sw) 
    980         if .type.isReference and not .type inherits NilableType 
    981             sw.write(r'[Cobra.Lang.NotNull] ') 
     1081        # TODO 
     1082        #if .type.isReference and not .type inherits NilableType 
     1083        #   sw.write(r'[Cobra.Lang.NotNull] ')  
    9821084        branch .direction 
    9831085            on Direction.In, pass 
    984             on Direction.InOut, sw.write('ref ') 
    985             on Direction.Out, sw.write('out ') 
     1086            on Direction.InOut, sw.write('/*inOut*/')   # default 
     1087            on Direction.Out, sw.write('/*out*/')       # TODO 
    9861088        sw.write('[.type.javaParamRef] [.javaName]') 
    9871089 
    9881090    def writeJavaDefSansReferenceLabels(sw as CurlyWriter) 
     
    10211123 
    10221124    def writeJavaNotNull(sw as CurlyWriter) 
    10231125        if .resultType.isReference and not .resultType inherits NilableType 
    1024             sw.writeLine(r'[' + .javaNotNullPrefix + 'Cobra.Lang.NotNull]') 
     1126            sw.writeLine(r'[' + .javaNotNullPrefix + 'cobra.lang.NotNull]') 
    10251127 
    10261128    get javaNotNullPrefix as String 
    1027         # TODO 
    1028         # 2007-12-22 Writing the attribute like [return: NotNull] is problematic because MemberInfo.getCustomAttributes() 
    1029         # will not see it. At least not on Novell Mono 1.2.4. I don't know if that is a bug or a "feature". 
    1030         #return 'return: ' 
     1129        # TODO make an annotation on BoxMember 
    10311130        return '' 
    10321131 
    10331132    def writeJavaTest(sw as CurlyWriter) 
     
    10581157        # if isNames is nil 
    10591158        #   isNames = _isNames 
    10601159         
    1061         # TODO: 
    10621160        isNameJava = { 
    10631161            # only have to specify the ones that are different 
    10641162            'shared': 'static', 
    1065             'nonvirtual': '', 
     1163            'nonvirtual': '',   # n/a - final is similar but cannot override (new) 
     1164            'new'       : '',   # n/a - cant override a final  
     1165            'virtual'   : '',   # default 
     1166            'override'  : '',   # n/a - TODO mark with annotation 
     1167            'readonly' : 'final', 
     1168            #   'public', 'protected', 'private',  
     1169            'internal' : ''     # goes to nothing which is package-private which is not quite the same  
     1170            # 'abstract' 
    10661171        } 
    10671172        wroteNames = Set<of String>() 
    10681173        sep = '' 
     
    10911196    # TODO: 
    10921197     
    10931198    get javaName as String is override 
    1094         return .name.capitalized 
     1199        return .name #.capitalized 
    10951200 
    10961201    def writeJavaDef(sw as CurlyWriter) is override 
    10971202        base.writeJavaDef(sw) 
     
    11051210 
    11061211class BoxField is partial 
    11071212 
    1108     get _backEndName as String 
    1109         name = .name 
    1110         if not name.startsWith('_') 
    1111             name = name.capitalized 
    1112         return name 
     1213    # java idiom uses same (sensible) naming  style as cobra 
     1214    #get _javaBackEndName from name 
     1215    get _javaBackEndName as String 
     1216        return .name 
    11131217 
    11141218 
    11151219class BoxConst is partial 
     
    11201224        .writeJavaIsNames(sw) 
    11211225        sw.write('const ') 
    11221226        sw.write(_type.javaRef) 
    1123         sw.write(' [_backEndName] = ') 
     1227        sw.write(' [_javaBackEndName] = ') 
    11241228        _initExpr.writeJavaDef(sw) 
    11251229        sw.write(';\n') 
    11261230 
     
    11281232class BoxVar is partial 
    11291233 
    11301234    get javaAssignmentNames as List<of String> 
    1131         return [_backEndName] 
     1235        return [_javaBackEndName] 
    11321236        # return List<of String>(_useBackEndNameStack) 
    11331237 
    11341238    get javaName as String is override 
    11351239        if _ifInheritsStack.count 
    11361240            if _type.isReference 
    1137                 return '(([_ifInheritsStack.peek.javaRef])[_backEndName])' 
    1138             else 
     1241                return '(([_ifInheritsStack.peek.javaRef])[_javaBackEndName])' 
     1242            else    # TODO fix this - .Net specific 
    11391243                # could it be a subclass? no. value types are structs and cannot be subclassed so this must be `if i` where `i` is nullable struct 
    1140                 return '[_backEndName].Value'  # Nullable<of T>.Value 
     1244                return '[_javaBackEndName].Value'  # Nullable<of T>.Value 
    11411245        else 
    11421246            return .name 
    11431247        # return _useBackEndNameStack.peek to ! 
     
    11471251        .writeJavaAttribs(sw) 
    11481252        .writeJavaIsNames(sw) 
    11491253        sw.write(_type.javaRef) 
    1150         sw.write(' [_backEndName]') 
     1254        sw.write(' [_javaBackEndName]') 
    11511255        if _initExpr 
    11521256            sw.write(' = ') 
    11531257            _initExpr.writeJavaDef(sw) 
     
    11791283    def innerWriteJavaDef(sw as CurlyWriter) 
    11801284        pass 
    11811285     
    1182     def writeJavaImp(sw as CurlyWriter) 
     1286    def writeJavaImp(sw as CurlyWriter, skipFirst as bool) 
    11831287        .compiler.codeMemberStack.push(this) 
    11841288        try 
    11851289            sw.writeAndIndent('{\n') 
     
    12011305                        javaInit = param.type.javaInit 
    12021306                        if not javaInit.length 
    12031307                            # TODO/HACK: yes we need something like this (or a way to convice C# that the out param reference in `finally` really is okay), 
    1204                             # but it should be something less hackish, like an attribute 
    12051308                            javaInit = 'DateTime.Today' 
    12061309                        sw.write('[param.javaName] = [javaInit];') 
    12071310                if _backEndResultVarName.length  # set in _bindImp 
     
    12101313                        sw.write('= [_returnType.javaInit]') 
    12111314                    sw.write(';\n') 
    12121315                sw.writeAndIndent('try {\n') 
    1213             for stmt in _stmts, stmt.writeJavaStmt(sw) 
     1316            for stmt in _stmts  
     1317                if skipFirst 
     1318                    skipFirst = false 
     1319                    continue 
     1320                stmt.writeJavaStmt(sw) 
    12141321            if willEnsure 
    12151322                if not stmt inherits ReturnStmt and not stmt inherits ThrowStmt 
    12161323                    sw.write('_lh_canEnsure = true;\n') 
     
    13301437        if .isCompilerGenerated, return 
    13311438        if param.type.isReference and not param.type inherits NilableType and not param.isOut 
    13321439            if .compiler.options.boolValue('include-nil-checks') 
    1333                 sw.write('if (Cobra.Lang.CobraCore._willCheckNil && [param.javaName]==null) throw new System.ArgumentNullException("[param.name]");\n') 
     1440                sw.write('if (cobra.lang.CobraCore._willCheckNil && [param.javaName]==null) throw new System.ArgumentNullException("[param.name]");\n') 
    13341441 
    13351442    def writeJavaDSTHead(sw as CurlyWriter) 
    13361443        if not .canHaveDetailedStackTrace 
    13371444            return 
    13381445        # could be a neat option, -trace-methods, but maybe done with events: 
    13391446        # sw.writeLine('Console.WriteLine(">> [.parentBox.name].[.name]");') 
    1340         sw.write('Cobra.Lang.CobraImp.PushFrame("[.parentBox.name]", "[.name]", [Utils.javaStringLiteralFor(.token.fullPathName)], [.token.lineNum]') 
     1447        sw.write('cobra.lang.CobraImp.pushFrame("[.parentBox.name]", "[.name]", [Utils.javaStringLiteralFor(.token.fullPathName)], [.token.lineNum]') 
    13411448        if not .isShared 
    13421449            sw.write(', "this", [.compiler.curBox.javaThis]') 
    13431450        for param in .params 
     
    13531460        # this catch all clashes with yield statements. which is why .canHaveDetailedStackTrace returns false if a method has a yield statement. 
    13541461        sw.dedentAndWrite('} catch (java.lang.Exception) {\n') 
    13551462        sw.indent 
    1356         sw.write('Cobra.Lang.CobraImp.CaughtUncaughtException();\n') 
     1463        sw.write('cobra.lang.CobraImp.CaughtUncaughtException();\n') 
    13571464        sw.write('throw;\n') 
    13581465        sw.dedentAndWrite('} finally {\n') 
    13591466        sw.indent 
    1360         sw.write('Cobra.Lang.CobraImp.PopFrame();\n') 
     1467        sw.write('cobra.lang.CobraImp.popFrame();\n') 
    13611468        sw.dedentAndWrite('}\n') 
    13621469 
    13631470 
     
    13661473    def innerWriteJavaDef(sw as CurlyWriter) 
    13671474        base.innerWriteJavaDef(sw) 
    13681475        .writeJavaAttribs(sw) 
    1369 # delme     first = if(_stmts.count, _stmts[0], nil) 
    1370 # delme     callInitializer as String? = nil 
    1371 /# 
    1372 delme 
     1476         
     1477        .writeJavaIsNames(sw) 
     1478        sw.write(' [.parentBox.rootName]') 
     1479        .writeJavaParams(sw) 
     1480         
     1481        .writeJavaImp(sw, _hasCallInitializer)  # Initializer Body 
     1482         
     1483        if _requirePart, _requirePart.writeJavaMethod(sw) 
     1484        if _ensurePart, _ensurePart.writeJavaMethod(sw) 
     1485        if .compiler.includeTests 
     1486            .writeJavaTest(sw) 
     1487 
     1488    def writeJavaImpHeader(sw as CurlyWriter) 
     1489        base.writeJavaImpHeader(sw) 
     1490 
     1491        first = if(_stmts.count, _stmts[0], nil) 
     1492        callInitializer as String? = nil 
    13731493        if first inherits DotExpr 
    13741494            if first.left inherits ThisOrBaseLit 
    13751495                if (firstRight = first.right) inherits IDotRightExpr 
     
    13781498                        args = firstRight.args 
    13791499                        Stmt.inInitCall = true 
    13801500                        didSetInInitCall = true 
    1381 #/ 
    1382         .writeJavaIsNames(sw) 
    1383         sw.write(' [.parentBox.rootName]') 
    1384         .writeJavaParams(sw) 
    1385 /# 
    1386 delme 
    1387         if callInitializer 
    1388             sw.writeAndIndent('\n') 
    1389             sw.write(': [callInitializer](') 
    1390             sep = '' 
    1391             for arg in args 
    1392                 sw.write(sep) 
    1393                 arg.writeJavaDef(sw) 
    1394                 sep = ', ' 
    1395             sw.write(') ') 
    1396             sw.dedent 
     1501            if args.count == 0 
     1502                sw.writeLine('//super() - default noarg initialiser call happens here') 
     1503            else 
     1504                sw.write('[callInitializer](') 
     1505                sep = '' 
     1506                for arg in args 
     1507                    sw.write(sep) 
     1508                    arg.writeJavaDef(sw) 
     1509                    sep = ', ' 
     1510                    sw.write(');') 
    13971511            if didSetInInitCall 
    13981512                assert Stmt.inInitCall  # make sure it wasn't reset somewhere else 
    13991513                Stmt.inInitCall = false 
    1400 #/ 
    1401         .writeJavaImp(sw) 
    1402         if _requirePart, _requirePart.writeJavaMethod(sw) 
    1403         if _ensurePart, _ensurePart.writeJavaMethod(sw) 
    1404         if .compiler.includeTests 
    1405             .writeJavaTest(sw) 
    14061514 
    1407     def writeJavaImpHeader(sw as CurlyWriter) 
    1408         base.writeJavaImpHeader(sw) 
    14091515        if .isStructMember and .compiler.options['contracts'] <> 'none' 
    14101516            sw.write('\n_ih_invariantGuard = 0;\n\n')  # otherwise C# complains: Field "STRUCTNAME._ih_invariantGuard" must be fully assigned before control leaves the constructor 
    14111517         
    1412  
     1518             
     1519    def _hasCallInitializer as bool 
     1520        callInitializer as String? = nil 
     1521        first = if(_stmts.count, _stmts[0], nil) 
     1522        if first inherits DotExpr 
     1523            if first.left inherits ThisOrBaseLit 
     1524                if (firstRight = first.right) inherits IDotRightExpr 
     1525                    if firstRight.name == 'init' 
     1526                        callInitializer = (first.left to ThisOrBaseLit).asJava 
     1527        return callInitializer <> nil 
     1528                     
     1529             
    14131530class Method is partial 
    14141531 
    14151532    get javaGenericParams as String is override 
     
    14371554            name = _implementsType.javaRef + '.' + name 
    14381555        .writeJavaIsNames(sw) 
    14391556        sw.write('[returnType.javaRef] [name][.javaGenericParams]') 
    1440         .writeJavaParams(sw) 
     1557        if .isMain   
     1558            sw.write(r'(String[] args)') 
     1559        else 
     1560            .writeJavaParams(sw) 
    14411561        if .genericParams.count 
    14421562            sw.indent 
    14431563            for param in .genericParams 
     
    14481568            sw.write(';\n') 
    14491569        else 
    14501570            if .isAbstract, sw.writeLine(';') 
    1451             else, .writeJavaImp(sw) 
     1571            else, .writeJavaImp(sw, false) 
    14521572            if _requirePart, _requirePart.writeJavaMethod(sw) 
    14531573            if _ensurePart, _ensurePart.writeJavaMethod(sw) 
    14541574            if .compiler.includeTests, .writeJavaTest(sw) 
     
    14571577        base.writeJavaImpHeader(sw) 
    14581578        if .isMain 
    14591579            if .compiler.hasExceptionReportOption 
    1460                 sw.writeLine('try { // Exception Report') 
     1580                sw.writeLine('try { // Exception Report')  
    14611581                sw.indent 
    1462             else if .compiler.options.boolValue('debugging-tips') 
    1463                 sw.writeLine('try { // -debugging-tips') 
     1582            else if .compiler.options.boolValue('debugging-tips')  
     1583                sw.writeLine('try { // -debugging-tips  - turn off with -d/-debug (see cobra -h)') 
    14641584                sw.indent 
    14651585        if .isMain and .compiler.options.boolValue('include-tests') 
    1466             sw.writeLine('Cobra.Lang.CobraCore.RunAllTests();  // turn off with -include-tests:no (see cobra -h)') 
     1586            sw.writeLine('cobra.lang.CobraCore.runAllTests();  // turn off with -include-tests:no (see cobra -h)') 
    14671587 
    14681588    def writeJavaImpFooter(sw as CurlyWriter) 
    14691589        base.writeJavaImpFooter(sw) 
    14701590        if .isMain 
    14711591            if .compiler.hasExceptionReportOption 
    14721592                sw.dedent 
    1473                 sw.writeLine('} catch (java.lang.Throwable _lh_exceptionReportThrowable) { Cobra.Lang.CobraCore.HandleUnhandledException(_lh_exceptionReportThrowable); }') 
     1593                sw.writeLine('} catch (java.lang.Throwable _lh_exceptionReportThrowable) { cobra.lang.CobraCore.HandleUnhandledException(_lh_exceptionReportThrowable); }') 
    14741594            else if .compiler.options.boolValue('debugging-tips') 
    14751595                sw.dedent 
    14761596                sw.writeLine('} catch (java.lang.Throwable _lh_debuggingTipsThrowable) {') 
    14771597                sw.indent 
    1478                 sw.writeLine('Cobra.Lang.CobraCore.PrintDebuggingTips();') 
    1479                 sw.writeLine('throw _lh_debuggingTipsThrowable.fillInStackTrace();') 
     1598                sw.writeLine('cobra.lang.CobraCore.printDebuggingTips();') 
     1599                #sw.writeLine('throw _lh_debuggingTipsThrowable.fillInStackTrace();') 
     1600                sw.writeLine('_lh_debuggingTipsThrowable.printStackTrace();') 
    14801601                sw.dedent 
    14811602                sw.writeLine('}') 
    14821603 
    14831604    get javaName as String is override 
    1484         return .name.capitalized 
     1605        return .name #.capitalized 
    14851606 
     1607# Java, for its sins, does not have support for properties built into the language... 
     1608# efforts to correct this stupidity seem to be mired in language navel gazing plus associated  
     1609# belly button lint picking followed by mastubatory dick waving to find the most obscure and difficult  
     1610# corner cases which then leads to it being then dropped in the 'too hard' basket 
     1611# Historically and currently it instead uses a convention which leads to a whole lot of obfuscating boilerplate code 
     1612#   Its obviously too difficult to just copy C# (turnabout is fair play), accept and then evolve any edge misses  
    14861613 
    14871614class ProperDexer is partial 
    14881615 
     
    15791706            if not Path.isPathRooted(fileName) 
    15801707                fileName = Path.combine(Environment.currentDirectory, fileName) 
    15811708            fileName = Utils.javaStringLiteralFor(fileName) 
    1582             return 'new Cobra.Lang.SourceSite([fileName], [tok.lineNum], [boxName], [memberName], [javaThis])' 
     1709            return 'new cobra.lang.SourceSite([fileName], [tok.lineNum], [boxName], [memberName], [javaThis])' 
    15831710 
    15841711    get javaThis as String 
    15851712        if _inInitCall  # C# won't allow 'this' in a base constructor call -- TODO 
     
    15931720 
    15941721    def writeJavaSetLine(sw as CurlyWriter) 
    15951722        if _canSetLine and .token.lineNum > 0 
    1596             sw.write('Cobra.Lang.CobraImp._curFrame._lineNum = [.token.lineNum];\n') 
     1723            sw.write('cobra.lang.CobraImp._curFrame._lineNum = [.token.lineNum];\n') 
    15971724 
    15981725    def writeJavaStmt(sw as CurlyWriter) 
    15991726        assert .didBindImp 
     
    16081735        base.writeJavaDef(sw) 
    16091736        if not .compiler.options.boolValue('include-asserts') 
    16101737            return 
    1611         sw.write('if (Cobra.Lang.CobraCore._willCheckAssert && !') 
     1738        sw.write('if (cobra.lang.CobraCore._willCheckAssert') 
     1739        # TODO - implement cobra assertions - needs cobra assertException + Sourcesite 
     1740        /#  
     1741        sw.write(' && !') 
    16121742        _expr.writeJavaDef(sw) 
    1613         sw.write(') ') 
     1743        sw.write(')\n') 
    16141744        sw.indent 
    1615         sw.write('throw new Cobra.Lang.AssertException([.javaSourceSite], ') 
     1745         
     1746        # TODO later Implement SourceSite and CobraLang AssertException  
     1747        sw.write('throw new cobra.lang.AssertException([.javaSourceSite], ') 
    16161748        _expr.writeJavaBreakdown(sw) 
    16171749        sw.write('[.javaThis], ') 
    16181750        if _info 
     
    16211753            sw.write('null') 
    16221754        sw.write(');\n') 
    16231755        sw.dedent 
     1756        #/ 
     1757         
     1758        # use java asserts initially at least 
     1759        sw.write(')\n') 
     1760        sw.indent 
     1761        sw.write('assert ') 
     1762        _expr.writeJavaDef(sw) 
     1763        #_expr.writeJavaBreakdown(sw) 
     1764        #sw.write('[.javaThis]') 
     1765        if _info 
     1766            sw.write(' : ') 
     1767            _info.writeJavaDef(sw) 
     1768        else        # Tmp till get java asserts 
     1769            sw.write(' : ') 
     1770            sw.write('" assert ') 
     1771            _expr.writeJavaDef(sw) 
     1772            sw.write(' FAILED"') 
     1773             
     1774        sw.write(';\n') 
     1775        sw.dedent 
    16241776 
    16251777 
    16261778class BlockStmt is partial 
     
    16611813    def writeJavaDef(sw as CurlyWriter) 
    16621814        base.writeJavaDef(sw) 
    16631815        if _expr.type.isDynamic 
    1664             # if the expression is dynamic, then use an if-else ladder with CobraImp.Equals( 
     1816            # if the expression is dynamic, then use an if-else ladder with CobraImp.equals( 
    16651817            sw.writeLine('// branch [_expr.toCobraSource]') 
    16661818             
    16671819            varName = '_lh_branch_[.serialNum]' 
     
    16751827                sep = '' 
    16761828                for e in onPart.exprs 
    16771829                    sw.write(sep) 
    1678                     sw.write('Cobra.Lang.CobraImp.Equals([varName], ') 
     1830                    sw.write('cobra.lang.CobraImp.equals([varName], ') 
    16791831                    e.writeJavaDef(sw, false) 
    16801832                    sw.write(')') 
    16811833                    sep = ' || ' 
     
    17371889        sw.write('// exactly what is expected\n') 
    17381890        sw.write('[gotRightExceptionVarName] = true;\n') 
    17391891        sw.dedentAndWrite('}\n') 
    1740         if _exceptionType inherits Box and not (_exceptionType to Box).isSystemExceptionClass 
     1892        if _exceptionType inherits Box and not (_exceptionType to Box).isJvmSystemExceptionClass 
    17411893            wrongExceptionVarName = '_lh_expect_[_varNumber]' 
    17421894            assert gotRightExceptionVarName <> wrongExceptionVarName 
    17431895            sw.writeAndIndent('catch (java.lang.Throwable [wrongExceptionVarName]) {\n') 
    1744             sw.write('throw new Cobra.Lang.ExpectException(typeof([exceptionTypeRef]), [wrongExceptionVarName]);\n') 
     1896            sw.write('throw new cobra.lang.ExpectException(typeof([exceptionTypeRef]), [wrongExceptionVarName]);\n') 
    17451897            sw.dedentAndWrite('}\n') 
    1746         sw.write('if (![gotRightExceptionVarName]) throw new Cobra.Lang.ExpectException([exceptionTypeRef].getClass(), null);\n') 
     1898        sw.write('if (![gotRightExceptionVarName]) throw new cobra.lang.ExpectException([exceptionTypeRef].getClass(), null);\n') 
    17471899 
    17481900 
    17491901class ForStmt is partial 
     
    17581910        varName = _var.javaName 
    17591911        trackLocals = .compiler.willTrackLocals 
    17601912        if trackLocals 
    1761             sw.write('for (Cobra.Lang.CobraImp.SetLocal("[.var.name]", [varName]=') 
     1913            sw.write('for (cobra.lang.CobraImp.setLocal("[.var.name]", [varName]=') 
    17621914        else 
    17631915            sw.write('for ([varName]=') 
    17641916        _start.writeJavaDef(sw) 
    17651917        if trackLocals 
    17661918            sw.write(')') 
    17671919        if _var.type.isDynamic 
    1768             sw.write('; Cobra.Lang.CobraImp.DynamicCompare([varName], ') 
     1920            sw.write('; cobra.lang.CobraImp.dynamicCompare([varName], ') 
    17691921            _stop.writeJavaDef(sw, false) 
    17701922            sw.write(')[if(_dir==1, "<", ">")]0') 
    17711923            opName = if(_dir==1, 'op_Addition', 'op_Subtraction') 
    1772             sw.write('; [varName]=Cobra.Lang.CobraImp.DynamicOp("[opName]", [varName], ') 
     1924            sw.write('; [varName]=cobra.lang.CobraImp.dynamicOp("[opName]", [varName], ') 
    17731925            if _step, _step.writeJavaDef(sw, false) 
    17741926            else, sw.write('1') 
    17751927            sw.write(')') 
     
    18001952        # TODO: this is the old numeric for loop behavior.  
    18011953        varName = _var.javaName 
    18021954        trackLocals = .compiler.willTrackLocals 
    1803         if trackLocals, sw.write('for (Cobra.Lang.CobraImp.SetLocal("[.var.name]", [varName]=') 
     1955        if trackLocals, sw.write('for (cobra.lang.CobraImp.setLocal("[.var.name]", [varName]=') 
    18041956        else, sw.write('for ([varName]=') 
    18051957        _start.writeJavaDef(sw) 
    18061958        if trackLocals 
    18071959            sw.write(')') 
    1808         sw.write('; Cobra.Lang.CobraImp.DynamicCompare([varName], ') 
     1960        sw.write('; cobra.lang.CobraImp.dynamicCompare([varName], ') 
    18091961        _stop.writeJavaDef(sw, false) 
    18101962        sw.write(')[if(_dir==1, "<", ">")]0') 
    18111963        opName = if(_dir==1, 'op_Addition', 'op_Subtraction') 
    1812         sw.write('; [varName]=Cobra.Lang.CobraImp.DynamicOp("[opName]", [varName], ') 
     1964        sw.write('; [varName]=cobra.lang.CobraImp.dynamicOp("[opName]", [varName], ') 
    18131965        if _step, _step.writeJavaDef(sw, false) 
    18141966        else, sw.write('1') 
    18151967        sw.write(')') 
     
    18752027            sw.write('int [javaDir] = [javaStep] < 0 ? -1 : +1;\n') 
    18762028 
    18772029        sw.write('for(') 
    1878         if trackLocals, sw.write('Cobra.Lang.CobraImp.SetLocal("[.var.name]", [javaVar] = [javaStart])') 
     2030        if trackLocals, sw.write('cobra.lang.CobraImp.setLocal("[.var.name]", [javaVar] = [javaStart])') 
    18792031        else, sw.write('[javaVar] = [javaStart]')        
    18802032        if isSimpleStep, sw.write('; [javaVar] < [javaStop] ; ') 
    18812033        else, sw.write('; ([javaDir]==1) ? [javaVar] < [javaStop] : [javaVar] > [javaStop]; ') 
    1882         if trackLocals, sw.write('Cobra.Lang.CobraImp.SetLocal("[.var.name]", [javaVar] += [javaStep])') 
     2034        if trackLocals, sw.write('cobra.lang.CobraImp.setLocal("[.var.name]", [javaVar] += [javaStep])') 
    18832035        else, sw.write('[javaVar] += [javaStep]')        
    18842036        sw.write(') ') 
    18852037 
     
    19022054        # TODO: the javaRef of a type is not qualified and there is no using System.Collections; 
    19032055        # _what.writeJavaDefInContext(sw, false) 
    19042056        if _what.type.isDynamic 
    1905             sw.write('Cobra.Lang.CobraImp.GetEnumerable(') 
     2057            sw.write('cobra.lang.CobraImp.getEnumerable(') # TODO shld be getIterable ?? 
    19062058            _what.writeJavaDef(sw, false) 
    19072059            sw.write(')') 
    19082060        else 
     
    19112063        sw.write(')') 
    19122064        stmt = '[.var.javaName] = [helperName]' 
    19132065        if .compiler.willTrackLocals 
    1914             stmt = 'Cobra.Lang.CobraImp.SetLocal("[.var.name]", [stmt])' 
     2066            stmt = 'cobra.lang.CobraImp.setLocal("[.var.name]", [stmt])' 
    19152067        stmt += ';\n' 
    19162068        _block.writeJavaDef(sw, stmt) 
    19172069 
     
    19662118 
    19672119    def writeJavaDef(sw as CurlyWriter) 
    19682120        base.writeJavaDef(sw) 
    1969         if _destination 
     2121        if _destination # java Writer 
    19702122            _destination.writeJavaDef(sw, true) 
    1971             methodName = if(_stop, 'Write', 'WriteLine') 
     2123            methodName = if(_stop, 'write', 'writeLine') 
    19722124            sw.write('.[methodName](') 
    19732125        else 
    1974             methodName = if(_stop, 'PrintStop', 'PrintLine') 
    1975             sw.write('Cobra.Lang.CobraImp.[methodName](') 
     2126            methodName = if(_stop, 'printStop', 'printLine') 
     2127            sw.write('cobra.lang.CobraImp.[methodName](') 
    19762128        sep = '' 
    19772129        for arg in _args 
    1978             sw.write('[sep]Cobra.Lang.CobraImp._printStringMaker.MakeString(') 
     2130            sw.write('[sep]cobra.lang.CobraImp._printStringMaker.makeString(') 
    19792131            arg.writeJavaDef(sw) 
    19802132            sw.write(')') 
    19812133            sep = '+" "+' 
     
    19862138 
    19872139    def writeJavaDef(sw as CurlyWriter) 
    19882140        base.writeJavaDef(sw) 
    1989         sw.write('Cobra.Lang.CobraImp.PushPrintTo(') 
     2141        sw.write('cobra.lang.CobraImp.pushPrintTo(') 
    19902142        _destination.writeJavaDef(sw, false) 
    19912143        sw.write(');\n') 
    19922144        sw.write('try') 
    19932145        _block.writeJavaDef(sw) 
    19942146        sw.write('finally {\n') 
    19952147        sw.indent 
    1996         sw.write('Cobra.Lang.CobraImp.PopPrintTo();\n') 
     2148        sw.write('cobra.lang.CobraImp.popPrintTo();\n') 
    19972149        sw.dedent 
    19982150        sw.write('}\n') 
    19992151 
     
    20022154 
    20032155    def writeJavaDef(sw as CurlyWriter) 
    20042156        base.writeJavaDef(sw) 
    2005         name = .name.capitalized 
     2157        name = .name #.capitalized 
    20062158        localName = '_lh_event_[.serialNum]' 
    20072159        sw.writeLine('// raise [.name] ...') 
    20082160        sw.write('{ [_eventType.javaRef] [localName] = this.[name]; if ([localName]!=null) [localName](') 
     
    20852237        base.writeJavaDef(sw) 
    20862238        branch .direction 
    20872239            on Direction.In,    pass 
    2088             on Direction.Out,   sw.write('out ')  # TODO 
    2089             on Direction.InOut, sw.write('ref ')  # TODO 
     2240            on Direction.Out,   sw.write('/*out*/')  # TODO 
     2241            on Direction.InOut, sw.write('/*ref*/ ')  # TODO 
    20902242        .writeJavaDef(sw, true) 
    20912243 
    20922244    def writeJavaDef(sw as CurlyWriter, parens as bool) 
     2245        #print 'Expr.writeJavaDef', this 
    20932246        pass 
    20942247 
    20952248    def writeJavaStmt(sw as CurlyWriter) is override 
     
    21202273class NameExpr is partial 
    21212274 
    21222275    get asJava as String 
    2123         return _definition.javaName 
     2276        #print 'Dbg: NameExpr::', _definition.javaName       
     2277        return _definition.javaName      
    21242278 
    21252279 
    21262280class AsExpr is partial 
     
    21302284        sw.write('// [_name] as [_type.name]\n') 
    21312285 
    21322286    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2287        #print .asJava 
    21332288        sw.write(.asJava) 
    2134  
    2135  
     2289         
    21362290class AnonymousMethodExpr is partial 
    21372291 
    21382292    # TODO 
     
    21522306        name = .name 
    21532307        if _definition inherits BoxMember and (_definition to BoxMember).binaryName 
    21542308            name = (_definition to BoxMember).binaryName to ! 
    2155         else 
    2156             name = name.capitalized 
     2309            # Tmp while remapping .Net libs  
     2310            if name.startsWithNonLowerLetter 
     2311                name = Utils.cobraNameForNativeMemberName(name)  
     2312        #else 
     2313        #   name = name.capitalized 
     2314        #trace name 
    21572315        sw.write('[name]') 
    21582316        if _genericArgTypes and _genericArgTypes.count 
    21592317            sw.write('<') 
     
    22142372        # recall that this cannot be the right side of "foo.bar" since that is a MemberExpr 
    22152373        java = .javaQualification + .javaName 
    22162374        if _requiresGetClass, java = java + '.getClass()' 
     2375        #print 'Dbg: IdExpr::', java 
    22172376        sw.write(java) 
    22182377 
    22192378    get javaQualification as String 
     
    22242383        else 
    22252384            pn = .definition.parentNameSpace 
    22262385            if pn, qual = pn.javaQualifier 
     2386        #print 'Dbg: IdExpr.qual::', qual 
    22272387        return qual 
    22282388         
    22292389    get javaName as String 
     
    22332393        if .superNode inherits DotExpr 
    22342394            assert this is not (.superNode to DotExpr).right  # should be a CallExpr or MemberExpr instead 
    22352395        defi = .namedDefinition 
     2396        #print 'Dbg: IdExpr.name::', defi.javaName 
    22362397        return defi.javaName 
    22372398 
    22382399    def _requiresGetClass as bool 
     
    22962457 
    22972458        # tpart: 
    22982459        src = Utils.javaStringLiteralFor(tpart.toCobraSource) 
    2299         sw.write(', [src], new Cobra.Lang.CobraDirectString(') 
     2460        sw.write(', [src], new cobra.lang.CobraDirectString(') 
    23002461        cond.writeJavaDefForBreakdown(sw) 
    2301         sw.write(' ? Cobra.Lang.CobraCore.ToTechString(') 
     2462        sw.write(' ? cobra.lang.CobraCore.toTechString(') 
    23022463        tpart.writeJavaDefForBreakdown(sw) 
    23032464        sw.write(') : "(not-evaluated)")') 
    23042465 
    23052466        # fpart: 
    23062467        src = Utils.javaStringLiteralFor(fpart.toCobraSource) 
    2307         sw.write(', [src], new Cobra.Lang.CobraDirectString(') 
     2468        sw.write(', [src], new cobra.lang.CobraDirectString(') 
    23082469        cond.writeJavaDefForBreakdown(sw) 
    2309         sw.write(' ? "(not-evaluated)" : Cobra.Lang.CobraCore.ToTechString(') 
     2470        sw.write(' ? "(not-evaluated)" : cobra.lang.CobraCore.toTechString(') 
    23102471        fpart.writeJavaDefForBreakdown(sw) 
    23112472        sw.write('))') 
    23122473 
     
    23172478 
    23182479    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
    23192480        if _target.type.isDynamic 
    2320             sw.write('Cobra.Lang.CobraImp.GetIndexerValue(') 
     2481            sw.write('cobra.lang.CobraImp.getIndexerValue(') 
    23212482            _target.writeJavaDef(sw, false) 
    23222483            for expr in _args 
    23232484                sw.write(', ') 
     
    23802541        _expr.writeJavaBreakdownItems(sw) 
    23812542 
    23822543 
     2544class TruthExpr 
     2545    is partial 
     2546 
     2547    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2548        lparen = if(parens, '(', '') 
     2549        rparen = if(parens, ')', '') 
     2550        branch _treatment 
     2551            on Treatment.AsIs 
     2552                _expr.writeJavaDef(sw, parens) 
     2553            on Treatment.InvokeRuntime 
     2554                sw.write('CobraLangInternal.CobraImp.IsTrue(') 
     2555                _expr.writeJavaDef(sw, false) 
     2556                sw.write(')')                
     2557            on Treatment.CompareToZero 
     2558                sw.write('[lparen]0!=') 
     2559                _expr.writeJavaDef(sw, true) 
     2560                sw.write(rparen) 
     2561            on Treatment.CompareToZeroChar 
     2562                sw.write("[lparen]'\\0'!=") 
     2563                _expr.writeJavaDef(sw, true) 
     2564                sw.write(rparen) 
     2565            on Treatment.CompareToNull 
     2566                sw.write('[lparen]null!=') 
     2567                _expr.writeJavaDef(sw, true) 
     2568                sw.write(rparen) 
     2569 
     2570    def writeJavaBreakdownItems(sw as CurlyWriter) is override 
     2571        # leaving out the base class is intentional: 
     2572        # base.writeJavaBreakdownItems(sw, isFirstExpr) 
     2573        _expr.writeJavaBreakdownItems(sw) 
     2574         
     2575     
     2576class TypeExpr 
     2577    is partial 
     2578 
     2579    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2580        javaRef = _containedType.javaRef  
     2581        # handle the case of "X.X" where namespace and class are both called "X". 
     2582        # C# chokes on it because the first "X" is considered to be the type 
     2583        #if .curBox.name + '.' in javaRef 
     2584        #   javaRef = 'global::' + javaRef 
     2585        if _requiresTypeOf() 
     2586            sw.write('typeof(') 
     2587            sw.write(javaRef) 
     2588            sw.write(')') 
     2589        else 
     2590            sw.write(javaRef) 
     2591 
     2592/#  def _requiresTypeOf as bool 
     2593        # Cobra never requires that you wrap a type reference in typeof(Foo). 
     2594        # C# requires typeof() in a variety of circumstances and won't accept it in a variety of others. 
     2595        superNode = .superNode 
     2596        if superNode is nil 
     2597            return false 
     2598        else 
     2599            if superNode inherits DotExpr 
     2600                return false 
     2601            if superNode inherits PostCallExpr 
     2602                # could be Type(foo) or _bar(Type) 
     2603                # in C#, the second requires `typeof` and the first won't take it 
     2604                if superNode.expr is this 
     2605                    return false 
     2606            if superNode inherits BinaryOpExpr 
     2607                if this is superNode.right 
     2608                    if superNode inherits InheritsExpr or superNode inherits AbstractToExpr 
     2609                        return false 
     2610            return true 
     2611            #/ 
     2612             
     2613    def writeJavaDefForBreakdown(sw as CurlyWriter) is override 
     2614        requiresTypeOf = _requiresTypeOf # using C# version currently - chop ? 
     2615        if not requiresTypeOf, sw.write('typeof(') 
     2616        .writeSharpDef(sw) 
     2617        if not requiresTypeOf, sw.write(')') 
     2618 
     2619         
     2620class UnaryOpExpr 
     2621    is partial 
     2622 
     2623    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2624        if _op == 'PLUS' 
     2625            if parens 
     2626                sw.write('(') 
     2627            _expr.writeJavaDef(sw, false) 
     2628            if parens 
     2629                sw.write(')') 
     2630            return 
     2631        if _expr.type.isDynamic 
     2632            specs = OperatorSpecs.unaryOpSpecsByCobraText 
     2633            assert specs.containsKey(.token.text) 
     2634            spec = specs[.token.text] 
     2635            opText = Utils.javaStringLiteralFor(spec.opMethodName) 
     2636            sw.write('CobraLangInternal.CobraImp.DynamicOp([opText], ') 
     2637            _expr.writeJavaDef(sw, false) 
     2638            sw.write(')') 
     2639            return 
     2640        if parens 
     2641            sw.write('(') 
     2642        branch _op 
     2643            on 'MINUS' 
     2644                sw.write('-') 
     2645            on 'TILDE' 
     2646                sw.write('~') 
     2647            on 'NOT' 
     2648                sw.write('!') 
     2649            else 
     2650                throw FallThroughException(_op) 
     2651        _expr.writeJavaDef(sw) 
     2652        if parens 
     2653            sw.write(')') 
     2654 
     2655    def writeJavaBreakdownItems(sw as CurlyWriter) 
     2656        base.writeJavaBreakdownItems(sw) 
     2657        sw.write(', +1') 
     2658        _expr.writeJavaBreakdownItems(sw) 
     2659        sw.write(', -1') 
     2660 
     2661         
     2662         
     2663class Literal 
     2664    is partial 
     2665 
     2666    def asJava as String 
     2667        return '/* TODO_Literal */' 
     2668 
     2669    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2670        sw.write(.asJava) 
     2671 
     2672 
     2673class AtomicLiteral 
     2674    is partial 
     2675 
     2676    get willWriteJavaBreakdownItems as bool is override 
     2677        return false 
     2678 
     2679class IntegerLit is partial 
     2680 
     2681    def asJava as String is override 
     2682        s = '' 
     2683        if (info = .token.info) inherits int 
     2684            branch info 
     2685                on - 8, s = 'byte'   # java.lang.Byte 
     2686                on + 8, s = 'short'  # unsigned Byte uint8 
     2687                on -16, s = 'short'  #'Int16' 
     2688                on +16, s = 'int'    # unsigned short UInt16' 
     2689                on -32, s = 'int'    # int32 
     2690                on +32, s = 'long'   # unsigned int32 
     2691                on -64, s = 'long' 
     2692                on +64, s = 'long'   # unsigned int64 
     2693                else, throw FallThroughException(info) 
     2694        if s.length <= 2 
     2695            return _value.toString + s 
     2696        else 
     2697            return '([s])[_value.toString]' 
     2698         
     2699class BoolLit 
     2700    is partial 
     2701 
     2702    def asJava as String is override 
     2703        return if(_value, 'true', 'false') 
     2704 
     2705 
     2706class CharLit 
     2707    is partial 
     2708 
     2709    def asJava as String is override 
     2710        if _value[0] to int == 39, return "'\\''"  # single quote 
     2711        else, return "'" + _value.toString + "'" 
     2712             
     2713         
     2714class NilLiteral 
     2715    is partial 
     2716 
     2717    def asJava as String is override 
     2718        return 'null' 
     2719 
     2720class StringLit is partial 
     2721 
     2722    def asJava as String is override 
     2723        return Utils.javaStringLiteralFor(_string) 
     2724     
     2725class StringSubstLit is partial 
     2726 
     2727    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2728        if _items.count>1 
     2729            sw.write('cobra.lang.CobraImp._printStringMaker.makeString(') 
     2730        sep = '' 
     2731        for item in _items 
     2732            sw.write(sep) 
     2733            if item inherits StringLit 
     2734                item.writeJavaDef(sw, true)  # CC: axe the "true" when the bug about overload groups crossing inheritance is fixed 
     2735            else if item inherits FormattedExpr 
     2736                sw.write('cobra.lang.CobraImp._printStringMaker.makeString(') 
     2737                item.expr.writeJavaDef(sw) 
     2738                sw.write(',') 
     2739                sw.write(Utils.javaStringLiteralFor(item.format)) 
     2740                sw.write(')') 
     2741            else 
     2742                sw.write('cobra.lang.CobraImp._printStringMaker.makeString(') 
     2743                item.writeJavaDef(sw, false) 
     2744                sw.write(')') 
     2745            sep = ',' 
     2746        if _items.count>1 
     2747            sw.write(')') 
     2748 
     2749class BaseLit is partial 
     2750 
     2751    def asJava as String is override 
     2752        return 'super' 
     2753 
     2754 
     2755class ThisLit is partial 
     2756 
     2757    def asJava as String is override 
     2758        return .compiler.curBox.javaThis 
     2759 
     2760 
     2761class VarLit is partial 
     2762 
     2763    def asJava as String is override 
     2764        return _name 
     2765 
     2766         
     2767             
    23832768## 
     2769## Binary Expressions 
     2770## 
     2771 
     2772class BinaryOpExpr is partial 
     2773 
     2774    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2775        if parens, sw.write('(') 
     2776        _writeJavaDef(sw) 
     2777        if parens, sw.write(')') 
     2778 
     2779    def _writeJavaDef(sw as CurlyWriter) 
     2780        sw.write('/* TODO_BinaryOp */') 
     2781        # pass 
     2782 
     2783    def writeJavaBreakdownItems(sw as CurlyWriter) 
     2784        base.writeJavaBreakdownItems(sw) 
     2785        sw.write(', +1') 
     2786        _writeJavaBreakdownItemsLeft(sw) 
     2787        _writeJavaBreakdownItemsRight(sw) 
     2788        sw.write(', -1') 
     2789 
     2790    def _writeJavaBreakdownItemsLeft(sw as CurlyWriter) 
     2791        _left.writeJavaBreakdownItems(sw) 
     2792 
     2793    def _writeJavaBreakdownItemsRight(sw as CurlyWriter) 
     2794        _right.writeJavaBreakdownItems(sw) 
     2795 
     2796         
     2797class AbstractAssignExpr is partial 
     2798 
     2799    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2800        if _trackLocal 
     2801            sw.write('CobraLangInternal.CobraImp.SetLocal("[_trackName]", ') 
     2802        else if parens 
     2803            sw.write('(') 
     2804        _writeJavaDef(sw) 
     2805        if _trackLocal or parens 
     2806            sw.write(')') 
     2807 
     2808 
     2809class AssignExpr is partial 
     2810 
     2811    def _writeJavaDef(sw as CurlyWriter) is override 
     2812        # TODO: 
     2813        # if trackLocal: 
     2814        #   out.write('CobraLangInternal.CobraImp.SetLocal("%s", ' % .left.name) 
     2815        if _left inherits IndexExpr 
     2816            if _left.target.type.isDynamic 
     2817                # assigning to an indexer of a dynamically typed target requires special code gen 
     2818                sw.write('CobraLangInternal.CobraImp.SetIndexerValue(') 
     2819                _left.target.writeJavaDef(sw, false) 
     2820                sw.write(', ') 
     2821                _right.writeJavaDef(sw, false) 
     2822                for expr in _left.args 
     2823                    sw.write(', ') 
     2824                    expr.writeJavaDef(sw, false) 
     2825                sw.write(')') 
     2826                return 
     2827        handled = false 
     2828        if _left inherits IdentifierExpr 
     2829            names = _left.javaAssignmentNames 
     2830            if names and names.count 
     2831                names.reverse 
     2832                for i in names.count 
     2833                    sw.write(if(i==0, '', '=')) 
     2834                    assert names[i].length 
     2835                    sw.write(names[i]) 
     2836            else 
     2837                assert _left.javaName <> '' 
     2838                sw.write(_left.javaName) 
     2839            handled = true 
     2840        if not handled 
     2841            # `obj.foo = bar` where `obj` is dynamic, requires special handling 
     2842            if _left inherits DotExpr 
     2843                if _left.left.type.isDynamic 
     2844                    assert _left.right inherits MemberExpr 
     2845                    sw.write('CobraLangInternal.CobraImp.setPropertyValue(') 
     2846                    _left.left.writeJavaDef(sw, false) 
     2847                    sw.write(', ') 
     2848                    sw.write(Utils.javaStringLiteralFor((_left.right to MemberExpr).name)) 
     2849                    sw.write(', ') 
     2850                    _right.writeJavaDef(sw) 
     2851                    sw.write(')') 
     2852                    return 
     2853        if not handled 
     2854            # for something like "p.total = 0", cannot generate "(p.Total)=0" because then C# sees 
     2855            # the left hand side as an r-value instead an l-value/target. hence the false below. 
     2856            _left.writeJavaDef(sw, false) 
     2857        sw.write('=') 
     2858        _right.writeJavaDefInContext(sw) 
     2859        # handle the case where a type got backed up because of assignment inside of an if-inherits 
     2860        if _backUpIfInheritsStack 
     2861            assert _left.definition inherits IVar 
     2862            _left.definition.ifInheritsStack = Stack<of IType>(_backUpIfInheritsStack) 
     2863 
     2864class CompareExpr 
     2865    is partial 
     2866 
     2867    var _cobraToJava = { 
     2868        'EQ': '==', 
     2869        'NE': '!=', 
     2870        'GT': '>', 
     2871        'LT': '<', 
     2872        'GE': '>=', 
     2873        'LE': '<=', 
     2874        'IS': '==', 
     2875        'ISNOT': '!=', 
     2876    } 
     2877     
     2878    def _writeJavaDef(sw as CurlyWriter) is override 
     2879        left = _left 
     2880        right = _right 
     2881        op = _op 
     2882        # Compute the java operation which will be an operator or method call 
     2883        if op=='EQ' or op=='NE' 
     2884            if not left.type.isReference and not right.type.isReference 
     2885                # struct/value types 
     2886                #if not left.type inherits PrimitiveType and not right.type inherits PrimitiveType 
     2887                #   # user-defined structs 
     2888                #   op = '.Equals(' 
     2889                #else 
     2890                #   # primitives like ints and decimals (even mixed like someDecimal == someInt) 
     2891                #   op = _cobraToJava[_op] 
     2892                op = _cobraToJava[_op] 
     2893            else 
     2894                done = false 
     2895                stringType = .compiler.stringType 
     2896                if left.isKindOf(stringType) and right.isKindOf(stringType)  # TODO: check for static comparison operations instead 
     2897                    op = _cobraToJava[_op] 
     2898                    done = true 
     2899                else if left.type inherits Box  # TODO: try skipping on requiring that the type is a Box 
     2900                    leftBox = left.type to Box 
     2901                    compareTo = leftBox.memberForName('compareTo') 
     2902                    if compareTo and compareTo.isMethod and compareTo.resultType.isDescendantOf(.compiler.anyIntType) and right.type.isDescendantOf(leftBox)  # need last condition to prevent someString.CompareTo(someChar) 
     2903                        op = '.compareTo(' 
     2904                        done = true 
     2905                if not done 
     2906                    assert op in ['EQ', 'NE'] 
     2907                    assert op == .token.which 
     2908                    op = '.equals(' 
     2909        else if op=='IS' or op=='ISNOT' 
     2910            if left.type inherits PrimitiveType and right.type inherits PrimitiveType 
     2911                op = _cobraToJava[_op] 
     2912            else if left.type.isReference and right.type.isReference 
     2913                op = if(op=='IS', ' instanceof ', '! instanceof ') 
     2914            else 
     2915                # non-trivial situation.. fall back to runtime support 
     2916                op = if(op=='IS', 'CobraLangInternal.CobraImp.Is(', 'CobraLangInternal.CobraImp.IsNot(') 
     2917        else 
     2918            if left.type.isDynamic or right.type.isDynamic 
     2919                sw.write('CobraLangInternal.CobraImp.DynamicCompare(') 
     2920                left.writeJavaDef(sw, false) 
     2921                sw.write(', ') 
     2922                right.writeJavaDef(sw, false) 
     2923                sw.write(')[_cobraToJava[_op]]0') 
     2924                return 
     2925            else 
     2926                done = false 
     2927                if left.type inherits Box  # TODO: try skipping on requiring that the type is a Box 
     2928                    leftBox = left.type to Box 
     2929                    compareTo = leftBox.memberForName('compareTo') 
     2930                    if compareTo and compareTo.isMethod and compareTo.resultType.isDescendantOf(.compiler.anyIntType) and left.type == right.type  # need last condition to prevent someString.CompareTo(someChar) 
     2931                        op = '.compareTo(' 
     2932                        done = true 
     2933                if not done 
     2934                    op = _cobraToJava[_op] 
     2935        # Write the Java code 
     2936        if op.length <= 2 
     2937            left.writeJavaDef(sw) 
     2938            sw.write(op) 
     2939            right.writeJavaDef(sw) 
     2940        else if op == '.equals(' 
     2941            if _op == 'NE', sw.write('!(') 
     2942            left.writeJavaDef(sw) 
     2943            sw.write(op) 
     2944            right.writeJavaDef(sw, false) 
     2945            sw.write(')') 
     2946            if _op == 'NE', sw.write(')') 
     2947        else if op == '.compareTo(' 
     2948            left.writeJavaDef(sw) 
     2949            sw.write(op) 
     2950            right.writeJavaDef(sw, false) 
     2951            sw.write(') [_cobraToJava[_op]] 0') 
     2952        else if op.endsWith('(') 
     2953            sw.write(op) 
     2954            left.writeJavaDef(sw) 
     2955            sw.write(',') 
     2956            right.writeJavaDef(sw) 
     2957            sw.write(')') 
     2958        else 
     2959            throw FallThroughException(op) 
     2960 
     2961class ChainedCompareExpr is partial 
     2962     
     2963    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     2964        if parens, sw.write('(') 
     2965        .writeJavaDef(sw) 
     2966        if parens, sw.write(')') 
     2967     
     2968    def writeJavaDef(sw as CurlyWriter) is override 
     2969        sw.write('CobraLangInternal.CobraCore.ChainedComparison(') 
     2970        _items[0].writeJavaDef(sw) 
     2971        itemIndex = 1 
     2972        for operation in _operations 
     2973            sw.write(', "[operation]", ') 
     2974            _items[itemIndex].writeJavaDef(sw) 
     2975            itemIndex += 1 
     2976        sw.write(')') 
     2977         
     2978     
     2979class DotExpr 
     2980    is partial 
     2981 
     2982/#  def needsContextCast as bool  # in SharpGenerator 
     2983        r = base.needsContextCast 
     2984        if not r 
     2985            r = .left.type.isDynamic 
     2986            # Why isn't the base implementation sufficient? 
     2987            # Because for `d.getType` where `d` is dynamic, the type of `d.getType` is *not*. 
     2988            # It`s System.Type because `getType` is recognized as an Object method. 
     2989            # This would confuse the code generation into thinking that `d.getType` is a statically typed expression. 
     2990        return r 
     2991#/ 
     2992 
     2993    def _writeJavaDef(sw as CurlyWriter) is override 
     2994        if _left.receiverType.isDynamic 
     2995            # handle dynamic typing 
     2996            if _dotRightExpr.definition 
     2997                sw.write('(' + _dotRightExpr.type.javaRef + ')') 
     2998            if _right inherits MemberExpr 
     2999                sw.write('CobraLangInternal.CobraImp.GetPropertyValue(') 
     3000                _left.writeJavaDef(sw, not _left inherits DotExpr) 
     3001                sw.write(', ') 
     3002                sw.write(Utils.javaStringLiteralFor(_right.name)) # was .capitalized 
     3003                sw.write(')') 
     3004            else if _right inherits CallExpr 
     3005                sw.write('CobraLangInternal.CobraImp.InvokeMethod(') 
     3006                _left.writeJavaDef(sw, not _left inherits DotExpr) 
     3007                sw.write(', ') 
     3008                sw.write(Utils.javaStringLiteralFor(_right.name))   # was .capitalized 
     3009                for arg in _right.args 
     3010                    sw.write(', ') 
     3011                    arg.writeJavaDef(sw, false) 
     3012                sw.write(')') 
     3013            else 
     3014                throw FallThroughException(_right) 
     3015        else 
     3016            # Given Cobra "A.B.C()" where C is a class/type/struct, then the java needs to be "new A.B.C()" 
     3017            # (But stuff like this makes me wonder if the ASTs should be doing some transformations, like collapsing qualified types.) 
     3018            if _dotRightExpr.memberDefinition inherits BoxMember 
     3019                backing = _dotRightExpr.definition.sharedMethodBacking 
     3020                if backing 
     3021                    # example:  Cobra: c.isUpper   C#: char.IsUpper(c) 
     3022                    # also used for extension methods under .NET 2.0 
     3023                    sw.write(backing+'(') 
     3024                    if not (_dotRightExpr.memberDefinition to BoxMember).sharedMethodBackingIsAlias  # guard against Cobra "decimal.parse('5.0')" --> C# "Decimal.Parse(decimal, "5.0")" 
     3025                        _left.writeJavaDef(sw, false) 
     3026                        sep = ', ' 
     3027                    else 
     3028                        sep = '' 
     3029                    if _right inherits CallExpr 
     3030                        for arg in _right.args 
     3031                            sw.write(sep) 
     3032                            arg.writeJavaDefInContext(sw) 
     3033                            sep = ', ' 
     3034                    sw.write(')') 
     3035                    return 
     3036            # handle static typing 
     3037            # don't write 'this' for shared members 
     3038            writeThis = true 
     3039            if _left inherits ThisLit 
     3040                writeThis = not _dotRightExpr.memberDefinition.isShared 
     3041            else if .curCodeMember inherits Initializer and _right inherits IDotRightExpr and (_right to IDotRightExpr).name == 'init' and _left inherits ThisOrBaseLit 
     3042                Stmt.inInitCall = true 
     3043                didSetInInitCall = true 
     3044                writeThis = false 
     3045            if writeThis 
     3046                if _left.needsContextCast 
     3047                    _left.writeJavaDefInContext(sw) 
     3048                else 
     3049                    _left.writeJavaDef(sw, not _left inherits DotExpr) 
     3050                sw.write('.') 
     3051            #print 'Dbg: dotExpr::', _left.toCobraSource, _right.toCobraSource 
     3052            _right.writeJavaDef(sw, false) 
     3053            if didSetInInitCall 
     3054                Stmt.inInitCall = false 
     3055 
     3056    def _writeJavaBreakdownItemsLeft(sw as CurlyWriter) is override 
     3057        _left.writeJavaBreakdownItems(sw) 
     3058 
     3059 
     3060 
     3061class CoalesceExpr 
     3062    is partial 
     3063 
     3064    def _writeJavaDef(sw as CurlyWriter) is override 
     3065        # (L != null ? L : R ) 
     3066        sw.write('((') 
     3067        _left.writeJavaDef(sw) 
     3068        sw.write(') != null ? ') 
     3069        _left.writeJavaDef(sw) 
     3070        sw.write(' : ') 
     3071        _right.writeJavaDef(sw) 
     3072         
     3073class CoalesceAssignExpr 
     3074    is partial 
     3075 
     3076    def _writeJavaDef(sw as CurlyWriter) is override 
     3077        # L = (L != null ? L : R ) 
     3078        _left.writeJavaDef(sw) 
     3079        sw.write(' = ') 
     3080        sw.write('((') 
     3081        _left.writeJavaDef(sw) 
     3082        sw.write(') != null ? ') 
     3083        _left.writeJavaDef(sw) 
     3084        sw.write(' : ') 
     3085        _right.writeJavaDef(sw) 
     3086 
     3087         
     3088class MemberExpr 
     3089    is partial 
     3090 
     3091    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     3092        assert .superNode inherits DotExpr 
     3093        if _definition inherits BoxMember 
     3094            name = _definition.binaryName 
     3095        #if name is nil 
     3096        #   name = _name.capitalized 
     3097        if name is nil 
     3098            name = _name 
     3099        #print 'Dbg: MemberExpr::', name 
     3100        sw.write(name) 
     3101        if _definition and (_definition.isMethod or _name=='toString') and not _isReference  # TODO: axe the 'toString' check 
     3102            sw.write('()') 
     3103 
     3104    def writeJavaBreakdownItems(sw as CurlyWriter) is override 
     3105        pass 
     3106 
     3107class SharpExpr 
     3108    is partial 
     3109 
     3110    def writeJavaDef(sw as CurlyWriter, parens as bool) is override 
     3111        if parens, sw.write('(') 
     3112        if _sharpSource 
     3113            sw.write(_sharpSource) 
     3114        else 
     3115            sw.write(_expr.token.value) 
     3116        if parens, sw.write(')') 
     3117 
     3118## 
    23843119## Temporary 
    23853120## 
    23863121 
     
    23913126    def writeJavaTestInvocation(sw as CurlyWriter) 
    23923127        pass 
    23933128 
    2394 class IntegerLit is partial 
    2395  
    2396     def asJava as String 
    2397         return 'TODO' 
    2398  
    23993129class EnumMember is partial 
    24003130 
    24013131    def writeJavaTestInvocation(sw as CurlyWriter) 
     
    24043134class Extension is partial 
    24053135 
    24063136    get javaKeyWord as String is override 
    2407         return '' 
     3137        return 'TODO_Extension' 
    24083138     
    24093139    get javaInvariantVisibility as String is override 
    24103140        return '' 
     
    24223152    shared 
    24233153 
    24243154        def javaStringLiteralFor(args as vari dynamic) as String 
    2425             # TODO: 
    2426             for arg in args, return arg 
    2427             return '' 
     3155            sb = StringBuilder() 
     3156            for arg in args  
     3157                sb.append(Utils.sharpStringLiteralFor(arg to String)) 
     3158            return sb.toString 
    24283159 
    24293160class ThisOrBaseLit is partial 
    24303161 
    2431     def asJava as String 
     3162    def asJava as String is override 
    24323163        return 'this' 
    2433  
     3164         
    24343165class ContractPart is partial 
    24353166 
    24363167    def writeJavaMethod(args as vari dynamic) 
    24373168        pass 
     3169         
     3170     
     3171class JavaBackEndUtils 
     3172    # copied fm SharpGenerator and keywds corrected:  chg entire method Vars.cobra:AbstractLocalVar,_init 
     3173    shared 
     3174 
     3175        var _backEndKeyWordList = 'assert boolean break byte case catch char class const continue default do double else extends false final finally float for goto if implements import instanceof int interface long native new null package private protected public return short static strictfp super switch synchronized this throw throws transient true try void volatile while'.split 
     3176            # C#    'abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual void volatile while'.split 
     3177        var _backEndKeyWordSet = Set<of String>() 
     3178 
     3179        def isBackEndKeyWord(word as String) as bool 
     3180            """ 
     3181            Returns true if the given word is a keyword in Java6 
     3182            """ 
     3183            require 
     3184                word.length 
     3185            test 
     3186                assert .isBackEndKeyWord('byte') 
     3187                assert .isBackEndKeyWord('if') 
     3188                assert .isBackEndKeyWord('while') 
     3189                assert not .isBackEndKeyWord('total') 
     3190            body 
     3191                if _backEndKeyWordSet.count == 0 
     3192                    for word in _backEndKeyWordList 
     3193                        _backEndKeyWordSet.add(word) 
     3194                return word in _backEndKeyWordSet 
     3195 
     3196        def backEndNameForLocalVarName(name as String) as String 
     3197            if .isBackEndKeyWord(name) 
     3198                return '$' + name  # Java supports $ as a prefix  
     3199            return name 
     3200         
  • Source/Enums.cobra

     
     1 
    12class EnumDecl 
    23    is partial 
    34    inherits Container<of EnumMember> 
     
    2526        _idToken = Token.empty 
    2627        _attribs = AttributeList() 
    2728        _nativeType = nativeType 
    28         _storageTypeNode = ClrTypeProxy(Enum.getUnderlyingType((_nativeType to ClrNativeType).clrType))  # TODO: fix native 
     29        #_storageTypeNode = ClrTypeProxy(Enum.getUnderlyingType((_nativeType to ClrNativeType).backEndType))  # TODO: fix native 
     30        _callNativeScanMethod('UnderlyingType') 
    2931        _needScanNativeType = true 
    30  
    31     def _scanClrType 
    32         # TODO: read attribs 
    33         _needScanNativeType = false 
    34         clrType = (_nativeType to ClrNativeType).clrType # TODO: fix native 
    35         isByte  = Enum.getUnderlyingType(clrType).name == 'Byte' 
    36         is64    = Enum.getUnderlyingType(clrType).name == 'Int64' 
    37         isU32   = Enum.getUnderlyingType(clrType).name == 'UInt32' 
    38         isU64   = Enum.getUnderlyingType(clrType).name == 'UInt64' 
    39         values  = Enum.getValues(clrType) 
    40         i = 0 
    41         for name in Enum.getNames(clrType) 
    42             value = values.getValue(i) 
    43             # CC: lameness follows 
    44             if isByte 
    45                 intValue = int.parse((value to uint8).toString) 
    46             else if is64 
    47                 try 
    48                     intValue = int.parse((value to int64).toString) 
    49                 catch OverflowException 
    50                     intValue = 999  # CC: omg. but probably doesn't affect anything. we're reading the DLL here, not creating one 
    51             else if isU32 
    52                 try 
    53                     intValue = int.parse((value to uint32).toString) 
    54                 catch OverflowException 
    55                     intValue = 2147483647 
    56             else if isU64 
    57                 try 
    58                     intValue = int.parse((value to uint64).toString) 
    59                 catch OverflowException 
    60                     intValue = 2147483647 
    61             else 
    62                 intValue = value to int 
    63             member = EnumMember(name, intValue) 
    64             member.enumDecl = this 
    65             .addDecl(member) 
    66             i += 1 
    67  
     32         
     33    def _callNativeScanMethod(tag as String) 
     34        """ 
     35        Call a backend scan method for native type scan operation desired and backend in use. 
     36        """ 
     37        _needScanNativeType = true 
     38        # This is icky too - method to call needs to be set directly via backend somehow rather than this check and call code    
     39        # TODO: change to use strategy object set when init backend. 
     40        assert .compiler 
     41        assert tag in ['ScanNativeType', 'UnderlyingType'] 
     42        backEnd = .compiler.backEnd 
     43        branch backEnd.name 
     44            on 'c#-clr' 
     45                branch tag 
     46                    on 'UnderlyingType',  _setUnderlyingTypeClr # sets _storageTypeNode 
     47                    on 'ScanNativeType',  _scanNativeTypeClr 
     48            on 'java-jvm' 
     49                branch tag 
     50                    on 'UnderlyingType',  _setUnderlyingTypeJvm # sets _storageTypeNode 
     51                    on 'ScanNativeType',  _scanNativeTypeJvm 
     52            on 'objc' 
     53                print 'objc back end need method for [tag]' 
     54                assert false, 'Missing backEnd infrastructure for [backEnd.getType.name]' 
     55                #branch on tag 
     56                #   on 'UnderlyingType',  _setUnderlyingTypeObjc 
     57                #   on 'ScanNativeType',  _scancNativeTypeObjc 
     58            else  
     59                throw FallThroughException('No nativeScanMethod code for backend [backEnd.name] [backEnd.getType.name]') 
     60        #TODO: remove all direct uses of ClrNativeType, ClrTypeProxy 
     61         
    6862    get attributes as AttributeList is override 
    6963        return _attribs 
    7064 
     
    9993            return base.isUsed 
    10094        set 
    10195            base.isUsed = value 
    102             if _needScanNativeType 
    103                 _scanClrType 
     96            if _needScanNativeType, _callNativeScanMethod('ScanNativeType') 
    10497 
    10598    get nativeType from var 
    10699     
     
    117110            _storageType = _storageTypeNode.realType 
    118111            if not _storageType.isDescendantOf(.compiler.anyIntType) 
    119112                .throwError('The enumeration storage type must be a primitive integer type such as int8, uint8, int16, uint16, int, uint, int64 or uint64.') 
    120         if _needScanNativeType 
    121             _scanClrType 
     113        if _needScanNativeType, _callNativeScanMethod('ScanNativeType') 
    122114 
    123115    def _bindImp is override 
    124116        base._bindImp 
     
    132124        return name 
    133125 
    134126    def memberForName(name as String) as IMember? 
    135         if _needScanNativeType 
    136             _scanClrType 
     127        if _needScanNativeType, _callNativeScanMethod('ScanNativeType') 
    137128        m = base.memberForName(name) 
    138129        if m is nil 
    139130            objClass = .compiler.objectType 
  • Tests/320-misc-two/800-attributes/130-attributes-tricky-names.cobra

     
    88with no warnings or errors. 
    99""" 
    1010use System.Xml 
    11 use System.Xml.Linq 
    1211use System.Xml.Serialization 
    1312 
    1413class Season has Serializable