Skip to content

Sources and Sinks

Nil Geisweiller edited this page Jul 22, 2026 · 29 revisions

In addition to mere pattern matching and rewrite, MM2 supports sources and sinks, processing that can take place at querying time, via sources, or rewrite time, via sinks. This can enable a variety of things such as

  • Reading or writing from/to a file.
  • Performing negative querying.
  • Counting results.
  • Hashing a collection of results.
  • Executing numerical operations.
  • Running WebAssembly routines.
  • And much more.

Additional, the user, if willing to delve into the Rust code, can implement its own sources and sinks.

Usage

To use sources, simply replace , by I (for input) in the pattern argument of the exec command. For example

TODO

To use sinks, simply replace , by O (for output) in the template argument of the exec command. For example

TODO

Both sources and sinks can be use within the same exec command. For example

TODO

The set of sources and sinks currently supported by MORK are listed below.

Sources

  • ACT: pattern match the content of an ACT (Arena Compact Tree) file. The usage is as follows

    (exec PRIORITY (I (ACT MY_ACT_FILENAME PATTERN) [OTHERSOURCES]) TEMPLATE)
    

    where MY_ACT_FILENAME is a symbol (not a string) representing the name without file extension of an ACT file expected to found under /dev/shm. For example the following MM2 code

    (: Z Nat)
    (exec 0 (, (: Z Nat)) (O (ACT zero (Put Z in there))))
    (exec 1 (I (ACT zero (Put $k in there))) (, (I have found $k)))
    

    saves (Put Z in there) in ACT format into /dev/shm/zero.act then reads it and adds (I have found Z) in the main space.

  • BTM: pattern match the content in memory (BTM stands for Bytes Trie Map). The usage is as follows

    (exec PRIORITY (I (BTM PATTERN) [OTHERSOURCES]) TEMPLATE)
    

    For example the following

    (R A)
    (R B)
    (exec 0 (I (BTM (R $x))) (, (S $x)))
    

    outputs

    (R A)
    (R B)
    (S A)
    (S B)
    
  • ==: only match equal terms. Usage is as follows

    (exec PRIORITY (I (== PATTERN1 PATTERN2) [OTHERSOURCES]) TEMPLATE))
    

    For example, the following

    (R A)
    (R B)
    (exec 0 (I (== (R $x) (R $y)) (, (E $x $y))
    

    outputs

    (R A)
    (R B)
    (E A A)
    (E B B)
    
  • !=: only match unequal terms. Usage is as follows

    (exec PRIORITY (I (!= PATTERN1 PATTERN2) [OTHERSOURCES]) TEMPLATE))
    

    For example, the following

    (R A)
    (R B)
    (exec 0 (I (!= (R $x) (R $y)) (, (D $x $y))
    

    outputs

    (R A)
    (R B)
    (D A B)
    (D B A)
    
  • DUP

Sinks

Let us begin by going over the set of sinks currently supported by MORK.

  • -

TODO

  • +

TODO

  • ACT: write content in an ACT (Arena Compact Tree) file. The usage is as follows

    (exec PRIORITY PATTERN (O (ACT MY_ACT_FILENAME TEMPLATE) [OTHERSINKS]))
    

    where MY_ACT_FILENAME is a symbol (not a string) representing the name without file extension of an ACT file expected to found under /dev/shm. For example the following MM2 code

    (: Z Nat)
    (exec 0 (, (: Z Nat)) (O (ACT zero (Put Z in there))))
    (exec 1 (I (ACT zero (Put $k in there))) (, (I have found $k)))
    

    saves (Put Z in there) in ACT format into /dev/shm/zero.act then reads it and adds (I have found Z) in the main space.

    Warning: the ACT sink will overwrite the content of a previous file of the same name.

  • PATHS

TODO

  • COUNT

TODO

  • SUM

TODO

  • pure: allows to evaluate a call tree of pure functions from a library of Rust functions. The usage is as follows
    (exec PRIORITY PATTERN (O (pure PURETEMPLATE VARIABLE CALLTREE) [OTHERSINKS]))
    
    where CALLTREE is the call tree of functions to evaluate, such that its result is bound to VARIABLE and is then placed in the space via PURETEMPLATE. For example, the following
    (input 0 (arg 2) (arg 0.5))
    (input 1 (arg 4) (arg 0.2))
    (exec 0
          (, (input $i (arg $x) (arg $y)))
          (O (pure (result $i $res) $res (f64_to_string (product_f64 (i64_as_f64 (i64_from_string $x)) (f64_from_string $y))))))
    
    outputs
    (result 0 1.0)
    (result 1 0.8)
    (input 0 (arg 2) (arg 0.5))
    (input 1 (arg 4) (arg 0.2))
    
    MORK comes with a large library of pure functions, including:
    • ifnz: non-zero conditional. Usages are as follows:
      (ifnz CONDITION then THEN)
      (ifnz CONDITION then THEN else ELSE)
      
      where CONDITION is a symbol than must contain non zeros (not the ASCII character 0 but the actual byte) in order to evaluate the THEN branch, or optionally the ELSE branch if it contains only zeros. In our tests THEN and ELSE must also be symbols. For instance
      (input 0 00)
      (input 1 12)
      (exec 0
            (, (input $i $x))
            (O (pure (result $i $y) $y (ifnz (i8_from_string $x) then NZero else Zero))))
      
      outputs
      (input 0 00)
      (input 1 12)
      (result 0 Zero)
      (result 1 NZero)
      
    • tuple: wraps a list of elements in an tuple. Usage is as follows:
      (tuple [ELEMENTi])
      
      where ELEMENTi can either be a function call subtree, a symbol or a quote. The quote is necessary when one wants to make a tuple of expressions without evaluating then. For instance (tuple R (' (S A)) (' (T B))) will output (R (S A) (T B)). Otherwise, without quotes, it will be discarded because S and T are not pure functions.
    • clamp_i8, clamp_i16, clamp_i32, clamp_i64, clamp_f32, clamp_f64: clamp the first argument to be within the closed interval defined by the second and third arguments. Usage is as follows:
      (clamp_NUMTYPE X Y Z)
      
      such that the result is equal to X if X is within [Y, Z], else Y if X <= Y or else Z if X >= Z. WARNING: be careful to have Y <= Z, otherwise it may crash MORK. For instance
      (input 1 2 5)
      (exec 0
            (, (input $x $y $z))
            (O (pure (clampFn $x $y $z $r)
                     $r
                     (i8_to_string (clamp_i8 (i8_from_string $x)
                                             (i8_from_string $y)
                                             (i8_from_string $z))))))
      
      outputs
      (input 1 2 5)
      (clampFn 1 2 5 2)
      
    • i8_one, i16_one, i32_one, i64_one, i128_one: instantiate an integer unit. Usage is:
      (NUMTYPE_one)
      
      For instance:
      (exec 0 (,) (O (pure (one $x) $x (i8_to_string (i8_one)))))
      
      outputs
      (one 1)
      
    • sum_i8, sum_i16, sum_i32, sum_i64, sum_i128, sum_f32, sum_f64: sum an arbitrary number of numbers. Usage is:
      (sum_NUMTYPE ARG1 ... ARGn)
      
      For instance:
      (exec 0 (,) (O (pure (three $x) $x (i8_to_string (sum_i8 (i8_one) (i8_one) (i8_one))))))
      
      outputs
      (three 3)
      
    • sub_i8, sub_i16, sub_i32, sub_i64, sub_i128, sub_f32, sub_f64: subtract two numbers. Usage is:
      (sub_NUMTYPE ARG1 ARG2)
      
      For instance:
      (exec 0 (,) (O (pure (two $x) $x (i8_to_string (sub_i8 (i8_from_string 3) (i8_one))))))
      
      outputs
      (two 2)
      

Clone this wiki locally