/******************************************************************************
 * Copyright (c) 2000-2021 Ericsson Telecom AB
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors:
 *   
 *   Baji, Laszlo
 *   Balasko, Jeno
 *   Baranyi, Botond
 *   Cserveni, Akos
 *   Czerman, Oliver
 *   Delic, Adam
 *   Knapp, Adam
 *   Forstner, Matyas
 *   Gecse, Roland
 *   Kovacs, Ferenc
 *   Raduly, Csaba
 *   Szabados, Kristof
 *   Szabo, Bence Janos
 *   Szabo, Janos Zoltan – initial implementation
 *   Szalai, Gabor
 *   Zalanyi, Balazs Andor
 *   Pandi, Krisztian
 *
 ******************************************************************************/
#ifndef _Common_AST_HH
#define _Common_AST_HH


#undef new
#include <new>
#include <set>
#include <string>
#include "../common/dbgnew.hh"
#include "../common/version.h"

#include "../common/ModuleVersion.hh"
#include "CompilerError.hh"
#include "Setting.hh"
#include "Type.hh"
#include "Value.hh"
#include "vector.hh"

namespace Ttcn {
  // not defined here
  class Template;
  class FormalParList;
  class ArrayDimensions;
  class Group;
  class Module;
} // namespace Ttcn

// not defined here
class JSON_Tokenizer;

/**
 * This namespace contains things used both in TTCN-3
 * and ASN.1 compiler.
 */
namespace Common {

  /**
   * \defgroup AST AST
   *
   * These classes provide a unified interface for language entities
   * present both in TTCN and ASN. (Most of) the classes defined here
   * are abstract, and have a descendant (with the same name) in the
   * namespaces Asn and Ttcn.
   *
   * @{
   */

  class Identifier;
  class Modules;
  class Module;
  class Assignments;
  class Assignment;
  class TypeConv;
  class CodeGenHelper;

  enum visibility_t {
    NOCHANGE, /* for parser usage only; default visibility */
    PUBLIC,   /* public visibility */
    PRIVATE,  /* private visibility */
    FRIEND    /* friend visibility */
  };

  /**
   * Class for storing modules.
   *
   * This is, in effect, the "root" of the AST: there is only one instance
   * of this class (declared in main.cc).
   */
  class Modules : public Node {
  private:
    /** Containers to store the modules. */
    vector<Module> mods_v;
    map<string, Module> mods_m;
    
    /** Contains info needed for delayed type encoding checks */
    struct type_enc_t {
      Type* t;
      Module* mod;
      bool enc;
    };
    static vector<type_enc_t> delayed_type_enc_v;

    /** Not implemented */
    Modules(const Modules& p);
    Modules& operator=(const Modules& p);
  public:
    /** The default constructor. */
    Modules();
    /** The destructor. */
    ~Modules();
    /** Not implemented: generates FATAL_ERROR */
    virtual Modules *clone() const;
    /** Adds a new module. The uniqueness of identifier is not checked. */
    void add_mod(Module *p_mod);
    /** Returns whether a module with the given \a modid exists. */
    bool has_mod_withId(const Identifier& p_modid);
    /** Gets the module with the given \a modid. Returns 0 if the
     *  module does not exist (w/o error message). See also:
     *  has_mod_withId */
    Module* get_mod_byId(const Identifier& p_modid);
    /** Returns the referenced assignment or 0 if it does not exist.
     *  Append an error message when necessary. */
    Assignment* get_ass_bySRef(Ref_simple *p_ref);
    /** Checks the uniqueness of module identifiers. Prints an error
     *  message if <tt>get_modid()</tt> returns the same for two
     *  modules. */
    void chk_uniq();
    /** Performs the semantic analysis on modules of the ATS.
     * Generates error/warning messages when necessary */
    void chk();
    void write_checksums();
    std::set<ModuleVersion> getVersionsWithProductNumber() const;
  private:
    /* Checks the ASN.1 top-level PDU types that were passed as command line
     * arguments */
    void chk_top_level_pdus();
  public:
    void generate_code(CodeGenHelper& cgh);
    void dump(unsigned level=1) const;
    
