Skip to content

Commit 235097f

Browse files
committed
Merge branch 'master' into dev-ci-multihaxe
2 parents ab46220 + a4520c2 commit 235097f

File tree

2 files changed

+148
-40
lines changed

2 files changed

+148
-40
lines changed

hscript/Checker.hx

Lines changed: 111 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

6061
typedef CField = {
@@ -70,6 +71,7 @@ typedef CField = {
7071

7172
typedef CEnum = {> CNamedType,
7273
var constructors : Array<{ name : String, ?args : Array<{ name : String, opt : Bool, t : TType }> }>;
74+
var ?enumClass : TType;
7375
}
7476

7577
typedef 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
}

hscript/Parser.hx

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -457,24 +457,45 @@ class Parser {
457457
if( #if hscriptPos tokens.length != 0 #else !tokens.isEmpty() #end )
458458
throw "assert";
459459
if( readPos == start + ident.length + 1 ) {
460+
var startTag = "<"+ident;
460461
var endTag = "</"+ident+">";
461-
var end = input.indexOf(endTag, readPos);
462-
if( end < 0 ) {
463-
endTag = '/>';
464-
end = input.indexOf(endTag, readPos);
465-
}
466-
if( end >= 0 ) {
467-
readPos = end + endTag.length;
468-
char = -1;
469-
start--;
470-
var end = readPos - 1;
471-
#if hscriptPos
472-
tokenMin = start + offset;
473-
tokenMax = end + offset;
474-
#end
475-
var str = input.substr(start,end - start + 1);
476-
return mk(EMeta(":markup",[],mk(EConst(CString(str)))));
462+
var endTag2 = "/>";
463+
var end = -1;
464+
var count = 1, curPos = readPos;
465+
var r_nextTag = ~/<[A-Za-z0-9_]+/;
466+
while( count > 0 ) {
467+
end = input.indexOf(endTag, curPos + 1);
468+
if( end >= 0 )
469+
end += endTag.length;
470+
var end2 = input.indexOf(endTag2, curPos + 1);
471+
if( end2 > 0 && (end < 0 || end2 < end) ) {
472+
var nextTag = -1;
473+
if( r_nextTag.matchSub(input, curPos+1) )
474+
nextTag = r_nextTag.matchedPos().pos;
475+
if( nextTag < 0 || end2 < nextTag )
476+
end = end2 + endTag2.length;
477+
}
478+
if( end < 0 )
479+
error(ECustom("Unclosed "+startTag+">"), curPos, curPos + startTag.length + 1);
480+
var prev = input.indexOf(startTag, curPos + 1);
481+
if( prev < 0 || prev > end ) {
482+
count--;
483+
curPos = end - 1;
484+
} else {
485+
count++;
486+
curPos = prev;
487+
}
477488
}
489+
readPos = end;
490+
char = -1;
491+
start--;
492+
var end = readPos - 1;
493+
#if hscriptPos
494+
tokenMin = start + offset;
495+
tokenMax = end + offset;
496+
#end
497+
var str = input.substr(start,end - start + 1);
498+
return mk(EMeta(":markup",[],mk(EConst(CString(str)))));
478499
}
479500
}
480501
return unexpected(tk);

0 commit comments

Comments
 (0)