tengwar 0.3.3__py3-none-any.whl → 0.3.4__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.
- tengwar/__init__.py +1 -1
- tengwar/interpreter.py +134 -36
- {tengwar-0.3.3.dist-info → tengwar-0.3.4.dist-info}/METADATA +1 -1
- {tengwar-0.3.3.dist-info → tengwar-0.3.4.dist-info}/RECORD +8 -8
- {tengwar-0.3.3.dist-info → tengwar-0.3.4.dist-info}/WHEEL +0 -0
- {tengwar-0.3.3.dist-info → tengwar-0.3.4.dist-info}/entry_points.txt +0 -0
- {tengwar-0.3.3.dist-info → tengwar-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {tengwar-0.3.3.dist-info → tengwar-0.3.4.dist-info}/top_level.txt +0 -0
tengwar/__init__.py
CHANGED
tengwar/interpreter.py
CHANGED
|
@@ -75,18 +75,12 @@ class TengwarVector(TengwarValue):
|
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
class TengwarLazy(TengwarValue):
|
|
78
|
-
"""Lazy sequence —
|
|
79
|
-
def __init__(self,
|
|
80
|
-
self.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
val = self.init_val
|
|
85
|
-
for _ in range(n - 1):
|
|
86
|
-
val = call_fn(self.gen_fn, [val])
|
|
87
|
-
result.append(val)
|
|
88
|
-
return result
|
|
89
|
-
def __repr__(self): return f'<lazy-seq from {repr(self.init_val)}>'
|
|
78
|
+
"""Lazy sequence — uses a generator factory for composable lazy ops."""
|
|
79
|
+
def __init__(self, make_gen):
|
|
80
|
+
self._make_gen = make_gen # callable that returns a fresh generator
|
|
81
|
+
def __iter__(self):
|
|
82
|
+
return self._make_gen()
|
|
83
|
+
def __repr__(self): return '<lazy-seq>'
|
|
90
84
|
|
|
91
85
|
|
|
92
86
|
class TengwarClosure(TengwarValue):
|
|
@@ -543,6 +537,8 @@ class Interpreter:
|
|
|
543
537
|
return TengwarFloat(math.sqrt(args[0].value))
|
|
544
538
|
|
|
545
539
|
def _builtin_mod(self, args):
|
|
540
|
+
if args[1].value == 0:
|
|
541
|
+
raise RuntimeError_("Modulo by zero")
|
|
546
542
|
return TengwarInt(args[0].value % args[1].value)
|
|
547
543
|
|
|
548
544
|
def _builtin_len(self, args):
|
|
@@ -642,15 +638,30 @@ class Interpreter:
|
|
|
642
638
|
return TengwarVector(vec.elements[start:end])
|
|
643
639
|
|
|
644
640
|
def _builtin_map(self, args):
|
|
645
|
-
fn,
|
|
646
|
-
if
|
|
647
|
-
|
|
648
|
-
|
|
641
|
+
fn, seq = args[0], args[1]
|
|
642
|
+
if isinstance(seq, TengwarLazy):
|
|
643
|
+
interp = self
|
|
644
|
+
parent = seq._make_gen
|
|
645
|
+
def make_gen():
|
|
646
|
+
for val in parent():
|
|
647
|
+
yield interp._call_function(fn, [val])
|
|
648
|
+
return TengwarLazy(make_gen)
|
|
649
|
+
if not isinstance(seq, TengwarVector):
|
|
650
|
+
raise RuntimeError_("map requires a vector or lazy sequence")
|
|
651
|
+
return TengwarVector([self._call_function(fn, [e]) for e in seq.elements])
|
|
649
652
|
|
|
650
653
|
def _builtin_filter(self, args):
|
|
651
|
-
fn,
|
|
654
|
+
fn, seq = args[0], args[1]
|
|
655
|
+
if isinstance(seq, TengwarLazy):
|
|
656
|
+
interp = self
|
|
657
|
+
parent = seq._make_gen
|
|
658
|
+
def make_gen():
|
|
659
|
+
for val in parent():
|
|
660
|
+
if interp._is_truthy(interp._call_function(fn, [val])):
|
|
661
|
+
yield val
|
|
662
|
+
return TengwarLazy(make_gen)
|
|
652
663
|
result = []
|
|
653
|
-
for e in
|
|
664
|
+
for e in seq.elements:
|
|
654
665
|
if self._is_truthy(self._call_function(fn, [e])):
|
|
655
666
|
result.append(e)
|
|
656
667
|
return TengwarVector(result)
|
|
@@ -745,13 +756,22 @@ class Interpreter:
|
|
|
745
756
|
def _builtin_head(self, args):
|
|
746
757
|
vec = args[0]
|
|
747
758
|
if isinstance(vec, TengwarLazy):
|
|
748
|
-
|
|
759
|
+
for val in vec:
|
|
760
|
+
return val
|
|
761
|
+
raise RuntimeError_("head of empty lazy sequence")
|
|
749
762
|
if not vec.elements:
|
|
750
763
|
raise RuntimeError_("head of empty vector")
|
|
751
764
|
return vec.elements[0]
|
|
752
765
|
|
|
753
766
|
def _builtin_tail(self, args):
|
|
754
767
|
vec = args[0]
|
|
768
|
+
if isinstance(vec, TengwarLazy):
|
|
769
|
+
parent = vec._make_gen
|
|
770
|
+
def make_gen():
|
|
771
|
+
gen = parent()
|
|
772
|
+
next(gen, None) # skip first
|
|
773
|
+
yield from gen
|
|
774
|
+
return TengwarLazy(make_gen)
|
|
755
775
|
if not vec.elements:
|
|
756
776
|
raise RuntimeError_("tail of empty vector")
|
|
757
777
|
return TengwarVector(vec.elements[1:])
|
|
@@ -764,6 +784,11 @@ class Interpreter:
|
|
|
764
784
|
|
|
765
785
|
def _builtin_nth(self, args):
|
|
766
786
|
col, idx = args[0], args[1].value
|
|
787
|
+
if isinstance(col, TengwarLazy):
|
|
788
|
+
for i, val in enumerate(col):
|
|
789
|
+
if i == idx:
|
|
790
|
+
return val
|
|
791
|
+
raise RuntimeError_(f"nth: index {idx} out of range")
|
|
767
792
|
if isinstance(col, TengwarTuple): return col.elements[idx]
|
|
768
793
|
if isinstance(col, TengwarVector): return col.elements[idx]
|
|
769
794
|
raise RuntimeError_(f"Cannot nth into {type(col).__name__}")
|
|
@@ -897,8 +922,16 @@ class Interpreter:
|
|
|
897
922
|
def _builtin_enumerate(self, args):
|
|
898
923
|
"""(enumerate vec) = vector of (index, element) tuples"""
|
|
899
924
|
vec = args[0]
|
|
925
|
+
if isinstance(vec, TengwarLazy):
|
|
926
|
+
parent = vec._make_gen
|
|
927
|
+
def make_gen():
|
|
928
|
+
i = 0
|
|
929
|
+
for val in parent():
|
|
930
|
+
yield TengwarTuple([TengwarInt(i), val])
|
|
931
|
+
i += 1
|
|
932
|
+
return TengwarLazy(make_gen)
|
|
900
933
|
if not isinstance(vec, TengwarVector):
|
|
901
|
-
raise RuntimeError_("enumerate requires a vector")
|
|
934
|
+
raise RuntimeError_("enumerate requires a vector or lazy sequence")
|
|
902
935
|
return TengwarVector([
|
|
903
936
|
TengwarTuple([TengwarInt(i), e])
|
|
904
937
|
for i, e in enumerate(vec.elements)
|
|
@@ -915,10 +948,25 @@ class Interpreter:
|
|
|
915
948
|
def _builtin_apply(self, args):
|
|
916
949
|
fn, arg_vec = args[0], args[1]
|
|
917
950
|
if isinstance(arg_vec, TengwarVector):
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
951
|
+
elems = arg_vec.elements
|
|
952
|
+
elif isinstance(arg_vec, TengwarTuple):
|
|
953
|
+
elems = arg_vec.elements
|
|
954
|
+
else:
|
|
955
|
+
elems = [arg_vec]
|
|
956
|
+
if not elems:
|
|
957
|
+
raise RuntimeError_("apply: cannot apply function to empty collection")
|
|
958
|
+
if len(elems) == 1:
|
|
959
|
+
try:
|
|
960
|
+
return self._call_function(fn, elems)
|
|
961
|
+
except (TypeError, IndexError):
|
|
962
|
+
raise RuntimeError_("apply: function requires more arguments")
|
|
963
|
+
if len(elems) == 2:
|
|
964
|
+
return self._call_function(fn, elems)
|
|
965
|
+
# >2 args: reduce (Clojure-style variadic apply)
|
|
966
|
+
acc = self._call_function(fn, [elems[0], elems[1]])
|
|
967
|
+
for e in elems[2:]:
|
|
968
|
+
acc = self._call_function(fn, [acc, e])
|
|
969
|
+
return acc
|
|
922
970
|
|
|
923
971
|
def _builtin_err(self, args):
|
|
924
972
|
raise RuntimeError_(self._display(args[0]) if args else "error")
|
|
@@ -1014,17 +1062,39 @@ class Interpreter:
|
|
|
1014
1062
|
def _builtin_take(self, args):
|
|
1015
1063
|
n, seq = int(self._num_val(args[0])), args[1]
|
|
1016
1064
|
if isinstance(seq, TengwarLazy):
|
|
1017
|
-
|
|
1065
|
+
result = []
|
|
1066
|
+
for val in seq:
|
|
1067
|
+
result.append(val)
|
|
1068
|
+
if len(result) >= n:
|
|
1069
|
+
break
|
|
1070
|
+
return TengwarVector(result)
|
|
1018
1071
|
return TengwarVector(seq.elements[:n])
|
|
1019
1072
|
|
|
1020
1073
|
def _builtin_drop(self, args):
|
|
1021
|
-
n,
|
|
1022
|
-
|
|
1074
|
+
n, seq = int(self._num_val(args[0])), args[1]
|
|
1075
|
+
if isinstance(seq, TengwarLazy):
|
|
1076
|
+
parent = seq._make_gen
|
|
1077
|
+
count = n
|
|
1078
|
+
def make_gen():
|
|
1079
|
+
gen = parent()
|
|
1080
|
+
for _ in range(count):
|
|
1081
|
+
next(gen, None)
|
|
1082
|
+
yield from gen
|
|
1083
|
+
return TengwarLazy(make_gen)
|
|
1084
|
+
return TengwarVector(seq.elements[n:])
|
|
1023
1085
|
|
|
1024
1086
|
def _builtin_take_while(self, args):
|
|
1025
|
-
fn,
|
|
1087
|
+
fn, seq = args[0], args[1]
|
|
1088
|
+
if isinstance(seq, TengwarLazy):
|
|
1089
|
+
result = []
|
|
1090
|
+
for val in seq:
|
|
1091
|
+
if self._is_truthy(self._call_function(fn, [val])):
|
|
1092
|
+
result.append(val)
|
|
1093
|
+
else:
|
|
1094
|
+
break
|
|
1095
|
+
return TengwarVector(result)
|
|
1026
1096
|
result = []
|
|
1027
|
-
for e in
|
|
1097
|
+
for e in seq.elements:
|
|
1028
1098
|
if self._is_truthy(self._call_function(fn, [e])):
|
|
1029
1099
|
result.append(e)
|
|
1030
1100
|
else:
|
|
@@ -1032,10 +1102,21 @@ class Interpreter:
|
|
|
1032
1102
|
return TengwarVector(result)
|
|
1033
1103
|
|
|
1034
1104
|
def _builtin_drop_while(self, args):
|
|
1035
|
-
fn,
|
|
1105
|
+
fn, seq = args[0], args[1]
|
|
1106
|
+
if isinstance(seq, TengwarLazy):
|
|
1107
|
+
interp = self
|
|
1108
|
+
parent = seq._make_gen
|
|
1109
|
+
def make_gen():
|
|
1110
|
+
dropping = True
|
|
1111
|
+
for val in parent():
|
|
1112
|
+
if dropping and interp._is_truthy(interp._call_function(fn, [val])):
|
|
1113
|
+
continue
|
|
1114
|
+
dropping = False
|
|
1115
|
+
yield val
|
|
1116
|
+
return TengwarLazy(make_gen)
|
|
1036
1117
|
dropping = True
|
|
1037
1118
|
result = []
|
|
1038
|
-
for e in
|
|
1119
|
+
for e in seq.elements:
|
|
1039
1120
|
if dropping and self._is_truthy(self._call_function(fn, [e])):
|
|
1040
1121
|
continue
|
|
1041
1122
|
dropping = False
|
|
@@ -1089,10 +1170,20 @@ class Interpreter:
|
|
|
1089
1170
|
return TengwarTuple([TengwarVector(yes), TengwarVector(no)])
|
|
1090
1171
|
|
|
1091
1172
|
def _builtin_scan(self, args):
|
|
1092
|
-
fn, init,
|
|
1173
|
+
fn, init, seq = args[0], args[1], args[2]
|
|
1174
|
+
if isinstance(seq, TengwarLazy):
|
|
1175
|
+
interp = self
|
|
1176
|
+
parent = seq._make_gen
|
|
1177
|
+
def make_gen():
|
|
1178
|
+
acc = init
|
|
1179
|
+
yield acc
|
|
1180
|
+
for val in parent():
|
|
1181
|
+
acc = interp._call_function(fn, [acc, val])
|
|
1182
|
+
yield acc
|
|
1183
|
+
return TengwarLazy(make_gen)
|
|
1093
1184
|
acc = init
|
|
1094
1185
|
result = [acc]
|
|
1095
|
-
for e in
|
|
1186
|
+
for e in seq.elements:
|
|
1096
1187
|
acc = self._call_function(fn, [acc, e])
|
|
1097
1188
|
result.append(acc)
|
|
1098
1189
|
return TengwarVector(result)
|
|
@@ -1116,9 +1207,14 @@ class Interpreter:
|
|
|
1116
1207
|
def _builtin_iterate(self, args):
|
|
1117
1208
|
"""(iterate fn init n) → eager vector, (iterate fn init) → lazy sequence"""
|
|
1118
1209
|
if len(args) == 2:
|
|
1119
|
-
# Lazy form: return a TengwarLazy that take/head can consume
|
|
1120
1210
|
fn, init = args[0], args[1]
|
|
1121
|
-
|
|
1211
|
+
interp = self
|
|
1212
|
+
def make_gen():
|
|
1213
|
+
val = init
|
|
1214
|
+
while True:
|
|
1215
|
+
yield val
|
|
1216
|
+
val = interp._call_function(fn, [val])
|
|
1217
|
+
return TengwarLazy(make_gen)
|
|
1122
1218
|
fn, init, n = args[0], args[1], int(self._num_val(args[2]))
|
|
1123
1219
|
result = [init]
|
|
1124
1220
|
val = init
|
|
@@ -1855,7 +1951,9 @@ class Interpreter:
|
|
|
1855
1951
|
if op == '/':
|
|
1856
1952
|
if rv == 0: raise RuntimeError_("Division by zero")
|
|
1857
1953
|
return TengwarFloat(lv / rv) if use_float else TengwarInt(lv // rv)
|
|
1858
|
-
if op == '%':
|
|
1954
|
+
if op == '%':
|
|
1955
|
+
if rv == 0: raise RuntimeError_("Modulo by zero")
|
|
1956
|
+
return wrap(lv % rv)
|
|
1859
1957
|
if op == '=': return TengwarBool(lv == rv)
|
|
1860
1958
|
if op == '!=': return TengwarBool(lv != rv)
|
|
1861
1959
|
if op == '<': return TengwarBool(lv < rv)
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
tengwar/__init__.py,sha256=
|
|
1
|
+
tengwar/__init__.py,sha256=r2Fv1Bxv43nmcSUzoe1rVFZ1c9rI8gwXht1EyIVuMLI,579
|
|
2
2
|
tengwar/__main__.py,sha256=dF1qCzTBDRAf47QGJ6e2kqefPZztrEaE9WuM1n1NfLI,179
|
|
3
3
|
tengwar/ast_nodes.py,sha256=ghhqQQBoqWT-oc9xdCGo2hXBLSqh1zz74hKDyIUtE_Y,7749
|
|
4
4
|
tengwar/binary_ast.py,sha256=UVDGpk_OvHxPLcaToYkAuYA_cg9QQwj6yJXZ057dW0Q,20729
|
|
5
5
|
tengwar/errors.py,sha256=tpZwlDorqUvqX-rtTjL2nhu51Kcdc2ozYBbnJBhR1Hk,773
|
|
6
|
-
tengwar/interpreter.py,sha256=
|
|
6
|
+
tengwar/interpreter.py,sha256=t4Lun4pbUdVFwQoiU44_-1CSsjovo44u4CRX5IZRbuI,85532
|
|
7
7
|
tengwar/lexer.py,sha256=d8MphHWmS6aA7HhRdu-CzX1Ma_3oYZSqkhNNrqLa_Ak,17666
|
|
8
8
|
tengwar/mcp_server.py,sha256=P23h-OiedeiowHlvknKsDU1cZ1eaT2ZbXfjCMUGvHus,17921
|
|
9
9
|
tengwar/parser.py,sha256=J9Sc4x8Rs9Rmc5IkOegcfuEWOSIi54fXhjwviF0SjvY,25141
|
|
10
10
|
tengwar/repl.py,sha256=FOvKth8MLOEVExgUvdod-qJqLydbVFDEA1DRhVGjZnQ,4880
|
|
11
11
|
tengwar/vm.py,sha256=etTJTufLqn76GAnZpzG_DLQQ3rXLsyFvHPEU3aNphIY,15883
|
|
12
|
-
tengwar-0.3.
|
|
13
|
-
tengwar-0.3.
|
|
14
|
-
tengwar-0.3.
|
|
15
|
-
tengwar-0.3.
|
|
16
|
-
tengwar-0.3.
|
|
17
|
-
tengwar-0.3.
|
|
12
|
+
tengwar-0.3.4.dist-info/licenses/LICENSE,sha256=qzDJpz75A1ntwYbNw63k1J-9Ov6v4z62Uj7uDcWxv1w,1072
|
|
13
|
+
tengwar-0.3.4.dist-info/METADATA,sha256=Nb-AVaVRycCRe-lrQw8y7X7gkfNwyMSEl06vR4CTFa8,6949
|
|
14
|
+
tengwar-0.3.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
15
|
+
tengwar-0.3.4.dist-info/entry_points.txt,sha256=W_Zolo2TLJBIDkgAkV7yWzQWKwicET_J9gs4crmrfI4,46
|
|
16
|
+
tengwar-0.3.4.dist-info/top_level.txt,sha256=VyO8Esj_l1yx0c52WUt_KUheaLbXOv2O2kGPZ1eG38k,8
|
|
17
|
+
tengwar-0.3.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|