Added inferred map types and bypassAccessor

This commit is contained in:
NeeEoo
2023-03-19 05:26:27 +01:00
parent c1a36a3f4b
commit 4f9b449c6e
5 changed files with 219 additions and 161 deletions
+1 -1
View File
@@ -60,7 +60,7 @@ enum Expr {
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool); EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool);
EReturn( ?e : Expr ); EReturn( ?e : Expr );
EArray( e : Expr, index : Expr ); EArray( e : Expr, index : Expr );
EArrayDecl( e : Array<Expr> ); EArrayDecl( e : Array<Expr>, ?wantedType: CType);
ENew( cl : String, params : Array<Expr> ); ENew( cl : String, params : Array<Expr> );
EThrow( e : Expr ); EThrow( e : Expr );
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr ); ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
+67 -14
View File
@@ -23,6 +23,8 @@
/* /*
* YoshiCrafter Engine fixes: * YoshiCrafter Engine fixes:
* - Added Error handler * - Added Error handler
* - Added Imports
* - Added @:bypassAccessor
*/ */
package hscript; package hscript;
@@ -69,6 +71,8 @@ class Interp {
var declared:Array<{n:String, old:{r:Dynamic, depth:Int}, depth:Int}>; var declared:Array<{n:String, old:{r:Dynamic, depth:Int}, depth:Int}>;
var returnValue:Dynamic; var returnValue:Dynamic;
var isBypassAccessor:Bool = false;
public var importEnabled:Bool = true; public var importEnabled:Bool = true;
public var allowStaticVariables:Bool = false; public var allowStaticVariables:Bool = false;
@@ -355,7 +359,7 @@ class Interp {
} catch(e:Error) { } catch(e:Error) {
if (errorHandler != null) if (errorHandler != null)
errorHandler(e); errorHandler(e);
else else
throw e; throw e;
return null; return null;
} catch(e) { } catch(e) {
@@ -431,7 +435,6 @@ class Interp {
} }
if (doException) if (doException)
error(EUnknownVariable(id)); error(EUnknownVariable(id));
} }
return v; return v;
} }
@@ -449,7 +452,7 @@ class Interp {
var realClassName = splitClassName.join("."); var realClassName = splitClassName.join(".");
if (importBlocklist.contains(realClassName)) if (importBlocklist.contains(realClassName))
return null; return null;
var cl = Type.resolveClass(realClassName); var cl = Type.resolveClass(realClassName);
if (cl == null) if (cl == null)
cl = Type.resolveClass('${realClassName}_HSC'); cl = Type.resolveClass('${realClassName}_HSC');
@@ -464,7 +467,15 @@ class Interp {
// ENUM!!!! // ENUM!!!!
var enumThingy = {}; var enumThingy = {};
for (c in en.getConstructors()) { for (c in en.getConstructors()) {
Reflect.setField(enumThingy, c, en.createByName(c)); try {
Reflect.setField(enumThingy, c, en.createByName(c));
} catch(e) {
try {
Reflect.setField(enumThingy, c, Reflect.field(en, c));
} catch(ex) {
throw e;
}
}
} }
variables.set(splitClassName[splitClassName.length - 1], enumThingy); variables.set(splitClassName[splitClassName.length - 1], enumThingy);
} else { } else {
@@ -488,7 +499,8 @@ class Interp {
case EVar(n, _, e, isPublic, isStatic): case EVar(n, _, e, isPublic, isStatic):
declared.push({n: n, old: locals.get(n), depth: depth}); declared.push({n: n, old: locals.get(n), depth: depth});
locals.set(n, {r: (e == null) ? null : expr(e), depth: depth}); locals.set(n, {r: (e == null) ? null : expr(e), depth: depth});
if (depth == 0) (isStatic == true ? staticVariables : (isPublic ? publicVariables : variables)).set(n, locals[n].r); if (depth == 0)
(isStatic == true ? staticVariables : (isPublic ? publicVariables : variables)).set(n, locals[n].r);
return null; return null;
case EParent(e): case EParent(e):
return expr(e); return expr(e);
@@ -634,8 +646,16 @@ class Interp {
} }
} }
return f; return f;
case EArrayDecl(arr): case EArrayDecl(arr, wantedType):
if (arr.length > 0 && Tools.expr(arr[0]).match(EBinop("=>", _))) { var isMap = false;
var isTypeMap = false;
if(!isMap && wantedType != null) {
isMap = wantedType.match(CTPath(["Map"], [_, _]));
isTypeMap = true;
} else {
isMap = arr.length > 0 && Tools.expr(arr[0]).match(EBinop("=>", _));
}
if (isMap) {
var isAllString:Bool = true; var isAllString:Bool = true;
var isAllInt:Bool = true; var isAllInt:Bool = true;
var isAllObject:Bool = true; var isAllObject:Bool = true;
@@ -657,6 +677,22 @@ class Interp {
default: throw("=> expected"); default: throw("=> expected");
} }
} }
if(isTypeMap) {
if(wantedType != null) {
isAllString = wantedType.match(CTPath(["Map"], [CTPath(["String"], _), _]));
isAllInt = wantedType.match(CTPath(["Map"], [CTPath(["Int"], _), _]));
if(isAllString || isAllInt) {
isAllObject = false;
isAllEnum = false;
} else {
if(!isAllObject && !isAllEnum) {
throw("Unknown Type Key");
}
}
}
}
var map:Dynamic = { var map:Dynamic = {
if (isAllInt) if (isAllInt)
new haxe.ds.IntMap<Dynamic>(); new haxe.ds.IntMap<Dynamic>();
@@ -742,8 +778,15 @@ class Interp {
if (!match) if (!match)
val = def == null ? null : expr(def); val = def == null ? null : expr(def);
return val; return val;
case EMeta(_, _, e): case EMeta(a, b, e):
return expr(e); var oldAccessor = isBypassAccessor;
if(a == ":bypassAccessor") {
isBypassAccessor = true;
}
var val = expr(e);
isBypassAccessor = oldAccessor;
return val;
case ECheckType(e, _): case ECheckType(e, _):
return expr(e); return expr(e);
} }
@@ -860,8 +903,15 @@ class Interp {
return obj.hget(f); return obj.hget(f);
} else { } else {
var v = null; var v = null;
if ((v = Reflect.getProperty(o, f)) == null) if(isBypassAccessor) {
v = Reflect.getProperty(Type.getClass(o), f); if ((v = Reflect.field(o, f)) == null)
v = Reflect.field(Type.getClass(o), f);
}
if(v == null) {
if ((v = Reflect.getProperty(o, f)) == null)
v = Reflect.getProperty(Type.getClass(o), f);
}
return v; return v;
} }
} }
@@ -889,9 +939,12 @@ class Interp {
else if (o is IHScriptCustomBehaviour) { else if (o is IHScriptCustomBehaviour) {
var obj = cast(o, IHScriptCustomBehaviour); var obj = cast(o, IHScriptCustomBehaviour);
return obj.hset(f, v); return obj.hset(f, v);
} }
if(isBypassAccessor) {
Reflect.setProperty(o, f, v); Reflect.setField(o, f, v);
} else {
Reflect.setProperty(o, f, v);
}
return v; return v;
} }
+71 -66
View File
@@ -275,19 +275,19 @@ class Parser {
function isBlock(e) { function isBlock(e) {
if( e == null ) return false; if( e == null ) return false;
return switch( expr(e) ) { return switch( expr(e) ) {
case EBlock(_), EObject(_), ESwitch(_): true; case EBlock(_), EObject(_), ESwitch(_): true;
case EFunction(_,e,_,_,_,_): isBlock(e); case EFunction(_,e,_,_,_,_): isBlock(e);
case EVar(_, t, e, _,_): e != null ? isBlock(e) : t != null ? t.match(CTAnon(_)) : false; case EVar(_, t, e, _,_): e != null ? isBlock(e) : t != null ? t.match(CTAnon(_)) : false;
case EIf(_,e1,e2): if( e2 != null ) isBlock(e2) else isBlock(e1); case EIf(_,e1,e2): if( e2 != null ) isBlock(e2) else isBlock(e1);
case EBinop(_,_,e): isBlock(e); case EBinop(_,_,e): isBlock(e);
case EUnop(_,prefix,e): !prefix && isBlock(e); case EUnop(_,prefix,e): !prefix && isBlock(e);
case EWhile(_,e): isBlock(e); case EWhile(_,e): isBlock(e);
case EDoWhile(_,e): isBlock(e); case EDoWhile(_,e): isBlock(e);
case EFor(_,_,e): isBlock(e); case EFor(_,_,e): isBlock(e);
case EReturn(e): e != null && isBlock(e); case EReturn(e): e != null && isBlock(e);
case ETry(_, _, _, e): isBlock(e); case ETry(_, _, _, e): isBlock(e);
case EMeta(_, _, e): isBlock(e); case EMeta(_, _, e): isBlock(e);
default: false; default: false;
} }
} }
@@ -318,29 +318,29 @@ class Parser {
var tk = token(); var tk = token();
var id = null; var id = null;
switch( tk ) { switch( tk ) {
case TId(i): id = i; case TId(i): id = i;
case TConst(c): case TConst(c):
if( !allowJSON ) if( !allowJSON )
unexpected(tk);
switch( c ) {
case CString(s): id = s;
default: unexpected(tk);
}
case TBrClose:
break;
default:
unexpected(tk); unexpected(tk);
switch( c ) { break;
case CString(s): id = s;
default: unexpected(tk);
}
case TBrClose:
break;
default:
unexpected(tk);
break;
} }
ensure(TDoubleDot); ensure(TDoubleDot);
fl.push({ name : id, e : parseExpr() }); fl.push({ name : id, e : parseExpr() });
tk = token(); tk = token();
switch( tk ) { switch( tk ) {
case TBrClose: case TBrClose:
break; break;
case TComma: case TComma:
default: default:
unexpected(tk); unexpected(tk);
} }
} }
return parseExprNext(mk(EObject(fl),p1)); return parseExprNext(mk(EObject(fl),p1));
@@ -372,27 +372,27 @@ class Parser {
var e = parseExpr(); var e = parseExpr();
tk = token(); tk = token();
switch( tk ) { switch( tk ) {
case TPClose:
return parseExprNext(mk(EParent(e),p1,tokenMax));
case TDoubleDot:
var t = parseType();
tk = token();
switch( tk ) {
case TPClose: case TPClose:
return parseExprNext(mk(ECheckType(e,t),p1,tokenMax)); return parseExprNext(mk(EParent(e),p1,tokenMax));
case TDoubleDot:
var t = parseType();
tk = token();
switch( tk ) {
case TPClose:
return parseExprNext(mk(ECheckType(e,t),p1,tokenMax));
case TComma:
switch( expr(e) ) {
case EIdent(v): return parseLambda([{ name : v, t : t }], pmin(e));
default:
}
default:
}
case TComma: case TComma:
switch( expr(e) ) { switch( expr(e) ) {
case EIdent(v): return parseLambda([{ name : v, t : t }], pmin(e)); case EIdent(v): return parseLambda([{name:v}], pmin(e));
default: default:
} }
default: default:
}
case TComma:
switch( expr(e) ) {
case EIdent(v): return parseLambda([{name:v}], pmin(e));
default:
}
default:
} }
return unexpected(tk); return unexpected(tk);
case TBrOpen: case TBrOpen:
@@ -417,9 +417,9 @@ class Parser {
push(tk2); push(tk2);
push(tk); push(tk);
switch( tk2 ) { switch( tk2 ) {
case TDoubleDot: case TDoubleDot:
return parseExprNext(parseObject(p1)); return parseExprNext(parseObject(p1));
default: default:
} }
default: default:
push(tk); push(tk);
@@ -445,12 +445,12 @@ class Parser {
if( e == null ) if( e == null )
return makeUnop(op,e); return makeUnop(op,e);
switch( expr(e) ) { switch( expr(e) ) {
case EConst(CInt(i)): case EConst(CInt(i)):
return mk(EConst(CInt(-i)), start, pmax(e)); return mk(EConst(CInt(-i)), start, pmax(e));
case EConst(CFloat(f)): case EConst(CFloat(f)):
return mk(EConst(CFloat(-f)), start, pmax(e)); return mk(EConst(CFloat(-f)), start, pmax(e));
default: default:
return makeUnop(op,e); return makeUnop(op,e);
} }
} }
if( opPriority.get(op) < 0 ) if( opPriority.get(op) < 0 )
@@ -466,19 +466,19 @@ class Parser {
if( tk == TComma ) if( tk == TComma )
tk = token(); tk = token();
} }
if( a.length == 1 && a[0] != null ) if( a.length == 1 && a[0] != null ) // What is this for???
switch( expr(a[0]) ) { switch( expr(a[0]) ) {
case EFor(_), EWhile(_), EDoWhile(_): case EFor(_), EWhile(_), EDoWhile(_):
var tmp = "__a_" + (uid++); var tmp = "__a_" + (uid++);
var e = mk(EBlock([ var e = mk(EBlock([
mk(EVar(tmp, null, mk(EArrayDecl([]), p1)), p1), mk(EVar(tmp, null, mk(EArrayDecl([]), p1)), p1),
mapCompr(tmp, a[0]), mapCompr(tmp, a[0]),
mk(EIdent(tmp),p1), mk(EIdent(tmp),p1),
]),p1); ]),p1);
return parseExprNext(e); return parseExprNext(e);
default: default:
} }
return parseExprNext(mk(EArrayDecl(a), p1)); return parseExprNext(mk(EArrayDecl(a, nextType), p1));
case TMeta(id) if( allowMetadata ): case TMeta(id) if( allowMetadata ):
var args = parseMetaArgs(); var args = parseMetaArgs();
return mk(EMeta(id, args, parseExpr()),p1); return mk(EMeta(id, args, parseExpr()),p1);
@@ -583,6 +583,7 @@ class Parser {
var nextIsStatic:Bool = false; var nextIsStatic:Bool = false;
var nextIsPublic:Bool = false; var nextIsPublic:Bool = false;
var nextType:CType = null;
function parseStructure(id, ?oldPos:Int) { function parseStructure(id, ?oldPos:Int) {
#if hscriptPos #if hscriptPos
var p1 = tokenMin; var p1 = tokenMin;
@@ -653,15 +654,19 @@ class Parser {
var ident = getIdent(); var ident = getIdent();
var tk = token(); var tk = token();
var t = null; var t = null;
nextType = null;
if( tk == TDoubleDot && allowTypes ) { if( tk == TDoubleDot && allowTypes ) {
t = parseType(); t = parseType();
tk = token(); tk = token();
nextType = t;
} }
var e = null; var e = null;
if( Type.enumEq(tk,TOp("=")) ) if( Type.enumEq(tk,TOp("=")) )
e = parseExpr(); e = parseExpr();
else else
push(tk); push(tk);
nextType = null;
mk(EVar(ident,t,e,nextIsPublic,nextIsStatic),p1,(e == null) ? tokenMax : pmax(e)); mk(EVar(ident,t,e,nextIsPublic,nextIsStatic),p1,(e == null) ? tokenMax : pmax(e));
case "while": case "while":
var econd = parseExpr(); var econd = parseExpr();
+1 -1
View File
@@ -236,7 +236,7 @@ class Printer {
add("["); add("[");
expr(index); expr(index);
add("]"); add("]");
case EArrayDecl(el): case EArrayDecl(el, _):
add("["); add("[");
var first = true; var first = true;
for( e in el ) { for( e in el ) {
+79 -79
View File
@@ -11,95 +11,95 @@ import haxe.macro.Compiler;
using StringTools; using StringTools;
class UsingHandler { class UsingHandler {
public var usedClass:Class<Dynamic>; public var usedClass:Class<Dynamic>;
public var className:String; public var className:String;
public function new(className:String, usedClass:Class<Dynamic>) { public function new(className:String, usedClass:Class<Dynamic>) {
this.className = className; this.className = className;
this.usedClass = usedClass; this.usedClass = usedClass;
} }
public static function init() { public static function init() {
Compiler.addGlobalMetadata('flixel', '@:build(hscript.UsingHandler.build())'); Compiler.addGlobalMetadata('flixel', '@:build(hscript.UsingHandler.build())');
Compiler.addGlobalMetadata('openfl.display.BlendMode', '@:build(hscript.UsingHandler.build())'); Compiler.addGlobalMetadata('openfl.display.BlendMode', '@:build(hscript.UsingHandler.build())');
} }
public static function build():Array<Field> { public static function build():Array<Field> {
var fields = Context.getBuildFields(); var fields = Context.getBuildFields();
var clRef = Context.getLocalClass(); var clRef = Context.getLocalClass();
if (clRef == null) return fields; if (clRef == null) return fields;
var cl = clRef.get(); var cl = clRef.get();
if (/* cl.name.startsWith("Flx") && */ cl.name.endsWith("_Impl_") && cl.params.length <= 0 && !cl.meta.has(":multiType")) { if (/* cl.name.startsWith("Flx") && */ cl.name.endsWith("_Impl_") && cl.params.length <= 0 && !cl.meta.has(":multiType")) {
var metas = cl.meta.get(); var metas = cl.meta.get();
var shadowClass = macro class { var shadowClass = macro class {
}; };
shadowClass.params = switch(cl.params.length) { shadowClass.params = switch(cl.params.length) {
case 0: case 0:
null; null;
case 1: case 1:
[ [
{ {
name: "T", name: "T",
} }
]; ];
default: default:
[for(k=>e in cl.params) { [for(k=>e in cl.params) {
name: "T" + Std.int(k+1) name: "T" + Std.int(k+1)
}]; }];
}; };
shadowClass.name = '${cl.name.substr(0, cl.name.length - 6)}_HSC'; shadowClass.name = '${cl.name.substr(0, cl.name.length - 6)}_HSC';
for(f in fields) for(f in fields)
switch(f.kind) { switch(f.kind) {
case FFun(fun): case FFun(fun):
if (f.access.contains(AStatic)) { if (f.access.contains(AStatic)) {
if (fun.expr != null) if (fun.expr != null)
shadowClass.fields.push(f); shadowClass.fields.push(f);
} }
case FProp(get, set, t, e): case FProp(get, set, t, e):
if (get == "default" && (set == "never" || set == "null")) if (get == "default" && (set == "never" || set == "null"))
shadowClass.fields.push(f); shadowClass.fields.push(f);
case FVar(t, e): case FVar(t, e):
if (f.access.contains(AStatic) || cl.meta.has(":enum") || f.name.toUpperCase() == f.name) { if (f.access.contains(AStatic) || cl.meta.has(":enum") || f.name.toUpperCase() == f.name) {
var name:String = f.name; var name:String = f.name;
var enumType:String = cl.name; var enumType:String = cl.name;
var pack = cl.module.split("."); var pack = cl.module.split(".");
pack.pop(); pack.pop();
var complexType:ComplexType = t != null ? t : (name.contains("REGEX") ? TPath({ var complexType:ComplexType = t != null ? t : (name.contains("REGEX") ? TPath({
name: "EReg", name: "EReg",
pack: [] pack: []
}) : TPath({ }) : TPath({
name: cl.name.substr(0, cl.name.length - 6), name: cl.name.substr(0, cl.name.length - 6),
pack: pack})); pack: pack}));
var field:Field = { var field:Field = {
pos: f.pos, pos: f.pos,
name: f.name, name: f.name,
meta: f.meta, meta: f.meta,
kind: FVar(complexType, { kind: FVar(complexType, {
pos: Context.currentPos(), pos: Context.currentPos(),
expr: ECast(e, complexType) expr: ECast(e, complexType)
}), }),
doc: f.doc, doc: f.doc,
access: [APublic, AStatic] access: [APublic, AStatic]
} }
shadowClass.fields.push(field); shadowClass.fields.push(field);
} }
default: default:
} }
Context.defineModule(cl.module, [shadowClass], Context.getLocalImports()); Context.defineModule(cl.module, [shadowClass], Context.getLocalImports());
} }
return fields; return fields;
} }
} }
#else #else
class UsingHandler { class UsingHandler {
public var usedClass:Class<Dynamic>; public var usedClass:Class<Dynamic>;
public var className:String; public var className:String;
} }
#end #end