/**
 * @author Merijn de Jonge (mdjonge@cwi.nl)
 */
module stratego/gpp/PpTableIO

/**
 * @todo Fix this import (signature must be in library)
 */
imports
  pp-table
  libstratego-sglr

strategies

  /**
   * @type List(PpTable) -> HashTable
   */
  pptable-make-hashtable =
    where(tbl := <new-hashtable>)
    ; map(
        ?PP-Table(<id>)
        ; reverse
        ; map(pptable-desugar-entry; pptable-store-entry(|tbl))
      )
    ; !tbl

  pptable-store-entry(|tbl) =
     ?entry@PP-Entry(path, value)
     ; <hashtable-put(|<pptable-make-key> entry, (path, value))> tbl

/**
 * Pretty-printing of paths
 */
strategies

  /**
   * @type Path -> String
   */
  pptable-path-to-string = 
    ?Path1(<id>)

  /**
   * @type Path -> String
   */
  pptable-path-to-string =
    ?Path( s1, s2 )
    ; < map( \ selector(a,b) -> [".", <int-to-string>a,":", b] \ )
      ; concat
      > s2 => s3
    ; <concat-strings> [s1 | s3]

/**
 * Key of a pp entry.
 */
strategies

  /**
   * @type PP-Entry -> Key
   */
  pptable-make-key :
    PP-Entry(Path1(s), value) -> (arity, [s])
    where
      <pptable-arity-of-template> value => arity

  pptable-make-key :
    PP-Entry(Path(s1, s2), value) -> <reverse> [s1 | xs]
    where
      <map(?selector(<id>, _))> s2 =>  xs

  /**
   * Determines the arity of a template by collecting the Arg nodes.
   *
   * @type BOX -> Int
   */
  pptable-arity-of-template =
    collect(Arg(id)); length

/**
 * Desguaring of pp entries
 */
strategies
  
  pptable-desugar-entry =
    topdown(
      try(
        Arg(string-to-int)
      + Arg2(string-to-int, string-to-int)
      + S(un-double-quote; unescape)
      + selector(string-to-int, id)
      )
    )

/**
 * Access to the pp table
 */
strategies

  /**
   * Get an entry from the pp-table and log if the entry does not exist.
   */
  pptable-get-log(|tbl) =
    ?key
    ; ( <hashtable-get(|key)> tbl
        <+ log(|Error(),<concat-strings>["No pp entry found for: ",<write-to-string> key])
           ; fail)