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