/******************************************************************************* * Copyright (c) 2011 Bruno Medeiros and other Contributors. * 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: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package dtool.ast.definitions; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import melnorme.lang.tooling.ast.CommonASTNode; import melnorme.lang.tooling.ast.IASTVisitor; import melnorme.lang.tooling.ast.util.ASTCodePrinter; import melnorme.lang.tooling.ast.util.NodeVector; import melnorme.lang.tooling.ast_actual.ASTNodeTypes; import melnorme.lang.tooling.engine.PickedElement; import melnorme.lang.tooling.engine.resolver.NamedElementSemantics; import melnorme.lang.tooling.engine.scoping.IScopeElement; import melnorme.lang.tooling.engine.scoping.ScopeTraverser; import melnorme.lang.tooling.symbols.IConcreteNamedElement; import dtool.ast.declarations.DeclBlock; import dtool.ast.declarations.IDeclaration; import dtool.ast.expressions.Expression; import dtool.ast.expressions.MissingParenthesesExpression; import dtool.ast.references.RefTemplateInstance; import dtool.ast.statements.IStatement; import dtool.engine.analysis.templates.DefTemplateSemantics; import dtool.parser.common.Token; /** * Definition of a template. * http://dlang.org/template.html#TemplateDeclaration * * (Technically not allowed as statement, but parse so anyways.) */ public class DefinitionTemplate extends CommonDefinition implements IScopeElement, IDeclaration, IStatement, ITemplatableElement, IConcreteNamedElement { public final boolean isMixin; protected final NodeVector<ITemplateParameter> tplParams; public final Expression tplConstraint; public final DeclBlock decls; public final boolean wrapper; public DefinitionTemplate(Token[] comments, boolean isMixin, DefSymbol defName, NodeVector<ITemplateParameter> tplParams, Expression tplConstraint, DeclBlock decls) { super(comments, defName); this.isMixin = isMixin; this.tplParams = parentize(tplParams); this.tplConstraint = parentize(tplConstraint); this.decls = parentize(decls); this.wrapper = false; // TODO: determine this if(wrapper) { assertTrue(this.decls.nodes.size() == 1); assertTrue(decls.nodes.get(0) instanceof DefUnit); } } @Override public ASTNodeTypes getNodeType() { return ASTNodeTypes.DEFINITION_TEMPLATE; } @Override public void visitChildren(IASTVisitor visitor) { acceptVisitor(visitor, defName); acceptVisitor(visitor, tplParams); acceptVisitor(visitor, tplConstraint); acceptVisitor(visitor, decls); } @Override protected CommonASTNode doCloneTree() { return new DefinitionTemplate(comments, isMixin, clone(defName), clone(tplParams), clone(tplConstraint), clone(decls)); } @Override public void toStringAsCode(ASTCodePrinter cp) { cp.append(isMixin, "mixin "); cp.append("template "); cp.append(defName, " "); cp.appendList("(", tplParams, ",", ") "); tplConstraintToStringAsCode(cp, tplConstraint); cp.append(decls); } public static void tplConstraintToStringAsCode(ASTCodePrinter cp, Expression tplConstraint) { if(tplConstraint instanceof MissingParenthesesExpression) { cp.append("if", tplConstraint); } else { cp.append("if(", tplConstraint, ")"); } } @Override public EArcheType getArcheType() { return EArcheType.Template; } @Override public boolean isTemplated() { return true; } @Override public NodeVector<ITemplateParameter> getTemplateParameters() { return getEffectiveParameters(); } public NodeVector<ITemplateParameter> getEffectiveParameters() { return NodeVector.nullAsEmpty(tplParams); } @Override public DefUnit cloneTemplateElement(RefTemplateInstance templateRef) { return setParsedFromOther( new DefinitionTemplate_Instantiated(templateRef, comments, isMixin, clone(defName), clone(decls)), this); } public static class DefinitionTemplate_Instantiated extends DefinitionTemplate { protected final RefTemplateInstance templateRef; public DefinitionTemplate_Instantiated(RefTemplateInstance templateRef, Token[] comments, boolean isMixin, DefSymbol defName, DeclBlock decls) { super(comments, isMixin, defName, null, null, decls); this.templateRef = assertNotNull(templateRef); } @Override public String getExtendedName() { return getName() + templateRef.normalizedArgsToString(); } } /* ----------------- ----------------- */ @Override protected NamedElementSemantics doCreateSemantics(PickedElement<?> pickedElement) { return new DefTemplateSemantics(this, pickedElement); } @Override public ScopeTraverser getScopeTraverser() { return new ScopeTraverser(tplParams, false); } }