    /** Generates JSON schema segments for the types defined in the modules,
      * and references to these types. Information related to the types' 
      * JSON encoding and decoding functions is also inserted after the references.
      *
      * @param json JSON document containing the main schema, schema segments for 
      * the types will be inserted here
      * @param json_refs map of JSON documents containing the references and function
      * info related to each type */
    void generate_json_schema(JSON_Tokenizer& json, map<Type*, JSON_Tokenizer>& json_refs);
    
    /** Called if a Type::chk_coding() call could not be resolved (the check for
      * custom and PER coding requires the checks of all external functions to
      * be completed).
      * This stores the info needed to call the function again after everything
      * else has been checked. */
    static void delay_type_encode_check(Type* p_type, Module* p_module, bool p_encode);
  };

  /**
   * Interface-class to represent a module.
   *
   * Abstract class because of clone() and a bunch of other methods.
   */
  class Module : public Scope, public Location {
  public:
    enum moduletype_t { MOD_UNKNOWN, MOD_ASN, MOD_TTCN };
    /** The map is used as a set. */
    typedef map <Module*, void> module_set_t;
  protected: // *::Module need access
    moduletype_t moduletype;
    /** Module identifier ("module name") */
    Identifier *modid;
    /** The \c Modules collection which contains this module. Not owned. */
    /** Indicates whether the import list has been checked. */
    bool imp_checked;
    /** Indicates whether to generate C++ code for the module. */
    bool gen_code;
    /** Indicates whether the module has a checksum. */
    bool has_checksum;
    /** Contains the set of modules that are visible through imports (i.e. the
     * module is imported either directly or indirectly by an imported module).
     * The set is complete if \a this is added to the set. */
    module_set_t visible_mods;
    /** Contains the checksum (more correctly, a hash) of the module.
     *  It is an MD5 hash of the TTCN source, computed by the lexer. */
    unsigned char module_checksum[16];

    /** @name Containers to store string literals.
     *  @{ */
    map<string, string> bs_literals; ///< bitstring values
    map<string, string> bp_literals; ///< bitstring patterns
    map<string, string> hs_literals; ///< hexstring values
    map<string, string> hp_literals; ///< hexstring patterns
    map<string, string> os_literals; ///< octetstring values
    map<string, string> op_literals; ///< octetstring patterns
    map<string, string> cs_literals; ///< charstring values
    map<ustring, string> us_literals; ///< universal charstring values
    map<string, string> pp_literals; ///< padding patterns (RAW codec)
    map<string, string> mp_literals; ///< matching patterns (TEXT codec)
    /** @} */

    struct OID_literal {
      size_t nof_elems;
      string oid_id;
    };
    map<string, OID_literal> oid_literals;

    /** Counter for the temporary identifiers */
    size_t tmp_id_count;

    /** Control namespace and prefix.
     *  The module owns these strings. */
    char * control_ns;
    char * control_ns_prefix;

    /** Namespace declarations encountered (global for the entire program).
     *  Keys are the prefixes. Values are the URIs. */
    static map<string, const char> namespaces;

    /** The index of the replacement for the empty prefix, or -1. Returned by
     *  \p get_ns_index if the empty prefix has indeed been replaced. */
    static size_t replacement_for_empty_prefix;

    /** Namespace prefixes made up to avoid clashes.
     *  Keys are the URIs (!), values are the prefixes.
     *  (This is a reverse of a subset of the \p namespaces member).
     *  This allows reuse of made-up prefixes if the same namespace URI
     *  appears again. */
    static map<string, const char> invented_prefixes;

    /** Indexes of the namespaces used by this module.
     *  Written while Common::Type::generate_code_xerdescriptor() makes calls
     *  to Common::Module::get_ns_index(). */
    map<size_t, void> used_namespaces;

    /** How many different namespace URIs with empty prefix have been added */
    static size_t default_namespace_attempt;

    /** Type conversions found in this module */
    vector<TypeConv> type_conv_v;

    /** @name Module version fields
     *  @{ */
    char* product_number;
    unsigned int suffix;
    unsigned int release;
    unsigned int patch;
    unsigned int build;
    char* extra;
    enum version_t version_type;
    /** @} */

    friend class Ttcn::Module;

    /* * Value of GLOBAL-DEFAULTS MODIFIED-ENCODINGS */
    //TODO: introduce bool modified_encodings;

    /** Generates code for all string literals that belong to the
     *  module into \a target */
    void generate_literals(output_struct *target);
    /** Generates the module level entry functions based on
     * \a output->functions. The resulting functions are placed into
     * \a output->source.function_bodies.
     * Also writes the control part, module checksum, XML namespaces,
     * module object to output->source.global_vars */
    void generate_functions(output_struct *output);
    void generate_conversion_functions(output_struct *output);
    
