You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by hi...@apache.org on 2012/07/30 23:22:08 UTC

svn commit: r1367311 - in /ant/sandbox/antdsl/trunk: org.apache.ant.antdsl/src/org/apache/ant/antdsl/ org.apache.ant.antdsl/src/org/apache/ant/antdsl/expr/ org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/ test/

Author: hibou
Date: Mon Jul 30 21:22:07 2012
New Revision: 1367311

URL: http://svn.apache.org/viewvc?rev=1367311&view=rev
Log:
- use AntExpression rather than String as attributes of tasks
- rework macros so they can hold expressions:
  - regular arguments become local properties
  - no more @{} substitution
  - renamed to 'function' so avoid the confusion with xml style macros

=> needs ant trunk, the build needs to be rework


Added:
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionCall.java   (with props)
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionDef.java   (with props)
Removed:
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/ExtensionPoint.java
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/Target.java
Modified:
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AbstractAntDslProjectHelper.java
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AntDSL.g
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/expr/AntExpression.java
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDSL.xtext
    ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDslXTextProjectHelper.java
    ant/sandbox/antdsl/trunk/test/build.ant

Modified: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AbstractAntDslProjectHelper.java
URL: http://svn.apache.org/viewvc/ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AbstractAntDslProjectHelper.java?rev=1367311&r1=1367310&r2=1367311&view=diff
==============================================================================
--- ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AbstractAntDslProjectHelper.java (original)
+++ ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AbstractAntDslProjectHelper.java Mon Jul 30 21:22:07 2012
@@ -389,7 +389,7 @@ public abstract class AbstractAntDslProj
     }
 
     public UnknownElement mapUnknown(Project project, AntDslContext context, InnerElement innerElement, boolean innerUnknown) {
-        RuntimeConfigurable parentWrapper = context.currentWrapper();
+        RuntimeConfigurable parentWrapper = (RuntimeConfigurable) context.currentWrapper();
         Object parent = null;
 
         if (parentWrapper != null) {
@@ -427,7 +427,7 @@ public abstract class AbstractAntDslProj
         RuntimeConfigurable wrapper = new RuntimeConfigurable(element, element.getTaskName());
 
         if (innerElement.attributes != null) {
-            for (Entry<String, String> att : innerElement.attributes.entrySet()) {
+            for (Entry<String, AntExpression> att : innerElement.attributes.entrySet()) {
                 wrapper.setAttribute(att.getKey(), att.getValue());
             }
         }
@@ -485,7 +485,7 @@ public abstract class AbstractAntDslProj
 
         public String name;
 
-        public LinkedHashMap<String, String> attributes;
+        public LinkedHashMap<String, AntExpression> attributes;
 
         public List<InnerElement> children;
     }

Modified: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AntDSL.g
URL: http://svn.apache.org/viewvc/ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AntDSL.g?rev=1367311&r1=1367310&r2=1367311&view=diff
==============================================================================
--- ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AntDSL.g (original)
+++ ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/AntDSL.g Mon Jul 30 21:22:07 2012
@@ -26,16 +26,13 @@ package org.apache.ant.antdsl.antlr;
 
 import org.apache.ant.antdsl.*;
 import org.apache.ant.antdsl.AbstractAntDslProjectHelper.InnerElement;
+import org.apache.ant.antdsl.FunctionDef.LocalProperty;
+import org.apache.ant.antdsl.FunctionDef.NestedSequential;
+import org.apache.ant.antdsl.FunctionDef.TemplateElement;
 import org.apache.ant.antdsl.IfTask.ConditionnalSequential;
-import org.apache.ant.antdsl.Target;
-import org.apache.ant.antdsl.ExtensionPoint;
 import org.apache.ant.antdsl.expr.*;
 import org.apache.tools.ant.*;
 import org.apache.tools.ant.taskdefs.*;
-import org.apache.tools.ant.taskdefs.MacroDef.Attribute;
-import org.apache.tools.ant.taskdefs.MacroDef.NestedSequential;
-import org.apache.tools.ant.taskdefs.MacroDef.TemplateElement;
-import org.apache.tools.ant.taskdefs.MacroDef.Text;
 import org.apache.tools.ant.taskdefs.condition.*;
 import java.util.LinkedHashMap;
 }
@@ -72,7 +69,7 @@ project:
     { for (Task t : tl) { context.getImplicitTarget().addTask(t); } }
     (   target
       | extensionPoint
-      | macrodef
+      | funcdef
     )*
 ;
 
@@ -126,13 +123,13 @@ nsName returns [Pair<String, String> ns 
     (n=identifier { ns.first = n; } ':')? n=identifier { ns.second = n; }
 ;
 
-arguments returns [LinkedHashMap<String, String> args = new LinkedHashMap<String, String>();]:
+arguments returns [LinkedHashMap<String, AntExpression> args = new LinkedHashMap<String, AntExpression>();]:
     arg=argument { args.put(arg.first, arg.second); }
     (',' arg=argument { args.put(arg.first, arg.second); } )*
 ;
 
-argument returns [Pair<String, String> arg = new Pair<String, String>()]:
-    n=identifier { arg.first = n; } '=' v=stringLiteral { arg.second = v; }
+argument returns [Pair<String, AntExpression> arg = new Pair<String, AntExpression>()]:
+    n=identifier { arg.first = n; } '=' v=expr { arg.second = v; }
 ;
 
 innerElements returns [List<InnerElement> ies = new ArrayList<InnerElement>()]:
@@ -188,56 +185,46 @@ conditionedTasks returns [ConditionnalSe
     tl=taskList { for (Task t : tl) { seq.addTask(t); } }
 ;
 
-macrodef returns [MacroDef macroDef = new MacroDef()]:
-    ( d=doc { macroDef.setDescription(d); } )?
-    'macrodef' n=identifier { macroDef.setName(n); }
-    '(' ( atts=attributes
-          {  for (Object att : atts) {
-                if (att instanceof Attribute) {
-                    macroDef.addConfiguredAttribute((Attribute) att);
-                } else if (att instanceof Text) {
-                    macroDef.addConfiguredText((Text) att);
-                } else if (att instanceof TemplateElement) {
-                    macroDef.addConfiguredElement((TemplateElement) att);
+funcdef returns [FunctionDef funcDef = new FunctionDef()]:
+    ( d=doc { funcDef.setDescription(d); } )?
+    'function' n=identifier { funcDef.setName(n); }
+    '(' ( args=funcArguments
+          {  for (Object arg : args) {
+                if (arg instanceof LocalProperty) {
+                    funcDef.addConfiguredLocalProperty((LocalProperty) arg);
+                } else if (arg instanceof TemplateElement) {
+                    funcDef.addConfiguredElement((TemplateElement) arg);
                 } else {
-                    throw new IllegalArgumentException("Unsupported macro attribute " + att.getClass().getName());
+                    throw new IllegalArgumentException("Unsupported function argument " + arg.getClass().getName());
                 }
              }
           } )? ')'
     tl=taskList
     {
-        NestedSequential seq = macroDef.createSequential();
+        NestedSequential seq = funcDef.createSequential();
         for (Task t : tl) { seq.addTask(t); }
-        macroDef.setProject(project);
-        macroDef.execute();
+        funcDef.setProject(project);
+        funcDef.execute();
     }
 ;
 
-attributes returns [List atts = new ArrayList()]:
-    att=attribute { atts.add(att); }
-    (',' att=attribute { atts.add(att); } )*
+funcArguments returns [List args = new ArrayList()]:
+    arg=funcArgument { args.add(arg); }
+    (',' arg=funcArgument { args.add(arg); } )*
 ;
 
-attribute returns [Object att]:
-      aatt=argAttribute { att = aatt; }
-    | tatt=textAttribute { att = tatt; }
-    | eatt=elementAttribute  { att = eatt; }
+funcArgument returns [Object arg]:
+      lparg=localPropFuncArgument { arg = lparg; }
+    | earg=elementFuncArgument  { arg = earg; }
 ;
 
-argAttribute returns [Attribute att = new Attribute()]:
-    'arg'
-    n=identifier { att.setName(n); }
-    ('=' d=stringLiteral { att.setDefault(d); } )?
-;
-
-textAttribute returns [Text text = new Text()]:
-    ('optional' { text.setOptional(true); } )?
-    ('trimmed' { text.setTrim(true); } )?
-    'text'
-    n=identifier { text.setName(n); }
+localPropFuncArgument returns [LocalProperty localProp = new LocalProperty()]:
+    'local'
+    n=identifier { localProp.setName(n); }
+    ('=' d=expr { localProp.setDefault(d); } )?
 ;
 
-elementAttribute returns [TemplateElement element = new TemplateElement()]:
+elementFuncArgument returns [TemplateElement element = new TemplateElement()]:
     ('optional' { element.setOptional(true); } )?
     ('implicit' { element.setImplicit(true); } )?
     'element'

Added: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionCall.java
URL: http://svn.apache.org/viewvc/ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionCall.java?rev=1367311&view=auto
==============================================================================
--- ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionCall.java (added)
+++ ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionCall.java Mon Jul 30 21:22:07 2012
@@ -0,0 +1,265 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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 org.apache.ant.antdsl;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.ant.antdsl.FunctionDef.LocalProperty;
+import org.apache.ant.antdsl.FunctionDef.TemplateElement;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DynamicObjectAttribute;
+import org.apache.tools.ant.Evaluable;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.PropertyHelper;
+import org.apache.tools.ant.RuntimeConfigurable;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.TaskContainer;
+import org.apache.tools.ant.UnknownElement;
+import org.apache.tools.ant.property.LocalProperties;
+
+/**
+ * The class to be placed in the ant type definition. It is given a pointer to the template definition, and makes a copy of the unknown element,
+ * substituting the parameter values in attributes and text.
+ * 
+ */
+public class FunctionCall extends Task implements DynamicObjectAttribute, TaskContainer {
+
+    private FunctionDef functionDef;
+
+    private Map<String, Object> map = new HashMap<String, Object>();
+
+    private Map<String, TemplateElement> nsElements = null;
+
+    private Map<String, UnknownElement> presentElements;
+
+    private String implicitTag = null;
+
+    private List<UnknownElement> unknownElements = new ArrayList<UnknownElement>();
+
+    public void setFunctionDef(FunctionDef functionDef) {
+        this.functionDef = functionDef;
+    }
+
+    public FunctionDef getFunctionDef() {
+        return functionDef;
+    }
+
+    /**
+     * A parameter name value pair as a xml attribute.
+     * 
+     * @param name the name of the attribute
+     * @param value the value of the attribute
+     */
+    public void setDynamicAttribute(String name, Object value) {
+        map.put(name, value);
+    }
+
+    private Map<String, TemplateElement> getNsElements() {
+        if (nsElements == null) {
+            nsElements = new HashMap<String, TemplateElement>();
+            for (Entry<String, TemplateElement> entry : functionDef.getElements().entrySet()) {
+                FunctionDef.TemplateElement te = entry.getValue();
+                nsElements.put(entry.getKey(), te);
+                if (te.isImplicit()) {
+                    implicitTag = te.getName();
+                }
+            }
+        }
+        return nsElements;
+    }
+
+    /**
+     * Add a unknownElement for the macro instances nested elements.
+     * 
+     * @param nestedTask a nested element.
+     */
+    public void addTask(Task nestedTask) {
+        unknownElements.add((UnknownElement) nestedTask);
+    }
+
+    private void processTasks() {
+        if (implicitTag != null) {
+            return;
+        }
+        for (UnknownElement ue : unknownElements) {
+            String name = ProjectHelper.extractNameFromComponentName(ue.getTag()).toLowerCase(Locale.ENGLISH);
+            if (getNsElements().get(name) == null) {
+                throw new BuildException("unsupported element " + name);
+            }
+            if (presentElements.get(name) != null) {
+                throw new BuildException("Element " + name + " already present");
+            }
+            presentElements.put(name, ue);
+        }
+    }
+
+    /**
+     * Embedded element in macro instance
+     */
+    public static class Element implements TaskContainer {
+        private List<UnknownElement> unknownElements = new ArrayList<UnknownElement>();
+
+        /**
+         * Add an unknown element (to be snipped into the macroDef instance)
+         * 
+         * @param nestedTask an unknown element
+         */
+        public void addTask(Task nestedTask) {
+            unknownElements.add((UnknownElement) nestedTask);
+        }
+
+        /**
+         * @return the list of unknown elements
+         */
+        public List<UnknownElement> getUnknownElements() {
+            return unknownElements;
+        }
+    }
+
+    private UnknownElement copy(UnknownElement ue, boolean nested) {
+        UnknownElement ret = new UnknownElement(ue.getTag());
+        ret.setNamespace(ue.getNamespace());
+        ret.setProject(getProject());
+        ret.setQName(ue.getQName());
+        ret.setTaskType(ue.getTaskType());
+        ret.setTaskName(ue.getTaskName());
+        ret.setLocation(functionDef.getBackTrace() ? ue.getLocation() : getLocation());
+        if (getOwningTarget() == null) {
+            Target t = new Target();
+            t.setProject(getProject());
+            ret.setOwningTarget(t);
+        } else {
+            ret.setOwningTarget(getOwningTarget());
+        }
+        RuntimeConfigurable rc = new RuntimeConfigurable(ret, ue.getTaskName());
+        rc.setPolyType(ue.getWrapper().getPolyType());
+        Map<String, Object> m = ((RuntimeConfigurable) ue.getWrapper()).getAttributeMap();
+        for (Entry<String, Object> entry : m.entrySet()) {
+            rc.setAttribute(entry.getKey(), entry.getValue());
+        }
+
+        @SuppressWarnings("unchecked")
+        Enumeration<RuntimeConfigurable> e = ue.getWrapper().getChildren();
+        while (e.hasMoreElements()) {
+            RuntimeConfigurable r = e.nextElement();
+            UnknownElement unknownElement = (UnknownElement) r.getProxy();
+            String tag = unknownElement.getTaskType();
+            if (tag != null) {
+                tag = tag.toLowerCase(Locale.ENGLISH);
+            }
+            FunctionDef.TemplateElement templateElement = (FunctionDef.TemplateElement) getNsElements().get(tag);
+            if (templateElement == null || nested) {
+                UnknownElement child = copy(unknownElement, nested);
+                rc.addChild(child.getWrapper());
+                ret.addChild(child);
+            } else if (templateElement.isImplicit()) {
+                if (unknownElements.size() == 0 && !templateElement.isOptional()) {
+                    throw new BuildException("Missing nested elements for implicit element " + templateElement.getName());
+                }
+                for (UnknownElement elem : unknownElements) {
+                    UnknownElement child = copy(elem, true);
+                    rc.addChild(child.getWrapper());
+                    ret.addChild(child);
+                }
+            } else {
+                UnknownElement presentElement = presentElements.get(tag);
+                if (presentElement == null) {
+                    if (!templateElement.isOptional()) {
+                        throw new BuildException("Required nested element " + templateElement.getName() + " missing");
+                    }
+                    continue;
+                }
+                @SuppressWarnings("unchecked")
+                List<UnknownElement> list = presentElement.getChildren();
+                if (list != null) {
+                    for (UnknownElement elem : list) {
+                        UnknownElement child = copy(elem, true);
+                        rc.addChild(child.getWrapper());
+                        ret.addChild(child);
+                    }
+                }
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Execute the templates instance. Copies the unknown element, substitutes the attributes, and calls perform on the unknown element.
+     * 
+     */
+    public void execute() {
+        presentElements = new HashMap<String, UnknownElement>();
+        getNsElements();
+        processTasks();
+
+        LocalProperties localProperties = LocalProperties.get(getProject());
+        localProperties.enterScope();
+        PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(getProject());
+
+        try {
+            Set<String> copyKeys = new HashSet<String>(map.keySet());
+            for (LocalProperty localProperty : functionDef.getLocalProperties()) {
+                Object value = map.get(localProperty.getName());
+                if (value == null) {
+                    value = localProperty.getDefault();
+                }
+                if (value == null) {
+                    throw new BuildException("required argument " + localProperty.getName() + " not set");
+                }
+                if (value instanceof Evaluable) {
+                    value = ((Evaluable) value).eval();
+                }
+                localProperties.addLocal(localProperty.getName());
+                localProperties.setNew(localProperty.getName(), value, propertyHelper);
+                copyKeys.remove(localProperty.getName());
+            }
+            if (copyKeys.contains("id")) {
+                copyKeys.remove("id");
+            }
+            if (copyKeys.size() != 0) {
+                throw new BuildException("Unknown argument" + (copyKeys.size() > 1 ? "s " : " ") + copyKeys);
+            }
+    
+            // need to set the project on unknown element
+            UnknownElement c = copy(functionDef.getNestedTask(), false);
+            c.init();
+            c.perform();
+        } catch (BuildException ex) {
+            if (functionDef.getBackTrace()) {
+                throw ProjectHelper.addLocationToBuildException(ex, getLocation());
+            } else {
+                ex.setLocation(getLocation());
+                throw ex;
+            }
+        } finally {
+            presentElements = null;
+            localProperties.exitScope();
+        }
+    }
+
+}

Propchange: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionCall.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionCall.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionCall.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionDef.java
URL: http://svn.apache.org/viewvc/ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionDef.java?rev=1367311&view=auto
==============================================================================
--- ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionDef.java (added)
+++ ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionDef.java Mon Jul 30 21:22:07 2012
@@ -0,0 +1,568 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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 org.apache.ant.antdsl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.ant.antdsl.expr.AntExpression;
+import org.apache.tools.ant.AntTypeDefinition;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.ComponentHelper;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.RuntimeConfigurable;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.TaskContainer;
+import org.apache.tools.ant.UnknownElement;
+import org.apache.tools.ant.taskdefs.AntlibDefinition;
+
+public class FunctionDef extends AntlibDefinition {
+
+    private NestedSequential nestedSequential;
+
+    private String name;
+
+    private boolean backTrace = true;
+
+    private List<LocalProperty> localProperties = new ArrayList<LocalProperty>();
+
+    private Map<String, TemplateElement> elements = new HashMap<String, TemplateElement>();
+
+    private boolean hasImplicitElement = false;
+
+    /**
+     * Name of the definition
+     * 
+     * @param name the name of the definition
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Set the backTrace attribute.
+     * 
+     * @param backTrace if true and the macro instance generates an error, a backtrace of the location within the macro and call to the macro will be
+     *            output. if false, only the location of the call to the macro will be shown. Default is true.
+     * @since ant 1.7
+     */
+    public void setBackTrace(boolean backTrace) {
+        this.backTrace = backTrace;
+    }
+
+    /**
+     * @return the backTrace attribute.
+     * @since ant 1.7
+     */
+    public boolean getBackTrace() {
+        return backTrace;
+    }
+
+    /**
+     * This is the sequential nested element of the macrodef.
+     * 
+     * @return a sequential element to be configured.
+     */
+    public NestedSequential createSequential() {
+        if (this.nestedSequential != null) {
+            throw new BuildException("Only one sequential allowed");
+        }
+        this.nestedSequential = new NestedSequential();
+        return this.nestedSequential;
+    }
+
+    /**
+     * The class corresponding to the sequential nested element. This is a simple task container.
+     */
+    public static class NestedSequential implements TaskContainer {
+
+        private List<Task> nested = new ArrayList<Task>();
+
+        public void addTask(Task task) {
+            nested.add(task);
+        }
+
+        public List<Task> getNested() {
+            return nested;
+        }
+
+        /**
+         * A compare function to compare this with another NestedSequential. It calls similar on the nested unknown elements.
+         * 
+         * @param other the nested sequential to compare with.
+         * @return true if they are similar, false otherwise
+         */
+        public boolean similar(NestedSequential other) {
+            final int size = nested.size();
+            if (size != other.nested.size()) {
+                return false;
+            }
+            for (int i = 0; i < size; ++i) {
+                UnknownElement me = (UnknownElement) nested.get(i);
+                UnknownElement o = (UnknownElement) other.nested.get(i);
+                if (!me.similar(o)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Convert the nested sequential to an unknown element
+     * 
+     * @return the nested sequential as an unknown element.
+     */
+    public UnknownElement getNestedTask() {
+        UnknownElement ret = new UnknownElement("sequential");
+        ret.setTaskName("sequential");
+        ret.setNamespace("");
+        ret.setQName("sequential");
+        new RuntimeConfigurable(ret, "sequential");
+        final int size = nestedSequential.getNested().size();
+        for (int i = 0; i < size; ++i) {
+            UnknownElement e = (UnknownElement) nestedSequential.getNested().get(i);
+            ret.addChild(e);
+            ret.getWrapper().addChild(e.getWrapper());
+        }
+        return ret;
+    }
+
+    public List<LocalProperty> getLocalProperties() {
+        return localProperties;
+    }
+
+    /**
+     * Gets this macro's elements.
+     * 
+     * @return the map nested elements, keyed by element name, with {@link TemplateElement} values.
+     */
+    public Map<String, TemplateElement> getElements() {
+        return elements;
+    }
+
+    /**
+     * Check if a character is a valid character for an element or attribute name.
+     * 
+     * @param c the character to check
+     * @return true if the character is a letter or digit or '.' or '-' attribute name
+     */
+    public static boolean isValidNameCharacter(char c) {
+        // ? is there an xml api for this ?
+        return Character.isLetterOrDigit(c) || c == '.' || c == '-';
+    }
+
+    /**
+     * Check if a string is a valid name for an element or attribute.
+     * 
+     * @param name the string to check
+     * @return true if the name consists of valid name characters
+     */
+    private static boolean isValidName(String name) {
+        if (name.length() == 0) {
+            return false;
+        }
+        for (int i = 0; i < name.length(); ++i) {
+            if (!isValidNameCharacter(name.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Add a local property.
+     * 
+     * @param localProperty a local property
+     */
+    public void addConfiguredLocalProperty(LocalProperty localProperty) {
+        if (localProperty.getName() == null) {
+            throw new BuildException("the local property nested element needed a name");
+        }
+        final int size = localProperties.size();
+        for (int i = 0; i < size; ++i) {
+            LocalProperty att = (LocalProperty) localProperties.get(i);
+            if (att.getName().equals(localProperty.getName())) {
+                throw new BuildException("the name \"" + localProperty.getName() + "\" has already been used in another local property element");
+            }
+        }
+        localProperties.add(localProperty);
+    }
+
+    /**
+     * Add an element element.
+     * 
+     * @param element an element nested element.
+     */
+    public void addConfiguredElement(TemplateElement element) {
+        if (element.getName() == null) {
+            throw new BuildException("the element nested needed a name");
+        }
+        if (elements.get(element.getName()) != null) {
+            throw new BuildException("the element " + element.getName() + " has already been specified");
+        }
+        if (hasImplicitElement || (element.isImplicit() && elements.size() != 0)) {
+            throw new BuildException("Only one element allowed when using implicit elements");
+        }
+        hasImplicitElement = element.isImplicit();
+        elements.put(element.getName(), element);
+    }
+
+    /**
+     * Create a new ant type based on the embedded tasks and types.
+     */
+    public void execute() {
+        if (nestedSequential == null) {
+            throw new BuildException("Missing sequential element");
+        }
+        if (name == null) {
+            throw new BuildException("Name not specified");
+        }
+
+        name = ProjectHelper.genComponentName(getURI(), name);
+
+        FunctionTypeDefinition def = new FunctionTypeDefinition(this);
+        def.setName(name);
+        def.setClass(FunctionCall.class);
+
+        ComponentHelper helper = ComponentHelper.getComponentHelper(getProject());
+
+        helper.addDataTypeDefinition(def);
+        log("creating macro  " + name, Project.MSG_VERBOSE);
+    }
+
+    public static class LocalProperty {
+
+        private String name;
+
+        private AntExpression defaultValue;
+
+        private String description;
+
+        public void setName(String name) {
+            if (!isValidName(name)) {
+                throw new BuildException("Illegal name [" + name + "] for argument");
+            }
+            this.name = name.toLowerCase(Locale.ENGLISH);
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setDefault(AntExpression defaultValue) {
+            this.defaultValue = defaultValue;
+        }
+
+        public AntExpression getDefault() {
+            return defaultValue;
+        }
+
+        public void setDescription(String desc) {
+            description = desc;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+
+        public boolean equals(Object obj) {
+            if (obj == null) {
+                return false;
+            }
+            if (obj.getClass() != getClass()) {
+                return false;
+            }
+            LocalProperty other = (LocalProperty) obj;
+            if (name == null) {
+                if (other.name != null) {
+                    return false;
+                }
+            } else if (!name.equals(other.name)) {
+                return false;
+            }
+            if (defaultValue == null) {
+                if (other.defaultValue != null) {
+                    return false;
+                }
+            } else if (!defaultValue.equals(other.defaultValue)) {
+                return false;
+            }
+            return true;
+        }
+
+        public int hashCode() {
+            return objectHashCode(defaultValue) + objectHashCode(name);
+        }
+    }
+
+    /**
+     * A nested element for the MacroDef task.
+     */
+    public static class TemplateElement {
+
+        private String name;
+        private String description;
+        private boolean optional = false;
+        private boolean implicit = false;
+
+        /**
+         * Sets the name of this element.
+         * 
+         * @param name the name of the element
+         */
+        public void setName(String name) {
+            if (!isValidName(name)) {
+                throw new BuildException("Illegal name [" + name + "] for function element");
+            }
+            this.name = name.toLowerCase(Locale.ENGLISH);
+        }
+
+        /**
+         * Gets the name of this element.
+         * 
+         * @return the name of the element.
+         */
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * Sets a textual description of this element, for build documentation purposes only.
+         * 
+         * @param desc Description of the element.
+         * @since ant 1.6.1
+         */
+        public void setDescription(String desc) {
+            description = desc;
+        }
+
+        /**
+         * Gets the description of this element.
+         * 
+         * @return the description of the element, or <code>null</code> if no description is available.
+         * @since ant 1.6.1
+         */
+        public String getDescription() {
+            return description;
+        }
+
+        /**
+         * Sets whether this element is optional.
+         * 
+         * @param optional if true this element may be left out, default is false.
+         */
+        public void setOptional(boolean optional) {
+            this.optional = optional;
+        }
+
+        /**
+         * Gets whether this element is optional.
+         * 
+         * @return the optional attribute
+         */
+        public boolean isOptional() {
+            return optional;
+        }
+
+        /**
+         * Sets whether this element is implicit.
+         * 
+         * @param implicit if true this element may be left out, default is false.
+         */
+        public void setImplicit(boolean implicit) {
+            this.implicit = implicit;
+        }
+
+        /**
+         * Gets whether this element is implicit.
+         * 
+         * @return the implicit attribute
+         */
+        public boolean isImplicit() {
+            return implicit;
+        }
+
+        /**
+         * equality method.
+         * 
+         * @param obj an <code>Object</code> value
+         * @return a <code>boolean</code> value
+         */
+        public boolean equals(Object obj) {
+            if (obj == this) {
+                return true;
+            }
+            if (obj == null || !obj.getClass().equals(getClass())) {
+                return false;
+            }
+            TemplateElement t = (TemplateElement) obj;
+            return (name == null ? t.name == null : name.equals(t.name)) && optional == t.optional && implicit == t.implicit;
+        }
+
+        /**
+         * @return a hash code value for this object.
+         */
+        public int hashCode() {
+            return objectHashCode(name) + (optional ? 1 : 0) + (implicit ? 1 : 0);
+        }
+
+    } // END static class TemplateElement
+
+    /**
+     * same or similar equality method for macrodef, ignores project and runtime info.
+     * 
+     * @param obj an <code>Object</code> value
+     * @param same if true test for sameness, otherwise just similiar
+     * @return a <code>boolean</code> value
+     */
+    private boolean sameOrSimilar(Object obj, boolean same) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+        if (!obj.getClass().equals(getClass())) {
+            return false;
+        }
+        FunctionDef other = (FunctionDef) obj;
+        if (name == null) {
+            return other.name == null;
+        }
+        if (!name.equals(other.name)) {
+            return false;
+        }
+        // Allow two macro definitions with the same location
+        // to be treated as similar - bugzilla 31215
+        if (other.getLocation() != null && other.getLocation().equals(getLocation()) && !same) {
+            return true;
+        }
+        if (getURI() == null || getURI().equals("") || getURI().equals(ProjectHelper.ANT_CORE_URI)) {
+            if (!(other.getURI() == null || other.getURI().equals("") || other.getURI().equals(ProjectHelper.ANT_CORE_URI))) {
+                return false;
+            }
+        } else {
+            if (!getURI().equals(other.getURI())) {
+                return false;
+            }
+        }
+
+        if (!nestedSequential.similar(other.nestedSequential)) {
+            return false;
+        }
+        if (!localProperties.equals(other.localProperties)) {
+            return false;
+        }
+        if (!elements.equals(other.elements)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Similar method for this definition
+     * 
+     * @param obj another definition
+     * @return true if the definitions are similar
+     */
+    public boolean similar(Object obj) {
+        return sameOrSimilar(obj, false);
+    }
+
+    /**
+     * Equality method for this definition
+     * 
+     * @param obj another definition
+     * @return true if the definitions are the same
+     */
+    public boolean sameDefinition(Object obj) {
+        return sameOrSimilar(obj, true);
+    }
+
+    /**
+     * extends AntTypeDefinition, on create of the object, the template macro definition is given.
+     */
+    private static class FunctionTypeDefinition extends AntTypeDefinition {
+        private FunctionDef functionDef;
+
+        public FunctionTypeDefinition(FunctionDef functionDef) {
+            this.functionDef = functionDef;
+        }
+
+        /**
+         * Create an instance of the definition. The instance may be wrapped in a proxy class.
+         * 
+         * @param project the current project
+         * @return the created object
+         */
+        public Object create(Project project) {
+            Object o = super.create(project);
+            if (o == null) {
+                return null;
+            }
+            ((FunctionCall) o).setFunctionDef(functionDef);
+            return o;
+        }
+
+        /**
+         * Equality method for this definition
+         * 
+         * @param other another definition
+         * @param project the current project
+         * @return true if the definitions are the same
+         */
+        public boolean sameDefinition(AntTypeDefinition other, Project project) {
+            if (!super.sameDefinition(other, project)) {
+                return false;
+            }
+            FunctionTypeDefinition otherDef = (FunctionTypeDefinition) other;
+            return functionDef.sameDefinition(otherDef.functionDef);
+        }
+
+        /**
+         * Similar method for this definition
+         * 
+         * @param other another definition
+         * @param project the current project
+         * @return true if the definitions are the same
+         */
+        public boolean similarDefinition(AntTypeDefinition other, Project project) {
+            if (!super.similarDefinition(other, project)) {
+                return false;
+            }
+            FunctionTypeDefinition otherDef = (FunctionTypeDefinition) other;
+            return functionDef.similar(otherDef.functionDef);
+        }
+    }
+
+    private static int objectHashCode(Object o) {
+        if (o == null) {
+            return 0;
+        } else {
+            return o.hashCode();
+        }
+    }
+
+}

Propchange: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionDef.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionDef.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/FunctionDef.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/expr/AntExpression.java
URL: http://svn.apache.org/viewvc/ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/expr/AntExpression.java?rev=1367311&r1=1367310&r2=1367311&view=diff
==============================================================================
--- ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/expr/AntExpression.java (original)
+++ ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/expr/AntExpression.java Mon Jul 30 21:22:07 2012
@@ -17,9 +17,10 @@
  */
 package org.apache.ant.antdsl.expr;
 
+import org.apache.tools.ant.Evaluable;
 import org.apache.tools.ant.Project;
 
-public abstract class AntExpression {
+public abstract class AntExpression implements Evaluable {
 
     private Project project;
 

Modified: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDSL.xtext
URL: http://svn.apache.org/viewvc/ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDSL.xtext?rev=1367311&r1=1367310&r2=1367311&view=diff
==============================================================================
--- ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDSL.xtext (original)
+++ ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDSL.xtext Mon Jul 30 21:22:07 2012
@@ -30,7 +30,7 @@ EProject:
     )
     ('namespaces' '{' namespaces+=ENamespace* '}')?
     tasks=ETaskLists?
-    (targets+=ETarget | extensionPoints+=EExtensionPoint | macrodDefs+=EMacrodef)*
+    (targets+=ETarget | extensionPoints+=EExtensionPoint | functionDefs+=EFunctionDef)*
 ;
 
 ENamespace:
@@ -79,7 +79,7 @@ EArguments:
 ;
 
 EArgument:
-    name=Identifier '=' value=StringLiteral
+    name=Identifier '=' value=EExpr
 ;
 
 EInnerElements:
@@ -115,30 +115,26 @@ EConditionedTasks:
 ;
 
 ////////////////
-// Macro
+// Functions
 ////////////////
 
-EMacrodef:
-    description=DOC? 'macrodef' name=Identifier '(' attributes=EAttributes? ')' tasks=ETaskLists
+EFunctionDef:
+    description=DOC? 'function' name=Identifier '(' arguments=EFuncArguments? ')' tasks=ETaskLists
 ;
 
-EAttributes:
-    attributes+=EAttribute (',' attributes+=EAttribute)*
+EFuncArguments:
+    arguments+=EFuncArgument (',' arguments+=EFuncArgument)*
 ;
 
-EAttribute:
-    EArgAttribute | ETextAttribute | EElementAttribute
+EFuncArgument:
+    ELocalPropertyFuncArgument | EElementFuncArgument
 ;
 
-EArgAttribute:
-    'arg' name=Identifier ('=' default=StringLiteral)?
+ELocalPropertyFuncArgument:
+    'local' name=Identifier ('=' default=EExpr)?
 ;
 
-ETextAttribute:
-    (optional ?= 'optional')? (trimmed ?= 'trimmed')? 'text' name=Identifier
-;
-
-EElementAttribute:
+EElementFuncArgument:
     (optional ?= 'optional')? (implicit ?= 'implicit')? 'element' name=Identifier
 ;
 

Modified: ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDslXTextProjectHelper.java
URL: http://svn.apache.org/viewvc/ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDslXTextProjectHelper.java?rev=1367311&r1=1367310&r2=1367311&view=diff
==============================================================================
--- ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDslXTextProjectHelper.java (original)
+++ ant/sandbox/antdsl/trunk/org.apache.ant.antdsl/src/org/apache/ant/antdsl/xtext/AntDslXTextProjectHelper.java Mon Jul 30 21:22:07 2012
@@ -30,10 +30,12 @@ import org.apache.ant.antdsl.AntDslConte
 import org.apache.ant.antdsl.AssignLocalTask;
 import org.apache.ant.antdsl.AssignPropertyTask;
 import org.apache.ant.antdsl.AssignReferenceTask;
-import org.apache.ant.antdsl.ExtensionPoint;
+import org.apache.ant.antdsl.FunctionDef;
+import org.apache.ant.antdsl.FunctionDef.LocalProperty;
+import org.apache.ant.antdsl.FunctionDef.NestedSequential;
+import org.apache.ant.antdsl.FunctionDef.TemplateElement;
 import org.apache.ant.antdsl.IfTask;
 import org.apache.ant.antdsl.IfTask.ConditionnalSequential;
-import org.apache.ant.antdsl.Target;
 import org.apache.ant.antdsl.expr.AddAntExpression;
 import org.apache.ant.antdsl.expr.AndAntExpression;
 import org.apache.ant.antdsl.expr.AntExpression;
@@ -62,11 +64,8 @@ import org.apache.ant.antdsl.expr.Ternar
 import org.apache.ant.antdsl.expr.VariableAntExpression;
 import org.apache.ant.antdsl.xtext.antdsl.EAdditiveExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EAndExpr;
-import org.apache.ant.antdsl.xtext.antdsl.EArgAttribute;
 import org.apache.ant.antdsl.xtext.antdsl.EArgument;
 import org.apache.ant.antdsl.xtext.antdsl.EArguments;
-import org.apache.ant.antdsl.xtext.antdsl.EAttribute;
-import org.apache.ant.antdsl.xtext.antdsl.EAttributes;
 import org.apache.ant.antdsl.xtext.antdsl.EBooleanLiteralExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EBranch;
 import org.apache.ant.antdsl.xtext.antdsl.ECharacterLiteralExpr;
@@ -75,20 +74,23 @@ import org.apache.ant.antdsl.xtext.antds
 import org.apache.ant.antdsl.xtext.antdsl.EConditionnalExclusiveOrExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EConditionnalInclusiveOrExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EDecimalLiteralExpr;
-import org.apache.ant.antdsl.xtext.antdsl.EElementAttribute;
+import org.apache.ant.antdsl.xtext.antdsl.EElementFuncArgument;
 import org.apache.ant.antdsl.xtext.antdsl.EEqualityExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EExclusiveOrExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EExtensionPoint;
 import org.apache.ant.antdsl.xtext.antdsl.EFloatingPointLiteralExpr;
+import org.apache.ant.antdsl.xtext.antdsl.EFuncArgument;
+import org.apache.ant.antdsl.xtext.antdsl.EFuncArguments;
 import org.apache.ant.antdsl.xtext.antdsl.EFuncExpr;
+import org.apache.ant.antdsl.xtext.antdsl.EFunctionDef;
 import org.apache.ant.antdsl.xtext.antdsl.EHexLiteralExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EInclusiveOrExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EInnerElement;
 import org.apache.ant.antdsl.xtext.antdsl.EInnerElements;
 import org.apache.ant.antdsl.xtext.antdsl.EInstanceOfExpr;
 import org.apache.ant.antdsl.xtext.antdsl.ELocalAssignment;
-import org.apache.ant.antdsl.xtext.antdsl.EMacrodef;
+import org.apache.ant.antdsl.xtext.antdsl.ELocalPropertyFuncArgument;
 import org.apache.ant.antdsl.xtext.antdsl.EMultiplicativeExpr;
 import org.apache.ant.antdsl.xtext.antdsl.ENamespace;
 import org.apache.ant.antdsl.xtext.antdsl.ENullExpr;
@@ -104,17 +106,13 @@ import org.apache.ant.antdsl.xtext.antds
 import org.apache.ant.antdsl.xtext.antdsl.ETask;
 import org.apache.ant.antdsl.xtext.antdsl.ETaskLists;
 import org.apache.ant.antdsl.xtext.antdsl.ETernaryExpr;
-import org.apache.ant.antdsl.xtext.antdsl.ETextAttribute;
 import org.apache.ant.antdsl.xtext.antdsl.EUnaryExpr;
 import org.apache.ant.antdsl.xtext.antdsl.EVariableExpr;
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.ExtensionPoint;
 import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Target;
 import org.apache.tools.ant.Task;
-import org.apache.tools.ant.taskdefs.MacroDef;
-import org.apache.tools.ant.taskdefs.MacroDef.Attribute;
-import org.apache.tools.ant.taskdefs.MacroDef.NestedSequential;
-import org.apache.tools.ant.taskdefs.MacroDef.TemplateElement;
-import org.apache.tools.ant.taskdefs.MacroDef.Text;
 import org.apache.tools.ant.taskdefs.Sequential;
 import org.apache.tools.ant.taskdefs.condition.And;
 import org.apache.tools.ant.taskdefs.condition.Not;
@@ -171,10 +169,10 @@ public class AntDslXTextProjectHelper ex
             }
         }
 
-        EList<EMacrodef> macros = eProject.getMacrodDefs();
-        if (macros != null) {
-            for (EMacrodef macro : macros) {
-                mapMacro(project, context, macro);
+        EList<EFunctionDef> efuncs = eProject.getFunctionDefs();
+        if (efuncs != null) {
+            for (EFunctionDef efunc : efuncs) {
+                mapFunction(project, context, efunc);
             }
         }
         ETaskLists tasks = eProject.getTasks();
@@ -191,47 +189,40 @@ public class AntDslXTextProjectHelper ex
         }
     }
 
-    private void mapMacro(Project project, AntDslContext context, EMacrodef emacro) {
-        MacroDef macroDef = new MacroDef();
-        macroDef.setDescription(emacro.getDescription());
-        macroDef.setName(readIdentifier(emacro.getName()));
-        EAttributes eatts = emacro.getAttributes();
-        if (eatts != null) {
-            for (EAttribute eatt : eatts.getAttributes()) {
-                if (eatt instanceof EArgAttribute) {
-                    EArgAttribute eargatt = (EArgAttribute) eatt;
-                    Attribute att = new Attribute();
-                    att.setName(readIdentifier(eargatt.getName()));
-                    att.setDefault(readString(eargatt.getDefault()));
-                    macroDef.addConfiguredAttribute(att);
-                } else if (eatt instanceof ETextAttribute) {
-                    ETextAttribute etextatt = (ETextAttribute) eatt;
-                    Text text = new Text();
-                    text.setName(readIdentifier(etextatt.getName()));
-                    text.setTrim(etextatt.isTrimmed());
-                    text.setOptional(etextatt.isOptional());
-                    macroDef.addConfiguredText(text);
-                } else if (eatt instanceof EElementAttribute) {
-                    EElementAttribute eelematt = (EElementAttribute) eatt;
+    private void mapFunction(Project project, AntDslContext context, EFunctionDef efunc) {
+        FunctionDef funcDef = new FunctionDef();
+        funcDef.setDescription(efunc.getDescription());
+        funcDef.setName(readIdentifier(efunc.getName()));
+        EFuncArguments eargs = efunc.getArguments();
+        if (eargs != null) {
+            for (EFuncArgument earg : eargs.getArguments()) {
+                if (earg instanceof ELocalPropertyFuncArgument) {
+                    ELocalPropertyFuncArgument elocalpropatt = (ELocalPropertyFuncArgument) earg;
+                    LocalProperty localProp = new LocalProperty();
+                    localProp.setName(readIdentifier(elocalpropatt.getName()));
+                    localProp.setDefault(mapExpr(project, context, elocalpropatt.getDefault()));
+                    funcDef.addConfiguredLocalProperty(localProp);
+                } else if (earg instanceof EElementFuncArgument) {
+                    EElementFuncArgument eelemarg = (EElementFuncArgument) earg;
                     TemplateElement element = new TemplateElement();
-                    element.setImplicit(eelematt.isImplicit());
-                    element.setOptional(eelematt.isOptional());
-                    element.setName(readIdentifier(eelematt.getName()));
-                    macroDef.addConfiguredElement(element);
+                    element.setImplicit(eelemarg.isImplicit());
+                    element.setOptional(eelemarg.isOptional());
+                    element.setName(readIdentifier(eelemarg.getName()));
+                    funcDef.addConfiguredElement(element);
                 } else {
-                    throw new IllegalArgumentException("Unsupported macro attribute " + eatt.getClass().getName());
+                    throw new IllegalArgumentException("Unsupported function argument " + earg.getClass().getName());
                 }
             }
         }
-        ETaskLists etasks = emacro.getTasks();
+        ETaskLists etasks = efunc.getTasks();
         if (etasks != null) {
-            NestedSequential seq = macroDef.createSequential();
+            NestedSequential seq = funcDef.createSequential();
             for (ETask etask : etasks.getTasks()) {
                 seq.addTask(mapTask(project, context, etask));
             }
         }
-        macroDef.setProject(project);
-        macroDef.execute();
+        funcDef.setProject(project);
+        funcDef.execute();
     }
 
     private Target mapTarget(Project project, AntDslContext context, ETarget eTarget) {
@@ -300,7 +291,7 @@ public class AntDslXTextProjectHelper ex
         }
         if (eTask instanceof EInnerElement) {
             EInnerElement eInnerElement = (EInnerElement) eTask;
-            return mapUnknown(project, context, mapInnerElement(eInnerElement), false);
+            return mapUnknown(project, context, mapInnerElement(project, context, eInnerElement), false);
         }
         if (eTask instanceof EBranch) {
             EBranch eBranch = (EBranch) eTask;
@@ -342,7 +333,7 @@ public class AntDslXTextProjectHelper ex
         throw new IllegalStateException("Unknown task type " + eTask.getClass().getName());
     }
 
-    private InnerElement mapInnerElement(EInnerElement eInnerElement) {
+    private InnerElement mapInnerElement(Project project, AntDslContext context, EInnerElement eInnerElement) {
         if (eInnerElement == null) {
             return null;
         }
@@ -352,9 +343,9 @@ public class AntDslXTextProjectHelper ex
 
         EArguments arguments = eInnerElement.getArguments();
         if (arguments != null) {
-            innerElement.attributes = new LinkedHashMap<String, String>();
+            innerElement.attributes = new LinkedHashMap<String, AntExpression>();
             for (EArgument argument : arguments.getArguments()) {
-                innerElement.attributes.put(readIdentifier(argument.getName()), readString(argument.getValue()));
+                innerElement.attributes.put(readIdentifier(argument.getName()), mapExpr(project, context, argument.getValue()));
             }
         }
 
@@ -362,7 +353,7 @@ public class AntDslXTextProjectHelper ex
         if (inners != null) {
             innerElement.children = new ArrayList<InnerElement>();
             for (EInnerElement inner : inners.getElements()) {
-                innerElement.children.add(mapInnerElement(inner));
+                innerElement.children.add(mapInnerElement(project, context, inner));
             }
         }
 
@@ -596,7 +587,7 @@ public class AntDslXTextProjectHelper ex
         }
         if (eexpr instanceof EInnerElement) {
             EInnerElement elemExpr = (EInnerElement) eexpr;
-            return mapCallAntExpression(project, context, mapInnerElement(elemExpr));
+            return mapCallAntExpression(project, context, mapInnerElement(project, context, elemExpr));
         }
         if (eexpr instanceof EHexLiteralExpr) {
             EHexLiteralExpr eint = (EHexLiteralExpr) eexpr;

Modified: ant/sandbox/antdsl/trunk/test/build.ant
URL: http://svn.apache.org/viewvc/ant/sandbox/antdsl/trunk/test/build.ant?rev=1367311&r1=1367310&r2=1367311&view=diff
==============================================================================
--- ant/sandbox/antdsl/trunk/test/build.ant (original)
+++ ant/sandbox/antdsl/trunk/test/build.ant Mon Jul 30 21:22:07 2012
@@ -7,18 +7,18 @@ namespaces {
 
 {
     prop foo = "hello world!"
-    echo(message="${foo}")
+    echo(message = ${foo})
 }
 
-# Some documentation of the macro
-macrodef mymacro(arg t = "mymacro")
+# Some documentation of the function
+function myfunction(local t = "myfunction")
 {
-    echo(message = "@{t}")
+    echo(message = ${t})
 }
 
-macrodef mymacro2(arg dest, implicit element source)
+function myfunction2(local dest, implicit element source)
 {
-    copy(todir = "@{dest}" {
+    copy(todir = ${dest}, {
         source()
     })
 }
@@ -38,19 +38,19 @@ target notexecuted
 target build
     depends dep, notexecuted
 {
-    copy(file = "${basedir}/test/build.ant", tofile = "${basedir}/build/test/build.ant.copy")
+    copy(file = ${basedir} + "/test/build.ant", tofile = ${basedir} + "/build/test/build.ant.copy")
     // some comment
-    jar(file = "${basedir}/build/test/my.jar" {
-        fileset(dir="${basedir}/test", includes="*.ant")
+    jar(file = ${basedir} + "/build/test/my.jar" {
+        fileset(dir = ${basedir} + "/test", includes = "*.ant")
     })
-    mymacro()
-    mymacro(t = "simple macro")
+    myfunction()
+    myfunction(t = "simple function")
     /*
      * Some multiline comment 
      */
-    if (available(file = "${basedir}/test/build.ant")) {
-        mymacro2(dest = "${basedir}/build/test/dest", {
-            fileset(dir = "${basedir}", includes="build.*")
+    if (available(file = ${basedir} + "/test/build.ant")) {
+        myfunction2(dest = ${basedir} + "/build/test/dest", {
+            fileset(dir = ${basedir}, includes = "build.*")
         })
     } else {
         fail(message = "fail !")
@@ -65,7 +65,8 @@ target build
     echo(message = "test encoding\nline")
 
     local test = "hello" + ' ' + "world !"
-    echo(message = "${test}")
+    echo(message = ${test})
     local test2 = ((12345 + 6789) % 98765 == 12.4f)
-    echo(message = "${test2}")
+    echo(message = ${test2})
+    echo(message = eval("${test2}"))
 }