fez-lisp 1.0.38 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -171,7 +171,7 @@ console.log(
171
171
  Pass tree source as text:
172
172
 
173
173
  ```js
174
- import { fez, parse } from '../index.js'
174
+ import { fez } from '../index.js'
175
175
  const source = `(|>
176
176
  (array 1 2 3 4)
177
177
  (math:permutations)
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { evaluate } from './src/interpreter.js'
2
- import { parse, stringify, AST } from './src/parser.js'
2
+ import { LISP, AST } from './src/parser.js'
3
3
  import { fez, tree } from './src/utils.js'
4
4
  import std from './lib/baked/std.js'
5
5
  import { keywords } from './src/tokeniser.js'
6
6
  import { WORD, APPLY, ATOM, VALUE, TYPE } from './src/enums.js'
7
7
  const types = { WORD, APPLY, ATOM, VALUE, TYPE }
8
- export { fez, parse, stringify, keywords, evaluate, std, types, tree, AST }
8
+ export { fez, keywords, evaluate, std, types, tree, LISP, AST }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "fez-lisp",
3
3
  "description": "Lisp interpreted & compiled to JavaScript",
4
4
  "author": "AT290690",
5
- "version": "1.0.38",
5
+ "version": "1.0.39",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/formatter.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { APPLY, ATOM, KEYWORDS, TYPE, VALUE, WORD } from './enums.js'
2
- import { isLeaf, parse } from './parser.js'
2
+ import { isLeaf, LISP } from './parser.js'
3
3
  import { removeNoCode } from './utils.js'
4
4
  const tops = []
5
5
  const indent = (level) => ' '.repeat(level)
@@ -70,7 +70,7 @@ export const formatWithPreservedComments = (source) => {
70
70
  )
71
71
  .join('\n')
72
72
 
73
- return format(parse(removeNoCode(value)))
73
+ return format(LISP.parse(removeNoCode(value)))
74
74
  .split('\n')
75
75
  .map((x) => {
76
76
  if (x.includes(commentIdentifier)) {
package/src/parser.js CHANGED
@@ -2,55 +2,57 @@ import { APPLY, ATOM, WORD } from './enums.js'
2
2
  import { escape } from './utils.js'
3
3
  export const leaf = (type, value) => [type, value]
4
4
  export const isLeaf = ([car]) => car === APPLY || car === ATOM || car === WORD
5
- export const parse = (source) => {
6
- const tree = []
7
- let head = tree,
8
- stack = [tree],
9
- acc = ''
10
- for (let i = 0; i < source.length; ++i) {
11
- const cursor = source[i]
12
- if (cursor === '"') {
13
- acc += '"'
14
- ++i
15
- while (source[i] !== '"') {
16
- if (source[i] === '\\') acc += escape(source[++i])
17
- else acc += source[i]
5
+ export const LISP = {
6
+ parse: (source) => {
7
+ const tree = []
8
+ let head = tree,
9
+ stack = [tree],
10
+ acc = ''
11
+ for (let i = 0; i < source.length; ++i) {
12
+ const cursor = source[i]
13
+ if (cursor === '"') {
14
+ acc += '"'
18
15
  ++i
16
+ while (source[i] !== '"') {
17
+ if (source[i] === '\\') acc += escape(source[++i])
18
+ else acc += source[i]
19
+ ++i
20
+ }
19
21
  }
22
+ if (cursor === '(') {
23
+ head.push([])
24
+ stack.push(head)
25
+ head = head.at(-1)
26
+ } else if (cursor === ')' || cursor === ' ') {
27
+ let token = acc
28
+ acc = ''
29
+ if (token) {
30
+ if (!head.length) head.push(leaf(APPLY, token))
31
+ else if (token.match(/^"([^"]*)"/))
32
+ head.push(leaf(ATOM, token.substring(1, token.length - 1)))
33
+ else if (token.match(/^-?[0-9]\d*(\.\d+)?$/))
34
+ head.push(leaf(ATOM, Number(token)))
35
+ else head.push(leaf(WORD, token))
36
+ }
37
+ if (cursor === ')') head = stack.pop()
38
+ } else acc += cursor
20
39
  }
21
- if (cursor === '(') {
22
- head.push([])
23
- stack.push(head)
24
- head = head.at(-1)
25
- } else if (cursor === ')' || cursor === ' ') {
26
- let token = acc
27
- acc = ''
28
- if (token) {
29
- if (!head.length) head.push(leaf(APPLY, token))
30
- else if (token.match(/^"([^"]*)"/))
31
- head.push(leaf(ATOM, token.substring(1, token.length - 1)))
32
- else if (token.match(/^-?[0-9]\d*(\.\d+)?$/))
33
- head.push(leaf(ATOM, Number(token)))
34
- else head.push(leaf(WORD, token))
35
- }
36
- if (cursor === ')') head = stack.pop()
37
- } else acc += cursor
40
+ return tree
41
+ },
42
+ stringify: (ast) => {
43
+ if (ast == undefined) return '()'
44
+ else if (typeof ast === 'object')
45
+ if (Array.isArray(ast))
46
+ return ast.length ? `(array ${ast.map(stringify).join(' ')})` : '()'
47
+ else
48
+ return `(array ${ast
49
+ .map(([key, value]) => `("${key}" ${stringify(value)})`)
50
+ .join(' ')})`
51
+ else if (typeof ast === 'string') return `"${ast}"`
52
+ else if (typeof ast === 'function') return '()'
53
+ else if (typeof ast === 'boolean') return +ast
54
+ else return ast
38
55
  }
39
- return tree
40
- }
41
- export const stringify = (ast) => {
42
- if (ast == undefined) return '()'
43
- else if (typeof ast === 'object')
44
- if (Array.isArray(ast))
45
- return ast.length ? `(array ${ast.map(stringify).join(' ')})` : '()'
46
- else
47
- return `(array ${ast
48
- .map(([key, value]) => `("${key}" ${stringify(value)})`)
49
- .join(' ')})`
50
- else if (typeof ast === 'string') return `"${ast}"`
51
- else if (typeof ast === 'function') return '()'
52
- else if (typeof ast === 'boolean') return +ast
53
- else return ast
54
56
  }
55
57
  export const AST = {
56
58
  parse: (source) => {
package/src/tokeniser.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import std from '../lib/baked/std.js'
2
2
  import { TYPE, VALUE, WORD, KEYWORDS, APPLY } from './enums.js'
3
3
  import { evaluate, isAtom } from './interpreter.js'
4
- import { stringify } from './parser.js'
4
+ import { LISP } from './parser.js'
5
5
  import {
6
6
  isEqual,
7
7
  isEqualTypes,
@@ -990,14 +990,16 @@ const keywords = {
990
990
  ? console.log(
991
991
  '\x1b[31m',
992
992
  `${describe} Failed:\n`,
993
- `${rest[0]} => ${stringify(rest[1])} != ${stringify(rest[2])}`,
993
+ `${rest[0]} => ${LISP.stringify(rest[1])} != ${LISP.stringify(
994
+ rest[2]
995
+ )}`,
994
996
  '\n',
995
997
  '\x1b[0m'
996
998
  )
997
999
  : console.log(
998
1000
  '\x1b[32m',
999
1001
  `${describe} Passed:\n`,
1000
- `${rest[0]} => ${stringify(rest[1])}`,
1002
+ `${rest[0]} => ${LISP.stringify(rest[1])}`,
1001
1003
  '\n',
1002
1004
  '\x1b[0m'
1003
1005
  )
@@ -1017,7 +1019,7 @@ const keywords = {
1017
1019
  `Invalid number of arguments for (${KEYWORDS.SERIALISE})`
1018
1020
  )
1019
1021
  const data = evaluate(args[0], env)
1020
- return stringify(data)
1022
+ return LISP.stringify(data)
1021
1023
  },
1022
1024
  [KEYWORDS.SET_ARRAY]: (args, env) => {
1023
1025
  if (args.length !== 2 && args.length !== 3)
package/src/utils.js CHANGED
@@ -2,7 +2,7 @@ import std from '../lib/baked/std.js'
2
2
  import { comp } from './compiler.js'
3
3
  import { APPLY, KEYWORDS, TYPE, VALUE, WORD } from './enums.js'
4
4
  import { run } from './interpreter.js'
5
- import { AST, isLeaf, parse } from './parser.js'
5
+ import { AST, isLeaf, LISP } from './parser.js'
6
6
  export const logError = (error) => console.log('\x1b[31m', error, '\x1b[0m')
7
7
  export const logSuccess = (output) => console.log(output, '\x1b[0m')
8
8
  export const removeNoCode = (source) =>
@@ -142,21 +142,6 @@ export const treeShake = (ast, libs) => {
142
142
  // Filter out libraries that are not in the visited set
143
143
  return libs.filter((x) => visited.has(x.at(1)[VALUE]))
144
144
  }
145
-
146
- export const runFromCompiled = (source) => {
147
- const tree = parse(
148
- handleUnbalancedQuotes(handleUnbalancedParens(removeNoCode(source)))
149
- )
150
- const compiled = comp(tree)
151
- const JavaScript = `${compiled.top}${compiled.program}`
152
- return eval(JavaScript)
153
- }
154
- export const runFromInterpreted = (source, env = {}) => {
155
- const tree = parse(
156
- handleUnbalancedQuotes(handleUnbalancedParens(removeNoCode(source)))
157
- )
158
- run(tree, env)
159
- }
160
145
  export const dfs = (tree, callback) => {
161
146
  if (!isLeaf(tree)) for (const leaf of tree) dfs(leaf)
162
147
  else callback(tree)
@@ -174,7 +159,7 @@ export const fez = (source, options = {}) => {
174
159
  else code = removeNoCode(source)
175
160
  if (!options.mutation) code = removeMutation(code)
176
161
  if (!code.length && options.throw) throw new Error('Nothing to parse!')
177
- const parsed = parse(code)
162
+ const parsed = LISP.parse(code)
178
163
  if (parsed.length === 0 && options.throw)
179
164
  throw new Error(
180
165
  'Top level expressions need to be wrapped in a (do) block'
@@ -292,10 +277,12 @@ export const decompress = (raw) => {
292
277
  for (const tok of runes) result += tok
293
278
  return result
294
279
  }
295
- // shake(parse(removeNoCode(source)), std)
280
+ // shake(LISP.parse(removeNoCode(source)), std)
296
281
  export const shake = (parsed, std) => [...treeShake(parsed, std), ...parsed]
297
282
  export const tree = (source, std) =>
298
- std ? shake(parse(removeNoCode(source)), std) : parse(removeNoCode(source))
283
+ std
284
+ ? shake(LISP.parse(removeNoCode(source)), std)
285
+ : LISP.parse(removeNoCode(source))
299
286
  export const lispToJavaScriptVariableName = (name) =>
300
287
  toCamelCase(
301
288
  arrowFromTo(