rapydscript-ng 0.7.18 → 0.7.22

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 (52) hide show
  1. package/.github/workflows/ci.yml +40 -0
  2. package/CHANGELOG.md +49 -1
  3. package/README.md +22 -7
  4. package/bin/web-repl-export +2 -2
  5. package/package.json +2 -2
  6. package/publish.py +9 -8
  7. package/release/baselib-plain-pretty.js +1707 -1044
  8. package/release/baselib-plain-ugly.js +3 -1
  9. package/release/compiler.js +5530 -3366
  10. package/release/signatures.json +18 -17
  11. package/src/ast.pyj +3 -1
  12. package/src/baselib-builtins.pyj +14 -3
  13. package/src/baselib-containers.pyj +13 -6
  14. package/src/baselib-internal.pyj +5 -1
  15. package/src/baselib-str.pyj +15 -2
  16. package/src/lib/elementmaker.pyj +2 -2
  17. package/src/lib/gettext.pyj +8 -7
  18. package/src/lib/random.pyj +1 -0
  19. package/src/lib/re.pyj +4 -3
  20. package/src/lib/traceback.pyj +16 -4
  21. package/src/output/classes.pyj +33 -5
  22. package/src/output/codegen.pyj +5 -38
  23. package/src/output/comments.pyj +45 -0
  24. package/src/output/functions.pyj +30 -19
  25. package/src/output/modules.pyj +19 -6
  26. package/src/output/operators.pyj +50 -19
  27. package/src/output/statements.pyj +2 -2
  28. package/src/output/stream.pyj +13 -21
  29. package/src/parse.pyj +52 -36
  30. package/src/string_interpolation.pyj +6 -1
  31. package/src/tokenizer.pyj +8 -2
  32. package/test/baselib.pyj +10 -0
  33. package/test/classes.pyj +24 -0
  34. package/test/collections.pyj +8 -0
  35. package/test/functions.pyj +16 -0
  36. package/test/generic.pyj +39 -1
  37. package/test/internationalization.pyj +8 -2
  38. package/test/regexp.pyj +3 -2
  39. package/test/scoped_flags.pyj +2 -0
  40. package/test/starargs.pyj +43 -0
  41. package/test/str.pyj +19 -8
  42. package/tools/cli.js +6 -1
  43. package/tools/compiler.js +3 -3
  44. package/tools/embedded_compiler.js +3 -3
  45. package/tools/export.js +3 -3
  46. package/tools/gettext.js +5 -2
  47. package/tools/lint.js +24 -13
  48. package/tools/msgfmt.js +1 -1
  49. package/web-repl/env.js +7 -1
  50. package/.appveyor.yml +0 -13
  51. package/.npmignore +0 -9
  52. package/.travis.yml +0 -12
