/ src / terms.js
terms.js
 1  import * as API from './api.js'
 2  import * as Variable from './variable.js'
 3  import * as Bytes from './data/bytes.js'
 4  import * as Link from './data/link.js'
 5  import * as Constant from './constant.js'
 6  
 7  /**
 8   * @param {API.Terms|API.Term[]|undefined} source
 9   * @returns {Iterable<API.Variable>}
10   */
11  export function* variables(source) {
12    if (source == null) {
13      return
14    } else if (Variable.is(source)) {
15      yield source
16    } else if (Array.isArray(source)) {
17      if (!Bytes.is(source)) {
18        for (const term of source) {
19          if (Variable.is(term)) {
20            yield term
21          }
22        }
23      }
24    } else if (!Link.is(source)) {
25      for (const term of Object.values(source)) {
26        if (Variable.is(term)) {
27          yield term
28        }
29      }
30    }
31  }
32  
33  /**
34   * @param {API.Terms|API.Term[]} terms
35   * @returns {string}
36   */
37  export const toDebugString = (terms) => {
38    if (Variable.is(terms)) {
39      return Variable.toDebugString(terms)
40    } else if (Constant.is(terms)) {
41      return Constant.toDebugString(terms)
42    } else if (Array.isArray(terms)) {
43      const chunks = terms.map(toDebugString)
44      const line = `[${chunks.join(', ')}]`
45      if (line.length < 80) {
46        return line
47      } else {
48        return `[\n  ${chunks.join(',\n  ')}\n]`
49      }
50    } else {
51      const chunks = Object.entries(terms).map(
52        ([key, value]) => `${toKey(key)}: ${toDebugString(value)}`
53      )
54  
55      const line = `{ ${chunks.join(', ')} }`
56      if (line.length < 80) {
57        return line
58      } else {
59        return `{\n  ${chunks.join(',\n  ')}\n}`
60      }
61    }
62  }
63  
64  /**
65   * @param {API.Terms|API.Term[]} terms
66   * @returns {API.Scalar|object}
67   */
68  export const toJSON = (terms) => {
69    if (Variable.is(terms)) {
70      return Variable.toJSON(terms)
71    } else if (Constant.is(terms)) {
72      return Constant.toJSON(terms)
73    } else if (Array.isArray(terms)) {
74      return terms.map(toJSON)
75    } else {
76      return Object.fromEntries(
77        Object.entries(terms).map(([key, value]) => [key, toJSON(value)])
78      )
79    }
80  }
81  
82  /**
83   * @param {string} key
84   */
85  const toKey = (key) => (/^[a-zA-Z_]\w*$/.test(key) ? key : JSON.stringify(key))