Patch title: Release 84 bulk changes
Abstract:
File: /pliant/language/compiler/expression/expression.page
Key:
    Removed line
    Added line
title "Pliant compiler expressions"

para
  [You need to include module] ; fixed [ /pliant/language/compiler.pli] ; [ when using Expression data type.[lf]]
  [See ] ; link "pliant computing mechanism" "../tutorial/overview" ; [ for a general introduction on meta-programming]

para
  [Some of the methods are defined in ] ; link "expression.c" "expression.c"
  [ and others are defined in ] ; link "expression1.pli" "expression1.pli"
  [, ] ; link "expression2.pli" "expression2.pli"
  [ and ] ; link "expression3.pli" "expression3.pli"

para
  [Fields in the] ; fixed [ Expression ] ; [data type:]
  table columns 3
    cell bold:[Field name] ; cell bold:[Type] ; cell bold:[Content]

    cell fixed:[value] ; cell fixed:[Arrow] ; cell [Points to the content of the expression provided by the parser. If you see the expressions tree as a graph, this is the label of the node.]
    cell fixed:[arguments] ; cell fixed:[Array] ; cell [Pointers to the sub expressions]
    cell fixed:[module] ; cell fixed:[Link Module] ; cell [Points to the module which the expression belongs to (the module defines the context in which the expression is going to be compiled)]
    cell fixed:[position] ; cell fixed:[Str] ; cell [A string describing where the expression is in the source code (name of the module plus line and column number)]
    cell fixed:[instructions] ; cell fixed:[List] ; cell [The list of instructions generated by the compiling mechanism]
    cell fixed:[result] ; cell fixed:[Link Argument] ; cell [Points to the argument that contains the expression result when the instructions have been executed]
    cell fixed:[access] ; cell fixed:[Int] ; cell [The access rights on the result]
    cell
      fixed [cast_level]
    cell
      fixed [Int]
    cell
     [The number of successive casting that have been performed to the result to get a result with the requested type[lf]] ; bold [Do not use]
    cell
      fixed [operator]
    cell
      fixed [ParserOperator]
    cell
      [used by the parser to store the operator that will fold the expression at the end of the parsing process[lf]] ; bold [Do not use]
    cell
      fixed [close_operator_name]
    cell
      fixed [Str]
    cell
      [used by the parser to check that operators such as () or {} are nested properly[lf]] ; bold [Do not use]
    cell
      fixed [error_message]
    cell
      fixed [Str]
    cell
      [Used to keep an error message that has been cleared, in order to pick it back at the end if the function fails to compile[lf]] ; bold [Do not use]