    /** Generates the debugger initialization function for this module.
      * The function creates the global debug scope associated with this module,
      * and initializes it with all the global variables visible in the module
      * (including imported variables).
      * The debug scopes of all component types defined in the module are also
      * created and initialized with their variables. */
    virtual void generate_debugger_init(output_struct *output) = 0;
    
    /** Generates the variable adding code for all global variables defined
      * in this module. This function is called by generate_debugger_init()
      * for both the current module and all imported modules. */
    virtual char* generate_debugger_global_vars(char* str, Common::Module* current_mod) = 0;
    
    /** Generates the debugger variable printing function, which can print values
      * and templates of all types defined in this module (excluding subtypes). */
    virtual void generate_debugger_functions(output_struct *output) = 0;
    
  private:
    /** Copy constructor not implemented */
    Module(const Module& p);
    /** Assignment disabled */
    Module& operator=(const Module& p);

    /** Adds \a str to container \a literals with prefix \a prefix */
    static string add_literal(map<string, string>& literals, const string& str,
      const char *prefix);

    void generate_bs_literals(char *&src, char *&hdr);
    void generate_bp_literals(char *&src, char *&hdr);
    void generate_hs_literals(char *&src, char *&hdr);
    void generate_hp_literals(char *&src, char *&hdr);
    void generate_os_literals(char *&src, char *&hdr);
    void generate_op_literals(char *&src, char *&hdr);
    void generate_cs_literals(char *&src, char *&hdr);
    void generate_us_literals(char *&src, char *&hdr);
    void generate_oid_literals(char *&src, char *&hdr);
    void generate_pp_literals(char *&src, char *&hdr);
    void generate_mp_literals(char *&src, char *&hdr);

    /** Clears the container \a literals */
    static void clear_literals(map<string, string>& literals);

  public:
    Module(moduletype_t p_mt, Identifier *modid);
    virtual ~Module();
    /** Adds type conversion \p p_conv to this module.  */
    void add_type_conv(TypeConv *p_conv);
    /** Checks if \p p_from_type and \p p_to_type types need conversion in
     *  this module. */
    bool needs_type_conv(Type *p_from_type, Type *p_to_type) const;
    /** Returns the module type (either TTCN-3 or ASN.1). */
    moduletype_t get_moduletype() const {return moduletype;}
    /** Sets the flag to generate C++ code for this module. */
    void set_gen_code() {gen_code = true;}
    /** Returns whether to generate C++ code for this module. */
    bool get_gen_code() const {return gen_code;}
    /** Returns the module-identifier. */
    const Identifier& get_modid() const {return *modid;}
    /** Gets the module scope. This function returns this scope or a
     *  scope above this or 0 if neither is a Module. */
    virtual Module* get_scope_mod() {return this;}
    virtual Module* get_scope_mod_gen() {return this;}
    virtual Assignments *get_asss() =0;
    virtual Common::Assignment* importAssignment(
      const Identifier& p_source_modid, const Identifier& p_id) const =0;
    /** Returns true if a symbol with identifier \a p_id is
     *  exported. */
    virtual bool exports_sym(const Identifier& p_id) =0;
    /** Returns whether the module has an imported definition/assignment with
     * identifier \a p_id */
    virtual bool has_imported_ass_withId(const Identifier& p_id) = 0;
    /** Returns a pointer to the TTCN-3 special address type that is defined in
     * the TTCN-3 module. A NULL pointer is returned if the address type is not
     * defined in this module. This function is applicable to TTCN-3 modules
     * only (otherwise a FATAL_ERROR will occur). */
    virtual Type *get_address_type();
    /** Checks imports (and propagates the code generation
     *  flags). */
    virtual void chk_imp(ReferenceChain& refch, vector<Module>& moduleStack) = 0;
    /** Checks everything (imports, exports, assignments) */
    virtual void chk() = 0;
    /** Checks this module and all imported modules in bottom-up order.
     * Argument \a checked_modules contains the list of modules that are
     * already checked */
    void chk_recursive(module_set_t& checked_modules);
    /** Returns whether \a m is visible from \a this through imports. */
    bool is_visible(Module *m);
    /** Extends \a p_visible_mods with the set of visible modules. It uses the
     * cache \a visible_mods if possible or calls \a get_imported_mods()
     * otherwise. */
    void get_visible_mods(module_set_t& p_visible_mods);
    /** Walks through the import list and collects the imported modules into
         * \a p_imported_mods recursively. */
    virtual void get_imported_mods(module_set_t& p_imported_mods) = 0;
    void write_checksum();
    static char* get_product_identifier(const char* product_number,
        const unsigned int suffix, unsigned int release, unsigned int patch,
        unsigned int build, const char* extra=NULL, enum version_t version_type = UNKNOWN);
    ModuleVersion getVersion() const;
  protected: // *::Module need access
    /** Collects the set of visible modules into \a visible_mods. */
    void collect_visible_mods();
    virtual void generate_code_internal(CodeGenHelper& cgh) = 0;
  public:
    /** Adds a string to the module's bitstring container. Returns a
     *  string like "bs_xx", where xx is the index of the literal in
     *  the container. */
    inline string add_bitstring_literal(const string& bstr)
      { return add_literal(bs_literals, bstr, "bs_"); }
    inline string add_bitstring_pattern(const string& bpat)
      { return add_literal(bp_literals, bpat, "bp_"); }
    inline string add_hexstring_literal(const string& hstr)
      { return add_literal(hs_literals, hstr, "hs_"); }
    inline string add_hexstring_pattern(const string& hpat)
      { return add_literal(hp_literals, hpat, "hp_"); }
    inline string add_octetstring_literal(const string& ostr)
      { return add_literal(os_literals, ostr, "os_"); }
    inline string add_octetstring_pattern(const string& opat)
      { return add_literal(op_literals, opat, "op_"); }
    inline string add_charstring_literal(const string& cstr)
      { return add_literal(cs_literals, cstr, "cs_"); }
    inline string add_padding_pattern(const string& ppat)
      { return add_literal(pp_literals, ppat, "pp_"); }
    inline string add_matching_literal(const string& mpat)
      { return add_literal(mp_literals, mpat, "mp_"); }
    string add_ustring_literal(const ustring& ustr);
    string add_objid_literal(const string& oi_str, const size_t nof_elems);

