<commit_before>Javascript Translator
---------------------

translates intermediate form into final javascript.
This is also subclassed by these other backends:
* [gotranslator.md](gotranslator.md)
* [rusttranslator.md](rusttranslator.md)
* [cpptranslator.md](cpptranslator.md)

notes:
* the implementation of `spawn` is in [generatorbase.md](generatorbase.md)
* the builtin webworker pool spawn manager is in [builtins_core.py](runtime/builtins_core.py)

```python
# PythonJS to JavaScript Translator
# by <NAME> and <NAME> - copyright 2013
# License: "New BSD"

## note this should be cleared after a full round of translation,
## first the runtime is regenerated, and that is the first to populate
## the unicode name mapping.
UNICODE_NAME_MAP = {}

from types import GeneratorType
from ast import Str
from ast import Name
from ast import Tuple
from ast import Attribute
from ast import NodeVisitor

BLOCKIDS = False

class SwapLambda( RuntimeError ):
	def __init__(self, node):
		self.node = node
		RuntimeError.__init__(self)

class JSGenerator(NodeVisitorBase, GeneratorBase):
	def __init__(self, source, requirejs=True, insert_runtime=True, webworker=False, function_expressions=True, fast_javascript=False, fast_loops=False, runtime_checks=True, as_module=False):
		if not source:
			raise RuntimeError('empty source string')
		NodeVisitorBase.__init__(self, source)

		self._ES6 = {
			'imports' : True
		}
		self._as_module = as_module

		self._unicode_name_map = UNICODE_NAME_MAP

		self._iter_id = 0  ## used by for loops
		self._in_try = False
		self._runtime_type_checking = runtime_checks
		self.macros = {}
		self._sleeps = 0
		self._has_channels = False
		self._func_recv = 0
		self._with_oo = False
		self._fast_js = fast_javascript
		self._fast_loops = fast_loops
		self._func_expressions = function_expressions
		self._indent = 0
		self._global_functions = {}
		self._function_stack = []
		self._requirejs = requirejs
		self._insert_runtime = insert_runtime
		self._insert_nodejs_runtime = False
		self._insert_nodejs_tornado = False
		self._webworker = webworker
		self._exports = set()
		self._inline_lambda = False
		self.catch_call = set()  ## subclasses can use this to catch special calls

		self.special_decorators = set(['__typedef__', '__pyfunction__', 'expression'])

		self._typed_vars = dict()

		self._lua  = False
		self._dart = False
		self._go   = False
		self._rust = False
		self._cpp = False
		self._cheader = []
		self._cppheader = []
		self._cpp_class_impl = []
		self._match_stack = []       ## dicts of cases
		self._rename_hacks = {}      ## used by c++ backend, to support `if isinstance`
		self._globals = {}           ## name : type
		self._called_functions = {}  ## name : number of calls
```

reset
-----
`reset()` needs to be called for multipass backends, that are dumb and run translation twice to gather info in two passes.

```python

	def reset(self):
		self._cheader = []
		self._cppheader = []
		self._cpp_class_impl = []
		self._match_stack = []

```

Class
------
class is not implemented here for javascript, it gets translated ahead of time in 
[intermediateform.md](intermediateform.md)


