[Nice-commit] Nice/src/bossa/syntax methodbody.nice,NONE,1.1 enum.nice,1.4,1.5 tools.nice,1.64,1.65
Brought to you by:
bonniot
From: Arjan B. <ar...@us...> - 2004-11-27 18:46:46
|
Update of /cvsroot/nice/Nice/src/bossa/syntax In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6140/F:/nice/src/bossa/syntax Modified Files: enum.nice tools.nice Added Files: methodbody.nice Removed Files: MethodBodyDefinition.java Log Message: Converted MethodBodyDefinition. Index: tools.nice =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/tools.nice,v retrieving revision 1.64 retrieving revision 1.65 diff -C2 -d -r1.64 -r1.65 *** tools.nice 26 Nov 2004 20:26:02 -0000 1.64 --- tools.nice 27 Nov 2004 16:52:52 -0000 1.65 *************** *** 243,249 **** = native new MethodContainer.Constraint(TypeSymbol[], List, mlsub.typing.Monotype[], Location); ?gnu.bytecode.Type TypeImport_lookup(LocatedString) = native gnu.bytecode.Type nice.tools.code.TypeImport.lookup(LocatedString); - MethodBodyDefinition MethodBodyDefinition(NiceClass, LocatedString, ?Collection<LocatedString>, List<Pattern>, Statement) = native new MethodBodyDefinition(NiceClass, LocatedString, Collection, List, Statement); ?FormalParameters getFormalParameters(VarSymbol) = native FormalParameters VarSymbol.getFormalParameters(); List<Node> children(Node) = native Node.children; // Retypings needed since java types are not strict. --- 243,250 ---- = native new MethodContainer.Constraint(TypeSymbol[], List, mlsub.typing.Monotype[], Location); ?gnu.bytecode.Type TypeImport_lookup(LocatedString) = native gnu.bytecode.Type nice.tools.code.TypeImport.lookup(LocatedString); ?FormalParameters getFormalParameters(VarSymbol) = native FormalParameters VarSymbol.getFormalParameters(); List<Node> children(Node) = native Node.children; + Pattern[] formals(MethodImplementation) = native MethodImplementation.formals; + LocatedString name(Definition) = native Definition.name; // Retypings needed since java types are not strict. Index: enum.nice =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/enum.nice,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** enum.nice 26 Nov 2004 20:26:02 -0000 1.4 --- enum.nice 27 Nov 2004 16:52:52 -0000 1.5 *************** *** 78,82 **** if (! notNull(Definition.currentModule).interfaceFile()) // create the method implementation of family() ! globalDefs.add(new MethodBodyDefinition(impl, new LocatedString("family"), null, new LinkedList(), createReturnStmt(createLiteralArrayExp( elements.map(LocatedString elem => new IdentExp(elem))), true))); --- 78,82 ---- if (! notNull(Definition.currentModule).interfaceFile()) // create the method implementation of family() ! globalDefs.add(createMethodBodyDefinition(impl, new LocatedString("family"), null, new LinkedList(), createReturnStmt(createLiteralArrayExp( elements.map(LocatedString elem => new IdentExp(elem))), true))); --- MethodBodyDefinition.java DELETED --- --- NEW FILE: methodbody.nice --- /**************************************************************************/ /* N I C E */ /* A high-level object-oriented research language */ /* (c) Daniel Bonniot 2004 */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /**************************************************************************/ package bossa.syntax; import bossa.util.*; /** Definition of an alternative for a method. */ public class MethodBodyDefinition extends MethodImplementation { ?Collection<LocatedString> binders; // Null if type parameters are not bound private ?List<VarSymbol> symbols = null; hasThis() { return this.formals.length >= 1 && String.valueOf(this.formals[0].name).equals("this"); } firstArgument() { if (formals[0].tc != null) return notNull(formals[0].tc); else // Either there is no specialization on the first parameter, or // it was equivalent to the declaration type and has been erased, // so we return the information in the declaration. return notNull(nice.tools.typing.Types.equivalent(notNull(declaration).getArgTypes()[0]). head()); } private void setDeclaration(MethodDeclaration d) { if (d == null) User.error(this, "Method " + name + " is not declared"); this.declaration = d; if (d instanceof JavaMethod) { d.registerForDispatch(); if (TypeConstructors.isInterface(formals[0].tc)) User.error(this, notNull(name) + " is a native method. Dispatch can only occur if the first argument is not an interface."); } else if (! (d instanceof NiceMethod)) User.error(this, "Implementations can only be made for methods, but " + d.getName() + " is a function.\nIt was defined at:\n" + d.location()); this.buildSymbols(); } /** Returns the symbol of the method this declaration belongs to. */ private ?VarSymbol findSymbol(List<VarSymbol> symbols) { if (symbols.isEmpty()) return null; ?mlsub.typing.TypeConstructor[] additionalTags = cast(Pattern.getAdditionalTC(formals)); boolean hasAdditionalTags = additionalTags.any( ? TypeConstructor tc => tc != null); // Try to remember what caused the error when no symbol could be found. let errorList = new ErrorList(); for(let i = symbols.iterator(); i.hasNext();){ VarSymbol s = i.next(); if(s.getMethodDeclaration() == null) { i.remove(); continue; } MethodDeclaration m = s.getMethodDeclaration(); if (m.isIgnored()) { i.remove(); continue; } if (m.getArity() != formals.length || !(m instanceof NiceMethod || m instanceof JavaMethod)) { i.remove(); continue; } try{ int level; if (bossa.util.Debug.overloading) level = mlsub.typing.Typing.enter("Trying declaration " + m + " for method body "+name); else level = mlsub.typing.Typing.enter(); try{ mlsub.typing.Polytype t = m.getType(); mlsub.typing.Constraint.enter(t.getConstraint()); mlsub.typing.Monotype[] domain = t.domain(); for (int p = 0; p < domain.length; p++) try { formals[p].inDomain(domain[p]); } catch (TypingEx e) { errorList.add(m, new LocatedString("Pattern " + formals[p] + " is incompatible with " + domain[p], formals[p].location())); throw e; } } finally{ if (Typing.leave() != level) Internal.error("Enter/Leave error"); } } catch(TypingEx e){ if (bossa.util.Debug.overloading) bossa.util.Debug.println("Not the right choice :"+e); i.remove(); } catch(mlsub.typing.BadSizeEx e){ i.remove(); } } /* If the method are ambigious and the implementation has additional tc's * then try to find the most specific declaration(s) using these tc's * TODO: combine this code with removeNonMinimal in OverloadedSymbolExp */ if (symbols.size() > 1 && hasAdditionalTags) { // FIXME change to MethodSymbol[] once converted to nice. VarSymbol[] tempSymbols = symbols.toArray(); int size = symbols.size(); symbols = new LinkedList(); int len = formals.length; boolean[] removed = new boolean[size]; for (int m1 = 0; m1 < size; m1++) { mlsub.typing.Monotype[] dom1 = tempSymbols[m1].getMethodDeclaration().getType().domain(); for (int m2 = 0; m2 < size; m2++) if (m1 != m2) { boolean remove = true; boolean additionalsEqual = true; mlsub.typing.Monotype[] dom2 = tempSymbols[m2].getMethodDeclaration().getType().domain(); for (int i = 0; i < len; i++) if (additionalTags[i] != null) { try { this.domainMonotypeLeq(dom2[i], dom1[i]); try { this.domainMonotypeLeq(dom1[i], dom2[i]); } catch (TypingEx e) { additionalsEqual = false; } } catch(TypingEx e) { remove = false; break; } } //may not remove a method that is equal for the arguments with an additional. removed[m1] = remove && !additionalsEqual; if (removed[m1]) break; } if (!removed[m1]) symbols.add(tempSymbols[m1]); } } // Check that the non-dispatched parameter names match the declaration outer: for(let it = symbols.iterator(); it.hasNext();) { MethodDeclaration m = it.next().getMethodDeclaration(); if( m instanceof NiceMethod) { FormalParameters params = m.formalParameters(); for (int i = params.hasThis() ? 1 : 0; i < formals.length; i++) if (formals[i].atAny() && formals[i].name != null && params.getName(i) != null && !notNull(formals[i].name).toString().equals(params.getName(i).toString())) { errorList.add(m, new LocatedString("Parameter " + formals[i] + " should be called " + params.getName(i), formals[i].location())); it.remove(); continue outer; } } } removeNonMinimal(symbols); if (symbols.size() == 1) return symbols[0]; if (symbols.isEmpty()) { errorList.report(); // Default message in case we could not produce a better one. User.error(this, "No method called " + name + " is compatible with these patterns"); } String methods = ""; for (s : symbols) { MethodDeclaration m = s.getMethodDeclaration(); methods += m + " defined " + m.location() + "\n"; } throw User.error (this, "There is an ambiguity about which version " + " of the overloaded method \"" + name + "\" this alternative belongs to.\n" + "Try to use more patterns.\n\n" + "Possible methods:\n" + methods); } private void domainMonotypeLeq(mlsub.typing.Monotype m1, mlsub.typing.Monotype m2) { if (m1 == m2) return; nice.tools.typing.Types.setMarkedKind(m1); nice.tools.typing.Types.setMarkedKind(m2); mlsub.typing.Typing.leq(nice.tools.typing.Types.rawType(m1), nice.tools.typing.Types.rawType(m2)); } doResolve() { //Resolution of the body is delayed to enable overloading Pattern.resolve(notNull(typeScope), Node.getGlobalScope(), formals); symbols = notNull(scope).lookup(name); } void lateBuildScope() { Pattern.resolveValues(formals); let s = this.findSymbol(notNull(symbols)); symbols = null; if (s==null) throw User.error(this, name+" is not declared"); if (s.getMethodDeclaration() == null) User.error(this, name+" is not a method"); MethodDeclaration decl = s.getMethodDeclaration(); this.setDeclaration(decl); // Get type parameters if (binders != null) { let cst = notNull(declaration).getType().getConstraint(); if (! mlsub.typing.Constraint.hasBinders(cst)) User.error(name, "Method " + name + " has no type parameters"); try{ notNull(typeScope).addMappingsLS(cast(binders), notNull(cst).binders()); } catch(mlsub.typing.BadSizeEx e){ User.error(name, "Method " + name + " expects " + e.expected + " type parameters"); } catch(TypeScope.DuplicateName e) { User.error(this, e); } } try{ for (f : formals) { let tc = f.getRuntimeTC(); if (tc != null) notNull(typeScope).addSymbol(tc); } } catch(TypeScope.DuplicateName e) { User.error(this, e); } if (! notNull(declaration).specializesMethods()) this.removeUnnecessaryDispatch(); } private void removeUnnecessaryDispatch() { boolean entered = false; if (mlsub.typing.Constraint.hasBinders(notNull(declaration).getType().getConstraint())) { mlsub.typing.Typing.enter(); entered = true; } try { try { mlsub.typing.Constraint.enter(notNull(declaration).getType().getConstraint()); Typing.implies(); mlsub.typing.Monotype[] domain = notNull(declaration).getType().domain(); for (int n = 0; n < formals.length; n++) { let tc = nice.tools.typing.Types.rawType(domain[n]).head(); if (formals[n].tc != null) formals[n] = formals[n].setDomainEq(tc != null && nice.tools.typing.Types.isSure(domain[n]) && Typing.testLeq(tc, formals[n].tc)); } } finally { if (entered) Typing.leave(); } } catch(TypingEx ex) { Internal.warning(ex.toString()); } } typecheck() { boolean errorFound = false; int level; if (bossa.util.Debug.typing) level = Typing.enter("METHOD BODY " + this + "\n\n"); else level = Typing.enter(); try { try { try { mlsub.typing.Constraint.enter(notNull(declaration).getType().getConstraint()); } catch(TypingEx e){ throw User.error(name, "the constraint will never be satisfied", ": "+e.getMessage()); } // Introduce the types of the arguments mlsub.typing.Monotype[] monotypes = MonoSymbol.getMonotype(parameters); for (int n = 0; n < formals.length; n++) { let runtimeTC = formals[n].getRuntimeTC(); if (runtimeTC == null) mlsub.typing.Typing.introduce(monotypes[n]); else mlsub.typing.Typing.introduce(runtimeTC); } mlsub.typing.Monotype[] domain = notNull(declaration).getType().domain(); for(int n = 0; n < formals.length; n++) { let tc = nice.tools.typing.Types.rawType(domain[n]).head(); if (formals[n].tc != null) formals[n].setDomainTC(tc); } // The arguments are specialized by the patterns try { Pattern.in(monotypes, formals); } catch(TypingEx e){ throw User.error(name,"The patterns are not correct", e); } // The arguments have types below the method declaration domain for (int i = 0; i < monotypes.length; i++) try { mlsub.typing.Typing.leq(monotypes[i], domain[i]); } catch(TypingEx e) { /* This type error originates from an inadequation between the pattern and the domain. The parameter types are just variables that connected the two. */ throw User.error(formals[i], "Pattern " + formals[i] + " is incompatible with type " + domain[i]); } try { nice.tools.code.Types.setBytecodeType(monotypes); Typing.implies(); } catch(TypingEx e) { throw User.error(name, "Type error in method body \""+name+"\":\n"+e); } Node.currentFunction = this; if (this.hasThis()) Node.thisExp = new SymbolExp(notNull(parameters)[0], this.location()); typecheck(body); } catch(UserError ex){ module.compilation().error(ex); errorFound = true; } } finally { Node.currentFunction = null; Node.thisExp = null; try { if (Typing.leave() != level) Internal.error("Unmatching enter/leave"); } catch(TypingEx e){ if (! errorFound) User.error(this, "Type error in method "+name, ": "+e); } } // If the method we implement specialize others, then we cannot // omit the patterns, as we do handle only a special case of those // more general methods. if (notNull(declaration).specializesMethods()) this.addPatterns(); } printInterface(s) { // Not exported } javaArgTypes() { gnu.bytecode.Type[] res = cast(new gnu.bytecode.Type[notNull(parameters).length]); for(int n = 0; n < notNull(parameters).length; n++) res[n] = formals[n].atNull() ? nice.tools.code.Types.javaType(PrimitiveType.nullTC) : formals[n].tc == bossa.syntax.PrimitiveType.arrayTC ? nice.tools.code.SpecialArray.unknownTypeArray() : nice.tools.code.Types.javaType(notNull(parameters)[n].getMonotype()); return res; } gnu.expr.Expression[] compiledArguments() { return notNull(parameters).map(VarSymbol s => s.compile()); } toString() = notNull(name) + "(" + Util.map("", ", ", "", formals) + ")"; } /** * Create a method alternative. * * @param name the name of the method. * @param binders * used to rebind the type parameters of the method definition. * Null if one doesn't want to rebind them. * @param newConstraint list of AtomicConstraint * @param formals list of Pattern * @param body s statement representing the body of the method. */ public MethodBodyDefinition createMethodBodyDefinition(?NiceClass container, LocatedString name, ?Collection<LocatedString> binders, List<Pattern> formals, Statement body) { let res = new MethodBodyDefinition(name, body, makeFormals(formals, container, notNull(name.location())), binders: binders); res.declaration = null; return res; } private Pattern[] makeFormals(List<Pattern> formals, ?NiceClass container, bossa.util.Location loc) { if (container == null) return formals.toArray(); List<Pattern> res = new ArrayList(); res.add(createPattern(new LocatedString("this", loc), new TypeIdent(container.getName()))); res.addAll(formals); return res.toArray(); } private class ErrorList { private List<LocatedString> errors = new ArrayList(); boolean multipleErrors = false; void add(MethodDeclaration method, LocatedString message) { errors.add(message); } void report() { if (errors.size() == 1) { let message = errors[0]; throw new UserError(message.location(), message.toString()); } } } |