Skip to content

JavaScript Unicode Literate Output

brett hartshorn edited this page Sep 9, 2015 · 3 revisions

The command line option --literate-unicode enables unicode variable names in the output javascript. To check if the unicode characters are valid in javascript, go to: https://mothereff.in/js-variables

Note that mini-macros can use any unicode characters, and the option --literate-unicode is not required, this is because the mini-macro name is replaced by the macro definition at compile time.

Examples

Transpiler Spec

This is a spec that makes some suggestions how to implement a unicode language that is output from a transpiler into JavaScript.

Some of the spec comes from a Python-to-JavaScript perspective, other parts are generic. The spec is intended to be implemented by a transpiler, and not hand written by people. The intention is to have a unicode based language that is easy for people to read, with as little eye strain as possible. Note that, by "language" we are talking about variable and function names, not actual syntax because that remains JavaScript.

𝑨𝒃𝒄

In the development of the spec many fonts were tried, and viewed in the browser and different text editors, the primary font that is clear and distinct was found to be: Mathematical Bold Italic. This font clearly stands out from regular text, so the user is quickly able to see their own code from the builtin functions of the language.

𝔸𝕓𝕔

Another font we recommend for special cases is: Mathematical Double Struck. It can be used to signal the user that the item it refers to is in some way hidden or not to be used directly. If the transpiler allows end users to define their own unicode based variables and functions, the end user should not used double-struck fonts, to avoid any conflicts with internal use.

For Loop Iteration

When translating a for loop that iterates over items in an array, for item in somearray:, an index variable needs to be generated. To improve readability of the JavaScript output, the generated index variable can be named 𝓷. That is the mathematical bold script small n, U+1D4F7. If there are nested for loops, then a unique index must be generated for each one, in these cases 𝓷 can be followed by a number, 𝓷1.
Note that while it would be more readable to use subscript numbers: ₀₁₂₃₄₅₆₇₈₉. They are not in the valid unicode range.

If the transpiler also needs to generate an iterator name for the loop, it can prefix the name with 𝕚𝕥𝕖𝕣 Example translation for this python input: for k in mydict: pass

		var 𝕚𝕥𝕖𝕣mydict = mydict;
		// some runtime magic here the transpiler may inject to reassign `𝕚𝕥𝕖𝕣mydict` to an array of its keys
		for (var 𝓷 = 0; 𝓷 < 𝕚𝕥𝕖𝕣mydict.length; 𝓷++) {
			var k = 𝕚𝕥𝕖𝕣idict[ 𝓷 ];
		}

Python Builtins

Python has a whole set of builtin functions, but often these names are too short; while that makes it quick to type, reading it becomes harder. In addition, the output code may be read by other programmers, who know JavaScript but may not know the Python API and builtins, for these users, plain English names are going to be much easier to understand. This is not an absolute rule, for example dict and dir look ok with their short-handed names.

getattr

The Python builtin function getattr( OBJECT, NAME ) should be transpiled to: 𝑮𝒆𝒕𝑨𝒕𝒕𝒓𝒊𝒃𝒖𝒕𝒆( OBJECT, NAME ).

setattr

The Python builtin function setattr( OBJECT, NAME, VALUE ) should be transpiled to: 𝑺𝒆𝒕𝑨𝒕𝒕𝒓𝒊𝒃𝒖𝒕𝒆( OBJECT, NAME, VALUE ).

int

The Python builtin function int( NUMBER ) should be transpiled to: 𝑰𝒏𝒕𝒆𝒈𝒆𝒓( NUMBER ).

float

The Python builtin function float( NUMBER ) should be transpiled to: 𝑭𝒍𝒐𝒂𝒕( NUMBER ).

str

The Python builtin function str( OBJECT ) should be transpiled to: 𝑺𝒕𝒓𝒊𝒏𝒈( OBJECT ).

dict

The Python builtin class dict( OBJECT ) should be transpiled to: 𝑫𝒊𝒄𝒕( OBJECT ). Note: in this case we recommend keeping the short-hand name.

list

The Python builtin class list( OBJECT ) should be transpiled to: 𝑳𝒊𝒔𝒕( OBJECT ).

set

The Python builtin class set( OBJECT ) should be transpiled to: 𝑺𝒆𝒕( OBJECT ).

len

