lispython 0.4.3__tar.gz → 0.4.6__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.3 → lispython-0.4.6}/PKG-INFO +23 -11
- {lispython-0.4.3 → lispython-0.4.6}/README.md +21 -10
- {lispython-0.4.3 → lispython-0.4.6}/docs/syntax/expressions.md +2 -2
- lispython-0.4.6/docs/usage/cli.md +41 -0
- {lispython-0.4.3 → lispython-0.4.6}/mkdocs.yml +1 -1
- {lispython-0.4.3 → lispython-0.4.6}/pyproject.toml +5 -2
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/macro.py +19 -1
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/nodes.py +5 -1
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/lsp/server.lpy +79 -0
- lispython-0.4.6/src/lispy/tools.lpy +720 -0
- lispython-0.4.6/tests/test_literal_unwrap.py +73 -0
- {lispython-0.4.3 → lispython-0.4.6}/uv.lock +24 -1
- lispython-0.4.3/docs/usage/cli.md +0 -22
- lispython-0.4.3/src/lispy/tools.lpy +0 -228
- {lispython-0.4.3 → lispython-0.4.6}/.claude/settings.local.json +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/.gitignore +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/.pre-commit-config.yaml +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/.vscode/settings.json +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/LICENSE.md +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/docs/index.md +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/docs/macros.md +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/docs/syntax/overview.md +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/docs/syntax/statements.md +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/docs/usage/getting-started.md +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/docs/version_macro.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/docs/why-lispy.md +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/__init__.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/builtins.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/__init__.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/expr.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/literal.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/stmt.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/utils.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/importer.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/meta_functions.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/parser.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/utils.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core_meta_functions.lpy +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/lsp/__init__.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/lsp/__main__.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/macros/__init__.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/macros/init.lpy +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/src/lispy/macros/sugar.lpy +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/__init__.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/test_as_thread.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/test_expr.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/test_gensym.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/test_include_meta.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/test_literal.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/test_meta_functions.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/test_parser.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/tests/test_stmt.py +0 -0
- {lispython-0.4.3 → lispython-0.4.6}/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.6
|
|
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
|
|
@@ -8,6 +8,7 @@ Author-email: Jetack <jetack23@gmail.com>
|
|
|
8
8
|
License: MIT
|
|
9
9
|
License-File: LICENSE.md
|
|
10
10
|
Requires-Python: >=3.11
|
|
11
|
+
Requires-Dist: prompt-toolkit>=3.0.52
|
|
11
12
|
Requires-Dist: pygls>=1.0.0
|
|
12
13
|
Provides-Extra: dev
|
|
13
14
|
Requires-Dist: pre-commit>=3.6.0; extra == 'dev'
|
|
@@ -84,25 +85,36 @@ lpy -m pytest
|
|
|
84
85
|
LisPython ships with a language server (`lpy-lsp`) that speaks LSP over stdio. It provides:
|
|
85
86
|
|
|
86
87
|
- Diagnostics (parse / compile errors)
|
|
87
|
-
-
|
|
88
|
+
- Completions (special forms, builtins, file/workspace symbols)
|
|
89
|
+
- Hover documentation for special forms and builtins
|
|
88
90
|
- Document symbols
|
|
89
91
|
- Go-to-definition, including across `.lpy` files in the workspace
|
|
90
92
|
|
|
93
|
+
## nREPL Server
|
|
94
|
+
LisPython includes an nREPL server for REPL-driven development:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
lpy --nrepl # start on a random port
|
|
98
|
+
lpy --nrepl 7888 # start on a specific port
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The server accepts newline-delimited JSON over TCP and supports:
|
|
102
|
+
- `eval` — evaluate LisPython code, return value/stdout/error
|
|
103
|
+
- `load-file` — load a `.lpy` file into the session
|
|
104
|
+
- `macroexpand` — expand macros and return the result
|
|
105
|
+
- `complete` — prefix and dot-completion from the live scope
|
|
106
|
+
- `docs` — signature and docstring for a symbol
|
|
107
|
+
- `annotate` — type tag (function/class/module/macro)
|
|
108
|
+
|
|
91
109
|
### Editor setup
|
|
92
|
-
Point your editor's LSP client at the `lpy-lsp` command for files with the `.lpy` extension. The server speaks LSP over stdio.
|
|
93
110
|
|
|
94
|
-
####
|
|
95
|
-
Install the [LisPython](https://marketplace.visualstudio.com/items?itemName=jetack.vscode-lispython) extension
|
|
111
|
+
#### VS Code
|
|
112
|
+
Install the [LisPython](https://marketplace.visualstudio.com/items?itemName=jetack.vscode-lispython) extension. It connects to both LSP and nREPL automatically.
|
|
96
113
|
|
|
97
114
|
#### Emacs
|
|
98
|
-
Use [`lpy-mode`](https://github.com/jetack/lpy-mode)
|
|
115
|
+
Use [`lpy-mode`](https://github.com/jetack/lpy-mode). It provides nREPL integration (eval, completion, eldoc, macroexpand) and LSP via eglot.
|
|
99
116
|
|
|
100
117
|
## Todo
|
|
101
|
-
### Environment
|
|
102
|
-
- [ ] Test on more python versions
|
|
103
|
-
- [ ] REPL should track history and arrow key navigation
|
|
104
|
-
- [ ] REPL multi-line input support
|
|
105
|
-
- [ ] Better compilation error messages
|
|
106
118
|
### Python AST
|
|
107
119
|
- [ ] `type_comment` never considered. Later, it should be covered
|
|
108
120
|
- [ ] Any missing AST nodes in the version 3.12+
|
|
@@ -62,25 +62,36 @@ lpy -m pytest
|
|
|
62
62
|
LisPython ships with a language server (`lpy-lsp`) that speaks LSP over stdio. It provides:
|
|
63
63
|
|
|
64
64
|
- Diagnostics (parse / compile errors)
|
|
65
|
-
-
|
|
65
|
+
- Completions (special forms, builtins, file/workspace symbols)
|
|
66
|
+
- Hover documentation for special forms and builtins
|
|
66
67
|
- Document symbols
|
|
67
68
|
- Go-to-definition, including across `.lpy` files in the workspace
|
|
68
69
|
|
|
70
|
+
## nREPL Server
|
|
71
|
+
LisPython includes an nREPL server for REPL-driven development:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
lpy --nrepl # start on a random port
|
|
75
|
+
lpy --nrepl 7888 # start on a specific port
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The server accepts newline-delimited JSON over TCP and supports:
|
|
79
|
+
- `eval` — evaluate LisPython code, return value/stdout/error
|
|
80
|
+
- `load-file` — load a `.lpy` file into the session
|
|
81
|
+
- `macroexpand` — expand macros and return the result
|
|
82
|
+
- `complete` — prefix and dot-completion from the live scope
|
|
83
|
+
- `docs` — signature and docstring for a symbol
|
|
84
|
+
- `annotate` — type tag (function/class/module/macro)
|
|
85
|
+
|
|
69
86
|
### Editor setup
|
|
70
|
-
Point your editor's LSP client at the `lpy-lsp` command for files with the `.lpy` extension. The server speaks LSP over stdio.
|
|
71
87
|
|
|
72
|
-
####
|
|
73
|
-
Install the [LisPython](https://marketplace.visualstudio.com/items?itemName=jetack.vscode-lispython) extension
|
|
88
|
+
#### VS Code
|
|
89
|
+
Install the [LisPython](https://marketplace.visualstudio.com/items?itemName=jetack.vscode-lispython) extension. It connects to both LSP and nREPL automatically.
|
|
74
90
|
|
|
75
91
|
#### Emacs
|
|
76
|
-
Use [`lpy-mode`](https://github.com/jetack/lpy-mode)
|
|
92
|
+
Use [`lpy-mode`](https://github.com/jetack/lpy-mode). It provides nREPL integration (eval, completion, eldoc, macroexpand) and LSP via eglot.
|
|
77
93
|
|
|
78
94
|
## Todo
|
|
79
|
-
### Environment
|
|
80
|
-
- [ ] Test on more python versions
|
|
81
|
-
- [ ] REPL should track history and arrow key navigation
|
|
82
|
-
- [ ] REPL multi-line input support
|
|
83
|
-
- [ ] Better compilation error messages
|
|
84
95
|
### Python AST
|
|
85
96
|
- [ ] `type_comment` never considered. Later, it should be covered
|
|
86
97
|
- [ ] Any missing AST nodes in the version 3.12+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## REPL
|
|
2
|
+
```shell
|
|
3
|
+
lpy
|
|
4
|
+
#or
|
|
5
|
+
lpy -t #if you want to print python translation.
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
The REPL features Emacs-style keybindings (C-a, C-e, C-b, C-f, M-b, M-f, etc.), arrow key navigation, and persistent command history saved to `~/.lpy_history`.
|
|
9
|
+
|
|
10
|
+
### Auto-closing pairs
|
|
11
|
+
|
|
12
|
+
The REPL automatically inserts closing brackets and quotes when you type an opening one:
|
|
13
|
+
|
|
14
|
+
| You type | REPL inserts | Cursor position |
|
|
15
|
+
|----------|-------------|-----------------|
|
|
16
|
+
| `(` | `()` | between `(` and `)` |
|
|
17
|
+
| `[` | `[]` | between `[` and `]` |
|
|
18
|
+
| `{` | `{}` | between `{` and `}` |
|
|
19
|
+
| `'` | `''` | between the quotes |
|
|
20
|
+
| `"` | `""` | between the quotes |
|
|
21
|
+
|
|
22
|
+
- Typing a closing character (`)`, `]`, `}`) when the cursor is already before one will skip over it instead of inserting a duplicate.
|
|
23
|
+
- Typing a quote (`'`, `"`) when the cursor is before the same quote will skip over it.
|
|
24
|
+
- Pressing backspace between an empty pair deletes both characters.
|
|
25
|
+
|
|
26
|
+
## Run from source
|
|
27
|
+
```shell
|
|
28
|
+
lpy {filename}.lpy
|
|
29
|
+
```
|
|
30
|
+
## Run translation
|
|
31
|
+
```shell
|
|
32
|
+
l2py {filename}.lpy
|
|
33
|
+
```
|
|
34
|
+
It just displays translation. (don't run it)
|
|
35
|
+
## Run Tests (for development)
|
|
36
|
+
```shell
|
|
37
|
+
# in project root directory
|
|
38
|
+
pytest
|
|
39
|
+
#or
|
|
40
|
+
lpy -m pytest
|
|
41
|
+
```
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "lispython"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.6"
|
|
4
4
|
description = "Lisp-like Syntax for Python with Lisp-like Macros"
|
|
5
5
|
authors = [{ name = "Jetack", email = "jetack23@gmail.com" }]
|
|
6
6
|
license = { text = "MIT" }
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
requires-python = ">=3.11"
|
|
9
|
-
dependencies = [
|
|
9
|
+
dependencies = [
|
|
10
|
+
"prompt-toolkit>=3.0.52",
|
|
11
|
+
"pygls>=1.0.0",
|
|
12
|
+
]
|
|
10
13
|
|
|
11
14
|
[project.urls]
|
|
12
15
|
Homepage = "https://jetack.github.io/lispython"
|
|
@@ -8,6 +8,22 @@ from lispy.core.nodes import *
|
|
|
8
8
|
|
|
9
9
|
__macro_namespace: Dict[str, Callable[[Node], ast.AST]] = {}
|
|
10
10
|
|
|
11
|
+
_ast_literal_eval = __import__("ast").literal_eval
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _unwrap_literal(node):
|
|
15
|
+
if isinstance(node, Constant):
|
|
16
|
+
try:
|
|
17
|
+
return _ast_literal_eval(node.value)
|
|
18
|
+
except (ValueError, SyntaxError):
|
|
19
|
+
return node
|
|
20
|
+
elif isinstance(node, String):
|
|
21
|
+
try:
|
|
22
|
+
return _ast_literal_eval(node.value)
|
|
23
|
+
except (ValueError, SyntaxError):
|
|
24
|
+
return node
|
|
25
|
+
return node
|
|
26
|
+
|
|
11
27
|
|
|
12
28
|
def define_macro(sexp, scope, include_meta=True):
|
|
13
29
|
transformed = defmacro_transform(sexp)
|
|
@@ -69,7 +85,9 @@ def macroexpand_1_and_check(sexp, scope=globals(), in_quasi=False, include_meta=
|
|
|
69
85
|
elif str(op) == "require" and not in_quasi:
|
|
70
86
|
sexp = require_macro(sexp, scope, include_meta=include_meta)
|
|
71
87
|
elif str(op) in scope.setdefault("__macro_namespace", {}) and not in_quasi and isinstance(sexp, Paren):
|
|
72
|
-
sexp = scope["__macro_namespace"][str(op)](*operands)
|
|
88
|
+
sexp = scope["__macro_namespace"][str(op)](*[_unwrap_literal(o) for o in operands])
|
|
89
|
+
if not isinstance(sexp, Node):
|
|
90
|
+
sexp = data_to_generator_expression(sexp)
|
|
73
91
|
expanded = True
|
|
74
92
|
else:
|
|
75
93
|
expanded_list, expanded_feedbacks = zip(
|
|
@@ -44,7 +44,11 @@ class Node:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def data_to_generator_expression(data):
|
|
47
|
-
if isinstance(data,
|
|
47
|
+
if isinstance(data, bool) or data is None:
|
|
48
|
+
return Constant(str(data))
|
|
49
|
+
elif isinstance(data, (int, float, complex)):
|
|
50
|
+
return Constant(str(data))
|
|
51
|
+
elif isinstance(data, str):
|
|
48
52
|
return String('"' + data + '"')
|
|
49
53
|
elif isinstance(data, list):
|
|
50
54
|
return Bracket(*data)
|
|
@@ -751,6 +751,85 @@
|
|
|
751
751
|
:range (make-range lineno 0 lineno 0))])))))
|
|
752
752
|
(return None)))
|
|
753
753
|
|
|
754
|
+
;; ---------------------------------------------------------------------------
|
|
755
|
+
;; Completion
|
|
756
|
+
;; ---------------------------------------------------------------------------
|
|
757
|
+
|
|
758
|
+
(= _LPY-KEYWORDS
|
|
759
|
+
["defn" "cond" "conde" "ife" "when" "unless"
|
|
760
|
+
"do" "deco" "require" "fn" "match" "case"
|
|
761
|
+
"async-def" "async-for" "async-with"
|
|
762
|
+
"yield-from" "except*"
|
|
763
|
+
"->" "->>" "as->"
|
|
764
|
+
"gensym" "pprint"])
|
|
765
|
+
|
|
766
|
+
(deco (server.feature
|
|
767
|
+
lsp.TEXT_DOCUMENT_COMPLETION
|
|
768
|
+
(lsp.CompletionOptions :trigger-characters ["." "-"]))
|
|
769
|
+
(def completion [ls params]
|
|
770
|
+
(= doc (.get-text-document ls.workspace params.text_document.uri))
|
|
771
|
+
(= pos params.position)
|
|
772
|
+
(= items [])
|
|
773
|
+
(= seen (set))
|
|
774
|
+
|
|
775
|
+
;; 1. Special forms
|
|
776
|
+
(for name in SPECIAL-FORM-DOCS
|
|
777
|
+
(if (not (in name seen))
|
|
778
|
+
(do (seen.add name)
|
|
779
|
+
(items.append
|
|
780
|
+
(lsp.CompletionItem
|
|
781
|
+
:label name
|
|
782
|
+
:kind lsp.CompletionItemKind.Keyword
|
|
783
|
+
:detail "special form")))))
|
|
784
|
+
|
|
785
|
+
;; 2. LisPython-specific keywords
|
|
786
|
+
(for name in _LPY-KEYWORDS
|
|
787
|
+
(if (not (in name seen))
|
|
788
|
+
(do (seen.add name)
|
|
789
|
+
(items.append
|
|
790
|
+
(lsp.CompletionItem
|
|
791
|
+
:label name
|
|
792
|
+
:kind lsp.CompletionItemKind.Keyword
|
|
793
|
+
:detail "keyword")))))
|
|
794
|
+
|
|
795
|
+
;; 3. Python builtins
|
|
796
|
+
(for [name info] in (BUILTIN-INFO.items)
|
|
797
|
+
(if (not (in name seen))
|
|
798
|
+
(do (seen.add name)
|
|
799
|
+
(= kind (ife (isinstance (getattr builtins name None) type)
|
|
800
|
+
lsp.CompletionItemKind.Class
|
|
801
|
+
lsp.CompletionItemKind.Function))
|
|
802
|
+
(items.append
|
|
803
|
+
(lsp.CompletionItem
|
|
804
|
+
:label name
|
|
805
|
+
:kind kind
|
|
806
|
+
:detail (or (.get info "signature") ""))))))
|
|
807
|
+
|
|
808
|
+
;; 4. Symbols from current file
|
|
809
|
+
(try
|
|
810
|
+
(= tree (parse doc.source))
|
|
811
|
+
(= defs (collect-definitions tree doc.uri))
|
|
812
|
+
(for name in defs
|
|
813
|
+
(if (not (in name seen))
|
|
814
|
+
(do (seen.add name)
|
|
815
|
+
(items.append
|
|
816
|
+
(lsp.CompletionItem
|
|
817
|
+
:label name
|
|
818
|
+
:kind lsp.CompletionItemKind.Variable)))))
|
|
819
|
+
(except [Exception] (pass)))
|
|
820
|
+
|
|
821
|
+
;; 5. Workspace symbols
|
|
822
|
+
(for name in WORKSPACE-INDEX
|
|
823
|
+
(if (not (in name seen))
|
|
824
|
+
(do (seen.add name)
|
|
825
|
+
(items.append
|
|
826
|
+
(lsp.CompletionItem
|
|
827
|
+
:label name
|
|
828
|
+
:kind lsp.CompletionItemKind.Variable
|
|
829
|
+
:detail "workspace")))))
|
|
830
|
+
|
|
831
|
+
(return (lsp.CompletionList :is-incomplete False :items items))))
|
|
832
|
+
|
|
754
833
|
(deco (server.feature lsp.TEXT_DOCUMENT_REFERENCES)
|
|
755
834
|
(def references [ls params]
|
|
756
835
|
(= doc (.get-text-document ls.workspace params.text_document.uri))
|