    /** Sets the module checksum. Parameter \a checksum_ptr points to the
     * checksum to be set, which consists of \a checksum_len bytes. */
    void set_checksum(size_t checksum_len, const unsigned char* checksum_ptr);

    /** Returns an identifier used for temporary C++ objects,
     *  which is unique in the module */
    string get_temporary_id();

    /** Sets the control namespace and its prefix.
     * Any previous value is overwritten.
     * Takes ownership of the strings (must be allocated on the heap). */
    void set_controlns(char *ns, char *prefix);

    /** Gets the control namespace components.
     * The caller must not free the strings. */
    void get_controlns(const char * &ns, const char * &prefix);

    /** Adds a namespace to the list of known namespaces.
     *  No effect if the namespace is already in the map.
     *  @param new_uri namespace URI
     *  @param new_prefix namespace prefix; NULL means "make up a prefix"
     *  @note If \p new_prefix is empty and there is already a namespace with
     *  an empty prefix, a new, non-empty prefix is invented for this URI;
     *  in this case \p new_prefix is modified to contain the "made-up" value.
     *  @note \p new_prefix \b MUST be expstring_t or allocated by Malloc
     *  (add_namespace may call Free() on it) */
    static void add_namespace(const char *new_uri, char * &new_prefix);

    /** Returns the number of XML namespaces */
    static inline size_t get_nof_ns()
    { return namespaces.size(); }

    /** Return the index of the given namespace prefix in the list of namespaces.
     *  If the namespace is not found, FATAL_ERROR occurs.
     *  @note also records the index in the per-instance member used_namespaces
     *  (which is why it cannot be static) */
    size_t get_ns_index(const char *prefix);

    /** Rename the default namespace, but only if there were two or more
     *  namespaces with empty prefixes */
    static void rename_default_namespace();

    /** Generates C++ code for the module */
    void generate_code(CodeGenHelper& cgh);
    virtual void dump(unsigned level) const;
    
