|  | @@ -8,7 +8,6 @@ import org.openzen.zenscript.codemodel.CompareType;
 | 
		
	
		
			
			| 8 | 8 |  import org.openzen.zenscript.codemodel.FunctionParameter;
 | 
		
	
		
			
			| 9 | 9 |  import org.openzen.zenscript.codemodel.expression.*;
 | 
		
	
		
			
			| 10 | 10 |  import org.openzen.zenscript.codemodel.expression.switchvalue.VariantOptionSwitchValue;
 | 
		
	
		
			
			| 11 |  | -import org.openzen.zenscript.codemodel.generic.TypeParameter;
 | 
		
	
		
			
			| 12 | 11 |  import org.openzen.zenscript.codemodel.member.ref.DefinitionMemberRef;
 | 
		
	
		
			
			| 13 | 12 |  import org.openzen.zenscript.codemodel.member.ref.FieldMemberRef;
 | 
		
	
		
			
			| 14 | 13 |  import org.openzen.zenscript.codemodel.statement.ReturnStatement;
 | 
		
	
	
		
			
			|  | @@ -1897,7 +1896,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
 | 
		
	
		
			
			| 1897 | 1896 |  		final JavaWriter functionWriter;
 | 
		
	
		
			
			| 1898 | 1897 |  		
 | 
		
	
		
			
			| 1899 | 1898 |  		//Bridge method!!!
 | 
		
	
		
			
			| 1900 |  | -		if(!Objects.equals(methodInfo.descriptor, signature)) {
 | 
		
	
		
			
			|  | 1899 | +		if (!Objects.equals(methodInfo.descriptor, signature)) {
 | 
		
	
		
			
			| 1901 | 1900 |  			final JavaMethod bridgeMethodInfo = new JavaMethod(methodInfo.cls, methodInfo.kind, methodInfo.name, methodInfo.compile, methodInfo.descriptor, methodInfo.modifiers | JavaModifiers.BRIDGE | JavaModifiers.SYNTHETIC, methodInfo.genericResult, methodInfo.typeParameterArguments);
 | 
		
	
		
			
			| 1902 | 1901 |  			final JavaWriter bridgeWriter = new JavaWriter(expression.position, lambdaCW, bridgeMethodInfo, null, methodInfo.descriptor, null, "java/lang/Override");
 | 
		
	
		
			
			| 1903 | 1902 |  			bridgeWriter.start();
 | 
		
	
	
		
			
			|  | @@ -1909,7 +1908,9 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
 | 
		
	
		
			
			| 1909 | 1908 |  				final FunctionParameter functionParameter = expression.header.parameters[i];
 | 
		
	
		
			
			| 1910 | 1909 |  				final Type type = context.getType(functionParameter.type);
 | 
		
	
		
			
			| 1911 | 1910 |  				bridgeWriter.load(type, i + 1);
 | 
		
	
		
			
			| 1912 |  | -				bridgeWriter.checkCast(type);
 | 
		
	
		
			
			|  | 1911 | +				if (!CompilerUtils.isPrimitive(functionParameter.type.type)) {
 | 
		
	
		
			
			|  | 1912 | +					bridgeWriter.checkCast(type);
 | 
		
	
		
			
			|  | 1913 | +				}
 | 
		
	
		
			
			| 1913 | 1914 |  			}
 | 
		
	
		
			
			| 1914 | 1915 |  			
 | 
		
	
		
			
			| 1915 | 1916 |  			bridgeWriter.invokeVirtual(new JavaMethod(JavaClass.fromInternalName(className, JavaClass.Kind.CLASS), methodInfo.kind, methodInfo.name, methodInfo.compile, signature, methodInfo.modifiers, methodInfo.genericResult));
 | 
		
	
	
		
			
			|  | @@ -3338,60 +3339,56 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
 | 
		
	
		
			
			| 3338 | 3339 |  				return;
 | 
		
	
		
			
			| 3339 | 3340 |  			}
 | 
		
	
		
			
			| 3340 | 3341 |  			case ARRAY_CONSTRUCTOR_LAMBDA: {
 | 
		
	
		
			
			| 3341 |  | -				ArrayTypeID type = (ArrayTypeID) expression.type.type;
 | 
		
	
		
			
			| 3342 |  | -
 | 
		
	
		
			
			| 3343 |  | -				if (type.dimension == 1) {
 | 
		
	
		
			
			| 3344 |  | -					// array = new T[arguments[0]]
 | 
		
	
		
			
			| 3345 |  | -					// lambda = arguments[1]
 | 
		
	
		
			
			| 3346 |  | -					// for (int i = 0; i < array.length; i++)
 | 
		
	
		
			
			| 3347 |  | -					//    array[i] = lambda.invoke(i);
 | 
		
	
		
			
			| 3348 |  | -					//
 | 
		
	
		
			
			| 3349 |  | -					// NOTE: arguments[1] can be a FunctionExpression; this can be optimized by running it inline
 | 
		
	
		
			
			| 3350 |  | -					throw new UnsupportedOperationException("Not yet supported!");
 | 
		
	
		
			
			| 3351 |  | -				} else {
 | 
		
	
		
			
			| 3352 |  | -					// TODO: implement
 | 
		
	
		
			
			| 3353 |  | -					throw new UnsupportedOperationException("Not yet supported!");
 | 
		
	
		
			
			| 3354 |  | -				}
 | 
		
	
		
			
			|  | 3342 | +				
 | 
		
	
		
			
			|  | 3343 | +				//Labels
 | 
		
	
		
			
			|  | 3344 | +				final Label begin = new Label();
 | 
		
	
		
			
			|  | 3345 | +				final Label end = new Label();
 | 
		
	
		
			
			|  | 3346 | +				javaWriter.label(begin);
 | 
		
	
		
			
			|  | 3347 | +				
 | 
		
	
		
			
			|  | 3348 | +				final Type ASMElementType = context.getType(expression.type);
 | 
		
	
		
			
			|  | 3349 | +				final int dimension = ((ArrayTypeID) expression.type.type).dimension;
 | 
		
	
		
			
			|  | 3350 | +				final int[] arraySizes = ArrayInitializerHelper.getArraySizeLocationsFromConstructor(dimension, expression.arguments.arguments, this);
 | 
		
	
		
			
			|  | 3351 | +				ArrayInitializerHelper.visitMultiDimArray(javaWriter, arraySizes, new int[dimension], dimension, ASMElementType, (elementType, counterLocations) -> {
 | 
		
	
		
			
			|  | 3352 | +					expression.arguments.arguments[dimension].accept(this);
 | 
		
	
		
			
			|  | 3353 | +					for (int counterLocation : counterLocations) {
 | 
		
	
		
			
			|  | 3354 | +						javaWriter.loadInt(counterLocation);
 | 
		
	
		
			
			|  | 3355 | +					}
 | 
		
	
		
			
			|  | 3356 | +					javaWriter.invokeInterface(context.getFunctionalInterface(expression.arguments.arguments[dimension].type));
 | 
		
	
		
			
			|  | 3357 | +				});
 | 
		
	
		
			
			|  | 3358 | +				javaWriter.label(end);
 | 
		
	
		
			
			|  | 3359 | +				return;
 | 
		
	
		
			
			| 3355 | 3360 |  			}
 | 
		
	
		
			
			| 3356 | 3361 |  			case ARRAY_CONSTRUCTOR_PROJECTED: {
 | 
		
	
		
			
			| 3357 |  | -
 | 
		
	
		
			
			| 3358 |  | -
 | 
		
	
		
			
			| 3359 | 3362 |  				ArrayTypeID type = (ArrayTypeID) expression.type.type;
 | 
		
	
		
			
			| 3360 |  | -
 | 
		
	
		
			
			|  | 3363 | +				
 | 
		
	
		
			
			|  | 3364 | +				//Labels
 | 
		
	
		
			
			| 3361 | 3365 |  				final Label begin = new Label();
 | 
		
	
		
			
			| 3362 | 3366 |  				final Label end = new Label();
 | 
		
	
		
			
			| 3363 |  | -
 | 
		
	
		
			
			| 3364 | 3367 |  				javaWriter.label(begin);
 | 
		
	
		
			
			| 3365 |  | -				expression.arguments.arguments[0].accept(this); //Origin array
 | 
		
	
		
			
			|  | 3368 | +				
 | 
		
	
		
			
			|  | 3369 | +				//Origin Array
 | 
		
	
		
			
			|  | 3370 | +				expression.arguments.arguments[0].accept(this);
 | 
		
	
		
			
			| 3366 | 3371 |  				final Type originArrayType = context.getType(expression.arguments.arguments[0].type);
 | 
		
	
		
			
			| 3367 | 3372 |  				final int originArrayLocation = javaWriter.local(originArrayType);
 | 
		
	
		
			
			| 3368 | 3373 |  				javaWriter.storeObject(originArrayLocation);
 | 
		
	
		
			
			| 3369 | 3374 |  				Type destinationArrayType = context.getType(expression.type);
 | 
		
	
		
			
			| 3370 |  | -
 | 
		
	
		
			
			| 3371 |  | -
 | 
		
	
		
			
			| 3372 |  | -				final boolean canBeInlined = ArrayInitializerHelper.canBeInlined(expression.arguments.arguments[1]);
 | 
		
	
		
			
			| 3373 |  | -				final Type functionType;    //Only used if not inline able
 | 
		
	
		
			
			| 3374 |  | -				final int functionLocation; //Only used if not inline able
 | 
		
	
		
			
			| 3375 |  | -				if (!canBeInlined) {
 | 
		
	
		
			
			| 3376 |  | -					expression.arguments.arguments[1].accept(this); //Projection Function
 | 
		
	
		
			
			| 3377 |  | -					functionType = context.getType(expression.arguments.arguments[1].type);
 | 
		
	
		
			
			| 3378 |  | -					functionLocation = javaWriter.local(functionType);
 | 
		
	
		
			
			| 3379 |  | -					javaWriter.storeObject(functionLocation);
 | 
		
	
		
			
			| 3380 |  | -					javaWriter.addVariableInfo(new JavaLocalVariableInfo(functionType, functionLocation, begin, "projectionFunction", end));
 | 
		
	
		
			
			| 3381 |  | -				}
 | 
		
	
		
			
			| 3382 |  | -
 | 
		
	
		
			
			| 3383 |  | -				final int[] arraySizes = ArrayInitializerHelper.getArraySizeLocationsProjected(type.dimension, originArrayType, originArrayLocation, javaWriter);
 | 
		
	
		
			
			| 3384 |  | -				ArrayInitializerHelper.visitProjected(javaWriter, arraySizes, type.dimension, originArrayLocation, originArrayType, destinationArrayType,
 | 
		
	
		
			
			| 3385 |  | -						(elementType, counterLocations) -> {
 | 
		
	
		
			
			| 3386 |  | -							if (canBeInlined) {
 | 
		
	
		
			
			|  | 3375 | +				
 | 
		
	
		
			
			|  | 3376 | +				
 | 
		
	
		
			
			|  | 3377 | +				final boolean canBeInLined = ArrayInitializerHelper.canBeInLined(expression.arguments.arguments[1]);
 | 
		
	
		
			
			|  | 3378 | +				if (canBeInLined) {
 | 
		
	
		
			
			|  | 3379 | +					//We can inline, so do it
 | 
		
	
		
			
			|  | 3380 | +					final int[] arraySizes = ArrayInitializerHelper.getArraySizeLocationsProjected(type.dimension, originArrayType, originArrayLocation, javaWriter);
 | 
		
	
		
			
			|  | 3381 | +					final Type projectedElementType = Type.getType(originArrayType.getDescriptor().substring(type.dimension));
 | 
		
	
		
			
			|  | 3382 | +					ArrayInitializerHelper.visitProjected(javaWriter, arraySizes, type.dimension, originArrayLocation, originArrayType, destinationArrayType,
 | 
		
	
		
			
			|  | 3383 | +							(elementType, counterLocations) -> {
 | 
		
	
		
			
			| 3387 | 3384 |  								Label inlineBegin = new Label();
 | 
		
	
		
			
			| 3388 | 3385 |  								Label inlineEnd = new Label();
 | 
		
	
		
			
			| 3389 | 3386 |  								javaWriter.label(inlineBegin);
 | 
		
	
		
			
			| 3390 |  | -								final Type projectedElementType = Type.getType(originArrayType.getDescriptor().substring(type.dimension));
 | 
		
	
		
			
			|  | 3387 | +								
 | 
		
	
		
			
			| 3391 | 3388 |  								final int projectedElementLocal = javaWriter.local(projectedElementType);
 | 
		
	
		
			
			| 3392 | 3389 |  								javaWriter.store(projectedElementType, projectedElementLocal);
 | 
		
	
		
			
			| 3393 |  | -
 | 
		
	
		
			
			| 3394 |  | -
 | 
		
	
		
			
			|  | 3390 | +								
 | 
		
	
		
			
			|  | 3391 | +								
 | 
		
	
		
			
			| 3395 | 3392 |  								JavaExpressionVisitor visitor = new JavaExpressionVisitor(context, module, javaWriter) {
 | 
		
	
		
			
			| 3396 | 3393 |  									@Override
 | 
		
	
		
			
			| 3397 | 3394 |  									public Void visitGetFunctionParameter(GetFunctionParameterExpression expression) {
 | 
		
	
	
		
			
			|  | @@ -3399,40 +3396,46 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
 | 
		
	
		
			
			| 3399 | 3396 |  										return null;
 | 
		
	
		
			
			| 3400 | 3397 |  									}
 | 
		
	
		
			
			| 3401 | 3398 |  								};
 | 
		
	
		
			
			| 3402 |  | -
 | 
		
	
		
			
			|  | 3399 | +								
 | 
		
	
		
			
			| 3403 | 3400 |  								Expression funcExpression = expression.arguments.arguments[1];
 | 
		
	
		
			
			| 3404 | 3401 |  								while (funcExpression instanceof StorageCastExpression) {
 | 
		
	
		
			
			| 3405 | 3402 |  									funcExpression = ((StorageCastExpression) funcExpression).value;
 | 
		
	
		
			
			| 3406 | 3403 |  								}
 | 
		
	
		
			
			| 3407 |  | -
 | 
		
	
		
			
			|  | 3404 | +								
 | 
		
	
		
			
			| 3408 | 3405 |  								if (funcExpression instanceof FunctionExpression && ((FunctionExpression) funcExpression).body instanceof ReturnStatement) {
 | 
		
	
		
			
			| 3409 | 3406 |  									((ReturnStatement) ((FunctionExpression) funcExpression).body).value.accept(visitor);
 | 
		
	
		
			
			| 3410 | 3407 |  									javaWriter.addVariableInfo(new JavaLocalVariableInfo(projectedElementType, projectedElementLocal, inlineBegin, ((FunctionExpression) funcExpression).header.parameters[0].name, inlineEnd));
 | 
		
	
		
			
			| 3411 | 3408 |  								} else throw new IllegalStateException("Trying to inline a non-inlineable expression");
 | 
		
	
		
			
			| 3412 |  | -
 | 
		
	
		
			
			| 3413 |  | -
 | 
		
	
		
			
			|  | 3409 | +								
 | 
		
	
		
			
			|  | 3410 | +								
 | 
		
	
		
			
			| 3414 | 3411 |  								javaWriter.label(inlineEnd);
 | 
		
	
		
			
			| 3415 |  | -							} else {
 | 
		
	
		
			
			|  | 3412 | +							});
 | 
		
	
		
			
			|  | 3413 | +				} else {
 | 
		
	
		
			
			|  | 3414 | +					//We cannot inline, so get a hold of the function expression and apply it to every
 | 
		
	
		
			
			|  | 3415 | +					expression.arguments.arguments[1].accept(this); //Projection Function
 | 
		
	
		
			
			|  | 3416 | +					final Type functionType = context.getType(expression.arguments.arguments[1].type);
 | 
		
	
		
			
			|  | 3417 | +					final int functionLocation = javaWriter.local(functionType);
 | 
		
	
		
			
			|  | 3418 | +					javaWriter.storeObject(functionLocation);
 | 
		
	
		
			
			|  | 3419 | +					javaWriter.addVariableInfo(new JavaLocalVariableInfo(functionType, functionLocation, begin, "projectionFunction", end));
 | 
		
	
		
			
			|  | 3420 | +					final int[] arraySizes = ArrayInitializerHelper.getArraySizeLocationsProjected(type.dimension, originArrayType, originArrayLocation, javaWriter);
 | 
		
	
		
			
			|  | 3421 | +					ArrayInitializerHelper.visitProjected(javaWriter, arraySizes, type.dimension, originArrayLocation, originArrayType, destinationArrayType,
 | 
		
	
		
			
			|  | 3422 | +							(elementType, counterLocations) -> {
 | 
		
	
		
			
			| 3416 | 3423 |  								//Apply function here
 | 
		
	
		
			
			| 3417 |  | -								//javaWriter.loadObject(functionLocation);
 | 
		
	
		
			
			| 3418 |  | -								//javaWriter.swap();
 | 
		
	
		
			
			| 3419 |  | -
 | 
		
	
		
			
			| 3420 |  | -								//TODO invoke?
 | 
		
	
		
			
			| 3421 |  | -								//javaWriter.invokeVirtual(new JavaMethod(JavaClass.fromInternalName("lambda1", JavaClass.Kind.CLASS), JavaMethod.Kind.INSTANCE, "accept", true, "(Ljava/lang/String;)Ljava/lang/String;", 0, false));
 | 
		
	
		
			
			| 3422 |  | -
 | 
		
	
		
			
			| 3423 |  | -								//FIXME Critical! Currently returning the same object!
 | 
		
	
		
			
			| 3424 |  | -								//throw new UnsupportedOperationException("Cannot use projection functions yet!");
 | 
		
	
		
			
			| 3425 |  | -							}
 | 
		
	
		
			
			| 3426 |  | -						});
 | 
		
	
		
			
			| 3427 |  | -
 | 
		
	
		
			
			| 3428 |  | -
 | 
		
	
		
			
			|  | 3424 | +								javaWriter.loadObject(functionLocation);
 | 
		
	
		
			
			|  | 3425 | +								javaWriter.swap();
 | 
		
	
		
			
			|  | 3426 | +								
 | 
		
	
		
			
			|  | 3427 | +								javaWriter.invokeInterface(context.getFunctionalInterface(expression.arguments.arguments[1].type));
 | 
		
	
		
			
			|  | 3428 | +							});
 | 
		
	
		
			
			|  | 3429 | +				}
 | 
		
	
		
			
			|  | 3430 | +				
 | 
		
	
		
			
			|  | 3431 | +				
 | 
		
	
		
			
			| 3429 | 3432 |  				javaWriter.label(end);
 | 
		
	
		
			
			| 3430 | 3433 |  				return;
 | 
		
	
		
			
			| 3431 |  | -
 | 
		
	
		
			
			|  | 3434 | +				
 | 
		
	
		
			
			| 3432 | 3435 |  			}
 | 
		
	
		
			
			| 3433 | 3436 |  			case ARRAY_CONSTRUCTOR_PROJECTED_INDEXED: {
 | 
		
	
		
			
			| 3434 | 3437 |  				ArrayTypeID type = (ArrayTypeID) expression.type.type;
 | 
		
	
		
			
			| 3435 |  | -
 | 
		
	
		
			
			|  | 3438 | +				
 | 
		
	
		
			
			| 3436 | 3439 |  				if (type.dimension == 1) {
 | 
		
	
		
			
			| 3437 | 3440 |  					// original = arguments[0] (this is an array)
 | 
		
	
		
			
			| 3438 | 3441 |  					// projector = arguments[1] (this is a lambda with 2 parameters)
 |