/** * Copyright (c) 2009-2011, The HATS Consortium. All rights reserved. * This file is licensed under the terms of the Modified BSD License. */ package abs.frontend.typechecker.ext; import java.util.List; import abs.frontend.analyser.AnnotationHelper; import abs.frontend.analyser.ErrorMessage; import abs.frontend.analyser.TypeError; import abs.frontend.ast.ASTNode; import abs.frontend.ast.Annotation; import abs.frontend.ast.AwaitStmt; import abs.frontend.ast.Call; import abs.frontend.ast.GetExp; import abs.frontend.ast.MethodImpl; import abs.frontend.ast.MethodSig; import abs.frontend.ast.Model; import abs.frontend.ast.SuspendStmt; public class AtomicityChecker extends DefaultTypeSystemExtension { protected AtomicityChecker(Model m) { super(m); } @Override public void checkOverride(MethodSig impl, MethodSig overriden) { if (impl.isAtomic() != overriden.isAtomic()) { errors.add(new TypeError(impl, ErrorMessage.ATOMIC_METHOD_WRONG_OVERRIDE,impl.getName(),impl.getName(),overriden.getContextDecl().getName())); } } @Override public void checkAwaitStmt(AwaitStmt s) { ensureNonAtomic(s,s.getContextMethod(),"an await statement"); } @Override public void checkSuspendStmt(SuspendStmt s) { ensureNonAtomic(s,s.getContextMethod(),"a suspend statement"); } @Override public void checkGetExp(GetExp e) { ensureNonAtomic(e,e.getContextMethod(),"a suspend statement"); } @Override public void checkMethodCall(Call call) { if (!call.isAsync()) { MethodSig sig = call.getMethodSig(); if (!isAtomic(sig.getAnnotations())) { ensureNonAtomic(call, call.getContextMethod(), "a synchronous call of a non-atomic method"); } } } private void ensureNonAtomic(ASTNode<?> n, MethodImpl impl, String descr) { if (impl == null) return; MethodSig sig = impl.getMethodSig(); if (sig.isAtomic()) { errors.add(new TypeError(n, ErrorMessage.ATOMIC_METHOD_CONTAINS_ILLEGAL_CODE,descr,sig.getName())); } } public static boolean isAtomic(abs.frontend.ast.List<Annotation> list) { List<Annotation> anns = AnnotationHelper.getAnnotationsOfType(list, "ABS.StdLib.AtomicityAnnotation"); return !anns.isEmpty(); } }