/src/org/ooc/frontend/model/FunctionCall.java

http://github.com/nddrylliog/ooc · Java · 769 lines · 608 code · 131 blank · 30 comment · 216 complexity · 95b25b024f002a758ccd1c582cc0281f MD5 · raw file

  1. package org.ooc.frontend.model;
  2. import java.io.IOException;
  3. import java.util.Iterator;
  4. import org.ooc.frontend.Levenshtein;
  5. import org.ooc.frontend.Visitor;
  6. import org.ooc.frontend.model.interfaces.MustBeResolved;
  7. import org.ooc.frontend.model.tokens.Token;
  8. import org.ooc.middle.OocCompilationError;
  9. import org.ooc.middle.hobgoblins.Resolver;
  10. public class FunctionCall extends Access implements MustBeResolved {
  11. protected boolean dead = false;
  12. protected boolean superCall;
  13. protected String name;
  14. protected String suffix;
  15. protected final NodeList<Expression> typeParams;
  16. protected final NodeList<Expression> arguments;
  17. protected FunctionDecl impl;
  18. protected Expression returnArg;
  19. protected Type realType;
  20. public FunctionCall(String name, Token startToken) {
  21. this(name, null, startToken);
  22. }
  23. public FunctionCall(String name, String suffix, Token startToken) {
  24. super(startToken);
  25. this.name = name;
  26. this.suffix = suffix;
  27. this.typeParams = new NodeList<Expression>();
  28. this.arguments = new NodeList<Expression>(startToken);
  29. this.impl = null;
  30. this.returnArg = null;
  31. this.realType = null;
  32. if(name.equals("super")) setSuperCall(true);
  33. }
  34. public FunctionCall(FunctionDecl func, Token startToken) {
  35. this(func.getName(), func.getSuffix(), startToken);
  36. setImpl(func);
  37. }
  38. public boolean isSuperCall() {
  39. return superCall;
  40. }
  41. public void setSuperCall(boolean superCall) {
  42. this.superCall = superCall;
  43. }
  44. public void setImpl(FunctionDecl impl) {
  45. this.impl = impl;
  46. }
  47. public FunctionDecl getImpl() {
  48. return impl;
  49. }
  50. public String getName() {
  51. return name;
  52. }
  53. public void setName(String name) {
  54. this.name = name;
  55. }
  56. public String getSuffix() {
  57. return suffix;
  58. }
  59. public void setSuffix(String suffix) {
  60. this.suffix = suffix;
  61. }
  62. public NodeList<Expression> getTypeParams() {
  63. return typeParams;
  64. }
  65. public NodeList<Expression> getArguments() {
  66. return arguments;
  67. }
  68. public Expression getReturnArg() {
  69. return returnArg;
  70. }
  71. public void setReturnArg(Expression returnArg) {
  72. this.returnArg = returnArg;
  73. }
  74. public Type getType() {
  75. return realType;
  76. }
  77. private Type realTypize(Type typeArg, Resolver res, NodeList<Node> stack) {
  78. Type type = getRealType(typeArg, stack, res, true);
  79. if(type == null) {
  80. type = typeArg.clone();
  81. }
  82. int i = -1;
  83. for(Access exprParam: type.getTypeParams()) {
  84. i++;
  85. String name = "";
  86. if(exprParam instanceof VariableAccess) {
  87. name = ((VariableAccess) exprParam).getName();
  88. } else if(exprParam instanceof FunctionCall) {
  89. name = ((FunctionCall) exprParam).getName();
  90. }
  91. Access expr = getExprParam(name, stack, res, true);
  92. if(expr != null){
  93. type.getTypeParams().set(i, expr);
  94. }
  95. }
  96. return type;
  97. }
  98. public void accept(Visitor visitor) throws IOException {
  99. visitor.visit(this);
  100. }
  101. public boolean hasChildren() {
  102. return true;
  103. }
  104. public void acceptChildren(Visitor visitor) throws IOException {
  105. typeParams.accept(visitor);
  106. arguments.accept(visitor);
  107. if(realType != null) realType.accept(visitor);
  108. if(returnArg != null) returnArg.accept(visitor);
  109. }
  110. @Override
  111. public boolean replace(Node oldie, Node kiddo) {
  112. if(oldie == impl) {
  113. impl = (FunctionDecl) kiddo;
  114. return true;
  115. }
  116. return false;
  117. }
  118. public boolean isResolved() {
  119. return false;
  120. }
  121. public Response resolve(final NodeList<Node> stack, final Resolver res, final boolean fatal) {
  122. if(dead) return Response.OK;
  123. if(impl == null) {
  124. Response response;
  125. if (name.equals("this")) {
  126. int fDeclIndex = stack.find(FunctionDecl.class);
  127. FunctionDecl fDecl = (FunctionDecl) stack.get(fDeclIndex);
  128. throw new OocCompilationError(this, stack, "this calls are deprecated now. Just use "+fDecl.getName());
  129. } else if (name.equals("super")) {
  130. response = resolveConstructorCall(stack, res, true);
  131. } else {
  132. response = resolveRegular(stack, res, fatal);
  133. }
  134. if(response != Response.OK) return response;
  135. }
  136. if(impl != null) {
  137. if(impl.isMember()) {
  138. turnIntoMemberCall(stack, res);
  139. return Response.LOOP;
  140. }
  141. }
  142. if(impl != null) {
  143. autocast(stack, res);
  144. Response response = handleGenerics(stack, res, fatal);
  145. if(response != Response.OK) return response;
  146. }
  147. if(impl == null) {
  148. if(fatal) {
  149. String message = "No such function "+name+getArgsRepr()+".";
  150. String guess = guessCorrectName(stack, res);
  151. if(guess != null) {
  152. message += " Did you mean "+guess+" ?";
  153. }
  154. throw new OocCompilationError(this, stack, message);
  155. }
  156. return Response.LOOP;
  157. }
  158. return Response.OK;
  159. }
  160. protected Response handleGenerics(final NodeList<Node> stack, final Resolver res, boolean fatal) {
  161. if(dead) return Response.OK;
  162. if(impl == null) {
  163. if(fatal) throw new OocCompilationError(this, stack, "Didn't find implementation for "
  164. +this+", can't handle generics.");
  165. return Response.LOOP;
  166. }
  167. boolean andedSomearg = false;
  168. int argOffset = impl.hasThis() ? 1 : 0;
  169. for(int j = 0; j < impl.getArguments().size() - argOffset; j++) {
  170. Argument implArg = impl.getArguments().get(j + argOffset);
  171. if(implArg instanceof VarArg) { continue; }
  172. if(implArg.getType() == null || !implArg.getType().isResolved()) {
  173. // need ref arg type, we'll do it later
  174. return Response.LOOP;
  175. }
  176. if(!(implArg.getType().isGeneric() &&
  177. implArg.getType().getPointerLevel() == 0 &&
  178. implArg.getType().getReferenceLevel() == 0)) { continue; }
  179. Expression callArg = arguments.get(j);
  180. if(callArg.getType() == null || !callArg.getType().isResolved()) {
  181. // need call arg type
  182. return Response.LOOP;
  183. }
  184. if(!(callArg instanceof AddressOf) && !callArg.getType().isGeneric()) {
  185. arguments.set(j, new AddressOf(callArg, callArg.startToken));
  186. andedSomearg = true;
  187. }
  188. }
  189. // Find all variable accesses to fill this function's type params
  190. if(typeParams.size() < impl.getTypeParams().size()) {
  191. Iterator<TypeParam> iter = impl.getTypeParams().values().iterator();
  192. for(int i = 0; i < typeParams.size(); i++) iter.next();
  193. while(iter.hasNext()) {
  194. TypeParam typeParam = iter.next();
  195. Expression result = getExprParam(typeParam.getName(), stack, res, fatal);
  196. if(result == null) {
  197. if(fatal) throwUnresolvedType(stack, typeParam.getName(), res);
  198. return Response.LOOP;
  199. }
  200. typeParams.add(result);
  201. }
  202. //return Response.RESTART;
  203. }
  204. // Determine the real type of this function call.
  205. if(realType == null) {
  206. Type retType = impl.getReturnType();
  207. if(!retType.isResolved()) {
  208. // should know if it's generic or not
  209. return Response.LOOP;
  210. }
  211. if(retType.isGenericRecursive()) {
  212. Type candidate = realTypize(retType, res, stack);
  213. if(candidate == null) {
  214. if(fatal) throw new OocCompilationError(this, stack, "RealType still null, can't resolve generic type "+retType);
  215. return Response.LOOP;
  216. }
  217. realType = candidate;
  218. } else {
  219. realType = retType;
  220. }
  221. }
  222. /* Unwrap if needed */
  223. {
  224. Response response = unwrapIfNeeded(stack);
  225. if(response != Response.OK) return response;
  226. }
  227. /* Resolve returnArg */
  228. if(returnArg != null) {
  229. if(returnArg instanceof MustBeResolved && !((MustBeResolved) returnArg).isResolved()) {
  230. // need returnArg to be resolved
  231. return Response.LOOP;
  232. }
  233. if(!(returnArg instanceof AddressOf)) {
  234. returnArg = returnArg.getGenericOperand();
  235. }
  236. }
  237. if(andedSomearg) return Response.LOOP;
  238. return Response.OK;
  239. }
  240. private Response unwrapIfNeeded(final NodeList<Node> stack) {
  241. Node parent = stack.peek();
  242. if(impl == null || impl.getReturnType() == null) {
  243. // need ref and refType
  244. return Response.LOOP;
  245. }
  246. Cast cast = null;
  247. int idx = 1;
  248. while(parent instanceof Cast) {
  249. cast = (Cast) parent;
  250. idx += 1;
  251. parent = stack.peek(idx);
  252. }
  253. if(impl.getReturnType().isGeneric() && !isFriendlyHost(parent)) {
  254. VariableDecl vDecl = new VariableDecl(getType(), generateTempName("genCall", stack), startToken, stack.getModule());
  255. stack.addBeforeLine(stack, vDecl);
  256. VariableAccess varAcc = new VariableAccess(vDecl, startToken);
  257. setReturnArg(varAcc);
  258. CommaSequence seq = new CommaSequence(startToken);
  259. seq.getBody().add(this);
  260. seq.getBody().add(cast != null ? new Cast(varAcc, cast.getType(), varAcc.startToken) : varAcc);
  261. stack.peek().replace(this, seq);
  262. // just unwrapped
  263. return Response.LOOP;
  264. }
  265. return Response.OK;
  266. }
  267. /**
  268. * In some cases, a generic function call needs to be unwrapped,
  269. * e.g. when it's used as an expression in another call, etc.
  270. * However, some nodes are 'friendly' parents to us, e.g.
  271. * they handle things themselves and we don't need to unwrap.
  272. * @return true if the node is friendly, false if it is not and we
  273. * need to unwrap
  274. */
  275. private boolean isFriendlyHost (Node node) {
  276. return (node instanceof Line) ||
  277. (node instanceof CommaSequence) ||
  278. (node instanceof VariableDecl) ||
  279. (node instanceof Assignment);
  280. }
  281. protected final Type getRealType(Type typeArg, NodeList<Node> stack, Resolver res, boolean fatal) {
  282. Expression realExpr = getRealExpr(typeArg.getName(), stack, res, fatal);
  283. if(realExpr == null) {
  284. return null;
  285. }
  286. if(realExpr instanceof VariableAccess && ((VariableAccess) realExpr).getName().equals(typeArg.getName())) {
  287. return typeArg.clone();
  288. }
  289. return realExpr instanceof TypeParam ? null : realExpr.getType();
  290. }
  291. protected Expression getRealExpr(String typeParam, NodeList<Node> stack, Resolver res, boolean fatal) {
  292. if(impl == null) return null;
  293. Expression result = null;
  294. int i = -1;
  295. boolean isFirst = true;
  296. for(Argument arg: impl.getArguments()) {
  297. if(isFirst && impl.hasThis()) {
  298. isFirst = false;
  299. continue;
  300. }
  301. i++;
  302. Expression callArg = arguments.get(i);
  303. // e.g. func <T> myFunc(T: Class), and arg = T
  304. if(arg.getName().equals(typeParam)) {
  305. result = callArg;
  306. if(res.params.veryVerbose || debugCondition())
  307. System.out.println("[getRealExpr] Matched <"+typeParam+"> with "+result+", argName-wise");
  308. break;
  309. }
  310. // e.g. func <T> myFunc(value: T), and arg = value.
  311. if(arg.getType().getName().equals(typeParam)) {
  312. // not resolved yet?
  313. if(callArg.getType() == null) return null;
  314. Type ourType = callArg.getType();
  315. // make it flat!
  316. if(!ourType.isFlat()) {
  317. ourType = ourType.clone();
  318. ourType.setPointerLevel(0);
  319. ourType.setReferenceLevel(0);
  320. ourType.setArray(false);
  321. }
  322. TypeAccess typeAcc = new TypeAccess(ourType, callArg.startToken);
  323. typeAcc.resolve(stack, res, fatal);
  324. result = typeAcc;
  325. if(res.params.veryVerbose || debugCondition())
  326. System.out.println("[getRealExpr] Matched <"+typeParam+"> with "+result+", varAccType-wise");
  327. break;
  328. }
  329. // e.g. func <T> myFunc(list: List<T>)
  330. if(arg.getType().isGenericRecursive()) {
  331. if(res.params.veryVerbose || debugCondition())
  332. System.out.println("[getRealExpr] "+arg.getType()+" is generic-recursive, trying to get <"+typeParam+"> in it.");
  333. result = searchTypeParam(typeParam, callArg.getType(), stack, res, fatal);
  334. if(result != null) {
  335. if(res.params.veryVerbose)
  336. System.out.println("[getRealExpr] Matched <"+typeParam+"> with "+result+", genericRecursive-wise");
  337. break;
  338. }
  339. }
  340. }
  341. return result;
  342. }
  343. /**
  344. * Search for the type param @needle in the type @haystack
  345. */
  346. private Expression searchTypeParam(String needle, Type haystack,
  347. NodeList<Node> stack, Resolver res, boolean fatal) {
  348. Declaration ref = haystack.getRef();
  349. if(ref instanceof TypeDecl) {
  350. TypeDecl typeDecl = (TypeDecl) ref;
  351. Iterator<String> keys = typeDecl.getTypeParams().keySet().iterator();
  352. int i = -1;
  353. while(keys.hasNext()) {
  354. i++;
  355. String key = keys.next();
  356. if(key.equals(needle)) {
  357. Type realType = getRealType(haystack, stack, res, fatal);
  358. if(realType != null && i < realType.getTypeParams().size()) {
  359. return realType.getTypeParams().get(i);
  360. }
  361. }
  362. }
  363. }
  364. return null;
  365. }
  366. protected Access getExprParam(String typeParam, NodeList<Node> stack, Resolver res, boolean fatal) {
  367. if(impl == null) return null;
  368. Access result = null;
  369. Expression callArg = getRealExpr(typeParam, stack, res, fatal);
  370. if(callArg != null && callArg.getType() != null) {
  371. if(callArg.getType().getName().equals("Class")) {
  372. result = (Access) callArg;
  373. if(debugCondition()) System.out.println("[getExprParam] callArg type name is 'Class'");
  374. } else if(callArg.getType().isGeneric()) {
  375. VariableAccess varAcc = new VariableAccess(typeParam, callArg.startToken);
  376. result = varAcc;
  377. if(debugCondition()) System.out.println("[getExprParam] callArg type is generic");
  378. } else {
  379. result = (Access) callArg;
  380. if(debugCondition()) System.out.println("[getExprParam] callArg-normal");
  381. }
  382. }
  383. if(debugCondition()) System.out.println("Found exprParam "+result+" for typeParam "+typeParam+" in "+this);
  384. return result;
  385. }
  386. // used to determine if debug messages should be printed (usually comparing a name)
  387. private boolean debugCondition() {
  388. return false;
  389. }
  390. protected void autocast(NodeList<Node> stack, Resolver res) {
  391. if(impl == null) return;
  392. Iterator<Expression> callArgs = arguments.iterator();
  393. Iterator<Argument> implArgs = impl.getThisLessArgsIter();
  394. while(implArgs.hasNext() && callArgs.hasNext()) {
  395. Expression callArg = callArgs.next();
  396. Argument implArg = implArgs.next();
  397. if(implArg.getType() == null || callArg.getType() == null) {
  398. continue;
  399. }
  400. if(implArg.getType().isSuperOf(callArg.getType())
  401. && implArg.getType().getRef() != null
  402. && callArg.getType().getRef() != null) {
  403. Type targetType = implArg.getType();
  404. if(!callArg.getType().getTypeParams().isEmpty()) {
  405. targetType = targetType.clone();
  406. targetType.getTypeParams().clear();
  407. targetType.getTypeParams().addAll(callArg.getType().getTypeParams());
  408. }
  409. arguments.replace(callArg, new Cast(callArg, targetType, callArg.startToken));
  410. }
  411. }
  412. }
  413. protected String guessCorrectName(final NodeList<Node> mainStack, final Resolver res) {
  414. int bestDistance = Integer.MAX_VALUE;
  415. String bestMatch = null;
  416. NodeList<FunctionDecl> funcs = new NodeList<FunctionDecl>();
  417. for(int i = mainStack.size() - 1; i >= 0; i--) {
  418. Node node = mainStack.get(i);
  419. if(!(node instanceof Scope)) continue;
  420. ((Scope) node).getFunctions(funcs);
  421. }
  422. for(FunctionDecl decl: funcs) {
  423. int distance = Levenshtein.distance(name, decl.getName());
  424. if(distance < bestDistance) {
  425. bestDistance = distance;
  426. bestMatch = decl.getProtoRepr();
  427. }
  428. }
  429. Module module = (Module) mainStack.get(0);
  430. for(Import imp: module.getGlobalImports()) {
  431. for(Node node: imp.getModule().body) {
  432. if(node instanceof FunctionDecl) {
  433. FunctionDecl decl = (FunctionDecl) node;
  434. int distance = Levenshtein.distance(name, decl.getName());
  435. if(distance < bestDistance) {
  436. bestDistance = distance;
  437. bestMatch = decl.getProtoRepr();
  438. }
  439. }
  440. }
  441. }
  442. if(bestDistance > 3) return null;
  443. return bestMatch;
  444. }
  445. protected Response resolveConstructorCall(final NodeList<Node> mainStack, Resolver res, final boolean isSuper) throws OocCompilationError {
  446. int typeIndex = mainStack.find(TypeDecl.class);
  447. if(typeIndex == -1) {
  448. throw new OocCompilationError(this, mainStack, (isSuper ? "super" : "this")
  449. +getArgsRepr()+" call outside a class declaration, doesn't make sense.");
  450. }
  451. TypeDecl typeDecl = (TypeDecl) mainStack.get(typeIndex);
  452. if(isSuper) {
  453. if(!(typeDecl instanceof ClassDecl)) {
  454. throw new OocCompilationError(this, mainStack, "super"+getArgsRepr()+" call in type def "
  455. +typeDecl.getName()+" which is not a class! wtf?");
  456. }
  457. ClassDecl classDecl = ((ClassDecl) typeDecl);
  458. if(classDecl.getSuperRef() == null) {
  459. throw new OocCompilationError(this, mainStack, "super"+getArgsRepr()+" call in class "
  460. +typeDecl.getName()+" which has no super-class!");
  461. }
  462. typeDecl = classDecl.getSuperRef();
  463. }
  464. int funcIndex = mainStack.find(FunctionDecl.class);
  465. if(funcIndex == -1) {
  466. throw new OocCompilationError(this, mainStack, (isSuper ? "super" : "this")
  467. +getArgsRepr()+" call outside a function declaration, doesn't make sense.");
  468. }
  469. FunctionDecl outDecl = (FunctionDecl) mainStack.get(funcIndex);
  470. impl = typeDecl.getFunction(outDecl.getName(), getSuffix(), this);
  471. if(impl != null) {
  472. setName(impl.getName());
  473. turnIntoMemberCall(mainStack, res);
  474. return Response.LOOP;
  475. }
  476. return Response.OK;
  477. }
  478. protected Response resolveRegular(NodeList<Node> stack, Resolver res, boolean fatal) {
  479. impl = getFunction(name, suffix, this, stack);
  480. if(impl == null) {
  481. Module module = (Module) stack.get(0);
  482. for(Import imp: module.getGlobalImports()) {
  483. searchIn(imp.getModule());
  484. if(impl != null) break;
  485. }
  486. }
  487. if(impl == null) {
  488. int typeIndex = stack.find(TypeDecl.class);
  489. if(typeIndex != -1) {
  490. TypeDecl typeDeclaration = (TypeDecl) stack.get(typeIndex);
  491. for(VariableDecl varDecl: typeDeclaration.getVariables()) {
  492. if(varDecl.getType() instanceof FuncType && varDecl.getName().equals(name)) {
  493. FuncType funcType = (FuncType) varDecl.getType();
  494. if(matchesArgs(funcType.getDecl())) {
  495. impl = funcType.getDecl();
  496. // copy the module information for getFullName if it's global.
  497. if(varDecl.isGlobal())
  498. impl.module = varDecl.module;
  499. break;
  500. }
  501. }
  502. }
  503. }
  504. }
  505. if(impl == null) {
  506. VariableDecl varDecl = getVariable(name, stack, null);
  507. if(varDecl != null) {
  508. if(varDecl.getName().equals(name)) {
  509. if(varDecl.getType() instanceof FuncType) {
  510. FuncType funcType = (FuncType) varDecl.getType();
  511. impl = funcType.getDecl();
  512. // copy the module information for getFullName if it's global.
  513. if(varDecl.isGlobal())
  514. impl.module = varDecl.module;
  515. } else {
  516. if(varDecl.getType() == null) return Response.OK;
  517. if(fatal) {
  518. throw new OocCompilationError(this, stack, "Trying to call "
  519. +name+", which isn't a function pointer (Func), but a "+varDecl.getType());
  520. }
  521. return Response.LOOP;
  522. }
  523. }
  524. }
  525. }
  526. return Response.OK;
  527. }
  528. private void turnIntoMemberCall(final NodeList<Node> stack, final Resolver res) {
  529. MemberCall memberCall = null;
  530. if(impl.isStatic()) {
  531. memberCall = new MemberCall(new VariableAccess(impl.getTypeDecl().getType().getName(), startToken), this, startToken);
  532. } else {
  533. VariableAccess thisAccess = new VariableAccess("this", startToken);
  534. thisAccess.resolve(stack, res, true);
  535. memberCall = new MemberCall(thisAccess, this, startToken);
  536. }
  537. memberCall.setImpl(impl);
  538. memberCall.setSuperCall(isSuperCall());
  539. if(name.equals("super")) {
  540. System.out.println("KALAMAZOO just replaced " + this + " memberCall " + memberCall + ", isSuper = "+memberCall.isSuperCall());
  541. }
  542. stack.peek().replace(this, memberCall);
  543. this.dead = true;
  544. }
  545. protected void searchIn(Module module) {
  546. for(Node node: module.getBody()) {
  547. if(node instanceof FunctionDecl) {
  548. FunctionDecl decl = (FunctionDecl) node;
  549. if(matches(decl)) {
  550. impl = decl;
  551. return;
  552. }
  553. }
  554. }
  555. }
  556. public boolean matches(FunctionDecl decl) {
  557. return matchesName(decl) && matchesArgs(decl);
  558. }
  559. public boolean matchesArgs(FunctionDecl decl) {
  560. int numArgs = decl.getArguments().size();
  561. if(decl.hasThis()) numArgs--;
  562. if(numArgs == arguments.size()
  563. || ((numArgs > 0 && decl.getArguments().getLast() instanceof VarArg)
  564. && (numArgs - 1 <= arguments.size()))) {
  565. return true;
  566. }
  567. return false;
  568. }
  569. public boolean matchesName(FunctionDecl decl) {
  570. return decl.isNamed(name, suffix);
  571. }
  572. public String getArgsRepr() {
  573. StringBuilder sB = new StringBuilder();
  574. sB.append('(');
  575. Iterator<Expression> iter = arguments.iterator();
  576. while(iter.hasNext()) {
  577. Expression arg = iter.next();
  578. sB.append(arg.getType()+":"+arg);
  579. if(iter.hasNext()) sB.append(", ");
  580. }
  581. sB.append(')');
  582. return sB.toString();
  583. }
  584. public boolean isConstructorCall() {
  585. return name.equals("this") || name.equals("super");
  586. }
  587. public String getProtoRepr() {
  588. if(suffix == null || suffix.length() == 0) {
  589. return name+getArgsRepr();
  590. }
  591. return name+"~"+suffix+getArgsRepr();
  592. }
  593. @Override
  594. public String toString() {
  595. return getProtoRepr();
  596. }
  597. public int getScore(FunctionDecl decl) {
  598. int score = 0;
  599. NodeList<Argument> declArgs = decl.getArguments();
  600. if(matchesArgs(decl)) {
  601. score += 10;
  602. } else {
  603. return 0;
  604. }
  605. if(declArgs.size() == 0) return score;
  606. Iterator<Argument> declIter = declArgs.iterator();
  607. if(decl.hasThis() && declIter.hasNext()) declIter.next();
  608. Iterator<Expression> callIter = arguments.iterator();
  609. while(callIter.hasNext() && declIter.hasNext()) {
  610. Argument declArg = declIter.next();
  611. Expression callArg = callIter.next();
  612. if(declArg.getType() == null) {
  613. return -1;
  614. }
  615. if(declArg.getType().equals(callArg.getType())) {
  616. score += 10;
  617. }
  618. if(declArg.getType().isSuperOf(callArg.getType())) {
  619. score += 5;
  620. }
  621. }
  622. return score;
  623. }
  624. public void throwUnresolvedType(NodeList<Node> stack, String typeName, Resolver res) {
  625. if(res.params.veryVerbose) {
  626. Thread.dumpStack();
  627. }
  628. if(impl != null) {
  629. throw new OocCompilationError(this, stack, "Couldn't figure out generic type <"+typeName+"> for call to "+impl);
  630. }
  631. throw new OocCompilationError(this, stack, "Couldn't figure out generic type <"+typeName+"> for call to "+getProtoRepr());
  632. }
  633. public String getFullName() {
  634. if(impl.module != null)
  635. return impl.module.getMemberPrefix() + getName();
  636. return getName();
  637. }
  638. }