~kylep/pipes

6c45b4b1e7b8fc32fcebec4998705d1492a84272 — Kyle Perik 2 months ago 678af22
Complete conditions, boolean ops, refactor
1 files changed, 30 insertions(+), 28 deletions(-)

M src/runtime.js
M src/runtime.js => src/runtime.js +30 -28
@@ 15,7 15,7 @@ function checkMatch (data, match, refs=[]) {
      name: match.value, value: data
    }]) }
  } else if (match.type === OBJ) {
    if (typeof data !== 'object') {
    if (!data || typeof data !== 'object') {
      return false
    }
    return Object.keys(match.value).reduce((r, key) => {


@@ 72,20 72,24 @@ function handleOp(result, refs, defs) {
    sub: (a, b) => a - b,
    mul: (a, b) => a * b,
    div: (a, b) => a / b,
    // TODO: check equality by value, not by reference
    eq: (a, b) => a === b,
    gt: (a, b) => a > b,
    lt: (a, b) => a < b,
    gte: (a, b) => a >= b,
    lte: (a, b) => a <= b,
    and: (a, b) => a && b,
    or: (a, b) => a || b,
  }[result.op]
  const id = {
    add: 0, sub: 0, mul: 1, div: 1
  }
  if (!func) {
    throw new Error(`Operation not recognized: ${result.op}`)
  }
  return result.operands.map(
    operand => buildResult(operand, refs, defs)
  ).reduce((r, v) => {
    return r.flatMap(result => v.flatMap(
      value => func(value, result)
    ))
  }, [id[result.op]])
  const allOperands = buildResult(result.operands, refs, defs)
  const val = allOperands.flatMap(([a, ...rest]) => {
    // This doesn't make sense to reduce for many operations, oops
    return rest.reduce(func, a)
  })
  return val
}

function buildResult (result, refs, defs) {


@@ 151,6 155,14 @@ function handlePipe (data, pipe, definitions) {
    if (!match.matched) {
      return []
    }
    if (pipe.condition) {
      const condition = buildResult(pipe.condition, match.refs, definitions)
      // Just check if there is any returned scenario which is strictly true
      // Sidestep js truthy weirdness
      if (!condition.some(c => c === true)) {
        return []
      }
    }
    return buildResult(pipe.result, match.refs, definitions)
  }
  throw new Error(`Pipe type not recognized: ${pipe.type}`)


@@ 159,30 171,20 @@ function handlePipe (data, pipe, definitions) {
function getOpDef (op) {
  return {
    type: PATTERN,
    match: {
      type: LIST,
      value: [
        { type: REF, value: 'a' },
        { type: REF, value: 'b' },
      ]
    },
    match: { type: REF, value: 'operands' },
    result: {
      type: OP,
      op,
      operands: [
        { type: REF, value: 'a' },
        { type: REF, value: 'b' },
      ]
      operands: { type: REF, value: 'operands' }
    }
  }
}

const standardDefinitions = {
  add: [[getOpDef('add')]],
  sub: [[getOpDef('sub')]],
  mul: [[getOpDef('mul')]],
  div: [[getOpDef('div')]],
}
const standardDefinitions = [
  'add', 'sub', 'mul', 'div',
  'eq', 'gt', 'lt', 'gte',
  'and', 'or'
].reduce((r, op) => ({...r, [op]: [[getOpDef(op)]]}), {})

// Run a payload through the program
function send (data, patterns, definitions) {