tengwar 0.3.1__py3-none-any.whl → 0.3.2__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.1"
8
+ __version__ = "0.3.2"
9
9
  __author__ = "TENGWAR Project"
10
10
 
11
11
  from .lexer import tokenize
tengwar/ast_nodes.py CHANGED
@@ -215,8 +215,9 @@ class TypeAnn(ASTNode):
215
215
 
216
216
  @dataclass
217
217
  class Proof(ASTNode):
218
- """(⊢ assertion) - proof obligation"""
218
+ """(⊢ assertion) or (⊢ assertion message) - proof obligation"""
219
219
  assertion: Any = None
220
+ message: Any = None
220
221
  def __post_init__(self):
221
222
  self.type = NodeType.PROOF
222
223
 
tengwar/interpreter.py CHANGED
@@ -241,6 +241,8 @@ class Interpreter:
241
241
  # Vector/sequence ops
242
242
  env.set('vec', TengwarBuiltin('vec', lambda args: TengwarVector(list(args))))
243
243
  env.set('push', TengwarBuiltin('push', self._builtin_push))
244
+ env.set('cons', TengwarBuiltin('cons', self._builtin_cons))
245
+ env.set('prepend', TengwarBuiltin('prepend', self._builtin_cons))
244
246
  env.set('pop', TengwarBuiltin('pop', self._builtin_pop))
245
247
  env.set('get', TengwarBuiltin('get', self._builtin_get))
246
248
  env.set('set-at', TengwarBuiltin('set-at', self._builtin_set_at))
@@ -314,6 +316,7 @@ class Interpreter:
314
316
  env.set('&', TengwarBuiltin('&', lambda args: self._eval_binop('&', args[0], args[1])))
315
317
  env.set('|', TengwarBuiltin('|', lambda args: self._eval_binop('|', args[0], args[1])))
316
318
  env.set('!', TengwarBuiltin('!', lambda args: self._eval_unop('!', args[0])))
319
+ env.set('not', TengwarBuiltin('not', lambda args: self._eval_unop('!', args[0])))
317
320
 
318
321
  # === DICT / HASHMAP ===
319
322
  env.set('dict', TengwarBuiltin('dict', self._builtin_dict))
@@ -583,6 +586,13 @@ class Interpreter:
583
586
  raise RuntimeError_("push requires a vector")
584
587
  return TengwarVector(vec.elements + [args[1]])
585
588
 
589
+ def _builtin_cons(self, args):
590
+ """(cons element vector) — prepend element to front"""
591
+ elem, vec = args[0], args[1]
592
+ if not isinstance(vec, TengwarVector):
593
+ raise RuntimeError_("cons requires a vector as second argument")
594
+ return TengwarVector([elem] + vec.elements)
595
+
586
596
  def _builtin_pop(self, args):
587
597
  vec = args[0]
588
598
  if not isinstance(vec, TengwarVector):
@@ -695,13 +705,15 @@ class Interpreter:
695
705
  return TengwarVector(sorted(vec.elements, key=lambda e: e.value))
696
706
 
697
707
  def _builtin_flatten(self, args):
698
- result = []
699
- for e in args[0].elements:
700
- if isinstance(e, TengwarVector):
701
- result.extend(e.elements)
702
- else:
703
- result.append(e)
704
- return TengwarVector(result)
708
+ def _deep_flatten(elements):
709
+ result = []
710
+ for e in elements:
711
+ if isinstance(e, TengwarVector):
712
+ result.extend(_deep_flatten(e.elements))
713
+ else:
714
+ result.append(e)
715
+ return result
716
+ return TengwarVector(_deep_flatten(args[0].elements))
705
717
 
706
718
  def _builtin_zip(self, args):
707
719
  vecs = [a.elements for a in args]
@@ -1092,9 +1104,21 @@ class Interpreter:
1092
1104
  return TengwarVector(result)
1093
1105
 
1094
1106
  def _builtin_juxt(self, args):
