Skip to content

Commit e66918c

Browse files
committed
module aliases halfway
1 parent 40abca0 commit e66918c

File tree

9 files changed

+202
-20
lines changed

9 files changed

+202
-20
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from org.transcrypt.stubs.browser import __pragma__
2+
import org.transcrypt.autotester
3+
4+
import arguments
5+
import attribs_by_name
6+
import builtin_super
7+
import byte_arrays
8+
import callable_test
9+
import classes
10+
import complex_numbers
11+
import conditional_expressions
12+
import control_structures
13+
14+
if __pragma__ ('defined', '__py3.7__'):
15+
import dashed_numbers
16+
17+
import data_classes
18+
import data_structures
19+
import decorators
20+
import dict_comprehensions
21+
import dictionaries
22+
import div_issues
23+
import div_pulls
24+
import docstrings
25+
import exceptions
26+
import extended_slices
27+
import fstrings
28+
import general_functions
29+
import globals_function
30+
import indices_and_slices
31+
import iterators_and_generators
32+
import lambda_functions
33+
import list_comprehensions
34+
import local_classes
35+
import metaclasses
36+
import method_and_class_decorators
37+
import module_builtin
38+
import module_cmath
39+
40+
if __pragma__ ('defined', 'undefined'):
41+
import module_collections
42+
43+
import module_datetime
44+
import module_itertools
45+
import module_math
46+
import module_unicodedata
47+
import modules
48+
import nonlocals
49+
import operator_overloading
50+
import properties
51+
import proxies
52+
import reprtest
53+
import set_comprehensions
54+
import simple_and_augmented_assignment
55+
56+
if __pragma__ ('defined', '__sform__'):
57+
import string_format
58+
59+
import truthyness
60+
import tuple_assignment
61+
62+
autoTester = org.transcrypt.autotester.AutoTester ()
63+
autoTester.run (arguments, 'arguments')
64+
autoTester.run (attribs_by_name, 'attribs_by_name')
65+
autoTester.run (builtin_super, 'builtin_super')
66+
autoTester.run (byte_arrays, 'byte_arrays')
67+
autoTester.run (callable_test, 'callable')
68+
autoTester.run (classes, 'classes')
69+
autoTester.run (complex_numbers, 'complex_numbers')
70+
autoTester.run (conditional_expressions, 'conditional_expressions')
71+
autoTester.run (control_structures, 'control_structures')
72+
autoTester.run (dashed_numbers, 'dashed_numbers')
73+
autoTester.run (data_classes, 'data_classes')
74+
autoTester.run (data_structures, 'data_structures')
75+
autoTester.run (decorators, 'decorators')
76+
autoTester.run (dict_comprehensions, 'dict_comprehensions')
77+
autoTester.run (dictionaries, 'dictionaries')
78+
autoTester.run (div_issues, 'div_issues')
79+
autoTester.run (div_pulls, 'div_pulls')
80+
autoTester.run (docstrings, 'docstrings')
81+
autoTester.run (exceptions, 'exceptions')
82+
autoTester.run (extended_slices, 'extended_slices')
83+
autoTester.run (fstrings, 'fstrings')
84+
autoTester.run (general_functions, 'general_functions')
85+
autoTester.run (globals_function, 'globals_function')
86+
autoTester.run (indices_and_slices, 'indices_and_slices')
87+
autoTester.run (iterators_and_generators, 'iterators_and_generators')
88+
autoTester.run (lambda_functions, 'lambda_functions')
89+
autoTester.run (list_comprehensions, 'list_comprehensions')
90+
autoTester.run (local_classes, 'local_classes')
91+
autoTester.run (metaclasses, 'metaclasses')
92+
autoTester.run (method_and_class_decorators, 'method_and_class_decorators')
93+
autoTester.run (module_builtin, 'module_builtin')
94+
autoTester.run (module_cmath, 'module_cmath')
95+
96+
if __pragma__ ('defined', 'undefined'):
97+
autoTester.run (module_collections, 'module_collections')
98+
99+
autoTester.run (module_datetime, 'module_datetime')
100+
autoTester.run (module_itertools, 'module_itertools')
101+
autoTester.run (module_math, 'module_math')
102+
autoTester.run (module_unicodedata, 'module_unicodedata')
103+
autoTester.run (modules, 'modules')
104+
autoTester.run (nonlocals, 'nonlocals')
105+
autoTester.run (operator_overloading, 'operator_overloading')
106+
autoTester.run (properties, 'properties')
107+
autoTester.run (reprtest, 'repr_str')
108+
autoTester.run (proxies, 'proxies')
109+
autoTester.run (set_comprehensions, 'set_comprehensions')
110+
autoTester.run (simple_and_augmented_assignment, 'simple_and_augmented_assignment')
111+
112+
if __pragma__ ('defined', '__sform__'):
113+
autoTester.run (string_format, 'string_format')
114+
115+
autoTester.run (truthyness, 'truthyness')
116+
autoTester.run (tuple_assignment, 'tuple_assignment')
117+
118+
autoTester.done ()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function bFunction (aPrint) {
2+
aPrint.check ('B function called<br>');
3+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<html>
2+
<head>
3+
<style>
4+
#__terminal__ {
5+
width: 100%;
6+
height: 100%;
7+
background-color: black;
8+
color: white;
9+
font-family: arial;
10+
font-size: 14px;
11+
}
12+
</style>
13+
</head>
14+
<body>
15+
<div id="__terminal__">
16+
<div>
17+
<script type="module">import * as hello from "./__target__/test.js";</script>
18+
</body>
19+
</html>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# __pragma__ ('alias', 'specific_module_a', 'specific-module-a')
2+
# __pragma__ ('alias', 'S', '$')
3+
4+
# __pragma__ ('alias', 'test_modules_b', 'test-modules-b')
5+
# __pragma__ ('alias', 'specific_module_b', 'specific-module-b')
6+
7+
# x__pragma__ ('alias', 'specific_submodule_c', 'specific-submodule-c')
8+
9+
from test_modules_a.__specific_module_a import a__S__Function
10+
from test_modules_b__.__specific_module_b import bFunction as theBFunction
11+
from test_modules_c.specific_module_c import *
12+
13+
def aPrint (any):
14+
document.getElementById ('__terminal__') .innerHTML += str (any)
15+
16+
def run (autoTester):
17+
the__S__Variable = 3
18+
aPrint (the__S__Variable)
19+
20+
a__S__Function (aPrint)
21+
theBFunction (aPrint)
22+
test_modules_c.specific_module_c.specific_submodule_c.c__S__Function (aPrint)
23+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function a$Function (aPrint) {
2+
aPrint ('A function called<br>');
3+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# x__pragma__ ('alias', 'specific_submodule_c', 'specific-submodule-c')
2+
3+
import test_modules_c.specific_submodule_c
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function c$Function (aPrint) {
2+
aPrint.check ('C function called<br>');
3+
};

transcrypt/modules/org/transcrypt/compiler.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,14 @@ def __init__ (
106106
message = f'\n\t{exception}'
107107
)
108108

109-
def provide (self, moduleName, __moduleName__ = None):
109+
def provide (self, filteredModuleName, __moduleName__ = None):
110110
# moduleName may contain dots if it's imported, but it'll have the same name in every import
111111

112-
if moduleName in self.moduleDict: # Find out if module is already provided
113-
return self.moduleDict [moduleName]
112+
if filteredModuleName in self.moduleDict: # Find out if module is already provided
113+
return self.moduleDict [filteredModuleName]
114114
else: # If not, provide by loading or compiling
115-
# This may fail legally if moduleName ends on a name of something in a module, rather than of the module itself
116-
return Module (self, moduleName, __moduleName__)
115+
# This may fail legally if filteredModuleName ends on a name of something in a module, rather than of the module itself
116+
return Module (self, filteredModuleName, __moduleName__)
117117

118118
class Module:
119119
def __init__ (self, program, name, __name__ = None):
@@ -230,6 +230,8 @@ def __init__ (self, program, name, __name__ = None):
230230
self.exportedNames = javascriptDigest.exportedNames
231231

232232
for importedModuleName in self.importedModuleNames:
233+
234+
# Unfiltered hyphens allowed, since we may be in a JavaScript-only part of the module hierarchy
233235
self.program.provide (importedModuleName)
234236

235237
# Remove eventual intermediate files
@@ -242,7 +244,7 @@ def __init__ (self, program, name, __name__ = None):
242244

243245
def findPaths (self):
244246
searchedModulePaths = []
245-
247+
246248
relSourceSlug = self.name.replace ('.', '/')
247249
for searchDir in self.program.moduleSearchDirs:
248250
# Find source slugs
@@ -608,13 +610,13 @@ def getPriority (exprNode):
608610

609611
def getAliaser (self, sourceFragment, targetFragment):
610612
return (sourceFragment, re.compile ('''
611-
(^{0}$)| # Whole word
612-
(.+__{0}__.+)| # Truly contains __<pyFragment>__ (Truly, so spare e.g. __name__)
613-
(^{0}__)| # Starts with <pyFragment>__
614-
(__{0}$)| # Ends with __<pyFragment>
615-
((?<=\.){0}__)| # Starts with '.<pyFragment>__'
616-
(__{0}(?=\.)) # Ends with '__<pyFragment>.'
617-
'''.format (sourceFragment), re.VERBOSE), targetFragment)
613+
(^{0}$)| # Whole word
614+
((.+)(__{0}__)(.+))| # Truly contains __<pyFragment>__ (Truly, so spare e.g. __name__)
615+
(^{0}__)| # Starts with <pyFragment>__
616+
(__{0}$)| # Ends with __<pyFragment>
617+
((?<=\.){0}__)| # Starts with '.<pyFragment>__'
618+
(__{0}(?=\.)) # Ends with '__<pyFragment>.'
619+
'''.format (sourceFragment), re.VERBOSE), fr'\3{targetFragment}\5')
618620

619621
def filterId (self, qualifiedId): # Convention: only called at emission time
620622
if self.idFiltering:
@@ -818,8 +820,14 @@ def prevTemp (self, name):
818820
del self.tempIndices [name]
819821

820822
def useModule (self, name):
821-
self.module.program.importStack [-1][1] = self.lineNr # Remember line nr of import statement for the error report
822-
return self.module.program.provide (name) # Must be done first because it can generate a healthy exception
823+
self.module.program.importStack [-1][1] = self.lineNr # Remember line nr of import statement for the error report
824+
825+
# Filter to get hyphen in name if a suitable alias is defined
826+
# Filtering has to be done early, since the hyphen has to be used in the filename when loading the module
827+
# The filename for this is made by the Program class, that doesn't have pragma's available
828+
# So name has to be passed "ready made"
829+
830+
return self.module.program.provide (self.filterId (name) if utils.commandArgs.alimod else name) # Must be done first because it can generate a healthy exception
823831

824832
def isCall (self, node, name):
825833
return type (node) == ast.Call and type (node.func) == ast.Name and node.func.id == name
@@ -2861,6 +2869,7 @@ def revisit_ImportFrom (self, node): # From ... import ... can import modules o
28612869
try: # Try if alias.name denotes a module
28622870
module = self.useModule ('{}.{}'.format (node.module, alias.name))
28632871
self.emit ('import * as {} from \'{}\';\n', self.filterId (alias.asname) if alias.asname else self.filterId (alias.name), module.importRelPath)
2872+
# self.allImportedNames.add(alias.asname or alias.name) # add import to allImportedNames of this module
28642873
except: # If it doesn't it denotes a facility inside a module
28652874
module = self.useModule (node.module)
28662875
namePairs.append (utils.Any (name = alias.name, asName = alias.asname))
@@ -3004,7 +3013,7 @@ def visit_Module (self, node):
30043013
self.importHoistFragmentIndex = self.fragmentIndex
30053014

30063015
# Let the module know its __name__
3007-
self.emit ('var __name__ = \'{}\';\n', self.module.__name__)
3016+
self.emit ('var __name__ = \'{}\';\n', self.module.__name__) # ??? Needs filterId ?
30083017
self.allOwnNames.add ('__name__')
30093018

30103019
# Generate code for the module body
@@ -3051,7 +3060,7 @@ def visit_Module (self, node):
30513060
])
30523061
+
30533062
'}});\n'
3054-
)
3063+
) # ??? Needs filterid?
30553064

30563065
# Import other modules (generatable only late, but hoisted) and nest them into the import heads
30573066
# The import head definitions are generated later but inserted before the imports
@@ -3065,7 +3074,7 @@ def visit_Module (self, node):
30653074
# Transit export of imported facilities (so no facilities that weren't imported and no modules)
30663075
if utils.commandArgs.xreex or self.module.sourcePrename == '__init__':
30673076
if self.allImportedNames:
3068-
self.emit ('export {{{}}};\n', ', '.join (self.allImportedNames)) # This does emit an export list
3077+
self.emit ('export {{{}}};\n', ', '.join ([self.filterId (importedName) for importedName in self.allImportedNames])) # This emits an export list
30693078

30703079
# Import runtime module (generatable only late, but hoisted)
30713080
# Place it first, but decimate its imported names last, since they should appear to be overriden by later imports

transcrypt/modules/org/transcrypt/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def parse (self):
3737

3838
self.argParser.add_argument ('source', nargs='?', help = ".py file containing source code of main module")
3939
self.argParser.add_argument ('-a', '--anno', help = "annotate target files that were compiled from Python with source file names and source line numbers", action = 'store_true')
40+
self.argParser.add_argument ('-am', '--alimod', help = "use aliasing for module paths", action = 'store_true')
4041
self.argParser.add_argument ('-b', '--build', help = "rebuild all target files from scratch", action = 'store_true')
4142
self.argParser.add_argument ('-c', '--complex', help = "enable complex number support, locally requires operator overloading", action = 'store_true')
4243
self.argParser.add_argument ('-d', '--docat', help = "enable __doc__ attributes. Apply sparsely, since it will make docstrings part of the generated code", action = 'store_true')
@@ -297,7 +298,7 @@ def __pragma__ (name, *args):
297298

298299
namesPattern = re.compile ('({.*})')
299300
pathPattern = re.compile ('([\'|\"].*[\'|\"])')
300-
wordPattern = re.compile (r'\w+')
301+
wordPattern = re.compile (r'[\w+$]')
301302
for line in passableLines:
302303
words = wordPattern.findall (line)
303304

@@ -320,7 +321,7 @@ def __pragma__ (name, *args):
320321

321322
# Substitute to become "{'p', 'q', 'r', 's'}" and use that set to extend the exported names list
322323
if match:
323-
result.exportedNames.extend (eval (re.sub (r'\w+', lambda nameMatch: f'\'{nameMatch.group ()}\'', match.group (1))))
324+
result.exportedNames.extend (eval (wordPattern.sub (lambda nameMatch: f'\'{nameMatch.group ()}\'', match.group (1))))
324325

325326
if words [0] == 'import':
326327
# Deducing imported modules from JavaScript is needed to provide the right modules to JavaScript-only modules

0 commit comments

Comments
 (0)