header "Checking and changing the expression status"

  para
    listing
      method `e ¤ident -> `id
        arg Expression `e ; arg Str `id
  para
    [If the expression value is an identifier, then the identifier is returned, converted to string, elsewhere an empty string is returned.]

  para
    listing
      method `e ¤is_pure_ident -> `id
        arg Expression `e ; arg CBool `id
  para
    [Returns true if the expression value is an identifier and the expression as no subexpressions (] ; fixed [arguments ] ; [field size is 0).]

  para
    listing
      method `e ¤is_compiled -> `c
        arg Expression `e ; arg CBool `
  para
    [Test if the expression has already been compiled.]

  para
    listing
      method `e ¤compile
        arg Expression `e
  para
    [Asks Pliant engine to compile the expression if it is not done yet.]

  para
    listing
      method `e ¤compile_as¤ `e2 -> `success
        arg_rw Expression `e `e2 ; arg CBool `success
  para
    ['e2' is considered as a rewritten version of 'e', so tries to compile 'e2' and if success, then use the instructions and result as the way to compile 'e' (for more details, see example at the end of this document)]

  note "there are more complicated versions available"

    para
      listing
        method `e ¤compile_step2
          arg_rw Expression `e
    para
      [Attempts to compile the expression just as method] ; fixed [ compile ] ; [would do, but do not set error message if compiling fails.]

    para
      listing
        function `e ¤compile_step3
          arg_rw Expression `e
    para
      [If the expression fails to compile, method ] ; fixed [ compile_step2 ] ; [ or] ; fixed [ compile ] ; [ would attempt to rearrange it a bit, then retry before surrendering whereas] ; fixed [ compile_step3 ] ; [will not.]

    para
      listing
        function `e ¤compile_step4 `value `access
          arg_rw Expression `e ; arg address `value ; arg Int `access
    para
      [Same as] ; fixed [ compile_step3 ] ; [method, but consider that the parsing content of the expression is stored at 'address' and has 'access' access rights rather than assuming that it's address is in the ] ; fixed [ value ] ; [field and that it is a constant.]

  para
    listing
      method `e ¤constant `wished_type -> `address
        arg Expression `e ; arg Type `wished_type ; arg address `address
  para
    [First attempts to compile the expression if not done yet, then attempt to cast the result to the desired type. If the result is a constant then return it's address, elsewhere returns null.]

  para
    listing
      method `e ¤execute
        arg Expression `e
  para
    [Attempts to compile, then generate code, and finally execute the code.]

  para
    listing
      method `e ¤evaluate `value
        arg Expression `e ; arg address `value
  para
    [Attempts to compile, then generate code, and finally execute the code. On return, 'value' points to a constant which is the computed result.]


header "Casting"

  para
    listing
      method `e ¤cast `wished_type -> `success
        arg Expression `e ; arg Type `wished_type ; arg CBool `success
  para
    [First attempts to compile the expression if not done yet, then attempt to cast the result to the desired type.[lf]]
    bold [Common mistake: ] ; [Casting an expression will often add instructions to the instructions list, so if you intend to suckup the expression, then you have to ask for the cast before calling] ; fixed [ suckup ] ; [method.[lf]]

  para
    listing
      method `e ¤explicit_cast `t -> `success
        arg_rw Expression `e ; arg Type `t ; arg CBool `success
  para
    [Try to cast the expression to type ] ; italic [t] ; [[lf]]
    [Please read ] ; link "Pliant casting mechanism" "../type/casting" ; [ for a general introduction on Pliant casting rules]

  note "there is also a more complicated versions available"

    para
      listing
        method `e ¤cast `result `access_rights `wished_type `filter_bits -> `new_argument
          arg Expression `e ; arg Argument `result ; arg Int `access_rights ; arg Type `wished_type ; arg Int `filter_bits ; arg_RW Argument `new_argument
    para
      ['result' and 'access_rights' are considered to be the current result and access rights on the result (the] ; fixed [ result ] ; [and] ; fixed [ access ] ; [fields in the expression are ignored)[lf]]
    para
      [only functions that have one bit set which is also set in 'filter_bits' can be used to archive the casting:[lf]]
      [10h allows implicit casting functions[lf]]
      [20h allows extension casting functions[lf]]
      [40h allows reduction casting functions[lf]]
      [on the other hand, if 'filter_bits' is 0, all casting functions are allowed[lf]]
    para
      [if the casting succeeds, then a pointer the the new expression result is returned, elsewhere 'new_argument' will map null.]


header "manually compiling the expression"

  para
    listing
      method `e ¤add `i
        arg_rw Expression `e ; arg Instruction `i
  para
    [add instruction 'i' at the end of the instructions list of 'e'.]

  para
    listing
      method `e ¤suckup `sub
        arg_rw Expression `e ; arg Expression `sub
  para
    [add all instructions in the 'sub' instructions list at the end of the instructions list of 'e'.]

  para
    listing
      method `e ¤set_void_result
        arg_rw Expression `e
  para
    [Defines that the expression is an instruction (it as no result, which is meant by attaching the constant of type] ; fixed [ Void ] ; [as the result)]

  para
    listing
      method `e ¤set_result `result `access_rights
        arg_rw Expression `e ; arg Argument `result ; arg Int `access_rights
  para
    [Attaches the 'result' to the expression.[lf]]
    [For the 'access_rights' argument, use either] ; fixed [ access_read ] ; [or] ; fixed [ access_read_write] ; [.]

  para
    [An expression is considered to be successfully compiled when a result as been attached to it. So the basic way to compile an expression is to call method] ; fixed [ add ] ; [or] ; fixed [ suckup ] ; [several times to attach the various instructions, then either call] ; fixed [ set_result ] ; [or] ; " set_void_result"


note "extra compiling methods that you will probably never need to use"

  para
    listing
      method `e ¤set_error `msg
        arg_rw Expression `e ; arg Str `msg
  para
    [Notify that the expression is not valid.[lf]]
    [When the expression does not look as expected by your meta programming function, you should return without calling] ; fixed [ set_error ] ; [method in most cases because another meta function could be satisfyed with it. If you set the error, no other function get a chance to compile the expression, so you bring polymorphism down.]
  
  para
    listing
      method `e ¤unset_error
        arg_rw Expression `e
  para
    [Clears the error condition on the expression.]


header "Selecting a sub expression"

  para
    listing
      method `e ¤size -> `s
        arg Expression `e ; arg_C Int `s
  para
    [Returns the number of sub expressions in the expression[lf]]
    [This is not the prototype of a real methods but indicates that you can also use] ; fixed [ size ] ; [method to change the number of sub expressions in the expression just like you can use] ; fixed [ size ] ; [method to resize a variable size array.]

  para
    listing
      method `e ¤'' `i -> `ei
        arg Expression `e ; arg Int `i ; arg_C Expression `ei
  para
    [Selects one of the subexpressions.[lf]]


header "Building expressions"

  para
    listing
      function ¤duplicate `e -> `e2
        arg Expression `e ; arg_RW Expression `e2
  para
    [Duplicates the expression and it's sub expressions and returns a pointer to the copy.]

  para
    listing
      function ¤expression ... -> `e
        arg_RW Expression `e
    [Builds a new expression.[lf]]
    [This are the various parameters that may appear in an 'expression' function:]
    table columns 2
      cell
        listing
          ¤duplicate `original
      cell
        [The ] ; italic [original] ; [ expression will be copyed and used as the basis for the new one.]
      cell
        listing
          ¤map `existing
      cell
        [The ] ; italic [existing] ; [ expression will be modifyed by subsequent parameters and a pointer on it will be return.]
      cell
        listing
          ¤immediat `body
      cell
        [The ] ; italic [body] ; [ expression will be copyed and used as the basis for the new expression. The 'body' parameter is not evaluated: the raw expression provided by the parser is used.]
      cell
        listing
          ¤auto_rename
      cell
        [All identifiers in the expression that end with a '_' will be renamed in order to be unique. This is mainly used when the expression is constructed using the 'immediat' parameter.[lf]]
        [You can find an example in ] ; link "each.pli" "../../basic/each.pli"
      cell
        listing
          ¤ident `str
      cell
        [Sets the 'value' field of the expression (see at the beginning of the page) to an identifier 'str' provided as a string.]
      cell
        listing
          ¤constant `value
      cell
        [Sets the 'value' field of the expression (see at the beginning of the page) to the provided value.]
      cell
        listing
          ¤near `existing
      cell
        [All the subexpressions that are currently not linked to a module will be linked to the module to which ] ; italic [existing] ; [ is linked.]
      cell
        listing
          ¤subexpressions `parameters
      cell
        [All the remaining parameters are specifying the subexpressions of the new expression.]
        [each parameter can be either:]
        list
          item
            [another expression]
          item
            [a subset of the subexpressions of an expression.[lf]]
            [The subset is extracted using the method with the prototype given just under this table.]
      cell
        listing
          ¤substitute `identifier `expression
      cell
        [All the occurrences of the identifier will be replaced by a copy of the expression.]
        [The 'expression' may also be several sub-expressions specifyed using the method with the prototype given just under this table.[lf]]
        [Be awarded: only the occurrences of the identifier that are not yet linked to a module will be substituted, so if you used 'near' as a previous parameter the expression will not be modifyed ![lf]]
        [Now, the expression you provide for substitution, and all it's sub expressions must be already linked to a module.[lf]]
        [These constraints are expressed in order to avoid name clashes when several substitutions are performed. Moreover, they also apply for the 'insert' and 'remove' parameter listed below.[lf]]
      cell
        listing
          ¤insert `identifier `expression
      cell
        [A copy of 'expression' will be inserted in front of each of the occurrences of the identifier.[lf]]
        [Be awarded: only the occurrences of the identifier that are not yet linked to a module will considered, and the inserted expression(s) must be fully linked to some modules.]
      cell
        listing
          ¤remove `identifier
      cell
        [All the occurrences of the identifier will be removed.[lf]]
        [Be awarded: only the occurrences of the identifier that are not yet linked to a module will be removed.]
  
    listing
      function ¤'' `e `base `nb -> `range
        arg Expression `e ; arg Int `base `nb ; arg ExpressionRange `range

    [There are mainly three ways of building an expression:]
    list
      item [Copying an existing expression (duplicate) then modifying it]
      item [Using an expression provided as a constant (immediat) with identifiers that will be substituted using 'substitute' option]
      item [Building the expression from scratch (ident, an_ident or constant)]

    [This is an example taken from the user forum:]
    listing
      module "/pliant/v1.pli"
      module "/pliant/meta.pli"

      constant use_method 2

      meta foo e
        if e:size<>3
          return
        if use_method=1
          var Link:Expression call_titi :> expression ident "titi" subexpressions (duplicate e:0)
          var Link:Expression call_toto :> expression ident "toto" subexpressions call_titi
          var Link:Expression call_tutu :> expression ident "tutu" subexpressions (e 0 3)
          var Link:Expression all :> expression ident "{}" subexpressions call_toto call_tutu
          e compile_as all
        eif use_method=2
          e compile_as (expression immediat { toto titi:x ; tutu x y z } substitute x e:0 substitute y e:1 substitute z e:2)

      # sample usage

      function toto x
        arg Int x
        console x eol

      function titi x -> y
        arg Int x y
        y := x*x

      function tutu x y z -> t
        arg Int x y z t
        t := x+y+z

      console (foo 2 5 10) eol


  header "An example"
    [You can find an example of building a new expression in ]
    link "setfield.pli" "../../basic/setfield.pli"
    [ module which does the following:[lf]]
    para
      [Each time an expression such as:]
      table columns 2 border 0
        cell
          listing
            a size := 12
        cell
          image "figures/fig1.png"
      [is found, then it attempts to compile it as:]
      table columns 2 border 0
        cell
          listing
            a 'size :=' 12
        cell
          image "figures/fig2.png"


  para
    listing
      function ¤parse `string -> `e
        arg Str string ; arg Link:Expression Expression `e
    [The 'string' will be submitted to the parser and returned as an expression.]


header "Other methods for modifyed expressions"

  para
    listing
      method `e ¤'ident :=' `id
        arg_rw Expression `e ; arg Str `id

  para
    listing
      method `e ¤near `original
        arg_rw Expression `e ; arg Expression `original
 
  para
    listing
      method `e ¤auto_rename
        arg_rw Expression `e

  para
    listing
      method `e ¤substitute `id `value -> `newone
        arg_rw Expression `e ; arg Str `id ; arg Expression `value ; arg_RW Expression `newone

  para
    listing
      method `e ¤substitute `id `values
        arg_rw Expression `e ; arg Str `id ; arg ExpressionRange `values

  para
    listing
      method `e ¤insert `id `value
        arg_rw Expression `e ; arg Str `id ; arg Expression `value

  para
    listing
      method `e ¤remove `id
        arg_rw Expression `e ; arg Str `id
        
  [All these methods are called in order to modify the expression when you use the 'expression' function.]

  para
    listing
      ¤named_expression `label
        `body
    [is roughly equivalent to]
    listing
      var constant Expression label (expression immediat body)
    [but a more convenient notation for multi lines immediat expressions.]