Skip to content

Commit

Permalink
GH-710 Support typed array, improve generic types matching and releas…
Browse files Browse the repository at this point in the history
…e 0.5.1-alpha (Resolve  #710)
  • Loading branch information
dzikoysk committed Dec 3, 2021
1 parent 8080ee7 commit 83f3cd3
Show file tree
Hide file tree
Showing 23 changed files with 206 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The latest indev build
<dependency>
<groupId>org.panda-lang</groupId>
<artifactId>panda</artifactId>
<version>0.5.0-alpha</version>
<version>0.5.1-alpha</version>
</dependency>
```

Expand Down
10 changes: 10 additions & 0 deletions examples/lang/array.panda
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'java' { collections }

import java.util.Arrays

main {
let array = 'Hello World'.split(' ')
array.set(1, 'Panda')
log array.get(0)
log array.toList().get(1)
}
2 changes: 1 addition & 1 deletion examples/lang/loops.panda
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ main {

/* Iterator based for-each loop */

List iterable = new ArrayList() // TODO: Replace with generic based collections
List<String> iterable = new ArrayList()
iterable.add('#bokkitty')
iterable.add('#onlypanda')

Expand Down
2 changes: 1 addition & 1 deletion examples/summary-example/src/app.panda
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ main {
}

// assign ArrayList (class) value to List (interface) variable and add some values
List list = new ArrayList()
List<String> list = new ArrayList()
list.add("val1")
list.add("val2")

Expand Down
2 changes: 1 addition & 1 deletion panda-framework/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<artifactId>panda-parent</artifactId>
<groupId>org.panda-lang</groupId>
<version>0.5.0-alpha</version>
<version>0.5.1-alpha</version>
</parent>

<artifactId>panda-framework</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public final class PandaFrameworkConstants {
/**
* Current version of the Panda Framework
*/
public static final String VERSION = "0.5.0-alpha";
public static final String VERSION = "0.5.1-alpha";

private PandaFrameworkConstants() { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
import panda.interpreter.architecture.type.member.method.PandaMethod;
import panda.interpreter.architecture.type.member.method.TypeMethod;
import panda.interpreter.architecture.type.member.parameter.PropertyParameter;
import panda.interpreter.architecture.type.signature.GenericSignature;
import panda.interpreter.architecture.type.signature.Relation;
import panda.interpreter.architecture.type.signature.Signature;
import panda.interpreter.runtime.PandaRuntimeException;
import panda.interpreter.token.PandaSnippet;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
Expand All @@ -50,7 +54,7 @@ final class MethodGenerator {
this.method = method;
}

protected TypeMethod generate(TypeLoader typeLoader) {
TypeMethod generate(TypeLoader typeLoader) {
// TODO: Generate bytecode
method.setAccessible(true);

Expand Down Expand Up @@ -110,12 +114,16 @@ protected TypeMethod generate(TypeLoader typeLoader) {

List<? extends PropertyParameter> mappedParameters = TypeGeneratorUtils.toParameters(generator, typeLoader, type.getModule(), method.getParameters());

Signature returnType = method.getGenericReturnType() != method.getReturnType()
? new GenericSignature(typeLoader, null, method.getGenericReturnType().getTypeName(), null, new Signature[0], Relation.DIRECT, PandaSnippet.empty())
: generator.findOrGenerate(typeLoader, type.getModule(), method.getReturnType()).getSignature();

return PandaMethod.builder()
.name(method.getName())
.type(type)
.isNative(true)
.isStatic(Modifier.isStatic(method.getModifiers()))
.returnType(generator.findOrGenerate(typeLoader, type.getModule(), method.getReturnType()).getSignature())
.returnType(returnType)
.location(type.getLocation())
.customBody(methodBody)
.parameters(mappedParameters)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@
import panda.interpreter.architecture.type.State;
import panda.interpreter.architecture.type.Type;
import panda.interpreter.architecture.type.Visibility;
import panda.interpreter.architecture.type.member.method.PandaMethod;
import panda.interpreter.architecture.type.member.parameter.PropertyParameterImpl;
import panda.interpreter.architecture.type.signature.GenericSignature;
import panda.interpreter.architecture.type.signature.Relation;
import panda.interpreter.architecture.type.signature.Signature;
import panda.interpreter.architecture.type.signature.TypedSignature;
import panda.interpreter.source.ClassSource;
import panda.interpreter.source.Location;
import panda.interpreter.token.PandaSnippet;
import panda.std.reactive.Completable;
import panda.utilities.ClassUtils;
Expand All @@ -39,13 +43,18 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public final class TypeGenerator {

protected final Map<Class<?>, Type> initializedTypes = new HashMap<>();
protected final FrameworkController frameworkController;
final Map<Class<?>, Type> initializedTypes = new HashMap<>();
final FrameworkController frameworkController;

public TypeGenerator(FrameworkController frameworkController) {
this.frameworkController = frameworkController;
Expand All @@ -56,20 +65,34 @@ public Type allocate(Class<?> javaType, Type type) {
return type;
}

public Reference generate(Module module, String name, Class<?> javaType) {
public Reference generate(TypeLoader stdTypeLoader, Module module, String rawName, Class<?> javaType) {
if (rawName.endsWith("[]")) {
rawName = rawName.replace("[]", "Array");
}

String name = rawName;

return Option.of(initializedTypes.get(javaType))
.map(Reference::new)
.orElse(() -> module.get(name))
.orElseGet(() -> {
Completable<Type> completableType = new Completable<>();
Reference reference = new Reference(completableType, module, name, Visibility.OPEN, Kind.of(javaType), new ClassSource(module, javaType).toLocation());
Location location = new ClassSource(module, javaType).toLocation();
Reference reference = new Reference(completableType, module, name, Visibility.OPEN, Kind.of(javaType), location);

TypeVariable<?>[] javaGenerics = javaType.getTypeParameters();
Signature[] generics = new Signature[javaGenerics.length];

for (int index = 0; index < javaGenerics.length; index++) {
generics[index] = new GenericSignature(stdTypeLoader, null, javaGenerics[index].getName(), null, new Signature[0], Relation.DIRECT, PandaSnippet.empty());
}

Type type = PandaType.builder()
.name(name)
.module(module)
.associatedType(Completable.completed(javaType))
.isNative(true)
.signature(new TypedSignature(null, reference, new Signature[0], Relation.DIRECT, PandaSnippet.empty()))
.signature(new TypedSignature(null, reference, generics, Relation.DIRECT, PandaSnippet.empty()))
.location(reference.getLocation())
.kind(reference.getKind())
.state(State.of(javaType))
Expand Down Expand Up @@ -115,14 +138,59 @@ public Reference generate(Module module, String name, Class<?> javaType) {
MethodGenerator generator = new MethodGenerator(frameworkController, this, initializedType, method);
initializedType.getMethods().declare(method.getName(), () -> generator.generate(typeLoader));
}

if (javaType.isArray()) {
Signature componentType = typeLoader.forJavaType(javaType.getComponentType()).get().getSignature();
Signature indexType = typeLoader.forJavaType(int.class).get().getSignature();

type.getMethods().declare("set", () -> PandaMethod.builder()
.type(type)
.name("set")
.parameters(Arrays.asList(
new PropertyParameterImpl(0, indexType, "index", false, false),
new PropertyParameterImpl(1, componentType, "value", false, true)
))
.returnType(type.getSignature())
.customBody((property, stack, instance, arguments) -> {
((Object[]) Objects.requireNonNull(instance))[(int) arguments[0]] = arguments[1];
return instance;
})
.location(location)
.build());
type.getMethods().declare("get", () -> PandaMethod.builder()
.type(type)
.name("get")
.parameters(Collections.singletonList(new PropertyParameterImpl(0, typeLoader.forJavaType(int.class).get().getSignature(), "index", false, false)))
.returnType(componentType)
.customBody((property, stack, instance, arguments) -> ((Object[]) Objects.requireNonNull(instance))[(int) arguments[0]])
.location(location)
.build());

TypedSignature typedListSignature = new TypedSignature(
null,
typeLoader.forJavaType(List.class).get().getReference(),
new Signature[] { typeLoader.forJavaType(String.class).get().getSignature() },
Relation.DIRECT,
PandaSnippet.empty()
);

type.getMethods().declare("toList", () -> PandaMethod.builder()
.type(type)
.name("toList")
.parameters(Collections.emptyList())
.returnType(typedListSignature)
.customBody((property, stack, instance, arguments) -> Arrays.asList((Object[]) Objects.requireNonNull(instance)))
.location(location)
.build());
}
});

completableType.complete(allocate(javaType, type));
return type.getReference();
});
}

protected Type findOrGenerate(TypeLoader typeLoader, Module module, Class<?> javaType) {
Type findOrGenerate(TypeLoader typeLoader, Module module, Class<?> javaType) {
if (javaType.isPrimitive()) {
javaType = ClassUtils.getNonPrimitiveClass(javaType);
}
Expand All @@ -139,7 +207,7 @@ protected Type findOrGenerate(TypeLoader typeLoader, Module module, Class<?> jav
return type;
}

return generate(module, javaType.getSimpleName(), javaType).fetchType();
return generate(typeLoader, module, javaType.getSimpleName(), javaType).fetchType();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static List<? extends PropertyParameter> toParameters(TypeGenerator typeGenerato

for (int index = 0; index < parameters.length; index++) {
Parameter parameter = parameters[index];
Type type = typeLoader.load(typeGenerator.generate(module, parameter.getType().getSimpleName(), parameter.getType()).fetchType());
Type type = typeLoader.load(typeGenerator.generate(typeLoader, module, parameter.getType().getSimpleName(), parameter.getType()).fetchType());
mappedParameters.add(new PropertyParameterImpl(index, type.getSignature(), parameter.getName(), false, false));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ private List<T> withBases(List<T> properties, Function<Members<? extends T>, Col
}

protected List<T> getPropertiesLike(String name, Predicate<T> filter) {
List<T> properties = Option.of(propertiesMap.get(name)).orElseGet(Collections::emptyList).stream()
List<T> properties = Option.of(propertiesMap.get(name))
.orElseGet(Collections::emptyList).stream()
.map(Lazy::get)
.filter(filter)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public interface ParametrizedMember extends Member {
boolean isInvokableBy(List<? extends Typed> arguments);

/**
* Get references to types of executable's parameters
* Get references to type of executable's parameters
*
* @return array of used by parameter types
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public final class PandaMethod extends AbstractParametrizedMember<TypeMethod> im
private final boolean isNative;
private final boolean isOverriding;

protected PandaMethod(PandaMethodBuilder builder) {
PandaMethod(PandaMethodBuilder builder) {
super(builder);

this.methodBody = builder.body;
Expand Down Expand Up @@ -76,11 +76,11 @@ public static PandaMethodBuilder builder() {

public static final class PandaMethodBuilder extends PandaParametrizedExecutableBuilder<TypeMethod, PandaMethodBuilder> {

protected MemberInvoker<TypeMethod, Object, Object> body;
protected boolean isAbstract;
protected boolean isStatic;
protected boolean isNative;
protected boolean isOverriding;
MemberInvoker<TypeMethod, Object, Object> body;
boolean isAbstract;
boolean isStatic;
boolean isNative;
boolean isOverriding;

private PandaMethodBuilder() { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public static Result<? extends Signature, String> isAssignable(Signature root, S
return baseResult;
}

for (int index = 0; index < root.getGenerics().length; index++) {
for (int index = 0; index < inheritor.getGenerics().length; index++) {
Signature rootParameter = root.getGenerics()[index];
Signature inheritorParameter = inheritor.getGenerics()[index];
Result<? extends Signature, String> parameterResult = isAssignable(rootParameter, inheritorParameter);
Expand All @@ -42,10 +42,6 @@ public static Result<? extends Signature, String> isAssignable(Signature root, S
}

private static Result<? extends Signature, String> isBaseAssignable(Signature root, Signature inheritor) {
if (root.getSignature().getGenerics().length != inheritor.getSignature().getGenerics().length) {
return Result.error("Invalid amount of parameters in generic signature");
}

if (root.isTyped()) {
if (inheritor.isTyped()) {
return typedToTyped(root.toTyped(), inheritor.toTyped());
Expand All @@ -56,6 +52,10 @@ private static Result<? extends Signature, String> isBaseAssignable(Signature ro
}
}

if (root.getSignature().getGenerics().length != inheritor.getSignature().getGenerics().length) {
return Result.error("Invalid amount of parameters in generic signature");
}

if (root.isGeneric()) {
if (inheritor.isTyped()) {
return genericToTyped(root.toGeneric(), inheritor.toTyped());
Expand Down
Loading

0 comments on commit 83f3cd3

Please sign in to comment.