lispython 0.4.1__tar.gz → 0.4.3__tar.gz
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.
- {lispython-0.4.1 → lispython-0.4.3}/PKG-INFO +1 -4
- {lispython-0.4.1 → lispython-0.4.3}/README.md +0 -3
- {lispython-0.4.1 → lispython-0.4.3}/docs/macros.md +19 -0
- {lispython-0.4.1 → lispython-0.4.3}/pyproject.toml +1 -1
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/builtins.py +11 -1
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/macros/sugar.lpy +11 -0
- lispython-0.4.3/tests/test_as_thread.py +49 -0
- {lispython-0.4.1 → lispython-0.4.3}/uv.lock +1 -1
- {lispython-0.4.1 → lispython-0.4.3}/.claude/settings.local.json +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/.gitignore +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/.pre-commit-config.yaml +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/.vscode/settings.json +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/LICENSE.md +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/docs/index.md +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/docs/syntax/expressions.md +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/docs/syntax/overview.md +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/docs/syntax/statements.md +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/docs/usage/cli.md +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/docs/usage/getting-started.md +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/docs/version_macro.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/docs/why-lispy.md +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/mkdocs.yml +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/__init__.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/compiler/__init__.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/compiler/expr.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/compiler/literal.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/compiler/stmt.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/compiler/utils.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/importer.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/macro.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/meta_functions.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/nodes.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/parser.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core/utils.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/core_meta_functions.lpy +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/lsp/__init__.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/lsp/__main__.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/lsp/server.lpy +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/macros/__init__.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/macros/init.lpy +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/src/lispy/tools.lpy +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/__init__.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/test_expr.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/test_gensym.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/test_include_meta.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/test_literal.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/test_meta_functions.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/test_parser.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/test_stmt.py +0 -0
- {lispython-0.4.1 → lispython-0.4.3}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lispython
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Lisp-like Syntax for Python with Lisp-like Macros
|
|
5
5
|
Project-URL: Homepage, https://jetack.github.io/lispython
|
|
6
6
|
Project-URL: Repository, https://github.com/jetack/lispython
|
|
@@ -103,9 +103,6 @@ Use [`lpy-mode`](https://github.com/jetack/lpy-mode) for syntax highlighting and
|
|
|
103
103
|
- [ ] REPL should track history and arrow key navigation
|
|
104
104
|
- [ ] REPL multi-line input support
|
|
105
105
|
- [ ] Better compilation error messages
|
|
106
|
-
### Macro System
|
|
107
|
-
- [ ] `as->` macro for syntactic sugar
|
|
108
|
-
- [ ] `gensym` for avoiding name collision
|
|
109
106
|
### Python AST
|
|
110
107
|
- [ ] `type_comment` never considered. Later, it should be covered
|
|
111
108
|
- [ ] Any missing AST nodes in the version 3.12+
|
|
@@ -81,9 +81,6 @@ Use [`lpy-mode`](https://github.com/jetack/lpy-mode) for syntax highlighting and
|
|
|
81
81
|
- [ ] REPL should track history and arrow key navigation
|
|
82
82
|
- [ ] REPL multi-line input support
|
|
83
83
|
- [ ] Better compilation error messages
|
|
84
|
-
### Macro System
|
|
85
|
-
- [ ] `as->` macro for syntactic sugar
|
|
86
|
-
- [ ] `gensym` for avoiding name collision
|
|
87
84
|
### Python AST
|
|
88
85
|
- [ ] `type_comment` never considered. Later, it should be covered
|
|
89
86
|
- [ ] Any missing AST nodes in the version 3.12+
|
|
@@ -56,6 +56,25 @@ Just change `def` in function definition to `defmacro`. And macros usually retur
|
|
|
56
56
|
```
|
|
57
57
|
You can find more in `src/lispython/macros/sugar.lpy`.
|
|
58
58
|
|
|
59
|
+
### `as->`
|
|
60
|
+
Unlike `->` (thread first) and `->>` (thread last), `as->` lets you name the threaded value and place it anywhere in each form:
|
|
61
|
+
```python
|
|
62
|
+
(as-> 0 x
|
|
63
|
+
(+ x 10) ;; x = 10
|
|
64
|
+
(* 2 x) ;; x = 20
|
|
65
|
+
(str x)) ;; x = "20"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This expands to:
|
|
69
|
+
```python
|
|
70
|
+
x = 0
|
|
71
|
+
x = x + 10
|
|
72
|
+
x = 2 * x
|
|
73
|
+
x = str(x)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Useful when the threaded value doesn't always go in the first or last position.
|
|
77
|
+
|
|
59
78
|
## gensym
|
|
60
79
|
`gensym` generates unique symbols to avoid variable name collisions in macros. It is automatically available inside `defmacro` bodies.
|
|
61
80
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from lispy.core.nodes import Symbol
|
|
1
|
+
from lispy.core.nodes import Expression, Symbol, Wrapper
|
|
2
2
|
|
|
3
3
|
_gensym_counter = 0
|
|
4
4
|
|
|
@@ -17,3 +17,13 @@ def gensym(prefix="gensym"):
|
|
|
17
17
|
def reset_gensym_counter():
|
|
18
18
|
global _gensym_counter
|
|
19
19
|
_gensym_counter = 0
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def replace_symbol(node, old, new):
|
|
23
|
+
if isinstance(node, Symbol) and node.value == old.value:
|
|
24
|
+
return new
|
|
25
|
+
if isinstance(node, Expression):
|
|
26
|
+
node.list = [replace_symbol(child, old, new) for child in node.list]
|
|
27
|
+
elif isinstance(node, Wrapper):
|
|
28
|
+
node.value = replace_symbol(node.value, old, new)
|
|
29
|
+
return node
|
|
@@ -28,6 +28,17 @@
|
|
|
28
28
|
(return `(->> ~f ~@rest)))
|
|
29
29
|
(return `(-> (~f ~x) ~@rest))))
|
|
30
30
|
|
|
31
|
+
(defmacro as-> [expr name *forms]
|
|
32
|
+
(if (== 0 (len forms))
|
|
33
|
+
(return expr))
|
|
34
|
+
(= sym (gensym (str name)))
|
|
35
|
+
(= stmts [])
|
|
36
|
+
(stmts.append `(= ~sym ~expr))
|
|
37
|
+
(for f in forms
|
|
38
|
+
(stmts.append `(= ~sym ~(replace-symbol f name sym))))
|
|
39
|
+
(stmts.append sym)
|
|
40
|
+
(return `(do ~@stmts)))
|
|
41
|
+
|
|
31
42
|
(defmacro fn [*body]
|
|
32
43
|
(return `(lambda ~@body)))
|
|
33
44
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from lispy.core.builtins import reset_gensym_counter
|
|
2
|
+
from lispy.tools import src_to_python_org
|
|
3
|
+
|
|
4
|
+
PREAMBLE = "(require lispy.macros *)\n"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestAsThread:
|
|
8
|
+
def setup_method(self):
|
|
9
|
+
reset_gensym_counter()
|
|
10
|
+
|
|
11
|
+
def test_no_forms(self):
|
|
12
|
+
assert src_to_python_org(PREAMBLE + "(as-> 42 x)") == "42"
|
|
13
|
+
|
|
14
|
+
def test_single_form(self):
|
|
15
|
+
result = src_to_python_org(PREAMBLE + "(as-> 0 x (+ x 1))")
|
|
16
|
+
assert "__x_0 = 0" in result
|
|
17
|
+
assert "__x_0 = __x_0 + 1" in result
|
|
18
|
+
|
|
19
|
+
def test_multiple_forms(self):
|
|
20
|
+
result = src_to_python_org(
|
|
21
|
+
PREAMBLE + "(as-> 0 x (+ x 10) (* 2 x) (str x))"
|
|
22
|
+
)
|
|
23
|
+
assert "__x_0 = 0" in result
|
|
24
|
+
assert "__x_0 = __x_0 + 10" in result
|
|
25
|
+
assert "__x_0 = 2 * __x_0" in result
|
|
26
|
+
assert "__x_0 = str(__x_0)" in result
|
|
27
|
+
|
|
28
|
+
def test_method_call(self):
|
|
29
|
+
result = src_to_python_org(
|
|
30
|
+
PREAMBLE + '(as-> "hello" s (.upper s))'
|
|
31
|
+
)
|
|
32
|
+
assert "__s_0 = 'hello'" in result
|
|
33
|
+
assert "__s_0 = __s_0.upper()" in result
|
|
34
|
+
|
|
35
|
+
def test_flexible_placement(self):
|
|
36
|
+
result = src_to_python_org(
|
|
37
|
+
PREAMBLE + "(as-> 1 x (+ 10 x) (- x 5))"
|
|
38
|
+
)
|
|
39
|
+
assert "__x_0 = 10 + __x_0" in result
|
|
40
|
+
assert "__x_0 = __x_0 - 5" in result
|
|
41
|
+
|
|
42
|
+
def test_does_not_shadow_outer_variable(self):
|
|
43
|
+
result = src_to_python_org(
|
|
44
|
+
PREAMBLE + "(= x 100)\n(as-> 0 x (+ x 10))\n(print x)"
|
|
45
|
+
)
|
|
46
|
+
assert "x = 100" in result
|
|
47
|
+
assert "print(x)" in result
|
|
48
|
+
assert "__x_0 = 0" in result
|
|
49
|
+
assert "__x_0 = __x_0 + 10" in result
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|