~kylep/pipes

c6e4a82f20dbfde4eb60768caade0a861799e076 — Kyle Perik 2 months ago 8b74386
Refactoring parse, modify syntax
4 files changed, 92 insertions(+), 73 deletions(-)

M src/device.js
M src/main.js
M src/parser.js
M src/runtime.js
M src/device.js => src/device.js +2 -2
@@ 31,7 31,7 @@ function initDevices () {
  })
  function frame () {
    try {
      processEvent(['tick', null])
      // processEvent(['tick', null])
    } catch (e) {
      console.error(e)
    }


@@ 92,10 92,10 @@ function draw (element) {

function handle (event) {
  // console.log({event})
  eventLog.push(event)
  if (!Array.isArray(event)) {
    return
  }
  eventLog.push(event)
  const [type, value] = event;
  if (type === 'log') {
    logOutput(JSON.stringify(value))

M src/main.js => src/main.js +9 -9
@@ 146,33 146,33 @@ const programJson = {
}
const initialProgramText = `
def input {
  ? ['input', value] : value;
  ['input', value, s]: value;
}
def log {
  ? value : ['log', value];
  value: ['log', value];
}
def draw {
  ? element : ['draw', element];
  element: ['draw', element];
}
def mousemove {
  ? ['mousemove', value] : value;
  ['mousemove', value, s]: value;
}

| input | (
  ? 'marco' : 'polo' | log;
input | (
  'marco': 'polo' | log;

  ? 'circle': {
  'circle': {
    type: 'circle',
    radius: 30,
    pos: { x: 30, y: 30 }
  } | draw;

  ? 'clear' : {
  'clear': {
    type: 'clear'
  } | draw;
);

| mousemove ? pos : {
mousemove | pos : {
  type: 'circle',
  radius: 3,
  pos

M src/parser.js => src/parser.js +81 -61
@@ 166,65 166,107 @@ function parsePatternFragment (group) {
  }
}

function processPipeToken (r, tokens) {
  if (tokens.length !== 1) {
    console.error(r)
    throw Error(`Only one token allowed for pipe: ${JSON.stringify(tokens)}`)
  }
  token = tokens[0]
  if (typeof token === 'object') {
    if (token.type === 'parens') {
      return {
        ...r,
        mode: 'pending',
        pendingPatterns: r.pendingPatterns.concat([
          {
            type: GROUP,
            patterns: parseGroups(token.tokens).patterns
          }
        ])
      }
    }
  }
  return {
    ...r,
    mode: 'pending',
    pendingPatterns: r.pendingPatterns.concat([{
      type: REF,
      value: token
    }])
  }
}

function processPatternMatch(r, tokens) {
  if (tokens.length !== 1) {
    console.error(r)
    throw Error(`Only one token allowed for pattern results: ${JSON.stringify(tokens)}`)
  }
  token = tokens[0]
  return {
    ...r,
    mode: 'pending',
    match: null,
    pendingPatterns: r.pendingPatterns.concat([{
      type: PATTERN,
      match: r.match,
      result: parsePatternFragment(token)
    }]),
  }
}

function parseGroups (tokenGroups) {
  const result = tokenGroups.reduce((r, token) => {
    if (!r.mode) {
      if (token === '?') {
        return {
          ...r,
          mode: 'match',
        }
      } else if (token === 'def') {
      if (token === 'def') {
        return {
          ...r,
          mode: 'define'
        }
      } else if (token === '|') {
      } else {
        return {
          ...r,
          mode: 'pipe',
          pendingTokens: r.pendingTokens.concat([token]),
          mode: 'pending'
        }
      }
    } else if (r.mode === 'building') {
      if (token === ';') {
        return {
          ...r,
          mode: null,
          pendingPatterns: [],
          patterns: r.patterns.concat([r.pendingPatterns])
    } else if (r.mode === 'pending') {
      if (token === '|') {
        let result;
        if (r.match) {
          result = processPatternMatch(r, r.pendingTokens)
        } else {
          result = processPipeToken(r, r.pendingTokens)
        }
      } else if (token === '?') {
        if (result) {
          return { ...result, pendingTokens: [] }
        }
      } else if (token === ':') {
        return {
          ...r,
          mode: 'match',
          mode: 'pending',
          pendingTokens: [],
          match: parsePatternFragment(r.pendingTokens[0]),
        }
      } else if (token === ';') {
        let result;
        if (r.match) {
          result = processPatternMatch(r, r.pendingTokens)
        } else {
          result = processPipeToken(r, r.pendingTokens)
        }
      } else if (token === '|') {
        return {
          ...r,
          mode: 'pipe',
          ...result,
          mode: null,
          pendingTokens: [],
          pendingPatterns: [],
          patterns: result.patterns.concat([result.pendingPatterns])
        }
      }
    } else if (r.mode === 'pipe') {
      if (typeof token === 'object' && token.type === 'parens') {
      } else {
        return {
          ...r,
          mode: 'building',
          pendingPatterns: r.pendingPatterns.concat([
            {
              type: GROUP,
              patterns: parseGroups(token.tokens).patterns
            }
          ])
          pendingTokens: r.pendingTokens.concat([token]),
        }
      }
      return {
        ...r,
        mode: 'building',
        pendingPatterns: r.pendingPatterns.concat([{
          type: REF,
          value: token
        }])
      }
    } else if (r.mode === 'define') {
      if (!r.key) {
        return {


@@ 243,35 285,13 @@ function parseGroups (tokenGroups) {
        definitions: newDefinitions,
        mode: null
      }
    } else if (r.mode === 'match') {
      if (token === ':') {
        return {
          ...r,
          mode: 'result'
        }
      } else {
        return {
          ...r,
          match: parsePatternFragment(token)
        }
      }
    } else if (r.mode === 'result') {
      return {
        ...r,
        mode: 'building',
        match: null,
        pendingPatterns: r.pendingPatterns.concat([{
          type: PATTERN,
          match: r.match,
          result: parsePatternFragment(token)
        }]),
      }
    }
    throw new Error(`Unexpected token for mode: ${JSON.stringify(token)}, ${r.mode}`)
  }, {
    patterns: [],
    definitions: {},
    pendingPatterns: [],
    pendingTokens: [],
    mode: null
  })
  let patterns = result.patterns

M src/runtime.js => src/runtime.js +0 -1
@@ 8,7 8,6 @@ const GROUP = 'group'
const PATTERN = 'pattern'

function checkMatch (data, match, refs=[]) {
  // console.log({data, match})
  if (match.type === LIT) {
    return { matched: match.value === data, refs: refs }
  } else if (match.type === REF) {