Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67bb4bab98 | ||
|
|
927f771024 | ||
|
|
8221dca2b0 | ||
|
|
4c218116a6 | ||
|
|
fc15dbd382 | ||
|
|
bb3785c53c | ||
|
|
1892f0793f |
@@ -1,4 +1,2 @@
|
|||||||
/hscript.swf
|
/hscript.swf
|
||||||
/release.zip
|
/release.zip
|
||||||
|
|
||||||
tests/bin/*
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
--macro keep('IntIterator')
|
--macro keep('IntIterator')
|
||||||
--macro hscript.macros.UsingHandler.init()
|
--macro hscript.macros.UsingHandler.init()
|
||||||
--macro hscript.macros.ClassExtendMacro.init()
|
--macro hscript.macros.ClassExtendMacro.init()
|
||||||
|
--macro hscript.macros.AbstractHandler.init()
|
||||||
--define HSCRIPT_NEW
|
--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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,10 +29,6 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function hnew(args:Array<Dynamic>):Dynamic {
|
public function hnew(args:Array<Dynamic>):Dynamic {
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
throw "todo: do all this lmao -lunar";
|
|
||||||
return null;
|
|
||||||
#else
|
|
||||||
var interp = new Interp();
|
var interp = new Interp();
|
||||||
interp.errorHandler = ogInterp.errorHandler;
|
interp.errorHandler = ogInterp.errorHandler;
|
||||||
|
|
||||||
@@ -57,15 +53,8 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var comparisonMap = new Map();
|
|
||||||
for(key => value in interp.variables) {
|
|
||||||
comparisonMap.set(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
_class.__custom__variables = interp.variables;
|
_class.__custom__variables = interp.variables;
|
||||||
|
|
||||||
//trace(fields);
|
|
||||||
|
|
||||||
for(expr in fields) {
|
for(expr in fields) {
|
||||||
@:privateAccess
|
@:privateAccess
|
||||||
interp.exprReturn(expr);
|
interp.exprReturn(expr);
|
||||||
@@ -75,27 +64,12 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
|||||||
|
|
||||||
_class.__interp = interp; // TODO: Remove
|
_class.__interp = interp; // TODO: Remove
|
||||||
interp.scriptObject = _class;
|
interp.scriptObject = _class;
|
||||||
// get only variables that were not set before
|
|
||||||
var classVariables = [for(key => value in interp.variables) if(!comparisonMap.exists(key) || comparisonMap[key] != value) key => value];
|
|
||||||
for(variable => value in classVariables) {
|
|
||||||
if(variable == "this" || variable == "super") continue;
|
|
||||||
@:privateAccess
|
|
||||||
if(!interp.__instanceFields.contains(variable)) {
|
|
||||||
interp.__instanceFields.push(variable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//trace([for(key => value in classVariables) key]);
|
|
||||||
//@:privateAccess
|
|
||||||
//trace(interp.__instanceFields);
|
|
||||||
|
|
||||||
_class.__allowSetGet = false;
|
|
||||||
|
|
||||||
for(variable => value in interp.variables) {
|
for(variable => value in interp.variables) {
|
||||||
if(variable == "this") continue;
|
if(variable == "this") continue;
|
||||||
|
|
||||||
if(variable.startsWith("set_") || variable.startsWith("get_")) {
|
if(variable.startsWith("set_") || variable.startsWith("get_")) {
|
||||||
_class.__allowSetGet = true;
|
_class.__allowSetGet = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,12 +78,7 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
|||||||
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
|
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
var newFunc = interp.variables.get("new");
|
|
||||||
if(newFunc != null) {
|
|
||||||
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
|
|
||||||
}
|
|
||||||
return _class;
|
return _class;
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toString():String {
|
public function toString():String {
|
||||||
@@ -155,6 +124,6 @@ class TemplateClass implements IHScriptCustomClassBehaviour implements IHScriptC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class StaticHandler {
|
class StaticHandler {
|
||||||
public function new() {}
|
public function new() {}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -62,7 +62,7 @@ enum Error_
|
|||||||
EInvalidEscape( s : String );
|
EInvalidEscape( s : String );
|
||||||
}
|
}
|
||||||
|
|
||||||
enum abstract ErrorMessage(Expr.UInt8) from Expr.UInt8 to Expr.UInt8 {
|
enum abstract ErrorMessage(Int) from Int to Int {
|
||||||
final INVALID_CHAR_CODE_MULTI;
|
final INVALID_CHAR_CODE_MULTI;
|
||||||
final FROM_CHAR_CODE_NON_INT;
|
final FROM_CHAR_CODE_NON_INT;
|
||||||
final EMPTY_INTERPOLATION;
|
final EMPTY_INTERPOLATION;
|
||||||
|
|||||||
+35
-221
@@ -21,16 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
|
|
||||||
typedef Int8 = #if cpp cpp.Int8 #else Int #end;
|
|
||||||
typedef Int16 = #if cpp cpp.Int16 #else Int #end;
|
|
||||||
typedef Int32 = #if cpp cpp.Int32 #else Int #end;
|
|
||||||
typedef Int64 = #if cpp cpp.Int64 #else Int #end;
|
|
||||||
|
|
||||||
typedef UInt8 = #if cpp cpp.UInt8 #else Int #end;
|
|
||||||
typedef UInt16 = #if cpp cpp.UInt16 #else Int #end;
|
|
||||||
typedef UInt32 = #if cpp cpp.UInt32 #else Int #end;
|
|
||||||
typedef UInt64 = #if cpp cpp.UInt64 #else Int #end;
|
|
||||||
|
|
||||||
enum Const {
|
enum Const {
|
||||||
CInt( v : Int );
|
CInt( v : Int );
|
||||||
CFloat( f : Float );
|
CFloat( f : Float );
|
||||||
@@ -40,13 +30,12 @@ enum Const {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
enum abstract MapType(UInt8) {
|
enum MapType {
|
||||||
var Null;
|
IntMap;
|
||||||
var IntMap;
|
StringMap;
|
||||||
var StringMap;
|
EnumMap;
|
||||||
var EnumMap;
|
ObjectMap;
|
||||||
var ObjectMap;
|
UnknownMap;
|
||||||
var UnknownMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Error = hscript.Error.Error_;
|
typedef Error = hscript.Error.Error_;
|
||||||
@@ -65,6 +54,10 @@ class Expr {
|
|||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
this.line = line;
|
this.line = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function toString() {
|
||||||
|
return "<Expr " + e + ">";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enum ExprDef
|
enum ExprDef
|
||||||
#else
|
#else
|
||||||
@@ -73,28 +66,28 @@ enum Expr
|
|||||||
#end
|
#end
|
||||||
{
|
{
|
||||||
EConst( c : Const );
|
EConst( c : Const );
|
||||||
EIdent( v : VarN );
|
EIdent( v : String );
|
||||||
EVar( n : VarN, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
|
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
|
||||||
EParent( e : Expr, ?noOptimize : Bool );
|
EParent( e : Expr, ?noOptimize : Bool );
|
||||||
EBlock( e : Array<Expr> );
|
EBlock( e : Array<Expr> );
|
||||||
EField( e : Expr, f : String , ?safe : Bool );
|
EField( e : Expr, f : String , ?safe : Bool );
|
||||||
EBinop( op : Binop, e1 : Expr, e2 : Expr );
|
EBinop( op : String, e1 : Expr, e2 : Expr );
|
||||||
EUnop( op : Unop, prefix : Bool, e : Expr );
|
EUnop( op : String, prefix : Bool, e : Expr );
|
||||||
ECall( e : Expr, params : Array<Expr> );
|
ECall( e : Expr, params : Array<Expr> );
|
||||||
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
||||||
EWhile( cond : Expr, e : Expr );
|
EWhile( cond : Expr, e : Expr );
|
||||||
EFor( v : VarN, it : Expr, e : Expr);
|
EFor( v : String, it : Expr, e : Expr);
|
||||||
EForKeyValue( v : VarN, it : Expr, e : Expr, ithv: VarN);
|
EForKeyValue( v : String, it : Expr, e : Expr, ithv: String);
|
||||||
EBreak;
|
EBreak;
|
||||||
EContinue;
|
EContinue;
|
||||||
EFunction( args : Array<Argument>, e : Expr, ?name : VarN, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||||
EReturn( ?e : Expr );
|
EReturn( ?e : Expr );
|
||||||
EArray( e : Expr, index : Expr );
|
EArray( e : Expr, index : Expr );
|
||||||
EMapDecl( type: MapType, keys: Array<Expr>, values: Array<Expr> );
|
EMapDecl( type: MapType, keys: Array<Expr>, values: Array<Expr> );
|
||||||
EArrayDecl( e : Array<Expr> );
|
EArrayDecl( e : Array<Expr> );
|
||||||
ENew( cl : VarN, params : Array<Expr> );
|
ENew( cl : String, params : Array<Expr> );
|
||||||
EThrow( e : Expr );
|
EThrow( e : Expr );
|
||||||
ETry( e : Expr, v : VarN, t : Null<CType>, ecatch : Expr );
|
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||||
EObject( fl : Array<ObjectField> );
|
EObject( fl : Array<ObjectField> );
|
||||||
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||||
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
||||||
@@ -103,186 +96,12 @@ enum Expr
|
|||||||
ECheckType( e : Expr, t : CType );
|
ECheckType( e : Expr, t : CType );
|
||||||
|
|
||||||
EImport( c : String, mode: KImportMode );
|
EImport( c : String, mode: KImportMode );
|
||||||
EClass( name:VarN, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
||||||
|
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
EInfo( info: InfoClass, e: Expr );
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Binop {
|
|
||||||
/**
|
|
||||||
`+`
|
|
||||||
**/
|
|
||||||
OpAdd;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`*`
|
|
||||||
**/
|
|
||||||
OpMult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`/`
|
|
||||||
**/
|
|
||||||
OpDiv;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`-`
|
|
||||||
**/
|
|
||||||
OpSub;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`=`
|
|
||||||
**/
|
|
||||||
OpAssign;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`==`
|
|
||||||
**/
|
|
||||||
OpEq;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`!=`
|
|
||||||
**/
|
|
||||||
OpNotEq;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`>`
|
|
||||||
**/
|
|
||||||
OpGt;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`>=`
|
|
||||||
**/
|
|
||||||
OpGte;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`<`
|
|
||||||
**/
|
|
||||||
OpLt;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`<=`
|
|
||||||
**/
|
|
||||||
OpLte;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`&`
|
|
||||||
**/
|
|
||||||
OpAnd;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`|`
|
|
||||||
**/
|
|
||||||
OpOr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`^`
|
|
||||||
**/
|
|
||||||
OpXor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`&&`
|
|
||||||
**/
|
|
||||||
OpBoolAnd;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`||`
|
|
||||||
**/
|
|
||||||
OpBoolOr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`<<`
|
|
||||||
**/
|
|
||||||
OpShl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`>>`
|
|
||||||
**/
|
|
||||||
OpShr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`>>>`
|
|
||||||
**/
|
|
||||||
OpUShr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`%`
|
|
||||||
**/
|
|
||||||
OpMod;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`+=` `-=` `/=` `*=` `<<=` `>>=` `>>>=` `|=` `&=` `^=` `%=`
|
|
||||||
**/
|
|
||||||
OpAssignOp(op:Binop);
|
|
||||||
|
|
||||||
/**
|
|
||||||
`...`
|
|
||||||
**/
|
|
||||||
OpInterval;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`=>`
|
|
||||||
**/
|
|
||||||
OpArrow;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`is`
|
|
||||||
**/
|
|
||||||
OpIs; // used to be OpIn, but our system treats that differently
|
|
||||||
|
|
||||||
/**
|
|
||||||
`??`
|
|
||||||
**/
|
|
||||||
OpNullCoal;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum abstract Unop(UInt8) {
|
|
||||||
/**
|
|
||||||
`++`
|
|
||||||
**/
|
|
||||||
var OpIncrement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`--`
|
|
||||||
**/
|
|
||||||
var OpDecrement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`!`
|
|
||||||
**/
|
|
||||||
var OpNot;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`-`
|
|
||||||
**/
|
|
||||||
var OpNeg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`~`
|
|
||||||
**/
|
|
||||||
var OpNegBits;
|
|
||||||
|
|
||||||
/**
|
|
||||||
`...`
|
|
||||||
**/
|
|
||||||
var OpSpread;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
class InfoClass {
|
|
||||||
public var variables:Array<String>;
|
|
||||||
|
|
||||||
public function new(variables:Array<String>) {
|
|
||||||
this.variables = variables;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
enum KImportMode {
|
enum KImportMode {
|
||||||
INormal;
|
INormal;
|
||||||
IAs( name : String );
|
IAs( name : String );
|
||||||
IAsReturn;
|
|
||||||
IAll;
|
IAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,15 +115,20 @@ class ObjectField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@:structInit
|
class SwitchCase {
|
||||||
final class SwitchCase {
|
|
||||||
public var values : Array<Expr>;
|
public var values : Array<Expr>;
|
||||||
public var expr : Expr;
|
public var expr : Expr;
|
||||||
|
|
||||||
|
public function new(values, expr) {
|
||||||
|
this.values = values;
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
//typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
||||||
class Argument {
|
class Argument {
|
||||||
public var name : VarN;
|
public var name : String;
|
||||||
public var t : Null<CType>;
|
public var t : Null<CType>;
|
||||||
public var opt : Bool;
|
public var opt : Bool;
|
||||||
public var value : Null<Expr>;
|
public var value : Null<Expr>;
|
||||||
@@ -314,10 +138,6 @@ class Argument {
|
|||||||
this.opt = opt;
|
this.opt = opt;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toString() {
|
|
||||||
return (opt ? "?" : "") + name + (t != null ? ":" + Printer.convertTypeToString(t) : "") + (value != null ? "=" + Printer.convertExprToString(value) : "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
|
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
|
||||||
@@ -363,13 +183,13 @@ typedef FieldDecl = {
|
|||||||
var access : Array<FieldAccess>;
|
var access : Array<FieldAccess>;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum abstract FieldAccess(UInt8) {
|
enum FieldAccess {
|
||||||
var APublic;
|
APublic;
|
||||||
var APrivate;
|
APrivate;
|
||||||
var AInline;
|
AInline;
|
||||||
var AOverride;
|
AOverride;
|
||||||
var AStatic;
|
AStatic;
|
||||||
var AMacro;
|
AMacro;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FieldKind {
|
enum FieldKind {
|
||||||
@@ -389,9 +209,3 @@ typedef VarDecl = {
|
|||||||
var expr : Null<Expr>;
|
var expr : Null<Expr>;
|
||||||
var type : Null<CType>;
|
var type : Null<CType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
abstract VarN(Dynamic) from Int from String to Int to String {}
|
|
||||||
#else
|
|
||||||
typedef VarN = String;
|
|
||||||
#end
|
|
||||||
+129
-600
File diff suppressed because it is too large
Load Diff
+31
-34
@@ -50,7 +50,6 @@ class Optimizer {
|
|||||||
newExprs.push(e);
|
newExprs.push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mk(EBlock(newExprs), s);
|
return mk(EBlock(newExprs), s);
|
||||||
|
|
||||||
case EIf(econd, e1, e2):
|
case EIf(econd, e1, e2):
|
||||||
@@ -74,7 +73,7 @@ class Optimizer {
|
|||||||
var c2 = getBool(e2);
|
var c2 = getBool(e2);
|
||||||
|
|
||||||
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
||||||
return optimize(mk(EUnop(OpNot, true, econd), s));
|
return optimize(mk(EUnop("!", true, econd), s));
|
||||||
}
|
}
|
||||||
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
||||||
return optimize(mk(Tools.expr(econd), s));
|
return optimize(mk(Tools.expr(econd), s));
|
||||||
@@ -113,7 +112,7 @@ class Optimizer {
|
|||||||
var c2 = getBool(e2);
|
var c2 = getBool(e2);
|
||||||
|
|
||||||
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
||||||
return optimize(mk(EUnop(OpNot, true, econd), s));
|
return optimize(mk(EUnop("!", true, econd), s));
|
||||||
}
|
}
|
||||||
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
||||||
return optimize(mk(Tools.expr(econd), s));
|
return optimize(mk(Tools.expr(econd), s));
|
||||||
@@ -391,9 +390,9 @@ class Optimizer {
|
|||||||
// Possible bugs here
|
// Possible bugs here
|
||||||
if(isNumber(e1) && !isConstant(e2)) {
|
if(isNumber(e1) && !isConstant(e2)) {
|
||||||
var c1 = getNumber(e1);
|
var c1 = getNumber(e1);
|
||||||
if(compareNumber(c1, 0) && op == OpAdd)
|
if(compareNumber(c1, 0) && op == "+")
|
||||||
return mk(Tools.expr(e2), s);
|
return mk(Tools.expr(e2), s);
|
||||||
if(compareNumber(c1, 1) && op == OpMult)
|
if(compareNumber(c1, 1) && op == "*")
|
||||||
return mk(Tools.expr(e2), s);
|
return mk(Tools.expr(e2), s);
|
||||||
//if(compareNumber(c1, 0) && op == "*")
|
//if(compareNumber(c1, 0) && op == "*")
|
||||||
// return mk(convertConstant(0), s);
|
// return mk(convertConstant(0), s);
|
||||||
@@ -401,11 +400,11 @@ class Optimizer {
|
|||||||
|
|
||||||
if(!isConstant(e1) && isNumber(e2)) {
|
if(!isConstant(e1) && isNumber(e2)) {
|
||||||
var c2 = getNumber(e2);
|
var c2 = getNumber(e2);
|
||||||
if(op == OpAdd && compareNumber(c2, 0))
|
if(op == "+" && compareNumber(c2, 0))
|
||||||
return mk(Tools.expr(e1), s);
|
return mk(Tools.expr(e1), s);
|
||||||
if(op == OpDiv && compareNumber(c2, 1))
|
if(op == "/" && compareNumber(c2, 1))
|
||||||
return mk(Tools.expr(e1), s);
|
return mk(Tools.expr(e1), s);
|
||||||
if(op == OpMult && compareNumber(c2, 1))
|
if(op == "*" && compareNumber(c2, 1))
|
||||||
return mk(Tools.expr(e1), s);
|
return mk(Tools.expr(e1), s);
|
||||||
//if(op == "*" && compareNumber(c2, 0))
|
//if(op == "*" && compareNumber(c2, 0))
|
||||||
// return mk(convertConstant(0), s);
|
// return mk(convertConstant(0), s);
|
||||||
@@ -419,12 +418,11 @@ class Optimizer {
|
|||||||
if(isConstant(e) && prefix) {
|
if(isConstant(e) && prefix) {
|
||||||
var constant:Dynamic = getConstant(e);
|
var constant:Dynamic = getConstant(e);
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case OpNeg: return mk(convertConstant(-constant), s);
|
case "-": return mk(convertConstant(-constant), s);
|
||||||
case OpNot: return mk(convertConstant(!constant), s);
|
case "!": return mk(convertConstant(!constant), s);
|
||||||
case OpNegBits:
|
case "~":
|
||||||
var complement = #if (neko && !haxe3) haxe.Int32.complement(constant) #else ~constant #end;
|
var complement = #if (neko && !haxe3) haxe.Int32.complement(constant) #else ~constant #end;
|
||||||
return mk(convertConstant(complement), s);
|
return mk(convertConstant(complement), s);
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,7 +430,6 @@ class Optimizer {
|
|||||||
default:
|
default:
|
||||||
Sys.println("Unknown expr: " + e);
|
Sys.println("Unknown expr: " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,29 +603,29 @@ class Optimizer {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
static function optimizeOp(op:Binop, f1:Dynamic, f2:Dynamic):Dynamic {
|
static function optimizeOp(op, f1:Dynamic, f2:Dynamic):Dynamic {
|
||||||
//trace("Optimizing " + f1 + " " + op + " " + f2);
|
//trace("Optimizing " + f1 + " " + op + " " + f2);
|
||||||
return switch(op) {
|
return switch(op) {
|
||||||
case OpAdd: f1 + f2;
|
case "+": f1 + f2;
|
||||||
case OpSub: f1 - f2;
|
case "-": f1 - f2;
|
||||||
case OpMult: f1 * f2;
|
case "*": f1 * f2;
|
||||||
case OpDiv: f1 / f2;
|
case "/": f1 / f2;
|
||||||
case OpMod: f1 % f2;
|
case "%": f1 % f2;
|
||||||
case OpAnd: f1 & f2;
|
case "&": f1 & f2;
|
||||||
case OpOr: f1 | f2;
|
case "|": f1 | f2;
|
||||||
case OpXor: f1 ^ f2;
|
case "^": f1 ^ f2;
|
||||||
case OpShl: f1 << f2;
|
case "<<": f1 << f2;
|
||||||
case OpShr: f1 >> f2;
|
case ">>": f1 >> f2;
|
||||||
case OpUShr: f1 >>> f2;
|
case ">>>": f1 >>> f2;
|
||||||
case OpEq: f1 == f2;
|
case "==": f1 == f2;
|
||||||
case OpNotEq: f1 != f2;
|
case "!=": f1 != f2;
|
||||||
case OpGte: f1 >= f2;
|
case ">=": f1 >= f2;
|
||||||
case OpLte: f1 <= f2;
|
case "<=": f1 <= f2;
|
||||||
case OpGt: f1 > f2;
|
case ">": f1 > f2;
|
||||||
case OpLt: f1 < f2;
|
case "<": f1 < f2;
|
||||||
case OpBoolOr: f1 == true || f2 == true;
|
case "||": f1 == true || f2 == true;
|
||||||
case OpBoolAnd: f1 == true && f2 == true;
|
case "&&": f1 == true && f2 == true;
|
||||||
case OpNullCoal: f1 == null ? f2 : f1;
|
case "??": f1 == null ? f2 : f1;
|
||||||
default: null;
|
default: null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+78
-70
@@ -224,14 +224,13 @@ class Parser {
|
|||||||
parseFullExpr(a);
|
parseFullExpr(a);
|
||||||
}
|
}
|
||||||
var expr = if( a.length == 1 ) a[0] else mk(EBlock(a),0);
|
var expr = if( a.length == 1 ) a[0] else mk(EBlock(a),0);
|
||||||
|
expr = AbstractProcessor.process(expr);
|
||||||
expr = Preprocessor.process(expr);
|
expr = Preprocessor.process(expr);
|
||||||
if(Parser.optimize)
|
if(Parser.optimize) {
|
||||||
expr = Optimizer.optimize(expr);
|
expr = Optimizer.optimize(expr);
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
trace("INPUT: " + s);
|
||||||
expr = Postprocessor.processvars(expr);
|
trace("OUTPUT: " + Printer.toString(expr));
|
||||||
#end
|
}
|
||||||
// trace("INPUT: " + s); // useful for debugging
|
|
||||||
//trace("OUTPUT: " + Printer.toString(expr));
|
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,8 +399,10 @@ class Parser {
|
|||||||
function parseExprFromTokens(t:TokenList) {
|
function parseExprFromTokens(t:TokenList) {
|
||||||
var oldPos = readPos;
|
var oldPos = readPos;
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
var oldTokenMin = tokenMin;
|
var _oldTokenMin = tokenMin;
|
||||||
var oldTokenMax = tokenMax;
|
var _oldTokenMax = tokenMax;
|
||||||
|
var oldOldTokenMin = oldTokenMin;
|
||||||
|
var oldOldTokenMax = oldTokenMax;
|
||||||
#end
|
#end
|
||||||
var oldTokens = tokens;
|
var oldTokens = tokens;
|
||||||
|
|
||||||
@@ -409,7 +410,11 @@ class Parser {
|
|||||||
// unsure about these
|
// unsure about these
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
tokenMin = 0;
|
tokenMin = 0;
|
||||||
tokenMax = t.length - 1;
|
//tokenMax = t.length - 1;
|
||||||
|
tokenMax = 0;
|
||||||
|
oldTokenMin = 0;
|
||||||
|
oldTokenMax = 0;
|
||||||
|
//oldTokenMax = t.length - 1;
|
||||||
#end
|
#end
|
||||||
readPos = 0;
|
readPos = 0;
|
||||||
//trace(t.map(getTk).map(tokenString));
|
//trace(t.map(getTk).map(tokenString));
|
||||||
@@ -420,6 +425,8 @@ class Parser {
|
|||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
tokenMin = oldTokenMin;
|
tokenMin = oldTokenMin;
|
||||||
tokenMax = oldTokenMax;
|
tokenMax = oldTokenMax;
|
||||||
|
oldTokenMin = oldOldTokenMin;
|
||||||
|
oldTokenMax = oldOldTokenMax;
|
||||||
#end
|
#end
|
||||||
readPos = oldPos;
|
readPos = oldPos;
|
||||||
return e;
|
return e;
|
||||||
@@ -467,7 +474,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
e = mk(EBinop(OpAdd, e, er));
|
e = mk(EBinop("+", e, er));
|
||||||
//e = mk(EParent(e));
|
//e = mk(EParent(e));
|
||||||
}
|
}
|
||||||
while(tg.length > 0) {
|
while(tg.length > 0) {
|
||||||
@@ -606,8 +613,9 @@ class Parser {
|
|||||||
var tmp2 = "__m_" + (uid++);
|
var tmp2 = "__m_" + (uid++);
|
||||||
var e = mk(EBlock([
|
var e = mk(EBlock([
|
||||||
// TODO: Make it detect simple map comprehensions so we can optimize the map type
|
// 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
|
// TODO: make it detect the type from nextType
|
||||||
mk(EVar(tmp2, null, mk(EField(mk(EIdent(tmp), p1), "set"), p1)), p1),
|
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]),
|
mapMapCompr(tmp2, a[0]),
|
||||||
mk(EIdent(tmp),p1),
|
mk(EIdent(tmp),p1),
|
||||||
]),p1);
|
]),p1);
|
||||||
@@ -617,8 +625,8 @@ class Parser {
|
|||||||
var tmp = "__a_" + (uid++);
|
var tmp = "__a_" + (uid++);
|
||||||
var tmp2 = "__a_" + (uid++);
|
var tmp2 = "__a_" + (uid++);
|
||||||
var e = mk(EBlock([
|
var e = mk(EBlock([
|
||||||
mk(EVar(tmp, null, mk(EArrayDecl([]), p1)), p1),
|
mk(EVar(tmp, parseTypeString("Array<Dynamic>"), mk(EArrayDecl([]), p1)), p1),
|
||||||
mk(EVar(tmp2, null, mk(EField(mk(EIdent(tmp), p1), "push"), p1)), p1),
|
mk(EVar(tmp2, parseTypeString("(Dynamic) -> Int"), mk(EField(mk(EIdent(tmp), p1), "push"), p1)), p1),
|
||||||
mapArrCompr(tmp2, a[0]),
|
mapArrCompr(tmp2, a[0]),
|
||||||
mk(EIdent(tmp),p1),
|
mk(EIdent(tmp),p1),
|
||||||
]),p1);
|
]),p1);
|
||||||
@@ -630,7 +638,7 @@ class Parser {
|
|||||||
var isTypeMap = (nextType != null) && nextType.match(CTPath(["Map"], [_, _]));
|
var isTypeMap = (nextType != null) && nextType.match(CTPath(["Map"], [_, _]));
|
||||||
var isMap = isTypeMap;
|
var isMap = isTypeMap;
|
||||||
if(!isMap) {
|
if(!isMap) {
|
||||||
isMap = Lambda.exists(a, (e) -> Tools.expr(e).match(EBinop(OpArrow, _))); // Check if any element is a => b
|
isMap = Lambda.exists(a, (e) -> Tools.expr(e).match(EBinop("=>", _))); // Check if any element is a => b
|
||||||
}
|
}
|
||||||
if(isMap) {
|
if(isMap) {
|
||||||
// TODO: clean up this code more
|
// TODO: clean up this code more
|
||||||
@@ -642,7 +650,7 @@ class Parser {
|
|||||||
var values:Array<Expr> = [];
|
var values:Array<Expr> = [];
|
||||||
for (e in a) {
|
for (e in a) {
|
||||||
switch (Tools.expr(e)) {
|
switch (Tools.expr(e)) {
|
||||||
case EBinop(OpArrow, eKey, eValue): {
|
case EBinop("=>", eKey, eValue): {
|
||||||
switch(Tools.expr(eKey)) {
|
switch(Tools.expr(eKey)) {
|
||||||
case EConst(CInt(_)):// | EConst(CFloat(_)):
|
case EConst(CInt(_)):// | EConst(CFloat(_)):
|
||||||
isKeyInt = true;
|
isKeyInt = true;
|
||||||
@@ -676,14 +684,14 @@ class Parser {
|
|||||||
|
|
||||||
var t = b2i(isKeyString) + b2i(isKeyInt) + b2i(isKeyObject) + b2i(isKeyEnum);
|
var t = b2i(isKeyString) + b2i(isKeyInt) + b2i(isKeyObject) + b2i(isKeyEnum);
|
||||||
|
|
||||||
var type:MapType = Null;
|
var type:MapType = null;
|
||||||
if(t != 1) type = UnknownMap;
|
if(t != 1) type = UnknownMap;
|
||||||
else if(isKeyInt) type = IntMap;
|
else if(isKeyInt) type = IntMap;
|
||||||
else if(isKeyString) type = StringMap;
|
else if(isKeyString) type = StringMap;
|
||||||
else if(isKeyEnum) type = EnumMap;
|
else if(isKeyEnum) type = EnumMap;
|
||||||
else if(isKeyObject) type = ObjectMap;
|
else if(isKeyObject) type = ObjectMap;
|
||||||
|
|
||||||
if(type == Null)
|
if(type == null)
|
||||||
error(EPreset(UNKNOWN_MAP_TYPE), p1, p1);
|
error(EPreset(UNKNOWN_MAP_TYPE), p1, p1);
|
||||||
|
|
||||||
return parseExprNext(mk(EMapDecl(type, keys, values), p1));
|
return parseExprNext(mk(EMapDecl(type, keys, values), p1));
|
||||||
@@ -697,12 +705,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if cpp
|
|
||||||
static inline function b2i(b:Bool) return untyped __cpp__("({0} ? 1 : 0)", b);
|
|
||||||
//static inline function b2i(b:Bool) return untyped __cpp__("(int)({0})", b);
|
|
||||||
#else
|
|
||||||
static inline function b2i(b:Bool) return b ? 1 : 0;
|
static inline function b2i(b:Bool) return b ? 1 : 0;
|
||||||
#end
|
|
||||||
|
|
||||||
function parseLambda( args : Array<Argument>, pmin ) {
|
function parseLambda( args : Array<Argument>, pmin ) {
|
||||||
while( true ) {
|
while( true ) {
|
||||||
@@ -797,7 +800,7 @@ class Parser {
|
|||||||
default:
|
default:
|
||||||
// tmp.set(k, v);
|
// tmp.set(k, v);
|
||||||
switch( Tools.expr(e) ) {
|
switch( Tools.expr(e) ) {
|
||||||
case EBinop(OpArrow, e1, e2):
|
case EBinop("=>", e1, e2):
|
||||||
//ECall( mk(EField(mk(EIdent(tmp), pmin(e), pmax(e)), "set"), pmin(e), pmax(e)), [e1, e2]);
|
//ECall( mk(EField(mk(EIdent(tmp), pmin(e), pmax(e)), "set"), pmin(e), pmax(e)), [e1, e2]);
|
||||||
ECall( mk(EIdent(tmp), pmin(e), pmax(e)), [e1, e2]);
|
ECall( mk(EIdent(tmp), pmin(e), pmax(e)), [e1, e2]);
|
||||||
default: // default incase of error
|
default: // default incase of error
|
||||||
@@ -830,48 +833,37 @@ class Parser {
|
|||||||
isMapCompr(e2);
|
isMapCompr(e2);
|
||||||
default:
|
default:
|
||||||
// tmp.set(k, v);
|
// tmp.set(k, v);
|
||||||
return Tools.expr(e).match(EBinop(OpArrow, _));
|
return Tools.expr(e).match(EBinop("=>", _));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeUnop( op:String, e:Expr ):Expr {
|
function makeUnop( op, e ) {
|
||||||
var op = Tools.getUnopEnum(op);
|
|
||||||
return _makeUnop(op, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _makeUnop( op:Unop, e:Expr ):Expr {
|
|
||||||
if( e == null && resumeErrors )
|
if( e == null && resumeErrors )
|
||||||
return null;
|
return null;
|
||||||
return switch( Tools.expr(e) ) {
|
return switch( Tools.expr(e) ) {
|
||||||
case EBinop(bop, e1, e2): mk(EBinop(bop, _makeUnop(op, e1), e2), pmin(e1), pmax(e2));
|
case EBinop(bop, e1, e2): mk(EBinop(bop, makeUnop(op, e1), e2), pmin(e1), pmax(e2));
|
||||||
case ETernary(e1, e2, e3): mk(ETernary(_makeUnop(op, e1), e2, e3), pmin(e1), pmax(e3));
|
case ETernary(e1, e2, e3): mk(ETernary(makeUnop(op, e1), e2, e3), pmin(e1), pmax(e3));
|
||||||
default: mk(EUnop(op,true,e),pmin(e),pmax(e));
|
default: mk(EUnop(op,true,e),pmin(e),pmax(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeBinop( op:String, e1:Expr, e:Expr ) {
|
function makeBinop( op, e1, e ) {
|
||||||
// TODO: clean this up
|
// TODO: clean this up
|
||||||
if(!Tools.isValidBinOp(op))
|
if(!Tools.isValidBinOp(op))
|
||||||
error(EInvalidOp(op),pmin(e1),pmax(e1));
|
error(EInvalidOp(op),pmin(e1),pmax(e1));
|
||||||
var op = Tools.getOpEnum(op);
|
|
||||||
return _makeBinop(op, e1, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _makeBinop( op:Binop, e1:Expr, e:Expr ) {
|
|
||||||
// TODO: clean this up
|
|
||||||
if( e == null && resumeErrors )
|
if( e == null && resumeErrors )
|
||||||
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
|
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
|
||||||
return switch( Tools.expr(e) ) {
|
return switch( Tools.expr(e) ) {
|
||||||
case EBinop(op2,e2,e3):
|
case EBinop(op2,e2,e3):
|
||||||
if( opPriority.get(Printer.getBinaryOp(op)) <= opPriority.get(Printer.getBinaryOp(op2)) && !opRightAssoc.exists(Printer.getBinaryOp(op)) )
|
if( opPriority.get(op) <= opPriority.get(op2) && !opRightAssoc.exists(op) )
|
||||||
mk(EBinop(op2,_makeBinop(op,e1,e2),e3),pmin(e1),pmax(e3));
|
mk(EBinop(op2,makeBinop(op,e1,e2),e3),pmin(e1),pmax(e3));
|
||||||
else
|
else
|
||||||
mk(EBinop(op, e1, e), pmin(e1), pmax(e));
|
mk(EBinop(op, e1, e), pmin(e1), pmax(e));
|
||||||
case ETernary(e2,e3,e4):
|
case ETernary(e2,e3,e4):
|
||||||
if( opRightAssoc.exists(Printer.getBinaryOp(op)) )
|
if( opRightAssoc.exists(op) )
|
||||||
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
||||||
else
|
else
|
||||||
mk(ETernary(_makeBinop(op, e1, e2), e3, e4), pmin(e1), pmax(e));
|
mk(ETernary(makeBinop(op, e1, e2), e3, e4), pmin(e1), pmax(e));
|
||||||
default:
|
default:
|
||||||
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
||||||
}
|
}
|
||||||
@@ -1185,12 +1177,10 @@ class Parser {
|
|||||||
|
|
||||||
var fields = [];
|
var fields = [];
|
||||||
ensure(TBrOpen);
|
ensure(TBrOpen);
|
||||||
while( true ) {
|
while( !maybe(TBrClose) ) {
|
||||||
parseFullExpr(fields);
|
if(token() == TSemicolon) continue;
|
||||||
tk = token();
|
var a = parseExpr();
|
||||||
if( tk == TBrClose || (resumeErrors && tk == TEof) )
|
fields.push(a);
|
||||||
break;
|
|
||||||
push(tk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tk = token();
|
var tk = token();
|
||||||
@@ -1244,7 +1234,7 @@ class Parser {
|
|||||||
var tk = token();
|
var tk = token();
|
||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
case TId("case"):
|
case TId("case"):
|
||||||
var c:SwitchCase = { values : [], expr : null };
|
var c = new SwitchCase([], null);
|
||||||
cases.push(c);
|
cases.push(c);
|
||||||
disableOrOp = true;
|
disableOrOp = true;
|
||||||
while( true ) {
|
while( true ) {
|
||||||
@@ -1347,7 +1337,7 @@ class Parser {
|
|||||||
push(tk);
|
push(tk);
|
||||||
return e1;
|
return e1;
|
||||||
}
|
}
|
||||||
return parseExprNext(mk(EUnop(Tools.getUnopEnum(op),false,e1),pmin(e1)));
|
return parseExprNext(mk(EUnop(op,false,e1),pmin(e1)));
|
||||||
}
|
}
|
||||||
return makeBinop(op,e1,parseExpr());
|
return makeBinop(op,e1,parseExpr());
|
||||||
case TDot | TQuestionDot:
|
case TDot | TQuestionDot:
|
||||||
@@ -1441,8 +1431,27 @@ class Parser {
|
|||||||
return path;
|
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 {
|
function parseType() : CType {
|
||||||
var t = token();
|
var t = token();
|
||||||
|
trace("Token: " + tokenString(t));
|
||||||
|
if( t == TEof ) return null;
|
||||||
switch( t ) {
|
switch( t ) {
|
||||||
case TId(v):
|
case TId(v):
|
||||||
push(t);
|
push(t);
|
||||||
@@ -1457,18 +1466,18 @@ class Parser {
|
|||||||
params.push(parseType());
|
params.push(parseType());
|
||||||
t = token();
|
t = token();
|
||||||
switch( t ) {
|
switch( t ) {
|
||||||
case TComma: continue;
|
case TComma: continue;
|
||||||
case TOp(op):
|
case TOp(op):
|
||||||
if( op == ">" ) break;
|
if( op == ">" ) break;
|
||||||
if( op.charCodeAt(0) == ">".code ) {
|
if( op.charCodeAt(0) == ">".code ) {
|
||||||
tokens.add(realToken(
|
tokens.add(realToken(
|
||||||
TOp(op.substr(1)),
|
TOp(op.substr(1)),
|
||||||
tokenMax - op.length - 1,
|
tokenMax - op.length - 1,
|
||||||
tokenMax
|
tokenMax
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
unexpected(t);
|
unexpected(t);
|
||||||
break;
|
break;
|
||||||
@@ -2092,7 +2101,6 @@ class Parser {
|
|||||||
oldTokenMax = tokenMax;
|
oldTokenMax = tokenMax;
|
||||||
tokenMin = (this.char < 0) ? readPos : readPos - 1;
|
tokenMin = (this.char < 0) ? readPos : readPos - 1;
|
||||||
var t = _token();
|
var t = _token();
|
||||||
//trace(t, infos);
|
|
||||||
//ttrace(t, infos);
|
//ttrace(t, infos);
|
||||||
tokenMax = (this.char < 0) ? readPos - 1 : readPos - 2;
|
tokenMax = (this.char < 0) ? readPos - 1 : readPos - 2;
|
||||||
return t;
|
return t;
|
||||||
@@ -2290,7 +2298,7 @@ class Parser {
|
|||||||
case '?'.code:
|
case '?'.code:
|
||||||
var orp = readPos;
|
var orp = readPos;
|
||||||
if (readChar() == '='.code)
|
if (readChar() == '='.code)
|
||||||
return TOp("??" + "=");
|
return TOp("??"+"=");
|
||||||
|
|
||||||
this.readPos = orp;
|
this.readPos = orp;
|
||||||
return TOp("??");
|
return TOp("??");
|
||||||
@@ -2479,7 +2487,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
mk(EIdent(id), tokenMin, tokenMax);
|
mk(EIdent(id), tokenMin, tokenMax);
|
||||||
case TOp("!"):
|
case TOp("!"):
|
||||||
mk(EUnop(OpNot, true, parsePreproCond()), tokenMin, tokenMax);
|
mk(EUnop("!", true, parsePreproCond()), tokenMin, tokenMax);
|
||||||
default:
|
default:
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
}
|
}
|
||||||
@@ -2497,13 +2505,13 @@ class Parser {
|
|||||||
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName() + " with " + Tools.expr(e2).getName()), readPos, readPos);
|
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName() + " with " + Tools.expr(e2).getName()), readPos, readPos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case EUnop(OpNot, _, e):
|
case EUnop("!", _, e):
|
||||||
return !evalPreproCond(e);
|
return !evalPreproCond(e);
|
||||||
case EParent(e):
|
case EParent(e):
|
||||||
return evalPreproCond(e);
|
return evalPreproCond(e);
|
||||||
case EBinop(OpBoolAnd, e1, e2):
|
case EBinop("&&", e1, e2):
|
||||||
return evalPreproCond(e1) && evalPreproCond(e2);
|
return evalPreproCond(e1) && evalPreproCond(e2);
|
||||||
case EBinop(OpBoolOr, e1, e2):
|
case EBinop("||", e1, e2):
|
||||||
return evalPreproCond(e1) || evalPreproCond(e2);
|
return evalPreproCond(e1) || evalPreproCond(e2);
|
||||||
default:
|
default:
|
||||||
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName()), readPos, readPos);
|
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName()), readPos, readPos);
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
package hscript;
|
|
||||||
|
|
||||||
import hscript.Expr;
|
|
||||||
import hscript.Error;
|
|
||||||
import hscript.Tools;
|
|
||||||
import hscript.Parser;
|
|
||||||
|
|
||||||
@:access(hscript.Parser)
|
|
||||||
class Postprocessor {
|
|
||||||
static inline function expr(e:Expr) return Tools.expr(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
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
public static function processvars(e:Expr, ?vars:Array<String>) {
|
|
||||||
if(vars == null) vars = [];
|
|
||||||
for(v in getvars(e)) vars.push(v);
|
|
||||||
e = _processvars(e, vars);
|
|
||||||
|
|
||||||
return mk(EInfo(new InfoClass(vars), e), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function _processvars(e:Expr, vars:Array<String>):Expr {
|
|
||||||
if(e == null) return null;
|
|
||||||
var ge = e;
|
|
||||||
var doExtra = true;
|
|
||||||
var e = switch (expr(e)) {
|
|
||||||
case EIdent(v) if (v is String):
|
|
||||||
mk(EIdent(vars.indexOf(v)), e);
|
|
||||||
case EVar(n, t, _e, p, s) if (n is String):
|
|
||||||
mk(EVar(vars.indexOf(n), t, _e, p, s), e);
|
|
||||||
case EImport(c, IAs(n)) if (n is String):
|
|
||||||
mk(EVar(vars.indexOf(n), null, mk(EImport(c, IAsReturn), e), false, false), e);
|
|
||||||
case EFunction(args, _e, n, r, p, s, o) if (n is String):
|
|
||||||
var _args:Array<Argument> = [
|
|
||||||
for (arg in args)
|
|
||||||
new Argument(vars.indexOf(arg.name), arg.t, arg.opt, arg.value)
|
|
||||||
];
|
|
||||||
mk(EFunction(_args, _e, vars.indexOf(n), r, p, s, o), e);
|
|
||||||
case EFunction(args, _e, null, r, p, s, o):
|
|
||||||
var _args:Array<Argument> = [
|
|
||||||
for (arg in args)
|
|
||||||
new Argument(vars.indexOf(arg.name), arg.t, arg.opt, arg.value)
|
|
||||||
];
|
|
||||||
mk(EFunction(_args, _e, null, r, p, s, o), e);
|
|
||||||
case ENew(cl, p) if (cl is String):
|
|
||||||
var p = [for(arg in p) arg];
|
|
||||||
mk(ENew(vars.indexOf(cl), p), e);
|
|
||||||
case EClass(n, fls, extnd, i) if (n is String):
|
|
||||||
var fls:Array<Expr> = [for(f in fls) f];
|
|
||||||
mk(EClass(vars.indexOf(n), fls, extnd, i), e);
|
|
||||||
case ETry(_e, v, t, ec) if (v is String):
|
|
||||||
mk(ETry(_e, vars.indexOf(v), t, ec), e);
|
|
||||||
case EFor(v, it, _e) if (v is String):
|
|
||||||
mk(EFor(vars.indexOf(v), it, _e), e);
|
|
||||||
case EForKeyValue(v, it, _e, ithv) if (v is String && ithv is String):
|
|
||||||
mk(EForKeyValue(vars.indexOf(v), it, _e, vars.indexOf(ithv)), e);
|
|
||||||
default: {
|
|
||||||
doExtra = false;
|
|
||||||
e;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
e = Tools.map(e, function(e) {
|
|
||||||
return _processvars(e, vars);
|
|
||||||
});
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getvars(se:Expr, ?vars:Array<String>):Array<String> {
|
|
||||||
inline function pushVar(v:VarN) {
|
|
||||||
if(v is String) {
|
|
||||||
var v:String = cast v;
|
|
||||||
if (!vars.contains(v))
|
|
||||||
vars.push(v);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(vars == null) vars = [];
|
|
||||||
Tools.iterExprRecursive(se, (e) -> {
|
|
||||||
switch (expr(e)) {
|
|
||||||
case EVar(n, t, e, _,_): pushVar(n);
|
|
||||||
case EIdent(v): pushVar(v);
|
|
||||||
case EFunction(args,e,name,_,_,_,_):
|
|
||||||
pushVar(name);
|
|
||||||
for (a in args) {
|
|
||||||
pushVar(a.name);
|
|
||||||
}
|
|
||||||
case EFor(v,it,e): pushVar(v);
|
|
||||||
case EForKeyValue(v,it,e,ithv): pushVar(ithv); pushVar(v);
|
|
||||||
case ETry(e, v, _, ec): pushVar(v);
|
|
||||||
case ENew(cl, params): pushVar(cl);
|
|
||||||
case EClass(name, fls,_,_): pushVar(name);
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return vars;
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
+292
-357
@@ -78,14 +78,11 @@ class Printer {
|
|||||||
type(t);
|
type(t);
|
||||||
case CTFun(args, ret) if (Lambda.exists(args, function (a) return a.match(CTNamed(_, _)))):
|
case CTFun(args, ret) if (Lambda.exists(args, function (a) return a.match(CTNamed(_, _)))):
|
||||||
add('(');
|
add('(');
|
||||||
var first = true;
|
for (a in args)
|
||||||
for (i=>a in args) {
|
|
||||||
switch a {
|
switch a {
|
||||||
case CTNamed(_, _): type(a);
|
case CTNamed(_, _): type(a);
|
||||||
default: type(CTNamed('_', a));
|
default: type(CTNamed('_', a));
|
||||||
}
|
}
|
||||||
if( i != args.length - 1 ) add(", ");
|
|
||||||
}
|
|
||||||
add(')->');
|
add(')->');
|
||||||
type(ret);
|
type(ret);
|
||||||
case CTFun(args, ret):
|
case CTFun(args, ret):
|
||||||
@@ -204,59 +201,6 @@ class Printer {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVar(v:VarN) {
|
|
||||||
if( v == null ) {
|
|
||||||
return ("??NULL??");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(v is Int) {
|
|
||||||
return ("$" + v);
|
|
||||||
} else {
|
|
||||||
return (v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getBinaryOp(op:Binop) {
|
|
||||||
return switch(op) {
|
|
||||||
case OpAdd: "+";
|
|
||||||
case OpSub: "-";
|
|
||||||
case OpMult: "*";
|
|
||||||
case OpDiv: "/";
|
|
||||||
case OpMod: "%";
|
|
||||||
case OpAnd: "&";
|
|
||||||
case OpOr: "|";
|
|
||||||
case OpXor: "^";
|
|
||||||
case OpShl: "<<";
|
|
||||||
case OpShr: ">>";
|
|
||||||
case OpUShr: ">>>";
|
|
||||||
case OpEq: "==";
|
|
||||||
case OpNotEq: "!=";
|
|
||||||
case OpGt: ">";
|
|
||||||
case OpGte: ">=";
|
|
||||||
case OpLt: "<";
|
|
||||||
case OpLte: "<=";
|
|
||||||
case OpBoolAnd: "&&";
|
|
||||||
case OpBoolOr: "||";
|
|
||||||
case OpIs: "is";
|
|
||||||
case OpNullCoal: "??";
|
|
||||||
case OpAssign: "=";
|
|
||||||
case OpArrow: "=>";
|
|
||||||
case OpInterval: "...";
|
|
||||||
case OpAssignOp(op): getBinaryOp(op) + "=";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getUnaryOp(op:Unop) {
|
|
||||||
return switch(op) {
|
|
||||||
case OpIncrement: "++";
|
|
||||||
case OpDecrement: "--";
|
|
||||||
case OpNot: "!";
|
|
||||||
case OpNeg: "-";
|
|
||||||
case OpNegBits: "~";
|
|
||||||
case OpSpread: "...";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function expr( e : Expr ) {
|
function expr( e : Expr ) {
|
||||||
if( e == null ) {
|
if( e == null ) {
|
||||||
add("??NULL??");
|
add("??NULL??");
|
||||||
@@ -266,140 +210,298 @@ class Printer {
|
|||||||
// TODO: make else if print correctly
|
// TODO: make else if print correctly
|
||||||
|
|
||||||
switch( Tools.expr(e) ) {
|
switch( Tools.expr(e) ) {
|
||||||
case EImport(c, mode):
|
case EImport(c, mode):
|
||||||
add("import " + c);
|
add("import " + c);
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case IAs(name): add(' as $name');
|
case IAs(name): add(' as $name');
|
||||||
case IAll: add('.*');
|
case IAll: add('.*');
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
case EClass(name, fields, extend, interfaces):
|
||||||
|
add('class $name');
|
||||||
|
if (extend != null)
|
||||||
|
add(' extends $extend');
|
||||||
|
for(_interface in interfaces) {
|
||||||
|
add(' implements $_interface');
|
||||||
|
}
|
||||||
|
add(' {\n');
|
||||||
|
tabs += "\t";
|
||||||
|
// TODO: Print fields
|
||||||
|
//for(field in fields) {
|
||||||
|
// expr(field);
|
||||||
|
//}
|
||||||
|
|
||||||
|
tabs = tabs.substr(1);
|
||||||
|
add("}");
|
||||||
|
case EConst(c):
|
||||||
|
switch( c ) {
|
||||||
|
case CInt(i): add(i);
|
||||||
|
case CFloat(f): add(f);
|
||||||
|
case CString(s):
|
||||||
|
add('"');
|
||||||
|
add(getEscapedString(s));
|
||||||
|
add('"');
|
||||||
|
}
|
||||||
|
case EIdent(v):
|
||||||
|
add(v);
|
||||||
|
case EVar(n, t, e): // TODO: static, public, override
|
||||||
|
add("var " + n);
|
||||||
|
if( t != null )
|
||||||
|
addType(t);
|
||||||
|
else
|
||||||
|
switch( Tools.expr(e) ) {
|
||||||
|
case EMapDecl(type, _, _):
|
||||||
|
add(" : Map<");
|
||||||
|
switch( type ) {
|
||||||
|
case ObjectMap: add("Dynamic");
|
||||||
|
case StringMap: add("String");
|
||||||
|
case EnumMap: add("EnumValue");
|
||||||
|
case IntMap: add("Int");
|
||||||
|
case UnknownMap: add("?");
|
||||||
|
}
|
||||||
|
add(", Dynamic>");
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
case EClass(name, fields, extend, interfaces):
|
if( e != null ) {
|
||||||
add('class ${getVar(name)}');
|
add(" = ");
|
||||||
if (extend != null)
|
|
||||||
add(' extends $extend');
|
|
||||||
for(_interface in interfaces) {
|
|
||||||
add(' implements $_interface');
|
|
||||||
}
|
|
||||||
add(' {\n');
|
|
||||||
tabs += "\t";
|
|
||||||
// TODO: Print fields
|
|
||||||
//for(field in fields) {
|
|
||||||
// expr(field);
|
|
||||||
//}
|
|
||||||
|
|
||||||
tabs = tabs.substr(1);
|
|
||||||
add("}");
|
|
||||||
case EConst(c):
|
|
||||||
switch( c ) {
|
|
||||||
case CInt(i): add(i);
|
|
||||||
case CFloat(f): add(f);
|
|
||||||
case CString(s):
|
|
||||||
add('"');
|
|
||||||
add(getEscapedString(s));
|
|
||||||
add('"');
|
|
||||||
}
|
|
||||||
case EIdent(v):
|
|
||||||
add(getVar(v));
|
|
||||||
case EVar(n, t, e): // TODO: static, public, override
|
|
||||||
add("var " + getVar(n));
|
|
||||||
if( t != null )
|
|
||||||
addType(t);
|
|
||||||
else
|
|
||||||
switch( Tools.expr(e) ) {
|
|
||||||
case EMapDecl(type, _, _):
|
|
||||||
add(" : Map<");
|
|
||||||
switch( type ) {
|
|
||||||
case ObjectMap: add("Dynamic");
|
|
||||||
case StringMap: add("String");
|
|
||||||
case EnumMap: add("EnumValue");
|
|
||||||
case IntMap: add("Int");
|
|
||||||
case UnknownMap: add("?");
|
|
||||||
case Null: add("Null");
|
|
||||||
}
|
|
||||||
add(", Dynamic>");
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
if( e != null ) {
|
|
||||||
add(" = ");
|
|
||||||
expr(e);
|
|
||||||
}
|
|
||||||
case EParent(e):
|
|
||||||
add("("); expr(e); add(")");
|
|
||||||
case EBlock(el):
|
|
||||||
if( el.length == 0 ) {
|
|
||||||
add("{}");
|
|
||||||
} else {
|
|
||||||
tabs += "\t";
|
|
||||||
add("{\n");
|
|
||||||
for( e in el ) {
|
|
||||||
add(tabs);
|
|
||||||
expr(e);
|
|
||||||
add(";\n");
|
|
||||||
}
|
|
||||||
tabs = tabs.substr(1);
|
|
||||||
add(tabs);
|
|
||||||
add("}");
|
|
||||||
}
|
|
||||||
case EField(e, f, s):
|
|
||||||
expr(e);
|
expr(e);
|
||||||
add((s == true ? "?." : ".") + f);
|
}
|
||||||
case EBinop(op, e1, e2):
|
case EParent(e):
|
||||||
/*var op1 = switch(Tools.expr(e1)) {
|
add("("); expr(e); add(")");
|
||||||
case EBinop(op, _, _): op;
|
case EBlock(el):
|
||||||
case EConst(_): "_";
|
if( el.length == 0 ) {
|
||||||
case EIdent(_): "_";
|
add("{}");
|
||||||
default: null;
|
} else {
|
||||||
|
tabs += "\t";
|
||||||
|
add("{\n");
|
||||||
|
for( e in el ) {
|
||||||
|
add(tabs);
|
||||||
|
expr(e);
|
||||||
|
add(";\n");
|
||||||
}
|
}
|
||||||
var op2 = switch(Tools.expr(e2)) {
|
tabs = tabs.substr(1);
|
||||||
case EBinop(op, _, _): op;
|
add(tabs);
|
||||||
case EConst(_): "_";
|
add("}");
|
||||||
case EIdent(_): "_";
|
}
|
||||||
default: null;
|
case EField(e, f, s):
|
||||||
}
|
expr(e);
|
||||||
var paran = Tools.checkOpPrecedence(op, op1, op2);*/
|
add((s == true ? "?." : ".") + f);
|
||||||
var paran = 2;
|
case EBinop(op, e1, e2):
|
||||||
|
var shouldParen = false;
|
||||||
|
var op1 = switch(Tools.expr(e1)) {
|
||||||
|
case EBinop(op, _, _): op;
|
||||||
|
case EConst(_): "_";
|
||||||
|
case EIdent(_): "_";
|
||||||
|
default: null;
|
||||||
|
}
|
||||||
|
var op2 = switch(Tools.expr(e2)) {
|
||||||
|
case EBinop(op, _, _): op;
|
||||||
|
case EConst(_): "_";
|
||||||
|
case EIdent(_): "_";
|
||||||
|
default: null;
|
||||||
|
}
|
||||||
|
var paran = Tools.checkOpPrecedence(op, op1, op2);
|
||||||
|
|
||||||
var op = getBinaryOp(op);
|
if(paran == 0 || paran == 2) {
|
||||||
|
add("(");
|
||||||
if(paran == 0 || paran == 2) {
|
expr(e1);
|
||||||
|
add(")");
|
||||||
|
} else {
|
||||||
|
expr(e1);
|
||||||
|
}
|
||||||
|
if(op == "...")
|
||||||
|
add(op);
|
||||||
|
else
|
||||||
|
add(" " + op + " ");
|
||||||
|
if(paran == 1 || paran == 2) {
|
||||||
|
add("(");
|
||||||
|
expr(e2);
|
||||||
|
add(")");
|
||||||
|
} else {
|
||||||
|
expr(e2);
|
||||||
|
}
|
||||||
|
case EUnop(op, pre, e):
|
||||||
|
if( pre ) {
|
||||||
|
add(op);
|
||||||
|
expr(e);
|
||||||
|
} else {
|
||||||
|
expr(e);
|
||||||
|
add(op);
|
||||||
|
}
|
||||||
|
case ECall(e, args):
|
||||||
|
if( e == null )
|
||||||
|
expr(e);
|
||||||
|
else switch( Tools.expr(e) ) {
|
||||||
|
case EField(_), EIdent(_), EConst(_):
|
||||||
|
expr(e);
|
||||||
|
default:
|
||||||
add("(");
|
add("(");
|
||||||
expr(e1);
|
expr(e);
|
||||||
add(")");
|
add(")");
|
||||||
} else {
|
}
|
||||||
expr(e1);
|
add("(");
|
||||||
}
|
var first = true;
|
||||||
if(op == "...")
|
for( a in args ) {
|
||||||
add(op);
|
if( first ) first = false else add(", ");
|
||||||
else
|
expr(a);
|
||||||
add(" " + op + " ");
|
}
|
||||||
if(paran == 1 || paran == 2) {
|
add(")");
|
||||||
add("(");
|
case EIf(cond,e1,e2):
|
||||||
expr(e2);
|
add("if( ");
|
||||||
add(")");
|
expr(cond);
|
||||||
} else {
|
add(" )");
|
||||||
expr(e2);
|
var wasBlock = block(e1, true);
|
||||||
}
|
|
||||||
case EUnop(op, pre, e):
|
|
||||||
var op = getUnaryOp(op);
|
|
||||||
|
|
||||||
if( pre ) {
|
if( e2 != null ) {
|
||||||
add(op);
|
if(!wasBlock) add("\n" + tabs);
|
||||||
expr(e);
|
add(" else ");
|
||||||
} else {
|
block(e2);
|
||||||
expr(e);
|
}
|
||||||
add(op);
|
case EWhile(cond,e):
|
||||||
|
add("while( ");
|
||||||
|
expr(cond);
|
||||||
|
add(" )");
|
||||||
|
block(e, true);
|
||||||
|
case EDoWhile(cond,e):
|
||||||
|
add("do");
|
||||||
|
block(e, true);
|
||||||
|
add(" while ( ");
|
||||||
|
expr(cond);
|
||||||
|
add(" )");
|
||||||
|
case EFor(v, it, e):
|
||||||
|
add("for( "+v+" in ");
|
||||||
|
expr(it);
|
||||||
|
add(" )");
|
||||||
|
block(e, true);
|
||||||
|
case EForKeyValue(v, it, e, ithv):
|
||||||
|
add("for( "+ithv+" => "+v+" in ");
|
||||||
|
expr(it);
|
||||||
|
add(" )");
|
||||||
|
block(e, true);
|
||||||
|
case EBreak:
|
||||||
|
add("break");
|
||||||
|
case EContinue:
|
||||||
|
add("continue");
|
||||||
|
case EFunction(params, e, name, ret): // TODO: static, public, override
|
||||||
|
add("function");
|
||||||
|
if( name != null )
|
||||||
|
add(" " + name);
|
||||||
|
add("(");
|
||||||
|
var first = true;
|
||||||
|
for( a in params ) {
|
||||||
|
if( first ) first = false else add(", ");
|
||||||
|
if( a.opt ) add("?");
|
||||||
|
add(a.name);
|
||||||
|
addType(a.t);
|
||||||
|
}
|
||||||
|
add(")");
|
||||||
|
addType(ret);
|
||||||
|
add(" ");
|
||||||
|
expr(e);
|
||||||
|
case EReturn(e):
|
||||||
|
add("return");
|
||||||
|
if( e != null ) {
|
||||||
|
add(" ");
|
||||||
|
expr(e);
|
||||||
|
}
|
||||||
|
case EArray(e,index):
|
||||||
|
expr(e);
|
||||||
|
add("[");
|
||||||
|
expr(index);
|
||||||
|
add("]");
|
||||||
|
case EMapDecl(type, keys, values):
|
||||||
|
add("[");
|
||||||
|
var first = true;
|
||||||
|
for( i in 0...keys.length ) {
|
||||||
|
if( first ) first = false else add(", ");
|
||||||
|
expr(keys[i]);
|
||||||
|
add(" => ");
|
||||||
|
expr(values[i]);
|
||||||
|
}
|
||||||
|
add("]");
|
||||||
|
case EArrayDecl(el):
|
||||||
|
add("[");
|
||||||
|
var first = true;
|
||||||
|
for( e in el ) {
|
||||||
|
if( first ) first = false else add(", ");
|
||||||
|
expr(e);
|
||||||
|
}
|
||||||
|
add("]");
|
||||||
|
case ENew(cl, args):
|
||||||
|
add("new " + cl + "(");
|
||||||
|
var first = true;
|
||||||
|
for( e in args ) {
|
||||||
|
if( first ) first = false else add(", ");
|
||||||
|
expr(e);
|
||||||
|
}
|
||||||
|
add(")");
|
||||||
|
case EThrow(e):
|
||||||
|
add("throw ");
|
||||||
|
expr(e);
|
||||||
|
case ETry(e, v, t, ecatch):
|
||||||
|
add("try");
|
||||||
|
var wasBlock = block(e);
|
||||||
|
if( !wasBlock ) {
|
||||||
|
add("\n" + tabs);
|
||||||
|
} else add(" ");
|
||||||
|
add("catch( " + v);
|
||||||
|
addType(t);
|
||||||
|
add(" )");
|
||||||
|
block(ecatch);
|
||||||
|
case EObject(fl):
|
||||||
|
if( fl.length == 0 ) {
|
||||||
|
add("{}");
|
||||||
|
} else {
|
||||||
|
tabs += "\t";
|
||||||
|
add("{\n");
|
||||||
|
for( i=>f in fl ) {
|
||||||
|
add(tabs);
|
||||||
|
var name = isJson(f.name) ? "\"" + f.name + "\"" : f.name;
|
||||||
|
add(name+" : ");
|
||||||
|
expr(f.e);
|
||||||
|
if( i != fl.length - 1 ) add(",");
|
||||||
|
add("\n");
|
||||||
}
|
}
|
||||||
case ECall(e, args):
|
tabs = tabs.substr(1);
|
||||||
if( e == null )
|
add(tabs);
|
||||||
expr(e);
|
add("}");
|
||||||
else switch( Tools.expr(e) ) {
|
}
|
||||||
case EField(_), EIdent(_), EConst(_):
|
case ETernary(c,e1,e2):
|
||||||
expr(e);
|
expr(c);
|
||||||
default:
|
add(" ? ");
|
||||||
add("(");
|
expr(e1);
|
||||||
expr(e);
|
add(" : ");
|
||||||
add(")");
|
expr(e2);
|
||||||
|
case ESwitch(e, cases, def):
|
||||||
|
add("switch( ");
|
||||||
|
expr(e);
|
||||||
|
add(" ) {\n");
|
||||||
|
tabs += "\t";
|
||||||
|
for( c in cases ) {
|
||||||
|
add(tabs);
|
||||||
|
add("case ");
|
||||||
|
var first = true;
|
||||||
|
for( v in c.values ) {
|
||||||
|
if( first ) first = false else add(", ");
|
||||||
|
expr(v);
|
||||||
}
|
}
|
||||||
|
add(":");
|
||||||
|
block(c.expr, true);
|
||||||
|
add(";\n");
|
||||||
|
}
|
||||||
|
if( def != null ) {
|
||||||
|
add(tabs);
|
||||||
|
add("default: ");
|
||||||
|
block(def, true);
|
||||||
|
add(";\n");
|
||||||
|
}
|
||||||
|
tabs = tabs.substr(1);
|
||||||
|
add(tabs);
|
||||||
|
add("}");
|
||||||
|
case EMeta(name, args, e):
|
||||||
|
add("@");
|
||||||
|
add(name);
|
||||||
|
if( args != null && args.length > 0 ) {
|
||||||
add("(");
|
add("(");
|
||||||
var first = true;
|
var first = true;
|
||||||
for( a in args ) {
|
for( a in args ) {
|
||||||
@@ -407,182 +509,15 @@ class Printer {
|
|||||||
expr(a);
|
expr(a);
|
||||||
}
|
}
|
||||||
add(")");
|
add(")");
|
||||||
case EIf(cond,e1,e2):
|
}
|
||||||
add("if( ");
|
add(" ");
|
||||||
expr(cond);
|
expr(e);
|
||||||
add(" )");
|
case ECheckType(e, t):
|
||||||
var wasBlock = block(e1, true);
|
add("(");
|
||||||
|
expr(e);
|
||||||
if( e2 != null ) {
|
add(" : ");
|
||||||
if(!wasBlock) add("\n" + tabs);
|
addType(t);
|
||||||
add(" else ");
|
add(")");
|
||||||
block(e2);
|
|
||||||
}
|
|
||||||
case EWhile(cond,e):
|
|
||||||
add("while( ");
|
|
||||||
expr(cond);
|
|
||||||
add(" )");
|
|
||||||
block(e, true);
|
|
||||||
case EDoWhile(cond,e):
|
|
||||||
add("do");
|
|
||||||
block(e, true);
|
|
||||||
add(" while ( ");
|
|
||||||
expr(cond);
|
|
||||||
add(" )");
|
|
||||||
case EFor(v, it, e):
|
|
||||||
add("for( "+getVar(v)+" in ");
|
|
||||||
expr(it);
|
|
||||||
add(" )");
|
|
||||||
block(e, true);
|
|
||||||
case EForKeyValue(v, it, e, ithv):
|
|
||||||
add("for( "+getVar(ithv)+" => "+getVar(v)+" in ");
|
|
||||||
expr(it);
|
|
||||||
add(" )");
|
|
||||||
block(e, true);
|
|
||||||
case EBreak:
|
|
||||||
add("break");
|
|
||||||
case EContinue:
|
|
||||||
add("continue");
|
|
||||||
case EFunction(params, e, name, ret): // TODO: static, public, override
|
|
||||||
add("function");
|
|
||||||
if( name != null )
|
|
||||||
add(" " + getVar(name));
|
|
||||||
add("(");
|
|
||||||
var first = true;
|
|
||||||
for( a in params ) {
|
|
||||||
if( first ) first = false else add(", ");
|
|
||||||
if( a.opt ) add("?");
|
|
||||||
add(getVar(a.name));
|
|
||||||
addType(a.t);
|
|
||||||
}
|
|
||||||
add(")");
|
|
||||||
addType(ret);
|
|
||||||
add(" ");
|
|
||||||
expr(e);
|
|
||||||
case EReturn(e):
|
|
||||||
add("return");
|
|
||||||
if( e != null ) {
|
|
||||||
add(" ");
|
|
||||||
expr(e);
|
|
||||||
}
|
|
||||||
case EArray(e,index):
|
|
||||||
expr(e);
|
|
||||||
add("[");
|
|
||||||
expr(index);
|
|
||||||
add("]");
|
|
||||||
case EMapDecl(type, keys, values):
|
|
||||||
add("[");
|
|
||||||
var first = true;
|
|
||||||
for( i in 0...keys.length ) {
|
|
||||||
if( first ) first = false else add(", ");
|
|
||||||
expr(keys[i]);
|
|
||||||
add(" => ");
|
|
||||||
expr(values[i]);
|
|
||||||
}
|
|
||||||
add("]");
|
|
||||||
case EArrayDecl(el):
|
|
||||||
add("[");
|
|
||||||
var first = true;
|
|
||||||
for( e in el ) {
|
|
||||||
if( first ) first = false else add(", ");
|
|
||||||
expr(e);
|
|
||||||
}
|
|
||||||
add("]");
|
|
||||||
case ENew(cl, args):
|
|
||||||
add("new " + getVar(cl) + "(");
|
|
||||||
var first = true;
|
|
||||||
for( e in args ) {
|
|
||||||
if( first ) first = false else add(", ");
|
|
||||||
expr(e);
|
|
||||||
}
|
|
||||||
add(")");
|
|
||||||
case EThrow(e):
|
|
||||||
add("throw ");
|
|
||||||
expr(e);
|
|
||||||
case ETry(e, v, t, ecatch):
|
|
||||||
add("try");
|
|
||||||
var wasBlock = block(e);
|
|
||||||
if( !wasBlock ) {
|
|
||||||
add("\n" + tabs);
|
|
||||||
} else add(" ");
|
|
||||||
add("catch( " + v);
|
|
||||||
addType(t);
|
|
||||||
add(" )");
|
|
||||||
block(ecatch);
|
|
||||||
case EObject(fl):
|
|
||||||
if( fl.length == 0 ) {
|
|
||||||
add("{}");
|
|
||||||
} else {
|
|
||||||
tabs += "\t";
|
|
||||||
add("{\n");
|
|
||||||
for( i=>f in fl ) {
|
|
||||||
add(tabs);
|
|
||||||
var name = isJson(f.name) ? "\"" + f.name + "\"" : f.name;
|
|
||||||
add(name+" : ");
|
|
||||||
expr(f.e);
|
|
||||||
if( i != fl.length - 1 ) add(",");
|
|
||||||
add("\n");
|
|
||||||
}
|
|
||||||
tabs = tabs.substr(1);
|
|
||||||
add(tabs);
|
|
||||||
add("}");
|
|
||||||
}
|
|
||||||
case ETernary(c,e1,e2):
|
|
||||||
expr(c);
|
|
||||||
add(" ? ");
|
|
||||||
expr(e1);
|
|
||||||
add(" : ");
|
|
||||||
expr(e2);
|
|
||||||
case ESwitch(e, cases, def):
|
|
||||||
add("switch( ");
|
|
||||||
expr(e);
|
|
||||||
add(" ) {\n");
|
|
||||||
tabs += "\t";
|
|
||||||
for( c in cases ) {
|
|
||||||
add(tabs);
|
|
||||||
add("case ");
|
|
||||||
var first = true;
|
|
||||||
for( v in c.values ) {
|
|
||||||
if( first ) first = false else add(", ");
|
|
||||||
expr(v);
|
|
||||||
}
|
|
||||||
add(":");
|
|
||||||
block(c.expr, true);
|
|
||||||
add(";\n");
|
|
||||||
}
|
|
||||||
if( def != null ) {
|
|
||||||
add(tabs);
|
|
||||||
add("default: ");
|
|
||||||
block(def, true);
|
|
||||||
add(";\n");
|
|
||||||
}
|
|
||||||
tabs = tabs.substr(1);
|
|
||||||
add(tabs);
|
|
||||||
add("}");
|
|
||||||
case EMeta(name, args, e):
|
|
||||||
add("@");
|
|
||||||
add(name);
|
|
||||||
if( args != null && args.length > 0 ) {
|
|
||||||
add("(");
|
|
||||||
var first = true;
|
|
||||||
for( a in args ) {
|
|
||||||
if( first ) first = false else add(", ");
|
|
||||||
expr(e);
|
|
||||||
}
|
|
||||||
add(")");
|
|
||||||
}
|
|
||||||
add(" ");
|
|
||||||
expr(e);
|
|
||||||
case ECheckType(e, t):
|
|
||||||
add("(");
|
|
||||||
expr(e);
|
|
||||||
add(" : ");
|
|
||||||
addType(t);
|
|
||||||
add(")");
|
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
case EInfo(_, e):
|
|
||||||
expr(e);
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+63
-161
@@ -27,125 +27,75 @@ class Tools {
|
|||||||
|
|
||||||
public static function iter( e : Expr, f : Expr -> Void ) {
|
public static function iter( e : Expr, f : Expr -> Void ) {
|
||||||
switch( expr(e) ) {
|
switch( expr(e) ) {
|
||||||
case EConst(_), EIdent(_): f(e);
|
case EConst(_), EIdent(_):
|
||||||
case EImport(c, _): f(e);
|
case EImport(c, _): f(e);
|
||||||
case EClass(_, e, _, _): for( a in e ) f(a);
|
case EClass(_, e, _, _): for( a in e ) f(a);
|
||||||
case EVar(_, _, e): if( e != null ) f(e);
|
case EVar(_, _, e): if( e != null ) f(e);
|
||||||
case EParent(e, _): f(e);
|
case EParent(e): f(e);
|
||||||
case EBlock(el): for( e in el ) f(e);
|
case EBlock(el): for( e in el ) f(e);
|
||||||
case EField(e, _): f(e);
|
case EField(e, _): f(e);
|
||||||
case EBinop(_, e1, e2): f(e1); f(e2);
|
case EBinop(_, e1, e2): f(e1); f(e2);
|
||||||
case EUnop(_, _, e): f(e);
|
case EUnop(_, _, e): f(e);
|
||||||
case ECall(e, args): f(e); for( a in args ) f(a);
|
case ECall(e, args): f(e); for( a in args ) f(a);
|
||||||
case EIf(c, e1, e2): f(c); f(e1); if( e2 != null ) f(e2);
|
case EIf(c, e1, e2): f(c); f(e1); if( e2 != null ) f(e2);
|
||||||
case EWhile(c, e): f(c); f(e);
|
case EWhile(c, e): f(c); f(e);
|
||||||
case EDoWhile(c, e): f(c); f(e);
|
case EDoWhile(c, e): f(c); f(e);
|
||||||
case EFor(_, it, e): f(it); f(e);
|
case EFor(_, it, e): f(it); f(e);
|
||||||
case EForKeyValue(_, it, e, _): f(it); f(e);
|
case EForKeyValue(_, it, e, _): f(it); f(e);
|
||||||
case EBreak,EContinue:
|
case EBreak,EContinue:
|
||||||
case EFunction(_, e, _, _): f(e);
|
case EFunction(_, e, _, _): f(e);
|
||||||
case EReturn(e): if( e != null ) f(e);
|
case EReturn(e): if( e != null ) f(e);
|
||||||
case EArray(e, i): f(e); f(i);
|
case EArray(e, i): f(e); f(i);
|
||||||
case EMapDecl(type, keys, values): for( e in keys ) f(e); for( e in values ) f(e);
|
case EMapDecl(type, keys, values): for( e in keys ) f(e); for( e in values ) f(e);
|
||||||
case EArrayDecl(el): for( e in el ) f(e);
|
case EArrayDecl(el): for( e in el ) f(e);
|
||||||
case ENew(_,el): for( e in el ) f(e);
|
case ENew(_,el): for( e in el ) f(e);
|
||||||
case EThrow(e): f(e);
|
case EThrow(e): f(e);
|
||||||
case ETry(e, _, _, c): f(e); f(c);
|
case ETry(e, _, _, c): f(e); f(c);
|
||||||
case EObject(fl): for( fi in fl ) f(fi.e);
|
case EObject(fl): for( fi in fl ) f(fi.e);
|
||||||
case ETernary(c, e1, e2): f(c); f(e1); f(e2);
|
case ETernary(c, e1, e2): f(c); f(e1); f(e2);
|
||||||
case ESwitch(e, cases, def):
|
case ESwitch(e, cases, def):
|
||||||
f(e);
|
f(e);
|
||||||
for( c in cases ) {
|
for( c in cases ) {
|
||||||
for( v in c.values ) f(v);
|
for( v in c.values ) f(v);
|
||||||
f(c.expr);
|
f(c.expr);
|
||||||
}
|
}
|
||||||
if( def != null ) f(def);
|
if( def != null ) f(def);
|
||||||
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
|
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
|
||||||
case ECheckType(e,_): f(e);
|
case ECheckType(e,_): f(e);
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
case EInfo(info, e): f(e);
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function iterExprRecursive( ve : Expr, f : Expr -> Void ) {
|
|
||||||
var rec = (e:Expr) -> iterExprRecursive(e, f);
|
|
||||||
f(ve);
|
|
||||||
switch( expr(ve) ) {
|
|
||||||
case EConst(_), EIdent(_): {}
|
|
||||||
case EImport(c, _): {}
|
|
||||||
case EClass(_, e, _, _): for( a in e ) rec(a);
|
|
||||||
case EVar(_, _, e): if( e != null ) rec(e);
|
|
||||||
case EParent(e, _): rec(e);
|
|
||||||
case EBlock(el): for( e in el ) rec(e);
|
|
||||||
case EField(e, _): rec(e);
|
|
||||||
case EBinop(_, e1, e2): rec(e1); rec(e2);
|
|
||||||
case EUnop(_, _, e): rec(e);
|
|
||||||
case ECall(e, args): rec(e); for( a in args ) rec(a);
|
|
||||||
case EIf(c, e1, e2): rec(c); rec(e1); if( e2 != null ) rec(e2);
|
|
||||||
case EWhile(c, e): rec(c); rec(e);
|
|
||||||
case EDoWhile(c, e): rec(c); rec(e);
|
|
||||||
case EFor(_, it, e): rec(it); rec(e);
|
|
||||||
case EForKeyValue(_, it, e, _): rec(it); rec(e);
|
|
||||||
case EBreak,EContinue: {}
|
|
||||||
case EFunction(_, e, _, _): rec(e);
|
|
||||||
case EReturn(e): if( e != null ) rec(e);
|
|
||||||
case EArray(e, i): rec(e); rec(i);
|
|
||||||
case EMapDecl(type, keys, values): for( e in keys ) rec(e); for( e in values ) rec(e);
|
|
||||||
case EArrayDecl(el): for( e in el ) rec(e);
|
|
||||||
case ENew(_,el): for( e in el ) rec(e);
|
|
||||||
case EThrow(e): rec(e);
|
|
||||||
case ETry(e, _, _, c): rec(e); rec(c);
|
|
||||||
case EObject(fl): for( fi in fl ) rec(fi.e);
|
|
||||||
case ETernary(c, e1, e2): rec(c); rec(e1); rec(e2);
|
|
||||||
case ESwitch(e, cases, def):
|
|
||||||
rec(e);
|
|
||||||
for( c in cases ) {
|
|
||||||
for( v in c.values ) rec(v);
|
|
||||||
rec(c.expr);
|
|
||||||
}
|
|
||||||
if( def != null ) rec(def);
|
|
||||||
case EMeta(name, args, e): if( args != null ) for( a in args ) rec(a); rec(e);
|
|
||||||
case ECheckType(e,_): rec(e);
|
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
case EInfo(info, e): rec(e);
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function map( e : Expr, f : Expr -> Expr ) {
|
public static function map( e : Expr, f : Expr -> Expr ) {
|
||||||
var edef = switch( expr(e) ) {
|
var edef = switch( expr(e) ) {
|
||||||
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
|
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
|
||||||
case EVar(n, t, e, p, s): EVar(n, t, if( e != null ) f(e) else null, p, s);
|
case EVar(n, t, e, p, s): EVar(n, t, if( e != null ) f(e) else null, p, s);
|
||||||
case EParent(e, no): EParent(f(e), no);
|
case EParent(e, no): EParent(f(e), no);
|
||||||
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
||||||
case EField(e, fi, s): EField(f(e),fi,s);
|
case EField(e, fi, s): EField(f(e),fi,s);
|
||||||
case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2));
|
case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2));
|
||||||
case EUnop(op, pre, e): EUnop(op, pre, f(e));
|
case EUnop(op, pre, e): EUnop(op, pre, f(e));
|
||||||
case ECall(e, args): ECall(f(e),[for( a in args ) f(a)]);
|
case ECall(e, args): ECall(f(e),[for( a in args ) f(a)]);
|
||||||
case EIf(c, e1, e2): EIf(f(c),f(e1),if( e2 != null ) f(e2) else null);
|
case EIf(c, e1, e2): EIf(f(c),f(e1),if( e2 != null ) f(e2) else null);
|
||||||
case EWhile(c, e): EWhile(f(c),f(e));
|
case EWhile(c, e): EWhile(f(c),f(e));
|
||||||
case EDoWhile(c, e): EDoWhile(f(c),f(e));
|
case EDoWhile(c, e): EDoWhile(f(c),f(e));
|
||||||
case EFor(v, it, e): EFor(v, f(it), f(e));
|
case EFor(v, it, e): EFor(v, f(it), f(e));
|
||||||
case EForKeyValue(v, it, e, ithv): EForKeyValue(v, f(it), f(e), ithv);
|
case EForKeyValue(v, it, e, ithv): EForKeyValue(v, f(it), f(e), ithv);
|
||||||
case EFunction(args, e, name, t, p, s, o): EFunction(args, f(e), name, t, p, s, o);
|
case EFunction(args, e, name, t, p, s, o): EFunction(args, f(e), name, t, p, s, o);
|
||||||
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
||||||
case EArray(e, i): EArray(f(e),f(i));
|
case EArray(e, i): EArray(f(e),f(i));
|
||||||
case EMapDecl(type, keys, values): EMapDecl(type, [for( e in keys ) f(e)], [for( e in values ) f(e)]);
|
case EMapDecl(type, keys, values): EMapDecl(type, [for( e in keys ) f(e)], [for( e in values ) f(e)]);
|
||||||
case EArrayDecl(el): EArrayDecl([for( e in el ) f(e)]);
|
case EArrayDecl(el): EArrayDecl([for( e in el ) f(e)]);
|
||||||
case ENew(cl,el): ENew(cl,[for( e in el ) f(e)]);
|
case ENew(cl,el): ENew(cl,[for( e in el ) f(e)]);
|
||||||
case EThrow(e): EThrow(f(e));
|
case EThrow(e): EThrow(f(e));
|
||||||
case ETry(e, v, t, c): ETry(f(e), v, t, f(c));
|
case ETry(e, v, t, c): ETry(f(e), v, t, f(c));
|
||||||
case EObject(fl): EObject([for( fi in fl ) new ObjectField(fi.name, f(fi.e))]);
|
case EObject(fl): EObject([for( fi in fl ) new ObjectField(fi.name, f(fi.e))]);
|
||||||
case ETernary(c, e1, e2): ETernary(f(c), f(e1), f(e2));
|
case ETernary(c, e1, e2): ETernary(f(c), f(e1), f(e2));
|
||||||
case ESwitch(e, cases, def): ESwitch(f(e), [for( c in cases ) { values : [for( v in c.values ) f(v)], expr : f(c.expr) } ], def == null ? null : f(def));
|
case ESwitch(e, cases, def): ESwitch(f(e), [for( c in cases ) new SwitchCase([for( v in c.values ) f(v)], f(c.expr))], def == null ? null : f(def));
|
||||||
case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e));
|
case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e));
|
||||||
case ECheckType(e,t): ECheckType(f(e), t);
|
case ECheckType(e,t): ECheckType(f(e), t);
|
||||||
case EImport(c, m): EImport(c, m);
|
case EImport(c, m): EImport(c, m);
|
||||||
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
|
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
|
||||||
#if !HSCRIPT_NO_INT_VARS
|
|
||||||
case EInfo(info, e): EInfo(info, f(e));
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
return mk(edef, e);
|
return mk(edef, e);
|
||||||
}
|
}
|
||||||
@@ -183,54 +133,6 @@ class Tools {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getOpEnum(op:String):Binop {
|
|
||||||
return switch(op) {
|
|
||||||
case "+": OpAdd;
|
|
||||||
case "-": OpSub;
|
|
||||||
case "*": OpMult;
|
|
||||||
case "/": OpDiv;
|
|
||||||
case "%": OpMod;
|
|
||||||
case "&": OpAnd;
|
|
||||||
case "|": OpOr;
|
|
||||||
case "^": OpXor;
|
|
||||||
case "<<": OpShl;
|
|
||||||
case ">>": OpShr;
|
|
||||||
case ">>>": OpUShr;
|
|
||||||
case "==": OpEq;
|
|
||||||
case "!=": OpNotEq;
|
|
||||||
case ">=": OpGte;
|
|
||||||
case "<=": OpLte;
|
|
||||||
case ">": OpGt;
|
|
||||||
case "<": OpLt;
|
|
||||||
case "||": OpBoolOr;
|
|
||||||
case "&&": OpBoolAnd;
|
|
||||||
case "is": OpIs;
|
|
||||||
case "=": OpAssign;
|
|
||||||
case "=>": OpArrow;
|
|
||||||
case "??": OpNullCoal;
|
|
||||||
case "...": OpInterval;
|
|
||||||
default: {
|
|
||||||
var op2 = op.substr(0, op.length - 1);
|
|
||||||
if(isValidBinOp(op2)) {
|
|
||||||
return OpAssignOp(getOpEnum(op2));
|
|
||||||
}
|
|
||||||
throw "Unknown binary operator: " + op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getUnopEnum(op:String):Unop {
|
|
||||||
return switch(op) {
|
|
||||||
case "++": OpIncrement;
|
|
||||||
case "--": OpDecrement;
|
|
||||||
case "!": OpNot;
|
|
||||||
case "-": OpNeg;
|
|
||||||
case "~": OpNegBits;
|
|
||||||
case "...": OpSpread;
|
|
||||||
default: throw "Unknown unary operator: " + op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static var priorities = [
|
static var priorities = [
|
||||||
["%"],
|
["%"],
|
||||||
["*", "/"],
|
["*", "/"],
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -144,16 +144,12 @@ class ClassExtendMacro {
|
|||||||
|
|
||||||
//trace(getModuleName(cl));
|
//trace(getModuleName(cl));
|
||||||
|
|
||||||
var hasNew = false;
|
|
||||||
|
|
||||||
for(_field in [fields.copy(), superFields.copy()])
|
for(_field in [fields.copy(), superFields.copy()])
|
||||||
for(f in _field) {
|
for(f in _field) {
|
||||||
if (f == null)
|
if (f == null)
|
||||||
continue;
|
continue;
|
||||||
if (f.name == "new") {
|
if (f.name == "new")
|
||||||
hasNew = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (f.name.startsWith(FUNC_PREFIX))
|
if (f.name.startsWith(FUNC_PREFIX))
|
||||||
continue;
|
continue;
|
||||||
if (f.access.contains(ADynamic) || f.access.contains(AStatic) || f.access.contains(AExtern) || f.access.contains(AInline))
|
if (f.access.contains(ADynamic) || f.access.contains(AStatic) || f.access.contains(AExtern) || f.access.contains(AInline))
|
||||||
@@ -187,10 +183,10 @@ class ClassExtendMacro {
|
|||||||
overrideExpr = macro {
|
overrideExpr = macro {
|
||||||
var name:String = $v{name};
|
var name:String = $v{name};
|
||||||
|
|
||||||
if (__custom__variables != null) {
|
if (__interp != null) {
|
||||||
if(__custom__variables.exists(name)) {
|
if (__custom__variables.exists(name)) {
|
||||||
var v:Dynamic = null;
|
var v:Dynamic = null;
|
||||||
if (Reflect.isFunction(v = __custom__variables.get(name))) {
|
if(Reflect.isFunction(v = __custom__variables.get(name))) {
|
||||||
return v($a{arguments});
|
return v($a{arguments});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,10 +197,10 @@ class ClassExtendMacro {
|
|||||||
overrideExpr = macro {
|
overrideExpr = macro {
|
||||||
var name:String = $v{name};
|
var name:String = $v{name};
|
||||||
|
|
||||||
if (__custom__variables != null) {
|
if (__interp != null) {
|
||||||
if(__custom__variables.exists(name)) {
|
if (__custom__variables.exists(name)) {
|
||||||
var v:Dynamic = null;
|
var v:Dynamic = null;
|
||||||
if (Reflect.isFunction(v = __custom__variables.get(name))) {
|
if(Reflect.isFunction(v = __custom__variables.get(name))) {
|
||||||
v($a{arguments});
|
v($a{arguments});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -261,13 +257,6 @@ class ClassExtendMacro {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalFields = definedFields.length;
|
|
||||||
|
|
||||||
if(totalFields == 0 && !hasNew) {
|
|
||||||
//Sys.println(cl.pack.join(".") + "." + cl.name + ", " + totalFields);
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
shadowClass.kind = TDClass({
|
shadowClass.kind = TDClass({
|
||||||
pack: cl.pack.copy(),
|
pack: cl.pack.copy(),
|
||||||
name: cl.name
|
name: cl.name
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -25,10 +25,11 @@ class Utils {
|
|||||||
return type;
|
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 = [];
|
||||||
shadowClass.meta.push({name: ":dox", params: [macro hide], pos: Context.currentPos()});
|
shadowClass.meta.push({name: ":dox", params: [macro hide], pos: Context.currentPos()});
|
||||||
shadowClass.meta.push({name: ":noCompletion", params: [], pos: Context.currentPos()});
|
shadowClass.meta.push({name: ":noCompletion", params: [], pos: Context.currentPos()});
|
||||||
|
if(!doImports) return;
|
||||||
var module = Context.getModule(Context.getLocalModule());
|
var module = Context.getModule(Context.getLocalModule());
|
||||||
for(t in module) {
|
for(t in module) {
|
||||||
switch(t) {
|
switch(t) {
|
||||||
|
|||||||
+7
-2
@@ -17,9 +17,14 @@
|
|||||||
# File Specific Defines
|
# File Specific Defines
|
||||||
--define linux
|
--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
|
# Copying the assets from source code to bin folder
|
||||||
# --cmd rm -rf bin/cpp/assets
|
--cmd rm -rf bin/cpp/assets
|
||||||
# --cmd cp -r assets bin/cpp/assets
|
--cmd cp -r assets bin/cpp/assets
|
||||||
--cpp bin/cpp
|
--cpp bin/cpp
|
||||||
--cmd cd bin/cpp
|
--cmd cd bin/cpp
|
||||||
--cmd ./Main
|
--cmd ./Main
|
||||||
+3
-2
@@ -24,11 +24,12 @@
|
|||||||
--macro keep('IntIterator')
|
--macro keep('IntIterator')
|
||||||
# --macro hscript.macros.UsingHandler.init()
|
# --macro hscript.macros.UsingHandler.init()
|
||||||
# --macro hscript.macros.ClassExtendMacro.init()
|
# --macro hscript.macros.ClassExtendMacro.init()
|
||||||
|
--macro hscript.macros.AbstractHandler.init()
|
||||||
|
|
||||||
|
|
||||||
# Copying the assets from source code to bin folder
|
# Copying the assets from source code to bin folder
|
||||||
# --cmd rm -rf bin/cpp/assets
|
--cmd rm -rf bin/cpp/assets
|
||||||
# --cmd cp -r assets bin/cpp/assets
|
--cmd cp -r assets bin/cpp/assets
|
||||||
--cpp bin/cpp
|
--cpp bin/cpp
|
||||||
--cmd cd bin/cpp
|
--cmd cd bin/cpp
|
||||||
--cmd ./Main
|
--cmd ./Main
|
||||||
+2
-29
@@ -12,35 +12,7 @@ class Main {
|
|||||||
Sys.println("Running benchmark");
|
Sys.println("Running benchmark");
|
||||||
|
|
||||||
//new Benchmark("Test", 1000);
|
//new Benchmark("Test", 1000);
|
||||||
var haxeTotalTime:Float = 0;
|
new TestBenchmark();
|
||||||
var hscriptTotalTime:Float = 0;
|
|
||||||
|
|
||||||
var haxeTimes:Array<Float> = [];
|
|
||||||
var hscriptTimes:Array<Float> = [];
|
|
||||||
|
|
||||||
var iterations:Int = 10;
|
|
||||||
for (i in 0...iterations) {
|
|
||||||
var benchmark:TestBenchmark = new TestBenchmark();
|
|
||||||
|
|
||||||
haxeTimes.push(benchmark.haxeTotalTime);
|
|
||||||
hscriptTimes.push(benchmark.hscriptTotalTime);
|
|
||||||
|
|
||||||
haxeTotalTime += benchmark.haxeTotalTime;
|
|
||||||
hscriptTotalTime += benchmark.hscriptTotalTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
haxeTimes.sort((a, b) -> return a > b ? 1 : -1);
|
|
||||||
hscriptTimes.sort((a, b) -> return a > b ? 1 : -1);
|
|
||||||
|
|
||||||
var slowestHaxeTime:Float = haxeTimes[haxeTimes.length-1];
|
|
||||||
var slowestHscriptTime:Float = hscriptTimes[hscriptTimes.length-1];
|
|
||||||
var fastestHaxeTime:Float = haxeTimes[0];
|
|
||||||
var fastestHscriptTime:Float = hscriptTimes[0];
|
|
||||||
|
|
||||||
var haxeWon = hscriptTotalTime > haxeTotalTime;
|
|
||||||
Sys.println('${haxeWon ? "Haxe" : "Hscript"} was faster overall (Faster by: ${Util.roundWith((haxeWon ? hscriptTotalTime/haxeTotalTime : haxeTotalTime/hscriptTotalTime), 100)}x)');
|
|
||||||
Sys.println('Haxe average time: ${Util.convertToReadableTime(haxeTotalTime/iterations)} (Highest: ${Util.convertToReadableTime(slowestHaxeTime)}) (Lowest: ${Util.convertToReadableTime(fastestHaxeTime)})');
|
|
||||||
Sys.println('Hscript average time: ${Util.convertToReadableTime(hscriptTotalTime/iterations)} (Highest: ${Util.convertToReadableTime(slowestHscriptTime)}) (Lowest: ${Util.convertToReadableTime(fastestHscriptTime)})');
|
|
||||||
#else
|
#else
|
||||||
Sys.println("Beginning tests");
|
Sys.println("Beginning tests");
|
||||||
if(!Main.SHOW_KNOWN_BUGS) {
|
if(!Main.SHOW_KNOWN_BUGS) {
|
||||||
@@ -68,6 +40,7 @@ class Main {
|
|||||||
// TODO: UnicodeCase.hx?
|
// TODO: UnicodeCase.hx?
|
||||||
// TODO: UnicodeStringCase.hx?
|
// TODO: UnicodeStringCase.hx?
|
||||||
runTest("Final", new FinalCase());
|
runTest("Final", new FinalCase());
|
||||||
|
runTest("Abstract", new AbstractCase());
|
||||||
Util.printTestResults();
|
Util.printTestResults();
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,7 +210,6 @@ class Util {
|
|||||||
// Print stack trace
|
// Print stack trace
|
||||||
var stack = haxe.CallStack.toString(haxe.CallStack.exceptionStack());
|
var stack = haxe.CallStack.toString(haxe.CallStack.exceptionStack());
|
||||||
Sys.println("## Stack trace: " + stack);
|
Sys.println("## Stack trace: " + stack);
|
||||||
Sys.exit(1);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ class Benchmark extends HScriptRunner {
|
|||||||
|
|
||||||
public function new(name:String, iterations:Int) {
|
public function new(name:String, iterations:Int) {
|
||||||
super();
|
super();
|
||||||
doBenchmark(name, iterations);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function doBenchmark(name:String, iterations:Int) {
|
|
||||||
haxeTimes = cast new haxe.ds.Vector<Float>(iterations);
|
haxeTimes = cast new haxe.ds.Vector<Float>(iterations);
|
||||||
hscriptTimes = cast new haxe.ds.Vector<Float>(iterations);
|
hscriptTimes = cast new haxe.ds.Vector<Float>(iterations);
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,7 +27,6 @@ class FinalCase extends TestCase {
|
|||||||
assertDisplay("(i - x) * 30 + 90", ((i-x) * 30) + 90);
|
assertDisplay("(i - x) * 30 + 90", ((i-x) * 30) + 90);
|
||||||
assertDisplay("i - x * 30 + 90", i-x * 30 + 90);
|
assertDisplay("i - x * 30 + 90", i-x * 30 + 90);
|
||||||
|
|
||||||
/*
|
|
||||||
// Test operator precedence
|
// Test operator precedence
|
||||||
assertDisplay("i / x * 30 + 90", i / x * 30 + 90);
|
assertDisplay("i / x * 30 + 90", i / x * 30 + 90);
|
||||||
assertDisplay("i / (x * 30) + 90", i / (x * 30) + 90);
|
assertDisplay("i / (x * 30) + 90", i / (x * 30) + 90);
|
||||||
@@ -45,7 +44,6 @@ class FinalCase extends TestCase {
|
|||||||
bloomShader.dim = dim = .8 + (.3 * FlxMath.fastSin(__totalTime));
|
bloomShader.dim = dim = .8 + (.3 * FlxMath.fastSin(__totalTime));
|
||||||
bloomShader.size = size = 18 + (8 * FlxMath.fastSin(__totalTime));
|
bloomShader.size = size = 18 + (8 * FlxMath.fastSin(__totalTime));
|
||||||
');
|
');
|
||||||
*/
|
|
||||||
|
|
||||||
Util.parse('sprite.setPosition(codesList.x + (sprite.ID % 2 == 1 ? 240 : 67),codesList.y + (15 * sprite.ID) + (sprite.ID%2 == 1 ? 35 : 54));');
|
Util.parse('sprite.setPosition(codesList.x + (sprite.ID % 2 == 1 ? 240 : 67),codesList.y + (15 * sprite.ID) + (sprite.ID%2 == 1 ? 35 : 54));');
|
||||||
|
|
||||||
@@ -76,6 +74,7 @@ class FinalCase extends TestCase {
|
|||||||
|
|
||||||
assertEq("[for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]", [for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]);
|
assertEq("[for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]", [for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]);
|
||||||
assertEq("[for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]", [for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]);
|
assertEq("[for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]", [for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]);
|
||||||
|
|
||||||
headerCode = "function area(a:Int, b:Int):Int { return a * b; };";
|
headerCode = "function area(a:Int, b:Int):Int { return a * b; };";
|
||||||
function area(a:Int, b:Int):Int { return a * b; }
|
function area(a:Int, b:Int):Int { return a * b; }
|
||||||
|
|
||||||
@@ -127,6 +126,8 @@ class FinalCase extends TestCase {
|
|||||||
import Math.round;
|
import Math.round;
|
||||||
round(1.9);", Math.round(1.9));
|
round(1.9);", Math.round(1.9));
|
||||||
|
|
||||||
|
trace(Type.resolveClass("hscript._Error.ErrorMessage_Impl_"));
|
||||||
|
|
||||||
// Test EOF with preprocessor
|
// Test EOF with preprocessor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,11 @@
|
|||||||
# File Specific Defines
|
# File Specific Defines
|
||||||
--define windows
|
--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
|
# Copying the assets from source code to bin folder
|
||||||
# --cmd Xcopy assets\ bin\cpp\assets\ /E /H /C /I /Y
|
# --cmd Xcopy assets\ bin\cpp\assets\ /E /H /C /I /Y
|
||||||
--cpp bin/cpp
|
--cpp bin/cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user