/** * Copyright (c) 2009-2011, The HATS Consortium. All rights reserved. * This file is licensed under the terms of the Modified BSD License. */ package abs.backend.tests; import java.util.HashSet; import java.util.Set; import abs.frontend.ast.Access; import abs.frontend.ast.Annotation; import abs.frontend.ast.AssignStmt; import abs.frontend.ast.AsyncCall; import abs.frontend.ast.Block; import abs.frontend.ast.Call; import abs.frontend.ast.ClassDecl; import abs.frontend.ast.DataTypeUse; import abs.frontend.ast.Decl; import abs.frontend.ast.DeltaDecl; import abs.frontend.ast.Exp; import abs.frontend.ast.ExpressionStmt; import abs.frontend.ast.FieldDecl; import abs.frontend.ast.FnApp; import abs.frontend.ast.FromImport; import abs.frontend.ast.Import; import abs.frontend.ast.InterfaceDecl; import abs.frontend.ast.InterfaceTypeUse; import abs.frontend.ast.List; import abs.frontend.ast.Local; import abs.frontend.ast.MethodImpl; import abs.frontend.ast.MethodSig; import abs.frontend.ast.Model; import abs.frontend.ast.ModifyClassModifier; import abs.frontend.ast.ModuleDecl; import abs.frontend.ast.ModuleModifier; import abs.frontend.ast.Name; import abs.frontend.ast.NewExp; import abs.frontend.ast.Opt; import abs.frontend.ast.ParamDecl; import abs.frontend.ast.ParametricDataTypeUse; import abs.frontend.ast.PureExp; import abs.frontend.ast.SyncCall; import abs.frontend.ast.TypeUse; import abs.frontend.ast.VarDecl; import abs.frontend.ast.VarDeclStmt; import abs.frontend.ast.VarOrFieldUse; import abs.frontend.ast.VarUse; /** * * @author woner * */ public final class AbsASTBuilderUtil { public interface Predicate<T> { boolean predicate(T t); } protected abstract static class Named { protected final String name; protected Named(String name) { this.name = name; } } public static final class DeclNamePredicate<T extends Decl> extends Named implements Predicate<T> { public DeclNamePredicate(String name) { super(name); } @Override public boolean predicate(T t) { return name.equals(t.getName()); } } public static final class ModifyClassModifierNamePredicate extends Named implements Predicate<ModifyClassModifier> { public ModifyClassModifierNamePredicate(String name) { super(name); } @Override public boolean predicate(ModifyClassModifier t) { return name.equals(t.getName()); } } public static final class MethodNamePredicate extends Named implements Predicate<MethodImpl> { public MethodNamePredicate(String name) { super(name); } @Override public boolean predicate(MethodImpl t) { return name.equals(t.getMethodSig().getName()); } } public static final class MethodSigNamePredicate extends Named implements Predicate<MethodSig> { public MethodSigNamePredicate(String name) { super(name); } @Override public boolean predicate(MethodSig t) { return name.equals(t.getName()); } } public static final class FieldNamePredicate extends Named implements Predicate<FieldDecl> { public FieldNamePredicate(String name) { super(name); } @Override public boolean predicate(FieldDecl t) { return name.equals(t.getName()); } } public static final <T extends Decl> Predicate<T> namePred(String name) { return new DeclNamePredicate<T>(name); } public static final FieldDecl getFieldDecl(ClassDecl clazz, Predicate<FieldDecl> p) { for (FieldDecl f : clazz.getFields()) { if (p.predicate(f)) { return f; } } return null; } public static final <T extends Decl> T getDecl(Model model, Class<T> klass, Predicate<T> p) { return getDecl(model, null, klass, p); } public static final <T extends Decl> T getDecl(Model model, String moduleName, Class<T> klass, Predicate<T> p) { if (moduleName == null) { for (ModuleDecl module : model.getModuleDecls()) { T r = getDecl(module, klass, p); if (r != null) return r; } } else { for (ModuleDecl module : model.getModuleDecls()) { if (moduleName.equals(module.getName())) { T r = getDecl(module, klass, p); if (r != null) return r; } } } return null; } public static final <T extends Decl> T getDecl(ModuleDecl module, Class<T> klass, Predicate<T> p) { for (Decl d : module.getDeclList()) { if (klass.isInstance(d)) { T t = klass.cast(d); if (p.predicate(t)) { return t; } } } return null; } public static final MethodImpl findMethodImpl(ClassDecl clazz, Predicate<MethodImpl> pred) { for (MethodImpl m : clazz.getMethodList()) { if (pred.predicate(m)) { return m; } } return null; } public static final MethodSig findMethodSig(InterfaceDecl inf, Predicate<MethodSig> pred) { for (MethodSig m : inf.getAllMethodSigs()) { if (pred.predicate(m)) { return m; } } return null; } public static final FnApp getFnApp(String fn, PureExp... exps) { List<PureExp> ps = new List<PureExp>(); for (PureExp p : exps) { ps.add(p); } return new FnApp(fn, ps); } public static final AssignStmt getVAssign(VarOrFieldUse v, Exp exp) { AssignStmt s = new AssignStmt(); s.setVar(v); s.setValue(exp); return s; } public static final AssignStmt getVAssign(String v, Exp exp) { return getVAssign(new VarUse(v), exp); } public static final ExpressionStmt getExpStmt(Exp exp) { ExpressionStmt ex = new ExpressionStmt(); ex.setExp(exp); return ex; } public static final Call getCall(PureExp who, String method, boolean sync, PureExp... exps) { Call call; if (sync) { call = new SyncCall(); } else { call = new AsyncCall(); } call.setCallee(who); call.setMethod(method); for (int i=0; i<exps.length; i++) { call.setParam(exps[i], i); } return call; } public static final InterfaceDecl createInterface(String interfaceName) { return new InterfaceDecl(interfaceName, new abs.frontend.ast.List<Annotation>(), new abs.frontend.ast.List<InterfaceTypeUse>(), new abs.frontend.ast.List<MethodSig>()); } public static final MethodImpl createMethodImpl(MethodSig method) { MethodImpl methodImpl = new MethodImpl(method.copy(), new Block(), false); return methodImpl; } public static final MethodSig createMethodSig(String methodName, Access returnType, ParamDecl... decls) { abs.frontend.ast.List<ParamDecl> dl = new abs.frontend.ast.List<ParamDecl>(); for (ParamDecl d : decls) { dl.add(d); } MethodSig method = new MethodSig(methodName, new abs.frontend.ast.List<Annotation>(), returnType, dl); return method; } public static final <T extends ModuleModifier> T findClassOrIfaceModifier( DeltaDecl delta, Class<T> klazz, Predicate<T> predicate) { abs.frontend.ast.List<ModuleModifier> modifiers = delta.getModuleModifiers(); for (int i=0; i<modifiers.getNumChild(); i++) { ModuleModifier modifier = modifiers.getChild(i); if (klazz.isInstance(modifier)) { T obj = klazz.cast(modifier); if (predicate.predicate(obj)) { return obj; } } } return null; } public static final PureExp getThis() { return new VarUse("this"); } public static final DataTypeUse getFutUnitType() { return getType("Fut", getType("Unit")); } public static final DataTypeUse getType(String n, TypeUse... types) { if (types.length > 0) { ParametricDataTypeUse set = new ParametricDataTypeUse(); set.setName(n); for (TypeUse d : types) { set.addParam(d); } return set; } else { DataTypeUse set = new DataTypeUse(); set.setName(n); return set; } } public static final VarDeclStmt getVarDecl(String name, Access a, Exp exp) { Opt<Exp> opt = new Opt<Exp>(); if (exp != null) { opt.setChild(exp, 0); } return new VarDeclStmt(new List<Annotation>(), new VarDecl(name, a, opt)); } public static final FieldDecl makeFieldDecl(Access access, String name) { FieldDecl fd = new FieldDecl(); fd.setName(name); fd.setAccess(access); return fd; } public static final NewExp newObj(ClassDecl clazz, boolean local, PureExp... ps) { NewExp ne = new NewExp(); ne.setClassName(clazz.getName()); for (int i=0; i < ps.length; i++) { ne.setParam(ps[i], i); } if (local) { ne.setLocal(new Local()); } return ne; } public static final VarDeclStmt newObj(InterfaceDecl inf, ClassDecl clazz, String name, boolean local) { return getVarDecl(name, new InterfaceTypeUse(inf.getName(), new List<Annotation>()), newObj(clazz, local)); } /** * Generates import statement {@code import DeclName from DeclModule;} * * @param decl * @return */ public static final Import generateImportAST(Decl decl) { return generateImportAST(decl.getName(), decl.getModuleDecl().getName()); } public static final Set<Import> generateImportsAST(Set<TypeUse> typeUses) { Set<Import> imports = new HashSet<Import>(); for (TypeUse type : typeUses) { if (type instanceof DataTypeUse) { imports.addAll(generateImportAST(type)); } else { imports.add(generateImportAST(type.getName(), type.getModuleDecl().getName())); } } return imports; } public static final Set<Import> generateImportAST(TypeUse t) { Set<Import> imports = new HashSet<Import>(); imports.add(generateImportAST(t.getName(), t.getModuleDecl().getName())); if (t instanceof ParametricDataTypeUse) { for (TypeUse st : ((ParametricDataTypeUse) t).getParams()) { imports.addAll(generateImportAST(st)); } } return imports; } /** * Generates import statement {@code import name from module;} * * @param name * @param module * @return */ public static final Import generateImportAST(String name, String module) { return new FromImport(new List<Name>().add(new Name(name)), module); } public static final DataTypeUse getUnit() { return new DataTypeUse("Unit", new abs.frontend.ast.List<Annotation>()); } }