|
|
@@ -116,21 +116,7 @@ public class CGAdapter implements IClassGenerator {
|
|
|
/// return this.that.method_name(args...);
|
|
|
/// }
|
|
|
|
|
|
- // Find method with arguments:
|
|
|
- // 1. identical
|
|
|
- // 2. assignable
|
|
|
- // 3. castable
|
|
|
- CQuery<IMethod> query = that.methods().require(IAttribute.ANY).require(method.name()).stream().fetch();
|
|
|
-
|
|
|
- IMethod target = query.filter(r -> r.declares(method.arguments())).first()
|
|
|
- .or(() -> query.filter(r -> r.matches(method.arguments())).first())
|
|
|
- .or(() -> query.filter(r -> method.matches(r.arguments())).first())
|
|
|
- .or(() -> {
|
|
|
- List<IMethod> out = query.filter(r -> possible(method, r)).list();
|
|
|
- return Optional.ofNullable(out.size()==1 ? out.get(0) : null);
|
|
|
- })
|
|
|
- .orElseThrow(() -> new IllegalArgumentException("Not found method for: " + method));
|
|
|
-
|
|
|
+ IMethod target = find(method);
|
|
|
List<IClass<?>> oargs = target.arguments().types().list();
|
|
|
List<IClass<?>> iargs = method.arguments().types().list();
|
|
|
|
|
|
@@ -154,7 +140,61 @@ public class CGAdapter implements IClassGenerator {
|
|
|
m.end();
|
|
|
}
|
|
|
|
|
|
- private boolean possible(IMethod m1, IMethod m2) {
|
|
|
+ private IMethod find(IMethod method) {
|
|
|
+ BindInternal bi = method.annotation(BindInternal.class).orElse(null);
|
|
|
+ if(bi != null && bi.reflective()) {
|
|
|
+ throw new LinkageError("No compatible binding to " + method, new UnsupportedOperationException("Reflective binding is not implemented"));
|
|
|
+ }
|
|
|
+ IAttribute scope = bi != null ? IAttribute.ANY : IAttribute.PUBLIC;
|
|
|
+
|
|
|
+ CQuery<IMethod> query = that.methods()
|
|
|
+ .require(scope)
|
|
|
+ .require(method.name())
|
|
|
+ .stream()
|
|
|
+ .fetch();
|
|
|
+
|
|
|
+ if(query.size() == 1) {
|
|
|
+ IMethod found = query.first().get();
|
|
|
+ if(!isPossible(found, found)) {
|
|
|
+ throw new LinkageError("No compatible binding to " + method);
|
|
|
+ }
|
|
|
+ return found;
|
|
|
+ }
|
|
|
+
|
|
|
+ Optional<IMethod> exact = query.filter(r -> r.declares(method.arguments())).first();
|
|
|
+
|
|
|
+ if(exact.isPresent()) {
|
|
|
+ return exact.get();
|
|
|
+ }
|
|
|
+
|
|
|
+ CQuery<IMethod> assignable = query.filter(r -> r.matches(method.arguments()));
|
|
|
+ if(assignable.size() == 1) {
|
|
|
+ return assignable.first().get();
|
|
|
+ }
|
|
|
+ if(assignable.size() > 1) {
|
|
|
+ throw new LinkageError("Ambiguous widening binding to " + method);
|
|
|
+ }
|
|
|
+
|
|
|
+ CQuery<IMethod> narrowing = query.filter(r -> method.matches(r.arguments()));
|
|
|
+ if(narrowing.size() == 1) {
|
|
|
+ return narrowing.first().get();
|
|
|
+ }
|
|
|
+ if(narrowing.size() > 1) {
|
|
|
+ throw new LinkageError("Ambiguous narrowing binding to " + method);
|
|
|
+ }
|
|
|
+
|
|
|
+ CQuery<IMethod> possible = query.filter(r -> isPossible(method, r));
|
|
|
+ if(possible.size() == 1) {
|
|
|
+ return possible.first().get();
|
|
|
+ }
|
|
|
+ if(possible.size() > 1) {
|
|
|
+ throw new LinkageError("Ambiguous possible binding to " + method);
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new LinkageError("No compatible binding to " + method);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isPossible(IMethod m1, IMethod m2) {
|
|
|
if(m1.arguments().count() != m2.arguments().count()) {
|
|
|
return false;
|
|
|
}
|