    /** Generates JSON schema segments for the types defined in the modules,
      * and references to these types. Information related to the types' 
      * JSON encoding and decoding functions is also inserted after the references.
      *
      * @param json JSON document containing the main schema, schema segments for 
      * the types will be inserted here
      * @param json_refs map of JSON documents containing the references and function
      * info related to each type */
    virtual void generate_json_schema(JSON_Tokenizer& json, map<Type*, JSON_Tokenizer>& json_refs) = 0;
  };

  /**
   * Class to store assignments.
   */
  class Assignments : public Scope {
  protected:  // Ttcn::Definitions and Asn::Assignments need access

    Assignments(const Assignments& p): Scope(p) {}
  public:
    /** Constructor. */
    Assignments() : Scope() {}

    virtual Assignments* get_scope_asss();
    /** Returns the referenced assignment or 0 if it does not exist.
     *  An error message is generated when necessary. */
    virtual Assignment* get_ass_bySRef(Ref_simple *p_ref);
    /** Returns whether an assignment with id \a p_id exists;
     * either in the current scope or its parent (recursively). */
    virtual bool has_ass_withId(const Identifier& p_id);
    /** Returns whether an assignment with id \a p_id exists.
     * Unlike \a has_ass_withId() this function does not look into the
     * parent scope. */
    virtual bool has_local_ass_withId(const Identifier& p_id) = 0;
    /** Returns the locally defined assignment with the given id,
     * or NULL if it does not exist. */
    virtual Assignment* get_local_ass_byId(const Identifier& p_id) = 0;
    /** Returns the number of assignments. Only the uniquely named
     *  assignments are visible. */
    virtual size_t get_nof_asss() = 0;
    /** Returns the assignment with the given index. Only the uniquely
     *  named assignments are visible. */
    virtual Assignment* get_ass_byIndex(size_t p_i, bool p_reordered = true) = 0;
  };
  
  enum param_eval_t {
    NORMAL_EVAL,
    LAZY_EVAL,
    FUZZY_EVAL
  };

  /**
   * Abstract class to represent different kinds of assignments.
   */
  class Assignment : public Node, public Location {
  public:
    enum asstype_t {
      A_TYPE,           /**< type */
      A_CONST,          /**< value (const) */
      A_UNDEF,          /**< undefined/undecided (ASN.1) */
      A_ERROR,          /**< erroneous; the kind cannot be deduced (ASN.1) */
      A_OC,             /**< information object class (ASN.1) */
      A_OBJECT,         /**< information object (ASN.1) */
      A_OS,             /**< information object set (ASN.1) */
      A_VS,             /**< value set (ASN.1) */
      A_EXT_CONST,      /**< external constant (TTCN-3) */
      A_MODULEPAR,      /**< module parameter (TTCN-3) */
      A_MODULEPAR_TEMP, /**< template module parameter */
      A_TEMPLATE,       /**< template (TTCN-3) */
      A_VAR,            /**< variable (TTCN-3) */
      A_EXCEPTION,      /**< exception (at the beginning of a catch block) (TTCN-3) */
      A_VAR_TEMPLATE,   /**< template variable, dynamic template (TTCN-3) */
      A_TIMER,          /**< timer (TTCN-3) */
      A_PORT,           /**< port (TTCN-3) */
      A_FUNCTION,       /**< function without return type (TTCN-3) */
      A_FUNCTION_RVAL,  /**< function that returns a value (TTCN-3) */
      A_FUNCTION_RTEMP, /**< function that returns a template (TTCN-3) */
      A_EXT_FUNCTION,   /**< external function without return type (TTCN-3) */
      A_EXT_FUNCTION_RVAL,  /**< ext. func that returns a value (TTCN-3) */
      A_EXT_FUNCTION_RTEMP, /**< ext. func that returns a template (TTCN-3) */
      A_ALTSTEP,        /**< altstep (TTCN-3) */
      A_TESTCASE,       /**< testcase (TTCN-3) */
      A_CONSTRUCTOR,    /**< constructor (TTCN-3) */
      A_PAR_VAL,        /**< formal parameter (value) (TTCN-3) */
      A_PAR_VAL_IN,     /**< formal parameter (in value) (TTCN-3) */
      A_PAR_VAL_OUT,    /**< formal parameter (out value) (TTCN-3) */
      A_PAR_VAL_INOUT,  /**< formal parameter (inout value) (TTCN-3) */
      A_PAR_TEMPL_IN,   /**< formal parameter ([in] template) (TTCN-3) */
      A_PAR_TEMPL_OUT,  /**< formal parameter (out template) (TTCN-3) */
      A_PAR_TEMPL_INOUT,/**< formal parameter (inout template) (TTCN-3) */
      A_PAR_TIMER,      /**< formal parameter (timer) (TTCN-3) */
      A_PAR_PORT        /**< formal parameter (port) (TTCN-3) */
    };
  protected: // Ttcn::Definition and Asn::Assignment need access
    asstype_t asstype;
    Identifier *id; /**< the name of the assignment */
    Scope *my_scope; /**< the scope this assignment belongs to */
    bool checked;
    visibility_t visibilitytype;

