All Downloads are FREE. Search and download functionalities are using the official Maven repository.

wyil.check.SignatureCheck Maven / Gradle / Ivy

// Copyright 2011 The Whiley Project Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package wyil.check;

import wyil.lang.Compiler;
import wyil.lang.WyilFile;
import wyil.lang.WyilFile.*;
import wyil.util.AbstractConsumer;
import wyil.util.TypeMangler;
import wyc.util.ErrorMessages;

import java.util.HashSet;

import wycc.lang.Syntactic;

/**
 * 

* Responsible for checking no duplicate declarations exist. That is, * declarations with the same signature. For example, the following is * prohibited: * *

 * function f(int x) -> (int r):
 *    return x+1
 *
 * function f(int x) -> (int r):
 *    return x-1
 * 
* * There are a few special cases. For example, `export` declarations have no * mangle information associated with them at all. *

* * * @author David J. Pearce * */ public class SignatureCheck extends AbstractConsumer implements Compiler.Check { private static final TypeMangler mangler = new TypeMangler.Default(); private boolean status = true; @Override public boolean check(WyilFile file) { visitModule(file, new Context()); return status; } @Override public void visitExternalUnit(Decl.Unit unit, Context data) { // NOTE: we override this to prevent unnecessarily traversing units } @Override public void visitType(Decl.Type decl, Context data) { if(!data.register(decl)) { syntaxError(decl.getName(),WyilFile.DUPLICATE_DECLARATION); } } @Override public void visitProperty(Decl.Property decl, Context data) { if(!data.register(decl)) { syntaxError(decl.getName(),WyilFile.DUPLICATE_DECLARATION); } } @Override public void visitFunction(Decl.Function decl, Context data) { if(!data.register(decl)) { syntaxError(decl.getName(),WyilFile.DUPLICATE_DECLARATION); } } @Override public void visitMethod(Decl.Method decl, Context data) { if(!data.register(decl)) { syntaxError(decl.getName(),WyilFile.DUPLICATE_DECLARATION); } } @Override public void visitStaticVariable(Decl.StaticVariable decl, Context data) { if(!data.register(decl)) { syntaxError(decl.getName(),WyilFile.DUPLICATE_DECLARATION); } } /** * A simple store of name mangles used to identify any clashes. * * @author David J. Pearce * */ public static final class Context { private HashSet mangles = new HashSet<>(); /** * Register a new named declaration, and check whether or not it clashes with a * previously registered declaration. * * @param d * @return true if this name was successfully registered without a clash. */ public boolean register(Decl.Named d) { String mangle = toMangledName(d); return mangles.add(mangle); } /** * Determine the appropriate mangled string for a given named declaration. This * is critical to ensuring that overloaded declarations do not clash. * * @param decl * @return */ private String toMangledName(Decl.Named decl) { // Determine whether this is an exported symbol or not boolean exported = decl.getModifiers().match(Modifier.Export.class) != null; // Construct base name String name = decl.getQualifiedName().toString().replace("::", "$"); // Add type mangles for non-exported symbols if(!exported && decl instanceof Decl.Method) { Decl.Method method = (Decl.Method) decl; Type ret = method.getType().getReturn(); Type parameter = method.getType().getParameter(); name += getMangle(parameter); name += getMangle(ret); } else if(!exported && decl instanceof Decl.Callable) { Decl.Callable callable = (Decl.Callable) decl; Type ret = callable.getType().getReturn(); Type parameter = callable.getType().getParameter(); name += getMangle(parameter); name += getMangle(ret); } else if(decl instanceof Decl.Type) { name += "$type"; } else if(decl instanceof Decl.StaticVariable) { name += "$static"; } return name; } private String getMangle(Type type) { if (type.shape() == 0) { return ""; } else { return "$" + mangler.getMangle(type); } } } private void syntaxError(Syntactic.Item e, int code, Syntactic.Item... context) { status = false; ErrorMessages.syntaxError(e, code, context); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy