bare-script 4.1.1__tar.gz → 4.1.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 (44) hide show
  1. {bare_script-4.1.1/src/bare_script.egg-info → bare_script-4.1.3}/PKG-INFO +1 -1
  2. {bare_script-4.1.1 → bare_script-4.1.3}/setup.cfg +1 -1
  3. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/__init__.py +2 -2
  4. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/bare.py +2 -2
  5. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/library.py +2 -2
  6. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/parser.py +179 -156
  7. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/runtime.py +36 -32
  8. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/runtime_c.c +50 -34
  9. {bare_script-4.1.1 → bare_script-4.1.3/src/bare_script.egg-info}/PKG-INFO +1 -1
  10. {bare_script-4.1.1 → bare_script-4.1.3}/LICENSE +0 -0
  11. {bare_script-4.1.1 → bare_script-4.1.3}/README.md +0 -0
  12. {bare_script-4.1.1 → bare_script-4.1.3}/pyproject.toml +0 -0
  13. {bare_script-4.1.1 → bare_script-4.1.3}/setup.py +0 -0
  14. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/__main__.py +0 -0
  15. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/__init__.py +0 -0
  16. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/args.bare +0 -0
  17. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/baredoc.bare +0 -0
  18. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/baredocCLI.bare +0 -0
  19. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/data.bare +0 -0
  20. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/dataLineChart.bare +0 -0
  21. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/dataTable.bare +0 -0
  22. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/dataUtil.bare +0 -0
  23. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/diff.bare +0 -0
  24. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/draw.bare +0 -0
  25. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/elementModel.bare +0 -0
  26. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/forms.bare +0 -0
  27. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/markdown.bare +0 -0
  28. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/markdownElements.bare +0 -0
  29. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/markdownHighlight.bare +0 -0
  30. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/markdownParser.bare +0 -0
  31. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/markdownUp.bare +0 -0
  32. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/pager.bare +0 -0
  33. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/qrcode.bare +0 -0
  34. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/schemaDoc.bare +0 -0
  35. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/unittest.bare +0 -0
  36. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/include/unittestMock.bare +0 -0
  37. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/model.py +0 -0
  38. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/options.py +0 -0
  39. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script/value.py +0 -0
  40. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script.egg-info/SOURCES.txt +0 -0
  41. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script.egg-info/dependency_links.txt +0 -0
  42. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script.egg-info/entry_points.txt +0 -0
  43. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script.egg-info/requires.txt +0 -0
  44. {bare_script-4.1.1 → bare_script-4.1.3}/src/bare_script.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bare-script
3
- Version: 4.1.1
3
+ Version: 4.1.3
4
4
  Summary: bare-script
5
5
  Home-page: https://github.com/craigahobbs/bare-script
6
6
  Author: Craig A. Hobbs
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = bare-script
3
- version = 4.1.1
3
+ version = 4.1.3
4
4
  url = https://github.com/craigahobbs/bare-script
5
5
  author = Craig A. Hobbs
6
6
  author_email = craigahobbs@gmail.com
@@ -5,7 +5,7 @@
5
5
  bare-script package
6
6
  """
7
7
 
8
- import os as _os
8
+ import os
9
9
 
10
10
  from .model import \
11
11
  lint_script, \
@@ -29,7 +29,7 @@ from .parser import \
29
29
  from .runtime import \
30
30
  BareScriptRuntimeError
31
31
 
32
- if not _os.environ.get('BARESCRIPT_RUNTIME_PY'): # pragma: no cover
32
+ if not os.environ.get('BARESCRIPT_RUNTIME_PY'): # pragma: no cover
33
33
  try:
34
34
  from .runtime_c import evaluate_expression, execute_script
35
35
  except ImportError:
@@ -7,7 +7,7 @@ bare-script command-line interface (CLI)
7
7
 
8
8
  import argparse
9
9
  from functools import partial
10
- import os as _os
10
+ import os
11
11
  import sys
12
12
  import time
13
13
 
@@ -16,7 +16,7 @@ from .options import FETCH_SYSTEM_PREFIX, fetch_read_write, fetch_system, log_st
16
16
  from .parser import parse_expression, parse_script
17
17
  from .runtime import SYSTEM_GLOBAL_INCLUDES_NAME
18
18
  from .value import value_boolean
19
- if not _os.environ.get('BARESCRIPT_RUNTIME_PY'): # pragma: no cover
19
+ if not os.environ.get('BARESCRIPT_RUNTIME_PY'): # pragma: no cover
20
20
  try:
21
21
  from .runtime_c import evaluate_expression, execute_script
22
22
  except ImportError:
@@ -11,7 +11,7 @@ import functools
11
11
  import importlib
12
12
  import json
13
13
  import math
14
- import os as _os
14
+ import os
15
15
  import random
16
16
  import re
17
17
  import urllib
@@ -28,7 +28,7 @@ from .value import R_NUMBER_CLEANUP, ValueArgsError, value_args_model, value_arg
28
28
  # Helper to dynamically import evaluate_expression to avoid the circular dependency
29
29
  def _import_evaluate_expression():
30
30
  if not _EVALUATE_EXPRESSION:
31
- if not _os.environ.get('BARESCRIPT_RUNTIME_PY'): # pragma: no cover
31
+ if not os.environ.get('BARESCRIPT_RUNTIME_PY'): # pragma: no cover
32
32
  try:
33
33
  _EVALUATE_EXPRESSION.append(importlib.import_module('bare_script.runtime_c').evaluate_expression)
34
34
  except (ImportError, AttributeError):
@@ -44,8 +44,9 @@ def parse_script(script_text, start_line_number=1, script_name=None):
44
44
  for ix_line_part, line_part in enumerate(lines):
45
45
  statements = function_def['function']['statements'] if function_def is not None else script['statements']
46
46
 
47
- # Comment?
48
- if _R_SCRIPT_COMMENT.match(line_part) is not None:
47
+ # Comment or empty line?
48
+ line_part_trimmed = line_part.lstrip()
49
+ if not line_part_trimmed or line_part_trimmed[0] == '#':
49
50
  continue
50
51
 
51
52
  # Set the line index
@@ -74,29 +75,12 @@ def parse_script(script_text, start_line_number=1, script_name=None):
74
75
  if ix_line != ix_line_part:
75
76
  statement_base['lineCount'] = (ix_line_part - ix_line) + 1
76
77
 
77
- # Assignment?
78
- match_assignment = _R_SCRIPT_ASSIGNMENT.match(line)
79
- if match_assignment:
80
- # Parse the expression
81
- try:
82
- assignment_expr = parse_expression(match_assignment.group('expr'), line_number, script_name, True)
83
- except BareScriptParserError as error:
84
- column_number = len(line) - len(match_assignment.group('expr')) + error.column_number
85
- raise BareScriptParserError(error.error, line, column_number, start_line_number + ix_line, script_name)
86
-
87
- # Add the expression statement
88
- expr_statement = {
89
- 'expr': {
90
- 'name': match_assignment.group('name'),
91
- 'expr': assignment_expr,
92
- **statement_base
93
- }
94
- }
95
- statements.append(expr_statement)
96
- continue
78
+ # Determine the line's leading keyword for dispatch
79
+ match_keyword = _R_SCRIPT_KEYWORD.match(line)
80
+ keyword = match_keyword.group(1) if match_keyword else None
97
81
 
98
82
  # Function definition begin?
99
- match_function_begin = _R_SCRIPT_FUNCTION_BEGIN.match(line)
83
+ match_function_begin = _R_SCRIPT_FUNCTION_BEGIN.match(line) if keyword in ('function', 'async') else None
100
84
  if match_function_begin:
101
85
  # Nested function definitions are not allowed
102
86
  if function_def is not None:
@@ -121,7 +105,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
121
105
  continue
122
106
 
123
107
  # Function definition end?
124
- match_function_end = _R_SCRIPT_FUNCTION_END.match(line)
108
+ match_function_end = _R_SCRIPT_FUNCTION_END.match(line) if keyword == 'endfunction' else None
125
109
  if match_function_end:
126
110
  if function_def is None:
127
111
  raise BareScriptParserError('No matching function definition', line, 1, start_line_number + ix_line, script_name)
@@ -138,7 +122,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
138
122
  continue
139
123
 
140
124
  # If-then begin?
141
- match_if_begin = _R_SCRIPT_IF_BEGIN.match(line)
125
+ match_if_begin = _R_SCRIPT_IF_BEGIN.match(line) if keyword == 'if' else None
142
126
  if match_if_begin:
143
127
  # Parse the if-then expression
144
128
  try:
@@ -167,7 +151,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
167
151
  continue
168
152
 
169
153
  # Else-if-then?
170
- match_if_else_if = _R_SCRIPT_IF_ELSE_IF.match(line)
154
+ match_if_else_if = _R_SCRIPT_IF_ELSE_IF.match(line) if keyword == 'elif' else None
171
155
  if match_if_else_if:
172
156
  # Get the else-if-then definition
173
157
  label_def_depth = function_label_def_depth if function_def is not None else 0
@@ -177,7 +161,9 @@ def parse_script(script_text, start_line_number=1, script_name=None):
177
161
 
178
162
  # Cannot come after the else-then statement
179
163
  if ifthen['hasElse']:
180
- raise BareScriptParserError('Elif statement following else statement', line, 1, start_line_number + ix_line, script_name)
164
+ raise BareScriptParserError(
165
+ 'Elif statement following else statement', line, 1, start_line_number + ix_line, script_name
166
+ )
181
167
 
182
168
  # Parse teh else-if-then expression
183
169
  try:
@@ -204,7 +190,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
204
190
  continue
205
191
 
206
192
  # Else-then?
207
- match_if_else = _R_SCRIPT_IF_ELSE.match(line)
193
+ match_if_else = _R_SCRIPT_IF_ELSE.match(line) if keyword == 'else' else None
208
194
  if match_if_else:
209
195
  # Get the if-then definition
210
196
  label_def_depth = function_label_def_depth if function_def is not None else 0
@@ -225,7 +211,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
225
211
  continue
226
212
 
227
213
  # If-then end?
228
- match_if_end = _R_SCRIPT_IF_END.match(line)
214
+ match_if_end = _R_SCRIPT_IF_END.match(line) if keyword == 'endif' else None
229
215
  if match_if_end:
230
216
  # Pop the if-then definition
231
217
  label_def_depth = function_label_def_depth if function_def is not None else 0
@@ -242,7 +228,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
242
228
  continue
243
229
 
244
230
  # While-do begin?
245
- match_while_begin = _R_SCRIPT_WHILE_BEGIN.match(line)
231
+ match_while_begin = _R_SCRIPT_WHILE_BEGIN.match(line) if keyword == 'while' else None
246
232
  if match_while_begin:
247
233
  # Parse the while-do expression
248
234
  try:
@@ -271,7 +257,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
271
257
  continue
272
258
 
273
259
  # While-do end?
274
- match_while_end = _R_SCRIPT_WHILE_END.match(line)
260
+ match_while_end = _R_SCRIPT_WHILE_END.match(line) if keyword == 'endwhile' else None
275
261
  if match_while_end:
276
262
  # Pop the while-do definition
277
263
  label_def_depth = function_label_def_depth if function_def is not None else 0
@@ -290,7 +276,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
290
276
  continue
291
277
 
292
278
  # For-each begin?
293
- match_for_begin = _R_SCRIPT_FOR_BEGIN.match(line)
279
+ match_for_begin = _R_SCRIPT_FOR_BEGIN.match(line) if keyword == 'for' else None
294
280
  if match_for_begin:
295
281
  # Add the for-each label
296
282
  foreach = {
@@ -335,14 +321,19 @@ def parse_script(script_text, start_line_number=1, script_name=None):
335
321
  {'label': {'name': foreach['loop'], **statement_base}},
336
322
  {'expr': {
337
323
  'name': foreach['value'],
338
- 'expr': {'function': {'name': 'arrayGet', 'args': [{'variable': foreach['values']}, {'variable': foreach['index']}]}},
324
+ 'expr': {
325
+ 'function': {
326
+ 'name': 'arrayGet',
327
+ 'args': [{'variable': foreach['values']}, {'variable': foreach['index']}]
328
+ }
329
+ },
339
330
  **statement_base
340
331
  }}
341
332
  ])
342
333
  continue
343
334
 
344
335
  # For-each end?
345
- match_for_end = _R_SCRIPT_FOR_END.match(line)
336
+ match_for_end = _R_SCRIPT_FOR_END.match(line) if keyword == 'endfor' else None
346
337
  if match_for_end:
347
338
  # Pop the foreach definition
348
339
  label_def_depth = function_label_def_depth if function_def is not None else 0
@@ -364,7 +355,9 @@ def parse_script(script_text, start_line_number=1, script_name=None):
364
355
  }},
365
356
  {'jump': {
366
357
  'label': foreach['loop'],
367
- 'expr': {'binary': {'op': '<', 'left': {'variable': foreach['index']}, 'right': {'variable': foreach['length']}}},
358
+ 'expr': {
359
+ 'binary': {'op': '<', 'left': {'variable': foreach['index']}, 'right': {'variable': foreach['length']}}
360
+ },
368
361
  **statement_base
369
362
  }},
370
363
  {'label': {'name': foreach['done'], **statement_base}}
@@ -372,7 +365,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
372
365
  continue
373
366
 
374
367
  # Break statement?
375
- match_break = _R_SCRIPT_BREAK.match(line)
368
+ match_break = _R_SCRIPT_BREAK.match(line) if keyword == 'break' else None
376
369
  if match_break:
377
370
  # Get the loop definition
378
371
  label_def_depth = function_label_def_depth if function_def is not None else 0
@@ -388,13 +381,15 @@ def parse_script(script_text, start_line_number=1, script_name=None):
388
381
  continue
389
382
 
390
383
  # Continue statement?
391
- match_continue = _R_SCRIPT_CONTINUE.match(line)
384
+ match_continue = _R_SCRIPT_CONTINUE.match(line) if keyword == 'continue' else None
392
385
  if match_continue:
393
386
  # Get the loop definition
394
387
  label_def_depth = function_label_def_depth if function_def is not None else 0
395
388
  ix_label_def = next((i for i, d in reversed(list(enumerate(label_defs))) if 'if' not in d), -1)
396
389
  if ix_label_def < label_def_depth:
397
- raise BareScriptParserError('Continue statement outside of loop', line, 1, start_line_number + ix_line, script_name)
390
+ raise BareScriptParserError(
391
+ 'Continue statement outside of loop', line, 1, start_line_number + ix_line, script_name
392
+ )
398
393
  label_def = label_defs[ix_label_def]
399
394
  label_key = next(iter(label_def))
400
395
  loop_def = label_def[label_key]
@@ -404,14 +399,8 @@ def parse_script(script_text, start_line_number=1, script_name=None):
404
399
  statements.append({'jump': {'label': loop_def['continue'], **statement_base}})
405
400
  continue
406
401
 
407
- # Label definition?
408
- match_label = _R_SCRIPT_LABEL.match(line)
409
- if match_label:
410
- statements.append({'label': {'name': match_label.group('name'), **statement_base}})
411
- continue
412
-
413
402
  # Jump definition?
414
- match_jump = _R_SCRIPT_JUMP.match(line)
403
+ match_jump = _R_SCRIPT_JUMP.match(line) if keyword in ('jump', 'jumpif') else None
415
404
  if match_jump:
416
405
  jump_statement = {'jump': {'label': match_jump.group('name'), **statement_base}}
417
406
  if match_jump.group('expr'):
@@ -424,12 +413,14 @@ def parse_script(script_text, start_line_number=1, script_name=None):
424
413
  continue
425
414
 
426
415
  # Return definition?
427
- match_return = _R_SCRIPT_RETURN.match(line)
416
+ match_return = _R_SCRIPT_RETURN.match(line) if keyword == 'return' else None
428
417
  if match_return:
429
418
  return_statement = {'return': {**statement_base}}
430
419
  if match_return.group('expr'):
431
420
  try:
432
- return_statement['return']['expr'] = parse_expression(match_return.group('expr'), line_number, script_name, True)
421
+ return_statement['return']['expr'] = parse_expression(
422
+ match_return.group('expr'), line_number, script_name, True
423
+ )
433
424
  except BareScriptParserError as error:
434
425
  column_number = len(match_return.group('return')) - len(match_return.group('expr')) + error.column_number
435
426
  raise BareScriptParserError(error.error, line, column_number, start_line_number + ix_line, script_name)
@@ -437,7 +428,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
437
428
  continue
438
429
 
439
430
  # Include definition?
440
- match_include = _R_SCRIPT_INCLUDE.match(line) or _R_SCRIPT_INCLUDE_SYSTEM.match(line)
431
+ match_include = _R_SCRIPT_INCLUDE.match(line) or _R_SCRIPT_INCLUDE_SYSTEM.match(line) if keyword == 'include' else None
441
432
  if match_include:
442
433
  delim = match_include.group('delim')
443
434
  url = match_include.group('url') if delim == '<' else \
@@ -451,6 +442,35 @@ def parse_script(script_text, start_line_number=1, script_name=None):
451
442
  include_statement['include']['includes'].append({'url': url, 'system': True} if delim == '<' else {'url': url})
452
443
  continue
453
444
 
445
+ # Catch-all (line starts with an identifier but isn't a recognized control statement)
446
+ if keyword is not None:
447
+ # Assignment?
448
+ match_assignment = _R_SCRIPT_ASSIGNMENT.match(line)
449
+ if match_assignment:
450
+ # Parse the expression
451
+ try:
452
+ assignment_expr = parse_expression(match_assignment.group('expr'), line_number, script_name, True)
453
+ except BareScriptParserError as error:
454
+ column_number = len(line) - len(match_assignment.group('expr')) + error.column_number
455
+ raise BareScriptParserError(error.error, line, column_number, start_line_number + ix_line, script_name)
456
+
457
+ # Add the expression statement
458
+ expr_statement = {
459
+ 'expr': {
460
+ 'name': match_assignment.group('name'),
461
+ 'expr': assignment_expr,
462
+ **statement_base
463
+ }
464
+ }
465
+ statements.append(expr_statement)
466
+ continue
467
+
468
+ # Label definition?
469
+ match_label = _R_SCRIPT_LABEL.match(line)
470
+ if match_label:
471
+ statements.append({'label': {'name': match_label.group('name'), **statement_base}})
472
+ continue
473
+
454
474
  # Expression
455
475
  try:
456
476
  expr_statement = {'expr': {'expr': parse_expression(line, line_number, script_name, True), **statement_base}}
@@ -471,7 +491,7 @@ def parse_script(script_text, start_line_number=1, script_name=None):
471
491
  # BareScript regex
472
492
  _R_SCRIPT_LINE_SPLIT = re.compile(r'\r?\n')
473
493
  _R_SCRIPT_CONTINUATION = re.compile(r'\\\s*$')
474
- _R_SCRIPT_COMMENT = re.compile(r'^\s*(?:#.*)?$')
494
+ _R_SCRIPT_KEYWORD = re.compile(r'^\s*([A-Za-z_]\w*)')
475
495
  _R_SCRIPT_ASSIGNMENT = re.compile(r'^\s*(?P<name>[A-Za-z_]\w*)\s*=\s*(?P<expr>.+)$')
476
496
  _R_PART_COMMENT = r'\s*(#.*)?$'
477
497
  _R_SCRIPT_FUNCTION_BEGIN = re.compile(
@@ -516,7 +536,7 @@ def parse_expression(expr_text, line_number=None, script_name=None, array_litera
516
536
  :raises BareScriptParserError: A parsing error occurred
517
537
  """
