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 +1 -1
- tengwar/ast_nodes.py +2 -1
- tengwar/interpreter.py +37 -10
- tengwar/lexer.py +3 -1
- tengwar/parser.py +5 -2
- {tengwar-0.3.1.dist-info → tengwar-0.3.2.dist-info}/METADATA +1 -1
- tengwar-0.3.2.dist-info/RECORD +17 -0
- tengwar-0.3.1.dist-info/RECORD +0 -17
- {tengwar-0.3.1.dist-info → tengwar-0.3.2.dist-info}/WHEEL +0 -0
- {tengwar-0.3.1.dist-info → tengwar-0.3.2.dist-info}/entry_points.txt +0 -0
- {tengwar-0.3.1.dist-info → tengwar-0.3.2.dist-info}/licenses/LICENSE +0 -0
- {tengwar-0.3.1.dist-info → tengwar-0.3.2.dist-info}/top_level.txt +0 -0
tengwar/__init__.py
CHANGED
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
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
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 ...
|
|
1096
|
-
|
|
1097
|
-
|
|
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
|
-
'
|
|
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)"""
|
|
@@ -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,,
|
tengwar-0.3.1.dist-info/RECORD
DELETED
|
@@ -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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|