```python

	def visit_ClassDef(self, node):
		raise NotImplementedError(node)


	def visit_Global(self, node):
		return '/*globals: %s */' %','.join(node.names)

	def visit_Assert(self, node):
		return 'if (!(%s)) {throw new Error("assertion failed"); }' %self.visit(node.test)


	def visit_Expr(self, node):

		s = self.visit(node.value)
		if s is None:
			raise RuntimeError('GeneratorBase ExpressionError: %s' %node.value)

		if s.strip() and not s.endswith(';'):
			s += ';'

		if s==';' or not s:
			return ''
		else:
			if self._in_try or not self._runtime_type_checking:
				return s
			elif not len(self._function_stack) or s.startswith('var '):
				return s
			elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id=='inline':
				if typedpython.needs_escape(s):raise RuntimeError(s)
				return s

			elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id=='sleep':
				assert self._stack[-1] is node
				if len(self._stack) < 3:
					raise SyntaxError('the builtin `sleep` can not be used at the global level outside of a function.')
				elif isinstance(self._stack[-2], ast.If):
					raise SyntaxError('the builtin `sleep` can only be used in the function body, and not under an `if` block.')
				elif isinstance(self._stack[-2], ast.For):
					raise SyntaxError('the builtin `sleep` can only be used in the function body, and not inside a `for` loop.')
				elif isinstance(self._stack[-2], ast.While):
					raise SyntaxError('the builtin `sleep` can only be used in the function body, and not inside a `for` or `while` loop.')
				elif not isinstance(self._stack[-2], ast.FunctionDef):
					raise SyntaxError('the builtin `sleep` can only be used in the function body, and not nested under any blocks.')
				return s
			else:
				## note `debugger` is a special statement in javascript that sets a break point if the js console debugger is open ##
				caller = self._function_stack[-1].name
				called = None
				if isinstance(node.value, ast.Call):
					called = self.visit(node.value.func)

				a = '/***/ try {\n'
				a += self.indent() + s + '\n'
				if typedpython.unicode_vars:
					if called:
						a += self.indent() + '/***/ } catch (__err) { if (𝗗𝗲𝗯𝘂𝗴𝗴𝗲𝗿.onerror(__err, %s, %s)==true){debugger;}else{throw __err;} };' %(caller, called)
					else:
						a += self.indent() + '/***/ } catch (__err) { if (𝗗𝗲𝗯𝘂𝗴𝗴𝗲𝗿.onerror(__err, %s)==true){debugger;}else{throw __err;} };' %caller
				else:
					if called:
							a += self.indent() + '/***/ } catch (__err) { if (__debugger__.onerror(__err, %s, %s)==true){debugger;}else{throw __err;} };' %(caller, called)
					else:
						a += self.indent() + '/***/ } catch (__err) { if (__debugger__.onerror(__err, %s)==true){debugger;}else{throw __err;} };' %caller
	
				return a


	def visit_Assign(self, node):
		target = node.targets[0]
		isname = isinstance(target, ast.Name)

		if isinstance(target, Tuple):
			raise NotImplementedError('target tuple assignment should have been transformed to flat assignment by python_to_pythonjs.py')
		else:
			value = self.visit(node.value)

			if self._runtime_type_checking and isinstance(target, ast.Subscript):
				tar = self.visit(target.value)
				key = self.visit(target.slice)
				a = [
					'if (%s.__setitem__) { %s.__setitem__(%s, %s) }' %(tar,tar,key,value),
					self.indent() + 'else { %s = %s }' %(self.visit(target), value)
				]
				return '\n'.join(a)
<commit_msg>js backend: fixed debugger and `new`<commit_after>Javascript Translator
---------------------

translates intermediate form into final javascript.
This is also subclassed by these other backends:
* [gotranslator.md](gotranslator.md)
* [rusttranslator.md](rusttranslator.md)
* [cpptranslator.md](cpptranslator.md)

notes:
* the implementation of `spawn` is in [generatorbase.md](generatorbase.md)
* the builtin webworker pool spawn manager is in [builtins_core.py](runtime/builtins_core.py)

```python
# PythonJS to JavaScript Translator
# by <NAME> and <NAME> - copyright 2013
# License: "New BSD"

## note this should be cleared after a full round of translation,
## first the runtime is regenerated, and that is the first to populate
## the unicode name mapping.
UNICODE_NAME_MAP = {}

from types import GeneratorType
from ast import Str
from ast import Name
from ast import Tuple
from ast import Attribute
from ast import NodeVisitor

BLOCKIDS = False

class SwapLambda( RuntimeError ):
	def __init__(self, node):
		self.node = node
		RuntimeError.__init__(self)

class JSGenerator(NodeVisitorBase, GeneratorBase):
	def __init__(self, source, requirejs=True, insert_runtime=True, webworker=False, function_expressions=True, fast_javascript=False, fast_loops=False, runtime_checks=True, as_module=False):
		if not source:
			raise RuntimeError('empty source string')
		NodeVisitorBase.__init__(self, source)

		self._ES6 = {
			'imports' : True
		}
		self._as_module = as_module

		self._unicode_name_map = UNICODE_NAME_MAP

		self._iter_id = 0  ## used by for loops
		self._in_try = False
		self._runtime_type_checking = runtime_checks
		self.macros = {}
		self._sleeps = 0
		self._has_channels = False
		self._func_recv = 0
		self._with_oo = False
		self._fast_js = fast_javascript
		self._fast_loops = fast_loops
		self._func_expressions = function_expressions
		self._indent = 0
		self._global_functions = {}
		self._function_stack = []
		self._requirejs = requirejs
		self._insert_runtime = insert_runtime
		self._insert_nodejs_runtime = False
		self._insert_nodejs_tornado = False
		self._webworker = webworker
		self._exports = set()
		self._inline_lambda = False
		self.catch_call = set()  ## subclasses can use this to catch special calls

		self.special_decorators = set(['__typedef__', '__pyfunction__', 'expression'])

		self._typed_vars = dict()

		self._lua  = False
		self._dart = False
		self._go   = False
		self._rust = False
		self._cpp = False
		self._cheader = []
		self._cppheader = []
		self._cpp_class_impl = []
		self._match_stack = []       ## dicts of cases
		self._rename_hacks = {}      ## used by c++ backend, to support `if isinstance`
		self._globals = {}           ## name : type
		self._called_functions = {}  ## name : number of calls
