package otld.otld.intermediate;

import java.util.Arrays;

/**
 * Function in the program.
 *
 * A function has a unique identifier. A function can have zero or more arguments and always has a single return value.
 */
public class Function extends Element implements TypedElement {
    /** The unique identifier of this function. */
    private String id;

    /** The types of the arguments. The last argument is always the return type. */
    private Type[] args;

    /** The operations that form the body of this function. */
    private OperationSequence body;

    /**
     * @param id The unique identifier for this function.
     * @param args The types of the arguments for this function. At least one argument is required. The last argument is
     *             always the return type.
     */
    public Function(final String id, final Type... args) {
        assert args.length >= 1;
        this.id = id;
        this.args = args;
        this.body = new OperationSequence();
    }

    /**
     * @return The unique identifier of this function.
     */
    public final String getId() {
        return this.id;
    }

    /**
     * @return The body of this function.
     */
    public final OperationSequence getBody() {
        return this.body;
    }

    /**
     * Validates whether the variables with which this function is called are of the right type, and if the number of
     * arguments is correct.
     *
     * @param input The variables with which this function is called.
     * @return Whether the given variables are valid arguments for this function.
     */
    public final boolean validateInput(final Variable ... input) {
        final Type[] args = this.getArgs();

        if (args.length == input.length) {
            for (int i = 0; i < args.length; i++) {
                if (!args[i].worksWith(input[i].getType())) {
                    return false;
                }
            }
            return true;
        }

        return false;
    }

    /**
     * @return The types of the arguments for this function.
     */
    public final Type[] getArgs() {
        return Arrays.copyOf(this.args, this.args.length - 1);
    }

    /**
     * @return The return type of this function.
     */
    public final Type getType() {
        return this.args[this.args.length - 1];
    }

    @Override
    public final String toString() {
        return String.format("Function %s", this.getId());
    }
}

@@ -50,16 +50,38 @@
 .Arrays;
+%0Aimport java.util.Map;
 %0A%0A/**%0A *
@@ -482,16 +482,104 @@
  args;%0A%0A
+    /** The variables for the function arguments. */%0A    private Variable%5B%5D variables;%0A%0A
     /** 
@@ -1065,39 +1065,256 @@
 his.
-body = new OperationSequence();
+variables = new Variable%5Bthis.args.length - 1%5D;%0A        this.body = new OperationSequence();%0A%0A        for (int i = 0; i %3C this.variables.length; i++) %7B%0A            this.variables%5Bi%5D = new Variable(this.args%5Bi%5D, String.format(%22arg%25d%22, i));%0A        %7D
 %0A   
@@ -2336,34 +2336,185 @@
 @return The 
-types of t
+variables for the arguments of this function.%0A     */%0A    public final Variable%5B%5D getVariables() %7B%0A        return this.variables;%0A    %7D%0A%0A    /**%0A     * @return T
 he arguments

Add function argument variables