Nested map references break when clauses aren't grouped by sub-interval

Issue #21 resolved
Sean Kauffman repo owner created an issue

This fails with null reference errors at runtime

D :- (A before B) unless contain C
  where A.id = B.id 
      & A.id = C.id
      & A.id = 2

But this works

D :- (A before B) unless contain C
  where A.id = B.id 
      & A.id = 2
      & A.id = C.id

The issue is in group_restrictions_per_bie in semantic.c, and the logic around determining when subexpressions can be referenced directly and when they can't.

Comments (4)

  1. Sean Kauffman reporter

    It seems that it might work to replace any Boolean clause that references another interval expression with “true”.

    Then the decomposed rules would be

    AbB :- A before B where A.id = B.id & true & A.id = 2 map { id -> A.id, abid -> true, atwo = true }
    D:- AbB unless contain C where AbB.abid & AbB.id = C.id & AbB.atwo
    

    The trick is first figuring out which clauses to replace and then only doing it in nested rules.

  2. Sean Kauffman reporter
    /**
     * An expression node may be affiliated with a BIE, multiple BIEs or it may be neutral.
     * For children of binary Boolean operators (&, |), the affiliation of the children determine
     * whether or not they are included in nested rules.
     *
     * If a child (left or right) is affiliated with the node or is neutral, then it is included.
     * If a child is affiliated with another BIE, then it is replaced with the appropriate Boolean so that
     * only the other side is considered in the calculation.
     * If a child is affiliated with multiple BIE, then if any of them match the current one the
     * child is included.  If none of them match, then the child is replaced with the appropriate Boolean.
     *
     * So, at generation time we need to know IF the BIE for any given sub-tree matches the current one.
     * This is inefficient to store, so we can instead just calculate it during generation.
     *
     * The pseudocode during expression generation is basically this:
     * if (binary_boolean_expression) {
     *     if (left side doesn't include any matches for this BIE) {
     *         if (&) write true
     *         if (|) write false
     *     } else {
     *         recurse down the left side
     *     }
     *     if (right side doesn't include any matches for this BIE) {
     *         if (&) write true
     *         if (|) write false
     *     } else {
     *         recurse down the right side
     *     }
     *     write the operator
     * }
     *
     * We don't need to check for neither side including matches because we won't reach this node if that
     * is the case.  We won't recurse down the tree.
     */
    
  3. Log in to comment