    /// Copy constructor disabled
    Assignment(const Assignment& p);
    /// Assignment disabled
    Assignment& operator=(const Assignment& p);
    virtual string get_genname() const = 0;
  public:
    Assignment(asstype_t p_asstype, Identifier *p_id);
    virtual ~Assignment();
    virtual Assignment* clone() const =0;
    virtual asstype_t get_asstype() const;
    /** Returns the string representation of the assignment type */
    const char *get_assname() const;
    /** Returns the description of the definition, which consists of the
     * assignment type and name. The name is either the fullname or only
     * the id. It depends on \a asstype and \a my_scope. */
    string get_description();
    /** Gets the id of the assignment. */
    const Identifier& get_id() const {return *id;}
    /** Sets the internal pointer my_scope to \a p_scope. */
    virtual void set_my_scope(Scope *p_scope);
    Scope* get_my_scope() const { return my_scope; }
    bool get_checked() const { return checked; }
    /** Return the visibility type of the assignment */
    visibility_t get_visibility() const { return visibilitytype; }
    /** Returns whether the definition belongs to a TTCN-3 statement block
     * (i.e. it is defined in the body of a function, testcase, altstep or
     * control part). */
    virtual bool is_local() const;
    /** @name Need to be overridden and implemented in derived classes.
     *  Calling these methods causes a FATAL_ERROR.
     *
     * @{
     */
    virtual Setting* get_Setting();
    virtual Type *get_Type();
    virtual Value *get_Value();
    virtual Ttcn::Template *get_Template();
    virtual param_eval_t get_eval_type() const;
    /** @} */
    /** Returns the formal parameter list of a TTCN-3 definition */
    virtual Ttcn::FormalParList *get_FormalParList();
    /** Returns the dimensions of TTCN-3 port and timer arrays or NULL
     * otherwise. */
    virtual Ttcn::ArrayDimensions *get_Dimensions();
    /** Returns the component type referred by the 'runs on' clause of a
     * TTCN-3 definition */
    virtual Type *get_RunsOnType();
    /** Returns the component type referred by the 'mtc' clause of a
     * TTCN-3 definition */
    virtual Type *get_MtcType();
    /** Returns the component type referred by the 'system' clause of a
     * TTCN-3 definition */
    virtual Type *get_SystemType();
    /** Returns the port type referred by the 'port' clause of a
     * TTCN-3 function definition */
    virtual Type *get_PortType();
    /** Semantic check */
    virtual void chk() = 0;
    /** Checks whether the assignment has a valid TTCN-3 identifier,
     *  i.e. is reachable from TTCN. */
    void chk_ttcn_id();
    /** Returns a string containing the C++ reference pointing to this
     * definition from the C++ equivalent of scope \a p_scope. The reference
     * is a simple identifier qualified with a namespace when necessary.
     * If \a p_prefix is not NULL it is inserted before the string returned by
     * function \a get_genname(). */
    string get_genname_from_scope(Scope *p_scope, const char *p_prefix = 0);
    /** Returns the name of the C++ object in the RTE that contains the common
     * entry points for the module that the definition belongs to */
    const char *get_module_object_name();
    /** A stub function to avoid dynamic_cast's. It causes FATAL_ERROR unless
     * \a this is an `in' value or template parameter. The real implementation
     * is in class Ttcn::FormalPar. */
    virtual void use_as_lvalue(const Location& p_loc);
    virtual void generate_code(output_struct *target, bool clean_up = false);
    virtual void generate_code(CodeGenHelper& cgh); // FIXME: this should be pure virtual
    virtual void dump(unsigned level) const;
    virtual Ttcn::Group* get_parent_group();
  };

  /** @} end of AST group */

} // namespace Common

#endif // _Common_AST_HH
