Ticket #275: java-jvm-part3.patch
File java-jvm-part3.patch, 21.5 KB (added by hopscc, 13 years ago) |
---|
-
Source/Cobra.Lang/Java/mkjar
4 4 # copy them and std sig files to Source dir 5 5 6 6 [ -d classes ] || mkdir classes 7 javac -d classes CobraImp.java CobraCore.java 7 javac -d classes CobraImp.java CobraCore.java Delegate.java 8 8 [ $? == 0 ] || exit 9 9 jar cvf CobraLang.jar -C classes . 10 10 [ $? == 0 ] || exit -
Source/Cobra.Lang/Java/Delegate.java
1 /* 2 * Start of a Delegate baseclass for Cobra implemented for Java 3 * The cobra compiler java backend will be reponsible for mapping the construction, initialisation and 4 * invocation of a Delegate to the API below 5 * construct sig delName(param as paramType0,...) as retType -> d = new Delegate(retType, paramType0, ...) 6 * assign myDelegate as delName = ref inst.method -> d.init(inst, "method") 7 * call myDelegate(arg0,...) -> d.invoke(arg0,...) 8 * 9 * Doesnt support Generics. 10 * 11 * TODO: write some Tests exercising this implementation api 12 */ 13 14 package cobra.lang; 15 16 import java.lang.*; 17 import java.util.*; 18 import java.lang.reflect.*; 19 20 public class Delegate { 21 Class returnType; // method returnType 22 Class[] paramTypes; // Types of the method parameters 23 24 Class targetClass; 25 Object target; 26 String methodName; 27 Method method; 28 29 protected List<Delegate> multiCastList; 30 31 /* 32 * A Delegate is a Type describing a method signature (returnType and ParamTypes) that can hold a 33 * method and target to invoke it on (instance or static). Start with recording the signature 34 */ 35 public Delegate(Class returnType, Class... paramTypes) { 36 this.returnType = returnType; 37 this.paramTypes = paramTypes; 38 } 39 40 /* 41 * Initialise to a instance method on a particular target object 42 */ 43 public void init(Object target, String methodName){ 44 this.target = target; 45 this.targetClass = target.getClass(); 46 this.methodName = methodName; 47 matchMethod(); 48 } 49 50 /* 51 * initialise to a static method (on a target class) 52 */ 53 public void init(Class targetClass, String methodName){ 54 this.targetClass = targetClass; 55 this.methodName = methodName; 56 matchMethod(); 57 } 58 59 60 /* 61 * Ensure that there is a match for the given method name, return type and paramtypes on the target given. 62 * Record the Method and make accessible for later invocation 63 */ 64 @SuppressWarnings("unchecked") 65 void matchMethod() { 66 Class mclass = this.targetClass; 67 for(;;) { 68 try { 69 this.method = mclass.getDeclaredMethod(this.methodName, this.paramTypes); 70 this.method.setAccessible(true); 71 this.targetClass = mclass; 72 break; 73 } catch(NoSuchMethodException e) { 74 if (mclass == Object.class) { 75 throw new RuntimeException(e); 76 } else { 77 mclass = mclass.getSuperclass(); 78 } 79 } 80 } 81 Class methodType = this.method.getReturnType(); 82 if ( ! isCompatibleType(this.returnType, methodType)) { 83 String msg = "NoSuchMethodException "+this.methodName + ":" ; 84 msg += "method returnType" + methodType.getName() + " not compatible with Delegate returnType " + this.returnType.getName(); 85 throw new RuntimeException(new NoSuchMethodException(msg)); 86 } 87 } 88 89 /** Maps primitives to their corresponding wrappers and vice versa. */ 90 private static final Map<Class,Class> PRIMITIVES_MAP = new HashMap<Class,Class>(); 91 92 static { 93 PRIMITIVES_MAP.put(boolean.class, Boolean.class); 94 PRIMITIVES_MAP.put(byte.class, Byte.class); 95 PRIMITIVES_MAP.put(char.class, Character.class); 96 PRIMITIVES_MAP.put(double.class, Double.class); 97 PRIMITIVES_MAP.put(float.class, Float.class); 98 PRIMITIVES_MAP.put(int.class, Integer.class); 99 PRIMITIVES_MAP.put(long.class, Long.class); 100 PRIMITIVES_MAP.put(short.class, Short.class); 101 PRIMITIVES_MAP.put(Boolean.class, boolean.class); 102 PRIMITIVES_MAP.put(Byte.class, byte.class); 103 PRIMITIVES_MAP.put(Character.class, char.class); 104 PRIMITIVES_MAP.put(Double.class, double.class); 105 PRIMITIVES_MAP.put(Float.class, float.class); 106 PRIMITIVES_MAP.put(Integer.class, int.class); 107 PRIMITIVES_MAP.put(Long.class, long.class); 108 PRIMITIVES_MAP.put(Short.class, short.class); 109 } 110 111 private boolean isCompatibleType(Class<?> c1, Class<?> c2) { 112 return c1 == c2 || c1 == PRIMITIVES_MAP.get(c2) || c1.isAssignableFrom(c2) 113 || c2.isAssignableFrom(c1); 114 } 115 116 /** 117 * Executes the method synchronously on the calling thread and returns the 118 * result value. 119 * @param arguments Values to pass to the method. 120 * @return Result of calling the method. 121 */ 122 public Object invoke(Object... arguments) { 123 assert this.method != null; 124 Object result = null; 125 try { 126 result = this.method.invoke(this.target, arguments); 127 } catch(IllegalAccessException e) { 128 throw new RuntimeException(e); 129 } catch(InvocationTargetException e) { 130 throw new RuntimeException(e.getCause()); 131 } 132 if ( !this.multiCastList.isEmpty()) { 133 for (Delegate d : this.multiCastList) { 134 result = d.invoke(arguments); 135 } 136 } 137 return result; 138 } 139 140 /* 141 * Add an additional Delegate to make a multicast invocation List on a single Delegate. 142 * The original Delegate is not inserted in the multicast List 143 */ 144 public void add(Object target, String methodName){ 145 Delegate d = new Delegate(this.returnType, this.paramTypes); 146 if (target instanceof Class) 147 d.init((Class)target, methodName); 148 else 149 d.init(target, methodName); 150 151 if (this.multiCastList == null) { 152 this.multiCastList = new ArrayList<Delegate>(); 153 } 154 this.multiCastList.add(d); 155 } 156 157 /* 158 * Remove an entry from a multicast invocation List. 159 */ 160 public void remove(Object target, String methodName){ 161 if (this.multiCastList == null || this.multiCastList.isEmpty()) { 162 return; 163 } 164 Delegate found = null; 165 for (Delegate d : this.multiCastList) { 166 if (d.target == target && d.methodName == methodName) { 167 found = d; 168 break; 169 } 170 } 171 if (found != null) { 172 this.multiCastList.remove(found); 173 } 174 175 } 176 } -
Source/Cobra.Lang/Java/CobraImp.java
7 7 package cobra.lang; 8 8 9 9 import java.lang.*; 10 import java.util.*; 10 11 11 12 12 13 public class CobraImp { -
Source/Cobra.Lang/Java/mkjarAll
5 5 6 6 echo 'making RTL from java sources' 7 7 [ -d classes ] || mkdir classes 8 javac -d classes CobraImp.java CobraCore.java 8 javac -d classes CobraImp.java CobraCore.java Delegate.java 9 9 [ $? == 0 ] || exit 10 10 jar cvf CobraLang.jar -C classes . 11 11 [ $? == 0 ] || exit -
Source/BackEndJvm/to-do.text
24 24 DONE 31-Jan-2011 25 25 Unworkable Jul-2011 - cobra assumptions in code 26 26 Change to cobra casing 8-Jul-2011 27 27 revisit later (all lowcase) - backend variances on .canBeUndottedMemberName?? 28 28 29 29 java names lowcase 30 30 method Names - DONE 31-Jan-2011 … … 43 43 44 44 properties - pro/get/set 45 45 - auto convert to java getters/setters and map calls 46 - Whats the equiv for indexers 46 - Whats the equiv for indexers? 47 47 Look at Beans spec but otherwise use/convert to {get,set}Indexer method call. 48 48 <indexedT> getIndexer<T, indexedT>(T) and 49 49 setIndexer<T, indexedT>(T, indexedT) 50 50 DONE 51 51 52 codegen for props: 'propName' -> getPropName and setPropName 52 codegen for props: 'propName' -> getPropName (DONE) 53 setPropName convert propName = a.b.c -> setPropName(a.b.c) (DONE - minimally at least) 53 54 54 55 AutoMap map indexers '[]' to methods X.get(idx) v = X[idx] , X.set(idx,val) and X.put(idx,val) -> X[idx] = val 55 56 - unworkable - too many false positives … … 260 261 261 262 262 263 Delegates 264 Need some sort of placeholder for setProperties 265 Drop something into CobraCore - Cobra.Lang.Delegate? (DONE) 266 267 Delegate - dcl - returnType and paramList d = new Delegate( Class ret, Class... paramList) 268 - store ret and paramList types 269 - init (assign) method ref d.init( Object target, String methodName) 270 d.init( Class target, String methodName) 271 lookup target MethodName chk param types match, 272 get and store its Method m and Object target 273 - call d.invoke(Object... paramList) 274 m.invoke(target, paramList) 275 263 276 264 277 Events 265 wot to do 278 wot to do? 266 279 267 280 268 281 Exception Adaption -
Source/BackEndJvm/JvmBackEnd.cobra
19 19 'String' : 'Java.Lang.String', 20 20 'Exception' : 'Java.Lang.RuntimeException', 21 21 22 'Delegate' : ' System.Delegate', #cobra.lang.Delegate22 'Delegate' : 'Cobra.Lang.Delegate', 23 23 'Attribute' : 'Java.Lang.Annotation.Annotation', 24 24 'ICloneable': 'Java.Lang.Cloneable', 25 25 'IEnumerable': 'Java.Lang.Iterable', -
Source/BackEndJvm/JavaGenerator.cobra
81 81 outName = .computeOutNameJava 82 82 83 83 # compute backEndOptions 84 backEndOptions = '-d .' # Put namespaced classfiles in own hierarchy 84 backEndOptions = '-d . ' # Put namespaced classfiles in own hierarchy 85 backEndOptions += ' -Xlint:all ' # warn about everything (non std option) 85 86 86 87 # -optimize isn't supported by JVM, but it could potentially be used by Cobra itself 87 88 … … 648 649 return 'null' 649 650 650 651 get javaRef as String is override 651 return _wrappedType.javaRef + if(not _wrappedType.isReference, ' ?', '')652 return _wrappedType.javaRef + if(not _wrappedType.isReference, ' /*?*/ ', '') 652 653 653 654 654 655 class NilType is partial … … 1399 1400 if not local.isImplicit 1400 1401 sw.write('[local.type.javaRef] [local.javaName]') 1401 1402 init = local.type.javaInit 1402 if init.length, sw.write(' = [init]') 1403 if init.length 1404 if not local.type.isReference and init == 'null' 1405 pass 1406 else 1407 sw.write(' = [init]') 1403 1408 sw.write(';\n') 1409 sw.write('// end locals\n\n') 1404 1410 1405 1411 def writeJavaRequireParamDecls(sw as CurlyWriter) 1406 1412 sep = '' … … 1635 1641 # efforts to correct this stupidity seem to be mired in language navel gazing plus associated 1636 1642 # belly button lint picking followed by mastubatory dick waving to find the most obscure and difficult 1637 1643 # corner cases which then leads to it being then dropped in the 'too hard' basket 1638 # Historically and currently it instead uses a convention which leads to a whole lot of obfuscating boilerplate code1639 # 1644 # Historically and currently it instead uses a convention on paired methodNames which leads to a whole lot of obfuscating boilerplate code 1645 # Its obviously too difficult to just copy C# (turnabout is fair play), accept and then evolve any edge misses 1640 1646 1641 1647 class ProperDexer is partial 1642 1648 # AbstractBaseClass for Property and Indexer … … 1879 1885 _expr.writeJavaDef(sw) 1880 1886 #_expr.writeJavaBreakdown(sw) 1881 1887 #sw.write('[.javaThis]') 1888 sw.write(' : ') 1882 1889 if _info 1883 sw.write(' :')1890 sw.write('"') 1884 1891 _info.writeJavaDef(sw) 1885 else # Tmp till get java asserts 1886 sw.write(' : ') 1887 sw.write('" assert ') 1888 _expr.writeJavaDef(sw) 1892 sw.write('"') 1893 else 1894 sw.write('"assertion ') 1895 tmpsw = CurlyWriter(StringWriter(), sw.curlyLineNumberTreatment) 1896 _expr.writeJavaDef(tmpsw) 1897 sw.write(tmpsw.toString.replace('"', r'\"')) 1889 1898 sw.write(' FAILED"') 1890 1891 1899 sw.write(';\n') 1892 1900 sw.dedent 1893 1901 … … 2972 2980 2973 2981 2974 2982 class AssignExpr is partial 2975 2983 2984 var isJavaSetProperty = false 2985 2976 2986 def _writeJavaDef(sw as CurlyWriter) is override 2977 2987 # TODO: 2978 2988 # if trackLocal: … … 3019 3029 # for something like "p.total = 0", cannot generate "(p.Total)=0" because then C# sees 3020 3030 # the left hand side as an r-value instead an l-value/target. hence the false below. 3021 3031 _left.writeJavaDef(sw, false) 3022 sw.write('=') 3023 _right.writeJavaDefInContext(sw) 3032 if .isJavaSetProperty # set in MemberExpr.writeJavaDef 3033 sw.write('(') 3034 _right.writeJavaDefInContext(sw) 3035 sw.write(')') 3036 else 3037 sw.write('=') 3038 _right.writeJavaDefInContext(sw) 3024 3039 # handle the case where a type got backed up because of assignment inside of an if-inherits 3025 3040 if _backUpIfInheritsStack 3026 3041 assert _left.definition inherits IVar … … 3313 3328 3314 3329 def writeJavaDef(sw as CurlyWriter, parens as bool) is override 3315 3330 assert .superNode inherits DotExpr 3316 if _definition inherits BoxMember 3317 name = _definition.binaryName 3318 #if name is nil 3319 # name = _name.capitalized 3320 if name is nil 3321 name = _name 3331 if _definition inherits BoxMember, name = _definition.binaryName 3332 if name is nil, name = _name 3322 3333 #print 'Dbg: MemberExpr::', name 3323 3334 if _definition inherits Property 3324 xet='get' 3325 if _isLValue, xet = 'set' 3326 sw.write(xet+name) 3327 sw.write('()') 3335 lValue = _setPropInAssignExpr 3336 if lValue 3337 # TODO chk for use of 'is' prefixed props 3338 xet = 'set' 3339 sw.write(xet+name) 3340 lValue.isJavaSetProperty = true # flag assignExpr for remainder of setProp handling 3341 else 3342 xet = 'get' 3343 sw.write(xet+name) 3344 sw.write('()') 3328 3345 else 3329 3346 sw.write(name) 3330 if _definition and (_definition.isMethod or _name=='toString') and not _isReference # TODO: axe the 'toString' check3347 if _definition and (_definition.isMethod or _name=='toString') and not _isReference 3331 3348 sw.write('()') 3332 3349 3333 def _isLValue as bool 3350 def _setPropInAssignExpr as AssignExpr? 3351 """ Return ancestor assignExpr if member is the lvalue in an AssignExpr, nil otherwise.""" 3334 3352 if not (.superNode and .superNode inherits BinaryOpExpr) 3335 return false3353 return nil 3336 3354 bsn0 = this to INode 3337 3355 bsn = .binarySuperNode 3338 3356 while true 3339 3357 if bsn inherits AssignExpr and bsn0 is bsn.left 3340 return true3358 return bsn to AssignExpr 3341 3359 if not (bsn.superNode and bsn.superNode inherits BinaryOpExpr) 3342 return false3360 return nil 3343 3361 bsn0 = bsn 3344 3362 bsn = bsn.binarySuperNode 3345 3363 3346 3364 def writeJavaBreakdownItems(sw as CurlyWriter) is override 3347 3365 pass 3348 3366 3367 3368 class OldExpr 3369 is partial 3370 3371 var _javaVarName as String? 3372 pro javaVarName from var 3373 3374 def writeJavaAssignment(sw as CurlyWriter) 3375 require 3376 .didBindImp 3377 .javaVarName 3378 .type 3379 body 3380 sw.write('[.type.javaRef] [_javaVarName] = ') 3381 _expr.writeJavaDef(sw) 3382 sw.write(';\n') 3383 3384 def writeJavaDef(sw as CurlyWriter, parens as bool) is override 3385 assert _javaVarName 3386 # this gets called when generating the `ensure` code 3387 sw.write(_javaVarName) 3388 3389 3390 class PostCallExpr 3391 is partial 3392 3393 def writeJavaDef(sw as CurlyWriter, parens as bool) is override 3394 if _helperMethod 3395 sw.write(_helperMethod.name + '(') 3396 sep = '' 3397 for arg in _args 3398 sw.write(sep) 3399 if arg inherits AssignExpr 3400 arg = arg.right 3401 arg.writeJavaDefInContext(sw, false) 3402 sep = ',' 3403 sw.write(')') 3404 else 3405 if parens, sw.write('(') 3406 expr = _expr 3407 isMethodSig = false 3408 isDynamic = false 3409 if expr inherits TypeExpr 3410 if expr.containedType inherits ArrayType 3411 # arrays 3412 sw.write('new ') 3413 sw.write((expr.containedType to ArrayType).theWrappedType.javaRef) 3414 sw.write(r'[') 3415 .writeJavaArgs(sw) 3416 sw.write(r']') 3417 else 3418 sw.write('new ') 3419 expr.writeJavaDef(sw) 3420 sw.write('(') 3421 .writeJavaArgs(sw) 3422 sw.write(')') 3423 else if expr inherits IdentifierExpr 3424 if expr.isTypeReference 3425 sw.write('new ') 3426 expr.writeJavaDef(sw) 3427 sw.write('(') 3428 .writeJavaArgs(sw) 3429 sw.write(')') 3430 else if expr.receiverType inherits GenericParam # TODO: shouldn't expr.isTypeReference above have caught this? 3431 sw.write('new [expr.receiverType.javaRef](') 3432 .writeJavaArgs(sw) 3433 sw.write(')') 3434 else if expr.type.nonNil.isDescendantOf(.compiler.delegateType) 3435 isMethodSig = true 3436 else if expr.type.isSystemTypeClass or _type.isDynamic 3437 isDynamic = true 3438 else 3439 assert false, expr 3440 else if expr inherits IndexExpr 3441 if expr.type.nonNil.isDescendantOf(.compiler.delegateType) 3442 isMethodSig = true 3443 else if expr.type.isSystemTypeClass or _type.isDynamic 3444 isDynamic = true 3445 else 3446 assert false, expr 3447 else 3448 assert false, expr 3449 if isMethodSig 3450 expr.writeJavaDef(sw, false) 3451 sw.write('.invoke(') 3452 .writeJavaArgs(sw) 3453 sw.write(')') 3454 else if isDynamic 3455 defi = expr.definition 3456 assert not defi inherits Box, expr # TODO: just curious 3457 what = if(defi inherits IType, '([defi.javaName].class)', defi.javaName to String) 3458 whatType = defi.javaName to String 3459 if defi inherits IVar 3460 if defi.type.isDynamic 3461 what = '(java.lang.Class)' + what 3462 #sw.write('System.Activator.CreateInstance([what]') 3463 3464 if _args.count # maybe 3465 sw.write('(<Constructor([whatType]>[what].getConstructor(') 3466 .writeJavaArgs(sw, ', ') 3467 sw.write(')).newInstance(') 3468 .writeJavaArgs(sw, ', ') 3469 sw.write(')') 3470 else 3471 sw.write('[what].newInstance()') 3472 # maybe better do this 3473 #sw.write('cobra.lang.CobraImp.newInstance<[whatType]>([what],') 3474 #.writeJavaArgs(sw, ', ') 3475 #sw.write(')') 3476 if parens, sw.write(')') 3477 3478 def writeJavaArgs(sw as CurlyWriter) 3479 .writeJavaArgs(sw, '') 3480 3481 def writeJavaArgs(sw as CurlyWriter, sep as String) 3482 for arg in _args 3483 sw.write(sep) 3484 arg.writeJavaDefInContext(sw, false) 3485 sep = ',' 3486 3487 def writeJavaBreakdownItems(sw as CurlyWriter) 3488 base.writeJavaBreakdownItems(sw) 3489 sw.write(', +1') 3490 _expr.writeJavaBreakdownItems(sw) 3491 for expr in _args 3492 expr.writeJavaBreakdownItems(sw) 3493 sw.write(', -1') 3494 3495 3496 class RefExpr 3497 is partial 3498 3499 def writeJavaDef(sw as CurlyWriter, parens as bool) is override 3500 if parens 3501 sw.write('(') 3502 _expr.writeJavaDef(sw, false) 3503 if parens 3504 sw.write(')') 3505 3506 def writeJavaBreakdownItems(sw as CurlyWriter) 3507 base.writeJavaBreakdownItems(sw) 3508 # TODO 3509 3349 3510 class SharpExpr 3350 3511 is partial 3351 3512 … … 3381 3542 get javaInvariantVisibility as String is override 3382 3543 return '' 3383 3544 3384 class OldExpr is partial3385 3386 def writeJavaAssignment(args as vari dynamic)3387 pass3388 3389 get javaVarName as String3390 return ''3391 3392 3545 class Utils is partial 3393 3546 3394 3547 shared -
Tests/100-basics/034j-set-property.cobra
1 # .require. jvm 2 namespace Test 3 class Test 4 def main is shared 5 # this would be ideal but its deprecated 6 # maybe use to test Attributes/Annotations when add handling for them 7 #d = Date() 8 #minutes = d.minutes # d.getMinute 9 #d.minutes = minutes # d.setMinute 10 #print d 11 12 fd = Java.Beans.FeatureDescriptor() 13 fd.name = 'Polly' 14 fd.shortDescription = 'Polly wolly Doodle' 15 #print 'FeatureDescriptor: [fd.getName], [fd.getShortDescription]' 16 name = fd.name 17 fd.name = '[name]nu' 18 #print 'FeatureDescriptor: [fd.getName], [fd.getShortDescription]' 19 assert fd.name == 'Pollynu' 20 assert fd.shortDescription == 'Polly wolly Doodle' 21