@@ -1,30 +1,31 @@
1
1
  {
2
- "ast": "1146ab4709bdfa631410b9ff162612d8e7a78551",
3
- "baselib-builtins": "681435f650d8c3a7621703b54fcc038048b1f577",
4
- "baselib-containers": "bf6799ed79ba4aacd8c59dac9275f060907dc325",
2
+ "ast": "7a1a1800d9ee7af7f7153eee38002e4e9dcfb71e",
3
+ "baselib-builtins": "50927b38fded9bd9dbe14c42a20dd8e930ac021f",
4
+ "baselib-containers": "f7ac21a4dfc6311693239ea1eb45e74fae45a3f5",
5
5
  "baselib-errors": "f2423e1e2489bdd7fb8c8725bb76436898c8008c",
6
- "baselib-internal": "dab57c2bfc07bf761e46dc7469969668fefe7a7c",
6
+ "baselib-internal": "1b77d40970a8ef2d886132dc7c21c9510d2eb4cd",
7
7
  "baselib-itertools": "ab1f3257642c8d26fab1ff9d392814a459a60cdb",
8
- "baselib-str": "532d9d31003b9e19b4505e062a40365d29e693fa",
8
+ "baselib-str": "8c396e4fae02ae34b6d3d805becf7bfdd36625ee",
9
9
  "compiler": "cfbfceb0439fed3302f78d80b303dca713b25e7b",
10
10
  "errors": "d1b33848d19b141e19cc079cf78421f29b6d2c05",
11
11
  "output/__init__": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
12
- "output/classes": "dd1ac2387a01da170b0c984ba33b6994d702db80",
13
- "output/codegen": "b8970a936267f1fcb00c821961237fc25cb9efe6",
12
+ "output/classes": "d05c1992cc91b337a4e4ff137b0aa3d626e6624b",
13
+ "output/codegen": "0519a88c2704fe60b98fe747ca39f6be43b9abf3",
14
+ "output/comments": "78ec38d8b34da96c078653e2d0d4049d7003906b",
14
15
  "output/exceptions": "c7d90155694c7108e94d0940a160ae83725421d7",
15
- "output/functions": "9067d5c2b22277a65e9653d0f6ebdeb4dd2027f9",
16
+ "output/functions": "abaa81b171359eb77be6ea87cbdf9d7421d4622b",
16
17
  "output/literals": "fdbfb744fec8dfea1e1c62cb49767c60160fd402",
17
18
  "output/loops": "f59cc623320f57edb01953f7877d712758e9f825",
18
- "output/modules": "e5d60443c0d84fa303b4ad68a4d051bf5c54e01c",
19
- "output/operators": "c1b45fd5b97329f46d4437ee5e70d0ff601db82e",
20
- "output/statements": "ea38bdd2ca8a5fe0ceaa2c88d4a7b058df02675e",
21
- "output/stream": "66d54f69f4ed1bba506d243b39cc425fb82394c0",
19
+ "output/modules": "bd3e3f3f6794fb6e401867b4d011c4e3aab98893",
20
+ "output/operators": "f8142836a13b75680cb4874391db9e871fad0cad",
21
+ "output/statements": "7d8dfdc0b43e3e430be7ce3b23ffaf1b41408d8c",
22
+ "output/stream": "46375cb467477ac898546e818bfdfa5be738c352",
22
23
  "output/utils": "595968f96f6fdcc51eb41c34d64c92bb595e3cb1",
23
- "parse": "469e4fbdf935b03939f5d45397759f8eec872f77",
24
- "string_interpolation": "a1d336a7b11ac5760e004e79a82eb558be6f0368",
25
- "tokenizer": "1a0f90773ee7050a1b3c8fee2c059f3c9d5b9f6b",
24
+ "parse": "d5c1a77662dfcff841dfcd368d5dbb129a592f5d",
25
+ "string_interpolation": "bff1cc76d772d24d35707f6c794f38734ca08376",
26
+ "tokenizer": "00fc24a41edac9f9b31735e6290348005a623cef",
26
27
  "unicode_aliases": "79ac6eaa5e6be44a5397d62c561f854a8fe7528e",
27
28
  "utils": "c1666db819aa7c8db38697e34e18362e3cb45869",
28
- "#compiler#": "d4261f3ec5afc29831ed8295d61c84e4ce8418a6",
29
- "#compiled_with#": "d4261f3ec5afc29831ed8295d61c84e4ce8418a6"
29
+ "#compiler#": "d98fcbb15d08dae74d9c7371ea28fea676642e67",
30
+ "#compiled_with#": "d98fcbb15d08dae74d9c7371ea28fea676642e67"
30
31
  }
package/src/ast.pyj CHANGED
@@ -326,6 +326,7 @@ class AST_Toplevel(AST_Scope):
326
326
  'classes': "[Object/S] a map of class names to AST_Class for classes defined in this module",
327
327
  'filename': "[string] The absolute path to the file from which this module was read",
328
328
  'srchash': "[string] SHA1 hash of source code, used for caching",
329
+ 'comments_after': '[array] True iff there were comments before this token',
329
330
  }
330
331
 
331
332
  class AST_Import(AST_Statement):
@@ -411,7 +412,7 @@ class AST_Class(AST_Scope):
411
412
  'init': "[AST_Function] constructor for the class",
412
413
  'parent': "[AST_Symbol?] parent class this class inherits from",
413
414
  'bases': "[AST_Symbol*] list of base classes this class inherits from",
414
- "static": "[string*] list of static methods",
415
+ "static": "[dict] A hash whose keys are names of static methods for this class",
415
416
  'external': "[boolean] true if class is declared elsewhere, but will be within current scope at runtime",
416
417
  'bound': "[string*] list of methods that need to be bound to self",