```

reset
-----
`reset()` needs to be called for multipass backends, that are dumb and run translation twice to gather info in two passes.

```python

	def reset(self):
		self._cheader = []
		self._cppheader = []
		self._cpp_class_impl = []
		self._match_stack = []

```

Class
------
class is not implemented here for javascript, it gets translated ahead of time in 
[intermediateform.md](intermediateform.md)


```python

	def visit_ClassDef(self, node):
		raise NotImplementedError(node)


	def visit_Global(self, node):
		return '/*globals: %s */' %','.join(node.names)

	def visit_Assert(self, node):
		return 'if (!(%s)) {throw new Error("assertion failed"); }' %self.visit(node.test)


	def visit_Expr(self, node):

		s = self.visit(node.value)
		if s is None:
			raise RuntimeError('GeneratorBase ExpressionError: %s' %node.value)

		if s.strip() and not s.endswith(';'):
			s += ';'

		if s==';' or not s:
			return ''
		else:
			if self._in_try or not self._runtime_type_checking:
				return s
			elif not len(self._function_stack) or s.startswith('var '):
				return s
			elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id=='inline':
				if typedpython.needs_escape(s):raise RuntimeError(s)
				return s

			elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id=='sleep':
				assert self._stack[-1] is node
				if len(self._stack) < 3:
					raise SyntaxError('the builtin `sleep` can not be used at the global level outside of a function.')
				elif isinstance(self._stack[-2], ast.If):
					raise SyntaxError('the builtin `sleep` can only be used in the function body, and not under an `if` block.')
				elif isinstance(self._stack[-2], ast.For):
					raise SyntaxError('the builtin `sleep` can only be used in the function body, and not inside a `for` loop.')
				elif isinstance(self._stack[-2], ast.While):
					raise SyntaxError('the builtin `sleep` can only be used in the function body, and not inside a `for` or `while` loop.')
				elif not isinstance(self._stack[-2], ast.FunctionDef):
					raise SyntaxError('the builtin `sleep` can only be used in the function body, and not nested under any blocks.')
				return s
			else:
				## note `debugger` is a special statement in javascript that sets a break point if the js console debugger is open ##
				do_try = True
				caller = self._function_stack[-1].name
				called = None
				if isinstance(node.value, ast.Call):
					called = self.visit(node.value.func)
					if isinstance(node.value.func, ast.Name) and node.value.func.id=='new':
						do_try = False
				elif isinstance(node.value, ast.Attribute):
					do_try = False

				if not do_try:
					return s
				else:
					a = '/***/ try {\n'
					a += self.indent() + s + '\n'
					if typedpython.unicode_vars:
						if called:
							a += self.indent() + '/***/ } catch (__err) { if (𝗗𝗲𝗯𝘂𝗴𝗴𝗲𝗿.onerror(__err, %s, %s)==true){debugger;}else{throw __err;} };' %(caller, called)
						else:
							a += self.indent() + '/***/ } catch (__err) { if (𝗗𝗲𝗯𝘂𝗴𝗴𝗲𝗿.onerror(__err, %s)==true){debugger;}else{throw __err;} };' %caller
					else:
						if called:
								a += self.indent() + '/***/ } catch (__err) { if (__debugger__.onerror(__err, %s, %s)==true){debugger;}else{throw __err;} };' %(caller, called)
						else:
							a += self.indent() + '/***/ } catch (__err) { if (__debugger__.onerror(__err, %s)==true){debugger;}else{throw __err;} };' %caller
		
					return a


	def visit_Assign(self, node):
		target = node.targets[0]
		isname = isinstance(target, ast.Name)

		if isinstance(target, Tuple):
			raise NotImplementedError('target tuple assignment should have been transformed to flat assignment by python_to_pythonjs.py')
		else:
			value = self.visit(node.value)

			if self._runtime_type_checking and isinstance(target, ast.Subscript):
				tar = self.visit(target.value)
				key = self.visit(target.slice)
				a = [
					'if (%s.__setitem__) { %s.__setitem__(%s, %s) }' %(tar,tar,key,value),
					self.indent() + 'else { %s = %s }' %(self.visit(target), value)
				]
				return '\n'.join(a)

{'fraction_non_alphanumeric': 0.13039621525724424, 'fraction_numerical': 0.002513305736250739, 'mean_word_length': 3.767089499647639, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3175931', 'n_tokens_mistral': 5060, 'n_tokens_neox': 4419, 'n_words': 1259}