fez-lisp 1.6.89 → 1.6.91
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 +92 -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,95 @@ const IfApplyBranch = ({
|
|
614
614
|
return setPropToReturn(ref[STATS], prop, branch[STATS])
|
615
615
|
}
|
616
616
|
}
|
617
|
+
const inferIf = (branch, re, env, name) => {
|
618
|
+
switch (branch[TYPE]) {
|
619
|
+
case ATOM:
|
620
|
+
return [[ATOM, NUMBER_SUBTYPE()]]
|
621
|
+
case WORD:
|
622
|
+
if (branch[VALUE] === NIL) return [[UNKNOWN]]
|
623
|
+
if (env[branch[VALUE]]) return [env[branch[VALUE]][STATS][TYPE_PROP]]
|
624
|
+
break
|
625
|
+
case APPLY:
|
626
|
+
if (branch[VALUE] !== name && env[branch[VALUE]])
|
627
|
+
if (branch[VALUE] === KEYWORDS.CREATE_ARRAY) {
|
628
|
+
return [initArrayType({ rem: re, env })[RETURNS]]
|
629
|
+
} else if (branch[VALUE] === KEYWORDS.IF) {
|
630
|
+
const conc = isLeaf(re[2]) ? re[2] : re[2][0]
|
631
|
+
const alt = isLeaf(re[3]) ? re[3] : re[3][0]
|
632
|
+
return inferIf(conc, re[2], env, name).concat(
|
633
|
+
inferIf(alt, re[3], env, name)
|
634
|
+
)
|
635
|
+
} else return [env[branch[VALUE]][STATS][RETURNS]]
|
636
|
+
break
|
637
|
+
}
|
638
|
+
return []
|
639
|
+
}
|
640
|
+
const validateIfMatchingBranches = (
|
641
|
+
concequent,
|
642
|
+
alternative,
|
643
|
+
env,
|
644
|
+
exp,
|
645
|
+
re,
|
646
|
+
name
|
647
|
+
) => {
|
648
|
+
const A = inferIf(concequent, re[0], env, name).filter(
|
649
|
+
(x) => x[0] !== UNKNOWN && x[0] !== ANY
|
650
|
+
)
|
651
|
+
const B = inferIf(alternative, re[1], env, name).filter(
|
652
|
+
(x) => x[0] !== UNKNOWN && x[0] !== ANY
|
653
|
+
)
|
654
|
+
|
655
|
+
if (!A.length || !B.length) return
|
656
|
+
|
657
|
+
const isSame = (A, B) => {
|
658
|
+
if (
|
659
|
+
A[0] !== B[0] ||
|
660
|
+
(isSubType(A[1]) && isSubType(B[1]) && !A[1].isMatching(B[1]))
|
661
|
+
) {
|
662
|
+
throw new TypeError(
|
663
|
+
`(if) needs to have matching concequent and alternative branches but got (${formatSubType(
|
664
|
+
A
|
665
|
+
)}) and (${formatSubType(B)}) (${stringifyArgs(exp)}) (check #1005)`
|
666
|
+
)
|
667
|
+
}
|
668
|
+
}
|
669
|
+
A.forEach((x) => isSame(A[0], x))
|
670
|
+
B.forEach((x) => isSame(B[0], x))
|
671
|
+
|
672
|
+
const FA = A[0]
|
673
|
+
const FB = B[0]
|
674
|
+
if (
|
675
|
+
FA[0] !== FB[0] ||
|
676
|
+
(isSubType(FA[1]) && isSubType(FB[1]) && !FA[1].isMatching(FB[1]))
|
677
|
+
) {
|
678
|
+
throw new TypeError(
|
679
|
+
`(if) needs to have matching concequent and alternative branches but got (${formatSubType(
|
680
|
+
FA
|
681
|
+
)}) and (${formatSubType(FB)}) (${stringifyArgs(exp)}) (check #1005)`
|
682
|
+
)
|
683
|
+
}
|
684
|
+
}
|
617
685
|
const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
|
618
|
-
|
619
|
-
|
686
|
+
const conc = isLeaf(re[0]) ? re[0] : re[0][0]
|
687
|
+
const alt = isLeaf(re[1]) ? re[1] : re[1][0]
|
688
|
+
const concequent = env[conc[VALUE]]
|
689
|
+
const alternative = env[alt[VALUE]]
|
690
|
+
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
691
|
+
setPropToAtom(ref[STATS], prop)
|
692
|
+
}
|
620
693
|
// TODO check that both branches are predicates if one is
|
621
694
|
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
695
|
// TODO make this more simple - it's so many different things just because types are functions or not
|
628
696
|
// WHY not consider making return types for everything
|
629
697
|
if (concequent)
|
630
698
|
if (conc[TYPE] === WORD) {
|
631
|
-
|
699
|
+
setPropToTypeRef(ref[STATS], prop, concequent[STATS])
|
632
700
|
} else if (
|
633
701
|
conc[TYPE] === APPLY &&
|
634
702
|
getType(concequent[STATS]) === APPLY &&
|
635
703
|
// Making sure the recursive function don't look for their own return type
|
636
704
|
concequent[STATS][SIGNATURE] !== ref[STATS][SIGNATURE]
|
637
|
-
)
|
705
|
+
)
|
638
706
|
IfApplyBranch({
|
639
707
|
leaf: conc,
|
640
708
|
branch: concequent,
|
@@ -646,16 +714,15 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
|
|
646
714
|
exp,
|
647
715
|
check
|
648
716
|
})
|
649
|
-
|
650
|
-
if (alternative) {
|
717
|
+
if (alternative)
|
651
718
|
if (alt[TYPE] === WORD) {
|
652
|
-
|
719
|
+
setPropToTypeRef(ref[STATS], prop, alternative[STATS])
|
653
720
|
} else if (
|
654
721
|
alt[TYPE] === APPLY &&
|
655
722
|
getType(alternative[STATS]) === APPLY &&
|
656
723
|
// Making sure the recursive function don't look for their own return type
|
657
724
|
alternative[STATS][SIGNATURE] !== ref[STATS][SIGNATURE]
|
658
|
-
)
|
725
|
+
)
|
659
726
|
IfApplyBranch({
|
660
727
|
leaf: alt,
|
661
728
|
branch: alternative,
|
@@ -667,9 +734,8 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
|
|
667
734
|
exp,
|
668
735
|
check
|
669
736
|
})
|
670
|
-
}
|
671
|
-
}
|
672
737
|
}
|
738
|
+
validateIfMatchingBranches(conc, alt, env, exp, re, ref[STATS][SIGNATURE])
|
673
739
|
}
|
674
740
|
const resolveCondition = ({ rem, name, env, exp, prop, stack, check }) => {
|
675
741
|
const ret = rem[0]
|
@@ -958,8 +1024,13 @@ const initArrayTypeRec = ({ rem, env }) =>
|
|
958
1024
|
x[TYPE] === ATOM ? NUMBER_SUBTYPE() : new SubType([UNKNOWN])
|
959
1025
|
]
|
960
1026
|
else if (env[x[0][VALUE]])
|
961
|
-
if (x.length > 1 &&
|
1027
|
+
if (x.length > 1 && x[0][VALUE] === KEYWORDS.CREATE_ARRAY)
|
962
1028
|
return initArrayTypeRec({ rem: x, env })
|
1029
|
+
else if (
|
1030
|
+
x.length > 1 &&
|
1031
|
+
env[x[0][VALUE]][STATS][RETURNS][0] === COLLECTION
|
1032
|
+
)
|
1033
|
+
return [getReturns(env[x[0][VALUE]][STATS])]
|
963
1034
|
else if (GET_ARRAY_INFERENCE_SET.has(x[0][VALUE])) {
|
964
1035
|
const res = resolveGetterRec(x, env)
|
965
1036
|
if (!res) return [UNKNOWN]
|
@@ -2114,7 +2185,7 @@ export const typeCheck = (
|
|
2114
2185
|
(x) => isGenericType(x[STATS]) || isGenericReturn(x[STATS])
|
2115
2186
|
)
|
2116
2187
|
) {
|
2117
|
-
const
|
2188
|
+
const genericRecursiveDecent = (ref) => {
|
2118
2189
|
if (isGenericReturn(ref[STATS])) {
|
2119
2190
|
const [index, multiplier] = ref[STATS][RETURNS][2]
|
2120
2191
|
const desiredTypeIndex = env[first[VALUE]][STATS][
|
@@ -2229,7 +2300,8 @@ export const typeCheck = (
|
|
2229
2300
|
expected[STATS][TYPE_PROP].length = 2
|
2230
2301
|
}
|
2231
2302
|
}
|
2232
|
-
if (expected[STATS][ARGUMENTS].length)
|
2303
|
+
if (expected[STATS][ARGUMENTS].length)
|
2304
|
+
genericRecursiveDecent(expected)
|
2233
2305
|
}
|
2234
2306
|
}
|
2235
2307
|
const copy = Object.create(env)
|
@@ -2240,7 +2312,7 @@ export const typeCheck = (
|
|
2240
2312
|
}
|
2241
2313
|
copy[newName][STATS][SIGNATURE] = newName
|
2242
2314
|
|
2243
|
-
|
2315
|
+
genericRecursiveDecent(copy[newName])
|
2244
2316
|
|
2245
2317
|
const cexp = structuredClone(exp)
|
2246
2318
|
copy[newName][STATS].source = structuredClone(
|
@@ -2260,6 +2332,7 @@ export const typeCheck = (
|
|
2260
2332
|
}
|
2261
2333
|
}
|
2262
2334
|
}
|
2335
|
+
|
2263
2336
|
stagger(stack, 'append', [first, env], judge)
|
2264
2337
|
stagger(stack, 'prepend', [first, env], judge)
|
2265
2338
|
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)
|