tengwar 0.3.2__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 CHANGED
@@ -5,7 +5,7 @@ Built from first principles for machine intelligence.
5
5
  Zero ambiguity. Maximum semantic density. Binary AST protocol.
6
6
  """
7
7
 
8
- __version__ = "0.3.2"
8
+ __version__ = "0.3.4"
9
9
  __author__ = "TENGWAR Project"
10
10
 
11
11
  from .lexer import tokenize
tengwar/interpreter.py CHANGED
@@ -74,6 +74,15 @@ class TengwarVector(TengwarValue):
74
74
  def __eq__(self, other): return isinstance(other, TengwarVector) and self.elements == other.elements
75
75
 
76
76
 
77
+ class TengwarLazy(TengwarValue):
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>'
84
+
85
+
77
86
  class TengwarClosure(TengwarValue):
78
87
  def __init__(self, params: list, body, env: 'Environment', name: str = ""):
79
88
  self.params = params
@@ -528,6 +537,8 @@ class Interpreter:
528
537
  return TengwarFloat(math.sqrt(args[0].value))
529
538
 
530
539
  def _builtin_mod(self, args):
540
+ if args[1].value == 0:
541
+ raise RuntimeError_("Modulo by zero")
531
542
  return TengwarInt(args[0].value % args[1].value)
532
543
 
533
544
  def _builtin_len(self, args):
@@ -627,15 +638,30 @@ class Interpreter:
627
638
  return TengwarVector(vec.elements[start:end])
628
639
 
629
640
  def _builtin_map(self, args):
630
- fn, vec = args[0], args[1]
631
- if not isinstance(vec, TengwarVector):
632
- raise RuntimeError_("map requires a vector")
633
- return TengwarVector([self._call_function(fn, [e]) for e in vec.elements])
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])
634
652
 
635
653
  def _builtin_filter(self, args):
636
- fn, vec = args[0], args[1]
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)
637
663
  result = []
638
- for e in vec.elements:
664
+ for e in seq.elements:
639
665
  if self._is_truthy(self._call_function(fn, [e])):
640
666
  result.append(e)
641
667
  return TengwarVector(result)
@@ -729,12 +755,23 @@ class Interpreter:
729
755
 
730
756
  def _builtin_head(self, args):
731
757
  vec = args[0]
758
+ if isinstance(vec, TengwarLazy):
759
+ for val in vec:
760
+ return val
761
+ raise RuntimeError_("head of empty lazy sequence")
732
762
  if not vec.elements:
733
763
  raise RuntimeError_("head of empty vector")
734
764
  return vec.elements[0]
735
765
 
736
766
  def _builtin_tail(self, args):
737
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)
738
775
  if not vec.elements:
739
776
  raise RuntimeError_("tail of empty vector")
740
777
  return TengwarVector(vec.elements[1:])
@@ -747,6 +784,11 @@ class Interpreter:
747
784
 
748
785
  def _builtin_nth(self, args):
749
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")
750
792
  if isinstance(col, TengwarTuple): return col.elements[idx]
751
793
  if isinstance(col, TengwarVector): return col.elements[idx]
752
794
  raise RuntimeError_(f"Cannot nth into {type(col).__name__}")
@@ -880,8 +922,16 @@ class Interpreter:
880
922
  def _builtin_enumerate(self, args):
881
923
  """(enumerate vec) = vector of (index, element) tuples"""
882
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)
883
933
  if not isinstance(vec, TengwarVector):
884
- raise RuntimeError_("enumerate requires a vector")
934
+ raise RuntimeError_("enumerate requires a vector or lazy sequence")
885
935
  return TengwarVector([
886
936
  TengwarTuple([TengwarInt(i), e])
887
937
  for i, e in enumerate(vec.elements)
@@ -898,10 +948,25 @@ class Interpreter:
898
948
  def _builtin_apply(self, args):
899
949
  fn, arg_vec = args[0], args[1]
900
950
  if isinstance(arg_vec, TengwarVector):
901
- return self._call_function(fn, arg_vec.elements)
902
- if isinstance(arg_vec, TengwarTuple):
903
- return self._call_function(fn, arg_vec.elements)
904
- return self._call_function(fn, [arg_vec])
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
905
970
 
906
971
  def _builtin_err(self, args):
907
972
  raise RuntimeError_(self._display(args[0]) if args else "error")
@@ -995,17 +1060,41 @@ class Interpreter:
995
1060
  return TengwarInt(-1)
996
1061
 
997
1062
  def _builtin_take(self, args):
998
- n, vec = int(self._num_val(args[0])), args[1]
999
- return TengwarVector(vec.elements[:n])
1063
+ n, seq = int(self._num_val(args[0])), args[1]
1064
+ if isinstance(seq, TengwarLazy):
1065
+ result = []
1066
+ for val in seq:
1067
+ result.append(val)
1068
+ if len(result) >= n:
1069
+ break
1070
+ return TengwarVector(result)
1071
+ return TengwarVector(seq.elements[:n])
1000
1072
 
1001
1073
  def _builtin_drop(self, args):
1002
- n, vec = int(self._num_val(args[0])), args[1]
1003
- return TengwarVector(vec.elements[n:])
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:])
1004
1085
 
1005
1086
  def _builtin_take_while(self, args):
1006
- fn, vec = args[0], args[1]
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)
1007
1096
  result = []
1008
- for e in vec.elements:
1097
+ for e in seq.elements:
1009
1098
  if self._is_truthy(self._call_function(fn, [e])):
1010
1099
  result.append(e)
1011
1100
  else:
@@ -1013,10 +1102,21 @@ class Interpreter:
1013
1102
  return TengwarVector(result)
1014
1103
 
1015
1104
  def _builtin_drop_while(self, args):
1016
- fn, vec = args[0], args[1]
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)
1017
1117
  dropping = True
1018
1118
  result = []
1019
- for e in vec.elements:
1119
+ for e in seq.elements:
1020
1120
  if dropping and self._is_truthy(self._call_function(fn, [e])):
1021
1121
  continue
1022
1122
  dropping = False
@@ -1070,10 +1170,20 @@ class Interpreter:
1070
1170
  return TengwarTuple([TengwarVector(yes), TengwarVector(no)])
1071
1171
 
1072
1172
  def _builtin_scan(self, args):
1073
- fn, init, vec = args[0], args[1], args[2]
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)
1074
1184
  acc = init
1075
1185
  result = [acc]
1076
- for e in vec.elements:
1186
+ for e in seq.elements:
1077
1187
  acc = self._call_function(fn, [acc, e])
1078
1188
  result.append(acc)
1079
1189
  return TengwarVector(result)
@@ -1095,6 +1205,16 @@ class Interpreter:
1095
1205
  return TengwarVector([val] * n)
1096
1206
 
1097
1207
  def _builtin_iterate(self, args):
1208
+ """(iterate fn init n) → eager vector, (iterate fn init) → lazy sequence"""
1209
+ if len(args) == 2:
1210
+ fn, init = args[0], args[1]
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)
1098
1218
  fn, init, n = args[0], args[1], int(self._num_val(args[2]))
1099
1219
  result = [init]
1100
1220
  val = init
@@ -1815,9 +1935,9 @@ class Interpreter:
1815
1935
  raise RuntimeError_(f"Unknown node type: {type(node).__name__}")
1816
1936
 
1817
1937
  def _eval_binop(self, op: str, left: TengwarValue, right: TengwarValue) -> TengwarValue:
1818
- # String concatenation with +
1819
- if op == '+' and isinstance(left, TengwarStr):
1820
- return TengwarStr(left.value + self._display(right))
1938
+ # String concatenation with + (both must be strings — no implicit coercion)
1939
+ if op == '+' and isinstance(left, TengwarStr) and isinstance(right, TengwarStr):
1940
+ return TengwarStr(left.value + right.value)
1821
1941
 
1822
1942
  # Numeric operations
1823
1943
  if isinstance(left, (TengwarInt, TengwarFloat)) and isinstance(right, (TengwarInt, TengwarFloat)):
@@ -1831,7 +1951,9 @@ class Interpreter:
1831
1951
  if op == '/':
1832
1952
  if rv == 0: raise RuntimeError_("Division by zero")
1833
1953
  return TengwarFloat(lv / rv) if use_float else TengwarInt(lv // rv)
1834
- if op == '%': return wrap(lv % rv)
1954
+ if op == '%':
1955
+ if rv == 0: raise RuntimeError_("Modulo by zero")
1956
+ return wrap(lv % rv)
1835
1957
  if op == '=': return TengwarBool(lv == rv)
1836
1958
  if op == '!=': return TengwarBool(lv != rv)
1837
1959
  if op == '<': return TengwarBool(lv < rv)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tengwar
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: The AI-Native Programming Language
5
5
  Author: TENGWAR Project
6
6
  License: MIT
@@ -1,17 +1,17 @@
1
- tengwar/__init__.py,sha256=VTzmTP2TkxHnpaK9J0Scu_4UiIyo0rpM6bBEcEuN27E,579
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=kqezVPs30DDE63Wb7LHu2SH2r6A5hMTaULKVK-ESAd8,80867
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.2.dist-info/licenses/LICENSE,sha256=qzDJpz75A1ntwYbNw63k1J-9Ov6v4z62Uj7uDcWxv1w,1072
13
- tengwar-0.3.2.dist-info/METADATA,sha256=ZZ2gjmAMC7XCqCna3PzSNUfu5M7eIcRyU_jCBehIY9A,6949
14
- tengwar-0.3.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
15
- tengwar-0.3.2.dist-info/entry_points.txt,sha256=W_Zolo2TLJBIDkgAkV7yWzQWKwicET_J9gs4crmrfI4,46
16
- tengwar-0.3.2.dist-info/top_level.txt,sha256=VyO8Esj_l1yx0c52WUt_KUheaLbXOv2O2kGPZ1eG38k,8
17
- tengwar-0.3.2.dist-info/RECORD,,
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,,