module php/reflect/version5/main
imports
  php/reflect/version5/php5-environment
  php/reflect/version5/function
  php/reflect/version5/class
  php/reflect/version5/interface

strategies
  /**
   * Creates a new php-environment and stores it.
   * It is assumed that the given document is the main 
   * AST.
   *
   * @param Doc, the new to be added.
   * @type Document-AST -> PHPEnvironment
   */
  init-php5-environment(|doc) =
      where(env := <new-php5-environment>)
    ; fill-php5-environment(|env,doc)
    ; <set-main-ast(|doc)> env
    ; set-php5-environment(|env)
    ; !env

  /**
   * Fills a given PHP5 environment with the information of
   * the given AST. It stores this environment and returns the
   * new environment.
   *
   * @param env The environment to be filled
   * @param doc The documents AST to be analyzed
   */
  fill-php5-environment(|env,doc) =
      <collect-php5-functions(|env)> doc
    ; <collect-php5-classes(|env)> doc
    ; <collect-php5-interfaces(|env)> doc
    ; set-php5-environment(|env)
    ; !env

  /**
   * Collects the function declerations from the current AST.
   * This does not include the functions declared within classes.
   *
   * @param PHPEnvironment
   */
  collect-php5-functions(|env) =
     collect-all-skip-classes(match-php5-function-decl)
    ; map({ast, fun:
        ?ast
        ; fun := <new-php5-function(|ast)>
        ; <add-function(|fun)> env
      })

  match-php5-function-decl =
        match-function-decl 
     <+ ?FunctionDecl(_,_,_,MethodBody(_))
     <+ ?FunctionDeclRef(_,_,_,MethodBody(_))

  /**
   * Collects the class declerations of the current AST.
   *
   * @param PHPEnvironment
   */
  collect-php5-classes(|env) =
      collect-all(match-php5-class-decl)
    ; map({ast, class:
        ?ast
        ; class := <new-php5-class(|ast)>
        ; <add-class(|class)> env
      })

  match-php5-class-decl =
     match-class-decl
  <+ ?Class(_,_,_,_,_)
  
  /**
   * Collects the interface declerations of the current AST.
   *
   * @param PHP5Environment
   */
  collect-php5-interfaces(|env) =
      collect-all(match-php5-interfaces-decl)
    ; map({ast, interface:
        ?ast
        ; interface := <new-php5-interface(|ast)>
        ; <add-interface(|interface)> env
      })

  match-php5-interfaces-decl =
      ?InterfaceDecl(_,_,_)

strategies
  /**
   * Returns the current environment if it is a PHP5
   * environment.
   *
   * @type _ -> PHP5Environment
   */
  get-php5-environment =
      get-php-environment
     ;instanceof-PHP5Environment

  /**
   * Sets the current environment to a PHP5
   * environment.
   *
   * @param env PHP5Environment
   */
  set-php5-environment(|env) =
     <instanceof-PHP5Environment> env
    ; set-php-environment(|env)