fez-lisp 1.6.27 → 1.6.28

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/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.6.27",
5
+ "version": "1.6.28",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
@@ -0,0 +1,165 @@
1
+ import { serialise } from '../editor/utils.js'
2
+ import {
3
+ APPLY,
4
+ ATOM,
5
+ KEYWORDS,
6
+ TYPE,
7
+ VALUE,
8
+ WORD,
9
+ TRUE,
10
+ FALSE,
11
+ STATIC_TYPES
12
+ } from './keywords.js'
13
+ import { isLeaf, LISP } from './parser.js'
14
+ const keywords = {
15
+ [KEYWORDS.REMAINDER_OF_DIVISION]: (args, env) =>
16
+ evaluate(args[0], env) % evaluate(args[1], env),
17
+ [KEYWORDS.DIVISION]: (args, env) =>
18
+ evaluate(args[0], env) / evaluate(args[1], env),
19
+ [KEYWORDS.ARRAY_LENGTH]: (args, env) => evaluate(args[0], env).length,
20
+ [KEYWORDS.IS_ATOM]: (args, env) =>
21
+ +(typeof evaluate(args[0], env) === 'number'),
22
+ [KEYWORDS.IS_LAMBDA]: (args, env) =>
23
+ +(typeof evaluate(args[0], env) === 'function'),
24
+ [KEYWORDS.ADDITION]: (args, env) =>
25
+ evaluate(args[0], env) + evaluate(args[1], env),
26
+ [KEYWORDS.MULTIPLICATION]: (args, env) =>
27
+ evaluate(args[0], env) * evaluate(args[1], env),
28
+ [KEYWORDS.SUBTRACTION]: (args, env) =>
29
+ evaluate(args[0], env) - evaluate(args[1], env),
30
+ [KEYWORDS.CREATE_ARRAY]: (args, env) =>
31
+ args.length ? args.map((x) => evaluate(x, env)) : [],
32
+ [KEYWORDS.GET_ARRAY]: (args, env) =>
33
+ evaluate(args[0], env)[evaluate(args[1], env)],
34
+ [KEYWORDS.BLOCK]: (args, env) =>
35
+ args.reduce((_, x) => evaluate(x, env), FALSE),
36
+ [KEYWORDS.NOT]: (args, env) => +!evaluate(args[0], env),
37
+ [KEYWORDS.EQUAL]: (args, env) =>
38
+ +(evaluate(args[0], env) === evaluate(args[1], env)),
39
+ [KEYWORDS.LESS_THAN]: (args, env) =>
40
+ +(evaluate(args[0], env) < evaluate(args[1], env)),
41
+ [KEYWORDS.GREATHER_THAN]: (args, env) =>
42
+ +(evaluate(args[0], env) > evaluate(args[1], env)),
43
+ [KEYWORDS.GREATHER_THAN_OR_EQUAL]: (args, env) =>
44
+ +(evaluate(args[0], env) >= evaluate(args[1], env)),
45
+ [KEYWORDS.LESS_THAN_OR_EQUAL]: (args, env) =>
46
+ +(evaluate(args[0], env) <= evaluate(args[1], env)),
47
+ [KEYWORDS.AND]: (args, env) =>
48
+ !evaluate(args[0], env) ? FALSE : evaluate(args[1], env),
49
+ [KEYWORDS.OR]: (args, env) =>
50
+ evaluate(args[0], env) ? TRUE : evaluate(args[1], env),
51
+ [KEYWORDS.CALL_FUNCTION]: (args, env) => evaluate(args.pop(), env)(args, env),
52
+ [KEYWORDS.DEFINE_VARIABLE]: (args, env) =>
53
+ (env[args[0][VALUE]] = evaluate(args[1], env)),
54
+ [KEYWORDS.BITWISE_AND]: (args, env) =>
55
+ evaluate(args[0], env) & evaluate(args[1], env),
56
+ [KEYWORDS.BITWISE_NOT]: (args, env) => ~evaluate(args[0], env),
57
+ [KEYWORDS.BITWISE_OR]: (args, env) =>
58
+ evaluate(args[0], env) | evaluate(args[1], env),
59
+ [KEYWORDS.BITWISE_XOR]: (args, env) =>
60
+ evaluate(args[0], env) ^ evaluate(args[1], env),
61
+ [KEYWORDS.BITWISE_LEFT_SHIFT]: (args, env) =>
62
+ evaluate(args[0], env) << evaluate(args[1], env),
63
+ [KEYWORDS.BITWISE_RIGHT_SHIFT]: (args, env) =>
64
+ evaluate(args[0], env) >> evaluate(args[1], env),
65
+ [KEYWORDS.IF]: (args, env) =>
66
+ evaluate(args[0], env) ? evaluate(args[1], env) : evaluate(args[2], env),
67
+ [KEYWORDS.LOOP]: (args, env) => {
68
+ while (evaluate(args[0], env) === TRUE) evaluate(args[1], env)
69
+ return -1
70
+ },
71
+ [KEYWORDS.SET_ARRAY]: (args, env) => {
72
+ const array = evaluate(args[0], env)
73
+ array[evaluate(args[1], env)] = evaluate(args[2], env)
74
+ return array
75
+ },
76
+ [KEYWORDS.POP_ARRAY]: (args, env) => {
77
+ const array = evaluate(args[0], env)
78
+ array.pop()
79
+ return array
80
+ },
81
+ [KEYWORDS.ANONYMOUS_FUNCTION]: (args, env) => {
82
+ const params = args.slice(0, -1)
83
+ return (props = [], scope) => {
84
+ const localEnv = Object.create(env)
85
+ for (let i = 0; i < props.length; ++i)
86
+ localEnv[params[i][VALUE]] = evaluate(props[i], scope)
87
+ return evaluate(args.at(-1), localEnv)
88
+ }
89
+ },
90
+ // Only for type checking
91
+ [STATIC_TYPES.UNKNOWN]: (args, env) => evaluate(args[0], env),
92
+ [STATIC_TYPES.ANY]: (args, env) => evaluate(args[0], env),
93
+
94
+ [STATIC_TYPES.ATOM]: (args, env) => evaluate(args[0], env),
95
+ [STATIC_TYPES.ABSTRACTION]: (args, env) => evaluate(args[0], env),
96
+ [STATIC_TYPES.COLLECTION]: (args, env) => evaluate(args[0], env),
97
+
98
+ [STATIC_TYPES.BOOLEAN]: (args, env) => evaluate(args[0], env),
99
+ [STATIC_TYPES.NUMBER]: (args, env) => evaluate(args[0], env),
100
+ [STATIC_TYPES.NUMBERS]: (args, env) => evaluate(args[0], env),
101
+ [STATIC_TYPES.COLLECTIONS]: (args, env) => evaluate(args[0], env),
102
+ [STATIC_TYPES.ABSTRACTIONS]: (args, env) => evaluate(args[0], env),
103
+ [STATIC_TYPES.BOOLEANS]: (args, env) => evaluate(args[0], env)
104
+ }
105
+ const debugStack = []
106
+ const evaluate = (exp, env = keywords) => {
107
+ const [head, ...tail] = isLeaf(exp) ? [exp] : exp
108
+ if (head == undefined) return []
109
+ const type = head[TYPE]
110
+ const value = head[VALUE]
111
+ let res
112
+ switch (type) {
113
+ case WORD:
114
+ res = env[value]
115
+ return res
116
+ case APPLY:
117
+ res = env[value](tail, env)
118
+ if (
119
+ value !== KEYWORDS.BLOCK &&
120
+ value !== KEYWORDS.CALL_FUNCTION &&
121
+ value !== KEYWORDS.ANONYMOUS_FUNCTION &&
122
+ value !== KEYWORDS.DEFINE_VARIABLE
123
+ ) {
124
+ // debugStack.push(
125
+ // `\x1b[31m${LISP.source(exp)}\x1b[32m\n${
126
+ // typeof res === 'function' ? '(lambda)' : serialise(res)
127
+ // }\x1b[0m`
128
+ // )
129
+ const out = typeof res === 'function' ? '(lambda)' : serialise(res)
130
+ if (debugStack.at(-1)?.result !== out)
131
+ debugStack.push({
132
+ function: value,
133
+ source: LISP.source(exp),
134
+ result: out
135
+ })
136
+ // else debugStack[debugStack.length - 1].src += LISP.source(exp)
137
+ }
138
+ return res
139
+ case ATOM:
140
+ res = value
141
+ return res
142
+ }
143
+ }
144
+ export const debugStackToString = (stack) =>
145
+ stack.map(({ source, result }) => `${source}\n${result}`).join('\n')
146
+ export const startDebug = (ast, speed = 250, start, end) => {
147
+ debugStack.length = 0
148
+ evaluate(ast)
149
+ start = start ? debugStack.findIndex(start) : 0
150
+ end = end ? debugStack.findIndex(end) : debugStack.length
151
+ const stack = debugStack.slice(start, end).reverse()
152
+ if (speed !== 0) {
153
+ const rec = () => {
154
+ setTimeout(() => {
155
+ if (stack.length) {
156
+ const { source, result } = stack.pop()
157
+ console.log(`\x1b[31m${source}\x1b[32m\n${result}\x1b[0m`)
158
+ rec()
159
+ }
160
+ }, speed)
161
+ }
162
+ rec()
163
+ }
164
+ return stack
165
+ }
package/src/utils.js CHANGED
@@ -26,6 +26,7 @@ import {
26
26
  withCtxTypes
27
27
  } from './types.js'
28
28
  import { compile } from './compiler.js'
29
+ import { startDebug } from './debugger.js'
29
30
  export const logError = (error) =>
30
31
  console.log('\x1b[31m', `\n${error}\n`, '\x1b[0m')
31
32
  export const logSuccess = (output) => console.log('\x1b[32m', output, '\x1b[0m')
@@ -365,6 +366,7 @@ export const isInputVariable = (x) =>
365
366
  x[1][VALUE] === 'INPUT'
366
367
 
367
368
  export const UTILS = {
369
+ startDebug,
368
370
  handleUnbalancedQuotes,
369
371
  handleUnbalancedParens,
370
372
  logError,
@@ -529,6 +531,13 @@ export const fez = (ast, c = false) => {
529
531
 
530
532
  export const toTypedAst = (ast, userDefinedTypes) => {
531
533
  try {
534
+ const typeSet = (Types, name, env, exp) => {
535
+ Types.set(withScope(name, env), () => {
536
+ if (exp.at(-1)[TYPE] !== FLAG) exp.push(formatAstTypes(name, env))
537
+ else exp[exp.length - 1] = formatAstTypes(name, env)
538
+ return ''
539
+ })
540
+ }
532
541
  const types = typeCheck(
533
542
  ast,
534
543
  withCtxTypes(
@@ -539,19 +548,14 @@ export const toTypedAst = (ast, userDefinedTypes) => {
539
548
  }
540
549
  : definedTypes(filteredDefinedTypes(ast, std, stdT))
541
550
  ),
542
- (Types, name, env, exp) => {
543
- Types.set(withScope(name, env), () => {
544
- if (exp.at(-1)[TYPE] !== FLAG) exp.push(formatAstTypes(name, env))
545
- else exp[exp.length - 1] = formatAstTypes(name, env)
546
- return ''
547
- })
548
- }
551
+ typeSet
549
552
  )
550
553
  for (const v of types[1].values()) v()
551
554
  // types[0][1][1].slice(1)
552
555
  return types
553
556
  } catch (error) {
554
557
  logError(error.message)
558
+ return []
555
559
  }
556
560
  }
557
561
  export const atst = (ast, ctx) => toTypedAst(ast, ctx)[0]