/* * #%~ * The VDM Type Checker * %% * Copyright (C) 2008 - 2014 Overture * %% * 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 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #~% */ package org.overture.typechecker.assistant.definition; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Vector; import org.overture.ast.assistant.IAstAssistant; import org.overture.ast.definitions.AExplicitFunctionDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.factory.AstFactory; import org.overture.ast.intf.lex.ILexNameToken; import org.overture.ast.lex.LexNameToken; import org.overture.ast.node.NodeList; import org.overture.ast.patterns.PPattern; import org.overture.ast.typechecker.NameScope; import org.overture.ast.types.AFunctionType; import org.overture.ast.types.PType; import org.overture.typechecker.TypeChecker; import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory; public class AExplicitFunctionDefinitionAssistantTC implements IAstAssistant { protected ITypeCheckerAssistantFactory af; public AExplicitFunctionDefinitionAssistantTC( ITypeCheckerAssistantFactory af) { this.af = af; } public List<PType> getMeasureParams(AExplicitFunctionDefinition node) { AFunctionType functionType = (AFunctionType) node.getType(); List<PType> params = new LinkedList<PType>(); params.addAll(functionType.getParameters()); if (node.getIsCurried()) { PType rtype = functionType.getResult(); while (rtype instanceof AFunctionType) { AFunctionType ftype = (AFunctionType) rtype; params.addAll(ftype.getParameters()); rtype = ftype.getResult(); } } return params; } public PType checkParams(AExplicitFunctionDefinition node, ListIterator<List<PPattern>> plists, AFunctionType ftype) { List<PType> ptypes = ftype.getParameters(); List<PPattern> patterns = plists.next(); if (patterns.size() > ptypes.size()) { TypeChecker.report(3020, "Too many parameter patterns", node.getLocation()); TypeChecker.detail2("Pattern(s)", patterns, "Type(s)", ptypes); return ftype.getResult(); } else if (patterns.size() < ptypes.size()) { TypeChecker.report(3021, "Too few parameter patterns", node.getLocation()); TypeChecker.detail2("Pattern(s)", patterns, "Type(s)", ptypes); return ftype.getResult(); } if (ftype.getResult() instanceof AFunctionType) { if (!plists.hasNext()) { // We're returning the function itself return ftype.getResult(); } // We're returning what the function returns, assuming we // pass the right parameters. Note that this recursion // means that we finally return the result of calling the // function with *all* of the curried argument sets applied. // This is because the type check of the body determines // the return type when all of the curried parameters are // provided. return checkParams(node, plists, (AFunctionType) ftype.getResult()); } if (plists.hasNext()) { TypeChecker.report(3022, "Too many curried parameters", node.getLocation()); } return ftype.getResult(); } public List<PDefinition> getTypeParamDefinitions( AExplicitFunctionDefinition node) { List<PDefinition> defs = new ArrayList<PDefinition>(); for (ILexNameToken pname : node.getTypeParams()) { PDefinition p = AstFactory.newALocalDefinition(pname.getLocation(), pname.clone(), NameScope.NAMES, AstFactory.newAParameterType(pname.clone())); // pname.location, NameScope.NAMES,false,null, null, new // AParameterType(null,false,null,pname.clone()),false,pname.clone()); af.createPDefinitionAssistant().markUsed(p); defs.add(p); } return defs; } public AFunctionType getType(AExplicitFunctionDefinition efd, List<PType> actualTypes) { Iterator<PType> ti = actualTypes.iterator(); AFunctionType ftype = (AFunctionType) efd.getType(); if (efd.getTypeParams() != null) { for (ILexNameToken pname : efd.getTypeParams()) { PType ptype = ti.next(); ftype = (AFunctionType) af.createPTypeAssistant().polymorph(ftype, pname, ptype); } ftype.setInstantiated(true); } return ftype; } public AExplicitFunctionDefinition getPostDefinition( AExplicitFunctionDefinition d) { List<PPattern> last = new Vector<PPattern>(); int psize = d.getParamPatternList().size(); for (PPattern p : d.getParamPatternList().get(psize - 1)) { last.add(p.clone()); } LexNameToken result = new LexNameToken(d.getName().getModule(), "RESULT", d.getLocation()); last.add(AstFactory.newAIdentifierPattern(result)); List<List<PPattern>> parameters = new Vector<List<PPattern>>(); if (psize > 1) { for (List<PPattern> pPatternList : d.getParamPatternList().subList(0, psize - 1)) { NodeList<PPattern> tmpList = new NodeList<PPattern>(null); for (PPattern pPattern2 : pPatternList) { tmpList.add(pPattern2.clone()); } parameters.add(tmpList); } // parameters.addAll(d.getParamPatternList().subList(0, psize - 1)); } parameters.add(last); @SuppressWarnings("unchecked") AExplicitFunctionDefinition def = AstFactory.newAExplicitFunctionDefinition(d.getName().getPostName(d.getPostcondition().getLocation()), NameScope.GLOBAL, (List<ILexNameToken>) d.getTypeParams().clone(), af.createAFunctionTypeAssistant().getCurriedPostType((AFunctionType) d.getType(), d.getIsCurried()), parameters, d.getPostcondition(), null, null, false, null); def.setAccess(d.getAccess().clone()); def.setClassDefinition(d.getClassDefinition()); return def; } public AExplicitFunctionDefinition getPreDefinition( AExplicitFunctionDefinition d) { @SuppressWarnings("unchecked") AExplicitFunctionDefinition def = AstFactory.newAExplicitFunctionDefinition(d.getName().getPreName(d.getPrecondition().getLocation()), NameScope.GLOBAL, (List<ILexNameToken>) d.getTypeParams().clone(), af.createAFunctionTypeAssistant().getCurriedPreType((AFunctionType) d.getType(), d.getIsCurried()), (LinkedList<List<PPattern>>) d.getParamPatternList().clone(), d.getPrecondition(), null, null, false, null); def.setAccess(d.getAccess().clone()); def.setClassDefinition(d.getClassDefinition()); return def; } }