auto-editor 28.0.2__py3-none-any.whl → 29.0.0__py3-none-any.whl

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.
Files changed (58) hide show
  1. {auto_editor-28.0.2.dist-info → auto_editor-29.0.0.dist-info}/METADATA +5 -4
  2. auto_editor-29.0.0.dist-info/RECORD +5 -0
  3. auto_editor-29.0.0.dist-info/top_level.txt +1 -0
  4. auto_editor/__init__.py +0 -1
  5. auto_editor/__main__.py +0 -503
  6. auto_editor/analyze.py +0 -393
  7. auto_editor/cmds/__init__.py +0 -0
  8. auto_editor/cmds/cache.py +0 -69
  9. auto_editor/cmds/desc.py +0 -32
  10. auto_editor/cmds/info.py +0 -213
  11. auto_editor/cmds/levels.py +0 -199
  12. auto_editor/cmds/palet.py +0 -29
  13. auto_editor/cmds/repl.py +0 -113
  14. auto_editor/cmds/subdump.py +0 -72
  15. auto_editor/cmds/test.py +0 -812
  16. auto_editor/edit.py +0 -548
  17. auto_editor/exports/__init__.py +0 -0
  18. auto_editor/exports/fcp11.py +0 -195
  19. auto_editor/exports/fcp7.py +0 -313
  20. auto_editor/exports/json.py +0 -63
  21. auto_editor/exports/shotcut.py +0 -147
  22. auto_editor/ffwrapper.py +0 -187
  23. auto_editor/help.py +0 -223
  24. auto_editor/imports/__init__.py +0 -0
  25. auto_editor/imports/fcp7.py +0 -275
  26. auto_editor/imports/json.py +0 -234
  27. auto_editor/json.py +0 -297
  28. auto_editor/lang/__init__.py +0 -0
  29. auto_editor/lang/libintrospection.py +0 -10
  30. auto_editor/lang/libmath.py +0 -23
  31. auto_editor/lang/palet.py +0 -724
  32. auto_editor/lang/stdenv.py +0 -1184
  33. auto_editor/lib/__init__.py +0 -0
  34. auto_editor/lib/contracts.py +0 -235
  35. auto_editor/lib/data_structs.py +0 -278
  36. auto_editor/lib/err.py +0 -2
  37. auto_editor/make_layers.py +0 -315
  38. auto_editor/preview.py +0 -93
  39. auto_editor/render/__init__.py +0 -0
  40. auto_editor/render/audio.py +0 -517
  41. auto_editor/render/subtitle.py +0 -205
  42. auto_editor/render/video.py +0 -312
  43. auto_editor/timeline.py +0 -331
  44. auto_editor/utils/__init__.py +0 -0
  45. auto_editor/utils/bar.py +0 -142
  46. auto_editor/utils/chunks.py +0 -2
  47. auto_editor/utils/cmdkw.py +0 -206
  48. auto_editor/utils/container.py +0 -102
  49. auto_editor/utils/func.py +0 -128
  50. auto_editor/utils/log.py +0 -124
  51. auto_editor/utils/types.py +0 -277
  52. auto_editor/vanparse.py +0 -313
  53. auto_editor-28.0.2.dist-info/RECORD +0 -56
  54. auto_editor-28.0.2.dist-info/entry_points.txt +0 -6
  55. auto_editor-28.0.2.dist-info/top_level.txt +0 -2
  56. docs/build.py +0 -70
  57. {auto_editor-28.0.2.dist-info → auto_editor-29.0.0.dist-info}/WHEEL +0 -0
  58. {auto_editor-28.0.2.dist-info → auto_editor-29.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,1184 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import TYPE_CHECKING
5
-
6
- import bv
7
-
8
- from auto_editor.analyze import mut_remove_large, mut_remove_small
9
- from auto_editor.lib.contracts import *
10
- from auto_editor.lib.data_structs import *
11
- from auto_editor.lib.err import MyError
12
-
13
- from .palet import Syntax, env, is_boolarr, is_iterable, my_eval, p_slice, raise_, ref
14
-
15
- if TYPE_CHECKING:
16
- from fractions import Fraction
17
- from typing import Any, Literal
18
-
19
- import numpy as np
20
- from numpy.typing import NDArray
21
-
22
- Number = int | float | Fraction
23
- BoolList = NDArray[np.bool_]
24
- Node = tuple
25
-
26
-
27
- def make_standard_env() -> dict[str, Any]:
28
- import os.path
29
- from functools import reduce
30
- from operator import add, ge, gt, is_, le, lt, mod, mul
31
- from subprocess import run
32
- from time import sleep
33
-
34
- from numpy import logical_and, logical_not, logical_or, logical_xor
35
-
36
- from auto_editor.utils.func import boolop, mut_margin
37
-
38
- # fmt: off
39
-
40
- class UserProc(Proc):
41
- """A user-defined procedure."""
42
-
43
- __slots__ = ("env", "name", "parms", "body", "contracts", "arity")
44
-
45
- def __init__(
46
- self,
47
- env: Env,
48
- name: str,
49
- parms: list[str],
50
- contracts: tuple[Any, ...],
51
- body: Node,
52
- ):
53
- self.env = env
54
- self.name = name
55
- self.parms = parms
56
- self.body = body
57
- self.contracts = contracts
58
-
59
- if parms and parms[-1] == "...":
60
- parms.pop()
61
- self.arity: tuple[int, int | None] = len(parms) - 1, None
62
- else:
63
- self.arity = len(parms), len(parms)
64
-
65
- def __call__(self, *args: Any) -> Any:
66
- check_args(self.name, args, self.arity, self.contracts)
67
-
68
- if self.arity[1] is None:
69
- args = tuple(
70
- list(args[: len(self.parms) - 1]) + [list(args[len(self.parms) - 1 :])]
71
- )
72
-
73
- inner_env = Env(dict(zip(self.parms, args)), self.env)
74
-
75
- for item in self.body[0:-1]:
76
- my_eval(inner_env, item)
77
-
78
- return my_eval(inner_env, self.body[-1])
79
-
80
- @dataclass(slots=True)
81
- class KeywordUserProc:
82
- env: Env
83
- name: str
84
- parms: list[str]
85
- kw_parms: list[str]
86
- body: Node
87
- arity: tuple[int, None]
88
- contracts: list[Any] | None = None
89
-
90
- def __call__(self, *args: Any, **kwargs: Any) -> Any:
91
- env = {}
92
- all_parms = self.parms + self.kw_parms
93
- for i, arg in enumerate(args):
94
- if i >= len(all_parms):
95
- raise MyError("Too many arguments")
96
- env[all_parms[i]] = arg
97
-
98
- for key, val in kwargs.items():
99
- if key in env:
100
- raise MyError(
101
- f"Keyword: {key} already fulfilled by positional argument."
102
- )
103
- else:
104
- env[key] = val
105
-
106
- inner_env = Env(env, self.env)
107
-
108
- for item in self.body[0:-1]:
109
- my_eval(inner_env, item)
110
-
111
- return my_eval(inner_env, self.body[-1])
112
-
113
- def __str__(self) -> str:
114
- return self.name
115
-
116
- def __repr__(self) -> str:
117
- return f"#<kw-proc:{self.name}>"
118
-
119
- is_cont = Contract("contract?", is_contract)
120
- is_sequence = Contract(
121
- "sequence?",
122
- lambda v: type(v) in (str, range, Quoted) or isinstance(v, list | np.ndarray),
123
- )
124
- bool_or_barr = Contract(
125
- "(or/c bool? bool-array?)",
126
- lambda v: type(v) is bool or is_boolarr(v),
127
- )
128
- is_keyw = Contract("keyword?", lambda v: type(v) is QuotedKeyword)
129
- dtype_map = {
130
- Sym("bool"): np.bool_,
131
- Sym("int8"): np.int8,
132
- Sym("int16"): np.int16,
133
- Sym("int32"): np.int32,
134
- Sym("int64"): np.int64,
135
- Sym("uint8"): np.uint8,
136
- Sym("uint16"): np.uint16,
137
- Sym("uint32"): np.uint32,
138
- Sym("uint64"): np.uint64,
139
- Sym("float32"): np.float32,
140
- Sym("float64"): np.float64,
141
- }
142
-
143
- @dataclass(slots=True)
144
- class InputPort:
145
- name: str
146
- port: Any
147
- closed: bool
148
-
149
- def close(self) -> None:
150
- if not self.closed:
151
- self.closed = True
152
- self.port.close()
153
-
154
- def __str__(self) -> str:
155
- return f"#<input-port:{self.name}>"
156
-
157
- __repr__ = __str__
158
-
159
- @dataclass(slots=True)
160
- class OutputPort:
161
- name: str
162
- port: Any
163
- write: Any
164
- closed: bool
165
-
166
- def close(self) -> None:
167
- if not self.closed:
168
- self.closed = True
169
- self.port.close()
170
-
171
- def __str__(self) -> str:
172
- return f"#<output-port:{self.name}>"
173
-
174
- __repr__ = __str__
175
-
176
- def initInPort(name: str) -> InputPort | Literal[False]:
177
- try:
178
- port = open(name, encoding="utf-8")
179
- except Exception:
180
- return False
181
- return InputPort(name, port, False)
182
-
183
- def initOutPort(name: str) -> OutputPort | Literal[False]:
184
- try:
185
- port = open(name, "w", encoding="utf-8")
186
- except Exception:
187
- return False
188
- return OutputPort(name, port, port.write, False)
189
-
190
- def is_equal(a: object, b: object) -> bool:
191
- if isinstance(a, np.ndarray) and isinstance(b, np.ndarray):
192
- return np.array_equal(a, b)
193
- return type(a) == type(b) and a == b
194
-
195
- # Syntax definitions
196
- def check_for_syntax(env: Env, node: Node) -> tuple[Sym, Any]:
197
- name = node[0]
198
- if len(node) < 2:
199
- raise MyError(f"{name}: bad syntax")
200
-
201
- if len(node) == 2:
202
- raise MyError(f"{name}: missing body")
203
-
204
- assert isinstance(node[1], tuple)
205
- assert isinstance(node[1][0], tuple)
206
-
207
- var = node[1][0][0]
208
- if type(var) is not Sym:
209
- raise MyError(f"{name}: binding must be an identifier")
210
- my_iter = my_eval(env, node[1][0][1])
211
-
212
- if not is_iterable(my_iter):
213
- if type(my_iter) is int:
214
- return var, range(my_iter)
215
- raise MyError(f"{name}: got non-iterable in iter slot")
216
-
217
- return var, my_iter
218
-
219
- def syn_lambda(env: Env, node: Node) -> UserProc:
220
- if len(node) < 3:
221
- raise MyError(f"{node[0]}: too few terms")
222
-
223
- if type(node[1]) is not tuple:
224
- raise MyError(f"{node[0]}: bad syntax")
225
-
226
- parms: list[str] = []
227
- for item in node[1]:
228
- if type(item) is not Sym:
229
- raise MyError(f"{node[0]}: must be an identifier, got: {item} {type(item)}")
230
-
231
- parms.append(f"{item}")
232
-
233
- return UserProc(env, "", parms, (), node[2:])
234
-
235
- def syn_define(env: Env, node: Node) -> None:
236
- if len(node) < 2:
237
- raise MyError(f"{node[0]}: too few terms")
238
- if len(node) < 3:
239
- if type(node[1]) is Sym:
240
- raise MyError(f"{node[0]}: what should `{node[1]}` be defined as?")
241
- elif type(node[1]) is tuple and len(node[1]) > 0:
242
- raise MyError(f"{node[0]}: function `{node[1][0]}` needs a body.")
243
- raise MyError(f"{node[0]}: too few terms")
244
-
245
- if type(node[1]) is tuple:
246
- term = node[1]
247
- body = node[2:]
248
-
249
- if not term or type(term[0]) is not Sym:
250
- raise MyError(f"{node[0]}: proc-binding must be an identifier")
251
-
252
- n = term[0].val
253
- parms: list[str] = []
254
- kparms: list[str] = []
255
- kw_only = False
256
-
257
- for item in term[1:]:
258
- if kw_only:
259
- if type(item) is Sym:
260
- raise MyError(f"{node[0]}: {item} must be a keyword")
261
- if type(item) is not Keyword:
262
- raise MyError(f"{node[0]}: must be a keyword")
263
- kparms.append(item.val)
264
- else:
265
- if type(item) is Keyword:
266
- kw_only = True
267
- kparms.append(item.val)
268
- elif type(item) is Sym:
269
- parms.append(item.val)
270
- else:
271
- raise MyError(f"{node[0]}: must be an identifier")
272
-
273
- if kw_only:
274
- env[n] = KeywordUserProc(env, n, parms, kparms, body, (len(parms), None))
275
- else:
276
- env[n] = UserProc(env, n, parms, (), body)
277
- return None
278
-
279
- elif type(node[1]) is not Sym:
280
- raise MyError(f"{node[0]}: must be an identifier")
281
-
282
- if len(node) > 3:
283
- raise MyError(f"{node[0]}: multiple expressions after identifier")
284
-
285
- n = node[1].val
286
-
287
- if (
288
- type(node[2]) is tuple
289
- and node[2]
290
- and type(node[2][0]) is Sym
291
- and node[2][0].val in {"lambda", "λ"}
292
- ):
293
- terms = node[2][1]
294
- body = node[2][2:]
295
-
296
- parms = []
297
- for item in terms:
298
- if type(item) is not Sym:
299
- raise MyError(f"{node[0]}: must be an identifier")
300
-
301
- parms.append(f"{item}")
302
-
303
- env[n] = UserProc(env, n, parms, (), body)
304
-
305
- else:
306
- for item in node[2:-1]:
307
- my_eval(env, item)
308
- env[n] = my_eval(env, node[-1])
309
-
310
- def syn_definec(env: Env, node: Node) -> None:
311
- if len(node) < 3:
312
- raise MyError(f"{node[0]}: too few terms")
313
-
314
- if type(node[1]) is not tuple:
315
- raise MyError(f"{node[0]} only allows procedure declarations")
316
-
317
- if not node[1] or type(node[1][0]) is not Sym:
318
- raise MyError(f"{node[0]}: bad proc-binding syntax")
319
-
320
- n = node[1][0].val
321
-
322
- contracts: list[Any] = []
323
- parms: list[str] = []
324
- for item in node[1][1:]:
325
- if item == Sym("->"):
326
- break
327
- if type(item) is not tuple or len(item) != 2:
328
- raise MyError(f"{node[0]}: bad var-binding syntax")
329
- if type(item[0]) is not Sym:
330
- raise MyError(f"{node[0]}: binding must be identifier")
331
-
332
- con = my_eval(env, item[1])
333
- if not is_cont(con):
334
- raise MyError(f"{node[0]}: {print_str(con)} is not a valid contract")
335
-
336
- parms.append(f"{item[0]}")
337
- contracts.append(con)
338
-
339
- env[n] = UserProc(env, n, parms, tuple(contracts), node[2:])
340
- return None
341
-
342
- def guard_term(node: Node, n: int, u: int) -> None:
343
- if n == u:
344
- if len(node) != n:
345
- raise MyError(
346
- f"{node[0]}: Expects exactly {n-1} term{'s' if n > 2 else ''}"
347
- )
348
- return None
349
- if len(node) < n:
350
- raise MyError(f"{node[0]}: Expects at least {n-1} term{'s' if n > 2 else ''}")
351
- if len(node) > u:
352
- raise MyError(f"{node[0]}: Expects at most {u-1} term{'s' if u > 2 else ''}")
353
-
354
- def syn_set(env: Env, node: Node) -> None:
355
- guard_term(node, 3, 3)
356
-
357
- if type(node[1]) is Sym:
358
- name = node[1].val
359
- if name not in env:
360
- raise MyError(f"{node[0]}: Can't set variable `{name}` before definition")
361
- env[name] = my_eval(env, node[2])
362
- return None
363
-
364
- if type(node[1]) is tuple and len(node[1]) == 3 and node[1][0] == Sym("@r"):
365
- base = my_eval(env, node[1][1])
366
- name = node[1][2].val
367
- for i, item in enumerate(base.attrs[0::2]):
368
- if name == item:
369
- result = my_eval(env, node[2])
370
- check_args(item, (result,), (1, 1), (base.attrs[i * 2 + 1],))
371
- base.values[i] = result
372
- return None
373
-
374
- raise MyError(f"{node[0]}: {base.name} has no attribute `{name}`")
375
-
376
- raise MyError(f"{node[0]}: Expected identifier, got {print_str(node[1])}")
377
-
378
- def syn_incf(env: Env, node: Node) -> None:
379
- guard_term(node, 2, 3)
380
-
381
- incre_by = 1
382
- if len(node) == 3:
383
- incre_by = my_eval(env, node[2])
384
- if not is_num(incre_by):
385
- raise MyError(f"{node[0]}: Expected number? got: {print_str(incre_by)}")
386
-
387
- if type(node[1]) is Sym:
388
- name = node[1].val
389
-
390
- if type(env[name]) is NotFound:
391
- raise MyError(f"{node[0]}: `{name}` is not defined")
392
- if not is_num(env[name]):
393
- raise MyError(f"{node[0]}: `{name}` is not a number?")
394
- env[name] += incre_by
395
- return None
396
-
397
- if type(node[1]) is tuple and len(node[1]) == 3 and node[1][0] == Sym("@r"):
398
- base = my_eval(env, node[1][1])
399
- if type(base) is not PaletClass:
400
- raise MyError(f"{node[0]}: must be a class instance")
401
- if type(node[1][2]) is not Sym:
402
- raise MyError(f"{node[0]}: class attribute must be an identifier")
403
- name = node[1][2].val
404
- for i, item in enumerate(base.attrs[0::2]):
405
- if name == item:
406
- if not is_num(base.values[i]):
407
- raise MyError(f"{node[0]}: `{name}` is not a number?")
408
-
409
- check_args(
410
- name, (base.values[i] + incre_by,), (1, 1), (base.attrs[i * 2 + 1],)
411
- )
412
- base.values[i] += incre_by
413
- return None
414
- raise MyError(f"{node[0]}: {base.name} has no attribute `{name}`")
415
-
416
- raise MyError(f"{node[0]}: Expected identifier, got {print_str(node[1])}")
417
-
418
- def syn_decf(env: Env, node: Node) -> None:
419
- guard_term(node, 2, 3)
420
-
421
- incre_by = 1
422
- if len(node) == 3:
423
- incre_by = my_eval(env, node[2])
424
- if not is_num(incre_by):
425
- raise MyError(f"{node[0]}: Expected number? got: {print_str(incre_by)}")
426
-
427
- if type(node[1]) is Sym:
428
- name = node[1].val
429
-
430
- if type(env[name]) is NotFound:
431
- raise MyError(f"{node[0]}: `{name}` is not defined")
432
- if not is_num(env[name]):
433
- raise MyError(f"{node[0]}: `{name}` is not a number?")
434
- env[name] -= incre_by
435
- return None
436
-
437
- if type(node[1]) is tuple and len(node[1]) == 3 and node[1][0] == Sym("@r"):
438
- base = my_eval(env, node[1][1])
439
- if type(base) is not PaletClass:
440
- raise MyError(f"{node[0]}: must be a class instance")
441
- if type(node[1][2]) is not Sym:
442
- raise MyError(f"{node[0]}: class attribute must be an identifier")
443
- name = node[1][2].val
444
- for i, item in enumerate(base.attrs[0::2]):
445
- if name == item:
446
- if not is_num(base.values[i]):
447
- raise MyError(f"{node[0]}: `{name}` is not a number?")
448
-
449
- check_args(
450
- name, (base.values[i] - incre_by,), (1, 1), (base.attrs[i * 2 + 1],)
451
- )
452
- base.values[i] -= incre_by
453
- return None
454
- raise MyError(f"{node[0]}: {base.name} has no attribute `{name}`")
455
-
456
- raise MyError(f"{node[0]}: Expected identifier, got {print_str(node[1])}")
457
-
458
- def syn_strappend(env: Env, node: Node) -> None:
459
- guard_term(node, 3, 3)
460
-
461
- if type(node[1]) is not Sym:
462
- raise MyError(f"{node[0]}: Expected identifier, got {print_str(node[1])}")
463
- name = node[1].val
464
-
465
- if type(env[name]) is NotFound:
466
- raise MyError(f"{node[0]}: `{name}` is not defined")
467
- if not is_str(env[name]):
468
- raise MyError(f"{node[0]}: `{name}` is not a string?")
469
-
470
- if not is_str(num := my_eval(env, node[2])):
471
- raise MyError(f"{node[0]}: Expected string? got: {print_str(num)}")
472
- env[name] += num
473
-
474
- def syn_while(env: Env, node: Node) -> None:
475
- while my_eval(env, node[1]) == True:
476
- for c in node[2:]:
477
- my_eval(env, c)
478
-
479
- def syn_for(env: Env, node: Node) -> None:
480
- var, my_iter = check_for_syntax(env, node)
481
-
482
- if isinstance(my_iter, np.ndarray) and my_iter.dtype == np.bool_:
483
- for item in my_iter:
484
- env[var.val] = int(item)
485
- for c in node[2:]:
486
- my_eval(env, c)
487
- else:
488
- for item in my_iter:
489
- env[var.val] = item
490
- for c in node[2:]:
491
- my_eval(env, c)
492
-
493
- def syn_for_items(env: Env, node: Node) -> None:
494
- if len(node) < 2:
495
- raise MyError(f"{node[0]}: bad syntax")
496
-
497
- if type(node[1]) is not tuple or len(node[1]) != 3:
498
- raise MyError(f"{node[0]}: Invalid id body")
499
-
500
- key, val, dic = node[1]
501
- if type(key) is not Sym or type(val) is not Sym:
502
- raise MyError(f"{node[0]}: key and val must be identifiers")
503
-
504
- dic = my_eval(env, dic)
505
- if type(dic) is not dict:
506
- raise MyError(f"{node[0]}: dict must be a hash?")
507
-
508
- for k, v in dic.items():
509
- env[key.val] = k
510
- env[val.val] = v
511
- for c in node[2:]:
512
- my_eval(env, c)
513
-
514
- def syn_quote(_: Env, node: Node) -> Any:
515
- guard_term(node, 2, 2)
516
- if type(node[1]) is Keyword:
517
- return QuotedKeyword(node[1])
518
- if type(node[1]) is tuple:
519
- return Quoted(node[1])
520
- return node[1]
521
-
522
- def syn_if(env: Env, node: Node) -> Any:
523
- guard_term(node, 4, 4)
524
- test_expr = my_eval(env, node[1])
525
-
526
- if type(test_expr) is not bool:
527
- raise MyError(
528
- f"{node[0]} test-expr: expected bool?, got {print_str(test_expr)}"
529
- )
530
-
531
- return my_eval(env, node[2] if test_expr else node[3])
532
-
533
- def syn_when(env: Env, node: Node) -> Any:
534
- if len(node) < 3:
535
- raise MyError(f"{node[0]}: Expected at least 2 terms")
536
- test_expr = my_eval(env, node[1])
537
-
538
- if type(test_expr) is not bool:
539
- raise MyError(
540
- f"{node[0]} test-expr: expected bool?, got {print_str(test_expr)}"
541
- )
542
-
543
- if test_expr:
544
- for item in node[2:-1]:
545
- my_eval(env, item)
546
- return my_eval(env, node[-1])
547
- return None
548
-
549
- def syn_and(env: Env, node: Node) -> Any:
550
- if len(node) == 1:
551
- raise MyError(f"{node[0]}: Expected at least 1 term")
552
-
553
- first = my_eval(env, node[1])
554
- if first is False:
555
- return False
556
- if first is True:
557
- for n in node[2:]:
558
- val = my_eval(env, n)
559
- if val is False:
560
- return False
561
- if val is not True:
562
- raise MyError(f"{node[0]} args must be bool?")
563
- return True
564
-
565
- if is_boolarr(first):
566
- vals = [first] + [my_eval(env, n) for n in node[2:]]
567
- check_args(node[0], vals, (2, None), (is_boolarr,))
568
- return reduce(lambda a, b: boolop(a, b, logical_and), vals)
569
-
570
- raise MyError(f"{node[0]} expects (or/c bool? bool-array?)")
571
-
572
- def syn_or(env: Env, node: Node) -> Any:
573
- if len(node) == 1:
574
- raise MyError(f"{node[0]}: Expected at least 1 term")
575
-
576
- first = my_eval(env, node[1])
577
- if first is True:
578
- return True
579
- if first is False:
580
- for n in node[2:]:
581
- val = my_eval(env, n)
582
- if val is True:
583
- return True
584
- if val is not False:
585
- raise MyError(f"{node[0]} args must be bool?")
586
- return False
587
-
588
- if is_boolarr(first):
589
- vals = [first] + [my_eval(env, n) for n in node[2:]]
590
- check_args(node[0], vals, (2, None), (is_boolarr,))
591
- return reduce(lambda a, b: boolop(a, b, logical_or), vals)
592
-
593
- raise MyError(f"{node[0]} expects (or/c bool? bool-array?)")
594
-
595
- def syn_delete(env: Env, node: Node) -> None:
596
- guard_term(node, 2, 2)
597
- if type(node[1]) is not Sym:
598
- raise MyError(f"{node[0]}: Expected identifier for first term")
599
-
600
- del env[node[1].val]
601
-
602
- def syn_rename(env: Env, node: Node) -> None:
603
- guard_term(node, 3, 3)
604
-
605
- first = node[1]
606
- if type(first) is not Sym:
607
- raise MyError(f"{node[0]}: Expected identifier for first term")
608
-
609
- sec = node[2]
610
- if type(sec) is not Sym:
611
- raise MyError(f"{node[0]}: Expected identifier for second term")
612
-
613
- if first.val not in env:
614
- raise MyError(f"{node[0]}: Original identifier does not exist")
615
-
616
- env[sec.val] = env[first.val]
617
- del env[first.val]
618
-
619
- def syn_cond(env: Env, node: Node) -> Any:
620
- for test_expr in node[1:]:
621
- if type(test_expr) is not tuple or not test_expr:
622
- raise MyError(f"{node[0]}: bad syntax, clause is not a test-value pair")
623
-
624
- if test_expr[0] == Sym("else"):
625
- if len(test_expr) == 1:
626
- raise MyError(f"{node[0]}: missing expression in else clause")
627
- test_clause = True
628
- else:
629
- test_clause = my_eval(env, test_expr[0])
630
- if type(test_clause) is not bool:
631
- raise MyError(
632
- f"{node[0]} test-expr: expected bool?, got {print_str(test_clause)}"
633
- )
634
-
635
- if test_clause:
636
- if len(test_expr) == 1:
637
- return True
638
-
639
- for rest_clause in test_expr[1:-1]:
640
- my_eval(env, rest_clause)
641
- return my_eval(env, test_expr[-1])
642
-
643
- return None
644
-
645
- def syn_case(env: Env, node: Node) -> Any:
646
- val_expr = my_eval(env, node[1])
647
- for case_clause in node[2:]:
648
- if type(case_clause) is not tuple or len(case_clause) != 2:
649
- raise MyError("case: bad syntax")
650
- if type(case_clause[0]) is tuple:
651
- for case in case_clause[0]:
652
- if is_equal(case, val_expr):
653
- return my_eval(env, case_clause[1])
654
- elif type(case_clause[0]) is Sym and case_clause[0].val == "else":
655
- return my_eval(env, case_clause[1])
656
- else:
657
- raise MyError("case: bad syntax")
658
- return None
659
-
660
- def syn_let(env: Env, node: Node) -> Any:
661
- if len(node) < 2:
662
- raise MyError(f"{node[0]}: Expected at least 1 term")
663
-
664
- if type(node[1]) is Sym:
665
- raise MyError(f"{node[0]}: Named-let form is not supported")
666
-
667
- for var_ids in node[1]:
668
- if type(var_ids) is not tuple or len(var_ids) != 2:
669
- raise MyError(f"{node[0]}: Expected two terms: `id` and `val-expr`")
670
-
671
- new_maps: dict[str, Any] = {}
672
- for var, val in node[1]:
673
- if type(var) is not Sym:
674
- raise MyError(f"{node[0]}: Expected symbol for `id` term")
675
- new_maps[var.val] = my_eval(env, val)
676
-
677
- inner_env = Env(new_maps, env)
678
- for item in node[2:-1]:
679
- my_eval(inner_env, item)
680
- return my_eval(inner_env, node[-1])
681
-
682
- def syn_let_star(env: Env, node: Node) -> Any:
683
- if len(node) < 2:
684
- raise MyError(f"{node[0]}: Expected at least 1 term")
685
-
686
- for var_ids in node[1]:
687
- if len(var_ids) != 2:
688
- raise MyError(f"{node[0]}: Expected two terms: `id` and `val-expr`")
689
-
690
- inner_env = Env({}, env)
691
-
692
- for var, val in node[1]:
693
- if type(var) is not Sym:
694
- raise MyError(f"{node[0]}: Expected symbol for `id` term")
695
- inner_env[var.val] = my_eval(inner_env, val)
696
-
697
- for item in node[2:-1]:
698
- my_eval(inner_env, item)
699
- return my_eval(inner_env, node[-1])
700
-
701
- def syn_import(env: Env, node: Node) -> None:
702
- guard_term(node, 2, 2)
703
-
704
- if type(node[1]) is not Sym:
705
- raise MyError("class name must be an identifier")
706
-
707
- module = node[1].val
708
- try:
709
- obj = __import__(f"auto_editor.lang.lib{module}", fromlist=["lang"])
710
- except ImportError:
711
- raise MyError(f"No module named `{module}`")
712
-
713
- env.update(obj.all())
714
-
715
- def syn_class(env: Env, node: Node) -> None:
716
- if len(node) < 2:
717
- raise MyError(f"{node[0]}: Expects at least 1 term")
718
-
719
- if type(node[1]) is not Sym:
720
- raise MyError("class name must be an identifier")
721
-
722
- attr_len = len(node) - 2
723
- attrs: Any = [None] * (attr_len * 2)
724
- contracts = [None] * attr_len
725
-
726
- for i, item in enumerate(node[2:]):
727
- if type(item) is not tuple or len(item) != 2:
728
- raise MyError(f"{node[0]}: Invalid syntax")
729
-
730
- contracts[i] = my_eval(env, item[1])
731
- attrs[i * 2] = item[0].val
732
- attrs[i * 2 + 1] = contracts[i]
733
-
734
- name = node[1].val
735
- pred = name + "?"
736
- attrs = tuple(attrs)
737
-
738
- env[name] = Proc(
739
- name,
740
- lambda *args: PaletClass(name, attrs, list(args)),
741
- (attr_len, attr_len),
742
- *contracts,
743
- )
744
- env[pred] = Proc(
745
- pred,
746
- lambda v: type(v) is PaletClass and v.name == name and v.attrs == attrs,
747
- (1, 1),
748
- )
749
-
750
- def attr(env: Env, node: Node) -> Any:
751
- guard_term(node, 3, 3)
752
-
753
- if type(node[2]) is not Sym:
754
- raise MyError("@r: attribute must be an identifier")
755
-
756
- base = my_eval(env, node[1])
757
-
758
- if hasattr(base, "__pyx_vtable__"):
759
- try:
760
- return getattr(base, node[2].val)
761
- except AttributeError as e:
762
- raise MyError(e)
763
-
764
- if type(base) is PaletClass:
765
- if type(name := node[2]) is not Sym:
766
- raise MyError("@r: class attribute must be an identifier")
767
-
768
- for i, item in enumerate(base.attrs[0::2]):
769
- if name.val == item:
770
- return base.values[i]
771
-
772
- return my_eval(env, (node[2], node[1]))
773
-
774
- # Procedure definitions
775
- def minclip(oarr: BoolList, _min: int, /) -> BoolList:
776
- arr = np.copy(oarr)
777
- mut_remove_small(arr, _min, replace=1, with_=0)
778
- return arr
779
-
780
- def mincut(oarr: BoolList, _min: int, /) -> BoolList:
781
- arr = np.copy(oarr)
782
- mut_remove_small(arr, _min, replace=0, with_=1)
783
- return arr
784
-
785
- def maxclip(oarr: BoolList, _min: int, /) -> BoolList:
786
- arr = np.copy(oarr)
787
- mut_remove_large(arr, _min, replace=1, with_=0)
788
- return arr
789
-
790
- def maxcut(oarr: BoolList, _min: int, /) -> BoolList:
791
- arr = np.copy(oarr)
792
- mut_remove_large(arr, _min, replace=0, with_=1)
793
- return arr
794
-
795
- def margin(oarr: BoolList, start: int, end: int | None = None, /) -> BoolList:
796
- arr = np.copy(oarr)
797
- if end is None:
798
- mut_margin(arr, start, start)
799
- else:
800
- mut_margin(arr, start, end)
801
- return arr
802
-
803
- def equal_num(*values: object) -> bool:
804
- return all(values[0] == val for val in values[1:])
805
-
806
- def minus(*vals: Number) -> Number:
807
- if len(vals) == 1:
808
- return -vals[0]
809
- return reduce(lambda a, b: a - b, vals)
810
-
811
- def num_div(z: Number, *w: Number) -> Number:
812
- if len(w) == 0:
813
- w = (z,)
814
- z = 1
815
-
816
- for num in w:
817
- if num == 0:
818
- raise MyError("/: division by zero")
819
-
820
- z /= num
821
-
822
- return z
823
-
824
- def int_div(n: int, *m: int) -> int:
825
- if 0 in m:
826
- raise MyError("div: division by zero")
827
-
828
- return reduce(lambda a, b: a // b, m, n)
829
-
830
- def _xor(*vals: Any) -> bool | BoolList:
831
- if is_boolarr(vals[0]):
832
- check_args("xor", vals, (2, None), (is_boolarr,))
833
- return reduce(lambda a, b: boolop(a, b, logical_xor), vals)
834
- check_args("xor", vals, (2, None), (is_bool,))
835
- return reduce(lambda a, b: a ^ b, vals)
836
-
837
- def number_to_string(val: Number) -> str:
838
- return f"{val}"
839
-
840
- def string_to_number(val) -> float:
841
- try:
842
- return float(val)
843
- except Exception:
844
- raise MyError(f"failed to convert {val} to number")
845
-
846
- def palet_join(v: Any, s: str) -> str:
847
- try:
848
- return s.join(v)
849
- except Exception:
850
- raise MyError("join: expected string?")
851
-
852
- def _dtype_to_np(dtype: Sym) -> type[np.generic]:
853
- np_dtype = dtype_map.get(dtype)
854
- if np_dtype is None:
855
- raise MyError(f"Invalid array dtype: {dtype}")
856
- return np_dtype
857
-
858
- def array_proc(dtype: Sym, *vals: Any) -> np.ndarray:
859
- try:
860
- return np.array(vals, dtype=_dtype_to_np(dtype))
861
- except OverflowError:
862
- raise MyError(f"number too large to be converted to {dtype}")
863
-
864
- def make_array(dtype: Sym, size: int, v: int = 0) -> np.ndarray:
865
- try:
866
- return np.array([v] * size, dtype=_dtype_to_np(dtype))
867
- except OverflowError:
868
- raise MyError(f"number too large to be converted to {dtype}")
869
-
870
- def vector_set(vec: list, pos: int, v: Any) -> None:
871
- try:
872
- vec[pos] = v
873
- except IndexError:
874
- raise MyError(f"vector-set: Invalid index {pos}")
875
-
876
- def vector_extend(vec: list, *more_vecs: list) -> None:
877
- for more in more_vecs:
878
- vec.extend(more)
879
-
880
- def list_append(*v: Quoted) -> Quoted:
881
- result = Quoted(tuple())
882
- for item in v:
883
- result.val = result.val + item.val
884
- return result
885
-
886
- def palet_map(proc: Proc, seq: Any) -> Any:
887
- if type(seq) is str:
888
- return str(map(proc, seq))
889
- if type(seq) is Quoted:
890
- return Quoted(tuple(map(proc, seq.val)))
891
- if isinstance(seq, list | range):
892
- return list(map(proc, seq))
893
- elif isinstance(seq, np.ndarray):
894
- vectorized_proc = np.vectorize(proc)
895
- return vectorized_proc(seq)
896
- return proc(seq)
897
-
898
- def palet_member(v: object, seq: Any) -> bool:
899
- if type(v) is Char and type(seq) is str:
900
- return v.val in seq
901
- return v in seq
902
-
903
- def splice(
904
- arr: NDArray, v: int, start: int | None = None, end: int | None = None
905
- ) -> None:
906
- arr[start:end] = v
907
-
908
- def palet_hash(*args: Any) -> dict:
909
- result = {}
910
- if len(args) % 2 == 1:
911
- raise MyError("hash: number of args must be even")
912
- for key, item in zip(args[0::2], args[1::2]):
913
- result[key] = item
914
- return result
915
-
916
- def hash_ref(h: dict, k: object) -> object:
917
- try:
918
- return h[k]
919
- except Exception:
920
- raise MyError("hash-ref: invalid key")
921
-
922
- def hash_set(h: dict[object, object], k: object, v: object) -> None:
923
- h[k] = v
924
-
925
- def hash_remove(h: dict, v: object) -> None:
926
- try:
927
- del h[v]
928
- except Exception:
929
- pass
930
-
931
- def palet_assert(expr: object, msg: str | bool = False) -> None:
932
- if expr is not True:
933
- raise MyError("assert-error" if msg is False else f"assert-error: {msg}")
934
-
935
- def palet_system(cmd: str) -> bool:
936
- try:
937
- return run(cmd, shell=True).returncode == 0
938
- except Exception:
939
- return False
940
-
941
- def palet_system_star(*cmd: str) -> bool:
942
- try:
943
- return run(cmd).returncode == 0
944
- except Exception:
945
- return False
946
-
947
- def change_file_ext(a: str, ext: str) -> str:
948
- import os.path
949
-
950
- base_name = os.path.splitext(a)[0]
951
- return f"{base_name}.{ext}" if ext else base_name
952
-
953
-
954
- return {
955
- # constants
956
- "true": True,
957
- "false": False,
958
- "all": Sym("all"),
959
- # syntax
960
- "lambda": Syntax(syn_lambda),
961
- "λ": Syntax(syn_lambda),
962
- "defn": Syntax(syn_define),
963
- "define": Syntax(syn_define),
964
- "define/c": Syntax(syn_definec),
965
- "set!": Syntax(syn_set),
966
- "incf": Syntax(syn_incf),
967
- "decf": Syntax(syn_decf),
968
- "&=": Syntax(syn_strappend),
969
- "quote": Syntax(syn_quote),
970
- "if": Syntax(syn_if),
971
- "when": Syntax(syn_when),
972
- "cond": Syntax(syn_cond),
973
- "case": Syntax(syn_case),
974
- "let": Syntax(syn_let),
975
- "let*": Syntax(syn_let_star),
976
- "import": Syntax(syn_import),
977
- "class": Syntax(syn_class),
978
- "@r": Syntax(attr),
979
- # loops
980
- "for": Syntax(syn_for),
981
- "for-items": Syntax(syn_for_items),
982
- "while": Syntax(syn_while),
983
- # contracts
984
- "number?": is_num,
985
- "real?": is_real,
986
- "int?": is_int,
987
- "float?": is_float,
988
- "frac?": is_frac,
989
- "nat?": is_nat,
990
- "nat1?": is_nat1,
991
- "threshold?": is_threshold,
992
- "any": any_p,
993
- "bool?": is_bool,
994
- "void?": is_void,
995
- "symbol?": (is_symbol := Contract("symbol?", lambda v: type(v) is Sym)),
996
- "string?": is_str,
997
- "char?": (is_char := Contract("char?", lambda v: type(v) is Char)),
998
- "list?": (is_list := Contract("list?", lambda v: type(v) is Quoted or type(v) is tuple)),
999
- "vector?": (is_vector := Contract("vector?", lambda v: type(v) is list)),
1000
- "array?": (is_array := Contract("array?", lambda v: isinstance(v, np.ndarray))),
1001
- "bool-array?": is_boolarr,
1002
- "range?": (is_range := Contract("range?", lambda v: type(v) is range)),
1003
- "iterable?": is_iterable,
1004
- "sequence?": is_sequence,
1005
- "procedure?": is_proc,
1006
- "contract?": is_cont,
1007
- "hash?": (is_hash := Contract("hash?", lambda v: isinstance(v, dict))),
1008
- "begin": Proc("begin", lambda *x: x[-1] if x else None, (0, None)),
1009
- "void": Proc("void", lambda *v: None, (0, 0)),
1010
- # control / b-arrays
1011
- "not": Proc("not", lambda v: not v if type(v) is bool else logical_not(v), (1, 1), bool_or_barr),
1012
- "and": Syntax(syn_and),
1013
- "or": Syntax(syn_or),
1014
- "xor": Proc("xor", _xor, (2, None), bool_or_barr),
1015
- # booleans
1016
- ">": Proc(">", gt, (2, 2), is_real),
1017
- ">=": Proc(">=", ge, (2, 2), is_real),
1018
- "<": Proc("<", lt, (2, 2), is_real),
1019
- "<=": Proc("<=", le, (2, 2), is_real),
1020
- "=": Proc("=", equal_num, (1, None), is_num),
1021
- "eq?": Proc("eq?", is_, (2, 2)),
1022
- "equal?": Proc("equal?", is_equal, (2, 2)),
1023
- "zero?": UserProc(env, "zero?", ["z"], (is_num,), ((Sym("="), Sym("z"), 0),)),
1024
- "positive?": UserProc(env, "positive?", ["x"], (is_real,), ((Sym(">"), Sym("x"), 0),)),
1025
- "negative?": UserProc(env, "negative?", ["x"], (is_real,), ((Sym("<"), Sym("x"), 0),)),
1026
- "even?": UserProc(
1027
- env, "even?", ["n"], (is_int,), ((Sym("zero?"), (Sym("mod"), Sym("n"), 2)),)),
1028
- "odd?": UserProc(
1029
- env, "odd?", ["n"], (is_int,), ((Sym("not"), (Sym("even?"), Sym("n"))),)),
1030
- ">=/c": Proc(">=/c", gte_c, (1, 1), is_real),
1031
- ">/c": Proc(">/c", gt_c, (1, 1), is_real),
1032
- "<=/c": Proc("<=/c", lte_c, (1, 1), is_real),
1033
- "</c": Proc("</c", lt_c, (1, 1), is_real),
1034
- "between/c": Proc("between/c", between_c, (2, 2), is_real),
1035
- # numbers
1036
- "+": Proc("+", lambda *v: sum(v), (0, None), is_num),
1037
- "-": Proc("-", minus, (1, None), is_num),
1038
- "*": Proc("*", lambda *v: reduce(mul, v, 1), (0, None), is_num),
1039
- "/": Proc("/", num_div, (1, None), is_num),
1040
- "div": Proc("div", int_div, (2, None), is_int),
1041
- "add1": Proc("add1", lambda z: z + 1, (1, 1), is_num),
1042
- "sub1": Proc("sub1", lambda z: z - 1, (1, 1), is_num),
1043
- # reals
1044
- "pow": Proc("pow", pow, (2, 2), is_real),
1045
- "abs": Proc("abs", abs, (1, 1), is_real),
1046
- "round": Proc("round", round, (1, 2), is_real, is_int),
1047
- "max": Proc("max", lambda *v: max(v), (1, None), is_real),
1048
- "min": Proc("min", lambda *v: min(v), (1, None), is_real),
1049
- "max-seq": Proc("max-seq", max, (1, 1), is_sequence),
1050
- "min-seq": Proc("min-seq", min, (1, 1), is_sequence),
1051
- "mod": Proc("mod", mod, (2, 2), is_int),
1052
- "modulo": Proc("modulo", mod, (2, 2), is_int),
1053
- # symbols
1054
- "symbol->string": Proc("symbol->string", str, (1, 1), is_symbol),
1055
- "string->symbol": Proc("string->symbol", Sym, (1, 1), is_str),
1056
- # strings
1057
- "string": Proc("string", lambda *v: reduce(add, v, ""), (0, None), is_char),
1058
- "&": Proc("&", lambda *v: reduce(add, v, ""), (0, None), is_str),
1059
- "split": Proc("split", str.split, (1, 2), is_str, is_str),
1060
- "strip": Proc("strip", str.strip, (1, 1), is_str),
1061
- "str-repeat": Proc("str-repeat", mul, (2, 2), is_str, is_int),
1062
- "startswith": Proc("startswith", str.startswith, (2, 2), is_str),
1063
- "endswith": Proc("endswith", str.endswith, (2, 2), is_str),
1064
- "replace": Proc("replace", str.replace, (3, 4), is_str, is_str, is_str, is_int),
1065
- "title": Proc("title", str.title, (1, 1), is_str),
1066
- "lower": Proc("lower", str.lower, (1, 1), is_str),
1067
- "upper": Proc("upper", str.upper, (1, 1), is_str),
1068
- "join": Proc("join", palet_join, (2, 2), is_vector, is_str),
1069
- "change-file-ext": Proc("change-file-ext", change_file_ext, (2, 2), is_str),
1070
- # format
1071
- "char->int": Proc("char->int", lambda c: ord(c.val), (1, 1), is_char),
1072
- "int->char": Proc("int->char", Char, (1, 1), is_int),
1073
- "~a": Proc("~a", lambda *v: "".join([display_str(a) for a in v]), (0, None)),
1074
- "~s": Proc("~s", lambda *v: " ".join([display_str(a) for a in v]), (0, None)),
1075
- "~v": Proc("~v", lambda *v: " ".join([print_str(a) for a in v]), (0, None)),
1076
- # keyword
1077
- "keyword?": is_keyw,
1078
- "keyword->string": Proc("keyword->string", lambda v: v.val.val, (1, 1), is_keyw),
1079
- "string->keyword": Proc("string->keyword", QuotedKeyword, (1, 1), is_str),
1080
- # lists
1081
- "list": Proc("list", lambda *a: Quoted(a), (0, None)),
1082
- "append": Proc("append", list_append, (0, None), is_list),
1083
- # vectors
1084
- "vector": Proc("vector", lambda *a: list(a), (0, None)),
1085
- "make-vector": Proc(
1086
- "make-vector", lambda size, a=0: [a] * size, (1, 2), is_nat, any_p
1087
- ),
1088
- "add!": Proc("add!", list.append, (2, 2), is_vector, any_p),
1089
- "pop!": Proc("pop!", list.pop, (1, 1), is_vector),
1090
- "vec-set!": Proc("vec-set!", vector_set, (3, 3), is_vector, is_int, any_p),
1091
- "vec-append": Proc("vec-append", lambda *v: reduce(add, v, []), (0, None), is_vector),
1092
- "vec-extend!": Proc("vec-extend!", vector_extend, (2, None), is_vector),
1093
- "sort": Proc("sort", sorted, (1, 1), is_vector),
1094
- "sort!": Proc("sort!", list.sort, (1, 1), is_vector),
1095
- # arrays
1096
- "array": Proc("array", array_proc, (2, None), is_symbol, is_real),
1097
- "make-array": Proc("make-array", make_array, (2, 3), is_symbol, is_nat, is_real),
1098
- "array-splice!": Proc(
1099
- "array-splice!", splice, (2, 4), is_array, is_real, is_int, is_int
1100
- ),
1101
- "array-copy": Proc("array-copy", np.copy, (1, 1), is_array),
1102
- "count-nonzero": Proc("count-nonzero", np.count_nonzero, (1, 1), is_array),
1103
- # bool arrays
1104
- "bool-array": Proc(
1105
- "bool-array", lambda *a: np.array(a, dtype=np.bool_), (1, None), is_nat
1106
- ),
1107
- "margin": Proc("margin", margin, (2, 3), is_boolarr, is_int),
1108
- "mincut": Proc("mincut", mincut, (2, 2), is_boolarr, is_nat),
1109
- "minclip": Proc("minclip", minclip, (2, 2), is_boolarr, is_nat),
1110
- "maxcut": Proc("maxcut", maxcut, (2, 2), is_boolarr, is_nat),
1111
- "maxclip": Proc("maxclip", maxclip, (2, 2), is_boolarr, is_nat),
1112
- # ranges
1113
- "range": Proc("range", range, (1, 3), is_int, is_int, int_not_zero),
1114
- # generic iterables
1115
- "len": Proc("len", len, (1, 1), is_iterable),
1116
- "member": Proc("member", palet_member, (2, 2), any_p, is_sequence),
1117
- "reverse": Proc("reverse", lambda v: v[::-1], (1, 1), is_sequence),
1118
- "ref": Proc("ref", ref, (2, 2), is_sequence, is_int),
1119
- "slice": Proc("slice", p_slice, (2, 4), is_sequence, is_int),
1120
- # procedures
1121
- "map": Proc("map", palet_map, (2, 2), is_proc, is_sequence),
1122
- "apply": Proc("apply", lambda p, s: p(*s), (2, 2), is_proc, is_sequence),
1123
- "and/c": Proc("and/c", andc, (1, None), is_cont),
1124
- "or/c": Proc("or/c", orc, (1, None), is_cont),
1125
- "not/c": Proc("not/c", notc, (1, 1), is_cont),
1126
- # hashs
1127
- "hash": Proc("hash", palet_hash, (0, None)),
1128
- "hash-ref": Proc("hash", hash_ref, (2, 2), is_hash, any_p),
1129
- "hash-set!": Proc("hash-set!", hash_set, (3, 3), is_hash, any_p, any_p),
1130
- "has-key?": Proc("has-key?", lambda h, k: k in h, (2, 2), is_hash, any_p),
1131
- "hash-remove!": Proc("hash-remove!", hash_remove, (2, 2), is_hash, any_p),
1132
- "hash-update!": UserProc(env, "hash-update!", ["h", "v", "up"], (is_hash, any_p),
1133
- (
1134
- (Sym("hash-set!"), Sym("h"), Sym("v"), (Sym("up"), (Sym("h"), Sym("v"))),),
1135
- ),
1136
- ),
1137
- # i/o
1138
- "file-exists?": Proc("file-exists", os.path.isfile, (1, 1), is_str),
1139
- "open-input-file": Proc("open-input-file", initInPort, (1, 1), is_str),
1140
- "input-port?": (ip := Contract("input-port?", lambda v: type(v) is InputPort)),
1141
- "read-line": Proc("read-line",
1142
- lambda f: (r := f.port.readline(), None if r == "" else r.rstrip())[-1],
1143
- (1, 1), ip),
1144
- "open-output-file": Proc("open-output-file", initOutPort, (1, 1), is_str),
1145
- "output-port?": (op := Contract("output-port?", lambda v: type(v) is OutputPort)),
1146
- "port?": (port := Contract("port?", orc(ip, op))),
1147
- "close-port": Proc("close-port", lambda p: p.close, (1, 1), port),
1148
- "closed?": Proc("closed?", lambda o: o.closed, (1, 1), port),
1149
- # subprocess
1150
- "system": Proc("system", palet_system, (1, 1), is_str),
1151
- "system*": Proc("system*", palet_system_star, (1, None), is_str),
1152
- # printing
1153
- "display": Proc("display",
1154
- lambda v, f=None: print(display_str(v), end="", file=f), (1, 2), any_p, op),
1155
- "displayln": Proc("displayln",
1156
- lambda v, f=None: print(display_str(v), file=f), (1, 2), any_p, op),
1157
- "print": Proc("print",
1158
- lambda v, f=None: print(print_str(v), end="", file=f), (1, 2), any_p, op),
1159
- "println": Proc("println",
1160
- lambda v, f=None: print(print_str(v), file=f), (1, 2), any_p, op),
1161
- # actions
1162
- "assert": Proc("assert", palet_assert, (1, 2), any_p, orc(is_str, False)),
1163
- "error": Proc("error", raise_, (1, 1), is_str),
1164
- "sleep": Proc("sleep", sleep, (1, 1), is_int_or_float),
1165
- # conversions
1166
- "number->string": Proc("number->string", number_to_string, (1, 1), is_num),
1167
- "string->number": Proc("string->number", string_to_number, (1, 1), is_str),
1168
- "string->vector": Proc(
1169
- "string->vector", lambda s: [Char(c) for c in s], (1, 1), is_str
1170
- ),
1171
- "range->vector": Proc("range->vector", list, (1, 1), is_range),
1172
- # av
1173
- "encoder": Proc("encoder", lambda x: bv.Codec(x, "w"), (1, 1), is_str),
1174
- "decoder": Proc("decoder", lambda x: bv.Codec(x), (1, 1), is_str),
1175
- # reflexion
1176
- "var-exists?": Proc("var-exists?", lambda sym: sym.val in env, (1, 1), is_symbol),
1177
- "rename": Syntax(syn_rename),
1178
- "delete": Syntax(syn_delete),
1179
- "eval": Proc("eval",
1180
- lambda tl: my_eval(env, tl.val) if type(tl) is Quoted
1181
- else (my_eval(env, tl) if type(tl) is Sym else tl),
1182
- (1, 1)
1183
- ),
1184
- }