/******************************************************************************* * Copyright (c) 2009-2012 CWI * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI * * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl * * Arnold Lankamp - Arnold.Lankamp@cwi.nl * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI *******************************************************************************/ package org.rascalmpl.eclipse.terms; import static org.rascalmpl.eclipse.IRascalResources.ID_RASCAL_ECLIPSE_PLUGIN; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.rascalmpl.eclipse.Activator; import org.rascalmpl.interpreter.IEvaluatorContext; import org.rascalmpl.interpreter.result.ICallableValue; import io.usethesource.vallang.IConstructor; import io.usethesource.vallang.ISet; import io.usethesource.vallang.ISetWriter; import io.usethesource.vallang.ISourceLocation; import io.usethesource.vallang.IValue; import io.usethesource.vallang.IValueFactory; import io.usethesource.vallang.IWithKeywordParameters; import io.usethesource.vallang.type.TypeFactory; import org.rascalmpl.values.ValueFactoryFactory; import org.rascalmpl.values.uptr.ITree; import org.rascalmpl.values.uptr.RascalValueFactory; import org.rascalmpl.values.uptr.TreeAdapter; import io.usethesource.impulse.language.Language; import io.usethesource.impulse.language.LanguageRegistry; public class TermLanguageRegistry { private final Map<String, Language> languages = new HashMap<String,Language>(); private final Map<String, IEvaluatorContext> evals = new HashMap<String, IEvaluatorContext>(); private final Map<String, ICallableValue> parsers = new HashMap<String,ICallableValue>(); private final Map<String, ICallableValue> analyses = new HashMap<String,ICallableValue>(); private final Map<String, ICallableValue> outliners = new HashMap<String,ICallableValue>(); private final Map<String, ISet> contributions = new HashMap<String, ISet>(); private final Map<String, ISet> nonRascalContributions = new ConcurrentHashMap<String, ISet>(); static private class InstanceKeeper { public static TermLanguageRegistry sInstance = new TermLanguageRegistry(); } public static TermLanguageRegistry getInstance() { return InstanceKeeper.sInstance; } private TermLanguageRegistry() { } public void clear() { languages.clear(); evals.clear(); parsers.clear(); analyses.clear(); outliners.clear(); contributions.clear(); } public void clearNonRascal() { nonRascalContributions.clear(); } public void clear(String value) { Language lang = LanguageRegistry.findLanguage(value); if (lang != null) { LanguageRegistry.deregisterLanguage(lang); } languages.remove(value); evals.remove(value); parsers.remove(value); analyses.remove(value); outliners.remove(value); contributions.remove(value); } public void clearNonRascal(String value) { nonRascalContributions.remove(value); } public void registerLanguage(String name, String extension, ICallableValue parser, IEvaluatorContext ctx) { Language l = new Language(name, "", "demo editor for " + name, "Terms", "icons/rascal3D_2-32px.gif", "http://www.rascal-mpl.org",ID_RASCAL_ECLIPSE_PLUGIN,extension,"",null); languages.put(extension, l); evals.put(name, ctx); parsers.put(name, parser); LanguageRegistry.registerLanguage(l); } public void registerAnnotator(String lang, ICallableValue function) { analyses.put(lang, function); } public void registerOutliner(String lang, ICallableValue builder) { outliners.put(lang, builder); } public void registerContributions(String lang, ISet set) { contributions.put(lang, set); } public void registerNonRascalContributions(String lang, ISet set) { nonRascalContributions.put(lang, set); } public Language getLanguage(String fileExtension) { return languages.get(fileExtension); } public Language getLanguage(ISourceLocation loc) { String path = loc.getPath(); if (path != null) { int i = path.lastIndexOf('.'); if (i != -1 && i != path.length() - 1) { String ext = path.substring(i+1); return getLanguage(ext); } } return null; } public Language getLanguage(ITree parseTree) { if (parseTree.getType().isSubtypeOf(RascalValueFactory.Tree)) { return getLanguage(TreeAdapter.getLocation(parseTree)); } return null; } public IEvaluatorContext getEvaluator(Language lang) { return getEvaluator(lang.getName()); } private IEvaluatorContext getEvaluator(String lang) { return evals.get(lang); } public ICallableValue getParser(Language lang) { if (lang == null) { return null; } return parsers.get(lang.getName()); } public ICallableValue getOutliner(Language lang) { ICallableValue outliner = outliners.get(lang.getName()); if (outliner != null) { return outliner; } ISet outliners = getContributions(lang, "outliner"); if (outliners.size() > 1) { Activator.getInstance().logException("ignoring multiple outliners! for " + lang, new UnsupportedOperationException()); } if (outliners.size() > 0) { IConstructor tree = (IConstructor) outliners.iterator().next(); return (ICallableValue) tree.get("outliner"); } return null; } public ISet getContentProposer(Language lang) { return getContentProposer(lang.getName()); } public ISet getContentProposer(String lang) { return getContributions(lang, "proposer"); } public ISet getContributions(Language lang) { return getContributions(lang.getName()); } private ISet getContributions(String lang) { if (contributions.containsKey(lang)) return contributions.get(lang); else return ValueFactoryFactory.getValueFactory().set(TypeFactory.getInstance().voidType()); } public ISet getBuilders(Language lang) { return getContributions(lang, "builder"); } private ISet getContributions(Language lang, String cons) { return getContributions(lang.getName(), cons); } private ISet getContributions(String lang, String cons) { IValueFactory vf = getEvaluator(lang).getValueFactory(); ISetWriter result = vf.setWriter(); for (IValue contribution: getContributions(lang)) { IConstructor tree = (IConstructor) contribution; if (tree.getName().equals(cons)) { result.insert(tree); } } return result.done(); } public ISet getNonRascalContributions(String editorId) { return nonRascalContributions.get(editorId); } public ICallableValue getAnnotator(Language lang) { ICallableValue annotator = analyses.get(lang.getName()); if (annotator != null) { return annotator; } ISet annotators = getContributions(lang, "annotator"); if (annotators.size() > 1) { Activator.getInstance().logException("ignoring multiple annotator! for " + lang, new UnsupportedOperationException()); } if (annotators.size() > 0) { IConstructor tree = (IConstructor) annotators.iterator().next(); return (ICallableValue) tree.get("annotator"); } return null; } public ICallableValue getLiveUpdater(Language lang) { ISet updaters = getContributions(lang, "liveUpdater"); if (updaters.size() > 1) { Activator.getInstance().logException("ignoring multiple updater for " + lang, new UnsupportedOperationException()); } if (updaters.size() > 0) { IConstructor tree = (IConstructor) updaters.iterator().next(); return (ICallableValue) tree.get("updater"); } return null; } public IConstructor getSyntaxProperties(Language lang) { ISet properties = getContributions(lang, "syntaxProperties"); if (properties.size() > 1) { Activator.getInstance().logException("ignoring multiple syntax properties for " + lang, new UnsupportedOperationException()); } if (properties.size() > 0) { return (IConstructor) properties.iterator().next(); } return null; } }