1095
- """(juxt f1 f2 ... val) apply multiple fns to same value"""
1096
- fns, val = args[:-1], args[-1]
1097
- return TengwarVector([self._call_function(fn, [val]) for fn in fns])
1107
+ """(juxt f1 f2 ...) fn, or ((juxt f1 f2 ...) val) → vector of results"""
1108
+ def _is_tengwar_callable(x):
1109
+ return isinstance(x, (TengwarBuiltin, TengwarClosure))
1110
+ # If last arg is not callable, treat it as the value to apply to
1111
+ if len(args) >= 2 and not _is_tengwar_callable(args[-1]):
1112
+ fns, val = args[:-1], args[-1]
1113
+ return TengwarVector([self._call_function(fn, [val]) for fn in fns])
1114
+ else:
1115
+ # Return a closure that applies all functions to a value
1116
+ fns = list(args)
1117
+ interp = self
1118
+ def juxt_fn(inner_args):
1119
+ val = inner_args[0]
1120
+ return TengwarVector([interp._call_function(fn, [val]) for fn in fns])
1121
+ return TengwarBuiltin('juxt*', juxt_fn)
1098
1122
 
1099
1123
  def _builtin_min_by(self, args):
1100
1124
  fn, vec = args[0], args[1]
@@ -1678,6 +1702,9 @@ class Interpreter:
1678
1702
  if isinstance(node, Proof):
1679
1703
  result = self.eval(node.assertion, env)
1680
1704
  if not self._is_truthy(result):
1705
+ if node.message:
1706
+ msg = self.eval(node.message, env)
1707
+ raise ProofError(f"Proof obligation failed: {msg}")
1681
1708
  raise ProofError(f"Proof obligation failed: {repr(result)}")
1682
1709
  return result
1683
1710
 
tengwar/lexer.py CHANGED
@@ -120,7 +120,7 @@ KEYWORDS = {
120
120
  'do': TokenType.SEQ,
121
121
  'par': TokenType.PARALLEL,
122
122
  'nil': TokenType.UNIT,
123
- 'mod': TokenType.MODULE,
123
+ 'module': TokenType.MODULE,
124
124
  # Note: let, pipe, throw, catch, try are handled as symbols
125
125
  # by the parser since they need custom parse rules
126
126
  }
