Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Legacy #32

Open
wants to merge 5 commits into
base: legacy
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ artifacts {
}

test {
useJUnitPlatform()
//useJUnitPlatform()
testLogging{
events "PASSED", "FAILED", "SKIPPED"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package stanhebben.zenscript.compiler;

import jdk.internal.dynalink.support.BottomGuardingDynamicLinker;
import org.objectweb.asm.ClassVisitor;
import stanhebben.zenscript.*;
import stanhebben.zenscript.expression.partial.IPartialExpression;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import org.objectweb.asm.ClassVisitor;
import stanhebben.zenscript.*;
import stanhebben.zenscript.expression.partial.IPartialExpression;
import stanhebben.zenscript.expression.*;
import stanhebben.zenscript.expression.partial.*;
import stanhebben.zenscript.symbols.*;
import stanhebben.zenscript.type.ZenType;
import stanhebben.zenscript.util.*;
Expand All @@ -17,8 +18,8 @@ public class EnvironmentMethod implements IEnvironmentMethod {

private final MethodOutput output;
private final HashMap<SymbolLocal, Integer> locals;
private final IEnvironmentClass environment;
private final Map<String, IZenSymbol> local;
final IEnvironmentClass environment;
final Map<String, IZenSymbol> local;

public EnvironmentMethod(MethodOutput output, IEnvironmentClass environment) {
this.output = output;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package stanhebben.zenscript.compiler;

import stanhebben.zenscript.expression.*;
import stanhebben.zenscript.expression.partial.*;
import stanhebben.zenscript.symbols.*;
import stanhebben.zenscript.util.*;

import java.util.*;

public class EnvironmentMethodLambda extends EnvironmentMethod {

private static final List<Class<? extends IPartialExpression>> nonCapturedExpressions;
static {
nonCapturedExpressions = Arrays.asList(PartialStaticGetter.class, PartialStaticGenerated.class, PartialStaticMethod.class, ExpressionJavaStaticField.class, ExpressionJavaMethodStatic.class, ExpressionCallStatic.class);


}
private final List<SymbolCaptured> capturedVariables;
private final String clsName;

public EnvironmentMethodLambda(MethodOutput output, IEnvironmentClass environment, String clsName) {
super(output, environment);
this.clsName = clsName;
capturedVariables = new ArrayList<>(0);
}

@Override
public IPartialExpression getValue(String name, ZenPosition position) {
if(local.containsKey(name)) {
return local.get(name).instance(position);
} else {
final IPartialExpression value = environment.getValue(name, position);
if(value != null) {
if(nonCapturedExpressions.stream().anyMatch(c -> c.isInstance(value))) {
return value;
}


final SymbolCaptured capture = new SymbolCaptured(value.eval(environment), name, clsName);
capturedVariables.add(capture);
local.put(name, capture);
return capture.instance(position);
}
return null;
}
}

public List<SymbolCaptured> getCapturedVariables() {
return capturedVariables;
}

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package stanhebben.zenscript.expression;

import org.objectweb.asm.*;
import org.objectweb.asm.Type;
import stanhebben.zenscript.compiler.*;
import stanhebben.zenscript.definitions.ParsedFunctionArgument;
import stanhebben.zenscript.statements.Statement;
import stanhebben.zenscript.symbols.SymbolArgument;
import stanhebben.zenscript.symbols.*;
import stanhebben.zenscript.type.ZenType;
import stanhebben.zenscript.util.*;

import java.lang.reflect.Method;
import java.util.List;
import java.lang.reflect.*;
import java.util.*;

import static stanhebben.zenscript.util.ZenTypeUtil.*;

Expand All @@ -18,13 +19,13 @@
*/
public class ExpressionJavaLambda extends Expression {

private final Class interfaceClass;
private final Class<?> interfaceClass;
private final List<ParsedFunctionArgument> arguments;
private final List<Statement> statements;

private final ZenType type;

public ExpressionJavaLambda(ZenPosition position, Class interfaceClass, List<ParsedFunctionArgument> arguments, List<Statement> statements, ZenType type) {
public ExpressionJavaLambda(ZenPosition position, Class<?> interfaceClass, List<ParsedFunctionArgument> arguments, List<Statement> statements, ZenType type) {
super(position);

this.interfaceClass = interfaceClass;
Expand Down Expand Up @@ -52,20 +53,13 @@ public void compile(boolean result, IEnvironmentMethod environment) {
ClassWriter cw = new ZenClassWriter(ClassWriter.COMPUTE_FRAMES);
cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, clsName, null, "java/lang/Object", new String[]{internal(interfaceClass)});

MethodOutput constructor = new MethodOutput(cw, Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
constructor.start();
constructor.loadObject(0);
constructor.invokeSpecial("java/lang/Object", "<init>", "()V");
constructor.ret();
constructor.end();

MethodOutput output = new MethodOutput(cw, Opcodes.ACC_PUBLIC, method.getName(), descriptor(method), null, null);

IEnvironmentClass environmentClass = new EnvironmentClass(cw, environment);
IEnvironmentMethod environmentMethod = new EnvironmentMethod(output, environmentClass);
EnvironmentMethodLambda environmentMethod = new EnvironmentMethodLambda(output, environmentClass, clsName);

for(int i = 0, j = 0; i < arguments.size(); i++) {
environmentMethod.putValue(arguments.get(i).getName(), new SymbolArgument(i + 1, environment.getType(method.getGenericParameterTypes()[i])), getPosition());
environmentMethod.putValue(arguments.get(i).getName(), new SymbolArgument(i + j + 1, environment.getType(method.getGenericParameterTypes()[i])), getPosition());
if(environment.getType(method.getGenericParameterTypes()[i]).isLarge())
j++;
}
Expand All @@ -76,12 +70,50 @@ public void compile(boolean result, IEnvironmentMethod environment) {
}
output.ret();
output.end();


final List<SymbolCaptured> capturedVariables = environmentMethod.getCapturedVariables();
final StringJoiner sj = new StringJoiner("", "(", ")V");
for(SymbolCaptured value : capturedVariables) {
cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, value.getFieldName(), Type.getDescriptor(value.getType().toJavaClass()), null, null).visitEnd();
sj.add(Type.getDescriptor(value.getType().toJavaClass()));
}

MethodOutput constructor = new MethodOutput(cw, Opcodes.ACC_PUBLIC, "<init>", sj.toString(), null, null);
constructor.start();
constructor.loadObject(0);
constructor.invokeSpecial("java/lang/Object", "<init>", "()V");

{
int i = 1, j = 0;
for(SymbolCaptured capturedVariable : capturedVariables) {
final ZenType type = capturedVariable.getType();
constructor.loadObject(0);
constructor.load(Type.getType(type.toJavaClass()), i + j);
if(type.isLarge()) {
j++;
}
constructor.putField(clsName, capturedVariable.getFieldName(), Type.getDescriptor(capturedVariable.getType().toJavaClass()));
i++;
}
}

constructor.ret();
constructor.end();


environment.putClass(clsName, cw.toByteArray());

// make class instance
environment.getOutput().newObject(clsName);
environment.getOutput().dup();
environment.getOutput().construct(clsName);
final String[] arguments = capturedVariables.stream()
.map(SymbolCaptured::getEvaluated)
.peek(expression -> expression.compile(true, environment))
.map(Expression::getType)
.map(ZenType::toASMType)
.map(Type::getDescriptor)
.toArray(String[]::new);
environment.getOutput().construct(clsName, arguments);
}
}
61 changes: 61 additions & 0 deletions src/main/java/stanhebben/zenscript/symbols/SymbolCaptured.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package stanhebben.zenscript.symbols;

import org.objectweb.asm.Type;
import stanhebben.zenscript.compiler.*;
import stanhebben.zenscript.expression.*;
import stanhebben.zenscript.expression.partial.*;
import stanhebben.zenscript.type.*;
import stanhebben.zenscript.util.*;

import java.util.*;

public class SymbolCaptured implements IZenSymbol {

private final String fieldName;
private final String lambdaClassName;
private final Expression evaluated;


public SymbolCaptured(Expression original, String fieldName, String clsName) {
this.evaluated = original;
this.fieldName = fieldName;
this.lambdaClassName = clsName;
}

public ZenType getType() {
return evaluated.getType();
}

@Override
public IPartialExpression instance(ZenPosition position) {
return new Expression(position) {
@Override
public void compile(boolean result, IEnvironmentMethod environment) {
if(!result)
return;

final MethodOutput output = environment.getOutput();
if(lambdaClassName == null || fieldName == null || evaluated == null) {
throw new IllegalStateException(String.format(Locale.ENGLISH, "Captured variable with name %s in class %s and evaluated obj %s has at least one null info", fieldName, lambdaClassName, evaluated));
}


output.loadObject(0);
output.getField(lambdaClassName, fieldName, Type.getDescriptor(getType().toJavaClass()));
}

@Override
public ZenType getType() {
return SymbolCaptured.this.getType();
}
};
}

public Expression getEvaluated() {
return evaluated;
}

public String getFieldName() {
return fieldName;
}
}
53 changes: 51 additions & 2 deletions src/main/java/stanhebben/zenscript/type/ZenTypeNative.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ public void complete(ITypeRegistry types) {

//TODO check this
for(Method method : cls.getMethods()) {
//We only want those from the class itself, the super methods originate from the implements
//for(Method method : cls.getDeclaredMethods()) {

boolean isMethod = false;
String methodName = method.getName();
Expand Down Expand Up @@ -162,7 +164,27 @@ public void complete(ITypeRegistry types) {
if(method.getParameterTypes().length != 0) {
// TODO: error
} else {
unaryOperators.add(new ZenNativeOperator(operatorAnnotation.value(), new JavaMethod(method, types)));
final ZenNativeOperator toAdd = new ZenNativeOperator(operatorAnnotation.value(), new JavaMethod(method, types));
boolean found = false;
for(final ListIterator<ZenNativeOperator> iter = unaryOperators.listIterator(); iter.hasNext();) {
final ZenNativeOperator presentOperator = iter.next();
if(presentOperator.getOperator() == operatorAnnotation.value()) {
found = true;
final Class<?> theirRetType = presentOperator.getMethod().getReturnType().toJavaClass();
final Class<?> toAddRetType = method.getReturnType();
if(!toAddRetType.isAssignableFrom(theirRetType)) {
if(theirRetType.isAssignableFrom(theirRetType)) {
//Their type is less specific, use ours
iter.set(toAdd);
} else {
System.err.println("Two operators with similar methods were found: " + toAdd + " | " + presentOperator);
}
}
}
}
if(!found) {
unaryOperators.add(toAdd);
}
}
break;
case ADD:
Expand All @@ -182,7 +204,34 @@ public void complete(ITypeRegistry types) {
if(method.getParameterTypes().length != 1) {
// TODO: error
} else {
binaryOperators.add(new ZenNativeOperator(operatorAnnotation.value(), new JavaMethod(method, types)));
final OperatorType operatorType = operatorAnnotation.value();
final ZenNativeOperator toAdd = new ZenNativeOperator(operatorType, new JavaMethod(method, types));
boolean found = false;
for(final ListIterator<ZenNativeOperator> iter = binaryOperators.listIterator(); iter.hasNext(); ) {
ZenNativeOperator binaryOperator = iter.next();
if(binaryOperator.getOperator() == operatorType) {
final IJavaMethod presentMethod = binaryOperator.getMethod();
if(presentMethod.getParameterTypes()[0].toJavaClass().equals(method.getParameterTypes()[0])) {
found = true;
final Class<?> theirRetType = presentMethod.getReturnType().toJavaClass();
final Class<?> methodRetType = method.getReturnType();
if(!methodRetType.isAssignableFrom(theirRetType)) {
if(theirRetType.isAssignableFrom(methodRetType)) {
//Their type is less specific, use ours
iter.set(toAdd);
} else {
System.err.println("Two operators with similar methods were found: " + toAdd + " | " + presentMethod);
}
}

}
}
}

if(!found) {
//Otherwise we'd already set it in the iterator or used the other method instead
binaryOperators.add(toAdd);
}
}
break;
case INDEXSET:
Expand Down
13 changes: 9 additions & 4 deletions src/main/java/stanhebben/zenscript/type/natives/JavaMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@ public JavaMethod(Method method, ITypeRegistry types) {
}
}
boolean lastOptional = false;
for(boolean optional : optional) {
if(lastOptional && !optional)
throw new IllegalArgumentException("All optionals need to be placed at the end of the method declaration: " + method.toGenericString());
lastOptional = optional;
for(int i = 0; i < optional.length; i++) {
boolean opt = optional[i];
if(lastOptional && !opt) {
System.err.println("All optionals need to be placed at the end of the method declaration: " + method.toGenericString() + "! Setting last parameters to optional");
optional[i] = lastOptional = true;
//throw new IllegalArgumentException("All optionals need to be placed at the end of the method declaration: " + method.toGenericString());
} else {
lastOptional = opt;
}
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/main/java/stanhebben/zenscript/value/IntRange.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package stanhebben.zenscript.value;

import java.util.*;

/**
* @author Stan Hebben
*/
public class IntRange {

private final int from;
private final int to;
private final Random rand;

public IntRange(int from, int to) {
this.from = from;
this.to = to;
rand = new Random(2906);
}

public int getFrom() {
Expand All @@ -20,4 +24,16 @@ public int getFrom() {
public int getTo() {
return to;
}

public int getMin() {
return getFrom();
}

public int getMax() {
return getTo();
}

public int getRandom() {
return rand.nextInt((to - from) + 1) + from;
}
}
Loading