/**
  *
  *                      OOAS Compiler
  *
  *       Copyright 2015, AIT Austrian Institute of Technology.
  * This code is based on the C# Version of the OOAS Compiler, which is
  * copyright 2015 by the Institute of Software Technology, Graz University
  * of Technology with portions copyright by the AIT Austrian Institute of
  * Technology. All rights reserved.
  *
  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
  *
  * If you modify the file please update the list of contributors below to in-
  * clude your name. Please also stick to the coding convention of using TABs
  * to do the basic (block-level) indentation and spaces for anything after
  * that. (Enable the display of special chars and it should be pretty obvious
  * what this means.) Also, remove all trailing whitespace.
  *
  * Contributors:
  *               Willibald Krenn (AIT)
  *               Stephan Zimmerer (AIT)
  *               Markus Demetz (AIT)
  *               Christoph Czurda (AIT)
  *
  */


package org.momut.ooas.codegen.ast;

import org.momut.ooas.ast.expressions.ExpressionKind;
import org.momut.ooas.ast.identifiers.IdentifierKind;
import org.momut.ooas.ast.identifiers.MainModule;
import org.momut.ooas.ast.statements.StatementKind;
import org.momut.ooas.ast.types.TypeKind;

/**
 * Defines a low-level interface that can be used to copy
 * the OOAS AST. Initially defined for the C++ backend.
 *
 * @author willibald
 */

public interface IAstDuplicator<T> {

	/** Allocate an identifier */
	T createIdentifier(IdentifierKind kind, int subOrd);
	/** Allocate a type */
	T createType(TypeKind kind);
	/** Allocate an expression */
	T createExpression(ExpressionKind kind, int subOrd);
	/** Allocate a statement */
	T createStatement(StatementKind kind);
	/** Allocate a new action system instance object */
	T createActionSystemInstance();
	/** Allocate a new symbol table */
	T createSymbolTable();
	/** Allocate a new list for method/function parameters */
	T createParameterList();
	/** Allocate a new list for types */
	T createTypeList();
	/** Allocate a new list for action system instances */
	T createActionSystemInstanceList();
	/** Allocate a new statement list */
	T createStatementList();
	/** Allocate a new expression list */
	T createExpressionList();
	/** Allocate a new list of identifiers */
	T createIdentifierList();

	/** Cast an AstElement object to IScope */
	T castToIScope(T input);

	/** Adds an identifier to a symbol table */
	boolean addIdentifierToSymbolTable(T symbolTable, T identifier);
	/** Adds a parameter identifier to a parameter list */
	boolean addParameterIdentifierToList(T parameterList, T param);
	/** Adds a type to a type-list */
	boolean addTypeToList(T typeList, T type);
	/** Adds an instance (ref) to a instance list */
	boolean addActionSystemInstanceToList(T objectsList, T instanceRef);
	/** Adds an identifier to an identifier block */
	boolean addIdentifierToBlock(T idBlock, T idRef);
	/** Adds a statement to a statement list */
	boolean addStatementToList(T stmtList, T stmntRef);
	/** Adds an expression to an expression list */
	boolean addExpressionToList(T exprList, T exprRef);
	/** Adds an identifier to an identifier list */
	boolean addIdentifierToList(T idList, T idRef);

	/** Initialize an EnumIdentifier */
	boolean initEnumIdentifier(
			T enumId,
			int line,
			int col,
			String text,
			T scopeRef,
			T typeRef,
			boolean haveValue,
			int value);

	/** Initialize an ConstantIdentifier*/
	boolean initConstantIdentifier(
			T constId,
			int line,
			int col,
			String text,
			T scopeRef,
			T typeRef,
			T valueRef);

	/** Initialize an AttributeIdentifier */
	boolean initAttributeIdentifier(
			T attrId,
			int line,
			int col,
			String text,
			T scopeRef,
			T typeRef,
			T initRef,
			boolean isStatic,
			boolean isControllable,
			boolean isObservable);

	/** Initialize an ExpressionVarIdentifier */
	boolean initExprVarIdentifier(
			T exprVarId,
			int line,
			int col,
			String text,
			T scopeRef,
			T typeRef,
			boolean initialized);

	/** Initialize a ParamIdentifier */
	boolean initParamIdentifier(
			T paramId,
			int line,
			int column,
			String text,
			T scopeRef,
			T typeRef);

	/** Initialize a LocalVarIdentifier */
	boolean initLocalVarIdentifier(
			T locVarId,
			int line,
			int column,
			String text,
			T scopeRef,
			T typeRef);

	/** Initialize a TypeIdentifier */
	boolean initTypeIdentifier(
			T typeId,
			int line,
			int column,
			String text,
			T scopeRef,
			T typeRef,
			String prefix);

	/** Special version of the TypeIdentifier: */
	boolean initSelfIdentifier(
			T typeId,
			int line,
			int column,
			String text,
			T scopeRef,
			T typeRef,
			String prefix);

	/** Initialize a MethodIdentifier */
	boolean initMethodIdentifier(
			T methodId,
			int line,
			int column,
			String text,
			T scopeRef,
			T typeRef,
			String prefix,
			T parameterListRef,
			T symbolTableRef,
			T bodyRef);

	/** Initialize a Module */
	boolean initModule(
			T moduleId,
			int line,
			int column,
			String text,
			T scopeRef,
			T typeRef,
			String prefix,
			T symTabRef);

	/** Initialize the Main Module */
	boolean initMainModule(
			T moduleId,
			int line,
			int column,
			String text,
			T scopeRef,
			T typeRef,
			String prefix,
			T symTabRef,
			T identifierListRef);

