11namespace pxt . py {
22 import B = pxt . blocks ;
3+ import SK = pxtc . SymbolKind
34
45 interface Ctx {
56 currModule : py . Module ;
@@ -15,6 +16,7 @@ namespace pxt.py {
1516 let typeId = 0
1617 let numUnifies = 0
1718 let currErrs = ""
19+ let autoImport = true
1820
1921 function stmtTODO ( v : py . Stmt ) {
2022 return B . mkStmt ( B . mkText ( "TODO: " + v . kind ) )
@@ -32,22 +34,83 @@ namespace pxt.py {
3234 return B . mkStmt ( B . mkText ( "/** " + cmt + " */" ) )
3335 }
3436
37+ function defName ( n : string , tp : Type ) : Name {
38+ return {
39+ kind : "Name" ,
40+ id : n ,
41+ isdef : true ,
42+ ctx : "Store" ,
43+ tsType : tp
44+ } as any
45+ }
46+
47+ function mapTsType ( tp : string ) {
48+ let ai = apisInfo . byQName [ tp ]
49+ if ( ai && ai . kind == SK . Enum )
50+ return tpNumber
51+ let sym = lookupSymbol ( tp )
52+ if ( sym && sym . kind == "ClassDef" )
53+ return mkType ( { classType : sym as ClassDef } )
54+ return mkType ( { primType : tp } )
55+ }
56+
57+ function mapTsArg ( a : pxtc . ParameterDesc ) : Arg {
58+ return {
59+ kind : "Arg" ,
60+ arg : a . name ,
61+ type : mapTsType ( a . type ) ,
62+ } as any
63+ }
64+
3565 function lookupSymbol ( name : string ) : py . Symbol {
3666 if ( ! name ) return null
37- if ( moduleAst [ name ] )
38- return moduleAst [ name ]
67+
68+ const mod = moduleAst [ name ]
69+ if ( mod ) {
70+ if ( ! mod . body ) {
71+ mod . body = [ ]
72+ for ( let sym of mod . tsBody ) {
73+ if ( isModule ( sym ) ) {
74+ if ( moduleAst [ sym . qName ] )
75+ mod . body . push ( lookupSymbol ( sym . qName ) )
76+ } else if ( sym . kind == SK . Variable || sym . kind == SK . EnumMember ) {
77+ mod . body . push ( {
78+ kind : "Assign" ,
79+ targets : [ defName ( sym . name , mapTsType ( sym . retType ) ) ] ,
80+ value : null
81+ } as any )
82+ } else if ( sym . kind == SK . Function || sym . kind == SK . Method ) {
83+ let fd : FunctionDef = {
84+ kind : "FunctionDef" ,
85+ name : sym . name ,
86+ parent : mod ,
87+ args : {
88+ kind : "Arguments" ,
89+ args : [ ] ,
90+ defaults : [ ] ,
91+ kwonlyargs : [ ] ,
92+ kw_defaults : [ ]
93+ } ,
94+ body : [ ] ,
95+ decorator_list : [ ] ,
96+ retType : mapTsType ( sym . retType )
97+ } as any
98+ mod . body . push ( fd )
99+ fd . args . args = sym . parameters . map ( mapTsArg )
100+ } else {
101+ // TODO
102+ }
103+ }
104+ }
105+ return mod
106+ }
107+
39108 let parts = name . split ( "." )
40109 if ( parts . length >= 2 ) {
41110 let last = parts . length - 1
42111 let par = moduleAst [ parts . slice ( 0 , last ) . join ( "." ) ]
43112 let ename = parts [ last ]
44113 if ( par ) {
45- if ( ! par . body ) {
46- par . body = [ ]
47- for ( let sym of par . tsBody ) {
48- // do something
49- }
50- }
51114 for ( let stmt of par . body ) {
52115 if ( stmt . kind == "ClassDef" || stmt . kind == "FunctionDef" ) {
53116 if ( ( stmt as py . FunctionDef ) . name == ename )
@@ -65,9 +128,19 @@ namespace pxt.py {
65128 return null
66129 }
67130
131+ function isModule ( sym : pxtc . SymbolInfo ) {
132+ switch ( sym . kind ) {
133+ case SK . Module :
134+ case SK . Enum :
135+ return true
136+ default :
137+ return false
138+ }
139+ }
140+
68141 function reflectModules ( ) {
69142 for ( let sym of U . values ( apisInfo . byQName ) ) {
70- if ( sym . kind == pxtc . SymbolKind . Module ) {
143+ if ( isModule ( sym ) ) {
71144 let name = sym . qName
72145 moduleAst [ name ] = {
73146 kind : "Module" ,
@@ -80,8 +153,6 @@ namespace pxt.py {
80153 }
81154 }
82155 for ( let sym of U . values ( apisInfo . byQName ) ) {
83- if ( sym . kind == pxtc . SymbolKind . Module )
84- continue
85156 let m = / ( .* ) \. ( .* ) / . exec ( sym . qName )
86157 if ( ! m )
87158 continue
@@ -106,8 +177,18 @@ namespace pxt.py {
106177 return ctx . currModule . name == "main" && ! ctx . currFun && ! ctx . currClass
107178 }
108179
109- function defvar ( n : string , opts : py . VarDescOptions ) {
110- let scopeDef = currentScope ( )
180+ function addImport ( a : AST , name : string , scope ?: ScopeDef ) {
181+ const v = defvar ( name , { isPlainImport : true } , scope )
182+ const sym = lookupSymbol ( name )
183+ if ( ! sym )
184+ error ( a , U . lf ( "No module named '{0}'" , name ) )
185+ else
186+ unify ( a , v . type , mkType ( { moduleType : sym as Module } ) )
187+ return v
188+ }
189+
190+ function defvar ( n : string , opts : py . VarDescOptions , scope ?: ScopeDef ) {
191+ let scopeDef = scope || currentScope ( )
111192 let v = scopeDef . vars [ n ]
112193 if ( ! v ) {
113194 v = scopeDef . vars [ n ] = { type : mkType ( ) , name : n }
@@ -165,6 +246,8 @@ namespace pxt.py {
165246 return t . primType
166247 else if ( t . classType )
167248 return applyTypeMap ( getFullName ( t . classType ) )
249+ else if ( t . moduleType )
250+ return applyTypeMap ( t . moduleType . name )
168251 else if ( t . arrayType )
169252 return t2s ( t . arrayType ) + "[]"
170253 else
@@ -184,6 +267,7 @@ namespace pxt.py {
184267 function typeCtor ( t : Type ) : any {
185268 if ( t . primType ) return t . primType
186269 else if ( t . classType ) return t . classType
270+ else if ( t . moduleType ) return t . moduleType
187271 else if ( t . arrayType ) return "array"
188272 return null
189273 }
@@ -281,6 +365,9 @@ namespace pxt.py {
281365 s = s . parent
282366 } while ( s && s . kind == "ClassDef" )
283367 }
368+ if ( autoImport && lookupSymbol ( n ) ) {
369+ return addImport ( currentScope ( ) , n , ctx . currModule )
370+ }
284371 return null
285372 }
286373
@@ -321,6 +408,15 @@ namespace pxt.py {
321408 }
322409 }
323410
411+ function symbolType ( s : Symbol ) : Type {
412+ if ( s . kind == "Module" || s . kind == "ClassDef" )
413+ return mkType ( { moduleType : s as Module } )
414+ else if ( s . kind == "Assign" )
415+ return typeOf ( ( s as Assign ) . targets [ 0 ] )
416+ else
417+ return mkType ( { } )
418+ }
419+
324420 function scope ( f : ( ) => B . JsNode ) {
325421 const prevCtx = U . flatClone ( ctx )
326422 let r : B . JsNode ;
@@ -830,9 +926,7 @@ namespace pxt.py {
830926 defvar ( nm . asname , {
831927 expandsTo : nm . name
832928 } )
833- defvar ( nm . name , {
834- isPlainImport : true
835- } )
929+ addImport ( n , nm . name )
836930 }
837931 return B . mkText ( "" )
838932 } ,
@@ -1291,6 +1385,15 @@ namespace pxt.py {
12911385 let part = typeOf ( n . value )
12921386 let fd = getTypeField ( part , n . attr )
12931387 if ( fd ) unify ( n , n . tsType , fd . type )
1388+ else if ( part . moduleType ) {
1389+ let sym = lookupSymbol ( part . moduleType . name + "." + n . attr )
1390+ if ( sym )
1391+ unifyTypeOf ( n , symbolType ( sym ) )
1392+ else
1393+ error ( n , U . lf ( "module '{0}' has no attribute '{1}'" , part . moduleType . name , n . attr ) )
1394+ } else {
1395+ error ( n , U . lf ( "unknown object type; cannot lookup attribute '{0}'" , n . attr ) )
1396+ }
12941397 return B . mkInfix ( expr ( n . value ) , "." , B . mkText ( quoteStr ( n . attr ) ) )
12951398 } ,
12961399 Subscript : ( n : py . Subscript ) => {
0 commit comments