417
418
  'decorators': "[AST_Decorator*] function decorators, if any",
@@ -718,6 +719,7 @@ class AST_ItemAccess(AST_PropAccess):
718
719
  'Python index-style property access, i.e. `a.__getitem__("foo")`'
719
720
  properties = {
720
721
  'assignment': "[AST_Node or None] Not None if this is an assignment (a[x] = y) rather than a simple access",
722
+ 'assign_operator': "[String] The operator for a assignment like += or empty string if plain assignment",
721
723
  }
722
724
 
723
725
  def _walk(self, visitor):
@@ -15,13 +15,19 @@ def ρσ_print():
15
15
  console.log(parts.join(' '))
16
16
 
17
17
  def ρσ_int(val, base):
18
- ans = parseInt(val, base or 10)
18
+ if jstype(val) is "number":
19
+ ans = val | 0
20
+ else:
21
+ ans = parseInt(val, base or 10)
19
22
  if isNaN(ans):
20
23
  raise ValueError('Invalid literal for int with base ' + (base or 10) + ': ' + val)
21
24
  return ans
22
25
 
23
- def ρσ_float():
24
- ans = parseFloat.apply(None, arguments)
26
+ def ρσ_float(val):
27
+ if jstype(val) is "number":
28
+ ans = val
29
+ else:
30
+ ans = parseFloat(val)
25
31
  if isNaN(ans):
26
32
  raise ValueError('Could not convert string to float: ' + arguments[0])
27
33
  return ans
@@ -171,6 +177,11 @@ def ρσ_range(start, stop, step):
171
177
  if not this._cached:
172
178
  this._cached = list(this)
173
179
  return this._cached.index(val)
180
+ ans.__len__ = def():
181
+ return length
182
+ ans.__repr__ = def():
183
+ return f'range({start}, {stop}, {step})'
184
+ ans.__str__ = ans.toString = ans.__repr__
174
185
  if jstype(Proxy) is 'function':
