PageRenderTime 87ms CodeModel.GetById 2ms app.highlight 74ms RepoModel.GetById 1ms app.codeStats 1ms

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