518
538
  try:
519
- expr, next_text = _parse_binary_expression(expr_text, None, array_literals)
539
+ expr, next_text = _parse_binary_expression(expr_text, array_literals)
520
540
  if next_text.strip() != '':
521
541
  raise BareScriptParserError('Syntax error', next_text, 1, line_number, script_name)
522
542
  return expr
@@ -526,42 +546,47 @@ def parse_expression(expr_text, line_number=None, script_name=None, array_litera
526
546
 
527
547
 
528
548
  # Helper function to parse a binary operator expression chain
529
- def _parse_binary_expression(expr_text, bin_left_expr, array_literals):
530
- # Parse the binary operator's left unary expression if none was passed
531
- if bin_left_expr is not None:
532
- bin_text = expr_text
533
- left_expr = bin_left_expr
534
- else:
535
- left_expr, bin_text = _parse_unary_expression(expr_text, array_literals)
536
-
537
- # Match a binary operator - if not found, return the left expression
538
- match_binary_op = _R_EXPR_BINARY_OP.match(bin_text)
539
- if match_binary_op is None:
540
- # End-of-line comment?
541
- if _R_EXPR_COMMENT.match(bin_text):
542
- bin_text = ''
543
-
544
- return [left_expr, bin_text]
545
- bin_op = match_binary_op.group(1)
546
- right_text = bin_text[len(match_binary_op.group(0)):]
547
-
548
- # Parse the right sub-expression
549
- right_expr, next_text = _parse_unary_expression(right_text, array_literals)
550
-
551
- # Create the binary expression - re-order for binary operators as necessary
552
- bin_expr = None
553
- if 'binary' in left_expr and bin_op in BINARY_REORDER and left_expr['binary']['op'] in BINARY_REORDER[bin_op]:
554
- # Left expression has lower precedence - find where to put this expression within the left expression
555
- bin_expr = left_expr
556
- reorder_expr = left_expr
557
- while 'binary' in reorder_expr['binary']['right'] and reorder_expr['binary']['right']['binary']['op'] in BINARY_REORDER[bin_op]:
558
- reorder_expr = reorder_expr['binary']['right']
559
- reorder_expr['binary']['right'] = {'binary': {'op': bin_op, 'left': reorder_expr['binary']['right'], 'right': right_expr}}
560
- else:
561
- bin_expr = {'binary': {'op': bin_op, 'left': left_expr, 'right': right_expr}}
549
+ def _parse_binary_expression(expr_text, array_literals):
550
+ # Parse the binary operator's left unary expression
551
+ left_expr, bin_text = _parse_unary_expression(expr_text, array_literals)
552
+
553
+ # Consume binary operators while present, building up the binary expression tree
554
+ while True:
555
+ # Skip leading whitespace to find the first dispatch char
556
+ pos = 0
557
+ n = len(bin_text)
558
+ while pos < n and bin_text[pos] in ' \t\r\n\v\f':
559
+ pos += 1
560
+
561
+ # End of binary expression (empty, whitespace-only, or end-of-line comment)?
562
+ if pos >= n or bin_text[pos] == '#':
563
+ return [left_expr, '']
564
+
565
+ # Binary operator? First char must be one of "!%&*+-/<=>^|"
566
+ is_binary_op_start = bin_text[pos] in '!%&*+-/<=>^|'
567
+ match_binary_op = _R_EXPR_BINARY_OP.match(bin_text) if is_binary_op_start else None
568
+ if match_binary_op is None:
569
+ return [left_expr, bin_text]
570
+ bin_op = match_binary_op.group(1)
571
+ right_text = bin_text[len(match_binary_op.group(0)):]
572
+
573
+ # Parse the right sub-expression
574
+ right_expr, next_text = _parse_unary_expression(right_text, array_literals)
575
+
576
+ # Create the binary expression - re-order for binary operators as necessary
577
+ if 'binary' in left_expr and bin_op in BINARY_REORDER and left_expr['binary']['op'] in BINARY_REORDER[bin_op]:
578
+ # Left expression has lower precedence - find where to put this expression within the left expression
579
+ reorder_expr = left_expr
580
+ while ('binary' in reorder_expr['binary']['right']
581
+ and reorder_expr['binary']['right']['binary']['op'] in BINARY_REORDER[bin_op]):
582
+ reorder_expr = reorder_expr['binary']['right']
583
+ reorder_expr['binary']['right'] = {
584
+ 'binary': {'op': bin_op, 'left': reorder_expr['binary']['right'], 'right': right_expr}
585
+ }
586
+ else:
587
+ left_expr = {'binary': {'op': bin_op, 'left': left_expr, 'right': right_expr}}
562
588
 
563
- # Parse the next binary expression in the chain
564
- return _parse_binary_expression(next_text, bin_expr, array_literals)
589
+ bin_text = next_text
565
590
 
566
591
 
567
592
  # Binary operator re-order map
@@ -590,48 +615,54 @@ BINARY_REORDER = {
590
615
 
591
616
  # Helper function to parse a unary expression
592
617
  def _parse_unary_expression(expr_text, array_literals):
593
- # Group open?
594
- match_group_open = _R_EXPR_GROUP_OPEN.match(expr_text)
618
+ # Skip leading whitespace to find the first dispatch char
619
+ pos = 0
620
+ n = len(expr_text)
621
+ while pos < n and expr_text[pos] in ' \t\r\n\v\f':
622
+ pos += 1
623
+ if pos >= n:
624
+ raise BareScriptParserError('Syntax error', expr_text, 1, None, None)
625
+ c = expr_text[pos]
626
+
627
+ # Group? '('
628
+ match_group_open = _R_EXPR_GROUP_OPEN.match(expr_text) if c == '(' else None
595
629
  if match_group_open:
596
630
  group_text = expr_text[len(match_group_open.group(0)):]
597
- expr, next_text = _parse_binary_expression(group_text, None, array_literals)
631
+ expr, next_text = _parse_binary_expression(group_text, array_literals)
598
632
  match_group_close = _R_EXPR_GROUP_CLOSE.match(next_text)
599
633
  if match_group_close is None:
600
634
  raise BareScriptParserError('Unmatched parenthesis', expr_text, 1, None, None)
601
635
  return [{'group': expr}, next_text[len(match_group_close.group(0)):]]
602
636
 
603
- # Number?
604
- match_number = _R_EXPR_NUMBER.match(expr_text)
637
+ # Number? digit, '+', or '-' (the '-' falls through to unary below if no number matches)
638
+ match_number = _R_EXPR_NUMBER.match(expr_text) if c.isdigit() or c in '+-' else None
605
639
  if match_number:
606
640
  number_str = match_number.group(1)
607
641
  number = float(int(number_str, base=16)) if number_str.startswith('0x') else float(number_str)
608
- expr = {'number': number}
609
- return [expr, expr_text[len(match_number.group(0)):]]
642
+ return [{'number': number}, expr_text[len(match_number.group(0)):]]
610
643
 
611
- # String?
612
- match_string = _R_EXPR_STRING.match(expr_text)
644
+ # String? '\''
645
+ match_string = _R_EXPR_STRING.match(expr_text) if c == "'" else None
613
646
  if match_string:
614
647
  string = _R_EXPR_STRING_ESCAPES.sub(_replace_string_escape, match_string.group(1))
615
- expr = {'string': string}
616
- return [expr, expr_text[len(match_string.group(0)):]]
648
+ return [{'string': string}, expr_text[len(match_string.group(0)):]]
617
649
 
618
- # String (double quotes)?
619
- match_string_double = _R_EXPR_STRING_DOUBLE.match(expr_text)
650
+ # String (double quotes)? '"'
651
+ match_string_double = _R_EXPR_STRING_DOUBLE.match(expr_text) if c == '"' else None
620
652
  if match_string_double:
621
653
  string = _R_EXPR_STRING_ESCAPES.sub(_replace_string_escape, match_string_double.group(1))
622
- expr = {'string': string}
623
- return [expr, expr_text[len(match_string_double.group(0)):]]
654
+ return [{'string': string}, expr_text[len(match_string_double.group(0)):]]
624
655
 
625
- # Unary operator?
626
- match_unary = _R_EXPR_UNARY_OP.match(expr_text)
656
+ # Unary operator? '!', '-', '~'
657
+ match_unary = _R_EXPR_UNARY_OP.match(expr_text) if c in '!-~' else None
627
658
  if match_unary:
628
659
  unary_text = expr_text[len(match_unary.group(0)):]
629
660
  expr, next_text = _parse_unary_expression(unary_text, array_literals)
630
- unary_expr = {'unary': {'op': match_unary.group(1), 'expr': expr}}
631
- return [unary_expr, next_text]
661
+ return [{'unary': {'op': match_unary.group(1), 'expr': expr}}, next_text]
632
662
 
633
- # Function?
634
- match_function_open = _R_EXPR_FUNCTION_OPEN.match(expr_text)
663
+ # Function call? identifier followed by '('
664
+ is_ident = c.isalpha() or c == '_'
665
+ match_function_open = _R_EXPR_FUNCTION_OPEN.match(expr_text) if is_ident else None
635
666
  if match_function_open:
636
667
  arg_text = expr_text[len(match_function_open.group(0)):]
637
668
  args = []
@@ -650,15 +681,19 @@ def _parse_unary_expression(expr_text, array_literals):
650
681
  arg_text = arg_text[len(match_function_separator.group(0)):]
651
682
 
652
683
  # Get the argument
653
- arg_expr, next_arg_text = _parse_binary_expression(arg_text, None, array_literals)
684
+ arg_expr, next_arg_text = _parse_binary_expression(arg_text, array_literals)
654
685
  args.append(arg_expr)
655
686
  arg_text = next_arg_text
656
687
 
657
- fn_expr = {'function': {'name': match_function_open.group(1), 'args': args}}
658
- return [fn_expr, arg_text]
688
+ return [{'function': {'name': match_function_open.group(1), 'args': args}}, arg_text]
659
689
 
660
- # Object creation?
661
- match_object_open = _R_EXPR_OBJECT_OPEN.match(expr_text)
690
+ # Variable
691
+ match_variable = _R_EXPR_VARIABLE.match(expr_text) if is_ident else None
692
+ if match_variable:
693
+ return [{'variable': match_variable.group(1)}, expr_text[len(match_variable.group(0)):]]
694
+
695
+ # Object creation? '{'
696
+ match_object_open = _R_EXPR_OBJECT_OPEN.match(expr_text) if c == '{' else None
662
697
  if match_object_open:
663
698
  arg_text = expr_text[len(match_object_open.group(0)):]
664
699
  args = []
@@ -677,7 +712,7 @@ def _parse_unary_expression(expr_text, array_literals):
677
712
  arg_text = arg_text[len(match_object_separator.group(0)):]
678
713
 
679
714
  # Get the key
680
- arg_key, arg_text = _parse_binary_expression(arg_text, None, array_literals)
715
+ arg_key, arg_text = _parse_binary_expression(arg_text, array_literals)
681
716
  args.append(arg_key)
682
717
 
683
718
  # Key/value separator
@@ -687,58 +722,46 @@ def _parse_unary_expression(expr_text, array_literals):
687
722
  arg_text = arg_text[len(match_object_separator_key.group(0)):]
688
723
 
689
724
  # Get the value
690
- arg_value, arg_text = _parse_binary_expression(arg_text, None, array_literals)
725
+ arg_value, arg_text = _parse_binary_expression(arg_text, array_literals)
691
726
  args.append(arg_value)
692
727
 
693
- fn_expr = {'function': {'name': 'objectNew', 'args': args}}
694
- return [fn_expr, arg_text]
695
-
696
- # Array creation?
697
- if array_literals:
698
- match_array_open = _R_EXPR_ARRAY_OPEN.match(expr_text)
699
- if match_array_open:
700
- arg_text = expr_text[len(match_array_open.group(0)):]
701
- args = []
702
- while True:
703
- # Array close?
704
- match_array_close = _R_EXPR_ARRAY_CLOSE.match(arg_text)
705
- if match_array_close:
706
- arg_text = arg_text[len(match_array_close.group(0)):]
707
- break
708
-
709
- # Array key separator
710
- if args:
711
- match_array_separator = _R_EXPR_ARRAY_SEPARATOR.match(arg_text)
712
- if match_array_separator is None:
713
- raise BareScriptParserError('Syntax error', arg_text, 1, None, None)
714
- arg_text = arg_text[len(match_array_separator.group(0)):]
715
-
716
- # Get the value
717
- arg_value, arg_text = _parse_binary_expression(arg_text, None, array_literals)
718
- args.append(arg_value)
719
-
720
- fn_expr = {'function': {'name': 'arrayNew', 'args': args}}
721
- return [fn_expr, arg_text]
722
-
723
- # Variable?
724
- match_variable = _R_EXPR_VARIABLE.match(expr_text)
725
- if match_variable:
726
- expr = {'variable': match_variable.group(1)}
727
- return [expr, expr_text[len(match_variable.group(0)):]]
728
+ return [{'function': {'name': 'objectNew', 'args': args}}, arg_text]
729
+
730
+ # Array creation? '['
731
+ match_array_open = _R_EXPR_ARRAY_OPEN.match(expr_text) if c == '[' and array_literals else None
732
+ if match_array_open:
733
+ arg_text = expr_text[len(match_array_open.group(0)):]
734
+ args = []
735
+ while True:
736
+ # Array close?
737
+ match_array_close = _R_EXPR_ARRAY_CLOSE.match(arg_text)
738
+ if match_array_close:
739
+ arg_text = arg_text[len(match_array_close.group(0)):]
740
+ break
741
+
742
+ # Array key separator
743
+ if args:
744
+ match_array_separator = _R_EXPR_ARRAY_SEPARATOR.match(arg_text)
745
+ if match_array_separator is None:
746
+ raise BareScriptParserError('Syntax error', arg_text, 1, None, None)
747
+ arg_text = arg_text[len(match_array_separator.group(0)):]
748
+
749
+ # Get the value
750
+ arg_value, arg_text = _parse_binary_expression(arg_text, array_literals)
751
+ args.append(arg_value)
752
+
753
+ return [{'function': {'name': 'arrayNew', 'args': args}}, arg_text]
728
754
 
729
- # Variable (brackets)?
730
- if not array_literals:
731
- match_variable_ex = _R_EXPR_VARIABLE_EX.match(expr_text)
732
- if match_variable_ex:
733
- variable_name = _R_EXPR_VARIABLE_EX_ESCAPE.sub('\\1', match_variable_ex.group(1))
734
- expr = {'variable': variable_name}
735
- return [expr, expr_text[len(match_variable_ex.group(0)):]]
755
+ # Variable (brackets)? '['
756
+ match_variable_ex = _R_EXPR_VARIABLE_EX.match(expr_text) if c == '[' and not array_literals else None
757
+ if match_variable_ex:
758
+ variable_name = _R_EXPR_VARIABLE_EX_ESCAPE.sub('\\1', match_variable_ex.group(1))
759
+ return [{'variable': variable_name}, expr_text[len(match_variable_ex.group(0)):]]
736
760
 
737
761
  raise BareScriptParserError('Syntax error', expr_text, 1, None, None)
738
762
 
739
763
 
740
764
  # BareScript expression regex
741
- _R_EXPR_COMMENT = re.compile(r'^\s*#.*$')
742
765
  _R_EXPR_BINARY_OP = re.compile(r'^\s*(\*\*|\*|\/|%|\+|-|<<|>>|<=|<|>=|>|==|!=|&&|\|\||&|\^|\|)')
743
766
  _R_EXPR_UNARY_OP = re.compile(r'^\s*(!|-|~)')
744
767
  _R_EXPR_FUNCTION_OPEN = re.compile(r'^\s*([A-Za-z_]\w+)\s*\(')
@@ -224,13 +224,17 @@ def _script_function(script, function, args, options):
224
224
  if func_args is not None:
225
225
  args_length = len(args)
226
226
  func_args_length = len(func_args)
227
- ix_arg_last = function.get('lastArgArray', None) and (func_args_length - 1)
228
- for ix_arg in range(func_args_length):
229
- arg_name = func_args[ix_arg]
230
- if ix_arg < args_length:
231
- func_locals[arg_name] = args[ix_arg] if ix_arg != ix_arg_last else args[ix_arg:]
232
- else:
233
- func_locals[arg_name] = [] if ix_arg == ix_arg_last else None
227
+ if function.get('lastArgArray'):
228
+ ix_arg_last = func_args_length - 1
229
+ for ix_arg in range(func_args_length):
230
+ arg_name = func_args[ix_arg]
231
+ if ix_arg < args_length:
232
+ func_locals[arg_name] = args[ix_arg] if ix_arg != ix_arg_last else args[ix_arg:]
233
+ else:
234
+ func_locals[arg_name] = [] if ix_arg == ix_arg_last else None
235
+ else:
236
+ for ix_arg in range(func_args_length):
237
+ func_locals[func_args[ix_arg]] = args[ix_arg] if ix_arg < args_length else None
234
238
  return _execute_script_helper(script, function['statements'], options, func_locals)
235
239
 
236
240
 
@@ -399,35 +403,35 @@ def evaluate_expression(expr, options=None, locals_=None, builtins=True, script=
399
403
  (right_type is int or right_type is float)):
400
404
  return left_value / right_value
401
405
 
402
- elif bin_op == '==':
403
- if (left_type is int or left_type is float) and (right_type is int or right_type is float):
404
- return left_value == right_value
405
- return value_compare(left_value, right_value) == 0
406
-
407
- elif bin_op == '!=':
406
+ elif bin_op == '<':
408
407
  if (left_type is int or left_type is float) and (right_type is int or right_type is float):
409
- return left_value != right_value
410
- return value_compare(left_value, right_value) != 0
408
+ return left_value < right_value
409
+ return value_compare(left_value, right_value) < 0
411
410
 
412
411
  elif bin_op == '<=':
413
412
  if (left_type is int or left_type is float) and (right_type is int or right_type is float):
414
413
  return left_value <= right_value
415
414
  return value_compare(left_value, right_value) <= 0
416
415
 
417
- elif bin_op == '<':
416
+ elif bin_op == '>':
418
417
  if (left_type is int or left_type is float) and (right_type is int or right_type is float):
419
- return left_value < right_value
420
- return value_compare(left_value, right_value) < 0
418
+ return left_value > right_value
419
+ return value_compare(left_value, right_value) > 0
421
420
 
422
421
  elif bin_op == '>=':
423
422
  if (left_type is int or left_type is float) and (right_type is int or right_type is float):
424
423
  return left_value >= right_value
425
424
  return value_compare(left_value, right_value) >= 0
426
425
 
427
- elif bin_op == '>':
426
+ elif bin_op == '==':
428
427
  if (left_type is int or left_type is float) and (right_type is int or right_type is float):
429
- return left_value > right_value
430
- return value_compare(left_value, right_value) > 0
428
+ return left_value == right_value
429
+ return value_compare(left_value, right_value) == 0
430
+
431
+ elif bin_op == '!=':
432
+ if (left_type is int or left_type is float) and (right_type is int or right_type is float):
433
+ return left_value != right_value
434
+ return value_compare(left_value, right_value) != 0
431
435
 
432
436
  elif bin_op == '%':
433
437
  # number % number
@@ -443,32 +447,32 @@ def evaluate_expression(expr, options=None, locals_=None, builtins=True, script=
443
447
 
444
448
  elif bin_op == '&':
445
449
  # int & int
446
- if ((left_type is int or left_type is float) and int(left_value) == left_value and
447
- (right_type is int or right_type is float) and int(right_value) == right_value):
450
+ if ((left_type is int or (left_type is float and left_value.is_integer())) and
451
+ (right_type is int or (right_type is float and right_value.is_integer()))):
448
452
  return int(left_value) & int(right_value)
449
453
 
450
454
  elif bin_op == '|':
451
455
  # int & int
452
- if ((left_type is int or left_type is float) and int(left_value) == left_value and
453
- (right_type is int or right_type is float) and int(right_value) == right_value):
456
+ if ((left_type is int or (left_type is float and left_value.is_integer())) and
457
+ (right_type is int or (right_type is float and right_value.is_integer()))):
454
458
  return int(left_value) | int(right_value)
455
459
 
456
460
  elif bin_op == '^':
457
461
  # int & int
458
- if ((left_type is int or left_type is float) and int(left_value) == left_value and
459
- (right_type is int or right_type is float) and int(right_value) == right_value):
462
+ if ((left_type is int or (left_type is float and left_value.is_integer())) and
463
+ (right_type is int or (right_type is float and right_value.is_integer()))):
460
464
  return int(left_value) ^ int(right_value)
461
465
 
462
466
  elif bin_op == '<<':
463
467
  # int & int
464
- if ((left_type is int or left_type is float) and int(left_value) == left_value and
465
- (right_type is int or right_type is float) and int(right_value) == right_value):
468
+ if ((left_type is int or (left_type is float and left_value.is_integer())) and
469
+ (right_type is int or (right_type is float and right_value.is_integer()))):
466
470
  return int(left_value) << int(right_value)
467
471
 
468
472
  else: # bin_op == '>>':
469
473
  # int & int
470
- if ((left_type is int or left_type is float) and int(left_value) == left_value and
471
- (right_type is int or right_type is float) and int(right_value) == right_value):
474
+ if ((left_type is int or (left_type is float and left_value.is_integer())) and
475
+ (right_type is int or (right_type is float and right_value.is_integer()))):
472
476
  return int(left_value) >> int(right_value)
473
477
 
474
478
  # Invalid operation values
@@ -486,7 +490,7 @@ def evaluate_expression(expr, options=None, locals_=None, builtins=True, script=
486
490
  if val_type is int or val_type is float:
487
491
  return -value
488
492
  else: # unary_op == '~':
489
- if (val_type is int or val_type is float) and int(value) == value:
493
+ if val_type is int or (val_type is float and value.is_integer()):
490
494
  return ~int(value)
491
495
 
492
496
  # Invalid operation value
@@ -400,42 +400,58 @@ script_function_call(PyObject *script, PyObject *function, PyObject *args, PyObj
400
400
 
401
401
  PyObject *last_arg_array = dict_getitem_borrow(function, K_lastArgArray);
402
402
  if (PyErr_Occurred()) { Py_DECREF(func_locals); return NULL; }
403
- Py_ssize_t ix_arg_last = -1;
404
- if (last_arg_array != NULL && PyObject_IsTrue(last_arg_array) == 1) {
405
- ix_arg_last = func_args_length - 1;
406
- }
407
-
408
- for (Py_ssize_t ix = 0; ix < func_args_length; ix++) {
409
- PyObject *arg_name = PyList_GET_ITEM(func_args, ix);
410
- PyObject *val = NULL;
411
- int needs_decref = 0;
412
- if (ix < args_length) {
413
- if (ix == ix_arg_last) {
414
- /* args[ix:] */
415
- if (PyList_Check(args)) {
416
- val = PyList_GetSlice(args, ix, args_length);
403
+ int has_last_arg_array = (last_arg_array != NULL && PyObject_IsTrue(last_arg_array) == 1);
404
+
405
+ if (has_last_arg_array) {
406
+ Py_ssize_t ix_arg_last = func_args_length - 1;
407
+ for (Py_ssize_t ix = 0; ix < func_args_length; ix++) {
408
+ PyObject *arg_name = PyList_GET_ITEM(func_args, ix);
409
+ PyObject *val = NULL;
410
+ int needs_decref = 0;
411
+ if (ix < args_length) {
412
+ if (ix == ix_arg_last) {
413
+ /* args[ix:] */
414
+ if (PyList_Check(args)) {
415
+ val = PyList_GetSlice(args, ix, args_length);
416
+ } else {
417
+ val = PySequence_GetSlice(args, ix, args_length);
418
+ }
419
+ if (!val) { Py_DECREF(func_locals); return NULL; }
420
+ needs_decref = 1;
417
421
  } else {
418
- val = PySequence_GetSlice(args, ix, args_length);
422
+ val = PySequence_GetItem(args, ix);
423
+ if (!val) { Py_DECREF(func_locals); return NULL; }
424
+ needs_decref = 1;
419
425
  }
420
- if (!val) { Py_DECREF(func_locals); return NULL; }
421
- needs_decref = 1;
422
426
  } else {
423
- val = PySequence_GetItem(args, ix);
424
- if (!val) { Py_DECREF(func_locals); return NULL; }
425
- needs_decref = 1;
427
+ if (ix == ix_arg_last) {
428
+ val = PyList_New(0);
429
+ if (!val) { Py_DECREF(func_locals); return NULL; }
430
+ needs_decref = 1;
431
+ } else {
432
+ val = Py_None;
433
+ }
426
434
  }
427
- } else {
428
- if (ix == ix_arg_last) {
429
- val = PyList_New(0);
435
+ int rc = PyDict_SetItem(func_locals, arg_name, val);
436
+ if (needs_decref) Py_DECREF(val);
437
+ if (rc < 0) { Py_DECREF(func_locals); return NULL; }
438
+ }
439
+ } else {
440
+ for (Py_ssize_t ix = 0; ix < func_args_length; ix++) {
441
+ PyObject *arg_name = PyList_GET_ITEM(func_args, ix);
442
+ PyObject *val;
443
+ int needs_decref = 0;
444
+ if (ix < args_length) {
445
+ val = PySequence_GetItem(args, ix);
430
446
  if (!val) { Py_DECREF(func_locals); return NULL; }
431
447
  needs_decref = 1;
432
448
  } else {
433
449
  val = Py_None;
434
450
  }
451
+ int rc = PyDict_SetItem(func_locals, arg_name, val);
452
+ if (needs_decref) Py_DECREF(val);
453
+ if (rc < 0) { Py_DECREF(func_locals); return NULL; }
435
454
  }
436
- int rc = PyDict_SetItem(func_locals, arg_name, val);
437
- if (needs_decref) Py_DECREF(val);
438
- if (rc < 0) { Py_DECREF(func_locals); return NULL; }
439
455
  }
440
456
  }
441
457
 
@@ -588,12 +604,12 @@ op_to_id(PyObject *op)
588
604
  if (op == K_op_minus) return OP_MINUS;
589
605
  if (op == K_op_star) return OP_STAR;
590
606
  if (op == K_op_slash) return OP_SLASH;
591
- if (op == K_op_eq) return OP_EQ;
592
- if (op == K_op_ne) return OP_NE;
593
- if (op == K_op_le) return OP_LE;
594
607
  if (op == K_op_lt) return OP_LT;
595
- if (op == K_op_ge) return OP_GE;
608
+ if (op == K_op_le) return OP_LE;
596
609
  if (op == K_op_gt) return OP_GT;
610
+ if (op == K_op_ge) return OP_GE;
611
+ if (op == K_op_eq) return OP_EQ;
612
+ if (op == K_op_ne) return OP_NE;
597
613
  if (op == K_op_pct) return OP_PCT;
598
614
  if (op == K_op_star_star) return OP_STAR_STAR;
599
615
  if (op == K_op_amp_amp) return OP_AND_AND;
@@ -611,12 +627,12 @@ op_to_id(PyObject *op)
611
627
  if (PyUnicode_Compare(op, K_op_minus) == 0) return OP_MINUS;
612
628
  if (PyUnicode_Compare(op, K_op_star) == 0) return OP_STAR;
613
629
  if (PyUnicode_Compare(op, K_op_slash) == 0) return OP_SLASH;
614
- if (PyUnicode_Compare(op, K_op_eq) == 0) return OP_EQ;
615
- if (PyUnicode_Compare(op, K_op_ne) == 0) return OP_NE;
616
- if (PyUnicode_Compare(op, K_op_le) == 0) return OP_LE;
617
630
  if (PyUnicode_Compare(op, K_op_lt) == 0) return OP_LT;
618
- if (PyUnicode_Compare(op, K_op_ge) == 0) return OP_GE;
631
+ if (PyUnicode_Compare(op, K_op_le) == 0) return OP_LE;
619
632
  if (PyUnicode_Compare(op, K_op_gt) == 0) return OP_GT;
633
+ if (PyUnicode_Compare(op, K_op_ge) == 0) return OP_GE;
634
+ if (PyUnicode_Compare(op, K_op_eq) == 0) return OP_EQ;
635
+ if (PyUnicode_Compare(op, K_op_ne) == 0) return OP_NE;
620
636
  if (PyUnicode_Compare(op, K_op_pct) == 0) return OP_PCT;
621
637
  if (PyUnicode_Compare(op, K_op_star_star) == 0) return OP_STAR_STAR;
622
638
  if (PyUnicode_Compare(op, K_op_amp_amp) == 0) return OP_AND_AND;
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bare-script
3
- Version: 4.1.1
3
+ Version: 4.1.3
4
4
  Summary: bare-script
5
5
  Home-page: https://github.com/craigahobbs/bare-script
6
6
  Author: Craig A. Hobbs
File without changes
File without changes
File without changes
File without changes