pyscript-programming-language 1.4.0__tar.gz → 1.5.0__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.
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/PKG-INFO +5 -2
- pyscript_programming_language-1.5.0/pyscript/__init__.py +34 -0
- pyscript_programming_language-1.5.0/pyscript/__init__.pyi +73 -0
- pyscript_programming_language-1.5.0/pyscript/__main__.py +172 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/__init__.py +1 -1
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/analyzer.py +66 -41
- pyscript_programming_language-1.5.0/pyscript/core/bases.py +2 -0
- pyscript_programming_language-1.5.0/pyscript/core/buffer.py +33 -0
- pyscript_programming_language-1.5.0/pyscript/core/cache.py +96 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/constants.py +38 -30
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/context.py +13 -9
- pyscript_programming_language-1.5.0/pyscript/core/exceptions.py +110 -0
- pyscript_programming_language-1.5.0/pyscript/core/handlers.py +82 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/highlight.py +36 -31
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/interpreter.py +128 -151
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/lexer.py +44 -19
- pyscript_programming_language-1.5.0/pyscript/core/nodes.py +503 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/objects.py +35 -44
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/parser.py +383 -240
- pyscript_programming_language-1.5.0/pyscript/core/position.py +97 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/pysbuiltins.py +60 -41
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/results.py +1 -1
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/runner.py +100 -67
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/symtab.py +24 -11
- pyscript_programming_language-1.5.0/pyscript/core/token.py +39 -0
- pyscript_programming_language-1.5.0/pyscript/core/utils/__init__.py +13 -0
- pyscript_programming_language-1.5.0/pyscript/core/utils/constants.py +151 -0
- pyscript_programming_language-1.5.0/pyscript/core/utils/debug.py +35 -0
- pyscript_programming_language-1.5.0/pyscript/core/utils/decorators.py +44 -0
- pyscript_programming_language-1.5.0/pyscript/core/utils/general.py +139 -0
- pyscript_programming_language-1.5.0/pyscript/core/version.py +36 -0
- pyscript_programming_language-1.5.0/pyscript/lib/67.pys +1 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/brainfuck.pys +5 -5
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/getch.pys +2 -1
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/jsdict.pys +1 -9
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/parser.pys +33 -12
- pyscript_programming_language-1.5.0/pyscript/lib/this.pys +19 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript_programming_language.egg-info/PKG-INFO +5 -2
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript_programming_language.egg-info/SOURCES.txt +7 -2
- pyscript_programming_language-1.5.0/pyscript_programming_language.egg-info/requires.txt +3 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/setup.py +5 -2
- pyscript_programming_language-1.4.0/pyscript/__init__.py +0 -33
- pyscript_programming_language-1.4.0/pyscript/__init__.pyi +0 -54
- pyscript_programming_language-1.4.0/pyscript/__main__.py +0 -142
- pyscript_programming_language-1.4.0/pyscript/core/bases.py +0 -2
- pyscript_programming_language-1.4.0/pyscript/core/buffer.py +0 -26
- pyscript_programming_language-1.4.0/pyscript/core/cache.py +0 -16
- pyscript_programming_language-1.4.0/pyscript/core/exceptions.py +0 -91
- pyscript_programming_language-1.4.0/pyscript/core/handlers.py +0 -74
- pyscript_programming_language-1.4.0/pyscript/core/nodes.py +0 -326
- pyscript_programming_language-1.4.0/pyscript/core/position.py +0 -92
- pyscript_programming_language-1.4.0/pyscript/core/singletons.py +0 -124
- pyscript_programming_language-1.4.0/pyscript/core/token.py +0 -25
- pyscript_programming_language-1.4.0/pyscript/core/utils.py +0 -174
- pyscript_programming_language-1.4.0/pyscript/core/version.py +0 -5
- pyscript_programming_language-1.4.0/pyscript/lib/this.pys +0 -19
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/MANIFEST.in +0 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/README.md +0 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/__hello__.pys +0 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/clock.pys +0 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/sys.pys +0 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/this.py +0 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript_programming_language.egg-info/dependency_links.txt +0 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript_programming_language.egg-info/top_level.txt +0 -0
- {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyscript-programming-language
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: PyScript Programming Language
|
|
5
5
|
Home-page: https://github.com/azzammuhyala/pyscript
|
|
6
6
|
Author: azzammuhyala
|
|
@@ -15,8 +15,10 @@ Classifier: Intended Audience :: Developers
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
16
|
Classifier: Topic :: Software Development :: Interpreters
|
|
17
17
|
Classifier: Topic :: Software Development :: Compilers
|
|
18
|
-
Requires-Python: >=3.
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
|
+
Provides-Extra: typecheck
|
|
21
|
+
Requires-Dist: beartype; extra == "typecheck"
|
|
20
22
|
Dynamic: author
|
|
21
23
|
Dynamic: author-email
|
|
22
24
|
Dynamic: classifier
|
|
@@ -26,6 +28,7 @@ Dynamic: home-page
|
|
|
26
28
|
Dynamic: keywords
|
|
27
29
|
Dynamic: license
|
|
28
30
|
Dynamic: project-url
|
|
31
|
+
Dynamic: provides-extra
|
|
29
32
|
Dynamic: requires-python
|
|
30
33
|
Dynamic: summary
|
|
31
34
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PyScript is a programming language written in Python. \
|
|
3
|
+
This language is not isolated and is directly integrated with the Python's library and namespace levels.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
if __import__('sys').version_info < (3, 10):
|
|
7
|
+
raise ImportError("Python version 3.10 and above is required to run PyScript")
|
|
8
|
+
|
|
9
|
+
from . import core
|
|
10
|
+
|
|
11
|
+
from .core.constants import DEFAULT, DEBUG, SILENT, RETRES, COMMENT, NO_COLOR, REVERSE_POW_XOR
|
|
12
|
+
from .core.cache import undefined
|
|
13
|
+
from .core.highlight import HLFMT_HTML, HLFMT_ANSI, pys_highlight
|
|
14
|
+
from .core.runner import pys_exec, pys_eval, pys_shell
|
|
15
|
+
from .core.version import version_info, __version__, __date__
|
|
16
|
+
|
|
17
|
+
__all__ = (
|
|
18
|
+
'core',
|
|
19
|
+
'DEFAULT',
|
|
20
|
+
'DEBUG',
|
|
21
|
+
'SILENT',
|
|
22
|
+
'RETRES',
|
|
23
|
+
'COMMENT',
|
|
24
|
+
'NO_COLOR',
|
|
25
|
+
'REVERSE_POW_XOR',
|
|
26
|
+
'HLFMT_HTML',
|
|
27
|
+
'HLFMT_ANSI',
|
|
28
|
+
'undefined',
|
|
29
|
+
'version_info',
|
|
30
|
+
'pys_highlight',
|
|
31
|
+
'pys_exec',
|
|
32
|
+
'pys_eval',
|
|
33
|
+
'pys_shell'
|
|
34
|
+
)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Callable, Iterator, Literal, Optional
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from .core.buffer import PysFileBuffer
|
|
5
|
+
from .core.cache import PysUndefined
|
|
6
|
+
from .core.highlight import _HighlightFormatter
|
|
7
|
+
from .core.position import PysPosition
|
|
8
|
+
from .core.results import PysExecuteResult
|
|
9
|
+
from .core.symtab import PysSymbolTable
|
|
10
|
+
from .core.version import PysVersionInfo
|
|
11
|
+
|
|
12
|
+
from io import IOBase
|
|
13
|
+
|
|
14
|
+
from . import core as core
|
|
15
|
+
|
|
16
|
+
DEFAULT: int
|
|
17
|
+
DEBUG: int
|
|
18
|
+
SILENT: int
|
|
19
|
+
RETRES: int
|
|
20
|
+
COMMENT: int
|
|
21
|
+
NO_COLOR: int
|
|
22
|
+
REVERSE_POW_XOR: int
|
|
23
|
+
|
|
24
|
+
HLFMT_HTML: _HighlightFormatter
|
|
25
|
+
HLFMT_ANSI: _HighlightFormatter
|
|
26
|
+
|
|
27
|
+
undefined: PysUndefined
|
|
28
|
+
version_info: PysVersionInfo
|
|
29
|
+
|
|
30
|
+
def pys_highlight(
|
|
31
|
+
source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
|
|
32
|
+
format: Optional[
|
|
33
|
+
Callable[
|
|
34
|
+
[
|
|
35
|
+
str | Literal[
|
|
36
|
+
'start',
|
|
37
|
+
'bracket-unmatch',
|
|
38
|
+
'identifier', 'identifier-const', 'identifier-call', 'identifier-class',
|
|
39
|
+
'keyword', 'keyword-identifier',
|
|
40
|
+
'number', 'string', 'comment', 'newline',
|
|
41
|
+
'default',
|
|
42
|
+
'end'
|
|
43
|
+
],
|
|
44
|
+
PysPosition,
|
|
45
|
+
str
|
|
46
|
+
],
|
|
47
|
+
str
|
|
48
|
+
]
|
|
49
|
+
] = None,
|
|
50
|
+
max_parenthesis_level: int = 3,
|
|
51
|
+
flags: int = DEFAULT
|
|
52
|
+
) -> str: ...
|
|
53
|
+
|
|
54
|
+
def pys_exec(
|
|
55
|
+
source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
|
|
56
|
+
globals: Optional[dict[str, Any] | PysSymbolTable | PysUndefined] = None,
|
|
57
|
+
flags: int = DEFAULT
|
|
58
|
+
) -> None | PysExecuteResult: ...
|
|
59
|
+
|
|
60
|
+
def pys_eval(
|
|
61
|
+
source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
|
|
62
|
+
globals: Optional[dict[str, Any] | PysSymbolTable | PysUndefined] = None,
|
|
63
|
+
flags: int = DEFAULT
|
|
64
|
+
) -> Any | PysExecuteResult: ...
|
|
65
|
+
|
|
66
|
+
def pys_shell(
|
|
67
|
+
globals: Optional[dict[str, Any] | PysSymbolTable | PysUndefined] = None,
|
|
68
|
+
flags: int = DEFAULT
|
|
69
|
+
) -> int | Any: ...
|
|
70
|
+
|
|
71
|
+
__version__: str
|
|
72
|
+
__date__: str
|
|
73
|
+
__all__: tuple[str]
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
from .core.buffer import PysFileBuffer
|
|
2
|
+
from .core.cache import undefined
|
|
3
|
+
from .core.constants import DEFAULT, DEBUG, NO_COLOR
|
|
4
|
+
from .core.handlers import handle_execute
|
|
5
|
+
from .core.highlight import HLFMT_HTML, HLFMT_ANSI, pys_highlight
|
|
6
|
+
from .core.runner import pys_runner, pys_shell
|
|
7
|
+
from .core.symtab import build_symbol_table
|
|
8
|
+
from .core.utils.general import normalize_path
|
|
9
|
+
from .core.version import __version__
|
|
10
|
+
|
|
11
|
+
from argparse import ArgumentParser
|
|
12
|
+
|
|
13
|
+
from sys import executable, version_info, exit, setrecursionlimit
|
|
14
|
+
from os.path import basename, splitext
|
|
15
|
+
|
|
16
|
+
parser = ArgumentParser(
|
|
17
|
+
prog=splitext(basename(executable))[0] + ' -m pyscript',
|
|
18
|
+
description='PyScript Launcher for Python Version ' + '.'.join(map(str, version_info))
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
'file',
|
|
23
|
+
type=str,
|
|
24
|
+
nargs='?',
|
|
25
|
+
default=None,
|
|
26
|
+
help="file path"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
'-v', '--version',
|
|
31
|
+
action='version',
|
|
32
|
+
version=f"PyScript {__version__}",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
'-c', '--command',
|
|
37
|
+
type=str,
|
|
38
|
+
default=None,
|
|
39
|
+
help="execute PyScript from argument",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
'-d', '--debug',
|
|
44
|
+
action='store_true',
|
|
45
|
+
help="set a debug flag, this will remove the assert statement"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
'-i', '--inspect',
|
|
50
|
+
action='store_true',
|
|
51
|
+
help="inspect interactively after running a file",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
'-l', '--highlight',
|
|
56
|
+
choices=('html', 'ansi'),
|
|
57
|
+
default=None,
|
|
58
|
+
help='generate PyScript highlight code from a file'
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
'-n', '--no-color',
|
|
63
|
+
action='store_true',
|
|
64
|
+
help="no colorful traceback"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
parser.add_argument(
|
|
68
|
+
'-r', '--py-recursion',
|
|
69
|
+
type=int,
|
|
70
|
+
default=None,
|
|
71
|
+
help="set a python recursion limit"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
args = parser.parse_args()
|
|
75
|
+
|
|
76
|
+
if args.highlight and args.file is None:
|
|
77
|
+
parser.error("-l, --highlight: file path require")
|
|
78
|
+
|
|
79
|
+
if args.py_recursion is not None:
|
|
80
|
+
try:
|
|
81
|
+
setrecursionlimit(args.py_recursion)
|
|
82
|
+
except BaseException as e:
|
|
83
|
+
parser.error(f"-r, --py-recursion: {e}")
|
|
84
|
+
|
|
85
|
+
code = 0
|
|
86
|
+
flags = DEFAULT
|
|
87
|
+
|
|
88
|
+
if args.debug:
|
|
89
|
+
flags |= DEBUG
|
|
90
|
+
if args.no_color:
|
|
91
|
+
flags |= NO_COLOR
|
|
92
|
+
|
|
93
|
+
if args.file is not None:
|
|
94
|
+
path = normalize_path(args.file)
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
with open(path, 'r') as file:
|
|
98
|
+
file = PysFileBuffer(file, path)
|
|
99
|
+
|
|
100
|
+
except FileNotFoundError:
|
|
101
|
+
parser.error(f"can't open file {path!r}: No such file or directory")
|
|
102
|
+
|
|
103
|
+
except PermissionError:
|
|
104
|
+
parser.error(f"can't open file {path!r}: Permission denied.")
|
|
105
|
+
|
|
106
|
+
except IsADirectoryError:
|
|
107
|
+
parser.error(f"can't open file {path!r}: Path is not a file.")
|
|
108
|
+
|
|
109
|
+
except NotADirectoryError:
|
|
110
|
+
parser.error(f"can't open file {path!r}: Attempting to access directory from file.")
|
|
111
|
+
|
|
112
|
+
except (OSError, IOError):
|
|
113
|
+
parser.error(f"can't open file {path!r}: Attempting to access a system directory or file.")
|
|
114
|
+
|
|
115
|
+
except UnicodeDecodeError:
|
|
116
|
+
parser.error(f"can't read file {path!r}: Bad file.")
|
|
117
|
+
|
|
118
|
+
except BaseException as e:
|
|
119
|
+
parser.error(f"file {path!r}: Unexpected error: {e}")
|
|
120
|
+
|
|
121
|
+
if args.highlight:
|
|
122
|
+
try:
|
|
123
|
+
print(
|
|
124
|
+
pys_highlight(
|
|
125
|
+
file,
|
|
126
|
+
HLFMT_HTML if args.highlight == 'html' else HLFMT_ANSI
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
except BaseException as e:
|
|
130
|
+
parser.error(f"file {path!r}: Tokenize error: {e}")
|
|
131
|
+
|
|
132
|
+
else:
|
|
133
|
+
symtab = build_symbol_table(file)
|
|
134
|
+
symtab.set('__name__', '__main__')
|
|
135
|
+
|
|
136
|
+
result = pys_runner(
|
|
137
|
+
file=file,
|
|
138
|
+
mode='exec',
|
|
139
|
+
symbol_table=symtab,
|
|
140
|
+
flags=flags
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
code = handle_execute(result)
|
|
144
|
+
|
|
145
|
+
if args.inspect:
|
|
146
|
+
code = pys_shell(
|
|
147
|
+
globals=result.context.symbol_table,
|
|
148
|
+
flags=result.context.flags
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
elif args.command is not None:
|
|
152
|
+
file = PysFileBuffer(args.command)
|
|
153
|
+
|
|
154
|
+
symtab = build_symbol_table(file)
|
|
155
|
+
symtab.set('__name__', '__main__')
|
|
156
|
+
|
|
157
|
+
code = handle_execute(
|
|
158
|
+
pys_runner(
|
|
159
|
+
file=file,
|
|
160
|
+
mode='exec',
|
|
161
|
+
symbol_table=symtab,
|
|
162
|
+
flags=flags
|
|
163
|
+
)
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
else:
|
|
167
|
+
code = pys_shell(
|
|
168
|
+
globals=undefined,
|
|
169
|
+
flags=flags
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
exit(code)
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
from .bases import Pys
|
|
2
|
-
from .constants import TOKENS, DEFAULT
|
|
2
|
+
from .constants import TOKENS, DEFAULT, NSEQ_GLOBAL, NSEQ_DEL, NSEQ_DICT, NTER_GENERAL
|
|
3
3
|
from .context import PysContext
|
|
4
4
|
from .exceptions import PysException
|
|
5
|
-
from .nodes import
|
|
5
|
+
from .nodes import PysNode, PysKeywordNode, PysIdentifierNode, PysSequenceNode, PysAttributeNode, PysSubscriptNode
|
|
6
|
+
from .position import PysPosition
|
|
7
|
+
from .utils.decorators import typechecked
|
|
8
|
+
|
|
9
|
+
from typing import Optional
|
|
6
10
|
|
|
7
11
|
class PysAnalyzer(Pys):
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
@typechecked
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
node: PysNode,
|
|
17
|
+
flags: int = DEFAULT,
|
|
18
|
+
context_parent: Optional[PysContext] = None,
|
|
19
|
+
context_parent_entry_position: Optional[PysPosition] = None
|
|
20
|
+
) -> None:
|
|
21
|
+
|
|
22
|
+
self.node = node
|
|
11
23
|
self.flags = flags
|
|
12
24
|
self.context = context_parent
|
|
13
25
|
self.context_parent_entry_position = context_parent_entry_position
|
|
@@ -17,7 +29,7 @@ class PysAnalyzer(Pys):
|
|
|
17
29
|
self.error = PysException(
|
|
18
30
|
SyntaxError(message),
|
|
19
31
|
PysContext(
|
|
20
|
-
file=self.file,
|
|
32
|
+
file=self.node.position.file,
|
|
21
33
|
flags=self.flags,
|
|
22
34
|
parent=self.context,
|
|
23
35
|
parent_entry_position=self.context_parent_entry_position
|
|
@@ -25,15 +37,14 @@ class PysAnalyzer(Pys):
|
|
|
25
37
|
position
|
|
26
38
|
)
|
|
27
39
|
|
|
28
|
-
|
|
40
|
+
@typechecked
|
|
41
|
+
def analyze(self) -> PysException | None:
|
|
29
42
|
self.in_loop = 0
|
|
30
43
|
self.in_function = 0
|
|
31
44
|
self.in_switch = 0
|
|
32
|
-
|
|
33
45
|
self.error = None
|
|
34
46
|
|
|
35
|
-
self.visit(node)
|
|
36
|
-
|
|
47
|
+
self.visit(self.node)
|
|
37
48
|
return self.error
|
|
38
49
|
|
|
39
50
|
def visit(self, node):
|
|
@@ -43,37 +54,38 @@ class PysAnalyzer(Pys):
|
|
|
43
54
|
|
|
44
55
|
def visit_SequenceNode(self, node):
|
|
45
56
|
|
|
46
|
-
if node.type ==
|
|
57
|
+
if node.type == NSEQ_DEL:
|
|
47
58
|
|
|
48
59
|
for element in node.elements:
|
|
49
60
|
|
|
50
61
|
if isinstance(element, PysSubscriptNode):
|
|
51
|
-
self.visit(element.
|
|
62
|
+
self.visit(element.target)
|
|
52
63
|
if self.error:
|
|
53
64
|
return
|
|
54
65
|
|
|
55
|
-
self.
|
|
66
|
+
self.visit_slice_SubscriptNode(element.slice)
|
|
56
67
|
if self.error:
|
|
57
68
|
return
|
|
58
69
|
|
|
59
70
|
elif isinstance(element, PysAttributeNode):
|
|
60
|
-
self.visit(element.
|
|
71
|
+
self.visit(element.target)
|
|
61
72
|
if self.error:
|
|
62
73
|
return
|
|
63
74
|
|
|
64
75
|
elif isinstance(element, PysKeywordNode):
|
|
65
|
-
self.throw("cannot delete {
|
|
76
|
+
self.throw(f"cannot delete {element.token.value}", element.position)
|
|
66
77
|
return
|
|
67
78
|
|
|
68
79
|
elif not isinstance(element, PysIdentifierNode):
|
|
69
80
|
self.throw("cannot delete literal", element.position)
|
|
70
81
|
return
|
|
71
82
|
|
|
72
|
-
elif node.type ==
|
|
83
|
+
elif node.type == NSEQ_GLOBAL:
|
|
84
|
+
|
|
73
85
|
if self.in_function == 0:
|
|
74
86
|
self.throw("global outside of function", node.position)
|
|
75
87
|
|
|
76
|
-
elif node.type ==
|
|
88
|
+
elif node.type == NSEQ_DICT:
|
|
77
89
|
|
|
78
90
|
for key, value in node.elements:
|
|
79
91
|
|
|
@@ -86,20 +98,21 @@ class PysAnalyzer(Pys):
|
|
|
86
98
|
return
|
|
87
99
|
|
|
88
100
|
else:
|
|
101
|
+
|
|
89
102
|
for element in node.elements:
|
|
90
103
|
self.visit(element)
|
|
91
104
|
if self.error:
|
|
92
105
|
return
|
|
93
106
|
|
|
94
107
|
def visit_AttributeNode(self, node):
|
|
95
|
-
self.visit(node.
|
|
108
|
+
self.visit(node.target)
|
|
96
109
|
|
|
97
110
|
def visit_SubscriptNode(self, node):
|
|
98
|
-
self.visit(node.
|
|
111
|
+
self.visit(node.target)
|
|
99
112
|
if self.error:
|
|
100
113
|
return
|
|
101
114
|
|
|
102
|
-
self.
|
|
115
|
+
self.visit_slice_SubscriptNode(node.slice)
|
|
103
116
|
|
|
104
117
|
def visit_ChainOperatorNode(self, node):
|
|
105
118
|
for expression in node.expressions:
|
|
@@ -108,7 +121,7 @@ class PysAnalyzer(Pys):
|
|
|
108
121
|
return
|
|
109
122
|
|
|
110
123
|
def visit_TernaryOperatorNode(self, node):
|
|
111
|
-
if node.style ==
|
|
124
|
+
if node.style == NTER_GENERAL:
|
|
112
125
|
self.visit(node.condition)
|
|
113
126
|
if self.error:
|
|
114
127
|
return
|
|
@@ -140,17 +153,17 @@ class PysAnalyzer(Pys):
|
|
|
140
153
|
operator = 'increase' if node.operand.type == TOKENS['INCREMENT'] else 'decrease'
|
|
141
154
|
|
|
142
155
|
if isinstance(node.value, PysKeywordNode):
|
|
143
|
-
self.throw("cannot {} {
|
|
156
|
+
self.throw(f"cannot {operator} {node.value.token.value}", node.value.position)
|
|
144
157
|
return
|
|
145
158
|
|
|
146
159
|
elif not isinstance(node.value, (PysIdentifierNode, PysAttributeNode, PysSubscriptNode)):
|
|
147
|
-
self.throw("cannot {} literal"
|
|
160
|
+
self.throw(f"cannot {operator} literal", node.value.position)
|
|
148
161
|
return
|
|
149
162
|
|
|
150
163
|
self.visit(node.value)
|
|
151
164
|
|
|
152
165
|
def visit_AssignNode(self, node):
|
|
153
|
-
self.
|
|
166
|
+
self.visit_declaration_AssignNode(
|
|
154
167
|
node.target,
|
|
155
168
|
"cannot assign to expression here. Maybe you meant '==' instead of '='?"
|
|
156
169
|
)
|
|
@@ -225,7 +238,7 @@ class PysAnalyzer(Pys):
|
|
|
225
238
|
if len(node.header) == 2:
|
|
226
239
|
declaration, iterable = node.header
|
|
227
240
|
|
|
228
|
-
self.
|
|
241
|
+
self.visit_declaration_AssignNode(declaration, "cannot assign to expression")
|
|
229
242
|
if self.error:
|
|
230
243
|
return
|
|
231
244
|
|
|
@@ -323,7 +336,7 @@ class PysAnalyzer(Pys):
|
|
|
323
336
|
name = token.value
|
|
324
337
|
|
|
325
338
|
if name in parameter_names:
|
|
326
|
-
return self.throw("duplicate argument {!r} in function definition"
|
|
339
|
+
return self.throw(f"duplicate argument {name!r} in function definition", token.position)
|
|
327
340
|
|
|
328
341
|
parameter_names.add(name)
|
|
329
342
|
|
|
@@ -356,18 +369,20 @@ class PysAnalyzer(Pys):
|
|
|
356
369
|
keyword_argument_names = set()
|
|
357
370
|
|
|
358
371
|
for element in node.arguments:
|
|
359
|
-
value = element
|
|
360
372
|
|
|
361
373
|
if isinstance(element, tuple):
|
|
362
374
|
token, value = element
|
|
363
375
|
name = token.value
|
|
364
376
|
|
|
365
377
|
if name in keyword_argument_names:
|
|
366
|
-
self.throw("duplicate argument {!r} in call definition"
|
|
378
|
+
self.throw(f"duplicate argument {name!r} in call definition", token.position)
|
|
367
379
|
return
|
|
368
380
|
|
|
369
381
|
keyword_argument_names.add(name)
|
|
370
382
|
|
|
383
|
+
else:
|
|
384
|
+
value = element
|
|
385
|
+
|
|
371
386
|
self.visit(value)
|
|
372
387
|
if self.error:
|
|
373
388
|
return
|
|
@@ -399,41 +414,51 @@ class PysAnalyzer(Pys):
|
|
|
399
414
|
if self.in_loop == 0 and self.in_switch == 0:
|
|
400
415
|
self.throw("break outside of loop or switch case", node.position)
|
|
401
416
|
|
|
402
|
-
def
|
|
403
|
-
if isinstance(
|
|
404
|
-
for element in
|
|
405
|
-
self.
|
|
417
|
+
def visit_slice_SubscriptNode(self, nslice):
|
|
418
|
+
if isinstance(nslice, tuple):
|
|
419
|
+
for element in nslice:
|
|
420
|
+
self.visit_slice_SubscriptNode(element)
|
|
406
421
|
if self.error:
|
|
407
422
|
return
|
|
408
423
|
|
|
409
|
-
elif isinstance(
|
|
410
|
-
|
|
411
|
-
self.visit(
|
|
424
|
+
elif isinstance(nslice, slice):
|
|
425
|
+
if nslice.start is not None:
|
|
426
|
+
self.visit(nslice.start)
|
|
427
|
+
if self.error:
|
|
428
|
+
return
|
|
429
|
+
|
|
430
|
+
if nslice.stop is not None:
|
|
431
|
+
self.visit(nslice.stop)
|
|
432
|
+
if self.error:
|
|
433
|
+
return
|
|
434
|
+
|
|
435
|
+
if nslice.step is not None:
|
|
436
|
+
self.visit(nslice.step)
|
|
412
437
|
if self.error:
|
|
413
438
|
return
|
|
414
439
|
|
|
415
440
|
else:
|
|
416
|
-
self.visit(
|
|
441
|
+
self.visit(nslice)
|
|
417
442
|
|
|
418
|
-
def
|
|
443
|
+
def visit_declaration_AssignNode(self, node, message):
|
|
419
444
|
if isinstance(node, PysSequenceNode):
|
|
420
445
|
for element in node.elements:
|
|
421
|
-
self.
|
|
446
|
+
self.visit_declaration_AssignNode(element, message)
|
|
422
447
|
if self.error:
|
|
423
448
|
return
|
|
424
449
|
|
|
425
450
|
elif isinstance(node, PysSubscriptNode):
|
|
426
|
-
self.visit(node.
|
|
451
|
+
self.visit(node.target)
|
|
427
452
|
if self.error:
|
|
428
453
|
return
|
|
429
454
|
|
|
430
|
-
self.
|
|
455
|
+
self.visit_slice_SubscriptNode(node.slice)
|
|
431
456
|
|
|
432
457
|
elif isinstance(node, PysAttributeNode):
|
|
433
|
-
self.visit(node.
|
|
458
|
+
self.visit(node.target)
|
|
434
459
|
|
|
435
460
|
elif isinstance(node, PysKeywordNode):
|
|
436
|
-
self.throw("cannot assign to {
|
|
461
|
+
self.throw(f"cannot assign to {node.token.value}", node.position)
|
|
437
462
|
|
|
438
463
|
elif not isinstance(node, PysIdentifierNode):
|
|
439
464
|
self.throw(message, node.position)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from .bases import Pys
|
|
2
|
+
from .utils.decorators import immutable
|
|
3
|
+
from .utils.general import setimuattr, tostr
|
|
4
|
+
|
|
5
|
+
from io import IOBase
|
|
6
|
+
|
|
7
|
+
@immutable
|
|
8
|
+
class PysBuffer(Pys):
|
|
9
|
+
__slots__ = ()
|
|
10
|
+
|
|
11
|
+
class PysFileBuffer(PysBuffer):
|
|
12
|
+
|
|
13
|
+
__slots__ = ('text', 'name')
|
|
14
|
+
|
|
15
|
+
def __init__(self, text, name=None):
|
|
16
|
+
|
|
17
|
+
if isinstance(text, PysFileBuffer):
|
|
18
|
+
name = tostr(text.name if name is None else name)
|
|
19
|
+
text = tostr(text.text)
|
|
20
|
+
|
|
21
|
+
elif isinstance(text, IOBase):
|
|
22
|
+
name = tostr(text.name if name is None else name)
|
|
23
|
+
text = tostr(text)
|
|
24
|
+
|
|
25
|
+
else:
|
|
26
|
+
name = '<string>' if name is None else tostr(name)
|
|
27
|
+
text = tostr(text)
|
|
28
|
+
|
|
29
|
+
setimuattr(self, 'text', text)
|
|
30
|
+
setimuattr(self, 'name', name)
|
|
31
|
+
|
|
32
|
+
def __repr__(self):
|
|
33
|
+
return f'<FileBuffer from {self.name!r}>'
|