package otld.otld.intermediate;

import otld.otld.intermediate.exceptions.FunctionAlreadyDeclared;
import otld.otld.intermediate.exceptions.VariableAlreadyDeclared;

import java.util.HashMap;
import java.util.Map;

/**
 * Represents a program.
 *
 * A program has a unique identifier.
 *
 * A Program instance is responsible for keeping administration on all variables, functions, etc.
 */
public class Program {
    /** The identifier of the program. */
    private String id;

    /** The variables in this program indexed by identifier. */
    private Map<String, Variable> variables;

    /** The functions in this program indexed by identifier. */
    private Map<String, Function> functions;

    /** The operations that form the program. */
    private OperationSequence body;

    /**
     * @param id The unique identifier of the program.
     */
    public Program(final String id) {
        this.id = id;
        this.variables = new HashMap<String, Variable>();
        this.functions = new HashMap<String, Function>();
    }

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

    /**
     * @param id The identifier of the variable.
     * @return The variable or {@code null} if there is no variable with the given identifier.
     */
    public final Variable getVariable(final String id) {
        return this.variables.get(id);
    }

    /**
     * @param var The variable to add.
     * @throws VariableAlreadyDeclared There already exists a variable with the given name.
     */
    public final void addVariable(final Variable var) throws VariableAlreadyDeclared {
        if (this.variables.containsKey(var.getId())) {
            throw new VariableAlreadyDeclared();
        }
        this.variables.put(var.getId(), var);
    }

    /**
     * @param id The identifier of the function.
     * @return The function or {@code null} if there is no function with the given identifier.
     */
    public final Function getFunction(final String id) {
        return this.functions.get(id);
    }

    /**
     * @param function The function to add.
     * @throws FunctionAlreadyDeclared There already exists a function with the given name.
     */
    public final void addFunction(final Function function) throws FunctionAlreadyDeclared {
        if (this.functions.containsKey(function.getId())) {
            throw new FunctionAlreadyDeclared();
        }
        this.functions.put(function.getId(), function);
    }

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

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

@@ -180,37 +180,9 @@
 til.
-HashMap;%0Aimport java.util.Map
+*
 ;%0A%0A/
@@ -992,24 +992,745 @@
 Function%3E();
+%0A%0A        for (Function function : getDefaultFunctions()) %7B%0A            this.functions.put(function.getId(), function);%0A        %7D%0A    %7D%0A%0A    /**%0A     * Returns the default functions for a program based on the available operators.%0A     * @return The default functions for a program.%0A     */%0A    private static Set%3CFunction%3E getDefaultFunctions() %7B%0A        final Set%3CFunction%3E functions = new HashSet%3C%3E();%0A%0A        for (Operator op : Operator.values()) %7B%0A            final Type%5B%5D opArgs = op.getArgs();%0A            final Type%5B%5D types = Arrays.copyOf(opArgs, opArgs.length + 1);%0A            types%5BopArgs.length%5D = op.getType();%0A%0A            functions.add(new Function(op.name(), types));%0A        %7D%0A%0A        return functions;
 %0A    %7D%0A%0A    

Add default functions