@@ -130,6 +130,8 @@ SINGLE_CHAR = {
130
130
  ')': TokenType.RPAREN,
131
131
  '{': TokenType.LBRACE,
132
132
  '}': TokenType.RBRACE,
133
+ '[': TokenType.LBRACKET,
134
+ ']': TokenType.RBRACKET,
133
135
  '?': TokenType.COND,
134
136
  '~': TokenType.MATCH,
135
137
  '+': TokenType.PLUS,
tengwar/parser.py CHANGED
@@ -426,11 +426,14 @@ class Parser:
426
426
  return Recurse(name=name, body=body, line=line, col=col)
427
427
 
428
428
  def parse_proof(self, line: int, col: int) -> Proof:
429
- """(⊢ assertion)"""
429
+ """(⊢ assertion) or (⊢ assertion message)"""
430
430
  self.advance() # consume ⊢
431
431
  assertion = self.parse_expr()
432
+ message = None
433
+ if self.peek_type() != TokenType.RPAREN:
434
+ message = self.parse_expr()
432
435
  self.expect(TokenType.RPAREN)
433
- return Proof(assertion=assertion, line=line, col=col)
436
+ return Proof(assertion=assertion, message=message, line=line, col=col)
434
437
 
435
438
  def parse_mutate(self, line: int, col: int) -> Mutate:
436
439
  """(μ name value)"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tengwar
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: The AI-Native Programming Language
5
5
  Author: TENGWAR Project
6
6
  License: MIT
@@ -0,0 +1,17 @@
1
+ tengwar/__init__.py,sha256=VTzmTP2TkxHnpaK9J0Scu_4UiIyo0rpM6bBEcEuN27E,579
2
+ tengwar/__main__.py,sha256=dF1qCzTBDRAf47QGJ6e2kqefPZztrEaE9WuM1n1NfLI,179
3
+ tengwar/ast_nodes.py,sha256=ghhqQQBoqWT-oc9xdCGo2hXBLSqh1zz74hKDyIUtE_Y,7749
4
+ tengwar/binary_ast.py,sha256=UVDGpk_OvHxPLcaToYkAuYA_cg9QQwj6yJXZ057dW0Q,20729
5
+ tengwar/errors.py,sha256=tpZwlDorqUvqX-rtTjL2nhu51Kcdc2ozYBbnJBhR1Hk,773
6
+ tengwar/interpreter.py,sha256=kqezVPs30DDE63Wb7LHu2SH2r6A5hMTaULKVK-ESAd8,80867
7
+ tengwar/lexer.py,sha256=d8MphHWmS6aA7HhRdu-CzX1Ma_3oYZSqkhNNrqLa_Ak,17666
8
+ tengwar/mcp_server.py,sha256=P23h-OiedeiowHlvknKsDU1cZ1eaT2ZbXfjCMUGvHus,17921
9
+ tengwar/parser.py,sha256=J9Sc4x8Rs9Rmc5IkOegcfuEWOSIi54fXhjwviF0SjvY,25141
10
+ tengwar/repl.py,sha256=FOvKth8MLOEVExgUvdod-qJqLydbVFDEA1DRhVGjZnQ,4880
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,,
@@ -1,17 +0,0 @@
1
- tengwar/__init__.py,sha256=vnHeFtc3HEiQl6tDYr9B7A9PmjvAulARvZY02OHd40k,579
2
- tengwar/__main__.py,sha256=dF1qCzTBDRAf47QGJ6e2kqefPZztrEaE9WuM1n1NfLI,179
3
- tengwar/ast_nodes.py,sha256=Q5rrMaAtKNPraVJ0nnwpGUiXJerVKAhKXLZjmaaGfyg,7698
4
- tengwar/binary_ast.py,sha256=UVDGpk_OvHxPLcaToYkAuYA_cg9QQwj6yJXZ057dW0Q,20729
5
- tengwar/errors.py,sha256=tpZwlDorqUvqX-rtTjL2nhu51Kcdc2ozYBbnJBhR1Hk,773
6
- tengwar/interpreter.py,sha256=8tNzLtSGp8CIAFkuPGikZobnQDeeg0nKlmONqa4NutA,79426
7
- tengwar/lexer.py,sha256=6PjWeuAWrYHPug_Mtfuk1kyB6Rbp5oTVLil9TKlKH6o,17605
8
- tengwar/mcp_server.py,sha256=P23h-OiedeiowHlvknKsDU1cZ1eaT2ZbXfjCMUGvHus,17921
9
- tengwar/parser.py,sha256=VY6zNHl8IsOHOLjSUJa9nUL-I9IogRKKCsU1XdBQutM,24985
10
- tengwar/repl.py,sha256=FOvKth8MLOEVExgUvdod-qJqLydbVFDEA1DRhVGjZnQ,4880
11
- tengwar/vm.py,sha256=etTJTufLqn76GAnZpzG_DLQQ3rXLsyFvHPEU3aNphIY,15883
12
- tengwar-0.3.1.dist-info/licenses/LICENSE,sha256=qzDJpz75A1ntwYbNw63k1J-9Ov6v4z62Uj7uDcWxv1w,1072
13
- tengwar-0.3.1.dist-info/METADATA,sha256=KoCww2GbQcklh1j_u87ta2zidbkSehE5ikWEbbXn2nE,6949
14
- tengwar-0.3.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
15
- tengwar-0.3.1.dist-info/entry_points.txt,sha256=W_Zolo2TLJBIDkgAkV7yWzQWKwicET_J9gs4crmrfI4,46
16
- tengwar-0.3.1.dist-info/top_level.txt,sha256=VyO8Esj_l1yx0c52WUt_KUheaLbXOv2O2kGPZ1eG38k,8
17
- tengwar-0.3.1.dist-info/RECORD,,