	/** Initialize an integer type */
	boolean initIntType(
			T typeId,
			T identifierRef,
			boolean anonymousType,
			int low,
			int high);

	/** Initialize a bool type */
	boolean initBoolType(
			T typeId,
			T identifierRef,
			boolean anonymousType);

	/** Initialize a valued enum type */
	boolean initValuedEnumType(
			T typeId,
			T identifierRef,
			boolean anonymousType,
			T symTabRef,
			T intTypeRef);

	/** Initialize a normal enum type */
	boolean initEnumType(
			T typeId,
			T identifierRef,
			boolean anonymousType,
			T symTabRef);

	/** Initialize a list type */
	boolean initListType(
			T typeId,
			T identifierRef,
			boolean anonymousType,
			T innerTypeRef,
			int maxNumberOfElements);

	/** Initialize a meta type */
	boolean initMetaType(
			T typeId,
			T identifierRef,
			boolean anonymousType,
			T innerTypeRef);

	/** Initialize a tuple type */
	boolean initTupleType(
			T typeId,
			T identifierRef,
			boolean anonymousType,
			T typeListRef);

	/** Initialize a function type */
	boolean initFunctionType(
			T typeId,
			T identifierRef,
			boolean anonymousType,
			T paramTypeListRef,
			T returnTypeRef,
			int functionKind,
			boolean isPure);

	/** Initialize an action system instance */
	boolean initActionSystemInstance(
			T instance,
			T typeRef,
			String name,
			int numOfCreatedObjs,
			T parentInstanceRef);

	/** Initialize an action system type */
	boolean initActionSystemType(
			T typeId,
			T identifierRef,
			boolean anonymousType,
			T baseTypeRef,
			T parentScopeRef,
			T doOdBlockRef,
			T symTab,
			T objectsListRef,
			T derivedObjectsListRef,
			boolean autoConstruction,
			boolean isInSystemDescription);

	/** Initialize a null-type */
	boolean initNullType(
			T typeId,
			T identifierRef,
			boolean anonymousType);

	/** Initialize a skip statement */
	boolean initSkipStatement(
			T stmnt,
			int line,
			int col);

	/** Initialize a break statement */
	boolean initBreakStatement(
			T stmnt,
			int line,
			int col);

	/** Initialize an abort statement */
	boolean initAbortStatement(
			T stmnt,
			int line,
			int col);

	/** Initialize a nondet block */
	boolean initNondetBlock(
			T block,
			int line,
			int col,
			T symTabRef,
			T stmtListRef,
			T scopeRef);

	/** Initialize a nondet block */
	boolean initSeqBlock(
			T block,
			int line,
			int col,
			T symTabRef,
			T stmtListRef,
			T scopeRef,
			T filterExprRef);

	/** Initialize a nondet block */
	boolean initPrioBlock(
			T block,
			int line,
			int col,
			T symTabRef,
			T stmtListRef,
			T scopeRef);

	/** Initialize a guarded command */
	boolean initGuardedCommand(
			T stmt,
			int line,
			int pos,
			T scopeRef,
			T guardExprRef,
			T bodyRef);

	/** Initialize an assignment statement */
	boolean initAssignment(
			T stmt,
			int line,
			int pos,
			T scopeRef,
			T nonDetExprRef,
			T placeExprListRef,
			T valueExprListRef,
			T symTabRef);

	/** Initialize a call expression */
	boolean initCall(
			T stmt,
			int line,
			int pos,
			T callExprRef);

	/** Initialize a type expression */
	boolean initTypeExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T referredTypeRef);

	/** Initialize an identifier expression */
	boolean initIdentifierExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T identifierRef,
			boolean isSelf);

	/** Initialize a unary operator */
	boolean initUnaryExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T child);

	/** Initialize a binary expression */
	boolean initBinaryExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T left,
			T right);

	/** Initialize a ternary expression */
	boolean initTernaryExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T left,
			T mid,
			T right,
			T defScopeRef);

	/** Initialize an IntValue expression */
	boolean initIntValueExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			int value);

	/** Initialize a BoolValue expression */
	boolean initBoolValueExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			boolean value);

	/** Initialize a RefValue expression */
	boolean initNullValueExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef);

	/** Initialize a ListConstructor expression */
	boolean initListConstructor(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T exprList,
			T symTab,
			T parentScope,
			T comprehension,
			boolean hasComprehension);

	/** Initialize a SetConstructor expression */
	boolean initSetConstructor(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T exprList,
			T symTab,
			T parentScope,
			T comprehension,
			boolean hasComprehension);

	/** Initialize a TupleConstructor expression */
	boolean initTupleConstructor(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T exprList,
			T tupleTypeId,
			boolean isMatcher);

	/** Initialize an access expression */
	boolean initAccessExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T left,
			T right);

	/** Initialize a tuple/map access expression */
	boolean initTupleMapAccessExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T child,
			T argument);

	/** Initialize a tuple/map access expression */
	boolean initCallExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T child,
			T argumentList,
			T scopeRef);

	/** Initialize a quantifier expression */
	boolean initQuantifierExpression(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T child,
			T symTabRef,
			T scopeRef);

	/** Initialize an object constructor expression */
	boolean initObjectConstructor(
			T expr,
			int line,
			int pos,
			T typeRef,
			T callTargetsIdentifierListRef,
			T symbTabRef,
			T instanceList,
			int currentInstance,
			String name);


	/** Sets the top level structure of the AST - the main module. */
	void setMainModule(MainModule mainModule, T id);
}
