pyscript-programming-language 1.7.2__tar.gz → 1.7.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.
Files changed (77) hide show
  1. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/PKG-INFO +2 -2
  2. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/__main__.py +16 -15
  3. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/analyzer.py +9 -7
  4. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/exceptions.py +3 -1
  5. pyscript_programming_language-1.7.3/pyscript/core/mapping.py +131 -0
  6. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/objects.py +5 -4
  7. pyscript_programming_language-1.7.3/pyscript/core/position.py +99 -0
  8. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/pysbuiltins.py +148 -17
  9. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/runner.py +3 -0
  10. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/decorators.py +1 -1
  11. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/generic.py +29 -14
  12. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/module.py +1 -1
  13. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/shell.py +4 -0
  14. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/version.py +2 -2
  15. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/ast/__init__.pys +6 -0
  16. pyscript_programming_language-1.7.3/pyscript/lib/ast/ast_literal_eval.py +51 -0
  17. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/ast/ast_unparse.py +6 -69
  18. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/brainfuck.pys +3 -3
  19. pyscript_programming_language-1.7.3/pyscript/lib/dis.pys +7 -0
  20. pyscript_programming_language-1.7.3/pyscript/lib/token.pys +12 -0
  21. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/tokenize/__init__.pys +3 -1
  22. pyscript_programming_language-1.7.3/pyscript/lib/tokenize/tok_untokenize.py +27 -0
  23. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript_programming_language.egg-info/PKG-INFO +2 -2
  24. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript_programming_language.egg-info/SOURCES.txt +1 -0
  25. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/setup.py +2 -2
  26. pyscript_programming_language-1.7.2/pyscript/core/mapping.py +0 -67
  27. pyscript_programming_language-1.7.2/pyscript/core/position.py +0 -99
  28. pyscript_programming_language-1.7.2/pyscript/lib/dis.pys +0 -7
  29. pyscript_programming_language-1.7.2/pyscript/lib/token.pys +0 -1
  30. pyscript_programming_language-1.7.2/pyscript/lib/tokenize/tok_untokenize.py +0 -89
  31. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/MANIFEST.in +0 -0
  32. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/README.md +0 -0
  33. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/__init__.py +0 -0
  34. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/__init__.pyi +0 -0
  35. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/__init__.py +0 -0
  36. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/bases.py +0 -0
  37. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/buffer.py +0 -0
  38. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/cache.py +0 -0
  39. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/checks.py +0 -0
  40. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/constants.py +0 -0
  41. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/context.py +0 -0
  42. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/handlers.py +0 -0
  43. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/highlight.py +0 -0
  44. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/interpreter.py +0 -0
  45. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/lexer.py +0 -0
  46. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/nodes.py +0 -0
  47. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/parser.py +0 -0
  48. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/results.py +0 -0
  49. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/symtab.py +0 -0
  50. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/token.py +0 -0
  51. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/__init__.py +0 -0
  52. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/ansi.py +0 -0
  53. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/debug.py +0 -0
  54. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/path.py +0 -0
  55. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/similarity.py +0 -0
  56. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/core/utils/string.py +0 -0
  57. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/__hello__.pys +0 -0
  58. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/ansi.pys +0 -0
  59. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/ast/ast_dump.py +0 -0
  60. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/ast/ast_walk.py +0 -0
  61. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/explorer.pys +0 -0
  62. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/fpstimer.pys +0 -0
  63. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/getch.pys +0 -0
  64. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/inspect.pys +0 -0
  65. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/jsdict.pys +0 -0
  66. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/keyword.pys +0 -0
  67. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/parser.pys +0 -0
  68. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/site.pys +0 -0
  69. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/symtable.pys +0 -0
  70. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/sys.pys +0 -0
  71. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/lib/this.pys +0 -0
  72. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/site-packages/67.pys +0 -0
  73. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript/this.py +0 -0
  74. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript_programming_language.egg-info/dependency_links.txt +0 -0
  75. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript_programming_language.egg-info/requires.txt +0 -0
  76. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/pyscript_programming_language.egg-info/top_level.txt +0 -0
  77. {pyscript_programming_language-1.7.2 → pyscript_programming_language-1.7.3}/setup.cfg +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyscript-programming-language
