[Nice-commit] Nice/src/bossa/syntax assign.nice,NONE,1.1 break.nice,NONE,1.1 funexp.nice,NONE,1.1 if
Brought to you by:
bonniot
Update of /cvsroot/nice/Nice/src/bossa/syntax In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22973/F:/nice/src/bossa/syntax Modified Files: analyse.nice rewrite.nice tools.nice typecheck.nice Block.java CallExp.java CustomConstructor.java EnumDefinition.java Expression.java MethodBodyDefinition.java NewExp.java dispatch.java.bootstrap Added Files: assign.nice break.nice funexp.nice if.nice increment.nice literalarray.nice loop.nice newarray.nice overloadedsymbol.nice return.nice statementexp.nice synchronized.nice try.nice tuple.nice NiceUtils.java Log Message: Conversion of some expression and statement classes in bossa.syntax to nice code. Index: CustomConstructor.java =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/CustomConstructor.java,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** CustomConstructor.java 30 Jun 2004 14:12:37 -0000 1.15 --- CustomConstructor.java 28 Jul 2004 14:40:33 -0000 1.16 *************** *** 175,179 **** Location loc = ident.location(); ! call.function = new OverloadedSymbolExp (classe.getConstructorCallSymbols(), FormalParameters.thisName); call.function.setLocation(loc); --- 175,179 ---- Location loc = ident.location(); ! call.function = bossa.syntax.dispatch.createOverloadedSymbolExp (classe.getConstructorCallSymbols(), FormalParameters.thisName); call.function.setLocation(loc); Index: NewExp.java =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/NewExp.java,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -d -r1.38 -r1.39 *** NewExp.java 21 Dec 2003 02:50:55 -0000 1.38 --- NewExp.java 28 Jul 2004 14:40:33 -0000 1.39 *************** *** 80,84 **** constructors = (LinkedList) constructors.clone(); ! function = new OverloadedSymbolExp (constructors, new LocatedString("new " + tc, location())); } --- 80,84 ---- constructors = (LinkedList) constructors.clone(); ! function = bossa.syntax.dispatch.createOverloadedSymbolExp (constructors, new LocatedString("new " + tc, location())); } --- NEW FILE: funexp.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.*; /** A functional abstraction expression. */ public class FunExp extends Expression implements Function { final MonoSymbol[] formals; ?bossa.syntax.Constraint constraint; final Statement body; ?mlsub.typing.Constraint cst = null; boolean mightEscape = true; private boolean alwaysReturns = false; private ?mlsub.typing.Polytype _inferredReturnType = null; getExpectedType() { return cast(null); } checkReturnedType(returned) { if (_inferredReturnType == null) _inferredReturnType = returned; else { mlsub.typing.Polytype old = notNull(_inferredReturnType); _inferredReturnType = mlsub.typing.Polytype.union(_inferredReturnType, returned); if (! notNull(_inferredReturnType).trySimplify()) throw new Function.IncompatibleReturnType(old); } /* This is disabled, since currently default values of class fields are typechecked twice. if (type != null) Internal.error("Return statement discovered after computation of the type"); */ } void setAlwaysReturns(boolean value) { alwaysReturns = value; } computeType() { if (_inferredReturnType == null) // There is not return statement in the function. { if (alwaysReturns) /* This function never returns normally since there was no inferredReturnType, so it always throws an exception. Therefore, it can be considered to return any type. */ _inferredReturnType = mlsub.typing.Polytype.bottom(); else _inferredReturnType = PrimitiveType.voidPolytype; } else if (! alwaysReturns && ! nice.tools.typing.Types.isVoid(_inferredReturnType)) throw User.error(this, "Missing return statement"); mlsub.typing.Monotype t = new mlsub.typing.FunType(MonoSymbol.getMonotype(formals), notNull(_inferredReturnType).getMonotype()); type = new mlsub.typing.Polytype (mlsub.typing.Constraint.and(cst, notNull(_inferredReturnType).getConstraint()), bossa.syntax.Monotype.sure(t)); } inferredReturnType() { this.getType(); return notNull(_inferredReturnType); } /**************************************************************** * Code generation ****************************************************************/ compile() { gnu.expr.LambdaExp res = nice.tools.code.Gen.createMethod (null, nice.tools.code.Types.javaType(MonoSymbol.getMonotype(formals)), nice.tools.code.Types.javaType(this.inferredReturnType()), formals, false); nice.tools.code.Gen.setMethodBody(res, body.generateCode()); return res; } toString() { String bodyValue; if (body instanceof ReturnStmt) { let ReturnStmt rs = cast(body); bodyValue = notNull(rs.value).toString(); } else bodyValue = body.toString(); return (constraint == null ? mlsub.typing.Constraint.toString(cst) : notNull(constraint).toString()) + "(" + Util.map("",", ","",formals) + ") => " + bodyValue ; } } public Expression createFunExp(bossa.syntax.Constraint cst, List<MonoSymbol> formals, Statement body) { return new FunExp(constraint: cst, formals: formals.toArray(), body: body); } override Expression createFunExp(bossa.syntax.Constraint cst, MonoSymbol[] formals, Statement body) { let res = new FunExp(constraint: cst, formals: formals, body: body); res.setLocation(body.location()); return res; } --- NEW FILE: return.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.*; /** <tt>return</tt> in a function or method. */ public class ReturnStmt extends Statement { ?Expression value; boolean fake = false; mlsub.typing.Polytype returnType() { if (value == null) return notNull(PrimitiveType.voidPolytype); return notNull(value).getType(); } generateCode() { if (value == null) return notNull(nice.tools.code.Gen.returnVoid()); return nice.tools.code.Gen.returnValue(notNull(value).generateCode()); } toString() { return "return" + (value!=null ? " " + notNull(value) : "") + ";"; } } public Statement createReturnStmt(Expression value) { return createReturnStmt(value, false); } /** @param fake This return was not explicitely written, but is the result of syntactic sugar. */ public Statement createReturnStmt(Expression value, boolean fake) { let res = new ReturnStmt(value: value, fake: fake); if (value != null) res.setLocation(value.location()); return res; } --- NEW FILE: tuple.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.*; /** Creation of a tuple. */ public class TupleExp extends bossa.syntax.Expression { final bossa.syntax.Expression[] expressions; private mlsub.typing.Monotype[?] components = null; private mlsub.typing.Monotype[?] expectedComponents= null; /**************************************************************** * Typing ****************************************************************/ isAssignable() = expressions.all(Expression e => e.isAssignable()); /** Adjust the array type according to the context. This is usefull because arrays are non-variant. For instance, different code must be generated for [ 1, 2 ] in the contexts: int[] i = [ 1, 2 ] and byte[] b = [ 1, 2 ] */ resolveOverloading(mlsub.typing.Polytype expectedType) { // This can only help expectedType.simplify(); this.adjustToExpectedType(expectedType.getMonotype()); return this; } adjustToExpectedType(mlsub.typing.Monotype expectedType) { let m = nice.tools.typing.Types.equivalent(expectedType); // Get the expected component types if (m instanceof mlsub.typing.TupleType) { expectedComponents = (m).getComponents(); // Do the same for the elements of the tuple, since they might be // tuples themselves, literal arrays, ... bossa.syntax.Expression.adjustToExpectedType (expressions, expectedComponents); } } noOverloading() { for(int i = expressions.length; i-->0;) expressions[i] = expressions[i].noOverloading(); return this; } computeType() { let types = bossa.syntax.Expression.getType(expressions); // should create a new <tt>and</tt> method without the last dummy parameters let cst = mlsub.typing.Constraint.and(mlsub.typing.Polytype.getConstraint(types), null, null); components = mlsub.typing.Polytype.getMonotype(types); let tupleType = new mlsub.typing.TupleType(components); nice.tools.code.Types.setBytecodeType(components); if (expectedComponents == null) expectedComponents = components; type = new mlsub.typing.Polytype(cst, bossa.syntax.Monotype.sure(tupleType)); } /**************************************************************** * Code generation ****************************************************************/ compile() { // Force computation of the component types. this.getType(); /* We base the array type on the expected type, but we record the real type of the components. */ return nice.tools.code.TupleType.createExp (nice.tools.code.Types.lowestCommonSupertype(expectedComponents), nice.tools.code.Types.javaType(expectedComponents), bossa.syntax.Expression.compile(expressions)); } compileAssign(gnu.expr.Expression array) { ?gnu.expr.LetExp letExp = null; gnu.expr.Expression tupleExp; let arrayType = array.getType(); ?nice.tools.code.TupleType tupleType = null; if (arrayType instanceof nice.tools.code.TupleType) tupleType = arrayType; // if array is a complex expression, // we have to evaluate it and store the result // to avoid evaluating it several times. if (!(array instanceof gnu.expr.ReferenceExp)) { letExp = new gnu.expr.LetExp([array]); let tupleDecl = notNull(letExp).addDeclaration("tupleRef", arrayType); //FIXME: CanRead should be set automatically. tupleDecl.setCanRead(true); tupleExp = new gnu.expr.ReferenceExp(tupleDecl); } else tupleExp = array; let gnu.expr.Expression[] stmts = fill(new gnu.expr.Expression[expressions.length], int i => { gnu.expr.Expression value = new gnu.expr.ApplyExp(new nice.lang.inline.ArrayGetOp(null), [tupleExp, new gnu.expr.QuoteExp(new Integer(i))]); if (tupleType != null) value = nice.tools.code.EnsureTypeProc.ensure(value, notNull(tupleType.componentTypes)[i]); return expressions[i].compileAssign(value); }); if (letExp != null) { letExp.setBody(new gnu.expr.BeginExp(stmts)); return letExp; } else return new gnu.expr.BeginExp(stmts); } toString() = Util.map("(", ", ", ")", expressions); } public new TupleExp(List<bossa.syntax.Expression> expressions) { this(expressions: toArray(expressions)); } Index: Expression.java =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/Expression.java,v retrieving revision 1.54 retrieving revision 1.55 diff -C2 -d -r1.54 -r1.55 *** Expression.java 11 Feb 2004 12:46:39 -0000 1.54 --- Expression.java 28 Jul 2004 14:40:33 -0000 1.55 *************** *** 187,190 **** --- 187,196 ---- return res; } + + Polytype inferredReturnType() + { + Internal.error("inferredReturnType called in " + getClass()); + return null; + } void checkSpecialRequirements(Expression[] arguments) --- NEW FILE: loop.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.*; /** General loop statement (used for 'for', 'while do', 'do while' ...) */ public class LoopStmt extends Statement { ?Expression whileExp; final Statement loopBody; final ?Block iterationStatements = null; final boolean testFirst; ?gnu.expr.LoopExp code = null; private boolean mustCreateBlock = false; boolean isTestFirst() = testFirst; /**************************************************************** * Code generation ****************************************************************/ void createBlock() { mustCreateBlock = true; } /** Returns true iff there exists a break statement that target this loop. This means that the loop can complete abruptly because of that break. */ boolean isBreakTarget() = mustCreateBlock; /** Returns true iff this loop never completes normally. */ boolean isInfinite() { return (whileExp == null || notNull(whileExp).isTrue()) && ! this.isBreakTarget(); } generateCode() { gnu.expr.Expression test, iteration, res; if (whileExp == null) test = notNull(gnu.expr.QuoteExp.trueExp); else test = notNull(whileExp).generateCode(); if (iterationStatements == null) iteration = notNull(gnu.expr.QuoteExp.voidExp); else iteration = notNull(iterationStatements).generateCode(); code = new gnu.expr.LoopExp(test, iteration, testFirst); let savedBlock = currentLoopBlock; if (mustCreateBlock) res = currentLoopBlock = new gnu.expr.BlockExp(code); else res = notNull(code); notNull(code).setBody(loopBody != null ? notNull(loopBody).generateCode() : null); code = null; currentLoopBlock = savedBlock; return res; } /**************************************************************** * Printing ****************************************************************/ toString() { if (!testFirst) return "do {\n" + (loopBody == null ? " " : loopBody.toString()) + "}\n while (" + whileExp + ");"; if (iterationStatements == null) return "while (" + whileExp + ")" + (loopBody == null ? ";" : loopBody.toString()); Statement[] itStatements = cast(notNull(iterationStatements).statements); String itStats = ""; for(int i = 0; i<itStatements.length; i++) { String tmp = itStatements[i].toString(); itStats += tmp.substring(0, tmp.lastIndexOf(';')); if (i<itStatements.length-1) itStats += ", "; } return "for(; " + whileExp + " ;" + itStats + ")\n " + (loopBody == null ? "" : loopBody.toString()); } } public LoopStmt createForLoop (Expression test, Block update, Statement body) { return new LoopStmt(whileExp:test, loopBody: body, iterationStatements: update, testFirst: true); } public LoopStmt createWhileLoop(Expression test, Statement body) { return new LoopStmt(whileExp:test, loopBody: body, testFirst: true); } public LoopStmt createDoLoop(Expression test, Statement body) { return new LoopStmt(whileExp: test, loopBody: body, testFirst: false); } public Statement createForInLoop(?Monotype vartype, LocatedString varName, Location loc, Expression container, Statement body) { ?Monotype itertype = null; if (vartype != null) { List<Monotype> tparams = new ArrayList(1); tparams.add(vartype); itertype = new MonotypeConstructor(new TypeIdent(new LocatedString("Iterator", loc)), new TypeParameters(tparams), loc); notNull(itertype).nullness = Monotype.sure; } let getiter = CallExp.create(new IdentExp(new LocatedString("forIterator", loc)), container); let iter = new LocatedString(loc.uniqueIdentifier("for_in_iter_"), loc); let init = new Block.LocalVariable(iter, itertype, true, getiter); let iterexp = new IdentExp(iter); let cond = CallExp.create(new IdentExp(new LocatedString("hasNext", loc)), iterexp); let getvar = CallExp.create(new IdentExp(new LocatedString("next", loc)), iterexp); let assign = new Block.LocalVariable(varName, vartype, true, getvar); let loop = createWhileLoop(cond, new Block(new LinkedList([assign, body]))); return new Block(new LinkedList([init, loop])); } var ?gnu.expr.BlockExp currentLoopBlock = null; Index: typecheck.nice =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/typecheck.nice,v retrieving revision 1.101 retrieving revision 1.102 diff -C2 -d -r1.101 -r1.102 *** typecheck.nice 20 Jul 2004 22:37:49 -0000 1.101 --- typecheck.nice 28 Jul 2004 14:40:33 -0000 1.102 *************** *** 614,627 **** typecheck(e@LiteralArrayExp) { ! typecheckExps(notNull(e.elements)); } typecheck(e@NewArrayExp) { ! ?Expression[] knownDimensions = notNull(e.knownDimensions); ! typecheckExps(knownDimensions); for (int i=0; i<knownDimensions.length; i++) { ! Expression dim = notNull(knownDimensions[i]); try{ Typing.leq(dim.getType(), PrimitiveType.intPolytype); --- 614,627 ---- typecheck(e@LiteralArrayExp) { ! typecheckExps(cast(e.elements)); } typecheck(e@NewArrayExp) { ! Expression[] knownDimensions = notNull(e.knownDimensions); ! typecheckExps(cast(knownDimensions)); for (int i=0; i<knownDimensions.length; i++) { ! Expression dim = knownDimensions[i]; try{ Typing.leq(dim.getType(), PrimitiveType.intPolytype); *************** *** 651,655 **** typecheck(e@TupleExp) { ! typecheckExps(notNull(e.expressions)); } --- 651,655 ---- typecheck(e@TupleExp) { ! typecheckExps(cast(notNull(e.expressions))); } *************** *** 898,902 **** { typecheck(t.body); ! t.catches.foreach(TryStmt.Catch c => typecheck(c.body)); typecheck(t.finallyBody); } --- 898,902 ---- { typecheck(t.body); ! t.catches.foreach(ACatch c => typecheck(c.body)); typecheck(t.finallyBody); } --- NEW FILE: statementexp.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.*; /** A statement made by the evaluation of an expression. */ public class StatementExp extends Expression { Statement statement; toString() = statement.toString(); compile() { if (statement == null) return notNull(gnu.expr.QuoteExp.voidExp); return new gnu.expr.BeginExp(statement.generateCode(), gnu.expr.QuoteExp.voidExp); } computeType() { type = PrimitiveType.voidPolytype; } } --- NEW FILE: if.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.*; /** Conditional expression (used in statements too). */ public class IfExp extends Expression { Expression condition; Expression thenExp; Expression elseExp; /** set to true if the execution of the branch never completes. */ boolean thenUnreachable = false; boolean elseUnreachable = false; computeType() { this.type = mlsub.typing.Polytype.union(thenExp.getType(), elseExp.getType()); } compile() { gnu.expr.Expression thenCode, elseCode; thenCode = thenExp.generateCode(); elseCode = elseExp.generateCode(); if (elseCode.getType() == nice.tools.code.SpecialTypes.voidType) thenCode = voidify(thenCode); else if (thenCode.getType() == nice.tools.code.SpecialTypes.voidType) elseCode = voidify(elseCode); return new gnu.expr.SimpleIfExp(condition.generateCode(), thenCode, elseCode); } toString() { return "if(" + String.valueOf(condition) + ")\n" + String.valueOf(thenExp) + "\nelse\n" + String.valueOf(elseExp) + "\n" ; } } private gnu.expr.Expression voidify(gnu.expr.Expression e) { if (e.getType().isVoid()) return e; return new gnu.expr.BeginExp(e, gnu.expr.QuoteExp.voidExp); } public Statement createIfStmt(Expression cond, Statement thenStmt, ?Statement elseStmt, Location loc) { let ifExp = new IfExp(condition: cond, thenExp: new StatementExp(statement: thenStmt), elseExp: (elseStmt == null ? new VoidConstantExp() : new StatementExp(statement: elseStmt))); ifExp.setLocation(loc); return new ExpressionStmt(ifExp); } --- NEW FILE: literalarray.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.*; /** Creates an array containing the given elements. The array type is infered as the minimal possible type. */ public class LiteralArrayExp extends Expression { Expression[] elements; private boolean wrapAsCollection = false; computeType() { let elementType = mlsub.typing.Polytype.union(Expression.getType(elements)); type = this.array(elementType); // If the type cannot be simplified, it must be because elements // have incomparable types. In this case, we give the array the type // Object[]. if (! notNull(type).trySimplify()) type = this.array(PrimitiveType.objectPolytype()); } private mlsub.typing.Polytype array(mlsub.typing.Polytype elementType) { let res = new mlsub.typing.Polytype (elementType.getConstraint(), bossa.syntax.Monotype.sure(new mlsub.typing.MonotypeConstructor (PrimitiveType.arrayTC, [elementType.getMonotype()]))); res.setNotSimplified(); return res; } /** Adjust the array type according to the context. This is usefull because arrays are non-variant. For instance, different code must be generated for [ 1, 2 ] in the contexts: List<int[]> i = [[ 1, 2 ]] and List<List<byte[]>> b = [[ 1, 2 ]] */ resolveOverloading(mlsub.typing.Polytype expectedType) { let elementType = nice.tools.typing.Types.getTypeParameter(expectedType, 0); if (elementType != null) for (elem : elements) elem.adjustToExpectedType(elementType); return this; } adjustToExpectedType(mlsub.typing.Monotype expectedType) { let tc = nice.tools.typing.Types.equivalent(expectedType).head(); // Remember that we will need to wrap the array to make it a collection. // This cannot be found easily during code generation for nested arrays // since the bytecode type of both List<List<T>> and List<T[]> is // simply List. if (tc != PrimitiveType.arrayTC && tc != null && tc.isRigid() && mlsub.typing.Typing.testRigidLeq(tc, PrimitiveType.collectionTC)) { wrapAsCollection = true; } // Adjust nested elements. let elementType = nice.tools.typing.Types.getTypeParameter(expectedType, 0); if (elementType != null) for (elem : elements) elem.adjustToExpectedType(elementType); } compile() { gnu.expr.Expression[] args = Expression.compile(elements); gnu.bytecode.ArrayType t = nice.tools.code.SpecialTypes.array (nice.tools.code.Types.lowestUpperBound(args)); return new gnu.expr.ApplyExp (new nice.tools.code.LiteralArrayProc (t, elements.length, wrapAsCollection), args); } toString() = "[" + Util.map("", ", ", "", elements) + "]"; } public Expression createLiteralArrayExp(?List<Expression> elements) { if (elements == null) return new LiteralArrayExp(elements: new Expression[0]); return new LiteralArrayExp(elements: toArray(elements)); } Index: MethodBodyDefinition.java =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/MethodBodyDefinition.java,v retrieving revision 1.149 retrieving revision 1.150 diff -C2 -d -r1.149 -r1.150 *** MethodBodyDefinition.java 28 Feb 2004 14:23:43 -0000 1.149 --- MethodBodyDefinition.java 28 Jul 2004 14:40:33 -0000 1.150 *************** *** 243,247 **** } ! OverloadedSymbolExp.removeNonMinimal(symbols); if(symbols.size() == 1) --- 243,247 ---- } ! bossa.syntax.dispatch.removeNonMinimal(symbols); if(symbols.size() == 1) --- NEW FILE: try.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.*; /** A try/catch/finally statement */ public class TryStmt extends Statement { final Statement body; ?Statement finallyBody = null; List<ACatch> catches = new LinkedList(); public void setFinally(Statement body) { finallyBody = body; } public void addCatch(TypeIdent tc, LocatedString varName, Statement body) { this.catches.add(new ACatch(tc, varName, body)); } generateCode() { let res = new gnu.expr.TryExp(body.generateCode(), (finallyBody==null ? null : notNull(finallyBody).generateCode())); ?gnu.expr.CatchClause oldc = null; for (c: this.catches) { gnu.expr.CatchClause newc = c.clause(); if (oldc!=null) oldc.setNext(newc); else res.setCatchClauses(newc); oldc = newc; } return res; } toString() { String res = "try\n" + body; for (c : this.catches) res += "catch (" + c.t + " " + c.varName + ")\n" + c.body; if (finallyBody != null) res += "finally " + finallyBody; return res; } } public class ACatch { final MonoSymbol exnVar; ?TypeIdent tc; ?mlsub.typing.TypeConstructor t = null; private final LocatedString varName; final Statement body; private final Location typeLocation; gnu.expr.CatchClause clause() { try { mlsub.typing.Typing.leq(t, PrimitiveType.throwableTC); } catch (mlsub.typing.TypingEx e) { User.error(typeLocation, notNull(t) + " is not catchable"); } let res = new gnu.expr.CatchClause(varName.toString(), cast(nice.tools.code.Types.javaType(t))); exnVar.setDeclaration(res.getDeclaration()); res.setBody(body.generateCode()); return res; } } public new ACatch(TypeIdent tc, LocatedString varName, Statement body) { Monotype type = new MonotypeConstructor(tc, null, tc.location()); type.nullness = Monotype.sure; this(exnVar: new MonoSymbol(varName, type), tc: tc, typeLocation: tc.location, varName: varName, body: body); } Index: CallExp.java =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/CallExp.java,v retrieving revision 1.94 retrieving revision 1.95 diff -C2 -d -r1.94 -r1.95 *** CallExp.java 23 Jun 2004 19:38:09 -0000 1.94 --- CallExp.java 28 Jul 2004 14:40:33 -0000 1.95 *************** *** 96,100 **** public void addBlockArgument(Statement block, LocatedString name) { ! arguments.add(new FunExp(bossa.syntax.Constraint.True, new LinkedList(), block), name); } --- 96,100 ---- public void addBlockArgument(Statement block, LocatedString name) { ! arguments.add(bossa.syntax.dispatch.createFunExp(bossa.syntax.Constraint.True, new LinkedList(), block), name); } Index: analyse.nice =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/analyse.nice,v retrieving revision 1.103 retrieving revision 1.104 diff -C2 -d -r1.103 -r1.104 *** analyse.nice 22 Jul 2004 12:42:54 -0000 1.103 --- analyse.nice 28 Jul 2004 14:40:33 -0000 1.104 *************** *** 259,263 **** analyseAssigned(e@TupleExp, info) { ! Array<?Expression> es = notNull(e.expressions); for (int i = 0; i < es.length; i++) es[i] = es[i].analyseAssigned(info); --- 259,263 ---- analyseAssigned(e@TupleExp, info) { ! Expression[] es = notNull(e.expressions); for (int i = 0; i < es.length; i++) es[i] = es[i].analyseAssigned(info); *************** *** 393,401 **** if (possibilities.has(VarSymbol s => s.isFieldAccess())) { ! e.function = newOverloadedSymbolExp(possibilities, funName); return e; } else ! return newOverloadedSymbolExp(possibilities, funName); } --- 393,401 ---- if (possibilities.has(VarSymbol s => s.isFieldAccess())) { ! e.function = createOverloadedSymbolExp(possibilities, funName); return e; } else ! return createOverloadedSymbolExp(possibilities, funName); } *************** *** 410,414 **** funName); ! e.function = newOverloadedSymbolExp(possibilities, funName); return e; --- 410,414 ---- funName); ! e.function = createOverloadedSymbolExp(possibilities, funName); return e; *************** *** 440,444 **** if (e.formals != null) ! addVars(info, elementsNotNull(notNull(e.formals))); analyse(e.body, info); --- 440,444 ---- if (e.formals != null) ! addVars(info, e.formals); analyse(e.body, info); *************** *** 481,485 **** if (e.alwaysOverloadedSymbol) ! return new OverloadedSymbolExp(sym, e.ident); else return new SymbolExp(sym, e.location()); --- 481,485 ---- if (e.alwaysOverloadedSymbol) ! return createOverloadedSymbolExp(sym, notNull(e.ident)); else return new SymbolExp(sym, e.location()); *************** *** 513,517 **** { CallExp res = new CallExp ! (newOverloadedSymbolExp(symbols, e.ident), new Arguments([new Arguments.Argument(Node.thisExp)])); res.setLocation(e.location()); --- 513,517 ---- { CallExp res = new CallExp ! (createOverloadedSymbolExp(symbols, notNull(e.ident)), new Arguments([new Arguments.Argument(Node.thisExp)])); res.setLocation(e.location()); *************** *** 523,527 **** // Make an implicit call to fetch the static field's value. CallExp res = new CallExp ! (newOverloadedSymbolExp(symbols, e.ident), Arguments.noArguments()); res.setLocation(e.location()); --- 523,527 ---- // Make an implicit call to fetch the static field's value. CallExp res = new CallExp ! (createOverloadedSymbolExp(symbols, notNull(e.ident)), Arguments.noArguments()); res.setLocation(e.location()); *************** *** 532,536 **** } else ! return newOverloadedSymbolExp(symbols, e.ident); } --- 532,536 ---- } else ! return createOverloadedSymbolExp(symbols, notNull(e.ident)); } *************** *** 566,570 **** analyse(e@LiteralArrayExp, info) { ! analyseExps(notNull(e.elements), info); return e; } --- 566,570 ---- analyse(e@LiteralArrayExp, info) { ! analyseExps(cast(e.elements), info); return e; } *************** *** 573,577 **** { e.resolveTC(info.typeMap); ! analyseExps(notNull(e.knownDimensions), info); return e; } --- 573,577 ---- { e.resolveTC(info.typeMap); ! analyseExps(cast(notNull(e.knownDimensions)), info); return e; } *************** *** 636,640 **** analyse(e@TupleExp, info) { ! analyseExps(notNull(e.expressions), info); return e; } --- 636,640 ---- analyse(e@TupleExp, info) { ! analyseExps(cast(notNull(e.expressions)), info); return e; } *************** *** 845,849 **** analyse(t.body, info); ! t.catches.foreach(TryStmt.Catch c =>{ info.otherCase(); info.begin(); --- 845,849 ---- analyse(t.body, info); ! t.catches.foreach(ACatch c =>{ info.otherCase(); info.begin(); Index: dispatch.java.bootstrap =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/dispatch.java.bootstrap,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** dispatch.java.bootstrap 18 Feb 2004 11:50:54 -0000 1.12 --- dispatch.java.bootstrap 28 Jul 2004 14:40:33 -0000 1.13 *************** *** 2,5 **** --- 2,6 ---- package bossa.syntax; + import java.util.List; /* This file is only useful to bootstrap the compiler, *************** *** 12,15 **** --- 13,34 ---- public class dispatch { + public static Statement createReturnStmt(Expression value, boolean fake) + { return null; } + + public static Expression createFunExp(bossa.syntax.Constraint cst, List formals, Statement body) + { return null; } + + static Expression createFunExp(bossa.syntax.Constraint cst, MonoSymbol[] formals, Statement body) + { return null; } + + public static Expression createLiteralArrayExp(List exps) + { return null; } + + static Expression createOverloadedSymbolExp(List l, LocatedString s) + { return null; } + + static List removeNonMinimal(List l) + { return null; } + static Statement analyse(Statement s, VarScope v, TypeScope t, boolean r) { return null; } --- NEW FILE: break.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; public class BreakStmt extends Statement { generateCode() = new gnu.expr.ExitExp(currentLoopBlock); toString() = "break;"; } public class BreakLabelStmt extends Statement { final LocatedString label; ?LabeledStmt statement = null; generateCode() = new gnu.expr.ExitExp(notNull(statement).block); toString() = "break " + label + ";"; } public class ContinueStmt extends Statement { final ?LocatedString label; ?LoopStmt loop = null; generateCode() = new gnu.expr.LoopExp.ContinueExp(notNull(loop).code); toString() = "continue " + (label != null ? notNull(label).toString() : "") + ";"; } public Statement createBreakStmt(?LocatedString label) { if (label == null) return new BreakStmt(); else return new BreakLabelStmt(label: label); } public Statement createContinueStmt(LocatedString label) { return new ContinueStmt(label: label); } /** A statement anotated by a label (used by break and continue). */ public class LabeledStmt extends Statement { private final LocatedString label; private final Statement statement; private final ?LoopStmt loop = null; public String name() = label.toString(); public LocatedString getLabel() = label; public Statement getStatement() = statement; /** @return the loop targeted by this label, or null. */ ?LoopStmt getLoop() { if (loop != null) return loop; if (statement instanceof LoopStmt) return cast(statement); return null; } /**************************************************************** * Code generation ****************************************************************/ ?gnu.expr.BlockExp block = null; generateCode() { // if (statement == null) // return notNull(gnu.expr.QuoteExp.voidExp); let res = block = new gnu.expr.BlockExp(); notNull(block).setBody(statement.generateCode()); block = null; return res; } } public new LabeledStmt(LocatedString label, Statement statement, LoopStmt loop) { this(label:label, statement:statement, loop: loop, block: null); } Index: Block.java =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/Block.java,v retrieving revision 1.66 retrieving revision 1.67 diff -C2 -d -r1.66 -r1.67 *** Block.java 25 Feb 2004 11:23:29 -0000 1.66 --- Block.java 28 Jul 2004 14:40:33 -0000 1.67 *************** *** 252,256 **** { Expression value; ! value = new FunExp(Constraint.True, parameters.getMonoSymbols(), body); FunSymbol symbol = new FunSymbol(name, --- 252,256 ---- { Expression value; ! value = bossa.syntax.dispatch.createFunExp(Constraint.True, parameters.getMonoSymbols(), body); FunSymbol symbol = new FunSymbol(name, *************** *** 276,280 **** mlsub.typing.Polytype inferredReturnType() { ! return ((FunExp) value).inferredReturnType(); } --- 276,280 ---- mlsub.typing.Polytype inferredReturnType() { ! return value.inferredReturnType(); } Index: rewrite.nice =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/rewrite.nice,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** rewrite.nice 25 Sep 2002 16:40:25 -0000 1.3 --- rewrite.nice 28 Jul 2004 14:40:33 -0000 1.4 *************** *** 50,54 **** { ifExp.elseExp = new StatementExp ! (rewrite(makeBlock(notNull(ifExp.elseExp), statements.slice(from: i+1)))); return statements.slice(to: i); --- 50,54 ---- { ifExp.elseExp = new StatementExp ! (statement: rewrite(makeBlock(notNull(ifExp.elseExp), statements.slice(from: i+1)))); return statements.slice(to: i); *************** *** 57,61 **** { ifExp.thenExp = new StatementExp ! (rewrite(makeBlock(notNull(ifExp.thenExp), statements.slice(from: i+1)))); return statements.slice(to: i); --- 57,61 ---- { ifExp.thenExp = new StatementExp ! (statement: rewrite(makeBlock(notNull(ifExp.thenExp), statements.slice(from: i+1)))); return statements.slice(to: i); --- NEW FILE: overloadedsymbol.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.*; /** A symbol, for which overloading resolution has yet to be done. */ public class OverloadedSymbolExp extends Expression { List<VarSymbol> symbols; final LocatedString ident; /** Do not try to add an implicit 'this' access. */ private final boolean noImplicitThis = false; isAssignable() { Internal.error("Overloading resolution should be done before this."); return false; } private Expression uniqueExpression() { return new SymbolExp(symbols.get(0), this.location()); } private Expression uniqueExpression(VarSymbol sym, mlsub.typing.Polytype t) { SymbolExp res = new SymbolExp(sym, this.location()); res.type = t; return res; } resolveOverloading(CallExp callExp) { Arguments arguments = callExp.arguments; // It's better to do this know. OR is oriented, arguments first. arguments.computeTypes(); if (bossa.util.Debug.overloading) bossa.util.Debug.println("Overloading resolution for " + this + "\nwith parameters " + arguments); // FIRST PASS: only checks the number of parameters // remembers removed symbols, // to list possibilities if none matches LinkedList<VarSymbol> removed = new LinkedList(); // Useful in case of failure, to try adding an implicit 'this'. let fieldAccesses = this.filterFieldAccesses(); for(let i = symbols.iterator(); i.hasNext();) { let s = i.next(); if (s.isIgnored()) { removed.add(s); i.remove(); continue; } let case = s.match(arguments); if (case == 0) // Doesn't match { removed.add(s); i.remove(); } else if (case == 1) // Wasn't even a function or method { i.remove(); } else if (case == 2) // Matches { /* do nothing*/ } else // Should not happen { Internal.warning("Unknown O.R. case: " + s.getClass()); i.remove(); } } if (symbols.size() == 0) { if (! noImplicitThis) { let res = this.givePriorityToFields(fieldAccesses); if (res != null) return res; } User.error(this, this.noMatchError(removed, arguments)); } // SECOND PASS: check argument types removed.clear(); for (let i = symbols.iterator(); i.hasNext(); ) { let s = i.next(); if(bossa.util.Debug.overloading) bossa.util.Debug.println("Overloading: Trying with "+s); // we clone the type to avoid clashes with another use // of the same symbol // the cloned type is stored in the VarSymbol // and we check that cloneType() is not called twice // before the clone type is released s.makeClonedType(); mlsub.typing.Polytype[] argsType = this.computeArgsType(arguments.getExpressions(s), s.getClonedType(), arguments.getUsedArguments(s)); ?mlsub.typing.Polytype t = CallExp.wellTyped(s.getClonedType(), argsType); if (t == null) { removed.add(s); i.remove(); s.releaseClonedType(); } else arguments.types.put(s, t); } if (symbols.size() == 0) { if (! noImplicitThis) { let res = this.givePriorityToFields(fieldAccesses); if (res != null) return res; } if (removed.size() == 1) User.error(this, "Arguments " + arguments.printTypes() + " do not fit:\n" + removed[0]); else User.error(this, "No possible call for " + ident + ".\nArguments: " + arguments.printTypes() + "\nPossibilities:\n" + Util.map("", "\n", "", removed.toArray())); } removeNonMinimal(symbols, arguments); removeOverlappingJavaMethods(symbols); if (symbols.size() == 1) { let res = symbols[0]; // store the formal argument types for later use together with the type callExp.setComputedType(arguments.types.get(res), nice.tools.typing.Types.parameters(res.getClonedType())); res.releaseClonedType(); // store the expression (including default arguments) callExp.arguments.computedExpressions = cast(arguments.getExpressions(res)); //callExp.arguments = null; // free memory return this.uniqueExpression(); } this.releaseAllClonedTypes(); throw new AmbiguityError(this); } private mlsub.typing.Polytype[] computeArgsType(Expression[] args, mlsub.typing.Polytype functionType, int[?] usedArguments) { mlsub.typing.Monotype[?] domain = null; /* Where a default value was used, use the declared argument type instead of the value's type. This is more robust, as the application type will not depend on the default value. Furthermore, this avoids running into problems when the default value refers to type parameters (in anonymous functions, by refering to previous arguments, ...) which would not be in sync with the cloned ones. This is only needed when the type is polymorphic. */ mlsub.typing.Polytype[] res = fill(new mlsub.typing.Polytype[args.length], int i => { if (usedArguments != null && usedArguments[i] == 0) { if (domain == null) { mlsub.typing.FunType func = cast(nice.tools.typing.Types.rawType(functionType.getMonotype())); domain = func.domain(); } return new mlsub.typing.Polytype(notNull(domain)[i]); } return args[i].getType(); }); return res; } resolveOverloading(mlsub.typing.Polytype expectedType) { if(bossa.util.Debug.overloading) bossa.util.Debug.println("Overloading resolution (expected type " + expectedType + ") for " + this); // remembers removed symbols, // to list possibilities if none matches LinkedList<VarSymbol> removed = new LinkedList(); // Useful in case of failure. let fieldAccesses = this.filterFieldAccesses(); for (let i = symbols.iterator(); i.hasNext();) { let s = i.next(); s.makeClonedType(); try{ Typing.leq(s.getClonedType(), expectedType); if(bossa.util.Debug.overloading) bossa.util.Debug.println(s + "(" + s.location() + ") of type " + s.getClonedType() + " matches"); } catch(TypingEx e){ removed.add(s); i.remove(); s.releaseClonedType(); if(bossa.util.Debug.overloading) bossa.util.Debug.println("Not "+s+" of type\n" + s.getClonedType() + "\nbecause "+e); } } if (symbols.size() == 1) { let s = symbols[0]; let symType = s.getClonedType(); s.releaseClonedType(); return this.uniqueExpression(s, symType); } try { let res = this.givePriorityToFields(fieldAccesses); if (res != null) return res; if (nice.tools.typing.Types.parameters(expectedType) != null) { // in case of function objects symbols find the most precise match let nonMin = removeNonMinimal(symbols); if (symbols.size() == 1) { let s = symbols[0]; let symType = s.getClonedType(); s.releaseClonedType(); symbols = nonMin; return this.uniqueExpression(s, symType); } else symbols.addAll(nonMin); } if (symbols.size() != 0) throw new AmbiguityError(this); throw User.error(this, this.noMatchError(removed, expectedType)); } finally { this.releaseAllClonedTypes(); } } private void releaseAllClonedTypes() { for (s : symbols) s.releaseClonedType(); } noOverloading() { if(bossa.util.Debug.overloading) bossa.util.Debug.println("(no)Overloading resolution for "+this); if(symbols.size()==1) return this.uniqueExpression(); let res = this.givePriorityToFields(this.filterFieldAccesses()); if (res != null) return res; List<VarSymbol> globalvars = symbols.filter(VarSymbol sym => sym instanceof GlobalVarDeclaration.GlobalVarSymbol); // If there are global variables, give them the priority // (but not when there are *only* global variables, or it would loop). if (globalvars.size() > 0 && globalvars.size() < symbols.size()) return createOverloadedSymbolExp(globalvars, ident).noOverloading(); if (symbols.size() != 0) throw new AmbiguityError(this); throw User.error(this, "No variable or field in this class has name " + ident); } /** @return null if there is no solution. */ private ?Expression givePriorityToFields (List<VarSymbol> fieldAccesses) { if (fieldAccesses.size() != 0) { if (Node.thisExp != null) try { let res = new CallExp (createOverloadedSymbolExp(fieldAccesses, ident, true), //Arguments.noArguments()); new Arguments([new Arguments.Argument(Node.thisExp)])); res.setLocation(ident.location()); res.resolveOverloading(); return res; } catch (UserError e) {} symbols.removeAll(this.filterFieldAccesses()); if (symbols.size() == 1) return this.uniqueExpression(); } // There is no solution. return null; } private List<VarSymbol> filterFieldAccesses() { return symbols.filter(VarSymbol sym => sym.isFieldAccess()); } computeType() { Internal.error(this,ident+" has not been resolved yet.\n"+ "Possibilities are :"+this); } compile() { Internal.error("compile in "+this.getClass()+" "+this); return cast(null); } toString() { if (symbols.size() <= 1) return "[" + Util.map("", "\n|", "", symbols.toArray()) + "]"; return "\n[" + Util.map("", "\n|", "", symbols.toArray()) + "]"; } /**************************************************************** * Error messages ****************************************************************/ /** No method in removed matched these arguments. */ private String noMatchError(List<VarSymbol> removed, Arguments arguments) { if (removed.size() == 0) return "No method has name " + ident; if (removed.size() == 1) { let sym = removed[0]; if (sym.isIgnored()) return sym.getName() + " cannot be used because it has been ignored.\n" + "See above for the reason why it has been ignored"; return sym.explainWhyMatchFails(arguments); } return "No method with name " + ident + arguments.explainNoMatch(removed); } /** No symbol in removed had the expected type. */ private String noMatchError(List<VarSymbol> removed, mlsub.typing.Polytype expectedType) { if (removed.size() == 0) return "No method has name " + ident; if (removed.size() == 1) return ident + " has type " + removed[0].getType(); return "No symbol with name " + ident + " has type " + expectedType + ":\n" + Util.map("", "\n", "", removed.toArray()); } } /** @param symbols All the possible VarSymbols @param ident the original identifier */ Expression createOverloadedSymbolExp(List<VarSymbol> symbols, LocatedString ident) { if(symbols == null) Internal.error("No symbols"); let res = new OverloadedSymbolExp(symbols: symbols, ident: ident); res.setLocation(ident.location()); return res; } private Expression createOverloadedSymbolExp(List<VarSymbol> symbols, LocatedString ident, boolean noImplicitThis) { if(symbols == null) Internal.error("No symbols"); let res = new OverloadedSymbolExp(symbols: symbols, ident: ident, noImplicitThis: noImplicitThis); res.setLocation(ident.location()); return res; } Expression createOverloadedSymbolExp(VarSymbol symbol, LocatedString ident) { let List<VarSymbol> list = new LinkedList(); list.add(symbol); return createOverloadedSymbolExp(list, ident); } class AmbiguityError extends UserError {} new AmbiguityError(OverloadedSymbolExp sym) { this(sym, "Ambiguity for symbol " + sym.ident + ". Possibilities are :\n" + Util.map("", "\n", "", toArray(sym.symbols))); } List<VarSymbol> removeNonMinimal(List<VarSymbol> symbols) { List<VarSymbol> removed = new ArrayList(); // optimization if(symbols.size()<2) return removed; int len = symbols.size(); VarSymbol[] syms = new VarSymbol[len].fillWith(symbols); boolean[] remove = new boolean[len]; for(int s1 = 0; s1<len; s1++) { Domain d1 = nice.tools.typing.Types.domain(syms[s1].getType()); for(int s2 = 0; s2<len; s2++) /* Look for symbols s1 and s2 such that d2 <: d1 and not d1 <: d2 In that case s1 can be removed, since it is less specific than s2. Optimizations: Skip the diagonal. If s2 was removed, then there is s3 below s2. Therefore s1 will be removed anyway. */ if (s1 != s2 && !remove[s2]) { Domain d2 = nice.tools.typing.Types.domain(syms[s2].getType()); try { Typing.leq(d2, d1); try { Typing.leq(d1, d2); } catch (TypingEx e) { remove[s1] = true; break; } } catch(TypingEx e){ } } } for(int i = 0; i<len; i++) if(remove[i]) { if (bossa.util.Debug.overloading) bossa.util.Debug.println("Removing " + syms[i] + " since it is not minimal"); removed.add(syms[i]); symbols.remove(syms[i]); } return removed; } /** * Removes the symbols that do not have minimal domain types. * * For instance, if the set of symbols is {s1, s2} * with s1:A->C and s2:B->D with B<:A, * removoNonMinimal will remove s1. * * This allows for java-style overloading, * where the most precise method is choosen at compile-time. */ private void removeNonMinimal(List<VarSymbol> symbols, Arguments arguments) { // optimization if(symbols.size()<2) return; int len = symbols.size(); VarSymbol[] syms = new VarSymbol[len].fillWith(symbols); boolean[] remove = new boolean[len]; for(int s1 = 0; s1<len; s1++) { Domain d1 = domain(syms[s1].getClonedType(), arguments.getUsedArguments(syms[s1])); for(int s2 = 0; s2<len; s2++) /* Look for symbols s1 and s2 such that d2 <: d1 and not d1 <: d2 In that case s1 can be removed, since it is less specific than s2. Optimizations: Skip the diagonal. If s2 was removed, then there is s3 below s2. Therefore s1 will be removed anyway. */ if (s1 != s2 && !remove[s2]) { Domain d2 = domain(syms[s2].getClonedType(), arguments.getUsedArguments(syms[s2])); try { Typing.leq(d2, d1); try { Typing.leq(d1, d2); } catch (TypingEx e) { remove[s1] = true; break; } } catch(TypingEx e){ } } } for(int i = 0; i<len; i++) if(remove[i]) { if (bossa.util.Debug.overloading) bossa.util.Debug.println("Removing " + syms[i] + " since it is not minimal"); syms[i].releaseClonedType(); symbols.remove(syms[i]); } } private Domain domain(mlsub.typing.Polytype t, int[] usedArguments) { // remove nullness marker mlsub.typing.Monotype[] m = nice.tools.typing.Types.parameters(t.getMonotype()); ?mlsub.typing.Monotype[] dom; if (usedArguments == null) dom = cast(m);... [truncated message content] |