@@ -55,6 +55,7 @@ typedef CClass = {> CNamedType,
5555 var ? isInterface : Bool ;
5656 var fields : Map <String ,CField >;
5757 var statics : Map <String ,CField >;
58+ var ? staticClass : TType ;
5859}
5960
6061typedef CField = {
@@ -70,6 +71,7 @@ typedef CField = {
7071
7172typedef CEnum = {> CNamedType ,
7273 var constructors : Array <{ name : String , ? args : Array <{ name : String , opt : Bool , t : TType }> }>;
74+ var ? enumClass : TType ;
7375}
7476
7577typedef CTypedef = {> CNamedType ,
@@ -218,9 +220,19 @@ class CheckerTypes {
218220 cl .fields .set (f .name , f );
219221 }
220222 }
223+ var stc : CClass = {
224+ name : " #" + cl .name ,
225+ fields : [],
226+ statics : [],
227+ params : [],
228+ };
229+ cl .staticClass = TInst (stc ,[]);
221230 for ( f in c .statics ) {
222231 var f = addField (f );
223- if ( f != null ) cl .statics .set (f .name , f );
232+ if ( f != null ) {
233+ cl .statics .set (f .name , f );
234+ stc .fields .set (f .name , f );
235+ }
224236 }
225237 localParams = null ;
226238 });
@@ -231,6 +243,7 @@ class CheckerTypes {
231243 name : e .path ,
232244 params : [],
233245 constructors : [],
246+ enumClass : null ,
234247 };
235248 addMeta (e ,en );
236249 for ( p in e .params )
@@ -240,6 +253,8 @@ class CheckerTypes {
240253 for ( c in e .constructors )
241254 en .constructors .push ({ name : c .name , args : c .args == null ? null : [for ( a in c .args ) { name : a .name , opt : a .opt , t : makeXmlType (a .t ) }] });
242255 localParams = null ;
256+ var ent = TEnum (en ,en .params );
257+ en .enumClass = TType ({ name : " #" + en .name , params : [], t : TAnon ([for ( f in en .constructors ) { name : f .name , t : f .args == null ? ent : TFun (f .args ,ent ), opt : false }]) },[]);
243258 });
244259 types .set (en .name , CTEnum (en ));
245260 case TTypedecl (t ):
@@ -393,6 +408,8 @@ class Checker {
393408 public var allowReturn : Null <TType >;
394409 public var allowGlobalsDefine : Bool ;
395410 public var allowUntypedMeta : Bool ;
411+ public var allowPrivateAccess : Bool ;
412+ public var allowNew : Bool ;
396413
397414 public function new ( ? types ) {
398415 if ( types == null ) types = new CheckerTypes ();
@@ -839,11 +856,16 @@ class Checker {
839856 }
840857
841858 public function abstractCast ( t1 : TType , t2 : TType , e : Expr ) {
859+ var tf1 = follow (t1 );
860+ var tf2 = follow (t2 );
861+ switch ( [tf1 ,tf2 ] ) {
862+ case [TInst (c ,[]),TAbstract (a ,[ct ])] if ( a .name == " Class" && c .name .charCodeAt (0 ) == ' #' .code ):
863+ return tryUnify (types .resolve (c .name .substr (1 )), ct );
864+ default :
865+ }
842866 #if !hscriptPos
843867 return false ;
844868 #else
845- var tf1 = follow (t1 );
846- var tf2 = follow (t2 );
847869 return getAbstractCast (tf1 ,tf2 ,e ,false ) || getAbstractCast (tf2 ,tf1 ,e ,true );
848870 #end
849871 }
@@ -866,7 +888,7 @@ class Checker {
866888 var at = apply (arg .t , s .params , [for ( _ in s .params ) makeMono ()]);
867889 at = apply (at ,a .params ,args );
868890 var acc = mk (null ,e );
869- if ( tryUnify (to ,at ) && resolveGlobal (a .impl .name ,acc ,Value ) != null ) {
891+ if ( tryUnify (to ,at ) && resolveGlobal (a .impl .name ,acc ,Value , false ) != null ) {
870892 e .e = ECall (mk (EField (acc ,s .name ),e ),[mk (e .e ,e )]);
871893 return true ;
872894 }
@@ -1045,7 +1067,7 @@ class Checker {
10451067 return null ;
10461068 }
10471069 var acc = mk (null ,e );
1048- var impl = resolveGlobal (a .impl .name ,acc ,Value );
1070+ var impl = resolveGlobal (a .impl .name ,acc ,Value , false );
10491071 if ( impl == null )
10501072 return null ;
10511073 var t = checkField (cf ,a ,pl ,forWrite ,e );
@@ -1139,10 +1161,44 @@ class Checker {
11391161 return readPath (typeExpr (o , Value ), path , forWrite );
11401162 }
11411163
1164+ function patchStubAccess ( ef : Expr ) {
1165+ #if hscriptPos
1166+ switch ( ef .e ) {
1167+ case EField (e , f ):
1168+ var g = types .resolve (" hscript.Checker" ,[]);
1169+ if ( g == null ) return false ;
1170+ var acc = getTypeAccess (g , e );
1171+ if ( acc == null ) return false ;
1172+ e .e = acc ;
1173+ ef .e = EField (e ," stub_" + f );
1174+ return true ;
1175+ default :
1176+ }
1177+ #end
1178+ return false ;
1179+ }
1180+
11421181 function readPath ( ot : TType , path : Array <{ f : String , e : Expr }>, forWrite ) {
11431182 for ( p in path ) {
11441183 var ft = getField (ot , p .f , p .e , p == path [path .length - 1 ] ? forWrite : false );
11451184 if ( ft == null ) {
1185+ switch ( ot ) {
1186+ case TInst (c , _ ) if ( c .name == " #Std" ):
1187+ // these two methods are extern in HL and we must provide
1188+ // some stubs so they both type and execute
1189+ switch ( p .f ) {
1190+ case " int" :
1191+ if ( patchStubAccess (p .e ) )
1192+ return TFun ([{ name : " value" , opt : false , t : TFloat }],TInt );
1193+ case " downcast" :
1194+ var ct = makeMono ();
1195+ var t = types .resolve (" Class" ,[ct ]);
1196+ if ( t != null && patchStubAccess (p .e ) )
1197+ return TFun ([{ name : " value" , opt : false , t : TDynamic }, { name : " cl" , opt : false , t : t }],ct );
1198+ default :
1199+ }
1200+ default :
1201+ }
11461202 error (typeStr (ot )+ " has no field " + p .f , p .e );
11471203 return TDynamic ;
11481204 }
@@ -1158,7 +1214,7 @@ class Checker {
11581214 path .shift ();
11591215 return readPath (l ,path ,forWrite );
11601216 }
1161- var t = resolveGlobal (root .f ,root .e ,path .length == 1 ? withType : Value );
1217+ var t = resolveGlobal (root .f ,root .e ,path .length == 1 ? withType : Value , forWrite && path . length == 1 );
11621218 if ( t != null ) {
11631219 path .shift ();
11641220 return readPath (t ,path ,forWrite );
@@ -1167,7 +1223,7 @@ class Checker {
11671223 while ( path .length > 1 ) {
11681224 var name = [for ( p in path ) p .f ].join (" ." );
11691225 var union = punion (path [0 ].e ,path [path .length - 1 ].e );
1170- var t = resolveGlobal (name , union , Value );
1226+ var t = resolveGlobal (name , union , Value , forWrite && fields . length == 0 );
11711227 if ( t != null ) {
11721228 #if hscriptPos
11731229 if ( union .e != null ) path [path .length - 1 ].e .e = union .e ;
@@ -1188,7 +1244,7 @@ class Checker {
11881244 return false ;
11891245 }
11901246
1191- function resolveGlobal ( name : String , expr : Expr , withType : WithType ) : TType {
1247+ function resolveGlobal ( name : String , expr : Expr , withType : WithType , forWrite : Bool ) : TType {
11921248 var g = globals .get (name );
11931249 if ( g != null ) {
11941250 return switch ( g ) {
@@ -1257,7 +1313,7 @@ class Checker {
12571313 var acc = getTypeAccess (g , expr , name );
12581314 if ( acc != null ) {
12591315 expr .e = acc ;
1260- return apply ( f . t , f . params , [for ( a in f .params ) makeMono ()]);
1316+ return checkField ( f , c , [for ( a in f .params ) makeMono ()], forWrite , expr );
12611317 }
12621318 }
12631319 default :
@@ -1270,10 +1326,10 @@ class Checker {
12701326 if ( acc != null ) {
12711327 expr .e = acc ;
12721328 switch ( t ) {
1273- case TInst (c ,_ ):
1274- return TType ({ name : " # " + c . name , params : [], t : TAnon ([ for ( f in c . statics ) { name : f . name , t : f . t , opt : false }]) },[]) ;
1329+ case TInst (c ,_ ) if ( c . staticClass != null ) :
1330+ return c . staticClass ;
12751331 case TEnum (e ,_ ):
1276- return TType ({ name : " # " + e . name , params : [], t : TAnon ([ for ( f in e . constructors ) { name : f . name , t : f . args == null ? t : TFun ( f . args , t ), opt : false }]) },[]) ;
1332+ return e . enumClass ;
12771333 default :
12781334 throw " assert" ;
12791335 }
@@ -1288,6 +1344,21 @@ class Checker {
12881344 return null ;
12891345 }
12901346
1347+ function unifyCallParams ( args : Array <{ name : String , opt : Bool , t : TType }>, params : Array <Expr >, pos : Expr ) {
1348+ for ( i in 0 ... params .length ) {
1349+ var a = args [i ];
1350+ if ( a == null ) {
1351+ error (" Too many arguments" , params [i ]);
1352+ break ;
1353+ }
1354+ var t = typeExpr (params [i ], a == null ? Value : WithType (a .t ));
1355+ unify (t , a .t , params [i ]);
1356+ }
1357+ for ( i in params .length ... args .length )
1358+ if ( ! args [i ].opt )
1359+ error (" Missing argument " + args [i ].name + " :" + typeStr (args [i ].t ), pos );
1360+ }
1361+
12911362 function typeExpr ( expr : Expr , withType : WithType ) : TType {
12921363 if ( expr == null && isCompletion )
12931364 return switch ( withType ) {
@@ -1349,18 +1420,7 @@ class Checker {
13491420 callExpr = prev ;
13501421 switch ( follow (ft ) ) {
13511422 case TFun (args , ret ):
1352- for ( i in 0 ... params .length ) {
1353- var a = args [i ];
1354- if ( a == null ) {
1355- error (" Too many arguments" , params [i ]);
1356- break ;
1357- }
1358- var t = typeExpr (params [i ], a == null ? Value : WithType (a .t ));
1359- unify (t , a .t , params [i ]);
1360- }
1361- for ( i in params .length ... args .length )
1362- if ( ! args [i ].opt )
1363- error (" Missing argument " + args [i ].name + " :" + typeStr (args [i ].t ), expr );
1423+ unifyCallParams (args , params , expr );
13641424 return ret ;
13651425 case TDynamic :
13661426 for ( p in params ) typeExpr (p ,Value );
@@ -1683,6 +1743,24 @@ class Checker {
16831743 var et = typeExpr (e , Value );
16841744 return t == null ? makeMono () : makeType (t ,expr );
16851745 case ENew (cl , params ):
1746+ if ( ! allowNew ) error (" 'new' is not allowed" , expr );
1747+ var t = types .resolve (cl );
1748+ if ( t == null ) error (" Unknown class " + cl , expr );
1749+ switch ( t ) {
1750+ case TInst (c ,_ ) if ( c .constructor != null ):
1751+ switch ( c .constructor .t ) {
1752+ case TFun (args , _ ):
1753+ var ms = [for ( c in c .params ) makeMono ()];
1754+ var mf = [for ( c in c .constructor .params ) makeMono ()];
1755+ var args = [for ( a in args ) { name : a .name , opt : a .opt , t : apply (apply (a .t ,c .params ,ms ),c .constructor .params ,mf ) }];
1756+ unifyCallParams (args , params , expr );
1757+ return TInst (c , ms );
1758+ default :
1759+ throw " assert" ;
1760+ }
1761+ default :
1762+ error (typeStr (t )+ " cannot be constructed" , expr );
1763+ }
16861764 }
16871765 error (" Don't know how to type " + edef (expr ).getName (), expr );
16881766 return TDynamic ;
@@ -1691,6 +1769,13 @@ class Checker {
16911769 function checkMeta ( m : String , args : Array <Expr >, next : Expr , expr : Expr , withType ) {
16921770 if ( m == " :untyped" && allowUntypedMeta )
16931771 return makeMono ();
1772+ if ( m == " :privateAccess" && allowPrivateAccess ) {
1773+ var prev = checkPrivate ;
1774+ checkPrivate = false ;
1775+ var t = typeExpr (next , withType );
1776+ checkPrivate = prev ;
1777+ return t ;
1778+ }
16941779 return typeExpr (next , withType );
16951780 }
16961781
@@ -1750,5 +1835,7 @@ class Checker {
17501835 return { key : key , value : value };
17511836 }
17521837
1838+ static function stub_int ( v : Float ) return Std .int (v );
1839+ static function stub_downcast ( v : Dynamic , cl : Dynamic ) return Std .downcast (v , cl );
17531840
17541841}
0 commit comments