diff --git a/hscript/Bytes.hx b/hscript/Bytes.hx index dd69069..5bec616 100644 --- a/hscript/Bytes.hx +++ b/hscript/Bytes.hx @@ -124,10 +124,13 @@ class Bytes { #end bout.addByte(Type.enumIndex(e)); switch( e ) { + case EIgnore(_): case EImport(c): // TODO case EClass(_, _, _, _): // TODO + case ERedirect(_, _): + // TODO case EConst(c): doEncodeConst(c); case EIdent(v): diff --git a/hscript/Expr.hx b/hscript/Expr.hx index 836baaf..5190cdd 100644 --- a/hscript/Expr.hx +++ b/hscript/Expr.hx @@ -51,6 +51,7 @@ enum ExprDef { typedef ExprDef = Expr; enum Expr { #end + EIgnore(skip:Bool); EConst( c : Const ); EIdent( v : String ); EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool ); @@ -81,6 +82,7 @@ enum Expr { EImport( c : String, ?asname:String ); EClass( name:String, fields:Array, ?extend:String, interfaces:Array, ?isFinal:Bool, ?isPrivate:Bool ); + ERedirect( name:String, className:String, ?cl:Class ); } @:structInit diff --git a/hscript/Interp.hx b/hscript/Interp.hx index 203039d..1fe23f3 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -772,6 +772,7 @@ class Interp { var e = e.e; #end switch (e) { + case EIgnore(_): case EClass(name, fields, extend, interfaces): //Not sure if leave the old system or implement the new one. if (customClasses.exists(name)) error(EAlreadyExistingClass(name)); @@ -854,7 +855,11 @@ class Interp { } return null; - + case ERedirect(n, cln, cl): + if(cl != null) { + setVar(n, cl); + } + localImportRedirects.set(n, cln); case EConst(c): switch (c) { case CInt(v): return v; @@ -1644,8 +1649,8 @@ class Interp { } customClassDecl.cacheFields(); registerCustomClass(customClassDecl, as); - case DTypedef(_): - //TODO: maybe make this work :3 + case DTypedef(td): + // TODO: put this work } } } diff --git a/hscript/Parser.hx b/hscript/Parser.hx index fb752da..b4607b4 100644 --- a/hscript/Parser.hx +++ b/hscript/Parser.hx @@ -1033,7 +1033,39 @@ class Parser { var tk = token(); push(tk); mk(EClass(name, fields, extend, interfaces, nextIsFinal, nextIsPrivate), p1); + case "typedef": + var name = getIdent(); + ensureToken(TOp("=")); + + var t = parseType(); + + switch(t) { + case CTAnon(_) | CTFun(_): + mk(EIgnore(true)); + case CTPath(path, params): + if (params != null && params.length > 1) + error(ECustom("Typedefs can't have parameters"), tokenMin, tokenMax); + + if (path.length == 0) + error(ECustom("Typedefs can't be empty"), tokenMin, tokenMax); + + var className = path.join("."); + var cl = Tools.getClass(className); + if(cl != null) + return mk(ERedirect(name, className, cl)); + + var expr = mk(EIdent(path.shift())); + while (path.length > 0) { + expr = mk(EField(expr, path.shift(), false)); + } + + // todo? add import to the beginning of the file? + mk(EVar(name, null, expr)); + default: + error(ECustom("Typedef, unknown type " + t), tokenMin, tokenMax); + null; + } case "return": var tk = token(); push(tk); diff --git a/hscript/Printer.hx b/hscript/Printer.hx index 8e464c2..63491ff 100644 --- a/hscript/Printer.hx +++ b/hscript/Printer.hx @@ -113,7 +113,8 @@ class Printer { add("??NULL??"); return; } - switch( #if hscriptPos e.e #else e #end ) { + switch( Tools.expr(e) ) { + case EIgnore(_): case EImport(c, n): add("import " + c); if(n != null) @@ -133,6 +134,8 @@ class Printer { tabs = tabs.substr(1); add("}"); + case ERedirect(n, cl): + add('typedef $n = $cl'); case EConst(c): switch( c ) { case CInt(i): add(i); diff --git a/hscript/Tools.hx b/hscript/Tools.hx index 492f66b..0d9e806 100644 --- a/hscript/Tools.hx +++ b/hscript/Tools.hx @@ -59,7 +59,7 @@ class Tools { if( def != null ) f(def); case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e); case ECheckType(e,_): f(e); - + default: } } @@ -91,6 +91,7 @@ class Tools { case ECheckType(e,t): ECheckType(f(e), t); case EImport(c): EImport(c); case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces); + default: #if hscriptPos e.e #else e #end; } return mk(edef, e); } @@ -111,4 +112,36 @@ class Tools { #end } + public static function removeInnerClass(name: String): String { + var ll = name.lastIndexOf("."); + if (name.indexOf(".") != ll) { // checks if there are 2 or more dots + // wtf did i make -neo + // this is awesome -crow + return name.substr(0, name.lastIndexOf(".", ll - 1)) + "." + name.substr(ll + 1); + } + // only one dot or no dots (will work since -1 + 1 = 0) + return name.substr(ll + 1); + } + + public static function getClass(name: String): Dynamic { + var c: Dynamic = Type.resolveClass(name); + if (c == null) // try importing as enum + try + c = Type.resolveEnum(name); + + if (c == null) { + // lastly try removing any inner class from it + // this allows you to import stuff like + // flixel.text.FlxText.FlxTextBorderStyle + // without the script crashing immediately + var className = removeInnerClass(name); + if (className != name) { + c = Type.resolveClass(className); + if (c == null) + c = Type.resolveEnum(className); + } + } + return c; + } + } \ No newline at end of file