The Python builtin function len( LIST ) should be transpiled to: 𝑳𝒆𝒏𝒈𝒕𝒉( LIST ).

isinstance

The Python builtin function isinstance( LIST ) should be transpiled to: 𝑰𝒔𝑰𝒏𝒔𝒕𝒂𝒏𝒄𝒆( LIST ).

sum

The Python builtin function sum( LIST ) should be transpiled to: 𝑳𝒊𝒔𝒕𝑺𝒖𝒎( LIST ).

note: while it would be more mathmatically correct to use sigma , this is currently not in the valid unicode range for javascript variables.

But wait, U+1D6F4, 𝛴 is in the valid unicode range, so another option is: 𝛴( LIST ) However the problem with this is it inconsistent with the rest of the naming convention here, and most of the math symbols are not in the unicode range allowed for js variable names.

map

The Python builtin function map( FUNCTION, LIST ) should be transpiled to: 𝑳𝒊𝒔𝒕𝑴𝒂𝒑( FUNCTION, LIST )

filter

The Python builtin function filter( FUNCTION, LIST ) should be transpiled to: 𝑳𝒊𝒔𝒕𝑭𝒊𝒍𝒕𝒆𝒓( FUNCTION, LIST )

min

The Python builtin function min( LIST ) should be transpiled to: 𝑳𝒊𝒔𝒕𝑴𝒊𝒏( LIST )

max

The Python builtin function max( LIST ) should be transpiled to: 𝑳𝒊𝒔𝒕𝑴𝒂𝒙( LIST )

abs

The Python builtin function abs( NUMBER ) should be transpiled to: 𝑨𝒃𝒔𝒐𝒍𝒖𝒕𝒆( NUMBER )

chr

The Python builtin function chr( NUMBER ) should be transpiled to: 𝑪𝒉𝒂𝒓𝒂𝒄𝒕𝒆𝒓( NUMBER )

ord

The Python builtin function org( CHAR ) should be transpiled to: 𝑶𝒓𝒅𝒊𝒏𝒂𝒍( CHAR )

JavaScript Generic Helpers

A Python to JavaScript transpiler will likely need to have its own set of internal helper functions that are not part of the regular Python standard, the following is suggestions for some of these basic helpers and their names.

𝑰𝒔𝑨𝒓𝒓𝒂𝒚

JavaScript contains Array, and several other types that are Array-like, but are actually different types of objects, like: NodeList, FileList, DOMStringList, and others. The function, 𝑰𝒔𝑨𝒓𝒓𝒂𝒚( OBJECT ), should be able to detect those types and return true if the argument is Array-like. Below is an example implementation.

__dom_array_types__ = []
if typeof(NodeList) == 'function':  ## NodeList is only available in browsers
	## minimal dom array types common to allow browsers ##
	__dom_array_types__ = [ NodeList, FileList, DOMStringList, HTMLCollection, SVGNumberList, SVGTransformList]

	## extra dom array types ##
	if typeof(DataTransferItemList) == 'function':  ## missing in NodeWebkit
		__dom_array_types__.push( DataTransferItemList )
	if typeof(HTMLAllCollection) == 'function':     ## missing in Firefox
		__dom_array_types__.push( HTMLAllCollection )
	if typeof(SVGElementInstanceList) == 'function':## missing in Firefox
		__dom_array_types__.push( SVGElementInstanceList )
	if typeof(ClientRectList) == 'function':        ## missing in Firefox-trunk
		__dom_array_types__.push( ClientRectList )

def 𝑰𝒔𝑨𝒓𝒓𝒂𝒚( ob ):
	if __dom_array_types__.length > 0:
		for t in __dom_array_types__:
			if instanceof(ob, t):
				return True
	return False

𝑰𝒔𝑻𝒚𝒑𝒆𝒅𝑨𝒓𝒓𝒂𝒚

JavaScript includes typed arrays, however not all browsers support every type of typed array, that is why we need this helper function. Below is an example implementation.

def 𝑰𝒔𝑻𝒚𝒑𝒆𝒅𝑨𝒓𝒓𝒂𝒚( ob ):
	if instanceof( ob, Int16Array ) or instanceof( ob, Uint16Array ):
		return True
	elif instanceof( ob, Int32Array ) or instanceof( ob, Uint32Array ):
		return True
	elif instanceof( ob, Float32Array ) or instanceof( ob, Float64Array ):
		return True
	else:
		return False