3
- Version: 1.7.2
3
+ Version: 1.7.3
4
4
  Summary: PyScript Programming Language
5
- Home-page: https://github.com/azzammuhyala/pyscript
5
+ Home-page: https://azzammuhyala.github.io/pyscript
6
6
  Author: azzammuhyala
7
7
  Author-email: azzammuhyala@gmail.com
8
8
  License: MIT
@@ -9,7 +9,8 @@ from .core.version import __version__
9
9
 
10
10
  from argparse import ArgumentParser
11
11
  from os import environ
12
- from sys import executable, stderr, version_info, exit, setrecursionlimit
12
+
13
+ import sys
13
14
 
14
15
  FORMAT_HIGHLIGHT_MAP = {
15
16
  'html': HLFMT_HTML,
@@ -18,8 +19,8 @@ FORMAT_HIGHLIGHT_MAP = {
18
19
  }
19
20
 
20
21
  parser = ArgumentParser(
21
- prog=f'{get_module_name_from_path(executable)} -m pyscript',
22
- description=f'PyScript Launcher for Python Version {".".join(map(str, version_info))}'
22
+ prog=f'{get_module_name_from_path(sys.executable)} -m pyscript',
23
+ description=f'PyScript Launcher for Python Version {".".join(map(str, sys.version_info))}'
23
24
  )
24
25
 
25
26
  parser.add_argument(
@@ -27,7 +28,7 @@ parser.add_argument(
27
28
  type=str,
28
29
  nargs='?',
29
30
  default=None,
30
- help="file path"
31
+ help="File path to be executed"
31
32
  )
32
33
 
33
34
  parser.add_argument(
@@ -40,53 +41,53 @@ parser.add_argument(
40
41
  '-c', '--command',
41
42
  type=str,
42
43
  default=None,
43
- help="execute PyScript from argument",
44
+ help="Execute program from a string argument",
44
45
  )
45
46
 
46
47
  parser.add_argument(
47
48
  '-d', '--debug',
48
49
  action='store_true',
49
- help="set a debug flag, this will remove the assert statement"
50
+ help="Set a debug flag, this will remove the assert statement"
50
51
  )
51
52
 
52
53
  parser.add_argument(
53
54
  '-i', '--inspect',
54
55
  action='store_true',
55
- help="inspect interactively after running a file",
56
+ help="Inspect interactively after running a 'file'",
56
57
  )
57
58
 
58
59
  parser.add_argument(
59
60
  '-l', '--highlight',
60
61
  choices=tuple(FORMAT_HIGHLIGHT_MAP.keys()),
61
62
  default=None,
62
- help='generate PyScript highlight code from a file'
63
+ help="Generate highlight code from a 'file'"
63
64
  )
64
65
 
65
66
  parser.add_argument(
66
67
  '-n', '--no-color',
67
68
  action='store_true',
68
- help="no colorful traceback"
69
+ help="Suppress colored output"
69
70
  )
70
71
 
71
72
  parser.add_argument(
72
73
  '-r', '--py-recursion',
73
74
  type=int,
74
75
  default=None,
75
- help="set a python recursion limit"
76
+ help="Set a Python recursion limit"
76
77
  )
77
78
 
78
79
  def argument_error(argument, message):
79
- parser.print_usage(stderr)
80
+ parser.print_usage(sys.stderr)
80
81
  parser.exit(2, f"{parser.prog}: error: argument {argument}: {message}\n")
81
82
 
82
83
  args = parser.parse_args()
83
84
 
84
85
  if args.highlight and args.file is None:
85
- argument_error("-l/--highlight", "file path require")
86
+ argument_error("-l/--highlight", "argument 'file' required")
86
87
 
87
88
  if args.py_recursion is not None:
88
89
  try:
89
- setrecursionlimit(args.py_recursion)
90
+ sys.setrecursionlimit(args.py_recursion)
90
91
  except BaseException as e:
91
92
  argument_error("-r/--py-recursion", e)
92
93
 
@@ -121,7 +122,7 @@ if args.file is not None:
121
122
 
122
123
  if args.highlight:
123
124
  try:
124
- print(pys_highlight(file, FORMAT_HIGHLIGHT_MAP.get(args.highlight, None)))
125
+ print(pys_highlight(file, FORMAT_HIGHLIGHT_MAP.get(args.highlight)))
125
126
  except BaseException as e:
126
127
  parser.error(f"file {path!r}: Highlight error: {e}")
127
128
 
@@ -150,4 +151,4 @@ elif args.command is not None:
150
151
  else:
151
152
  code = pys_shell(undefined, flags)
152
153
 
153
- exit(code)
154
+ sys.exit(code)
@@ -157,23 +157,25 @@ class PysAnalyzer(Pys):
157
157
  self.visit(node.right)
158
158
 
159
159
  def visit_UnaryOperatorNode(self, node):
160
+ value = node.value
161
+
160
162
  if is_incremental(node.operand.type):
161
- type = node.value.__class__
163
+ type = value.__class__
162
164
  operator = 'increase' if node.operand.type == TOKENS['DOUBLE-PLUS'] else 'decrease'
163
165
 
164
166
  if type is PysKeywordNode:
165
- self.throw(f"cannot {operator} {node.value.token.value}", node.value.position)
167
+ self.throw(f"cannot {operator} {value.name.value}", value.position)
166
168
  return
167
169
 
168
- elif isinstance(node.value, PysNode):
170
+ elif isinstance(value, PysNode):
169
171
  if type not in (PysIdentifierNode, PysAttributeNode, PysSubscriptNode):
170
- self.throw(f"cannot {operator} literal", node.value.position)
172
+ self.throw(f"cannot {operator} literal", value.position)
171
173
  return
172
174
 
173
175
  else:
174
176
  raise TypeError("UnaryOperator: node.value is not PysNode")
175
177
 
176
- self.visit(node.value)
178
+ self.visit(value)
177
179
 
178
180
  def visit_StatementsNode(self, node):
179
181
  for element in node.body:
@@ -435,7 +437,7 @@ class PysAnalyzer(Pys):
435
437
  return
436
438
 
437
439
  elif type is PysKeywordNode:
438
- self.throw(f"cannot delete {target.token.value}", target.position)
440
+ self.throw(f"cannot delete {target.name.value}", target.position)
439
441
  return
440
442
 
441
443
  elif isinstance(target, PysNode):
@@ -502,7 +504,7 @@ class PysAnalyzer(Pys):
502
504
  return
503
505
 
504
506
  elif type is PysKeywordNode:
505
- self.throw(f"cannot assign to {node.token.value}", node.position)
507
+ self.throw(f"cannot assign to {node.name.value}", node.position)
506
508
 
507
509
  elif isinstance(node, PysNode):
508
510
  if type is not PysIdentifierNode:
@@ -21,6 +21,8 @@ class PysTraceback(Pys):
21
21
  return f'<traceback of exception {self.exception!r}>'
22
22
 
23
23
  def string_traceback(self):
24
+ from .position import format_arrow # circular import problem solved
25
+
24
26
  context = self.context
25
27
  position = self.position
26
28
 
@@ -44,7 +46,7 @@ class PysTraceback(Pys):
44
46
  '{}{}{}'.format(
45
47
  '' if is_positionless else f', line {magenta}{position.start_line}{reset}',
46
48
  '' if context_name is None else f', in {magenta}{context_name}{reset}',
47
- '' if is_positionless else f'\n{indent(position.format_arrow(colored), 4)}'
49
+ '' if is_positionless else f'\n{indent(format_arrow(position, colored), 4)}'
48
50
  )
49
51
  )
50
52
 
@@ -0,0 +1,131 @@
1
+ from .constants import TOKENS, KEYWORDS
2
+
3
+ from operator import (
4
+ is_not, eq, ne, lt, gt, le, ge, add, sub, mul, truediv, floordiv, pow, matmul, mod, and_, or_, xor, lshift, rshift,
5
+ iadd, isub, imul, itruediv, ifloordiv, ipow, imatmul, imod, iand, ior, ixor, ilshift, irshift, pos, neg, inv
6
+ )
7
+ from types import MappingProxyType
8
+
9
+ BINARY_FUNCTIONS_MAP = MappingProxyType({
10
+ TOKENS['NOT-IN']: lambda a, b : a not in b,
11
+ TOKENS['IS-NOT']: is_not,
12
+ TOKENS['PLUS']: add,
13
+ TOKENS['MINUS']: sub,
14
+ TOKENS['STAR']: mul,
15
+ TOKENS['SLASH']: truediv,
16
+ TOKENS['DOUBLE-SLASH']: floordiv,
17
+ TOKENS['DOUBLE-STAR']: pow,
18
+ TOKENS['AT']: matmul,
19
+ TOKENS['PERCENT']: mod,
20
+ TOKENS['AMPERSAND']: and_,
21
+ TOKENS['PIPE']: or_,
22
+ TOKENS['CIRCUMFLEX']: xor,
23
+ TOKENS['DOUBLE-LESS-THAN']: lshift,
24
+ TOKENS['DOUBLE-GREATER-THAN']: rshift,
25
+ TOKENS['DOUBLE-EQUAL']: eq,
26
+ TOKENS['EQUAL-EXCLAMATION']: ne,
27
+ TOKENS['LESS-THAN']: lt,
28
+ TOKENS['GREATER-THAN']: gt,
29
+ TOKENS['EQUAL-LESS-THAN']: le,
30
+ TOKENS['EQUAL-GREATER-THAN']: ge,
31
+ TOKENS['EQUAL-PLUS']: iadd,
32
+ TOKENS['EQUAL-MINUS']: isub,
33
+ TOKENS['EQUAL-STAR']: imul,
34
+ TOKENS['EQUAL-SLASH']: itruediv,
35
+ TOKENS['EQUAL-DOUBLE-SLASH']: ifloordiv,
36
+ TOKENS['EQUAL-DOUBLE-STAR']: ipow,
37
+ TOKENS['EQUAL-AT']: imatmul,
38
+ TOKENS['EQUAL-PERCENT']: imod,
39
+ TOKENS['EQUAL-AMPERSAND']: iand,
40
+ TOKENS['EQUAL-PIPE']: ior,
41
+ TOKENS['EQUAL-CIRCUMFLEX']: ixor,
42
+ TOKENS['EQUAL-DOUBLE-LESS-THAN']: ilshift,
43
+ TOKENS['EQUAL-DOUBLE-GREATER-THAN']: irshift,
44
+ })
45
+
46
+ UNARY_FUNCTIONS_MAP = MappingProxyType({
47
+ TOKENS['PLUS']: pos,
48
+ TOKENS['MINUS']: neg,
49
+ TOKENS['TILDE']: inv
50
+ })
51
+
52
+ KEYWORDS_TO_VALUES_MAP = MappingProxyType({
53
+ KEYWORDS['True']: True,
54
+ KEYWORDS['False']: False,
55
+ KEYWORDS['None']: None,
56
+ KEYWORDS['true']: True,
57
+ KEYWORDS['false']: False,
58
+ KEYWORDS['none']: None
59
+ })
60
+
61
+ BRACKETS_MAP = MappingProxyType({
62
+ TOKENS['LEFT-PARENTHESIS']: TOKENS['RIGHT-PARENTHESIS'],
63
+ TOKENS['LEFT-SQUARE']: TOKENS['RIGHT-SQUARE'],
64
+ TOKENS['LEFT-CURLY']: TOKENS['RIGHT-CURLY']
65
+ })
66
+
67
+ SYMBOLS_TOKEN_MAP = MappingProxyType({
68
+ TOKENS['NOT-IN']: KEYWORDS['not'] + ' ' + KEYWORDS['in'],
69
+ TOKENS['IS-NOT']: KEYWORDS['is'] + ' ' + KEYWORDS['not'],
70
+ TOKENS['NULL']: '\0',
71
+ TOKENS['NEWLINE']: '\n',
72
+ TOKENS['EXCLAMATION']: '!',
73
+ TOKENS['COMMENT']: '#',
74
+ TOKENS['PERCENT']: '%',
75
+ TOKENS['AMPERSAND']: '&',
76
+ TOKENS['RIGHT-PARENTHESIS']: ')',
77
+ TOKENS['LEFT-PARENTHESIS']: '(',
78
+ TOKENS['STAR']: '*',
79
+ TOKENS['PLUS']: '+',
80
+ TOKENS['COMMA']: ',',
81
+ TOKENS['MINUS']: '-',
82
+ TOKENS['DOT']: '.',
83
+ TOKENS['SLASH']: '/',
84
+ TOKENS['COLON']: ':',
85
+ TOKENS['SEMICOLON']: ';',
86
+ TOKENS['LESS-THAN']: '<',
87
+ TOKENS['EQUAL']: '=',
88
+ TOKENS['GREATER-THAN']: '>',
89
+ TOKENS['QUESTION']: '?',
90
+ TOKENS['AT']: '@',
91
+ TOKENS['LEFT-SQUARE']: '[',
92
+ TOKENS['RIGHT-SQUARE']: ']',
93
+ TOKENS['CIRCUMFLEX']: '^',
94
+ TOKENS['LEFT-CURLY']: '{',
95
+ TOKENS['PIPE']: '|',
96
+ TOKENS['RIGHT-CURLY']: '}',
97
+ TOKENS['TILDE']: '~',
98
+ TOKENS['DOUBLE-AMPERSAND']: '&&',
99
+ TOKENS['DOUBLE-STAR']: '**',
100
+ TOKENS['DOUBLE-PLUS']: '++',
101
+ TOKENS['DOUBLE-MINUS']: '--',
102
+ TOKENS['DOUBLE-SLASH']: '//',
103
+ TOKENS['DOUBLE-LESS-THAN']: '<<',
104
+ TOKENS['DOUBLE-EQUAL']: '==',
105
+ TOKENS['DOUBLE-GREATER-THAN']: '>>',
106
+ TOKENS['DOUBLE-QUESTION']: '??',
107
+ TOKENS['DOUBLE-PIPE']: '||',
108
+ TOKENS['TRIPLE-DOT']: '...',
109
+ TOKENS['EQUAL-EXCLAMATION']: '!=',
110
+ TOKENS['EQUAL-PERCENT']: '%=',
111
+ TOKENS['EQUAL-AMPERSAND']: '&=',
112
+ TOKENS['EQUAL-STAR']: '*=',
113
+ TOKENS['EQUAL-PLUS']: '+=',
114
+ TOKENS['EQUAL-MINUS']: '-=',
115
+ TOKENS['EQUAL-SLASH']: '/=',
116
+ TOKENS['EQUAL-COLON']: ':=',
117
+ TOKENS['EQUAL-LESS-THAN']: '<=',
118
+ TOKENS['EQUAL-GREATER-THAN']: '>=',
119
+ TOKENS['EQUAL-AT']: '@=',
120
+ TOKENS['EQUAL-CIRCUMFLEX']: '^=',
121
+ TOKENS['EQUAL-PIPE']: '|=',
122
+ TOKENS['EQUAL-TILDE']: '~=',
123
+ TOKENS['EQUAL-DOUBLE-STAR']: '**=',
124
+ TOKENS['EQUAL-DOUBLE-SLASH']: '//=',
125
+ TOKENS['EQUAL-DOUBLE-LESS-THAN']: '<<=',
126
+ TOKENS['EQUAL-DOUBLE-GREATER-THAN']: '>>=',
127
+ TOKENS['EQUAL-ARROW']: '=>',
128
+ TOKENS['EXCLAMATION-TILDE']: '~!'
129
+ })
130
+
131
+ EMPTY_MAP = MappingProxyType({})
@@ -19,10 +19,11 @@ class PysCode(PysObject):
19
19
  class PysPythonFunction(PysObject):
20
20
 
21
21
  def __init__(self, func):
22
- from .handlers import handle_call
22
+ from .handlers import handle_call # circular import problem solved
23
23
 
24
- self.__name__ = func.__name__
25
- self.__qualname__ = func.__qualname__
24
+ self.__name__ = getattr(func, '__name__', '<function>')
25
+ self.__qualname__ = getattr(func, '__qualname__', '<function>')
26
+ self.__doc__ = getattr(func, '__doc__', None)
26
27
  self.__func__ = func
27
28
  self.__code__ = PysCode(
28
29
  position=None,
@@ -46,7 +47,7 @@ class PysPythonFunction(PysObject):
46
47
  class PysFunction(PysObject):
47
48
 
48
49
  def __init__(self, name, qualname, parameters, body, position, context):
49
- from .interpreter import visit
50
+ from .interpreter import visit # circular import problem solved
50
51
 
51
52
  context = context.parent if isinstance(context, PysClassContext) else context
52
53
 
@@ -0,0 +1,99 @@
1
+ from .bases import Pys
2
+ from .buffer import PysFileBuffer
3
+ from .utils.ansi import BOLD, acolor
4
+ from .utils.decorators import typechecked, immutable
5
+ from .utils.generic import setimuattr
6
+
7
+ @immutable
8
+ class PysPosition(Pys):
9
+
10
+ __slots__ = ('file', 'start', 'end', 'start_line', 'start_column', 'end_line', 'end_column', 'is_positionless')
11
+
12
+ @typechecked
13
+ def __init__(self, file: PysFileBuffer, start: int, end: int) -> None:
14
+ is_positionless = start < 0 or end < 0 or start > end or end > len(file.text) + 1
15
+
16
+ setimuattr(self, 'file', file)
17
+ setimuattr(self, 'start', -1 if is_positionless else start)
18
+ setimuattr(self, 'end', -1 if is_positionless else end)
19
+ setimuattr(self, 'start_line', -1 if is_positionless else file.text.count('\n', 0, start) + 1)
20
+ setimuattr(self, 'start_column', -1 if is_positionless else start - file.text.rfind('\n', 0, start))
21
+ setimuattr(self, 'end_line', -1 if is_positionless else file.text.count('\n', 0, end) + 1)
22
+ setimuattr(self, 'end_column', -1 if is_positionless else end - file.text.rfind('\n', 0, end))
23
+ setimuattr(self, 'is_positionless', is_positionless)
24
+
25
+ def __repr__(self):
26
+ return f'<Position({self.start!r}, {self.end!r}) from {self.file.name!r}>'
27
+
28
+ def format_arrow(position, colored=True):
29
+ if position.is_positionless:
30
+ return ''
31
+
32
+ if colored:
33
+ reset = acolor('reset')
34
+ bred = acolor('red', style=BOLD)
35
+ else:
36
+ reset = ''
37
+ bred = ''
38
+
39
+ line_start = position.start_line
40
+ line_end = position.end_line
41
+ column_start = position.start_column
42
+ column_end = position.end_column
43
+
44
+ text = position.file.text
45
+
46
+ start = text.rfind('\n', 0, position.start) + 1
47
+ end = text.find('\n', start + 1)
48
+ if end == -1:
49
+ end = len(text)
50
+
51
+ if text[position.start:position.end] in ('', '\n'):
52
+ if position.start > start:
53
+ line = text[start:end].lstrip().replace('\t', ' ')
54
+ return f'{line}\n{bred}{" " * len(line)}^{reset}'
55
+ return f'\n{bred}^{reset}'
56
+
57
+ result = []
58
+ lines = []
59
+ count = line_end - line_start + 1
60
+
61
+ for i in range(count):
62
+ line = text[start:end].lstrip('\n')
63
+
64
+ lines.append(
65
+ (
66
+ line,
67
+ len(line.lstrip()),
68
+ column_start - 1 if i == 0 else 0,
69
+ column_end - 1 if i == count - 1 else len(line)
70
+ )
71
+ )
72
+
73
+ start = end
74
+ end = text.find('\n', start + 1)
75
+ if end == -1:
76
+ end = len(text)
77
+
78
+ minimum_indent = min(len(line) - line_code_length for line, line_code_length, _, _ in lines)
79
+
80
+ for i, (line, line_code_length, start, end) in enumerate(lines):
81
+ line = line[minimum_indent:]
82
+ er = end - minimum_indent
83
+
84
+ if i == 0:
85
+ sr = start - minimum_indent
86
+
87
+ arrow = '^' * (end - start)
88
+ line = f'{line[:sr]}{bred}{line[sr:er]}{reset}{line[er:]}\n{" " * sr}{bred}{arrow}{reset}'
89
+
90
+ else:
91
+ indent = len(line) - line_code_length
92
+
93
+ arrow = '^' * (end - start - (minimum_indent + indent))
94
+ line = f'{line[:indent]}{bred}{line[indent:er]}{reset}{line[er:]}\n{" " * indent}{bred}{arrow}{reset}'
95
+
96
+ if arrow:
97
+ result.append(line)
98
+
99
+ return '\n'.join(result).replace('\t', ' ')