175
186
  ans = new Proxy(ans, {
176
187
  'get': def(obj, prop):
@@ -81,6 +81,8 @@ def ρσ_list_index(val, start, stop):
81
81
  def ρσ_list_pop(index):
82
82
  if this.length is 0:
83
83
  raise IndexError('list is empty')
84
+ if index is undefined:
85
+ index = -1
84
86
  ans = this.splice(index, 1)
85
87
  if not ans.length:
86
88
  raise IndexError('pop index out of range')
@@ -464,7 +466,7 @@ Object.defineProperties(ρσ_set.prototype, {
464
466
  s.add(r.value)
465
467
  r = iterator.next()
466
468
 
467
- ρσ_set.prototype.toString = ρσ_set.prototype.inspect = def():
469
+ ρσ_set.prototype.toString = ρσ_set.prototype.__repr__ = ρσ_set.prototype.__str__ = ρσ_set.prototype.inspect = def():
468
470
  return '{' + list(this).join(', ') + '}'
469
471
 
470
472
  ρσ_set.prototype.__eq__ = def(other):
@@ -630,11 +632,16 @@ Object.defineProperties(ρσ_dict.prototype, {
630
632
  return ans
631
633
 
632
634
  ρσ_dict.prototype.popitem = def ():
633
- r = this.jsmap.entries().next()
634
- if r.done:
635
- raise KeyError('dict is empty')
636
- this.jsmap.delete(r.value[0])
637
- return r.value
635
+ last = None
636
+ e = this.jsmap.entries()
637
+ while True:
638
+ r = e.next()
639
+ if r.done:
640
+ if last is None:
641
+ raise KeyError('dict is empty')
642
+ this.jsmap.delete(last.value[0])
643
+ return last.value
644
+ last = r
638
645
 
639
646
  ρσ_dict.prototype.update = def ():
640
647
  if arguments.length is 0:
@@ -1,7 +1,7 @@
1
1
  # vim:fileencoding=utf-8
2
2
  # License: BSD
3
3
 
4
- # globals: exports, console, ρσ_iterator_symbol, ρσ_kwargs_symbol, ρσ_arraylike, ρσ_list_contains, ρσ_list_constructor, ρσ_str
4
+ # globals: exports, console, ρσ_iterator_symbol, ρσ_kwargs_symbol, ρσ_arraylike, ρσ_list_contains, ρσ_list_constructor, ρσ_str, ρσ_int, ρσ_float
5
5
 
6
6
  def ρσ_eslice(arr, step, start, end):
7
7
  if jstype(arr) is 'string' or v'arr instanceof String':
@@ -261,6 +261,10 @@ def ρσ_instanceof():
261
261
  return True
262
262
  if q is ρσ_str and (jstype(obj) is 'string' or v'obj instanceof String'):
263
263
  return True
264
+ if q is ρσ_int and (jstype(obj) is 'number' and Number.isInteger(obj)):
265
+ return True
266
+ if q is ρσ_float and (jstype(obj) is 'number' and not Number.isInteger(obj)):
267
+ return True
264
268
  if bases.length > 1:
265
269
  for v'var c = 1; c < bases.length; c++':
266
270
  cls = bases[c]
@@ -4,6 +4,14 @@
4
4
 
5
5
  # globals: ρσ_kwargs_symbol, ρσ_list_decorate, ρσ_iterator_symbol, HTMLElement
6
6
 
7
+ # Locale can’t be changed in-flight, so we just retrieve this once.
8
+ # Sadly older node versions (< 8) don’t support formatToParts
9
+ # decimal_sep = Intl.NumberFormat() \
10
+ # .formatToParts(1.1) \
11
+ # .find(def(part): return part.type == 'decimal';) \
12
+ # .value
13
+ decimal_sep = (1.1).toLocaleString()[1]
14
+
7
15
  def ρσ_repr_js_builtin(x, as_array):
8
16
  ans = v'[]'
9
17
  b = '{}'
@@ -174,7 +182,7 @@ define_str_func('format', def ():
174
182
  (\#)? # integer base specifier
175
183
  (0)? # zero-padding
176
184
  (\d+)? # width
177
- ([,_])? # use a comma thousands-seperator
185
+ ([,_])? # use a grouping (thousands) seperator
178
186
  (?:\.(\d+))? # precision
179
187
  ([bcdeEfFgGnosxX%])? # type
180
188
  ///
@@ -253,7 +261,7 @@ define_str_func('format', def ():
253
261
  else:
254
262
  value = value.toExponential(prec - 1)
255
263
  value = value.replace(/0+$/g, '')
256
- if value[-1] is '.':
264
+ if value[-1] is decimal_sep:
257
265
  value = value[:-1]
258
266
  if ftype is 'G':
259
267
  value = value.toUpperCase()
@@ -334,6 +342,9 @@ define_str_func('format', def ():
334
342
  key, transformer, format_spec = parse_markup(markup)
335
343
  if transformer and v"['a', 'r', 's']".indexOf(transformer) is -1:
336
344
  raise ValueError('Unknown conversion specifier: ' + transformer)
345
+ ends_with_equal = key.endsWith('=')
346
+ if ends_with_equal:
347
+ key = key[:-1]
337
348
  lkey = key.length and split(key, /[.\[]/, 1)[0]
338
349
  if lkey:
339
350
  explicit = True
@@ -359,6 +370,8 @@ define_str_func('format', def ():
359
370
  ans = '' + object
360
371
  if format_spec:
361
372
  ans = apply_formatting(ans, format_spec)
373
+ if ends_with_equal:
374
+ ans = f'{key}={ans}'
362
375
  return ans
363
376
 
364
377
 
@@ -3,12 +3,12 @@
3
3
 
4
4
  html_elements = {
5
5
  'a', 'abbr', 'acronym', 'address', 'area',
6
- 'article', 'aside', 'audio', 'b', 'big', 'blockquote', 'br', 'button',
6
+ 'article', 'aside', 'audio', 'b', 'base', 'big', 'body', 'blockquote', 'br', 'button',
7
7
  'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup',
8
8
  'command', 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn',
9
9
  'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'event-source', 'fieldset',
10
10
  'figcaption', 'figure', 'footer', 'font', 'form', 'header', 'h1',
11
- 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'input', 'ins',
11
+ 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'head', 'i', 'iframe', 'img', 'input', 'ins',
12
12
  'keygen', 'kbd', 'label', 'legend', 'li', 'm', 'map', 'menu', 'meter',
13
13
  'multicol', 'nav', 'nextid', 'ol', 'output', 'optgroup', 'option',
14
14
  'p', 'pre', 'progress', 'q', 's', 'samp', 'script', 'section', 'select',
@@ -531,29 +531,31 @@ def register_callback(func):
531
531
  register_callback.install_callbacks.push(func)
532
532
  register_callback.install_callbacks = v'[]'
533
533
 
534
+ empty_translation_data = {'entries': {}}
535
+
534
536
  class Translations:
535
537
 
536
538
  def __init__(self, translation_data):
537
- translation_data = translation_data or {}
538
- func = _get_plural_forms_function(translation_data['plural_forms'])
539
+ translation_data = translation_data or empty_translation_data
540
+ func = _get_plural_forms_function(translation_data.plural_forms)
539
541
  self.translations = [[translation_data, func]]
540
542
  self.language = translation_data['language']
541
543
 
542
544
  def add_fallback(self, fallback):
543
- fallback = fallback or {}
544
- func = _get_plural_forms_function(fallback['plural_forms'])
545
+ fallback = fallback or empty_translation_data
546
+ func = _get_plural_forms_function(fallback.plural_forms)
545
547
  self.translations.push([fallback, func])
546
548
 
547
549
  def gettext(self, text):
548
550
  for t in self.translations:
549
- m = t[0]['entries']
551
+ m = t[0].entries
550
552
  if has_prop(m, text):
551
553
  return m[text][0]
552
554
  return text
553
555
 
554
556
  def ngettext(self, text, plural, n):
555
557
  for t in self.translations:
556
- m = t[0]['entries']
558
+ m = t[0].entries
557
559
  if has_prop(m, text):
558
560
  idx = t[1](n)
559
561
  return m[text][idx] or (text if n is 1 else plural)
@@ -565,4 +567,3 @@ class Translations:
565
567
  return self.gettext.apply(self, arguments)
566
568
  _ngettext = def ():
567
569
  return self.ngettext.apply(self, arguments)
568
-
@@ -30,6 +30,7 @@
30
30
  ρσ_seed_state.key[ρσ_seed_state.key_j]) % 256]
31
31
 
32
32
  def seed(x=Date().getTime()):
33
+ ρσ_seed_state.key_i = ρσ_seed_state.key_j = 0
33
34
  if jstype(x) is 'number':
34
35
  x = x.toString()
35
36
  elif jstype(x) is not 'string':
package/src/lib/re.pyj CHANGED
@@ -125,9 +125,12 @@ def _expand(groups, repl, group_name_map):
125
125
  return '\\' + q
126
126
 
127
127
  ans = ch = ''
128
- while (ch = next()):
128
+ while True:
129
+ ch = next()
129
130
  if ch is '\\':
130
131
  ans += read_escape_sequence()
132
+ elif not ch:
133
+ break
131
134
  else:
132
135
  ans += ch
133
136
  return ans
@@ -184,8 +187,6 @@ def transform_regex(source, flags):
184
187
  flags |= flag_map[q]
185
188
  pos = close + 1
186
189
  continue
187
- if extension is '<':
188
- raise SyntaxError('Look behind assertions are not supported in JavaScript')
189
190
  if extension is '(':
190
191
  raise SyntaxError('Group existence assertions are not supported in JavaScript')
191
192
  if extension is 'P':
@@ -2,18 +2,30 @@
2
2
  # License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
3
3
  # globals: ρσ_str, ρσ_last_exception
4
4
 
5
+
5
6
  def _get_internal_traceback(err):
6
7
  if isinstance(err, Exception) and err.stack:
7
8
  lines = ρσ_str.splitlines(err.stack)
9
+ final_lines = v'[]'
10
+ found_sentinel = False
8
11
  for i, line in enumerate(lines):
9
- line = ρσ_str.strip(line)
12
+ sline = ρσ_str.strip(line)
13
+ if i is 0:
14
+ final_lines.push(line)
15
+ continue
16
+ if found_sentinel:
17
+ final_lines.push(line)
18
+ continue
10
19
  # These two conditions work on desktop Chrome and Firefox to identify the correct
11
20
  # line in the traceback.
12
- if line.startsWith('at new ' + err.name) or line.startsWith(err.name + '@'):
13
- return err.__repr__() + '\n' + lines.slice(i+1).join('\n')
21
+ if sline.startsWith('at new ' + err.name) or sline.startsWith(err.name + '@'):
22
+ found_sentinel = True
23
+ return final_lines.join('\n')
14
24
  return err and err.stack
15
25
 
16
26
  def format_exception(exc, limit):
27
+ if jstype(exc) is 'undefined':
28
+ exc = ρσ_last_exception
17
29
  if not isinstance(exc, Error):
18
30
  if exc and exc.toString:
19
31
  return [exc.toString()]
@@ -22,7 +34,7 @@ def format_exception(exc, limit):
22
34
  if tb:
23
35
  lines = ρσ_str.splitlines(tb)
24
36
  e = lines[0]
25
- lines = [l for l in lines[1:]]
37
+ lines = lines[1:]
26
38
  if limit:
27
39
  lines = lines[:limit+1] if limit > 0 else lines[limit:]
28
40
  lines.reverse()
@@ -5,6 +5,7 @@ from __python__ import hash_literals
5
5
  from ast import AST_Class, AST_Method, is_node_type
6
6
  from output.functions import decorate, function_definition, function_annotation
7
7
  from output.utils import create_doctring
8
+ from utils import has_prop
8
9
 
9
10
  def print_class(output):
10
11
  self = this
@@ -14,7 +15,7 @@ def print_class(output):
14
15
  def class_def(method, is_var):
15
16
  output.indent()
16
17
  self.name.print(output)
17
- if not is_var and method and self.static.indexOf(method) is not -1:
18
+ if not is_var and method and has_prop(self.static, method):
18
19
  output.assign("." + method)
19
20
  else:
20
21
  if is_var:
@@ -27,7 +28,7 @@ def print_class(output):
27
28
  if not is_property:
28
29
  class_def(name)
29
30
  # only strip first argument if the method is static
30
- is_static = self.static.indexOf(name) is not -1
31
+ is_static = has_prop(self.static, name)
31
32
  strip_first = not is_static
32
33
 
33
34
  # decorate the method
@@ -74,15 +75,25 @@ def print_class(output):
74
75
  output.end_statement()
75
76
  )
76
77
 
77
- # decorate the class
78
- if self.decorators and self.decorators.length:
78
+ decorators = self.decorators or v'[]'
79
+ if decorators.length:
79
80
  output.print('var ')
80
81
  output.assign(self.name)
81
- decorate(self.decorators, output, write_constructor)
82
+ write_constructor()
82
83
  output.semicolon()
83
84
  else:
84
85
  write_constructor()
85
86
  output.newline()
87
+ if decorators.length:
88
+ output.indent()
89
+ self.name.print(output)
90
+ output.spaced('.ρσ_decorators', '=', '[')
91
+ num = decorators.length
92
+ for i in range(num):
93
+ decorators[i].expression.print(output)
94
+ output.spaced(',' if i < num - 1 else ']')
95
+ output.semicolon()
96
+ output.newline()
86
97
 
87
98
  # inheritance
88
99
  if self.parent:
@@ -233,3 +244,20 @@ def print_class(output):
233
244
  output.indent()
234
245
  stmt.print(output)
235
246
  output.newline()
247
+
248
+ if decorators.length:
249
+ output.indent()
250
+ output.assign(self.name)
251
+ for di in range(decorators.length):
252
+ self.name.print(output)
253
+ output.print(f'.ρσ_decorators[{di}](')
254
+ self.name.print(output)
255
+ output.print(')' * decorators.length)
256
+ output.semicolon()
257
+ output.newline()
258
+ output.indent()
259
+ output.spaced('delete ')
260
+ self.name.print(output)
261
+ output.print('.ρσ_decorators')
262
+ output.semicolon()
263
+ output.newline()
@@ -8,9 +8,9 @@ from utils import noop
8
8
  from parse import PRECEDENCE
9
9
  from ast import (
10
10
  AST_Array, AST_Assign, AST_BaseCall, AST_Binary, AST_BlockStatement, AST_Break,
11
- AST_Catch, AST_Class, AST_Conditional, AST_Constant, AST_Continue,
11
+ AST_Class, AST_Conditional, AST_Constant, AST_Continue,
12
12
  AST_Debugger, AST_Definitions, AST_Directive, AST_Do, AST_Dot, is_node_type,
13
- AST_EmptyStatement, AST_Exit, AST_ExpressiveObject, AST_Finally, AST_ForIn,
13
+ AST_EmptyStatement, AST_Exit, AST_ExpressiveObject, AST_ForIn,
14
14
  AST_ForJS, AST_Function, AST_Hole, AST_If, AST_Imports, AST_Infinity,
15
15
  AST_Lambda, AST_ListComprehension, AST_LoopControl, AST_NaN, AST_New, AST_Node,
16
16
  AST_Number, AST_Object, AST_ObjectKeyVal, AST_ObjectProperty, AST_PropAccess,
@@ -25,6 +25,7 @@ from output.classes import print_class
25
25
  from output.literals import print_array, print_obj_literal, print_object, print_set, print_regexp
26
26
  from output.loops import print_do_loop, print_while_loop, print_for_loop_body, print_for_in, print_list_comprehension
27
27
  from output.modules import print_top_level, print_imports
28
+ from output.comments import print_comments
28
29
  from output.operators import (
29
30
  print_getattr, print_getitem, print_rich_getitem, print_splice_assignment,
30
31
  print_unary_prefix, print_binary_op, print_assign,
@@ -57,42 +58,8 @@ def generate_code():
57
58
 
58
59
  # -----[ comments ]-----
59
60
  AST_Node.prototype.add_comments = def(output):
60
- c = output.options.comments
61
- self = this
62
- if c:
63
- start = self.start
64
- if start and not start._comments_dumped:
65
- start._comments_dumped = True
66
- comments = start.comments_before
67
- # XXX: ugly fix for https://github.com/mishoo/RapydScript2/issues/112
68
- # if this node is `return` or `throw`, we cannot allow comments before
69
- # the returned or thrown value.
70
- if is_node_type(self, AST_Exit) and self.value and self.value.start.comments_before and self.value.start.comments_before.length > 0:
71
- comments = (comments or []).concat(self.value.start.comments_before)
72
- self.value.start.comments_before = []
73
-
74
- if c.test:
75
- comments = comments.filter(def(comment):
76
- return c.test(comment.value)
77
- )
78
- elif jstype(c) is "function":
79
- comments = comments.filter(def(comment):
80
- return c(self, comment)
81
- )
82
-
83
- for comm in comments:
84
- if comm.type is "comment1":
85
- output.print("//" + comm.value + "\n")
86
- output.indent()
87
- elif comm.type is "comment2":
88
- output.print("/*" + comm.value + "*/")
89
- if start.nlb:
90
- output.print("\n")
91
- output.indent()
92
- else:
93
- output.space()
94
-
95
-
61
+ if not is_node_type(this, AST_Toplevel):
62
+ print_comments(this, output)
96
63
 
97
64
  # -----[ PARENTHESES ]-----
98
65
  def PARENS(nodetype, func):
@@ -0,0 +1,45 @@
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
3
+ from __python__ import hash_literals
4
+
5
+ from ast import AST_Exit, is_node_type
6
+
7
+
8
+ def output_comments(comments, output, nlb):
9
+ for comm in comments:
10
+ if comm.type is "comment1":
11
+ output.print("//" + comm.value + "\n")
12
+ output.indent()
13
+ elif comm.type is "comment2":
14
+ output.print("/*" + comm.value + "*/")
15
+ if nlb:
16
+ output.print("\n")
17
+ output.indent()
18
+ else:
19
+ output.space()
20
+
21
+
22
+ def print_comments(self, output):
23
+ c = output.options.comments
24
+ if c:
25
+ start = self.start
26
+ if start and not start._comments_dumped:
27
+ start._comments_dumped = True
28
+ comments = start.comments_before
29
+ # XXX: ugly fix for https://github.com/mishoo/RapydScript2/issues/112
30
+ # if this node is `return` or `throw`, we cannot allow comments before
31
+ # the returned or thrown value.
32
+ if is_node_type(self, AST_Exit) and self.value and self.value.start.comments_before and self.value.start.comments_before.length > 0:
33
+ comments = (comments or v'[]').concat(self.value.start.comments_before)
34
+ self.value.start.comments_before = v'[]'
35
+
36
+ if c.test:
37
+ comments = comments.filter(def(comment):
38
+ return c.test(comment.value)
39
+ )
40
+ elif jstype(c) is "function":
41
+ comments = comments.filter(def(comment):
42
+ return c(self, comment)
43
+ )
44
+
45
+ output_comments(comments, output, start.nlb)
@@ -10,6 +10,12 @@ from output.utils import create_doctring
10
10
  from output.operators import print_getattr
11
11
 
12
12
  anonfunc = 'ρσ_anonfunc'
13
+ module_name = 'null'
14
+
15
+ def set_module_name(x):
16
+ nonlocal module_name
17
+ module_name = '"' + x + '"' if x else 'null'
18
+
13
19
 
14
20
  # Function definition {{{
15
21
 
@@ -148,7 +154,7 @@ def function_annotation(self, output, strip_first, name):
148
154
  output.print('true')
149
155
 
150
156
  # Create __argnames__
151
- if self.argnames.length:
157
+ if self.argnames.length > (1 if strip_first else 0):
152
158
  props.__argnames__ = def():
153
159
  output.print('[')
154
160
  for i, arg in enumerate(self.argnames):
@@ -164,29 +170,28 @@ def function_annotation(self, output, strip_first, name):
164
170
  props.__doc__ = def():
165
171
  output.print(JSON.stringify(create_doctring(self.docstrings)))
166
172
 
173
+ props.__module__ = def():
174
+ output.print(module_name)
175
+
167
176
  names = Object.keys(props)
168
- if names.length:
169
- output.indent()
170
- # Only define the properties if they were not already defined, which
171
- # can happen if the function definition is inside a loop, for example.
172
- output.spaced('if', '(!' + fname + '.' + names[0] + ')', 'Object.defineProperties(' + fname)
173
- output.comma()
174
- output.with_block(def():
175
- for v'var i = 0; i < names.length; i++':
176
- name = names[i]
177
- output.indent(), output.spaced(name, ':', '{value:', ''), props[name](), output.print('}')
178
- if i < names.length - 1:
179
- output.print(',')
180
- output.newline()
181
- )
182
- output.print(')'), output.end_statement()
177
+ output.indent()
178
+ # Only define the properties if they were not already defined, which
179
+ # can happen if the function definition is inside a loop, for example.
180
+ output.spaced('if', '(!' + fname + '.' + names[0] + ')', 'Object.defineProperties(' + fname)
181
+ output.comma()
182
+ output.with_block(def():
183
+ for v'var i = 0; i < names.length; i++':
184
+ name = names[i]
185
+ output.indent(), output.spaced(name, ':', '{value:', ''), props[name](), output.print('}')
186
+ if i < names.length - 1:
187
+ output.print(',')
188
+ output.newline()
189
+ )
190
+ output.print(')'), output.end_statement()
183
191
 
184
192
 
185
193
  def function_definition(self, output, strip_first, as_expression):
186
194
  as_expression = as_expression or self.is_expression or self.is_anonymous
187
- if not self.argnames.length and not self.return_annotation and (not output.options.keep_docstrings or not self.docstrings or not self.docstrings.length):
188
- # This function has no annotations so dont wrap it needlessly
189
- as_expression = False
190
195
  if as_expression:
191
196
  orig_indent = output.indentation()
192
197
  output.set_indentation(output.next_indent())
@@ -268,8 +273,10 @@ def print_this(expression, output):
268
273
  output.print('this')
269
274
 
270
275
  def print_function_call(self, output):
276
+ is_prototype_call = False
271
277
 
272
278
  def print_function_name(no_call):
279
+ nonlocal is_prototype_call
273
280
  if is_node_type(self, AST_ClassCall):
274
281
  # class methods are called through the prototype unless static
275
282
  if self.static:
@@ -277,6 +284,7 @@ def print_function_call(self, output):
277
284
  output.print(".")
278
285
  output.print(self.method)
279
286
  else:
287
+ is_prototype_call = True
280
288
  self.class.print(output)
281
289
  output.print(".prototype.")
282
290
  output.print(self.method)
@@ -396,6 +404,9 @@ def print_function_call(self, output):
396
404
  output.print('.apply(')
397
405
  do_print_this()
398
406
 
407
+ if is_prototype_call and self.args.length > 1:
408
+ self.args.shift()
409
+
399
410
  print_positional_args()
400
411
 
401
412
  if has_kwargs: