fez-lisp 1.6.89 → 1.6.90
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/lib/baked/std-T.js +1 -1
- package/lib/baked/std.js +1 -1
- package/package.json +1 -1
- package/src/check.js +105 -19
- package/src/compiler.js +11 -12
- package/src/enhance.js +0 -6
- package/src/keywords.js +0 -1
- package/src/macros.js +15 -2
- package/src/parser.js +0 -3
- package/src/types.js +0 -21
- package/src/utils.js +7 -4
package/package.json
CHANGED
package/src/check.js
CHANGED
@@ -614,27 +614,108 @@ const IfApplyBranch = ({
|
|
614
614
|
return setPropToReturn(ref[STATS], prop, branch[STATS])
|
615
615
|
}
|
616
616
|
}
|
617
|
+
|
618
|
+
const validateIfMatchingBranches = (
|
619
|
+
concequent,
|
620
|
+
alternative,
|
621
|
+
env,
|
622
|
+
exp,
|
623
|
+
re,
|
624
|
+
name
|
625
|
+
) => {
|
626
|
+
let A = null
|
627
|
+
let B = null
|
628
|
+
switch (concequent[TYPE]) {
|
629
|
+
case ATOM:
|
630
|
+
A = [ATOM, NUMBER_SUBTYPE()]
|
631
|
+
break
|
632
|
+
case WORD:
|
633
|
+
if (concequent[VALUE] === NIL) return
|
634
|
+
if (env[concequent[VALUE]]) A = env[concequent[VALUE]][STATS][TYPE_PROP]
|
635
|
+
break
|
636
|
+
case APPLY:
|
637
|
+
if (concequent[VALUE] !== name && env[concequent[VALUE]])
|
638
|
+
if (concequent[VALUE] === KEYWORDS.CREATE_ARRAY) {
|
639
|
+
A = initArrayType({ rem: re[0], env })[RETURNS]
|
640
|
+
} else if (concequent[VALUE] === KEYWORDS.IF && re[0][2]) {
|
641
|
+
const conc = isLeaf(re[0][2]) ? re[0][2] : re[0][2][0]
|
642
|
+
validateIfMatchingBranches(
|
643
|
+
conc,
|
644
|
+
alternative,
|
645
|
+
env,
|
646
|
+
exp,
|
647
|
+
isLeaf(re[0]) ? re[0].slice(2) : re[0].slice(2),
|
648
|
+
name
|
649
|
+
)
|
650
|
+
} else A = env[concequent[VALUE]][STATS][RETURNS]
|
651
|
+
break
|
652
|
+
}
|
653
|
+
switch (alternative[TYPE]) {
|
654
|
+
case ATOM:
|
655
|
+
B = [ATOM, NUMBER_SUBTYPE()]
|
656
|
+
break
|
657
|
+
case WORD:
|
658
|
+
if (alternative[VALUE] === NIL) return
|
659
|
+
if (env[alternative[VALUE]]) B = env[alternative[VALUE]][STATS][TYPE_PROP]
|
660
|
+
break
|
661
|
+
case APPLY:
|
662
|
+
if (alternative[VALUE] !== name && env[alternative[VALUE]])
|
663
|
+
if (alternative[VALUE] === KEYWORDS.CREATE_ARRAY) {
|
664
|
+
B = initArrayType({ rem: re[1], env })[RETURNS]
|
665
|
+
} else if (alternative[VALUE] === KEYWORDS.IF && re[1][2]) {
|
666
|
+
const alt = isLeaf(re[1][2]) ? re[1][2] : re[1][2][0]
|
667
|
+
validateIfMatchingBranches(
|
668
|
+
concequent,
|
669
|
+
alt,
|
670
|
+
env,
|
671
|
+
exp,
|
672
|
+
isLeaf(re[1]) ? re[1].slice(2) : re[1].slice(2),
|
673
|
+
name
|
674
|
+
)
|
675
|
+
} else B = env[alternative[VALUE]][STATS][RETURNS]
|
676
|
+
break
|
677
|
+
}
|
678
|
+
if (
|
679
|
+
A === null ||
|
680
|
+
B === null ||
|
681
|
+
A[0] === UNKNOWN ||
|
682
|
+
B[0] === UNKNOWN ||
|
683
|
+
A[0] === ANY ||
|
684
|
+
B[0] === ANY
|
685
|
+
)
|
686
|
+
return
|
687
|
+
if (
|
688
|
+
A[0] !== B[0] ||
|
689
|
+
(isSubType(A[1]) && isSubType(B[1]) && !A[1].isMatching(B[1]))
|
690
|
+
) {
|
691
|
+
throw new TypeError(
|
692
|
+
`(if) needs to have matching concequent and alternative branches but got (${formatSubType(
|
693
|
+
A
|
694
|
+
)}) and (${formatSubType(B)}) (${stringifyArgs(exp)}) (check #1005)`
|
695
|
+
)
|
696
|
+
}
|
697
|
+
}
|
617
698
|
const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
|
618
|
-
|
619
|
-
|
699
|
+
const conc = isLeaf(re[0]) ? re[0] : re[0][0]
|
700
|
+
const alt = isLeaf(re[1]) ? re[1] : re[1][0]
|
701
|
+
const concequent = env[conc[VALUE]]
|
702
|
+
const alternative = env[alt[VALUE]]
|
703
|
+
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
704
|
+
setPropToAtom(ref[STATS], prop)
|
705
|
+
}
|
620
706
|
// TODO check that both branches are predicates if one is
|
621
707
|
else {
|
622
|
-
const conc = isLeaf(re[0]) ? re[0] : re[0][0]
|
623
|
-
const alt = isLeaf(re[1]) ? re[1] : re[1][0]
|
624
|
-
const concequent = env[conc[VALUE]]
|
625
|
-
const alternative = env[alt[VALUE]]
|
626
|
-
|
627
708
|
// TODO make this more simple - it's so many different things just because types are functions or not
|
628
709
|
// WHY not consider making return types for everything
|
629
710
|
if (concequent)
|
630
711
|
if (conc[TYPE] === WORD) {
|
631
|
-
|
712
|
+
setPropToTypeRef(ref[STATS], prop, concequent[STATS])
|
632
713
|
} else if (
|
633
714
|
conc[TYPE] === APPLY &&
|
634
715
|
getType(concequent[STATS]) === APPLY &&
|
635
716
|
// Making sure the recursive function don't look for their own return type
|
636
717
|
concequent[STATS][SIGNATURE] !== ref[STATS][SIGNATURE]
|
637
|
-
)
|
718
|
+
)
|
638
719
|
IfApplyBranch({
|
639
720
|
leaf: conc,
|
640
721
|
branch: concequent,
|
@@ -646,16 +727,15 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
|
|
646
727
|
exp,
|
647
728
|
check
|
648
729
|
})
|
649
|
-
|
650
|
-
if (alternative) {
|
730
|
+
if (alternative)
|
651
731
|
if (alt[TYPE] === WORD) {
|
652
|
-
|
732
|
+
setPropToTypeRef(ref[STATS], prop, alternative[STATS])
|
653
733
|
} else if (
|
654
734
|
alt[TYPE] === APPLY &&
|
655
735
|
getType(alternative[STATS]) === APPLY &&
|
656
736
|
// Making sure the recursive function don't look for their own return type
|
657
737
|
alternative[STATS][SIGNATURE] !== ref[STATS][SIGNATURE]
|
658
|
-
)
|
738
|
+
)
|
659
739
|
IfApplyBranch({
|
660
740
|
leaf: alt,
|
661
741
|
branch: alternative,
|
@@ -667,9 +747,8 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
|
|
667
747
|
exp,
|
668
748
|
check
|
669
749
|
})
|
670
|
-
}
|
671
|
-
}
|
672
750
|
}
|
751
|
+
validateIfMatchingBranches(conc, alt, env, exp, re, ref[STATS][SIGNATURE])
|
673
752
|
}
|
674
753
|
const resolveCondition = ({ rem, name, env, exp, prop, stack, check }) => {
|
675
754
|
const ret = rem[0]
|
@@ -958,8 +1037,13 @@ const initArrayTypeRec = ({ rem, env }) =>
|
|
958
1037
|
x[TYPE] === ATOM ? NUMBER_SUBTYPE() : new SubType([UNKNOWN])
|
959
1038
|
]
|
960
1039
|
else if (env[x[0][VALUE]])
|
961
|
-
if (x.length > 1 &&
|
1040
|
+
if (x.length > 1 && x[0][VALUE] === KEYWORDS.CREATE_ARRAY)
|
962
1041
|
return initArrayTypeRec({ rem: x, env })
|
1042
|
+
else if (
|
1043
|
+
x.length > 1 &&
|
1044
|
+
env[x[0][VALUE]][STATS][RETURNS][0] === COLLECTION
|
1045
|
+
)
|
1046
|
+
return [getReturns(env[x[0][VALUE]][STATS])]
|
963
1047
|
else if (GET_ARRAY_INFERENCE_SET.has(x[0][VALUE])) {
|
964
1048
|
const res = resolveGetterRec(x, env)
|
965
1049
|
if (!res) return [UNKNOWN]
|
@@ -2114,7 +2198,7 @@ export const typeCheck = (
|
|
2114
2198
|
(x) => isGenericType(x[STATS]) || isGenericReturn(x[STATS])
|
2115
2199
|
)
|
2116
2200
|
) {
|
2117
|
-
const
|
2201
|
+
const genericRecursiveDecent = (ref) => {
|
2118
2202
|
if (isGenericReturn(ref[STATS])) {
|
2119
2203
|
const [index, multiplier] = ref[STATS][RETURNS][2]
|
2120
2204
|
const desiredTypeIndex = env[first[VALUE]][STATS][
|
@@ -2229,7 +2313,8 @@ export const typeCheck = (
|
|
2229
2313
|
expected[STATS][TYPE_PROP].length = 2
|
2230
2314
|
}
|
2231
2315
|
}
|
2232
|
-
if (expected[STATS][ARGUMENTS].length)
|
2316
|
+
if (expected[STATS][ARGUMENTS].length)
|
2317
|
+
genericRecursiveDecent(expected)
|
2233
2318
|
}
|
2234
2319
|
}
|
2235
2320
|
const copy = Object.create(env)
|
@@ -2240,7 +2325,7 @@ export const typeCheck = (
|
|
2240
2325
|
}
|
2241
2326
|
copy[newName][STATS][SIGNATURE] = newName
|
2242
2327
|
|
2243
|
-
|
2328
|
+
genericRecursiveDecent(copy[newName])
|
2244
2329
|
|
2245
2330
|
const cexp = structuredClone(exp)
|
2246
2331
|
copy[newName][STATS].source = structuredClone(
|
@@ -2260,6 +2345,7 @@ export const typeCheck = (
|
|
2260
2345
|
}
|
2261
2346
|
}
|
2262
2347
|
}
|
2348
|
+
|
2263
2349
|
stagger(stack, 'append', [first, env], judge)
|
2264
2350
|
stagger(stack, 'prepend', [first, env], judge)
|
2265
2351
|
for (let i = 0; i < rest.length; ++i) {
|
package/src/compiler.js
CHANGED
@@ -276,18 +276,17 @@ const comp = (tree, Drill) => {
|
|
276
276
|
)}}return -1})();`
|
277
277
|
}
|
278
278
|
|
279
|
-
case STATIC_TYPES.ABSTRACTION:
|
280
|
-
case STATIC_TYPES.COLLECTION:
|
281
|
-
case STATIC_TYPES.UNKNOWN:
|
282
|
-
case STATIC_TYPES.ATOM:
|
283
|
-
case STATIC_TYPES.BOOLEAN:
|
284
|
-
case STATIC_TYPES.ANY:
|
285
|
-
case STATIC_TYPES.NUMBER:
|
286
|
-
case STATIC_TYPES.NUMBERS:
|
287
|
-
case STATIC_TYPES.ABSTRACTIONS:
|
288
|
-
case STATIC_TYPES.BOOLEANS:
|
289
|
-
case STATIC_TYPES.COLLECTIONS:
|
290
|
-
case STATIC_TYPES.AS_NUMBER:
|
279
|
+
// case STATIC_TYPES.ABSTRACTION:
|
280
|
+
// case STATIC_TYPES.COLLECTION:
|
281
|
+
// case STATIC_TYPES.UNKNOWN:
|
282
|
+
// case STATIC_TYPES.ATOM:
|
283
|
+
// case STATIC_TYPES.BOOLEAN:
|
284
|
+
// case STATIC_TYPES.ANY:
|
285
|
+
// case STATIC_TYPES.NUMBER:
|
286
|
+
// case STATIC_TYPES.NUMBERS:
|
287
|
+
// case STATIC_TYPES.ABSTRACTIONS:
|
288
|
+
// case STATIC_TYPES.BOOLEANS:
|
289
|
+
// case STATIC_TYPES.COLLECTIONS:
|
291
290
|
case DEBUG.LOG:
|
292
291
|
case DEBUG.STRING:
|
293
292
|
case DEBUG.UNQUOTED_STRING:
|
package/src/enhance.js
CHANGED
@@ -36,11 +36,6 @@ const opt = (ast) => {
|
|
36
36
|
case APPLY:
|
37
37
|
{
|
38
38
|
switch (first[VALUE]) {
|
39
|
-
case STATIC_TYPES.AS_NUMBER:
|
40
|
-
exp.length = 0
|
41
|
-
for (let i = 0; i < rest.length; ++i) exp.push(...rest[i])
|
42
|
-
evaluate(exp)
|
43
|
-
break
|
44
39
|
case KEYWORDS.DEFINE_VARIABLE:
|
45
40
|
{
|
46
41
|
const last = exp.at(-1)
|
@@ -257,7 +252,6 @@ export const removeCast = (ast) => {
|
|
257
252
|
case STATIC_TYPES.ABSTRACTIONS:
|
258
253
|
case STATIC_TYPES.BOOLEANS:
|
259
254
|
case STATIC_TYPES.COLLECTIONS:
|
260
|
-
case STATIC_TYPES.AS_NUMBER:
|
261
255
|
exp.length = 0
|
262
256
|
for (let i = 0; i < rest.length; ++i) exp.push(...rest[i])
|
263
257
|
evaluate(exp)
|
package/src/keywords.js
CHANGED
package/src/macros.js
CHANGED
@@ -16,7 +16,7 @@ import {
|
|
16
16
|
VALUE,
|
17
17
|
WORD
|
18
18
|
} from './keywords.js'
|
19
|
-
import { hasBlock, stringifyArgs } from './utils.js'
|
19
|
+
import { hasBlock, logExp, stringifyArgs } from './utils.js'
|
20
20
|
import { NIL } from './types.js'
|
21
21
|
export const SUGGAR = {
|
22
22
|
// Syntactic suggars
|
@@ -382,6 +382,15 @@ export const deSuggarAst = (ast, scope) => {
|
|
382
382
|
exp[0][TYPE] = ATOM
|
383
383
|
exp[0][VALUE] = FALSE
|
384
384
|
} else if (rest.length > 2) {
|
385
|
+
// TODO: maybe one day implement
|
386
|
+
// Constant folding
|
387
|
+
// it works sort of like this
|
388
|
+
// while (
|
389
|
+
// rest.at(-2) &&
|
390
|
+
// rest.at(-1)[TYPE] === ATOM &&
|
391
|
+
// rest.at(-2)[TYPE] === ATOM
|
392
|
+
// )
|
393
|
+
// rest[rest.length - 2][VALUE] += rest.pop()[VALUE]
|
385
394
|
exp.length = 0
|
386
395
|
let temp = exp
|
387
396
|
for (let i = 0; i < rest.length; i += 1) {
|
@@ -522,7 +531,11 @@ export const deSuggarAst = (ast, scope) => {
|
|
522
531
|
KEYWORDS.IF
|
523
532
|
} ${stringifyArgs(rest)})`
|
524
533
|
)
|
525
|
-
if (rest.length === 2)
|
534
|
+
if (rest.length === 2) {
|
535
|
+
// for this to work also make nil to be a false boolean
|
536
|
+
// exp[2] = [[APPLY, 'logic:true'], exp[2]]
|
537
|
+
exp.push([WORD, NIL])
|
538
|
+
}
|
526
539
|
}
|
527
540
|
deSuggarAst(exp[1], scope)
|
528
541
|
break
|
package/src/parser.js
CHANGED
@@ -150,7 +150,6 @@ export const AST = {
|
|
150
150
|
case STATIC_TYPES.ABSTRACTIONS:
|
151
151
|
case STATIC_TYPES.BOOLEANS:
|
152
152
|
case STATIC_TYPES.COLLECTIONS:
|
153
|
-
case STATIC_TYPES.AS_NUMBER:
|
154
153
|
out += dfs(tail[0])
|
155
154
|
break
|
156
155
|
default:
|
@@ -193,7 +192,6 @@ export const AST = {
|
|
193
192
|
case STATIC_TYPES.ABSTRACTIONS:
|
194
193
|
case STATIC_TYPES.BOOLEANS:
|
195
194
|
case STATIC_TYPES.COLLECTIONS:
|
196
|
-
case STATIC_TYPES.AS_NUMBER:
|
197
195
|
out += dfs(tail[0])
|
198
196
|
break
|
199
197
|
default:
|
@@ -241,7 +239,6 @@ pub fn ${mod}() -> Expression { ${str} }`
|
|
241
239
|
case STATIC_TYPES.ABSTRACTIONS:
|
242
240
|
case STATIC_TYPES.BOOLEANS:
|
243
241
|
case STATIC_TYPES.COLLECTIONS:
|
244
|
-
case STATIC_TYPES.AS_NUMBER:
|
245
242
|
out += dfs(tail[0])
|
246
243
|
break
|
247
244
|
default:
|
package/src/types.js
CHANGED
@@ -234,27 +234,6 @@ export const SPECIAL_FORM_TYPES = {
|
|
234
234
|
[RETURNS]: [ATOM]
|
235
235
|
}
|
236
236
|
},
|
237
|
-
[STATIC_TYPES.AS_NUMBER]: {
|
238
|
-
[STATS]: {
|
239
|
-
[TYPE_PROP]: [APPLY],
|
240
|
-
[SIGNATURE]: STATIC_TYPES.AS_NUMBER,
|
241
|
-
retried: Infinity,
|
242
|
-
[ARG_COUNT]: 1,
|
243
|
-
[ARGUMENTS]: [
|
244
|
-
{
|
245
|
-
[STATS]: {
|
246
|
-
retried: Infinity,
|
247
|
-
[SIGNATURE]: PLACEHOLDER,
|
248
|
-
[TYPE_PROP]: [ATOM, SPECIAL_BOOLEAN],
|
249
|
-
[RETURNS]: [ATOM, SPECIAL_BOOLEAN],
|
250
|
-
[ARGUMENTS]: [],
|
251
|
-
[ARG_COUNT]: 0
|
252
|
-
}
|
253
|
-
}
|
254
|
-
],
|
255
|
-
[RETURNS]: [ATOM, SPECIAL_NUMBER]
|
256
|
-
}
|
257
|
-
},
|
258
237
|
[STATIC_TYPES.BOOLEAN]: {
|
259
238
|
[STATS]: {
|
260
239
|
[TYPE_PROP]: [APPLY],
|
package/src/utils.js
CHANGED
@@ -273,7 +273,7 @@ const toIgnore = (ast) => {
|
|
273
273
|
break
|
274
274
|
}
|
275
275
|
}
|
276
|
-
dfs(ast
|
276
|
+
dfs(ast)
|
277
277
|
return out
|
278
278
|
// ast.filter(([x]) => isDefinition(x)).map(([_, x]) => x[VALUE])
|
279
279
|
}
|
@@ -282,12 +282,12 @@ export const treeShake = (ast, libs) => {
|
|
282
282
|
const visited = new Set()
|
283
283
|
const ignored = new Set(toIgnore(ast))
|
284
284
|
deepShake(ast, deps, visited, ignored)
|
285
|
-
return extractDeps(visited, deps)
|
285
|
+
return [extractDeps(visited, deps), visited]
|
286
286
|
}
|
287
287
|
export const shakedList = (ast, libs) => {
|
288
288
|
const deps = toDeps(libs)
|
289
289
|
const visited = new Set()
|
290
|
-
const ignored = new Set(toIgnore(ast))
|
290
|
+
const ignored = new Set(toIgnore(ast[0]))
|
291
291
|
deepShake(ast, deps, visited, ignored)
|
292
292
|
const out = []
|
293
293
|
for (const [key] of deps) if (visited.has(key)) out.push(key)
|
@@ -311,7 +311,10 @@ export const wrapInApplyLambda = (ast) => [
|
|
311
311
|
]
|
312
312
|
export const interpret = (ast, keywords) =>
|
313
313
|
ast.reduce((_, x) => evaluate(x, keywords), 0)
|
314
|
-
export const shake = (parsed, std) =>
|
314
|
+
export const shake = (parsed, std) => {
|
315
|
+
const [shaked] = treeShake(parsed, std)
|
316
|
+
return shaked.concat(parsed)
|
317
|
+
}
|
315
318
|
export const tree = (source, std) =>
|
316
319
|
std
|
317
320
|
? shake(LISP.parse(deSuggarSource(removeNoCode(source))), std)
|