Skip to content

Commit

Permalink
[types] Improve types
Browse files Browse the repository at this point in the history
  • Loading branch information
5pilow committed Jun 6, 2023
1 parent 7684e5e commit 8429a57
Show file tree
Hide file tree
Showing 65 changed files with 981 additions and 377 deletions.
20 changes: 20 additions & 0 deletions src/main/java/leekscript/common/ClassType.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package leekscript.common;

import java.util.HashSet;

import leekscript.compiler.Complete;
import leekscript.compiler.Complete.CompleteCategory;
import leekscript.compiler.instruction.ClassDeclarationInstruction;

public class ClassType extends Type {
Expand Down Expand Up @@ -68,4 +72,20 @@ public CastType accepts(Type type) {
public Type returnType() {
return this.clazz.getType();
}

@Override
public Complete complete() {
// System.out.println("ClassType " + clazz.getName() + " complete");
var complete = new Complete(this);
for (var field : this.clazz.getFields().entrySet()) {
complete.add(CompleteCategory.FIELD, field.getKey(), field.getValue().getType());
}
for (var method : this.clazz.getMethods().entrySet()) {
for (var version : method.getValue().entrySet()) {
complete.add(CompleteCategory.METHOD, method.getKey(), version.getValue().block.getType());
}
}
// System.out.println("complete = " + complete);
return complete;
}
}
34 changes: 26 additions & 8 deletions src/main/java/leekscript/common/ClassValueType.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package leekscript.common;

import java.util.HashSet;
import java.util.List;

import leekscript.compiler.instruction.ClassDeclarationInstruction;
Expand All @@ -14,6 +15,7 @@ public ClassValueType(ClassDeclarationInstruction clazz) {
}

public Type member(String member) {
if (member == null) return Type.VOID;
if (member.equals("name")) return Type.STRING;
if (member.equals("super")) return this.clazz != null && this.clazz.getParent() != null ? this.clazz.getParent().getClassValueType() : Type.CLASS;
if (member.equals("fields")) return Type.ARRAY_STRING;
Expand Down Expand Up @@ -43,22 +45,20 @@ public CastType accepts(Type type) {
if (this.clazz == c.clazz) return CastType.EQUALS;

return CastType.UPCAST;
// // this = Animal, type = Dog
// if (c.clazz.descendsFrom(this.clazz)) return CastType.UPCAST;
// // this = Dog, type = Animal
// if (this.clazz != null && this.clazz.descendsFrom(c.clazz)) return CastType.UNSAFE_DOWNCAST;
// // Incompatible
// return CastType.INCOMPATIBLE;
}
return super.accepts(type);
}

@Override
public CastType acceptsArguments(List<Type> types) {
if (types.size() == 0 || clazz == null || clazz.getConstructor(types.size()) != null) {
if (types.size() == 0 || clazz == null) {
return CastType.EQUALS;
}
return CastType.INCOMPATIBLE;
// Vérification constructeurs
var constructor = clazz.getConstructor(types.size());
if (constructor == null) return CastType.INCOMPATIBLE;

return constructor.block.getType().acceptsArguments(types);
}

@Override
Expand Down Expand Up @@ -95,4 +95,22 @@ public boolean isIndexable() {
public boolean canBeIndexable() {
return true;
}

@Override
public Type getArgument(int a) {
if (this.clazz == null) return Type.ANY;
HashSet<Type> types = new HashSet<Type>();
for (var construct : this.clazz.getConstructors().entrySet()) {
if (construct.getValue().block != null) {
types.add(construct.getValue().block.getType().getArgument(a));
}
}
return Type.compound(types);
}


@Override
public String getCode() {
return this.clazz == null ? "Class" : "Class<" + this.clazz.getName() + ">";
}
}
73 changes: 58 additions & 15 deletions src/main/java/leekscript/common/CompoundType.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import java.util.List;
import java.util.stream.Collectors;

import leekscript.compiler.Complete;

public class CompoundType extends Type {

protected HashSet<Type> types;
Expand All @@ -25,23 +27,34 @@ public CastType accepts(Type type) {

if (type instanceof CompoundType ct) {
var worst = CastType.EQUALS;
boolean ok = false;
boolean nok = false;
for (var t2 : ct.types) {
var best = CastType.INCOMPATIBLE;
for (var t1 : types) {
var r = t1.accepts(t2);
if (r.ordinal() < best.ordinal()) best = r;
}
if (best != CastType.INCOMPATIBLE) ok = true;
if (best != CastType.EQUALS) nok = true;
if (best.ordinal() > worst.ordinal()) worst = best;
}
if (worst == CastType.INCOMPATIBLE && ok) return CastType.UNSAFE_DOWNCAST;
if (worst == CastType.EQUALS && nok) return CastType.UPCAST;
return worst;
}

var best = CastType.INCOMPATIBLE;
boolean ok = false;
boolean nok = false;
for (var t : types) {
var r = t.accepts(type);
if (r == CastType.EQUALS) return r;
if (r.ordinal() < best.ordinal()) best = r;
if (best != CastType.INCOMPATIBLE) ok = true;
if (best != CastType.EQUALS) nok = true;
}
if (best == CastType.INCOMPATIBLE && ok) return CastType.UNSAFE_DOWNCAST;
if (best == CastType.EQUALS && nok) return CastType.UPCAST;
return best;
}

Expand Down Expand Up @@ -126,12 +139,17 @@ public int getMaxArguments() {

@Override
public CastType acceptsArguments(List<Type> types) {
var worst = CastType.EQUALS;
var best = CastType.INCOMPATIBLE;
for (var t : this.types) {
var r = t.acceptsArguments(types);
if (r.ordinal() > worst.ordinal()) worst = r;
if (r.ordinal() < best.ordinal()) best = r;
}
return worst;
return best;
}

@Override
public Type getArgument(int a) {
return Type.compound(this.types.stream().map(t -> t.getArgument(a)).collect(Collectors.toCollection(HashSet::new)));
}

@Override
Expand Down Expand Up @@ -161,21 +179,32 @@ public boolean isWarning() {
return this.types.stream().anyMatch(t -> t.isWarning());
}


public boolean isIntOrReal() {
return types.size() == 2 && types.contains(Type.INT) && types.contains(Type.REAL);
}

public String getJavaPrimitiveName(int version) {
var set = new HashSet<String>();
for (var t : types) {
set.add(t.getJavaPrimitiveName(version));
}
if (set.size() == 1) return set.iterator().next();
if (types.size() == 2 && types.stream().anyMatch(t -> t == Type.NULL)) {
for (var t : types)
if (t != Type.NULL) {
if (t == Type.BOOL || t == Type.INT || t == Type.REAL) {
return t.getJavaName(version);
} else {
return t.getJavaPrimitiveName(version);
if (types.size() == 2) {
if (types.stream().anyMatch(t -> t == Type.NULL)) {
for (var t : types) {
if (t != Type.NULL) {
if (t == Type.BOOL || t == Type.INT || t == Type.REAL) {
return t.getJavaName(version);
} else {
return t.getJavaPrimitiveName(version);
}
}
}
}
if (types.contains(Type.INT) && types.contains(Type.REAL)) {
return "Number";
}
}
return "Object";
}
Expand All @@ -186,11 +215,25 @@ public String getJavaName(int version) {
set.add(t.getJavaName(version));
}
if (set.size() == 1) return set.iterator().next();
if (types.size() == 2 && types.stream().anyMatch(t -> t == Type.NULL)) {
for (var t : types)
if (t != Type.NULL)
return t.getJavaName(version);
if (types.size() == 2) {
if (types.stream().anyMatch(t -> t == Type.NULL)) {
for (var t : types)
if (t != Type.NULL)
return t.getJavaName(version);
}
if (types.contains(Type.INT) && types.contains(Type.REAL)) {
return "Number";
}
}
return "Object";
}

@Override
public Complete complete() {
var complete = new Complete(this);
for (var type : types) {
complete.addAll(type.complete());
}
return complete;
}
}
2 changes: 2 additions & 0 deletions src/main/java/leekscript/common/Error.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,6 @@ public enum Error {
MAY_NOT_BE_INDEXABLE, // 133
NOT_INDEXABLE, // 134
OVERRIDDEN_METHOD_DIFFERENT_TYPE, // 135
USELESS_CAST, // 136
TOO_MUCH_ERRORS, // 137
}
43 changes: 37 additions & 6 deletions src/main/java/leekscript/common/FunctionType.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

public class FunctionType extends Type {

Expand All @@ -13,13 +12,13 @@ public class FunctionType extends Type {
private int maxArguments = 0;

public FunctionType(Type return_type, List<Type> arguments) {
super("", "f", "FunctionLeekValue", "FunctionLeekValue", "new FunctionLeekValue()");
super("", "f", "FunctionLeekValue", "FunctionLeekValue", "null");
this.return_type = return_type;
this.arguments = arguments;
}

public FunctionType(Type return_type, Type... arguments) {
super("", "f", "FunctionLeekValue", "FunctionLeekValue", "new FunctionLeekValue()");
super("", "f", "FunctionLeekValue", "FunctionLeekValue", "null");
this.return_type = return_type;
this.arguments = new ArrayList<Type>(Arrays.asList(arguments));
this.minArguments = arguments.length;
Expand All @@ -28,7 +27,7 @@ public FunctionType(Type return_type, Type... arguments) {
}

public FunctionType(Type return_type, int min_arguments, Type... arguments) {
super("", "f", "FunctionLeekValue", "FunctionLeekValue", "new FunctionLeekValue()");
super("", "f", "FunctionLeekValue", "FunctionLeekValue", "null");
this.return_type = return_type;
this.arguments = new ArrayList<Type>(Arrays.asList(arguments));
this.minArguments = min_arguments;
Expand Down Expand Up @@ -78,8 +77,16 @@ public CastType accepts(Type type) {

if (ft.getArguments().size() < this.minArguments) return CastType.INCOMPATIBLE;

return CastType.EQUALS;
var worst = return_type.accepts(ft.getReturnType());
int n = Math.min(ft.getArguments().size(), this.arguments.size());
for (int a = 0; a < n; ++a) {
var cast = this.arguments.get(a).accepts(ft.getArgument(a));
if (cast.ordinal() > worst.ordinal()) worst = cast;
}

return worst;
}

if (type instanceof ClassValueType ct) {

if (ct.getClassDeclaration() == null) return CastType.UNSAFE_DOWNCAST;
Expand All @@ -99,8 +106,9 @@ public CastType accepts(Type type) {
return super.accepts(type);
}

@Override
public Type getArgument(int a) {
return arguments.get(a);
return a < arguments.size() ? arguments.get(a) : Type.VOID;
}

@Override
Expand Down Expand Up @@ -140,4 +148,27 @@ public boolean equals(Type type) {
}
return false;
}

@Override
public String getCode() {
String r = "Function<";
for (int a = 0; a < arguments.size(); ++a) {
if (a > 0) r += ", ";
// if (a >= this.minArguments) r += "[";
r += arguments.get(a).getCode();
// if (a >= this.minArguments) r += "]";
}
r += " => " + return_type.getCode() + ">";
return r;
}

@Override
public String getJavaPrimitiveName(int version) {
return "FunctionLeekValue<" + return_type.getJavaName(version) + ">";
}

@Override
public String getJavaName(int version) {
return "FunctionLeekValue<" + return_type.getJavaName(version) + ">";
}
}
2 changes: 1 addition & 1 deletion src/main/java/leekscript/common/ObjectType.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
public class ObjectType extends Type {

public ObjectType() {
super("Object", "o", "ObjectLeekValue", "ObjectLeekValue", "new ObjectLeekValue()");
super("Object", "o", "ObjectLeekValue", "ObjectLeekValue", "null");
}

@Override
Expand Down
Loading

0 comments on commit 8429a57

Please sign in to comment.