Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67bb4bab98 | ||
|
|
927f771024 | ||
|
|
8221dca2b0 | ||
|
|
4c218116a6 | ||
|
|
fc15dbd382 | ||
|
|
bb3785c53c | ||
|
|
1892f0793f |
@@ -1,4 +1,5 @@
|
||||
--macro keep('IntIterator')
|
||||
--macro hscript.macros.UsingHandler.init()
|
||||
--macro hscript.macros.ClassExtendMacro.init()
|
||||
--macro hscript.macros.AbstractHandler.init()
|
||||
--define HSCRIPT_NEW
|
||||
|
||||
@@ -0,0 +1,678 @@
|
||||
package hscript;
|
||||
|
||||
import hscript.Expr;
|
||||
import hscript.Error;
|
||||
import hscript.Tools;
|
||||
import hscript.Parser;
|
||||
|
||||
enum AVarType {
|
||||
VUnknown;
|
||||
VVar(name:String, type:ADeclType);
|
||||
}
|
||||
|
||||
typedef ATypeInfo = {
|
||||
impl: String,
|
||||
cl: Class<Any>,
|
||||
type: AType,
|
||||
}
|
||||
|
||||
enum AType {
|
||||
TUnknown;
|
||||
TBasic(name:String);
|
||||
TAbstract(type:Class<Any>, impl:String);
|
||||
}
|
||||
|
||||
@:structInit
|
||||
class ADeclVar {
|
||||
public var name:String;
|
||||
public var type:AVarType;
|
||||
public var depth:Int;
|
||||
|
||||
public function toString():String {
|
||||
return "var " + name + " : " + type + " @ " + depth;
|
||||
}
|
||||
}
|
||||
|
||||
@:structInit
|
||||
class ADeclType {
|
||||
public var name:String;
|
||||
public var inf:ATypeInfo;
|
||||
public var depth:Int;
|
||||
|
||||
public function toString():String {
|
||||
return "type " + name + " : " + inf.type + " @ " + depth;
|
||||
}
|
||||
}
|
||||
|
||||
typedef AbstractData = {
|
||||
var impl:String;
|
||||
var funcs:Array<Array<Dynamic>>;
|
||||
var props:Array<Array<String>>;
|
||||
}
|
||||
|
||||
@:access(hscript.Parser)
|
||||
class AbstractProcessor {
|
||||
static inline function expr(e:Expr) return Tools.expr(e);
|
||||
|
||||
private static var importStackName:Array<String> = [];
|
||||
private static var importStackMode:Array<KImportMode> = [];
|
||||
private static function addImport(e:String, mode:KImportMode = INormal) {
|
||||
for(i in importStackName) if(i == e) return;
|
||||
importStackName.push(e);
|
||||
importStackMode.push(mode);
|
||||
}
|
||||
|
||||
private static function popImport(e:Expr) {
|
||||
return mk(EImport(importStackName.pop(), importStackMode.pop()), e);
|
||||
}
|
||||
|
||||
private static var depth:Int = 0;
|
||||
private static var declared:Array<ADeclVar>;
|
||||
private static var declaredTypes:Array<ADeclType>;
|
||||
private static var abstractData:Map<String, AbstractData>;
|
||||
private static var unusedImports:Map<String, String>;
|
||||
|
||||
private static function addDeclared(e:String, type:AVarType = VUnknown) {
|
||||
declared.push({
|
||||
name: e,
|
||||
type: type,
|
||||
depth: depth
|
||||
});
|
||||
}
|
||||
|
||||
private static function addTypeDeclared(e:String, inf:ATypeInfo) {
|
||||
declaredTypes.push({
|
||||
name: e,
|
||||
inf: inf,
|
||||
depth: depth
|
||||
});
|
||||
}
|
||||
|
||||
private static function getDeclared(e:String):ADeclVar {
|
||||
var len = declared.length;
|
||||
for(i in 0...len) {
|
||||
var idx = len - i - 1;
|
||||
var v = declared[idx];
|
||||
if(v.name == e) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getDeclaredType(e:String):ADeclType {
|
||||
var len = declaredTypes.length;
|
||||
for(i in 0...len) {
|
||||
var idx = len - i - 1;
|
||||
var v = declaredTypes[idx];
|
||||
if(v.name == e) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
var abstr = resolveAbstract(e);
|
||||
if(abstr != null) {
|
||||
return {
|
||||
name: getFieldName(e),
|
||||
inf: abstr,
|
||||
depth: depth
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static function removeUnusedDeclared() {
|
||||
while(declared.length > 0 && declared[declared.length - 1].depth > depth) {
|
||||
declared.pop();
|
||||
}
|
||||
while(declaredTypes.length > 0 && declaredTypes[declaredTypes.length - 1].depth > depth) {
|
||||
declaredTypes.pop();
|
||||
}
|
||||
}
|
||||
|
||||
public static function process(e:Expr):Expr {
|
||||
importStackName = [];
|
||||
importStackMode = [];
|
||||
depth = 0;
|
||||
declared = new Array();
|
||||
declaredTypes = new Array();
|
||||
abstractData = new Map();
|
||||
unusedImports = new Map();
|
||||
storedTypes = [];
|
||||
|
||||
var e = _process(e, true);
|
||||
|
||||
// Remove data
|
||||
declared = null;
|
||||
declaredTypes = null;
|
||||
abstractData = null;
|
||||
unusedImports = null;
|
||||
storedTypes = null;
|
||||
|
||||
e = removeMetaType(e);
|
||||
|
||||
// Automatically add imports for stuff
|
||||
switch(expr(e)) {
|
||||
case EBlock(exprs):
|
||||
while(importStackName.length > 0) {
|
||||
exprs.unshift(popImport(e));
|
||||
}
|
||||
return mk(EBlock(exprs), e);
|
||||
default:
|
||||
if(importStackName.length > 0) {
|
||||
var exprs = [];
|
||||
while(importStackName.length > 0) {
|
||||
exprs.unshift(popImport(e));
|
||||
}
|
||||
exprs.push(e);
|
||||
return mk(EBlock(exprs), e);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static function removeMetaType(e:Expr) {
|
||||
if(e == null)
|
||||
return null;
|
||||
switch(Tools.expr(e)) {
|
||||
case EMeta(":$type", [expr(_) => EConst(CInt(t))], e):
|
||||
return e;
|
||||
default:
|
||||
}
|
||||
return Tools.map(e, removeMetaType);
|
||||
}
|
||||
|
||||
static function getAbstractImport(name:String, m:KImportMode = INormal):String {
|
||||
var typeInfo = resolveAbstract(name);
|
||||
if(typeInfo == null) return null;
|
||||
|
||||
var fname = getFieldName(name);
|
||||
var varName = switch(m) {
|
||||
case IAs(a): a;
|
||||
default: fname;
|
||||
}
|
||||
addTypeDeclared(varName, typeInfo);
|
||||
trace("Adding abstract " + name + " as " + varName);
|
||||
|
||||
return typeInfo.impl;
|
||||
}
|
||||
|
||||
public static function loadAbstractData(name:String, ?type:Class<Any>) {
|
||||
if(abstractData.exists(name)) return abstractData.get(name);
|
||||
|
||||
if(type == null) {
|
||||
var t = resolveClassAbstract(name);
|
||||
if(t == null) return null;
|
||||
type = t.cl;
|
||||
if(type == null) return null;
|
||||
}
|
||||
|
||||
var data:AbstractData = {
|
||||
//var t:Dynamic = Type.createInstance(type, []);
|
||||
var t:Dynamic = type;
|
||||
{
|
||||
impl: t.__hx_impl__,
|
||||
funcs: t.abstract_funcs(),
|
||||
props: t.abstract_props()
|
||||
}
|
||||
};
|
||||
|
||||
abstractData.set(name, data);
|
||||
abstractData.set(data.impl, data);
|
||||
trace("Loading abstract " + name + " as " + data);
|
||||
return data;
|
||||
}
|
||||
|
||||
static function resolveAbstract(name:String, m:KImportMode = INormal) {
|
||||
var typeInfo = resolveClassAbstract(name);
|
||||
if(typeInfo == null) return null;
|
||||
|
||||
//loadAbstractData(name, type);
|
||||
addImport(typeInfo.impl, m);
|
||||
typeInfo.type = TAbstract(typeInfo.cl, typeInfo.impl);
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
static function resolveClassAbstract(name:String):ATypeInfo {
|
||||
var cl = Type.resolveClass(name + "_HSA");
|
||||
trace("Resolving " + name + "_HSA");
|
||||
if(cl == null) {
|
||||
var spr = name.split(".");
|
||||
if(spr.length < 2)
|
||||
return null;
|
||||
spr.splice(-2, 1); // remove the last last name;
|
||||
trace("Resolving " + spr.join(".") + "_HSA");
|
||||
cl = Type.resolveClass(spr.join(".") + "_HSA");
|
||||
}
|
||||
if(cl != null) {
|
||||
var cld:Dynamic = cl;
|
||||
return {
|
||||
impl: cld.__hx_impl__,
|
||||
cl: cl,
|
||||
type: null,
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static function findAbstractFromFieldName(name:String):AType {
|
||||
if(name.indexOf(".") == -1) {
|
||||
trace("Finding abstract from field name " + name + " " + unusedImports);
|
||||
if(unusedImports.exists(name)) {
|
||||
var fullName = unusedImports.get(name);
|
||||
addImport(getAbstractImport(fullName, INormal), INormal);
|
||||
unusedImports.remove(name);
|
||||
var v = resolveAbstract(fullName, INormal);
|
||||
if(v != null)
|
||||
return v.type;
|
||||
}
|
||||
}
|
||||
|
||||
trace("Finding abstract from field name " + name);
|
||||
var v = resolveAbstract(name, INormal);
|
||||
if(v != null)
|
||||
return v.type;
|
||||
return null;
|
||||
}
|
||||
|
||||
static function getFieldName(e:String) {
|
||||
var name = e.substr(e.lastIndexOf(".") + 1);
|
||||
return name;
|
||||
}
|
||||
|
||||
private static var storedTypes:Array<AType>;
|
||||
|
||||
static function setStoredType(type:AType):Int {
|
||||
var idx = storedTypes.indexOf(type);
|
||||
if(idx != -1) return idx;
|
||||
storedTypes.push(type);
|
||||
return storedTypes.length - 1;
|
||||
}
|
||||
|
||||
static inline function getStoredType(idx:Int):AType {
|
||||
return storedTypes[idx];
|
||||
}
|
||||
|
||||
static function wrapType(e:Expr, type:AType):Expr {
|
||||
return mk(EMeta(":$type", [mk(EConst(CInt(setStoredType(type))), e)], e), e);
|
||||
}
|
||||
|
||||
private static function _process(e:Expr, top:Bool = false):Expr {
|
||||
if(e == null)
|
||||
return null;
|
||||
|
||||
// If stuff looks wrong, add this back
|
||||
//e = Tools.map(e, function(e) {
|
||||
// return _process(e, false);
|
||||
//});
|
||||
|
||||
e = endProcess(e);
|
||||
|
||||
if(e == null) return null;
|
||||
|
||||
var ge = e;
|
||||
|
||||
switch(expr(e)) {
|
||||
case EVar(vname, t, e, p, s):
|
||||
var type = null;
|
||||
switch(Tools.expr(e)) {
|
||||
case ENew(n, _):
|
||||
type = n;
|
||||
case EIdent(n): // i dont think this worksc
|
||||
// var a = Abstract;
|
||||
// var b = a; // Gets detected
|
||||
type = getDeclaredType(n).name;
|
||||
default:
|
||||
}
|
||||
|
||||
if(t != null) {
|
||||
type = Printer.convertTypeToString(t);
|
||||
}
|
||||
|
||||
if(type != null) {
|
||||
var v = getDeclaredType(type);
|
||||
if(v != null) {
|
||||
addDeclared(vname, VVar(vname, v));
|
||||
trace("Adding var " + vname + " with type " + v.name);
|
||||
//return mk(EField(mk(EIdent(v.name), e), "new", p), e);
|
||||
}
|
||||
} else {
|
||||
trace("No type for " + vname + " " + t);
|
||||
addDeclared(vname, VUnknown);
|
||||
}
|
||||
|
||||
// TODO: make this not be only inside EVar
|
||||
var e = switch(Tools.expr(e)) {
|
||||
case ENew(n, args):
|
||||
var type = getDeclaredType(n);
|
||||
if(type == null) return endProcess(ge);
|
||||
|
||||
var stype = t != null ? Printer.convertTypeToString(t) : null;
|
||||
trace("New " + n + " " + stype);
|
||||
|
||||
switch(type.inf.type) {
|
||||
case TAbstract(at, impl):
|
||||
var helper:AbstractDataHelper = new AbstractDataHelper(type.name, at);
|
||||
var constructor = helper.getFuncForConstructor();
|
||||
trace("Converting new call to " + constructor);
|
||||
_process(mk(
|
||||
ECall(
|
||||
mk(
|
||||
EField(
|
||||
mk(
|
||||
EIdent(getFieldName(impl)),
|
||||
e
|
||||
),
|
||||
constructor),
|
||||
e), args
|
||||
), e
|
||||
));
|
||||
default: null;
|
||||
}
|
||||
default: null;
|
||||
};
|
||||
if(e != null)
|
||||
return mk(EVar(vname, t, e, p, s), ge);
|
||||
case EField(e, f, p):
|
||||
var typeInfo = switch(Tools.expr(e)) {
|
||||
case EIdent(n):
|
||||
var a = getDeclared(n);
|
||||
if(a != null) {
|
||||
switch(a.type) {
|
||||
case VVar(name, type): type.inf.type;
|
||||
default: null;
|
||||
}
|
||||
} else {
|
||||
null;
|
||||
}
|
||||
case EMeta(":$type", [expr(_) => EConst(CInt(t))], _):
|
||||
getStoredType(t);
|
||||
default:
|
||||
null;
|
||||
}
|
||||
if(typeInfo == null) return endProcess(ge);
|
||||
trace("EField " + e + " " + f);
|
||||
trace("Type: " + typeInfo);
|
||||
|
||||
var e = switch(typeInfo) {
|
||||
case TAbstract(at, impl):
|
||||
var helper:AbstractDataHelper = new AbstractDataHelper(impl, at);
|
||||
|
||||
var resolve = helper.getResolveFunc();
|
||||
trace("Resolve func: " + resolve);
|
||||
if(resolve != null) { // a.b -> a.resolve(b);
|
||||
var returnType = helper.getTypeOfFunc(resolve);
|
||||
var retType = findAbstractFromFieldName(returnType);
|
||||
trace("Expr: " + Printer.toString(e));
|
||||
|
||||
var field = mk(EField(mk(EIdent(getFieldName(impl)), e), resolve, p), e);
|
||||
var call = mk(ECall(field, [e, mk(EConst(CString(f)), e)]), e);
|
||||
|
||||
if(retType != null) {
|
||||
call = wrapType(call, retType);
|
||||
}
|
||||
return endProcess(call);
|
||||
}
|
||||
|
||||
// access.has -> Access_Impl_.get_has()
|
||||
var v = helper.getProps(f);
|
||||
if(v != null) // get
|
||||
{
|
||||
var getterType = helper.getTypeOfFunc(v[0]);
|
||||
if(getterType != null) {
|
||||
trace("Getter: " + getterType);
|
||||
trace("v:" + v);
|
||||
|
||||
var retType = findAbstractFromFieldName(getterType);
|
||||
|
||||
var field = mk(EField(mk(EIdent(getFieldName(impl)), e), v[0], p), e);
|
||||
var call = mk(ECall(field, [e]), e);
|
||||
var meta = wrapType(call, retType);
|
||||
|
||||
trace("Expr: " + Printer.toString(meta));
|
||||
endProcess(meta);
|
||||
} else {
|
||||
null;
|
||||
}
|
||||
}
|
||||
else
|
||||
null;
|
||||
default: null;
|
||||
}
|
||||
|
||||
if(e != null)
|
||||
return e;
|
||||
case EImport(n, m):
|
||||
var abstractImport = getAbstractImport(n, m);
|
||||
if(abstractImport != null) {
|
||||
addImport(abstractImport, m);
|
||||
if(n == "haxe.xml.Access") {
|
||||
var toImport = [
|
||||
"haxe.xml.Access.NodeAccess",
|
||||
"haxe.xml.Access.AttribAccess",
|
||||
"haxe.xml.Access.HasAttribAccess",
|
||||
"haxe.xml.Access.HasNodeAccess",
|
||||
"haxe.xml.Access.NodeListAccess",
|
||||
];
|
||||
for(n in toImport) {
|
||||
//var m = INormal;//IAs("$" + n);
|
||||
//addImport(getAbstractImport(n, m), m);
|
||||
unusedImports.set(getFieldName(n), n);
|
||||
}
|
||||
}
|
||||
return null;//mk(abstractImport, e);
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return (e);
|
||||
}
|
||||
|
||||
static function endProcess(e:Expr):Expr {
|
||||
if(e == null) return null;
|
||||
var ge = e;
|
||||
return Tools.map(e, function(e) {
|
||||
if(e == null) return mk(EBlock([]), ge); // Hacky
|
||||
switch(Tools.expr(e)) {
|
||||
case EBlock(exprs):
|
||||
depth++;
|
||||
for(i in 0...exprs.length) {
|
||||
exprs[i] = _process(exprs[i]);
|
||||
}
|
||||
while(exprs.contains(null)) exprs.remove(null);
|
||||
depth--;
|
||||
removeUnusedDeclared();
|
||||
return mk(EBlock(exprs), e);
|
||||
case EFunction(args, expr, name, a, isPublic, isStatic, isOverride):
|
||||
depth++;
|
||||
_process(expr);
|
||||
//for(i in 0...expr.length) {
|
||||
// expr[i] = _process(expr[i]);
|
||||
//}
|
||||
depth--;
|
||||
removeUnusedDeclared();
|
||||
return mk(EFunction(args, expr, name, a, isPublic, isStatic, isOverride), e);
|
||||
default:
|
||||
}
|
||||
return _process(e);
|
||||
});
|
||||
}
|
||||
|
||||
static function mk(e:ExprDef, s:Expr):Expr {
|
||||
#if hscriptPos
|
||||
return new Expr(e, s.pmin, s.pmax, s.origin, s.line);
|
||||
#else
|
||||
return e;
|
||||
#end
|
||||
}
|
||||
|
||||
public static var isStringFromCharCodeFixed(get, null):Null<Bool> = null;
|
||||
static function get_isStringFromCharCodeFixed():Null<Bool> {
|
||||
if(isStringFromCharCodeFixed == null) {
|
||||
try {
|
||||
Reflect.callMethod(null, Reflect.field(String, "fromCharCode"), [65]);
|
||||
isStringFromCharCodeFixed = true;
|
||||
} catch(e:Dynamic) {
|
||||
isStringFromCharCodeFixed = false;
|
||||
}
|
||||
}
|
||||
return isStringFromCharCodeFixed;
|
||||
}
|
||||
}
|
||||
|
||||
class AbstractDataHelper {
|
||||
public var data:AbstractData;
|
||||
|
||||
public function new(name:String, ?cls: Class<Any>) {
|
||||
data = AbstractProcessor.loadAbstractData(name, cls);
|
||||
}
|
||||
|
||||
// [name, args, ret, access, special, ?op]
|
||||
|
||||
public function getProps(fieldName:String):Array<String> {
|
||||
var prop = data.props;
|
||||
for(v in prop) {
|
||||
if(v[0] == fieldName) {
|
||||
return [v[1], v[2]];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getResolveFunc(?wantedType:Null<String>):String {
|
||||
var t = getFuncForOp("a.b", wantedType);
|
||||
if(t != null) return t;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getTypeOfFunc(f:String):String {
|
||||
var funcs = data.funcs;
|
||||
for(func in funcs) {
|
||||
if(func[0] == f) {
|
||||
return func[2];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getFuncForOp(op:String, ?wantedType:Null<String>):String {
|
||||
var funcs = data.funcs;
|
||||
for(func in funcs) {
|
||||
if(func[4] & 16 != 0) {
|
||||
if(func[5] == op) {
|
||||
if(wantedType != null) {
|
||||
var types:Array<String> = func[1].split("|");
|
||||
var wtypes:Array<String> = wantedType.split("|");
|
||||
if(types.length != wtypes.length) continue;
|
||||
var didBreak = false;
|
||||
for(i=>type in types) {
|
||||
if(type != wtypes[i]) {
|
||||
didBreak = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(didBreak) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return func[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getFuncForArrayRead(?wantedType:Null<String>):String {
|
||||
var funcs = data.funcs;
|
||||
for(func in funcs) {
|
||||
if(func[4] & 1 != 0) {
|
||||
if(wantedType != null) {
|
||||
var types:Array<String> = func[1].split("|");
|
||||
var wtypes:Array<String> = wantedType.split("|");
|
||||
if(types.length != wtypes.length) continue;
|
||||
var didBreak = false;
|
||||
for(i=>type in types) {
|
||||
if(type != wtypes[i]) {
|
||||
didBreak = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(didBreak) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return func[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getFuncForArrayWrite(?wantedType:Null<String>):String {
|
||||
var funcs = data.funcs;
|
||||
for(func in funcs) {
|
||||
if(func[4] & 2 != 0) {
|
||||
if(wantedType != null) {
|
||||
var types:Array<String> = func[1].split("|");
|
||||
var wtypes:Array<String> = wantedType.split("|");
|
||||
if(types.length != wtypes.length) continue;
|
||||
var didBreak = false;
|
||||
for(i=>type in types) {
|
||||
if(type != wtypes[i]) {
|
||||
didBreak = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(didBreak) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return func[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getFuncForConstructor(?wantedType:Null<String>):String {
|
||||
var funcs = data.funcs;
|
||||
for(func in funcs) {
|
||||
if(func[4] & 4 != 0) {
|
||||
if(wantedType != null) {
|
||||
var types:Array<String> = func[1].split("|");
|
||||
var wtypes:Array<String> = wantedType.split("|");
|
||||
if(types.length != wtypes.length) continue;
|
||||
var didBreak = false;
|
||||
for(i=>type in types) {
|
||||
if(type != wtypes[i]) {
|
||||
didBreak = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(didBreak) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return func[0];
|
||||
}
|
||||
}
|
||||
for(func in funcs) {
|
||||
if(func[0] == "_new")
|
||||
return func[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getFuncForToConversion(?wantedType:Null<String>):Array<Dynamic> {
|
||||
var funcs = data.funcs;
|
||||
for(func in funcs) {
|
||||
if(func[4] & 8 != 0) {
|
||||
if(wantedType != null) {
|
||||
var types = func[2];
|
||||
var wtypes = wantedType;
|
||||
if(types != wantedType)
|
||||
continue;
|
||||
}
|
||||
return func[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,10 @@ class Expr {
|
||||
this.origin = origin;
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public function toString() {
|
||||
return "<Expr " + e + ">";
|
||||
}
|
||||
}
|
||||
enum ExprDef
|
||||
#else
|
||||
|
||||
+48
-19
@@ -224,6 +224,7 @@ class Parser {
|
||||
parseFullExpr(a);
|
||||
}
|
||||
var expr = if( a.length == 1 ) a[0] else mk(EBlock(a),0);
|
||||
expr = AbstractProcessor.process(expr);
|
||||
expr = Preprocessor.process(expr);
|
||||
if(Parser.optimize) {
|
||||
expr = Optimizer.optimize(expr);
|
||||
@@ -398,8 +399,10 @@ class Parser {
|
||||
function parseExprFromTokens(t:TokenList) {
|
||||
var oldPos = readPos;
|
||||
#if hscriptPos
|
||||
var oldTokenMin = tokenMin;
|
||||
var oldTokenMax = tokenMax;
|
||||
var _oldTokenMin = tokenMin;
|
||||
var _oldTokenMax = tokenMax;
|
||||
var oldOldTokenMin = oldTokenMin;
|
||||
var oldOldTokenMax = oldTokenMax;
|
||||
#end
|
||||
var oldTokens = tokens;
|
||||
|
||||
@@ -407,7 +410,11 @@ class Parser {
|
||||
// unsure about these
|
||||
#if hscriptPos
|
||||
tokenMin = 0;
|
||||
tokenMax = t.length - 1;
|
||||
//tokenMax = t.length - 1;
|
||||
tokenMax = 0;
|
||||
oldTokenMin = 0;
|
||||
oldTokenMax = 0;
|
||||
//oldTokenMax = t.length - 1;
|
||||
#end
|
||||
readPos = 0;
|
||||
//trace(t.map(getTk).map(tokenString));
|
||||
@@ -418,6 +425,8 @@ class Parser {
|
||||
#if hscriptPos
|
||||
tokenMin = oldTokenMin;
|
||||
tokenMax = oldTokenMax;
|
||||
oldTokenMin = oldOldTokenMin;
|
||||
oldTokenMax = oldOldTokenMax;
|
||||
#end
|
||||
readPos = oldPos;
|
||||
return e;
|
||||
@@ -604,8 +613,9 @@ class Parser {
|
||||
var tmp2 = "__m_" + (uid++);
|
||||
var e = mk(EBlock([
|
||||
// TODO: Make it detect simple map comprehensions so we can optimize the map type
|
||||
mk(EVar(tmp, null, mk(EMapDecl(ObjectMap, [], []), p1)), p1), // Assume ObjectMap, since it supports dynamic keys
|
||||
mk(EVar(tmp2, null, mk(EField(mk(EIdent(tmp), p1), "set"), p1)), p1),
|
||||
// TODO: make it detect the type from nextType
|
||||
mk(EVar(tmp, parseTypeString("haxe.ds.ObjectMap<Dynamic, Dynamic>"), mk(EMapDecl(ObjectMap, [], []), p1)), p1), // Assume ObjectMap, since it supports dynamic keys
|
||||
mk(EVar(tmp2, parseTypeString("(Dynamic, Dynamic) -> Void"), mk(EField(mk(EIdent(tmp), p1), "set"), p1)), p1),
|
||||
mapMapCompr(tmp2, a[0]),
|
||||
mk(EIdent(tmp),p1),
|
||||
]),p1);
|
||||
@@ -615,8 +625,8 @@ class Parser {
|
||||
var tmp = "__a_" + (uid++);
|
||||
var tmp2 = "__a_" + (uid++);
|
||||
var e = mk(EBlock([
|
||||
mk(EVar(tmp, null, mk(EArrayDecl([]), p1)), p1),
|
||||
mk(EVar(tmp2, null, mk(EField(mk(EIdent(tmp), p1), "push"), p1)), p1),
|
||||
mk(EVar(tmp, parseTypeString("Array<Dynamic>"), mk(EArrayDecl([]), p1)), p1),
|
||||
mk(EVar(tmp2, parseTypeString("(Dynamic) -> Int"), mk(EField(mk(EIdent(tmp), p1), "push"), p1)), p1),
|
||||
mapArrCompr(tmp2, a[0]),
|
||||
mk(EIdent(tmp),p1),
|
||||
]),p1);
|
||||
@@ -1421,8 +1431,27 @@ class Parser {
|
||||
return path;
|
||||
}
|
||||
|
||||
static var typeCache:Map<String, CType> = [];
|
||||
|
||||
function parseTypeString(str:String) {
|
||||
if(typeCache.exists(str))
|
||||
return typeCache.get(str);
|
||||
|
||||
var parser = new Parser();
|
||||
parser.initParser("__INTERNAL_TYPE_PARSER__:" + origin);
|
||||
parser.line = line;
|
||||
parser.input = str;
|
||||
parser.readPos = 0;
|
||||
var type = parser.parseType();
|
||||
|
||||
typeCache.set(str, type);
|
||||
return type;
|
||||
}
|
||||
|
||||
function parseType() : CType {
|
||||
var t = token();
|
||||
trace("Token: " + tokenString(t));
|
||||
if( t == TEof ) return null;
|
||||
switch( t ) {
|
||||
case TId(v):
|
||||
push(t);
|
||||
@@ -1437,18 +1466,18 @@ class Parser {
|
||||
params.push(parseType());
|
||||
t = token();
|
||||
switch( t ) {
|
||||
case TComma: continue;
|
||||
case TOp(op):
|
||||
if( op == ">" ) break;
|
||||
if( op.charCodeAt(0) == ">".code ) {
|
||||
tokens.add(realToken(
|
||||
TOp(op.substr(1)),
|
||||
tokenMax - op.length - 1,
|
||||
tokenMax
|
||||
));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case TComma: continue;
|
||||
case TOp(op):
|
||||
if( op == ">" ) break;
|
||||
if( op.charCodeAt(0) == ">".code ) {
|
||||
tokens.add(realToken(
|
||||
TOp(op.substr(1)),
|
||||
tokenMax - op.length - 1,
|
||||
tokenMax
|
||||
));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
unexpected(t);
|
||||
break;
|
||||
|
||||
+6
-1
@@ -49,6 +49,11 @@ class Printer {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static function convertTypeToString( t : CType ) {
|
||||
var printer = new Printer();
|
||||
return printer.typeToString(t);
|
||||
}
|
||||
|
||||
inline function add<T>(s:T) buf.add(s);
|
||||
|
||||
function type( t : CType ) {
|
||||
@@ -501,7 +506,7 @@ class Printer {
|
||||
var first = true;
|
||||
for( a in args ) {
|
||||
if( first ) first = false else add(", ");
|
||||
expr(e);
|
||||
expr(a);
|
||||
}
|
||||
add(")");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,519 @@
|
||||
package hscript.macros;
|
||||
|
||||
#if macro
|
||||
import Type.ValueType;
|
||||
import haxe.macro.ComplexTypeTools;
|
||||
import haxe.macro.Expr;
|
||||
import haxe.macro.Type;
|
||||
import haxe.macro.Context;
|
||||
import haxe.macro.Printer;
|
||||
import haxe.macro.Compiler;
|
||||
import haxe.macro.ComplexTypeTools;
|
||||
|
||||
using StringTools;
|
||||
using haxe.macro.PositionTools;
|
||||
|
||||
class AbstractHandler {
|
||||
public static inline final CLASS_SUFFIX = "_HSA";
|
||||
|
||||
public static function init() {
|
||||
#if !display
|
||||
if(Context.defined("display")) return;
|
||||
//for(apply in Config.ALLOWED_ABSTRACT_AND_ENUM) {
|
||||
//}
|
||||
Compiler.addGlobalMetadata("", '@:build(hscript.macros.AbstractHandler.build())');
|
||||
|
||||
//var module = cl.module + cl.name;
|
||||
#end
|
||||
}
|
||||
|
||||
static var abstracts = new Map<String, {
|
||||
|
||||
}>();
|
||||
|
||||
/*static function finalizeAbstract(a:AbstractType) {
|
||||
var name = a.name;
|
||||
if(name.endsWith(CLASS_SUFFIX)) return; // !name.endsWith("_Impl_") ||
|
||||
if(name != "NodeListAccess") return;
|
||||
|
||||
Sys.println("");
|
||||
Sys.println("");
|
||||
Sys.println("");
|
||||
Sys.println("");
|
||||
Sys.println("");
|
||||
|
||||
//Sys.println("name: " + a.name);
|
||||
//Sys.println("module: " + a.module);
|
||||
|
||||
Sys.println(MacroPrinter.convertAbstractTypeToString(a));
|
||||
|
||||
//trace("buildAbstract", a);
|
||||
}*/
|
||||
|
||||
static var currentSelf = "";
|
||||
|
||||
/*static function oldTypeToString(t:Type, selfCheck:String = null):String {
|
||||
var str = switch(t) {
|
||||
case TInst(_.get() => t, params):
|
||||
var str = "";
|
||||
if(t.pack.length > 0) {
|
||||
str += t.pack.join(".") + ".";
|
||||
}
|
||||
str += t.name;
|
||||
if(t.params != null && t.params.length > 0) {
|
||||
str += "<" + t.params.map((v)->oldTypeToString(v.t, t.name + "." + v.name)).join(", ") + ">";
|
||||
}
|
||||
//if(t.params.length > 0) {
|
||||
// throw "Params not supported yet " + t.name + " " + t.params;
|
||||
//}
|
||||
str;
|
||||
case TAbstract(_.get() => t, params):
|
||||
var str = "";
|
||||
if(t.pack.length > 0) {
|
||||
str += t.pack.join(".") + ".";
|
||||
}
|
||||
str += t.name;
|
||||
if(t.params != null && t.params.length > 0) {
|
||||
str += "<" + t.params.map((v)->oldTypeToString(v.t, t.name + "." + v.name)).join(", ") + ">";
|
||||
}
|
||||
//if(t.params.length > 0) {
|
||||
// throw "Params not supported yet " + t.name + " " + t.params;
|
||||
//}
|
||||
str;
|
||||
case TEnum(_.get() => t, params):
|
||||
var str = "";
|
||||
if(t.pack.length > 0) {
|
||||
str += t.pack.join(".") + ".";
|
||||
}
|
||||
str += t.name;
|
||||
if(t.params != null && t.params.length > 0) {
|
||||
str += "<" + t.params.map((v)->oldTypeToString(v.t, t.name + "." + v.name)).join(", ") + ">";
|
||||
}
|
||||
//if(t.params.length > 0) {
|
||||
// throw "Params not supported yet " + t.name + " " + t.params;
|
||||
//}
|
||||
str;
|
||||
case TType(_.get() => t, params):
|
||||
var str = "";
|
||||
if(t.pack.length > 0) {
|
||||
str += t.pack.join(".") + ".";
|
||||
}
|
||||
str += t.name;
|
||||
if(t.params != null && t.params.length > 0) {
|
||||
str += "<" + t.params.map((v)->oldTypeToString(v.t, t.name + "." + v.name)).join(", ") + ">";
|
||||
//trace("TType", str);
|
||||
}
|
||||
str;
|
||||
case TAnonymous(_.get() => t):
|
||||
//var str = "Dynamic {"+t.fields.map((f)->f.name).join(", ")+"}";
|
||||
//str += t.name;
|
||||
var str = "{ ";
|
||||
var first = true;
|
||||
for(f in t.fields) {
|
||||
if(!first) str += ", ";
|
||||
first = false;
|
||||
str += f.name + ":" + oldTypeToString(f.type);
|
||||
}
|
||||
str += " }";
|
||||
//trace("TAnonymous", str);
|
||||
str;
|
||||
case TDynamic(t):
|
||||
var str = "Dynamic";
|
||||
if(t != null) {
|
||||
str += "<" + oldTypeToString(t) + ">";
|
||||
}
|
||||
str;
|
||||
default:
|
||||
Sys.println("Unknown type " + Std.string(t));
|
||||
null;
|
||||
}
|
||||
|
||||
if(selfCheck != null) {
|
||||
if(str == selfCheck) {
|
||||
return selfCheck;
|
||||
//return currentSelf;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static function getResolvedType(t:ComplexType):String {
|
||||
if(t == null) return null;
|
||||
|
||||
try {
|
||||
//var type = Context.getType(checkType);
|
||||
var paramFree = switch(t) {
|
||||
case TPath(t):
|
||||
//trace(t);
|
||||
TPath({
|
||||
name: t.name,
|
||||
pack: t.pack,
|
||||
params: t.params,
|
||||
sub: t.sub
|
||||
});
|
||||
case TAnonymous(a):
|
||||
t;
|
||||
case TFunction(args, ret):
|
||||
t;
|
||||
default:
|
||||
trace("");
|
||||
trace(ComplexTypeTools.toString(t));
|
||||
throw "Unknown type " + Std.string(t);
|
||||
}
|
||||
var type = ComplexTypeTools.toType(paramFree);
|
||||
var strType = oldTypeToString(type);
|
||||
if(strType != null) return strType;
|
||||
} catch(e:Dynamic) {
|
||||
Sys.println(e);
|
||||
Sys.println(ComplexTypeTools.toString(t));
|
||||
Sys.println(haxe.CallStack.toString(haxe.CallStack.exceptionStack()));
|
||||
}
|
||||
|
||||
return MacroPrinter.typeToString(t);
|
||||
}*/
|
||||
|
||||
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.isExtern) return fields;
|
||||
|
||||
//if(cl.name != "Access_Impl_") return fields;
|
||||
//if(cl.name != "DrawQuadsView_Impl_") return fields;
|
||||
|
||||
if(cl.name.endsWith("_Impl_") && !cl.name.endsWith(CLASS_SUFFIX)) // && ["Access_Impl_", "AttribAccess_Impl_"].contains(cl.name))
|
||||
{
|
||||
//trace("Processing " + cl);
|
||||
//if(!initialized) {
|
||||
// initialized = true;
|
||||
// Context.onAfterTyping(function(mods) {
|
||||
// for(mod in mods) {
|
||||
// switch(mod) {
|
||||
// case TAbstract(_.get() => a):
|
||||
// //trace("onAfterTyping", a);
|
||||
// finalizeAbstract(a);
|
||||
// //ab = a;
|
||||
// default:
|
||||
// // return;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//}
|
||||
|
||||
currentSelf = cl.name.substr(0, cl.name.length - "_Impl_".length);
|
||||
|
||||
var funcInfos = [];
|
||||
var propsInfo = [];
|
||||
//for(f in fields) {
|
||||
// trace(f.name, f.kind);
|
||||
//}
|
||||
for(f in fields) {
|
||||
if(f.name.startsWith("__abstract_helper"))
|
||||
continue;
|
||||
//if(f.name != "escapes")
|
||||
// continue;
|
||||
//trace(f);
|
||||
//trace(
|
||||
//MacroPrinter.convertFieldToString(f, cl.module + "." + cl.name)
|
||||
//);
|
||||
//trace();
|
||||
//continue;
|
||||
switch(f.kind) {
|
||||
case FFun(fun):
|
||||
if(fun.expr != null) {
|
||||
var obj:Dynamic = {
|
||||
name: f.name,
|
||||
args: [for(a in fun.args) {
|
||||
//name: a.name,
|
||||
//opt: a.opt,
|
||||
//type: MacroPrinter.typeToString(a.type),
|
||||
//value: a.value,
|
||||
//meta: a.meta,
|
||||
var arg = a.type == null ? "_" : MacroPrinter.typeToString(a.type);
|
||||
if(a.opt) {
|
||||
arg = "?" + arg;
|
||||
}
|
||||
arg;
|
||||
}].join("|"),
|
||||
ret: fun.ret,
|
||||
//access: f.access.map(function(a) return Std.string(a)).join(","),
|
||||
access: {
|
||||
var special = 0;
|
||||
var map:Array<Access> = [AStatic, APrivate, APublic, AOverride, AInline, ADynamic, AExtern, AStatic];
|
||||
for(a in f.access) {
|
||||
var index = map.indexOf(a);
|
||||
if(index == -1) {
|
||||
trace("Unknown access " + a);
|
||||
continue;
|
||||
}
|
||||
special |= 1 << index;
|
||||
}
|
||||
special;
|
||||
},
|
||||
special: {
|
||||
var special = 0;//{arrayAccess: false, arrayWrite: false};
|
||||
for(m in f.meta) {
|
||||
if(m.name == ":arrayAccess") {
|
||||
if(fun.args.length == 1) {
|
||||
special |= 1;
|
||||
//special.arrayAccess = true;
|
||||
} else if(fun.args.length == 2) {
|
||||
special |= 2;
|
||||
//special.arrayWrite = true;
|
||||
} else {
|
||||
trace(f.pos);
|
||||
throw "Unknown :arrayAccess meta " + fun.args;
|
||||
}
|
||||
} else if(m.name == ":from") {
|
||||
//throw "Unknown :from meta " + m;
|
||||
special |= 4;
|
||||
} else if(m.name == ":to") {
|
||||
//throw "Unknown :to meta " + m;
|
||||
special |= 8;
|
||||
} else if(m.name == ":op") {
|
||||
special |= 16;
|
||||
}
|
||||
}
|
||||
special;
|
||||
},
|
||||
op: {
|
||||
var op = null;
|
||||
//trace("");
|
||||
//trace("");
|
||||
//trace("");
|
||||
//trace(f.name, f.meta);
|
||||
//trace(f.name, fun);
|
||||
for(m in f.meta) {
|
||||
if(m.name == ":resolve") {
|
||||
if(f.access.contains(AStatic) && fun.args.length == 2) {
|
||||
op = "a.b";
|
||||
} else if(!f.access.contains(AStatic) && fun.args.length == 1) {
|
||||
op = "a.b";
|
||||
} else {
|
||||
throw "Unknown :resolve meta " + fun.args;
|
||||
}
|
||||
}
|
||||
if(m.name == ":op") {
|
||||
switch (m.params[0].expr) {
|
||||
case EField(_.expr => EConst(CIdent(_)), _):
|
||||
op = "a.b";
|
||||
case EArrayDecl([]):
|
||||
op = "[]";
|
||||
case EUnop(o, suffix, _.expr => EConst(CIdent(_))):
|
||||
var opStr = switch(o) {
|
||||
case OpNeg: "-";
|
||||
case OpIncrement: "++";
|
||||
case OpDecrement: "--";
|
||||
case OpNot: "!";
|
||||
case OpNegBits: "~";
|
||||
case OpSpread: "...";
|
||||
}
|
||||
if(suffix) {
|
||||
op = "a" + opStr;
|
||||
} else {
|
||||
op = opStr + "a";
|
||||
}
|
||||
case EBinop(o, _.expr => EConst(CIdent(_)), _.expr => EConst(CIdent(_))):
|
||||
var opStr = getBinopStr(o);
|
||||
op = "a " + opStr + " b";
|
||||
#if (haxe >= "4.3.0")
|
||||
case ECall(_.expr => EConst(CIdent(_)), []):
|
||||
op = "a()";
|
||||
#end
|
||||
default:
|
||||
trace(f.name, cl.module);
|
||||
throw "Unknown op " + MacroPrinter.convertExprToString(m.params[0]) + "\n in " + f.name + " in " + cl.module;
|
||||
}
|
||||
//trace(op, convertExprToString(m.params[0]));
|
||||
//trace(Type.typeof(m.params[0]));
|
||||
//switch (m.params[0].expr) {
|
||||
// case EConst(CIdent(_i)):
|
||||
// id = _i;
|
||||
// default:
|
||||
//}
|
||||
}
|
||||
}
|
||||
op;
|
||||
}
|
||||
}
|
||||
|
||||
if(obj.op == null) {
|
||||
Reflect.deleteField(obj, "op");
|
||||
}
|
||||
|
||||
if(obj.ret == null && f.name.startsWith("get_")) {
|
||||
var v = getVarFromFields(fields, f.name.substr(4));
|
||||
var type = getTypeFromField(v);
|
||||
//Sys.println("getter " + f.name + " " + getResolvedType(type) + " " + type);
|
||||
obj.ret = type;
|
||||
} else if(obj.ret == null && f.name.startsWith("set_")) {
|
||||
var v = getVarFromFields(fields, f.name.substr(4));
|
||||
var type = getTypeFromField(v);
|
||||
//Sys.println("setter " + f.name + " " + getResolvedType(type) + " " + type);
|
||||
obj.ret = type;
|
||||
} else {
|
||||
if(obj.ret != null) {
|
||||
//Sys.println("normal field " + f.name + " " + getResolvedType(obj.ret) + " " + obj.ret);
|
||||
}
|
||||
}
|
||||
|
||||
//if(obj.name == "_new")
|
||||
// obj.name = "new";
|
||||
|
||||
obj.ret = MacroPrinter.typeToString(obj.ret);
|
||||
|
||||
//trace("FFun", obj);
|
||||
var save:Dynamic = null;
|
||||
if(true) {
|
||||
save = [obj.name, obj.args, obj.ret, obj.access, obj.special];
|
||||
if(obj.op != null) {
|
||||
save.push(obj.op);
|
||||
}
|
||||
} else {
|
||||
save = obj;
|
||||
}
|
||||
funcInfos.push(save);
|
||||
//trace(cl.name, obj);
|
||||
}
|
||||
case FProp(get, set, t, e):
|
||||
if(f.access.contains(AStatic)) {
|
||||
continue;
|
||||
}
|
||||
if(get != "get") {
|
||||
trace("Unknown FProp getter " + get, f.pos);
|
||||
continue;
|
||||
}
|
||||
if(e != null) {
|
||||
trace("Unknown FProp expression " + e, f.pos);
|
||||
continue;
|
||||
}
|
||||
//var getsetbits = 0;
|
||||
var canSet = false;
|
||||
// allow transform of getter setter
|
||||
//switch(get) {
|
||||
// case "get": getsetbits |= 1;
|
||||
// case "dynamic": getsetbits |= 1;
|
||||
// //case "null": getsetbits |= 1; // since this cant be called outside of the class
|
||||
//}
|
||||
switch(set) {
|
||||
case "set": canSet = true;
|
||||
case "dynamic": canSet = true;
|
||||
case "null": canSet = false; // since this cant be called outside of the class
|
||||
}
|
||||
|
||||
var obj:Dynamic = {
|
||||
name: f.name,
|
||||
get: "get_" + f.name,
|
||||
set: canSet ? "set_" + f.name : null
|
||||
}
|
||||
|
||||
//var getset = get + "," + set;
|
||||
var save:Dynamic = null;
|
||||
if(true) {
|
||||
save = [obj.name, obj.get, obj.set];
|
||||
} else {
|
||||
save = obj;
|
||||
}
|
||||
propsInfo.push(save);
|
||||
//trace("FProp", getset, t, e);
|
||||
default:
|
||||
}
|
||||
//funcInfos.push([f.name, ]);
|
||||
}
|
||||
|
||||
//trace(funcInfos);
|
||||
|
||||
//trace(cl.pos);
|
||||
|
||||
var shadowClass = macro class {
|
||||
public static var __hx_impl__:String = $v{cl.pack.join(".") + "." + cl.name};
|
||||
|
||||
public static function abstract_funcs():Array<Array<Dynamic>> {
|
||||
return @:fixed $v{funcInfos};
|
||||
}
|
||||
public static function abstract_props():Array<Array<String>> {
|
||||
return @:fixed $v{propsInfo};
|
||||
}
|
||||
}
|
||||
|
||||
shadowClass.kind = TDClass(null, [
|
||||
//{name: "IHScriptAbstractHelper", pack: ["hscript"]},
|
||||
//{name: "IHScriptCustomClassBehaviour", pack: ["hscript"]}
|
||||
], false, true, false);
|
||||
shadowClass.name = '${cl.name.substr(0, cl.name.length - "_Impl_".length)}$CLASS_SUFFIX';
|
||||
//trace(shadowClass.name);
|
||||
var imports = Context.getLocalImports().copy();
|
||||
Utils.setupMetas(shadowClass, [], false);
|
||||
|
||||
var moduleName = cl.module;
|
||||
Context.defineModule(moduleName, [shadowClass], imports);
|
||||
|
||||
//var printer = new haxe.macro.Printer();
|
||||
//var code = printer.printTypeDefinition(shadowClass);
|
||||
//trace(code);
|
||||
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
static var initialized = false;
|
||||
|
||||
static function getBinopStr(op:Binop):String {
|
||||
return switch(op) {
|
||||
case OpAdd: "+";
|
||||
case OpSub: "-";
|
||||
case OpMult: "*";
|
||||
case OpDiv: "/";
|
||||
case OpMod: "%";
|
||||
case OpEq: "==";
|
||||
case OpNotEq: "!=";
|
||||
case OpGt: ">";
|
||||
case OpGte: ">=";
|
||||
case OpLt: "<";
|
||||
case OpLte: "<=";
|
||||
case OpAnd: "&";
|
||||
case OpOr: "|";
|
||||
case OpXor: "^";
|
||||
case OpShl: "<<";
|
||||
case OpShr: ">>";
|
||||
case OpUShr: ">>>";
|
||||
case OpBoolAnd: "&&";
|
||||
case OpBoolOr: "||";
|
||||
case OpAssign: "=";
|
||||
case OpArrow: "=>";
|
||||
case OpAssignOp(op):
|
||||
getBinopStr(op) + "=";
|
||||
case OpIn: "in";
|
||||
case OpInterval: "...";
|
||||
}
|
||||
}
|
||||
|
||||
static function getVarFromFields(fields:Array<Field>, name:String):Field {
|
||||
for(f in fields) {
|
||||
if(f.name == name) {
|
||||
switch(f.kind) {
|
||||
case FProp(_, _, _, _):
|
||||
return f;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static function getTypeFromField(field:Field):ComplexType {
|
||||
//if(field == null) return null;
|
||||
return switch(field.kind) {
|
||||
case FProp(_, _, t, _): t;
|
||||
case FVar(t, _): t;
|
||||
case FFun(f): f.ret;
|
||||
default: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,10 +25,11 @@ class Utils {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static function setupMetas(shadowClass:TypeDefinition, imports) {
|
||||
public static function setupMetas(shadowClass:TypeDefinition, imports:Array<ImportExpr>, doImports:Bool = true) {
|
||||
shadowClass.meta = [];
|
||||
shadowClass.meta.push({name: ":dox", params: [macro hide], pos: Context.currentPos()});
|
||||
shadowClass.meta.push({name: ":noCompletion", params: [], pos: Context.currentPos()});
|
||||
if(!doImports) return;
|
||||
var module = Context.getModule(Context.getLocalModule());
|
||||
for(t in module) {
|
||||
switch(t) {
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
# File Specific Defines
|
||||
--define linux
|
||||
|
||||
--macro keep('IntIterator')
|
||||
# --macro hscript.macros.UsingHandler.init()
|
||||
# --macro hscript.macros.ClassExtendMacro.init()
|
||||
--macro hscript.macros.AbstractHandler.init()
|
||||
|
||||
# Copying the assets from source code to bin folder
|
||||
--cmd rm -rf bin/cpp/assets
|
||||
--cmd cp -r assets bin/cpp/assets
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
--macro keep('IntIterator')
|
||||
# --macro hscript.macros.UsingHandler.init()
|
||||
# --macro hscript.macros.ClassExtendMacro.init()
|
||||
--macro hscript.macros.AbstractHandler.init()
|
||||
|
||||
|
||||
# Copying the assets from source code to bin folder
|
||||
|
||||
@@ -40,6 +40,7 @@ class Main {
|
||||
// TODO: UnicodeCase.hx?
|
||||
// TODO: UnicodeStringCase.hx?
|
||||
runTest("Final", new FinalCase());
|
||||
runTest("Abstract", new AbstractCase());
|
||||
Util.printTestResults();
|
||||
#end
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package tests;
|
||||
|
||||
import haxe.xml.Access;
|
||||
import Xml;
|
||||
|
||||
class AbstractCase extends TestCase {
|
||||
override function setup() {
|
||||
super.setup();
|
||||
}
|
||||
|
||||
override function run() {
|
||||
var access = new Access(Xml.parse("<test test=\"cool\"><hello>world</hello></test>").firstElement());
|
||||
|
||||
trace(access.att.test);
|
||||
|
||||
getNewInterp().execute(Util.parse("
|
||||
|
||||
import haxe.xml.Access;
|
||||
|
||||
var access = new Access(Xml.parse('<test test=\"cool\"><hello>world</hello></test>').firstElement());
|
||||
var a2 = new haxe.xml.Access(Xml.parse('<test test=\"cool\"><hello>world</hello></test>').firstElement());
|
||||
|
||||
trace(access.att.test);
|
||||
"));
|
||||
|
||||
//var a2:Access = Xml.parse('<test test=\"cool\"><hello>world</hello></test>').firstElement();
|
||||
/*getNewInterp().execute(Util.parse("
|
||||
// Converts to
|
||||
import haxe.xml._Access.Access_Impl_;
|
||||
import haxe.xml._Access.AttribAccess_Impl_;
|
||||
|
||||
var access = Xml.parse('<test test=\"cool\"><hello>world</hello></test>').firstElement();
|
||||
|
||||
trace(AttribAccess_Impl_.resolve(Access_Impl_.get_att(access), 'test'));
|
||||
|
||||
|
||||
// trace(Access_Impl_.get_att(access));
|
||||
//abstract import haxe.xml.Access;
|
||||
//import haxe.xml.Access with Abstract;
|
||||
|
||||
|
||||
import haxe.xml.Access;
|
||||
|
||||
var access = new Access(Xml.parse('<test test=\"cool\"><hello>world</hello></test>').firstElement());
|
||||
|
||||
trace(access.att.test);
|
||||
"));*/
|
||||
|
||||
/*headerCode = "function area(a:Int, b:Int):Int { return a * b; };";
|
||||
function area(a:Int, b:Int):Int { return a * b; }
|
||||
|
||||
assertEq("[for(i in 0...10) for(j in 0...10) area(i, j)]", [for(i in 0...10) for(j in 0...10) area(i, j)]);*/
|
||||
}
|
||||
|
||||
override function teardown() {
|
||||
super.teardown();
|
||||
}
|
||||
}
|
||||
|
||||
abstract TestAbstract(Int)
|
||||
{
|
||||
//public static inline var TRANSPARENT:TestAbstract = 0x00000000;
|
||||
//public static inline var WHITE:TestAbstract = 0xFFFFFFFF;
|
||||
//public static inline var GRAY:TestAbstract = 0xFF808080;
|
||||
//public static inline var BLACK:TestAbstract = 0xFF000000;
|
||||
}
|
||||
|
||||
enum abstract TestEnumAbstract(Int) {
|
||||
|
||||
}
|
||||
@@ -126,6 +126,8 @@ class FinalCase extends TestCase {
|
||||
import Math.round;
|
||||
round(1.9);", Math.round(1.9));
|
||||
|
||||
trace(Type.resolveClass("hscript._Error.ErrorMessage_Impl_"));
|
||||
|
||||
// Test EOF with preprocessor
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
# File Specific Defines
|
||||
--define windows
|
||||
|
||||
--macro keep('IntIterator')
|
||||
# --macro hscript.macros.UsingHandler.init()
|
||||
# --macro hscript.macros.ClassExtendMacro.init()
|
||||
--macro hscript.macros.AbstractHandler.init()
|
||||
|
||||
# Copying the assets from source code to bin folder
|
||||
# --cmd Xcopy assets\ bin\cpp\assets\ /E /H /C /I /Y
|
||||
--cpp bin/cpp
|
||||
|
||||
Reference in New Issue
Block a user