jjinx 0.0.1__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.
jinx/primitives.py ADDED
@@ -0,0 +1,490 @@
1
+ """Primitives.
2
+
3
+ Names of sequences of characters that are assigned some meaning in the J language.
4
+
5
+ These objects are not tied to their implementation here and are defined here for
6
+ spelling (recognition of fragments of a sentence) and rank and obverse lookups.
7
+
8
+ The functions that implement these primitives are added at evaluation time (this allows
9
+ potentially different implementations to be used, e.g. pure Python, NumPy, etc.).
10
+
11
+ See:
12
+ - https://code.jsoftware.com/wiki/NuVoc
13
+ - https://code.jsoftware.com/wiki/Vocabulary/Inverses
14
+ """
15
+
16
+ from jinx.vocabulary import Adverb, Conjunction, Copula, Dyad, Monad, Verb
17
+
18
+ # The monad and dyad fields are not populated here (they default to None).
19
+ # This is to allow the correct implementation of the verb to be looked up
20
+ # when the verb is evaluated in the context of a sentence. It also allows
21
+ # different implementations of a verb to be chosen (pure Python, NumPy, etc.)
22
+
23
+ INFINITY = float("inf")
24
+
25
+ PRIMITIVES: list[Verb | Adverb | Conjunction | Copula] = [
26
+ Verb(
27
+ "=",
28
+ "EQ",
29
+ monad=Monad(name="Self-Classify", rank=INFINITY),
30
+ dyad=Dyad(name="Equal", left_rank=0, right_rank=0, is_commutative=True),
31
+ ),
32
+ Copula("=.", "EQDOT"),
33
+ Copula("=:", "EQCO"),
34
+ Verb(
35
+ "+",
36
+ "PLUS",
37
+ monad=Monad(name="Conjugate", rank=0),
38
+ dyad=Dyad(name="Plus", left_rank=0, right_rank=0, is_commutative=True),
39
+ obverse="+",
40
+ ),
41
+ Verb(
42
+ "+.",
43
+ "PLUSDOT",
44
+ monad=Monad(name="Real / Imaginary", rank=0),
45
+ dyad=Dyad(name="GCD (or)", left_rank=0, right_rank=0, is_commutative=True),
46
+ ),
47
+ Verb(
48
+ "+:",
49
+ "PLUSCO",
50
+ monad=Monad(name="Double", rank=0),
51
+ dyad=Dyad(name="Not-Or", left_rank=0, right_rank=0, is_commutative=True),
52
+ obverse="-:",
53
+ ),
54
+ Verb(
55
+ "*",
56
+ "STAR",
57
+ monad=Monad(name="Signum", rank=0),
58
+ dyad=Dyad(name="Times", left_rank=0, right_rank=0, is_commutative=True),
59
+ obverse="%:",
60
+ ),
61
+ Verb(
62
+ "*.",
63
+ "STARDOT",
64
+ monad=Monad(name="Length/Angle", rank=0),
65
+ dyad=Dyad(name="LCM (and)", left_rank=0, right_rank=0, is_commutative=True),
66
+ ),
67
+ Verb(
68
+ "*:",
69
+ "STARCO",
70
+ monad=Monad(name="Square", rank=0),
71
+ dyad=Dyad(name="Not-And", left_rank=0, right_rank=0, is_commutative=True),
72
+ obverse="%:",
73
+ ),
74
+ Verb(
75
+ "-",
76
+ "MINUS",
77
+ monad=Monad(name="Negate", rank=0),
78
+ dyad=Dyad(name="Minus", left_rank=0, right_rank=0, is_commutative=False),
79
+ obverse="-",
80
+ ),
81
+ Verb(
82
+ "-.",
83
+ "MINUSDOT",
84
+ monad=Monad(name="Not", rank=0),
85
+ dyad=Dyad(
86
+ name="Less", left_rank=INFINITY, right_rank=INFINITY, is_commutative=False
87
+ ),
88
+ obverse="-.",
89
+ ),
90
+ Verb(
91
+ "-:",
92
+ "MINUSCO",
93
+ monad=Monad(name="Halve", rank=0),
94
+ dyad=Dyad(
95
+ name="Match", left_rank=INFINITY, right_rank=INFINITY, is_commutative=True
96
+ ),
97
+ obverse="+:",
98
+ ),
99
+ Verb(
100
+ "%",
101
+ "PERCENT",
102
+ monad=Monad(name="Reciprocal", rank=0),
103
+ dyad=Dyad(name="Divide", left_rank=0, right_rank=0, is_commutative=False),
104
+ obverse="%",
105
+ ),
106
+ Verb(
107
+ "%:",
108
+ "PERCENTCO",
109
+ monad=Monad(name="Square Root", rank=0),
110
+ dyad=Dyad(name="Root", left_rank=0, right_rank=0, is_commutative=False),
111
+ obverse="%:",
112
+ ),
113
+ Verb(
114
+ "^",
115
+ "HAT",
116
+ monad=Monad(name="Exponential", rank=0),
117
+ dyad=Dyad(name="Power", left_rank=0, right_rank=0, is_commutative=False),
118
+ obverse="^.",
119
+ ),
120
+ Verb(
121
+ "^.",
122
+ "HATDOT",
123
+ monad=Monad(name="Natural Log", rank=0),
124
+ dyad=Dyad(name="Logarithm", left_rank=0, right_rank=0, is_commutative=False),
125
+ obverse="^",
126
+ ),
127
+ Conjunction("^:", "HATCO"),
128
+ Verb(
129
+ "<",
130
+ "LT",
131
+ monad=Monad(name="Box", rank=INFINITY),
132
+ dyad=Dyad(name="Less Than", left_rank=0, right_rank=0, is_commutative=False),
133
+ obverse=">",
134
+ ),
135
+ Verb(
136
+ "<.",
137
+ "LTDOT",
138
+ monad=Monad(name="Floor", rank=0),
139
+ dyad=Dyad(name="Min", left_rank=0, right_rank=0, is_commutative=True),
140
+ ),
141
+ Verb(
142
+ ">",
143
+ "GT",
144
+ monad=Monad(name="Open", rank=0),
145
+ dyad=Dyad(name="Larger Than", left_rank=0, right_rank=0, is_commutative=False),
146
+ obverse="<",
147
+ ),
148
+ Verb(
149
+ ">.",
150
+ "GTDOT",
151
+ monad=Monad(name="Ceiling", rank=0),
152
+ dyad=Dyad(name="Max", left_rank=0, right_rank=0, is_commutative=True),
153
+ ),
154
+ Verb(
155
+ "<:",
156
+ "LTCO",
157
+ monad=Monad(name="Decrement", rank=0),
158
+ dyad=Dyad(
159
+ name="Less Or Equal", left_rank=0, right_rank=0, is_commutative=False
160
+ ),
161
+ obverse=">:",
162
+ ),
163
+ Verb(
164
+ ">:",
165
+ "GTCO",
166
+ monad=Monad(name="Increment", rank=0),
167
+ dyad=Dyad(
168
+ name="Larger Or Equal", left_rank=0, right_rank=0, is_commutative=False
169
+ ),
170
+ obverse="<:",
171
+ ),
172
+ Adverb(
173
+ "~",
174
+ "TILDE",
175
+ monad=Monad(name="Reflex", rank=INFINITY),
176
+ # N.B. Left and right rank depend on the verb that this adverb is applied to.
177
+ dyad=Dyad(name="Passive", left_rank=0, right_rank=0, is_commutative=True),
178
+ ),
179
+ Verb(
180
+ "~.",
181
+ "TILDEDOT",
182
+ monad=Monad(name="Nub", rank=INFINITY),
183
+ ),
184
+ Verb(
185
+ "~:",
186
+ "TILDECO",
187
+ monad=Monad(name="Nub Sieve", rank=INFINITY),
188
+ dyad=Dyad(
189
+ name="Not-Equal",
190
+ left_rank=0,
191
+ right_rank=0,
192
+ is_commutative=True,
193
+ ),
194
+ ),
195
+ Verb(
196
+ "$",
197
+ "DOLLAR",
198
+ monad=Monad(name="Shape Of", rank=INFINITY),
199
+ dyad=Dyad(name="Shape", left_rank=1, right_rank=INFINITY, is_commutative=False),
200
+ ),
201
+ Conjunction("@", "AT"),
202
+ Conjunction("@:", "ATCO"),
203
+ Verb(
204
+ "i.",
205
+ "IDOT",
206
+ monad=Monad(name="Integers", rank=1),
207
+ dyad=Dyad(
208
+ name="Index Of",
209
+ left_rank=INFINITY,
210
+ right_rank=INFINITY,
211
+ is_commutative=False,
212
+ ),
213
+ ),
214
+ Verb(
215
+ "I.",
216
+ "ICAPDOT",
217
+ monad=Monad(name="Indices", rank=1),
218
+ dyad=Dyad(
219
+ name="Interval Index",
220
+ left_rank=INFINITY,
221
+ right_rank=INFINITY,
222
+ is_commutative=False,
223
+ ),
224
+ obverse="(+/ @:(=/ i.@>:@(>./)@(0&,)))",
225
+ ),
226
+ Adverb(
227
+ "/",
228
+ "SLASH",
229
+ monad=Monad(name="Insert", rank=INFINITY),
230
+ dyad=Dyad(
231
+ name="Table", left_rank=INFINITY, right_rank=INFINITY, is_commutative=False
232
+ ),
233
+ ),
234
+ Adverb(
235
+ "\\",
236
+ "BSLASH",
237
+ monad=Monad(name="Prefix", rank=INFINITY),
238
+ dyad=Dyad(name="Infix", left_rank=0, right_rank=INFINITY, is_commutative=False),
239
+ ),
240
+ Adverb(
241
+ "\\.",
242
+ "BSLASHDOT",
243
+ monad=Monad(name="Suffix", rank=INFINITY),
244
+ dyad=Dyad(
245
+ name="Outfix", left_rank=0, right_rank=INFINITY, is_commutative=False
246
+ ),
247
+ ),
248
+ Conjunction('"', "RANK"),
249
+ Verb(
250
+ ",",
251
+ "COMMA",
252
+ monad=Monad(name="Ravel", rank=INFINITY),
253
+ dyad=Dyad(
254
+ name="Append", left_rank=INFINITY, right_rank=INFINITY, is_commutative=False
255
+ ),
256
+ ),
257
+ Verb(
258
+ ",.",
259
+ "COMMADOT",
260
+ monad=Monad(name="Ravel Items", rank=INFINITY),
261
+ dyad=Dyad(
262
+ name="Stitch", left_rank=INFINITY, right_rank=INFINITY, is_commutative=False
263
+ ),
264
+ ),
265
+ Verb(
266
+ ",:",
267
+ "COMMACO",
268
+ monad=Monad(name="Itemize", rank=INFINITY),
269
+ dyad=Dyad(
270
+ name="Laminate",
271
+ left_rank=INFINITY,
272
+ right_rank=INFINITY,
273
+ is_commutative=False,
274
+ ),
275
+ obverse="{.",
276
+ ),
277
+ Verb(
278
+ "|",
279
+ "BAR",
280
+ monad=Monad(name="Magnitude", rank=0),
281
+ dyad=Dyad(name="Residue", left_rank=0, right_rank=0, is_commutative=False),
282
+ ),
283
+ Verb(
284
+ "|.",
285
+ "BARDOT",
286
+ monad=Monad(name="Reverse", rank=INFINITY),
287
+ dyad=Dyad(
288
+ name="Rotate", left_rank=1, right_rank=INFINITY, is_commutative=False
289
+ ),
290
+ obverse="|.",
291
+ ),
292
+ Verb(
293
+ "|:",
294
+ "BARCO",
295
+ monad=Monad(name="Transpose", rank=INFINITY),
296
+ dyad=Dyad(
297
+ name="Rearrange Axes",
298
+ left_rank=1,
299
+ right_rank=INFINITY,
300
+ is_commutative=False,
301
+ ),
302
+ obverse="|:",
303
+ ),
304
+ Verb(
305
+ "#",
306
+ "NUMBER",
307
+ monad=Monad(name="Tally", rank=INFINITY),
308
+ dyad=Dyad(name="Copy", left_rank=1, right_rank=INFINITY, is_commutative=False),
309
+ ),
310
+ Verb(
311
+ "#.",
312
+ "NUMBERDOT",
313
+ monad=Monad(name="Base 2", rank=1),
314
+ dyad=Dyad(
315
+ name="Base",
316
+ left_rank=1,
317
+ right_rank=1,
318
+ is_commutative=False,
319
+ ),
320
+ obverse="#:",
321
+ ),
322
+ Verb(
323
+ "#:",
324
+ "NUMBERCO",
325
+ monad=Monad(name="Antibase 2", rank=INFINITY),
326
+ dyad=Dyad(
327
+ name="Antibase",
328
+ left_rank=1,
329
+ right_rank=0,
330
+ is_commutative=False,
331
+ ),
332
+ obverse="#.",
333
+ ),
334
+ Verb(
335
+ "[",
336
+ "SQUARELF",
337
+ monad=Monad(name="Same", rank=INFINITY),
338
+ dyad=Dyad(
339
+ name="LEFT", left_rank=INFINITY, right_rank=INFINITY, is_commutative=False
340
+ ),
341
+ obverse="[",
342
+ ),
343
+ Verb(
344
+ "[:",
345
+ "SQUARELFCO",
346
+ monad=Monad(name="Cap", rank=INFINITY),
347
+ ),
348
+ Verb(
349
+ "]",
350
+ "SQUARERF",
351
+ monad=Monad(name="Same", rank=INFINITY),
352
+ dyad=Dyad(
353
+ name="RIGHT", left_rank=INFINITY, right_rank=INFINITY, is_commutative=False
354
+ ),
355
+ obverse="]",
356
+ ),
357
+ Conjunction("&", "AMPM"),
358
+ Adverb(
359
+ "/.",
360
+ "SLASHDOT",
361
+ monad=Monad(name="Oblique", rank=INFINITY),
362
+ dyad=Dyad(
363
+ name="Key",
364
+ left_rank=INFINITY,
365
+ right_rank=INFINITY,
366
+ is_commutative=False,
367
+ ),
368
+ ),
369
+ Verb(
370
+ "/:",
371
+ "SLASHCO",
372
+ monad=Monad(name="Grade Up", rank=INFINITY),
373
+ dyad=Dyad(
374
+ name="Sort Up",
375
+ left_rank=INFINITY,
376
+ right_rank=INFINITY,
377
+ is_commutative=False,
378
+ ),
379
+ obverse="/:",
380
+ ),
381
+ Verb(
382
+ "\\:",
383
+ "BSLASHCO",
384
+ monad=Monad(name="Grade Down", rank=INFINITY),
385
+ dyad=Dyad(
386
+ name="Sort Down",
387
+ left_rank=INFINITY,
388
+ right_rank=INFINITY,
389
+ is_commutative=False,
390
+ ),
391
+ obverse="/:@|.",
392
+ ),
393
+ Verb(
394
+ "!",
395
+ "BANG",
396
+ monad=Monad(name="Factorial", rank=0),
397
+ dyad=Dyad(
398
+ name="Out Of",
399
+ left_rank=0,
400
+ right_rank=0,
401
+ is_commutative=False,
402
+ ),
403
+ ),
404
+ Conjunction("&.:", "AMPDOTCO"),
405
+ Conjunction("&.", "AMPDOT"),
406
+ Verb(
407
+ "{",
408
+ "CURLYLF",
409
+ monad=Monad(name="Catalog", rank=1),
410
+ dyad=Dyad(
411
+ name="From",
412
+ left_rank=0,
413
+ right_rank=INFINITY,
414
+ is_commutative=False,
415
+ ),
416
+ ),
417
+ Verb(
418
+ "{.",
419
+ "CURLYLFDOT",
420
+ monad=Monad(name="Head", rank=INFINITY),
421
+ dyad=Dyad(
422
+ name="Take",
423
+ left_rank=1,
424
+ right_rank=INFINITY,
425
+ is_commutative=False,
426
+ ),
427
+ obverse=",:",
428
+ ),
429
+ Verb(
430
+ "}.",
431
+ "CURLYRTDOT",
432
+ monad=Monad(name="Behead", rank=INFINITY),
433
+ dyad=Dyad(
434
+ name="Drop",
435
+ left_rank=1,
436
+ right_rank=INFINITY,
437
+ is_commutative=False,
438
+ ),
439
+ ),
440
+ Verb(
441
+ "{:",
442
+ "CURLYLFCO",
443
+ monad=Monad(name="Tail", rank=INFINITY),
444
+ dyad=None,
445
+ ),
446
+ Verb(
447
+ "}:",
448
+ "CURLYRTCO",
449
+ monad=Monad(name="Curtail", rank=INFINITY),
450
+ dyad=None,
451
+ ),
452
+ Verb(
453
+ ";",
454
+ "SEMI",
455
+ monad=Monad(name="Raze", rank=INFINITY),
456
+ dyad=Dyad(
457
+ name="LINK",
458
+ left_rank=INFINITY,
459
+ right_rank=INFINITY,
460
+ is_commutative=False,
461
+ ),
462
+ ),
463
+ Verb(
464
+ "?",
465
+ "QUERY",
466
+ monad=Monad(name="Roll", rank=0),
467
+ dyad=Dyad(
468
+ name="Deal",
469
+ left_rank=0,
470
+ right_rank=0,
471
+ is_commutative=False,
472
+ ),
473
+ ),
474
+ Verb(
475
+ ";:",
476
+ "SEMICO",
477
+ monad=Monad(name="Words", rank=1),
478
+ dyad=Dyad(
479
+ name="Sequential Machine",
480
+ left_rank=INFINITY,
481
+ right_rank=INFINITY,
482
+ is_commutative=False,
483
+ ),
484
+ obverse="""}:@;@(,&' '&.>"1)""",
485
+ ),
486
+ Conjunction("`", "GRAVE"),
487
+ ]
488
+
489
+
490
+ PRIMITIVE_MAP = {primitive.name: primitive for primitive in PRIMITIVES}
jinx/shell.py ADDED
@@ -0,0 +1,68 @@
1
+ import argparse
2
+ import cmd
3
+ import sys
4
+
5
+ from jinx.errors import BaseJError, SpellingError
6
+ from jinx.execution.executor import Executor, load_executor
7
+ from jinx.vocabulary import PartOfSpeechT
8
+ from jinx.word_evaluation import evaluate_words, print_words
9
+ from jinx.word_formation import form_words
10
+ from jinx.word_spelling import spell_words
11
+
12
+
13
+ class Shell(cmd.Cmd):
14
+ prompt = " "
15
+
16
+ def __init__(self, executor: Executor):
17
+ super().__init__()
18
+ self.variables: dict[str, PartOfSpeechT] = {}
19
+ self.executor = executor
20
+
21
+ def do_exit(self, _):
22
+ return True
23
+
24
+ def default(self, line):
25
+ words = form_words(line)
26
+ try:
27
+ words = spell_words(words)
28
+ except SpellingError as e:
29
+ print(e, file=sys.stderr)
30
+ return
31
+ try:
32
+ result = evaluate_words(self.executor, words, self.variables)
33
+ print_words(self.executor, result, self.variables)
34
+ except BaseJError as error:
35
+ print(f"{type(error).__name__}: {error}", file=sys.stderr)
36
+
37
+ def do_EOF(self, _):
38
+ return True
39
+
40
+ # '?' is a primitive verb in J and we want the Cmd class to disregard it.
41
+ # and not treat it as a help command.
42
+ def do_help(self, line):
43
+ return self.default("?" + line)
44
+
45
+
46
+ def main():
47
+ """Entry point for the jinx shell."""
48
+ parser = argparse.ArgumentParser(description="Jinx shell")
49
+ parser.add_argument(
50
+ "--executor",
51
+ type=str,
52
+ choices=["numpy", "jax"],
53
+ default="numpy",
54
+ help="Executor to use.",
55
+ )
56
+ args = parser.parse_args()
57
+
58
+ # Currently only the "numpy" executor is implemented.
59
+ executor = load_executor(args.executor)
60
+
61
+ try:
62
+ Shell(executor).cmdloop()
63
+ except EOFError:
64
+ pass
65
+
66
+
67
+ if __name__ == "__main__":
68
+ main()