Compare commits
30
Commits
@@ -22,7 +22,6 @@ or set this in build.hxml
|
|||||||
|
|
||||||
Current Custom Class Limitations :
|
Current Custom Class Limitations :
|
||||||
|
|
||||||
- For now, you can only override functions from the current class, not from the extended part, like you cant override update in FlxText because FlxText doesnt have a update function overriden.
|
|
||||||
- You cannot create custom classes that extends a typed class (those ones that has `<T>`), this will be implemented in the future.
|
- You cannot create custom classes that extends a typed class (those ones that has `<T>`), this will be implemented in the future.
|
||||||
|
|
||||||
-----------
|
-----------
|
||||||
|
|||||||
+536
-536
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -156,11 +156,11 @@ class Bytes {
|
|||||||
doEncode(e);
|
doEncode(e);
|
||||||
doEncodeString(f);
|
doEncodeString(f);
|
||||||
case EBinop(op,e1,e2):
|
case EBinop(op,e1,e2):
|
||||||
doEncodeString(op);
|
doEncodeString(op.toString());
|
||||||
doEncode(e1);
|
doEncode(e1);
|
||||||
doEncode(e2);
|
doEncode(e2);
|
||||||
case EUnop(op,prefix,e):
|
case EUnop(op,prefix,e):
|
||||||
doEncodeString(op);
|
doEncodeString(op.toString()); // maybe doEncodeInt
|
||||||
bout.addByte(prefix?1:0);
|
bout.addByte(prefix?1:0);
|
||||||
doEncode(e);
|
doEncode(e);
|
||||||
case ECall(e,el):
|
case ECall(e,el):
|
||||||
@@ -278,11 +278,11 @@ class Bytes {
|
|||||||
var e = doDecode();
|
var e = doDecode();
|
||||||
EField(e,doDecodeString());
|
EField(e,doDecodeString());
|
||||||
case 6:
|
case 6:
|
||||||
var op = doDecodeString();
|
var op = Binop.fromString(doDecodeString());
|
||||||
var e1 = doDecode();
|
var e1 = doDecode();
|
||||||
EBinop(op,e1,doDecode());
|
EBinop(op,e1,doDecode());
|
||||||
case 7:
|
case 7:
|
||||||
var op = doDecodeString();
|
var op = Unop.fromString(doDecodeString());
|
||||||
var prefix = bin.get(pin++) != 0;
|
var prefix = bin.get(pin++) != 0;
|
||||||
EUnop(op,prefix,doDecode());
|
EUnop(op,prefix,doDecode());
|
||||||
case 8:
|
case 8:
|
||||||
|
|||||||
+30
-16
@@ -1073,10 +1073,10 @@ class Checker {
|
|||||||
case EUnop(op, _, e):
|
case EUnop(op, _, e):
|
||||||
var et = typeExpr(e, Value);
|
var et = typeExpr(e, Value);
|
||||||
switch( op ) {
|
switch( op ) {
|
||||||
case "++", "--", "-":
|
case OpIncrement | OpDecrement | OpNeg:
|
||||||
unify(et,TInt,e);
|
unify(et,TInt,e);
|
||||||
return et;
|
return et;
|
||||||
case "!":
|
case OpNot:
|
||||||
unify(et,TBool,e);
|
unify(et,TBool,e);
|
||||||
return et;
|
return et;
|
||||||
default:
|
default:
|
||||||
@@ -1113,11 +1113,11 @@ class Checker {
|
|||||||
return TVoid;
|
return TVoid;
|
||||||
case EBinop(op, e1, e2):
|
case EBinop(op, e1, e2):
|
||||||
switch( op ) {
|
switch( op ) {
|
||||||
case "&", "|", "^", ">>", ">>>", "<<":
|
case OpAnd, OpOr, OpXor, OpShr, OpUshr, OpShl:
|
||||||
typeExprWith(e1,TInt);
|
typeExprWith(e1,TInt);
|
||||||
typeExprWith(e2,TInt);
|
typeExprWith(e2,TInt);
|
||||||
return TInt;
|
return TInt;
|
||||||
case "=":
|
case OpAssign:
|
||||||
if( allowDefine ) {
|
if( allowDefine ) {
|
||||||
switch( edef(e1) ) {
|
switch( edef(e1) ) {
|
||||||
case EIdent(i) if( !locals.exists(i) && !globals.exists(i) ):
|
case EIdent(i) if( !locals.exists(i) && !globals.exists(i) ):
|
||||||
@@ -1133,7 +1133,7 @@ class Checker {
|
|||||||
}
|
}
|
||||||
typeExprWith(e2,vt);
|
typeExprWith(e2,vt);
|
||||||
return vt;
|
return vt;
|
||||||
case "+":
|
case OpAdd:
|
||||||
var t1 = typeExpr(e1,WithType(TInt));
|
var t1 = typeExpr(e1,WithType(TInt));
|
||||||
var t2 = typeExpr(e2,WithType(t1));
|
var t2 = typeExpr(e2,WithType(t1));
|
||||||
tryUnify(t1,t2);
|
tryUnify(t1,t2);
|
||||||
@@ -1150,14 +1150,14 @@ class Checker {
|
|||||||
unify(t1, TFloat, e1);
|
unify(t1, TFloat, e1);
|
||||||
unify(t2, TFloat, e2);
|
unify(t2, TFloat, e2);
|
||||||
}
|
}
|
||||||
case "-", "*", "/", "%":
|
case OpSub, OpMult, OpDiv, OpMod:
|
||||||
var t1 = typeExpr(e1,WithType(TInt));
|
var t1 = typeExpr(e1,WithType(TInt));
|
||||||
var t2 = typeExpr(e2,WithType(t1));
|
var t2 = typeExpr(e2,WithType(t1));
|
||||||
if( !tryUnify(t1,t2) )
|
if( !tryUnify(t1,t2) )
|
||||||
unify(t2,t1,e2);
|
unify(t2,t1,e2);
|
||||||
switch( [follow(t1), follow(t2)]) {
|
switch( [follow(t1), follow(t2)]) {
|
||||||
case [TInt, TInt]:
|
case [TInt, TInt]:
|
||||||
if( op == "/" ) return TFloat;
|
if( op == OpDiv ) return TFloat;
|
||||||
return TInt;
|
return TInt;
|
||||||
case [TFloat|TDynamic, TInt|TDynamic], [TInt|TDynamic, TFloat|TDynamic], [TFloat, TFloat]:
|
case [TFloat|TDynamic, TInt|TDynamic], [TInt|TDynamic, TFloat|TDynamic], [TFloat, TFloat]:
|
||||||
return TFloat;
|
return TFloat;
|
||||||
@@ -1165,21 +1165,21 @@ class Checker {
|
|||||||
unify(t1, TFloat, e1);
|
unify(t1, TFloat, e1);
|
||||||
unify(t2, TFloat, e2);
|
unify(t2, TFloat, e2);
|
||||||
}
|
}
|
||||||
case "&&", "||":
|
case OpBoolAnd, OpBoolOr:
|
||||||
typeExprWith(e1,TBool);
|
typeExprWith(e1,TBool);
|
||||||
typeExprWith(e2,TBool);
|
typeExprWith(e2,TBool);
|
||||||
return TBool;
|
return TBool;
|
||||||
case "...":
|
case OpInterval:
|
||||||
typeExprWith(e1,TInt);
|
typeExprWith(e1,TInt);
|
||||||
typeExprWith(e2,TInt);
|
typeExprWith(e2,TInt);
|
||||||
return makeIterator(TInt);
|
return makeIterator(TInt);
|
||||||
case "==", "!=":
|
case OpEq, OpNeq:
|
||||||
var t1 = typeExpr(e1,Value);
|
var t1 = typeExpr(e1,Value);
|
||||||
var t2 = typeExpr(e2,WithType(t1));
|
var t2 = typeExpr(e2,WithType(t1));
|
||||||
if( !tryUnify(t1,t2) )
|
if( !tryUnify(t1,t2) )
|
||||||
unify(t2,t1,e2);
|
unify(t2,t1,e2);
|
||||||
return TBool;
|
return TBool;
|
||||||
case ">", "<", ">=", "<=":
|
case OpGt, OpLt, OpGte, OpLte:
|
||||||
var t1 = typeExpr(e1,Value);
|
var t1 = typeExpr(e1,Value);
|
||||||
var t2 = typeExpr(e2,WithType(t1));
|
var t2 = typeExpr(e2,WithType(t1));
|
||||||
if( !tryUnify(t1,t2) )
|
if( !tryUnify(t1,t2) )
|
||||||
@@ -1190,12 +1190,26 @@ class Checker {
|
|||||||
error("Cannot compare "+typeStr(t1), expr);
|
error("Cannot compare "+typeStr(t1), expr);
|
||||||
}
|
}
|
||||||
return TBool;
|
return TBool;
|
||||||
|
case OpAddAssign, OpSubAssign, OpMultAssign, OpDivAssign, OpModAssign, OpAndAssign, OpOrAssign, OpXorAssign, OpShlAssign, OpShrAssign, OpUshrAssign, OpNcoalAssign:
|
||||||
|
var baseOp = switch(op) {
|
||||||
|
case OpAddAssign: OpAdd;
|
||||||
|
case OpSubAssign: OpSub;
|
||||||
|
case OpMultAssign: OpMult;
|
||||||
|
case OpDivAssign: OpDiv;
|
||||||
|
case OpModAssign: OpMod;
|
||||||
|
case OpAndAssign: OpAnd;
|
||||||
|
case OpOrAssign: OpOr;
|
||||||
|
case OpXorAssign: OpXor;
|
||||||
|
case OpShlAssign: OpShl;
|
||||||
|
case OpShrAssign: OpShr;
|
||||||
|
case OpUshrAssign: OpUshr;
|
||||||
|
case OpNcoalAssign: OpNcoal;
|
||||||
|
default: op;
|
||||||
|
};
|
||||||
|
var t = typeExpr(mk(EBinop(baseOp,e1,e2),expr),withType);
|
||||||
|
return typeExpr(mk(EBinop(OpAssign,e1,e2),expr), withType);
|
||||||
default:
|
default:
|
||||||
if( op.charCodeAt(op.length-1) == "=".code ) {
|
error("Unsupported operation "+op.toString(), expr);
|
||||||
var t = typeExpr(mk(EBinop(op.substr(0,op.length-1),e1,e2),expr),withType);
|
|
||||||
return typeExpr(mk(EBinop("=",e1,e2),expr), withType);
|
|
||||||
}
|
|
||||||
error("Unsupported operation "+op, expr);
|
|
||||||
}
|
}
|
||||||
case ETry(etry, v, et, ecatch):
|
case ETry(etry, v, et, ecatch):
|
||||||
var vt = typeExpr(etry, withType);
|
var vt = typeExpr(etry, withType);
|
||||||
|
|||||||
@@ -21,4 +21,9 @@ class Config {
|
|||||||
public static final DISALLOW_ABSTRACT_AND_ENUM = [
|
public static final DISALLOW_ABSTRACT_AND_ENUM = [
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@:unreflective
|
||||||
|
public static final IMPORT_BLACKLIST:Array<String> = [
|
||||||
|
// "flixel.FlxG"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
+13
-9
@@ -13,7 +13,6 @@ using Lambda;
|
|||||||
* @author Jamextreme140
|
* @author Jamextreme140
|
||||||
*/
|
*/
|
||||||
@:access(hscript.CustomClassHandler)
|
@:access(hscript.CustomClassHandler)
|
||||||
@:access(hscript.Property)
|
|
||||||
class CustomClass implements IHScriptCustomClassBehaviour {
|
class CustomClass implements IHScriptCustomClassBehaviour {
|
||||||
public var className(get, never):String;
|
public var className(get, never):String;
|
||||||
|
|
||||||
@@ -153,8 +152,12 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
|
|
||||||
if (fn != null && Reflect.isFunction(fn))
|
if (fn != null && Reflect.isFunction(fn))
|
||||||
return UnsafeReflect.callMethodUnsafe(null, fn, (args == null) ? [] : args);
|
return UnsafeReflect.callMethodUnsafe(null, fn, (args == null) ? [] : args);
|
||||||
else
|
|
||||||
__interp.error(ECustom('$name doesn\'t exists or is not a function'));
|
// If not found in current class, try parent class recursively
|
||||||
|
if (__superClass != null && __superClass is CustomClass)
|
||||||
|
return cast(__superClass, CustomClass).call(name, args, toSuper);
|
||||||
|
|
||||||
|
__interp.error(ECustom('$name doesn\'t exists or is not a function'));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,9 +173,9 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
var f = __interp.variables.get(name);
|
var f = __interp.variables.get(name);
|
||||||
if (f != null && allowProperty && f is Property) {
|
if (f != null && allowProperty && f is Property) {
|
||||||
var prop:Property = cast f;
|
var prop:Property = cast f;
|
||||||
prop.__allowSetGet = this.__allowSetGet;
|
//prop.__allowSetGet = this.__allowSetGet;
|
||||||
var r = prop.callGetter(name);
|
var r = prop.get(!__allowSetGet);
|
||||||
prop.__allowSetGet = null;
|
//prop.__allowSetGet = true;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
@@ -182,9 +185,9 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
var f = getField(name, false);
|
var f = getField(name, false);
|
||||||
if (f != null && f is Property) {
|
if (f != null && f is Property) {
|
||||||
var prop:Property = cast f;
|
var prop:Property = cast f;
|
||||||
prop.__allowSetGet = this.__allowSetGet;
|
//prop.__allowSetGet = this.__allowSetGet;
|
||||||
var r = prop.callSetter(name, val);
|
var r = prop.set(val, !__allowSetGet);
|
||||||
prop.__allowSetGet = null;
|
//prop.__allowSetGet = true;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
__interp.variables.set(name, val);
|
__interp.variables.set(name, val);
|
||||||
@@ -350,6 +353,7 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: scriptable "toString" function
|
||||||
public function toString():String
|
public function toString():String
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,23 +60,19 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
if(!__interp.variables.exists(f))
|
if(!__interp.variables.exists(f))
|
||||||
__interp.variables.set(f, v);
|
__interp.variables.set(f, v);
|
||||||
|
|
||||||
for(e in fields.copy()) {
|
for(i => e in fields.copy()) {
|
||||||
var validField:Bool = false;
|
var isValid:Bool = false;
|
||||||
var staticField:Bool = false;
|
var staticField:Bool = false;
|
||||||
var fieldName:String = "";
|
var fieldName:String = null;
|
||||||
switch (Tools.expr(e)) {
|
switch (Tools.expr(e)) {
|
||||||
case EVar(n, _, _, _, isStatic):
|
case EVar(n, _, _, _, isStatic) | EFunction(_, _, n, _, _, isStatic):
|
||||||
validField = true;
|
isValid = true;
|
||||||
staticField = isStatic;
|
|
||||||
fieldName = n;
|
|
||||||
case EFunction(_, _, n, _, _, isStatic, _, _, _, _):
|
|
||||||
validField = true;
|
|
||||||
staticField = isStatic;
|
staticField = isStatic;
|
||||||
fieldName = n;
|
fieldName = n;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if(staticField && validField) {
|
if(staticField && isValid) {
|
||||||
__interp.exprReturn(e);
|
__interp.exprReturn(e);
|
||||||
__staticFields.push(fieldName);
|
__staticFields.push(fieldName);
|
||||||
fields.remove(e);
|
fields.remove(e);
|
||||||
@@ -88,7 +84,7 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
return new CustomClass(this, args);
|
return new CustomClass(this, args);
|
||||||
|
|
||||||
@:allow(hscript.Interp)
|
@:allow(hscript.Interp)
|
||||||
function hasField(name:String) {
|
inline function hasField(name:String) {
|
||||||
return __staticFields.contains(name);
|
return __staticFields.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,9 +92,9 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
var f = __interp.variables.get(name);
|
var f = __interp.variables.get(name);
|
||||||
if(f is Property && allowProperty) {
|
if(f is Property && allowProperty) {
|
||||||
var prop:Property = cast f;
|
var prop:Property = cast f;
|
||||||
prop.__allowSetGet = this.__allowSetGet;
|
//prop.__allowSetGet = this.__allowSetGet;
|
||||||
var r = prop.callGetter(name);
|
var r = prop.get(!__allowSetGet);
|
||||||
prop.__allowSetGet = null;
|
//prop.__allowSetGet = true;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
@@ -108,9 +104,9 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
var f = getField(name, false);
|
var f = getField(name, false);
|
||||||
if(f is Property) {
|
if(f is Property) {
|
||||||
var prop:Property = cast f;
|
var prop:Property = cast f;
|
||||||
prop.__allowSetGet = this.__allowSetGet;
|
//prop.__allowSetGet = this.__allowSetGet;
|
||||||
var r = prop.callSetter(name, val);
|
var r = prop.set(val, !__allowSetGet);
|
||||||
prop.__allowSetGet = null;
|
//prop.__allowSetGet = true;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
__interp.variables.set(name, val);
|
__interp.variables.set(name, val);
|
||||||
@@ -119,10 +115,9 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
|
|
||||||
public function hget(name:String):Dynamic {
|
public function hget(name:String):Dynamic {
|
||||||
if(name == 'new') {
|
if(name == 'new') {
|
||||||
var __constructor = Reflect.makeVarArgs(function(args:Array<Dynamic>) {
|
return Reflect.makeVarArgs(function(args:Array<Dynamic>):Dynamic {
|
||||||
return this.hnew(args);
|
return inline this.hnew(args);
|
||||||
});
|
});
|
||||||
return __constructor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasField(name)) {
|
if(hasField(name)) {
|
||||||
|
|||||||
+403
-244
@@ -1,244 +1,403 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C)2008-2017 Haxe Foundation
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
* to deal in the Software without restriction, including without limitation
|
* to deal in the Software without restriction, including without limitation
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
|
|
||||||
typedef Int8 = #if cpp cpp.Int8 #elseif java java.Int8 #elseif cs cs.Int8 #else Int #end;
|
typedef Int8 = #if cpp cpp.Int8 #elseif java java.Int8 #elseif cs cs.Int8 #else Int #end;
|
||||||
typedef Int16 = #if cpp cpp.Int16 #elseif java java.Int16 #elseif cs cs.Int16 #else Int #end;
|
typedef Int16 = #if cpp cpp.Int16 #elseif java java.Int16 #elseif cs cs.Int16 #else Int #end;
|
||||||
typedef Int32 = #if cpp cpp.Int32 #else Int #end;
|
typedef Int32 = #if cpp cpp.Int32 #else Int #end;
|
||||||
typedef Int64 = #if cpp cpp.Int64 #elseif java java.Int64 #elseif cs cs.Int64 #else Int #end;
|
typedef Int64 = #if cpp cpp.Int64 #elseif java java.Int64 #elseif cs cs.Int64 #else Int #end;
|
||||||
|
|
||||||
typedef UInt8 = #if cpp cpp.UInt8 #elseif cs cs.UInt8 #else Int #end;
|
typedef UInt8 = #if cpp cpp.UInt8 #elseif cs cs.UInt8 #else Int #end;
|
||||||
typedef UInt16 = #if cpp cpp.UInt16 #elseif cs cs.UInt16 #else Int #end;
|
typedef UInt16 = #if cpp cpp.UInt16 #elseif cs cs.UInt16 #else Int #end;
|
||||||
typedef UInt32 = #if cpp cpp.UInt32 #else Int #end;
|
|
||||||
typedef UInt64 = #if cpp cpp.UInt64 #else Int #end;
|
enum abstract Binop(Int) from Int to Int {
|
||||||
|
var OpAdd = 0;
|
||||||
enum Const {
|
var OpSub = 1;
|
||||||
CInt( v : Int );
|
var OpMult = 2;
|
||||||
CFloat( f : Float );
|
var OpDiv = 3;
|
||||||
CString( s : String );
|
var OpMod = 4;
|
||||||
}
|
var OpAnd = 5;
|
||||||
|
var OpOr = 6;
|
||||||
#if hscriptPos
|
var OpXor = 7;
|
||||||
@:structInit
|
var OpShl = 8;
|
||||||
final class Expr {
|
var OpShr = 9;
|
||||||
public var e : ExprDef;
|
var OpUshr = 10;
|
||||||
public var pmin : Int;
|
var OpEq = 11;
|
||||||
public var pmax : Int;
|
var OpNeq = 12;
|
||||||
public var origin : String;
|
var OpGte = 13;
|
||||||
public var line : Int;
|
var OpLte = 14;
|
||||||
}
|
var OpGt = 15;
|
||||||
enum ExprDef {
|
var OpLt = 16;
|
||||||
#else
|
var OpBoolOr = 17;
|
||||||
typedef ExprDef = Expr;
|
var OpBoolAnd = 18;
|
||||||
enum Expr {
|
var OpIs = 19;
|
||||||
#end
|
var OpAssign = 20;
|
||||||
EConst( c : Const );
|
var OpNcoal = 21;
|
||||||
EIdent( v : String );
|
var OpInterval = 22;
|
||||||
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool, ?get : FieldPropertyAccess, ?set : FieldPropertyAccess, ?isVar:Bool );
|
var OpArrow = 23;
|
||||||
EParent( e : Expr );
|
var OpAddAssign = 24;
|
||||||
EBlock( e : Array<Expr> );
|
var OpSubAssign = 25;
|
||||||
EField( e : Expr, f : String , ?safe : Bool );
|
var OpMultAssign = 26;
|
||||||
EBinop( op : String, e1 : Expr, e2 : Expr );
|
var OpDivAssign = 27;
|
||||||
EUnop( op : String, prefix : Bool, e : Expr );
|
var OpModAssign = 28;
|
||||||
ECall( e : Expr, params : Array<Expr> );
|
var OpAndAssign = 29;
|
||||||
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
var OpOrAssign = 30;
|
||||||
EWhile( cond : Expr, e : Expr );
|
var OpXorAssign = 31;
|
||||||
EFor( v : String, it : Expr, e : Expr, ?ithv: String);
|
var OpShlAssign = 32;
|
||||||
EBreak;
|
var OpShrAssign = 33;
|
||||||
EContinue;
|
var OpUshrAssign = 34;
|
||||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool );
|
var OpNcoalAssign = 35;
|
||||||
EReturn( ?e : Expr );
|
var OpArrowFn = 36;
|
||||||
EArray( e : Expr, index : Expr );
|
|
||||||
EArrayDecl( e : Array<Expr>, ?wantedType: CType );
|
public static inline function fromString(s:String):Binop {
|
||||||
ENew( cl : String, params : Array<Expr>, ?paramType:Array<CType> );
|
return switch(s) {
|
||||||
EThrow( e : Expr );
|
case "+": OpAdd;
|
||||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
case "-": OpSub;
|
||||||
EObject( fl : Array<ObjectField> );
|
case "*": OpMult;
|
||||||
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
case "/": OpDiv;
|
||||||
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
case "%": OpMod;
|
||||||
EDoWhile( cond : Expr, e : Expr);
|
case "&": OpAnd;
|
||||||
EMeta( name : String, args : Array<Expr>, e : Expr );
|
case "|": OpOr;
|
||||||
ECheckType( e : Expr, t : CType );
|
case "^": OpXor;
|
||||||
|
case "<<": OpShl;
|
||||||
EPackage( ?n:String );
|
case ">>": OpShr;
|
||||||
EImport( c : String, ?asname:String, ?isUsing:Bool );
|
case ">>>": OpUshr;
|
||||||
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String>, ?isFinal:Bool, ?isPrivate:Bool );
|
case "==": OpEq;
|
||||||
EEnum( en:EnumDecl, ?isAbstract:Bool );
|
case "!=": OpNeq;
|
||||||
ECast(e:Expr, ?t:CType);
|
case ">=": OpGte;
|
||||||
ERegex(e:String, flags:String);
|
case "<=": OpLte;
|
||||||
}
|
case ">": OpGt;
|
||||||
|
case "<": OpLt;
|
||||||
@:structInit
|
case "||": OpBoolOr;
|
||||||
final class ObjectField {
|
case "&&": OpBoolAnd;
|
||||||
public var name : String;
|
case "is": OpIs;
|
||||||
public var e : Expr;
|
case "=": OpAssign;
|
||||||
}
|
case "??": OpNcoal;
|
||||||
|
case "...": OpInterval;
|
||||||
@:structInit
|
case "->": OpArrow;
|
||||||
final class SwitchCase {
|
case "=>": OpArrowFn;
|
||||||
public var values : Array<Expr>;
|
case "+=": OpAddAssign;
|
||||||
public var expr : Expr;
|
case "-=": OpSubAssign;
|
||||||
}
|
case "*=": OpMultAssign;
|
||||||
|
case "/=": OpDivAssign;
|
||||||
@:structInit
|
case "%=": OpModAssign;
|
||||||
final class Argument {
|
case "&=": OpAndAssign;
|
||||||
public var name : String;
|
case "|=": OpOrAssign;
|
||||||
public var t : CType;
|
case "^=": OpXorAssign;
|
||||||
public var opt : Bool;
|
case "<<=": OpShlAssign;
|
||||||
public var value : Expr;
|
case ">>=": OpShrAssign;
|
||||||
}
|
case ">>>=": OpUshrAssign;
|
||||||
|
case _ if (s == "??" + "="): OpNcoalAssign;
|
||||||
@:structInit
|
default: -1;
|
||||||
final class MetadataEntry {
|
}
|
||||||
public var name : String;
|
}
|
||||||
public var params : Array<Expr>;
|
|
||||||
}
|
public inline function toString():String {
|
||||||
|
return switch(this) {
|
||||||
typedef Metadata = Array<MetadataEntry>;
|
case OpAdd: "+";
|
||||||
|
case OpSub: "-";
|
||||||
@:structInit
|
case OpMult: "*";
|
||||||
final class EnumDecl {
|
case OpDiv: "/";
|
||||||
public var name : String;
|
case OpMod: "%";
|
||||||
public var fields : Array<EnumField>;
|
case OpAnd: "&";
|
||||||
}
|
case OpOr: "|";
|
||||||
|
case OpXor: "^";
|
||||||
@:structInit
|
case OpShl: "<<";
|
||||||
final class EnumField {
|
case OpShr: ">>";
|
||||||
public var name : String;
|
case OpUshr: ">>>";
|
||||||
public var args : Array<Argument>;
|
case OpEq: "==";
|
||||||
}
|
case OpNeq: "!=";
|
||||||
|
case OpGte: ">=";
|
||||||
enum CType {
|
case OpLte: "<=";
|
||||||
CTPath( path : Array<String>, ?params : Array<CType> );
|
case OpGt: ">";
|
||||||
CTFun( args : Array<CType>, ret : CType );
|
case OpLt: "<";
|
||||||
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
|
case OpBoolOr: "||";
|
||||||
CTParent( t : CType );
|
case OpBoolAnd: "&&";
|
||||||
CTOpt( t : CType );
|
case OpIs: "is";
|
||||||
CTNamed( n : String, t : CType );
|
case OpAssign: "=";
|
||||||
CTExpr( e : Expr ); // for type parameters only
|
case OpNcoal: "??";
|
||||||
}
|
case OpInterval: "...";
|
||||||
|
case OpArrow: "->";
|
||||||
#if hscriptPos
|
case OpArrowFn: "=>";
|
||||||
class Error {
|
case OpAddAssign: "+=";
|
||||||
public var e : ErrorDef;
|
case OpSubAssign: "-=";
|
||||||
public var pmin : Int;
|
case OpMultAssign: "*=";
|
||||||
public var pmax : Int;
|
case OpDivAssign: "/=";
|
||||||
public var origin : String;
|
case OpModAssign: "%=";
|
||||||
public var line : Int;
|
case OpAndAssign: "&=";
|
||||||
public function new(e, pmin, pmax, origin, line) {
|
case OpOrAssign: "|=";
|
||||||
this.e = e;
|
case OpXorAssign: "^=";
|
||||||
this.pmin = pmin;
|
case OpShlAssign: "<<=";
|
||||||
this.pmax = pmax;
|
case OpShrAssign: ">>=";
|
||||||
this.origin = origin;
|
case OpUshrAssign: ">>>=";
|
||||||
this.line = line;
|
case OpNcoalAssign: "??" + "=";
|
||||||
}
|
default: "?";
|
||||||
public function toString(): String {
|
}
|
||||||
return Printer.errorToString(this);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
enum ErrorDef {
|
enum abstract Unop(Int) from Int to Int {
|
||||||
#else
|
var OpNot = 0;
|
||||||
enum Error {
|
var OpNeg = 1;
|
||||||
#end
|
var OpIncrement = 2;
|
||||||
EInvalidChar( c : Int );
|
var OpDecrement = 3;
|
||||||
EUnexpected( s : String );
|
var OpNegBits = 4;
|
||||||
EUnterminatedString;
|
|
||||||
EUnterminatedComment;
|
public static inline function fromString(s:String):Unop {
|
||||||
EInvalidPreprocessor( msg : String );
|
return switch(s) {
|
||||||
EUnknownVariable( v : String );
|
case "!": OpNot;
|
||||||
EInvalidIterator( v : String );
|
case "-": OpNeg;
|
||||||
EInvalidOp( op : String );
|
case "++": OpIncrement;
|
||||||
EInvalidAccess( f : String );
|
case "--": OpDecrement;
|
||||||
ECustom( msg : String );
|
case "~": OpNegBits;
|
||||||
EInvalidClass( className : String);
|
default: -1;
|
||||||
EAlreadyExistingClass( className : String);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public inline function toString():String {
|
||||||
enum ModuleDecl {
|
return switch(this) {
|
||||||
DPackage( path : Array<String> );
|
case OpNot: "!";
|
||||||
DImport( path : Array<String>, ?everything : Bool );
|
case OpNeg: "-";
|
||||||
DClass( c : ClassDecl );
|
case OpIncrement: "++";
|
||||||
DTypedef( c : TypeDecl );
|
case OpDecrement: "--";
|
||||||
}
|
case OpNegBits: "~";
|
||||||
|
default: "?";
|
||||||
typedef ModuleType = {
|
}
|
||||||
var name : String;
|
}
|
||||||
var params : {}; // TODO : not yet parsed
|
}
|
||||||
var meta : Metadata;
|
|
||||||
var isPrivate : Bool;
|
typedef UInt32 = #if cpp cpp.UInt32 #else Int #end;
|
||||||
}
|
typedef UInt64 = #if cpp cpp.UInt64 #else Int #end;
|
||||||
|
|
||||||
typedef ClassDecl = {> ModuleType,
|
enum Const {
|
||||||
var extend : Null<CType>;
|
CInt( v : Int );
|
||||||
var implement : Array<CType>;
|
CFloat( f : Float );
|
||||||
var fields : Array<FieldDecl>;
|
CString( s : String, ?i : Bool );
|
||||||
var isExtern : Bool;
|
}
|
||||||
}
|
|
||||||
|
#if hscriptPos
|
||||||
typedef TypeDecl = {> ModuleType,
|
@:structInit
|
||||||
var t : CType;
|
final class Expr {
|
||||||
}
|
public var e : ExprDef;
|
||||||
|
public var pmin : Int;
|
||||||
typedef FieldDecl = {
|
public var pmax : Int;
|
||||||
var name : String;
|
public var origin : String;
|
||||||
var meta : Metadata;
|
public var line : Int;
|
||||||
var kind : FieldKind;
|
}
|
||||||
var access : Array<FieldAccess>;
|
enum ExprDef {
|
||||||
}
|
#else
|
||||||
|
typedef ExprDef = Expr;
|
||||||
enum abstract FieldAccess(UInt8) {
|
enum Expr {
|
||||||
var APublic;
|
#end
|
||||||
var APrivate;
|
EConst( c : Const );
|
||||||
var AInline;
|
EIdent( v : String );
|
||||||
var AOverride;
|
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool, ?get : FieldPropertyAccess, ?set : FieldPropertyAccess, ?isVar:Bool );
|
||||||
var AStatic;
|
EParent( e : Expr );
|
||||||
var AMacro;
|
EBlock( e : Array<Expr> );
|
||||||
}
|
EField( e : Expr, f : String , ?safe : Bool );
|
||||||
|
EBinop( op : Binop, e1 : Expr, e2 : Expr );
|
||||||
enum abstract FieldPropertyAccess(UInt8) {
|
EUnop( op : Unop, prefix : Bool, e : Expr );
|
||||||
var ADefault;
|
ECall( e : Expr, params : Array<Expr> );
|
||||||
var ANull;
|
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
||||||
var AGet;
|
EWhile( cond : Expr, e : Expr );
|
||||||
var ASet;
|
EFor( v : String, it : Expr, e : Expr, ?ithv: String);
|
||||||
var ADynamic;
|
EBreak;
|
||||||
var ANever;
|
EContinue;
|
||||||
}
|
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool );
|
||||||
|
EReturn( ?e : Expr );
|
||||||
enum FieldKind {
|
EArray( e : Expr, index : Expr );
|
||||||
KFunction( f : FunctionDecl );
|
EArrayDecl( e : Array<Expr>, ?wantedType: CType );
|
||||||
KVar( v : VarDecl );
|
ENew( cl : String, params : Array<Expr>, ?paramType:Array<CType> );
|
||||||
}
|
EThrow( e : Expr );
|
||||||
|
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||||
@:structInit
|
EObject( fl : Array<ObjectField> );
|
||||||
final class FunctionDecl {
|
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||||
public var args : Array<Argument>;
|
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
||||||
public var body : Expr;
|
EDoWhile( cond : Expr, e : Expr);
|
||||||
public var ret : Null<CType>;
|
EMeta( name : String, args : Array<Expr>, e : Expr );
|
||||||
}
|
ECheckType( e : Expr, t : CType );
|
||||||
|
|
||||||
typedef VarDecl = {
|
EPackage( ?n:String );
|
||||||
var get : Null<String>;
|
EImport( c : String, ?asname:String, ?isUsing:Bool );
|
||||||
var set : Null<String>;
|
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String>, ?isFinal:Bool, ?isPrivate:Bool );
|
||||||
var expr : Null<Expr>;
|
EEnum( en:EnumDecl, ?isAbstract:Bool );
|
||||||
var type : Null<CType>;
|
ECast(e:Expr, ?t:CType);
|
||||||
}
|
ERegex(e:String, flags:String);
|
||||||
|
}
|
||||||
|
|
||||||
|
@:structInit
|
||||||
|
final class ObjectField {
|
||||||
|
public var name : String;
|
||||||
|
public var e : Expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:structInit
|
||||||
|
final class SwitchCase {
|
||||||
|
public var values : Array<Expr>;
|
||||||
|
public var expr : Expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:structInit
|
||||||
|
final class Argument {
|
||||||
|
public var name : String;
|
||||||
|
public var t : CType;
|
||||||
|
public var opt : Bool;
|
||||||
|
public var value : Expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:structInit
|
||||||
|
final class MetadataEntry {
|
||||||
|
public var name : String;
|
||||||
|
public var params : Array<Expr>;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef Metadata = Array<MetadataEntry>;
|
||||||
|
|
||||||
|
@:structInit
|
||||||
|
final class EnumDecl {
|
||||||
|
public var name : String;
|
||||||
|
public var fields : Array<EnumField>;
|
||||||
|
public var underlyingType : Null<CType>;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:structInit
|
||||||
|
final class EnumField {
|
||||||
|
public var name : String;
|
||||||
|
public var args : Array<Argument>;
|
||||||
|
public var value : Null<Expr>;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CType {
|
||||||
|
CTPath( path : Array<String>, ?params : Array<CType> );
|
||||||
|
CTFun( args : Array<CType>, ret : CType );
|
||||||
|
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
|
||||||
|
CTParent( t : CType );
|
||||||
|
CTOpt( t : CType );
|
||||||
|
CTNamed( n : String, t : CType );
|
||||||
|
CTExpr( e : Expr ); // for type parameters only
|
||||||
|
}
|
||||||
|
|
||||||
|
#if hscriptPos
|
||||||
|
class Error {
|
||||||
|
public var e : ErrorDef;
|
||||||
|
public var pmin : Int;
|
||||||
|
public var pmax : Int;
|
||||||
|
public var origin : String;
|
||||||
|
public var line : Int;
|
||||||
|
public function new(e, pmin, pmax, origin, line) {
|
||||||
|
this.e = e;
|
||||||
|
this.pmin = pmin;
|
||||||
|
this.pmax = pmax;
|
||||||
|
this.origin = origin;
|
||||||
|
this.line = line;
|
||||||
|
}
|
||||||
|
public function toString(): String {
|
||||||
|
return Printer.errorToString(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enum ErrorDef {
|
||||||
|
#else
|
||||||
|
enum Error {
|
||||||
|
#end
|
||||||
|
EInvalidChar( c : Int );
|
||||||
|
EUnexpected( s : String );
|
||||||
|
EUnterminatedString;
|
||||||
|
EUnterminatedComment;
|
||||||
|
EInvalidPreprocessor( msg : String );
|
||||||
|
EUnknownVariable( v : String );
|
||||||
|
EInvalidIterator( v : String );
|
||||||
|
EInvalidOp( op : String );
|
||||||
|
EInvalidAccess( f : String );
|
||||||
|
ECustom( msg : String );
|
||||||
|
EInvalidClass( className : String);
|
||||||
|
EAlreadyExistingClass( className : String);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum ModuleDecl {
|
||||||
|
DPackage( path : Array<String> );
|
||||||
|
DImport( path : Array<String>, ?everything : Bool );
|
||||||
|
DClass( c : ClassDecl );
|
||||||
|
DTypedef( c : TypeDecl );
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ModuleType = {
|
||||||
|
var name : String;
|
||||||
|
var params : {}; // TODO : not yet parsed
|
||||||
|
var meta : Metadata;
|
||||||
|
var isPrivate : Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ClassDecl = {> ModuleType,
|
||||||
|
var extend : Null<CType>;
|
||||||
|
var implement : Array<CType>;
|
||||||
|
var fields : Array<FieldDecl>;
|
||||||
|
var isExtern : Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TypeDecl = {> ModuleType,
|
||||||
|
var t : CType;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef FieldDecl = {
|
||||||
|
var name : String;
|
||||||
|
var meta : Metadata;
|
||||||
|
var kind : FieldKind;
|
||||||
|
var access : Array<FieldAccess>;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum abstract FieldAccess(UInt8) {
|
||||||
|
var APublic;
|
||||||
|
var APrivate;
|
||||||
|
var AInline;
|
||||||
|
var AOverride;
|
||||||
|
var AStatic;
|
||||||
|
var AMacro;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum abstract FieldPropertyAccess(UInt8) {
|
||||||
|
var ADefault;
|
||||||
|
var ANull;
|
||||||
|
var AGet;
|
||||||
|
var ASet;
|
||||||
|
var ADynamic;
|
||||||
|
var ANever;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FieldKind {
|
||||||
|
KFunction( f : FunctionDecl );
|
||||||
|
KVar( v : VarDecl );
|
||||||
|
}
|
||||||
|
|
||||||
|
@:structInit
|
||||||
|
final class FunctionDecl {
|
||||||
|
public var args : Array<Argument>;
|
||||||
|
public var body : Expr;
|
||||||
|
public var ret : Null<CType>;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef VarDecl = {
|
||||||
|
var get : Null<String>;
|
||||||
|
var set : Null<String>;
|
||||||
|
var expr : Null<Expr>;
|
||||||
|
var type : Null<CType>;
|
||||||
|
}
|
||||||
|
|||||||
+119
-3
@@ -2,13 +2,13 @@ package hscript;
|
|||||||
|
|
||||||
import hscript.utils.UnsafeReflect;
|
import hscript.utils.UnsafeReflect;
|
||||||
|
|
||||||
// TODO: EnumTools for scripted enums
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class for enums, both for real and scripted.
|
* Wrapper class for enums, both for real and scripted.
|
||||||
|
* Use EnumTools and EnumValueTools for enum operations.
|
||||||
*/
|
*/
|
||||||
@:structInit
|
@:structInit
|
||||||
class HEnum implements IHScriptCustomBehaviour {
|
class HEnum implements IHScriptCustomBehaviour {
|
||||||
private var enumValues(default, null) = {};
|
var enumValues(default, null) = {};
|
||||||
|
|
||||||
public function setEnum(name:String, enumValue:Dynamic):Void {
|
public function setEnum(name:String, enumValue:Dynamic):Void {
|
||||||
UnsafeReflect.setField(enumValues, name, enumValue);
|
UnsafeReflect.setField(enumValues, name, enumValue);
|
||||||
@@ -20,6 +20,10 @@ class HEnum implements IHScriptCustomBehaviour {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEnumValues():Dynamic {
|
||||||
|
return enumValues;
|
||||||
|
}
|
||||||
|
|
||||||
public function hget(name:String):Dynamic {
|
public function hget(name:String):Dynamic {
|
||||||
return getEnum(name);
|
return getEnum(name);
|
||||||
}
|
}
|
||||||
@@ -57,10 +61,122 @@ class HEnumValue {
|
|||||||
if (args.length != other.args.length)
|
if (args.length != other.args.length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i in 0...args.length) // TODO: allow deep comparison, like arrays
|
for (i in 0...args.length)
|
||||||
if (args[i] != other.args[i])
|
if (args[i] != other.args[i])
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@:nullSafety
|
||||||
|
class EnumTools {
|
||||||
|
public static function getConstructors(e:Dynamic):Array<String> {
|
||||||
|
if(Std.isOfType(e, HEnum)) {
|
||||||
|
var henum:HEnum = cast e;
|
||||||
|
return UnsafeReflect.fields(henum.getEnumValues());
|
||||||
|
}
|
||||||
|
return Type.getEnumConstructs(cast e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createByName(e:Dynamic, constr:String, ?params:Array<Dynamic>):Dynamic {
|
||||||
|
if(Std.isOfType(e, HEnum)) {
|
||||||
|
var henum:HEnum = cast e;
|
||||||
|
var constructor = henum.getEnum(constr);
|
||||||
|
if(constructor == null)
|
||||||
|
throw 'Constructor $constr not found in enum';
|
||||||
|
if(Std.isOfType(constructor, HEnumValue))
|
||||||
|
return constructor;
|
||||||
|
if(Reflect.isFunction(constructor))
|
||||||
|
return constructor(params == null ? [] : params);
|
||||||
|
throw 'Invalid constructor type';
|
||||||
|
}
|
||||||
|
return Type.createEnum(cast e, constr, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createByIndex(e:Dynamic, index:Int, ?params:Array<Dynamic>):Dynamic {
|
||||||
|
if(Std.isOfType(e, HEnum)) {
|
||||||
|
var constructors = getConstructors(e);
|
||||||
|
if(index < 0 || index >= constructors.length)
|
||||||
|
throw 'Index $index out of bounds for enum';
|
||||||
|
return createByName(e, constructors[index], params);
|
||||||
|
}
|
||||||
|
return Type.createEnumIndex(cast e, index, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@:nullSafety
|
||||||
|
class EnumValueTools {
|
||||||
|
public static function getType(e:Dynamic):Null<String> {
|
||||||
|
if(Std.isOfType(e, HEnumValue)) {
|
||||||
|
var hv:HEnumValue = cast e;
|
||||||
|
return hv.enumName;
|
||||||
|
}
|
||||||
|
var en = Type.getEnum(e);
|
||||||
|
if(en != null)
|
||||||
|
return Type.getEnumName(en);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getName(e:Dynamic):String {
|
||||||
|
if(Std.isOfType(e, HEnumValue)) {
|
||||||
|
var hv:HEnumValue = cast e;
|
||||||
|
return hv.fieldName;
|
||||||
|
}
|
||||||
|
return Type.enumConstructor(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getParameters(e:Dynamic):Array<Dynamic> {
|
||||||
|
if(Std.isOfType(e, HEnumValue)) {
|
||||||
|
var hv:HEnumValue = cast e;
|
||||||
|
return hv.args.copy();
|
||||||
|
}
|
||||||
|
return Type.enumParameters(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getIndex(e:Dynamic):Int {
|
||||||
|
if(Std.isOfType(e, HEnumValue)) {
|
||||||
|
var hv:HEnumValue = cast e;
|
||||||
|
return hv.index;
|
||||||
|
}
|
||||||
|
return Type.enumIndex(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function equals(a:Dynamic, b:Dynamic):Bool {
|
||||||
|
if(Std.isOfType(a, HEnumValue) && Std.isOfType(b, HEnumValue)) {
|
||||||
|
var hva:HEnumValue = cast a;
|
||||||
|
var hvb:HEnumValue = cast b;
|
||||||
|
return hva.compare(hvb);
|
||||||
|
}
|
||||||
|
return Type.enumEq(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function match(e:Dynamic, pattern:Dynamic):Bool {
|
||||||
|
if(Std.isOfType(e, HEnumValue)) {
|
||||||
|
var hv:HEnumValue = cast e;
|
||||||
|
if(Std.isOfType(pattern, HEnumValue)) {
|
||||||
|
var hp:HEnumValue = cast pattern;
|
||||||
|
if(hv.enumName != hp.enumName || hv.fieldName != hp.fieldName)
|
||||||
|
return false;
|
||||||
|
if(hp.args.length == 0)
|
||||||
|
return true;
|
||||||
|
if(hv.args.length != hp.args.length)
|
||||||
|
return false;
|
||||||
|
for(i in 0...hp.args.length) {
|
||||||
|
var pa = hp.args[i];
|
||||||
|
if(pa != null && hv.args[i] != pa)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(Reflect.isObject(pattern)) {
|
||||||
|
var patternName = UnsafeReflect.hasField(pattern, "name") ? UnsafeReflect.field(pattern, "name") : null;
|
||||||
|
if(patternName != null && patternName != hv.fieldName)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Type.enumEq(e, pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+520
-306
File diff suppressed because it is too large
Load Diff
+5
-4
@@ -151,12 +151,13 @@ class Macro {
|
|||||||
case EField(e, f):
|
case EField(e, f):
|
||||||
EField(convert(e), f);
|
EField(convert(e), f);
|
||||||
case EBinop(op, e1, e2):
|
case EBinop(op, e1, e2):
|
||||||
var b = binops.get(op);
|
var b = binops.get(op.toString());
|
||||||
if( b == null ) throw EInvalidOp(op);
|
if( b == null ) throw EInvalidOp(op.toString());
|
||||||
EBinop(b, convert(e1), convert(e2));
|
EBinop(b, convert(e1), convert(e2));
|
||||||
case EUnop(op, prefix, e):
|
case EUnop(op, prefix, e):
|
||||||
var u = unops.get(op);
|
var opStr = op.toString();
|
||||||
if( u == null ) throw EInvalidOp(op);
|
var u = unops.get(opStr);
|
||||||
|
if( u == null ) throw EInvalidOp(opStr);
|
||||||
EUnop(u, !prefix, convert(e));
|
EUnop(u, !prefix, convert(e));
|
||||||
case ECall(e, params):
|
case ECall(e, params):
|
||||||
ECall(convert(e), map(params, convert));
|
ECall(convert(e), map(params, convert));
|
||||||
|
|||||||
+332
-172
@@ -215,7 +215,7 @@ class Parser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function push(tk: Token):Void {
|
@:analyzer(fusion) inline function push(tk: Token):Void {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
tokens.push( { t : tk, min : tokenMin, max : tokenMax } );
|
tokens.push( { t : tk, min : tokenMin, max : tokenMax } );
|
||||||
tokenMin = oldTokenMin;
|
tokenMin = oldTokenMin;
|
||||||
@@ -225,17 +225,17 @@ class Parser {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function ensure(tk:Token):Void {
|
@:analyzer(fusion) inline function ensure(tk:Token):Void {
|
||||||
var t = token();
|
var t = token();
|
||||||
if( t != tk ) unexpected(t);
|
if( t != tk ) unexpected(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function ensureToken(tk:Token):Void {
|
@:analyzer(fusion) inline function ensureToken(tk:Token):Void {
|
||||||
var t = token();
|
var t = token();
|
||||||
if( !Type.enumEq(t,tk) ) unexpected(t);
|
if( !Type.enumEq(t,tk) ) unexpected(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybe(tk:Token):Bool {
|
@:analyzer(fusion) inline function maybe(tk:Token):Bool {
|
||||||
var t = token();
|
var t = token();
|
||||||
if( Type.enumEq(t, tk) )
|
if( Type.enumEq(t, tk) )
|
||||||
return true;
|
return true;
|
||||||
@@ -253,7 +253,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function expr(e:Expr):#if hscriptPos ExprDef #else Expr #end {
|
@:analyzer(fusion) inline function expr(e:Expr):#if hscriptPos ExprDef #else Expr #end {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return e.e;
|
return e.e;
|
||||||
#else
|
#else
|
||||||
@@ -261,7 +261,7 @@ class Parser {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function pmin(e:Expr):Int {
|
@:analyzer(fusion) inline function pmin(e:Expr):Int {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return e == null ? 0 : e.pmin;
|
return e == null ? 0 : e.pmin;
|
||||||
#else
|
#else
|
||||||
@@ -269,7 +269,7 @@ class Parser {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function pmax(e:Expr):Int {
|
@:analyzer(fusion) inline function pmax(e:Expr):Int {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return e == null ? 0 : e.pmax;
|
return e == null ? 0 : e.pmax;
|
||||||
#else
|
#else
|
||||||
@@ -277,7 +277,7 @@ class Parser {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function mk(e:#if hscriptPos ExprDef #else Expr #end,?pmin:Int,?pmax:Int) : Expr {
|
@:analyzer(fusion) inline function mk(e:#if hscriptPos ExprDef #else Expr #end,?pmin:Int,?pmax:Int) : Expr {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
if( e == null ) return null;
|
if( e == null ) return null;
|
||||||
if( pmin == null ) pmin = tokenMin;
|
if( pmin == null ) pmin = tokenMin;
|
||||||
@@ -288,7 +288,7 @@ class Parser {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBlock(e:Expr):Bool {
|
@:analyzer(fusion) inline function isBlock(e:Expr):Bool {
|
||||||
if( e == null ) return false;
|
if( e == null ) return false;
|
||||||
return switch( expr(e) ) {
|
return switch( expr(e) ) {
|
||||||
case EBlock(_), EObject(_), ESwitch(_), EEnum(_, _): true;
|
case EBlock(_), EObject(_), ESwitch(_), EEnum(_, _): true;
|
||||||
@@ -308,7 +308,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseFullExpr( exprs : Array<Expr> ):Void {
|
@:analyzer(fusion) function parseFullExpr( exprs : Array<Expr> ):Void {
|
||||||
var e = parseExpr();
|
var e = parseExpr();
|
||||||
exprs.push(e);
|
exprs.push(e);
|
||||||
|
|
||||||
@@ -340,7 +340,7 @@ class Parser {
|
|||||||
if( !allowJSON )
|
if( !allowJSON )
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
switch( c ) {
|
switch( c ) {
|
||||||
case CString(s): id = s;
|
case CString(s, _): id = s;
|
||||||
default: unexpected(tk);
|
default: unexpected(tk);
|
||||||
}
|
}
|
||||||
case TBrClose:
|
case TBrClose:
|
||||||
@@ -371,12 +371,17 @@ class Parser {
|
|||||||
var p1 = tokenMin;
|
var p1 = tokenMin;
|
||||||
#end
|
#end
|
||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
case TId(id): // TODO: direct access to classes by typing their path
|
case TId(id):
|
||||||
var e = parseStructure(id, oldPos);
|
var e = parseStructure(id, oldPos);
|
||||||
if( e == null )
|
if( e == null )
|
||||||
e = mk(EIdent(id));
|
e = mk(EIdent(id));
|
||||||
return parseExprNext(e);
|
return parseExprNext(e);
|
||||||
case TConst(c):
|
case TConst(c):
|
||||||
|
switch(c) {
|
||||||
|
case CString(s, i):
|
||||||
|
if(i) return parseExprNext(interpolateString(s));
|
||||||
|
default:
|
||||||
|
}
|
||||||
return parseExprNext(mk(EConst(c)));
|
return parseExprNext(mk(EConst(c)));
|
||||||
case TPOpen:
|
case TPOpen:
|
||||||
tk = token();
|
tk = token();
|
||||||
@@ -599,27 +604,28 @@ class Parser {
|
|||||||
return switch( expr(e) ) {
|
return switch( 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(Unop.fromString(op),true,e),pmin(e),pmax(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeBinop( op:String, e1:Expr, e:Expr ):Expr {
|
@:analyzer(fusion) inline function makeBinop( op:String, e1:Expr, e:Expr ):Expr {
|
||||||
|
var binop = Binop.fromString(op);
|
||||||
if( e == null && resumeErrors )
|
if( e == null && resumeErrors )
|
||||||
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
|
return mk(EBinop(binop,e1,e),pmin(e1),pmax(e1));
|
||||||
return switch( expr(e) ) {
|
return switch( expr(e) ) {
|
||||||
case EBinop(op2,e2,e3):
|
case EBinop(op2,e2,e3):
|
||||||
var delta = opPriority.get(op) - opPriority.get(op2);
|
var delta = opPriority.get(op) - opPriority.get(op2.toString());
|
||||||
if( delta < 0 || (delta == 0 && !opRightAssoc.exists(op)) )
|
if( delta < 0 || (delta == 0 && !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(binop, e1, e), pmin(e1), pmax(e));
|
||||||
case ETernary(e2,e3,e4):
|
case ETernary(e2,e3,e4):
|
||||||
if( opRightAssoc.exists(op) )
|
if( opRightAssoc.exists(op) )
|
||||||
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
mk(EBinop(binop,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(binop,e1,e),pmin(e1),pmax(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1041,72 +1047,62 @@ class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "class":
|
case "class":
|
||||||
// example: class ClassName
|
// example: class ClassName<K, V>
|
||||||
var tk = token();
|
var name:String = null;
|
||||||
var name = null;
|
var ct = parseType(); // this is for handling type parameters
|
||||||
|
switch(ct) {
|
||||||
switch (tk) {
|
case CTPath(path, params):
|
||||||
case TId(id): name = id;
|
name = path.join(".");
|
||||||
default: push(tk);
|
default:
|
||||||
|
error(EUnexpected(Std.string(ct)), p1, tokenMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
var extend:String = null;
|
var extend:String = null;
|
||||||
var interfaces:Array<String> = [];
|
if(maybe(TId("extends"))) {
|
||||||
// optional - example: extends BaseClass
|
var e = parseType();
|
||||||
|
switch(e) {
|
||||||
while( true ) {
|
case CTPath(path, params):
|
||||||
var t = token();
|
var buf = new StringBuf();
|
||||||
switch( t ) {
|
for(i in 0...path.length) {
|
||||||
case TId("extends"):
|
if(i > 0) buf.add(".");
|
||||||
var e = parseType();
|
buf.add(path[i]);
|
||||||
switch(e) {
|
|
||||||
case CTPath(path, params):
|
|
||||||
if(extend != null) {
|
|
||||||
error(ECustom('Cannot extend a class twice.'), 0, 0);
|
|
||||||
}
|
|
||||||
extend = path.join(".");
|
|
||||||
default:
|
|
||||||
error(ECustom('${Std.string(e)} is not a valid path.'), 0, 0);
|
|
||||||
}
|
}
|
||||||
|
extend = buf.toString();
|
||||||
default:
|
default:
|
||||||
push(t);
|
error(ECustom('${Std.string(e)} is not a valid path.'), p1, tokenMax);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*while(true) {
|
var interfaces:Array<String> = [];
|
||||||
tk = token();
|
var tk:Token = null;
|
||||||
trace(tk);
|
if(maybe(TId("implements"))) {
|
||||||
switch (tk) {
|
// handled manually for multiple implements
|
||||||
case TId(id):
|
while(true) {
|
||||||
if (id == "extends") {
|
tk = token();
|
||||||
tk = token();
|
switch(tk) {
|
||||||
if(extend != null) {
|
case TId("implements"): continue;
|
||||||
unexpected(tk);
|
case TId("extends"):
|
||||||
} else {
|
error(ECustom('Implements must come after extends.'), p1, tokenMax);
|
||||||
switch (tk) {
|
case TId(_):
|
||||||
case TId(id): extend = id;
|
push(tk);
|
||||||
default: unexpected(tk);
|
var e = parseType();
|
||||||
}
|
switch(e) {
|
||||||
|
case CTPath(path, params):
|
||||||
|
var buf = new StringBuf();
|
||||||
|
for(i in 0...path.length) {
|
||||||
|
if(i > 0) buf.add(".");
|
||||||
|
buf.add(path[i]);
|
||||||
|
}
|
||||||
|
interfaces.push(buf.toString());
|
||||||
|
default:
|
||||||
|
error(ECustom('${Std.string(e)} is not a valid path.'), p1, tokenMax);
|
||||||
}
|
}
|
||||||
} else if (id == "implements") {
|
default:
|
||||||
tk = token();
|
push(tk);
|
||||||
switch (tk) {
|
break;
|
||||||
case TId(id): interfaces.push(id);
|
}
|
||||||
default: unexpected(tk);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//push(tk);
|
|
||||||
}
|
|
||||||
|
|
||||||
case TBrOpen:
|
|
||||||
push(tk);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
//push(tk);
|
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
var fields = [];
|
var fields = [];
|
||||||
ensure(TBrOpen);
|
ensure(TBrOpen);
|
||||||
@@ -1122,39 +1118,64 @@ class Parser {
|
|||||||
push(tk);
|
push(tk);
|
||||||
mk(EClass(name, fields, extend, interfaces, nextIsFinal, nextIsPrivate), p1);
|
mk(EClass(name, fields, extend, interfaces, nextIsFinal, nextIsPrivate), p1);
|
||||||
|
|
||||||
case "enum": // TODO: enum abstract
|
case "enum":
|
||||||
|
var isAbstract = maybe(TId("abstract"));
|
||||||
var name = getIdent();
|
var name = getIdent();
|
||||||
|
var underlyingType:CType = null;
|
||||||
|
|
||||||
|
if(isAbstract) {
|
||||||
|
ensure(TPOpen);
|
||||||
|
if(allowTypes) {
|
||||||
|
underlyingType = parseType();
|
||||||
|
ensure(TPClose);
|
||||||
|
} else {
|
||||||
|
var t = token();
|
||||||
|
while(t != TPClose && t != TEof) {
|
||||||
|
t = token();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ensure(TBrOpen);
|
ensure(TBrOpen);
|
||||||
|
|
||||||
// TODO: optimize this
|
|
||||||
var fields:Array<EnumField> = [];
|
var fields:Array<EnumField> = [];
|
||||||
var fieldName:String = '';
|
var fieldName:String = '';
|
||||||
var enumArgs:Array<Argument> = null;
|
var enumArgs:Array<Argument> = null;
|
||||||
//var tk = token();
|
var fieldValue:Expr = null;
|
||||||
|
|
||||||
while(!maybe(TBrClose)) {
|
while(!maybe(TBrClose)) {
|
||||||
var tk = token();
|
var tk = token();
|
||||||
|
|
||||||
switch(tk) {
|
switch(tk) {
|
||||||
//case TBrClose:
|
|
||||||
// break;
|
|
||||||
case TSemicolon | TComma:
|
case TSemicolon | TComma:
|
||||||
if(fieldName.trim().length == 0) continue;
|
if(fieldName.trim().length == 0) continue;
|
||||||
|
|
||||||
fields.push({
|
fields.push({
|
||||||
name: fieldName,
|
name: fieldName,
|
||||||
args: enumArgs == null ? [] : enumArgs
|
args: enumArgs == null ? [] : enumArgs,
|
||||||
|
value: fieldValue
|
||||||
});
|
});
|
||||||
fieldName = '';
|
fieldName = '';
|
||||||
enumArgs = null;
|
enumArgs = null;
|
||||||
|
fieldValue = null;
|
||||||
case TPOpen:
|
case TPOpen:
|
||||||
|
if(isAbstract) {
|
||||||
|
error(ECustom("Enum abstract fields cannot have parameters"), tokenMin, tokenMax);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(enumArgs != null) {
|
if(enumArgs != null) {
|
||||||
error(ECustom("Cannot have multiple argument lists in one enum constructor"), tokenMin, tokenMax);
|
error(ECustom("Cannot have multiple argument lists in one enum constructor"), tokenMin, tokenMax);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
enumArgs = parseFunctionArgs(true);
|
enumArgs = parseFunctionArgs(true);
|
||||||
|
case TOp("="):
|
||||||
|
if(!isAbstract) {
|
||||||
|
error(ECustom("Only enum abstract fields can have values"), tokenMin, tokenMax);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fieldValue = parseExpr();
|
||||||
default:
|
default:
|
||||||
|
if(tk.match(TId("var"))) continue;
|
||||||
if(fieldName.trim().length != 0) {
|
if(fieldName.trim().length != 0) {
|
||||||
error(ECustom("Expected comma or semicolon"), tokenMin, tokenMax);
|
error(ECustom("Expected comma or semicolon"), tokenMin, tokenMax);
|
||||||
break;
|
break;
|
||||||
@@ -1164,7 +1185,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mk(EEnum({ name: name, fields: fields }, false), p1);
|
mk(EEnum({ name: name, fields: fields, underlyingType: underlyingType }, isAbstract), p1);
|
||||||
case "cast":
|
case "cast":
|
||||||
var tk = token();
|
var tk = token();
|
||||||
var e:Expr = null;
|
var e:Expr = null;
|
||||||
@@ -1187,7 +1208,8 @@ class Parser {
|
|||||||
var e = if( tk == TSemicolon ) null else parseExpr();
|
var e = if( tk == TSemicolon ) null else parseExpr();
|
||||||
mk(EReturn(e),p1,if( e == null ) tokenMax else pmax(e));
|
mk(EReturn(e),p1,if( e == null ) tokenMax else pmax(e));
|
||||||
case "new":
|
case "new":
|
||||||
var a = [];
|
// TODO: maybe use CTPath for this
|
||||||
|
var a:Array<String> = [];
|
||||||
var params:Null<Array<CType>> = null;
|
var params:Null<Array<CType>> = null;
|
||||||
a.push(getIdent());
|
a.push(getIdent());
|
||||||
while( true ) {
|
while( true ) {
|
||||||
@@ -1364,7 +1386,7 @@ class Parser {
|
|||||||
push(tk);
|
push(tk);
|
||||||
return e1;
|
return e1;
|
||||||
}
|
}
|
||||||
return parseExprNext(mk(EUnop(op,false,e1),pmin(e1)));
|
return parseExprNext(mk(EUnop(Unop.fromString(op),false,e1),pmin(e1)));
|
||||||
}
|
}
|
||||||
return makeBinop(op,e1,parseExpr());
|
return makeBinop(op,e1,parseExpr());
|
||||||
case TId(op) if( opPriority.exists(op) ):
|
case TId(op) if( opPriority.exists(op) ):
|
||||||
@@ -1396,17 +1418,15 @@ class Parser {
|
|||||||
var done = false;
|
var done = false;
|
||||||
while( !done ) {
|
while( !done ) {
|
||||||
var name = null, opt = false;
|
var name = null, opt = false;
|
||||||
switch( tk ) {
|
if( tk == TQuestion ) {
|
||||||
case TQuestion:
|
opt = true;
|
||||||
opt = true;
|
tk = token();
|
||||||
tk = token();
|
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
case TId(id): name = id;
|
case TId(id):
|
||||||
|
name = id;
|
||||||
default:
|
default:
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
var arg : Argument = { name : name, opt: false, value: null, t: null };
|
var arg : Argument = { name : name, opt: false, value: null, t: null };
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
@@ -1421,13 +1441,12 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tk = token();
|
tk = token();
|
||||||
switch( tk ) {
|
if( tk == TComma ) {
|
||||||
case TComma:
|
tk = token();
|
||||||
tk = token();
|
} else if( tk == TPClose ) {
|
||||||
case TPClose:
|
done = true;
|
||||||
done = true;
|
} else {
|
||||||
default:
|
unexpected(tk);
|
||||||
unexpected(tk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1474,31 +1493,32 @@ class Parser {
|
|||||||
if( op == "<" ) {
|
if( op == "<" ) {
|
||||||
params = [];
|
params = [];
|
||||||
while( true ) {
|
while( true ) {
|
||||||
switch( token() ) {
|
var tt = token();
|
||||||
case TConst(c):
|
switch( tt ) {
|
||||||
params.push(CTExpr(mk(EConst(c))));
|
case TConst(c):
|
||||||
case tk:
|
params.push(CTExpr(mk(EConst(c))));
|
||||||
push(tk);
|
default:
|
||||||
params.push(parseType());
|
push(tt);
|
||||||
}
|
params.push(parseType());
|
||||||
t = token();
|
|
||||||
switch( t ) {
|
|
||||||
case TComma: continue;
|
|
||||||
case TOp(op):
|
|
||||||
if( op == ">" ) break;
|
|
||||||
if( op.charCodeAt(0) == ">".code ) {
|
|
||||||
#if hscriptPos
|
|
||||||
tokens.add({ t : TOp(op.substr(1)), min : tokenMax - op.length - 1, max : tokenMax });
|
|
||||||
#else
|
|
||||||
tokens.add(TOp(op.substr(1)));
|
|
||||||
#end
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
t = token();
|
||||||
|
switch( t ) {
|
||||||
|
case TComma: continue;
|
||||||
|
case TOp(op):
|
||||||
|
if( op == ">" ) break;
|
||||||
|
if( op.charCodeAt(0) == ">".code ) {
|
||||||
|
#if hscriptPos
|
||||||
|
tokens.add({ t : TOp(op.substr(1)), min : tokenMax - op.length - 1, max : tokenMax });
|
||||||
|
#else
|
||||||
|
tokens.add(TOp(op.substr(1)));
|
||||||
|
#end
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
unexpected(t);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
unexpected(t);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
push(t);
|
push(t);
|
||||||
default:
|
default:
|
||||||
@@ -1628,16 +1648,101 @@ class Parser {
|
|||||||
while( true ) {
|
while( true ) {
|
||||||
args.push(parseExpr());
|
args.push(parseExpr());
|
||||||
tk = token();
|
tk = token();
|
||||||
switch( tk ) {
|
if( tk == etk )
|
||||||
case TComma:
|
break;
|
||||||
default:
|
if( tk != TComma )
|
||||||
if( tk == etk ) break;
|
unexpected(tk);
|
||||||
unexpected(tk);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From hscript-iris: https://github.com/pisayesiwsi/hscript-iris/blob/dev/crowplexus/hscript/Parser.hx#L409
|
||||||
|
// by inky03
|
||||||
|
function interpolateString(s:String):Expr {
|
||||||
|
var exprs:Array<Expr> = [];
|
||||||
|
var dollarPos:Int = s.indexOf('$');
|
||||||
|
|
||||||
|
if(dollarPos == -1)
|
||||||
|
return mk(EConst(CString(s)));
|
||||||
|
|
||||||
|
final singleFirst:EReg = ~/[a-zA-Z_]/i;
|
||||||
|
final singleExpr:EReg = ~/[a-zA-Z0-9_]/i;
|
||||||
|
// TODO: optimize this using regex
|
||||||
|
while(dollarPos > -1) {
|
||||||
|
var pos:Int = dollarPos;
|
||||||
|
var pre:String = s.substr(0, pos);
|
||||||
|
var next:String = s.charAt(++pos);
|
||||||
|
if(next == '{') {
|
||||||
|
if (pre != '')
|
||||||
|
exprs.push(mk(EConst(CString(pre))));
|
||||||
|
var exprStr:String = '';
|
||||||
|
var depth:Int = 1;
|
||||||
|
while (true) {
|
||||||
|
next = s.charAt(++pos);
|
||||||
|
if (next == '{') {
|
||||||
|
depth++;
|
||||||
|
} else if (next == '}') {
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
if (depth < 1)
|
||||||
|
break;
|
||||||
|
if (pos >= s.length) {
|
||||||
|
error(EUnterminatedString, pos, pos);
|
||||||
|
}
|
||||||
|
exprStr += next;
|
||||||
|
}
|
||||||
|
if (exprStr.trim() == '') {
|
||||||
|
error(ECustom("Expression cannot be empty"), pos, pos);
|
||||||
|
}
|
||||||
|
var prevChar = char;
|
||||||
|
var prevInput = input;
|
||||||
|
var prevReadPos = readPos; // a bit stupid innit???
|
||||||
|
#if hscriptPos
|
||||||
|
var prevOrigin = origin;
|
||||||
|
#end
|
||||||
|
var expr = parseString('($exprStr)' #if hscriptPos, origin #end);
|
||||||
|
readPos = prevReadPos; // rolling back parser state because otherwise we get problems...
|
||||||
|
input = prevInput;
|
||||||
|
char = prevChar;
|
||||||
|
#if hscriptPos
|
||||||
|
origin = prevOrigin;
|
||||||
|
#end
|
||||||
|
exprs.push(expr);
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
else if(singleFirst.match(next)) {
|
||||||
|
if (pre != '')
|
||||||
|
exprs.push(mk(EConst(CString(pre))));
|
||||||
|
var ident: String = '';
|
||||||
|
while(singleExpr.match(next)) {
|
||||||
|
ident += next;
|
||||||
|
next = s.charAt(++pos);
|
||||||
|
}
|
||||||
|
exprs.push(mk(EIdent(ident)));
|
||||||
|
}
|
||||||
|
else if (next == '$') {
|
||||||
|
var secondToNext: String = s.charAt(pos);
|
||||||
|
if (secondToNext == "$") { // if its another dollar, skip...
|
||||||
|
s = pre + s.substr(pos, pos + 1); // remove $ ahead of the current one
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exprs.push(mk(EConst(CString(pre + '$'))));
|
||||||
|
}
|
||||||
|
s = s.substr(pos++);
|
||||||
|
dollarPos = s.indexOf('$');
|
||||||
|
}
|
||||||
|
if (exprs.length == 0) {
|
||||||
|
return mk(EConst(CString(s)));
|
||||||
|
} else {
|
||||||
|
exprs.push(mk(EConst(CString(s))));
|
||||||
|
var expr:Null<Expr> = exprs.shift();
|
||||||
|
while(true) {
|
||||||
|
if(exprs.length == 0) break;
|
||||||
|
expr = mk(EBinop(OpAdd, expr, exprs.shift()));
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function checkAccess(get:FieldPropertyAccess, set:FieldPropertyAccess, ?expr:Expr, ?type:CType) {
|
function checkAccess(get:FieldPropertyAccess, set:FieldPropertyAccess, ?expr:Expr, ?type:CType) {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
@@ -1873,8 +1978,9 @@ class Parser {
|
|||||||
return StringTools.fastCodeAt(input, readPos++);
|
return StringTools.fastCodeAt(input, readPos++);
|
||||||
}
|
}
|
||||||
|
|
||||||
function readString( until:Int, regex:Bool = false ):String {
|
function readString( until:Int, regex:Bool = false, interpolate:Bool = false ):String {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
|
var prev = 0;
|
||||||
var b = new StringBuf();
|
var b = new StringBuf();
|
||||||
var esc = false;
|
var esc = false;
|
||||||
var old = line;
|
var old = line;
|
||||||
@@ -1923,11 +2029,53 @@ class Parser {
|
|||||||
}
|
}
|
||||||
} else if( c == 92 && !regex)
|
} else if( c == 92 && !regex)
|
||||||
esc = true;
|
esc = true;
|
||||||
else if( c == until )
|
else if( c == until ) {
|
||||||
break;
|
if(regex && prev == 92) {
|
||||||
|
b.addChar(c);
|
||||||
|
prev = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (c == 36 && interpolate) { // brace for impact !!
|
||||||
|
// From hscript-iris: https://github.com/pisayesiwsi/hscript-iris/blob/dev/crowplexus/hscript/Parser.hx#L1665
|
||||||
|
// by inky03
|
||||||
|
// TODO: optimize this
|
||||||
|
b.addChar(c);
|
||||||
|
var next = readChar();
|
||||||
|
if (next == 123) {
|
||||||
|
b.addChar(next);
|
||||||
|
var depth:Int = 0;
|
||||||
|
while (true) {
|
||||||
|
next = readChar();
|
||||||
|
if (StringTools.isEof(next)) {
|
||||||
|
error(EUnterminatedString, p1, p1);
|
||||||
|
}
|
||||||
|
b.addChar(next);
|
||||||
|
if (next == "'".code) {
|
||||||
|
var nextStr:String = readString("'".code, false, true);
|
||||||
|
for (char in nextStr) {
|
||||||
|
b.addChar(char);
|
||||||
|
}
|
||||||
|
b.addChar("'".code);
|
||||||
|
next = readChar();
|
||||||
|
b.addChar(next);
|
||||||
|
}
|
||||||
|
if (next == 125) {
|
||||||
|
depth--;
|
||||||
|
if (depth < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
readPos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if( c == 10 ) line++;
|
if( c == 10 ) line++;
|
||||||
b.addChar(c);
|
b.addChar(c);
|
||||||
|
if(regex)
|
||||||
|
prev = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return b.toString();
|
return b.toString();
|
||||||
@@ -2028,7 +2176,9 @@ class Parser {
|
|||||||
switch( char ) {
|
switch( char ) {
|
||||||
case 48,49,50,51,52,53,54,55,56,57:
|
case 48,49,50,51,52,53,54,55,56,57:
|
||||||
n = n * 10 + (char - 48);
|
n = n * 10 + (char - 48);
|
||||||
|
continue;
|
||||||
case '_'.code:
|
case '_'.code:
|
||||||
|
continue;
|
||||||
case "e".code, "E".code:
|
case "e".code, "E".code:
|
||||||
var tk = token();
|
var tk = token();
|
||||||
var pow : Null<Int> = null;
|
var pow : Null<Int> = null;
|
||||||
@@ -2057,46 +2207,48 @@ class Parser {
|
|||||||
invalidChar(char);
|
invalidChar(char);
|
||||||
}
|
}
|
||||||
exp = 1.;
|
exp = 1.;
|
||||||
|
continue;
|
||||||
case "x".code:
|
case "x".code:
|
||||||
if( n > 0 || exp > 0 )
|
if( n > 0 || exp > 0 )
|
||||||
invalidChar(char);
|
invalidChar(char);
|
||||||
// read hexa
|
// read hexa
|
||||||
var n = 0;
|
var hex = 0;
|
||||||
while( true ) {
|
while( true ) {
|
||||||
char = readChar();
|
char = readChar();
|
||||||
switch( char ) {
|
if( char >= 48 && char <= 57 ) {
|
||||||
case 48,49,50,51,52,53,54,55,56,57: // 0-9
|
hex = (hex << 4) + char - 48;
|
||||||
n = (n << 4) + char - 48;
|
continue;
|
||||||
case 65,66,67,68,69,70: // A-F
|
} else if( char >= 65 && char <= 70 ) {
|
||||||
n = (n << 4) + (char - 55);
|
hex = (hex << 4) + char - 55;
|
||||||
case 97,98,99,100,101,102: // a-f
|
continue;
|
||||||
n = (n << 4) + (char - 87);
|
} else if( char >= 97 && char <= 102 ) {
|
||||||
case '_'.code:
|
hex = (hex << 4) + char - 87;
|
||||||
default:
|
continue;
|
||||||
this.char = char;
|
} else if( char == '_'.code ) {
|
||||||
return TConst(CInt(n));
|
continue;
|
||||||
}
|
}
|
||||||
|
this.char = char;
|
||||||
|
return TConst(CInt(hex));
|
||||||
}
|
}
|
||||||
case "b".code: // Custom thing, not supported in haxe
|
case "b".code: // Custom thing, not supported in haxe
|
||||||
if( n > 0 || exp > 0 )
|
if( n > 0 || exp > 0 )
|
||||||
invalidChar(char);
|
invalidChar(char);
|
||||||
// read binary
|
// read binary
|
||||||
var n = 0;
|
var bin = 0;
|
||||||
while( true ) {
|
while( true ) {
|
||||||
char = readChar();
|
char = readChar();
|
||||||
switch( char ) {
|
if( char == 48 || char == 49 ) {
|
||||||
case 48,49: // 0-1
|
bin = (bin << 1) + char - 48;
|
||||||
n = (n << 1) + char - 48;
|
continue;
|
||||||
case '_'.code:
|
} else if( char == '_'.code ) {
|
||||||
default:
|
continue;
|
||||||
this.char = char;
|
|
||||||
return TConst(CInt(n));
|
|
||||||
}
|
}
|
||||||
|
this.char = char;
|
||||||
|
return TConst(CInt(bin));
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
this.char = char;
|
this.char = char;
|
||||||
var i = Std.int(n);
|
return TConst( (exp > 0) ? CFloat(n * 10 / exp) : ((n % 1 == 0) ? CInt(Std.int(n)) : CFloat(n)) );
|
||||||
return TConst( (exp > 0) ? CFloat(n * 10 / exp) : ((i == n) ? CInt(i) : CFloat(n)) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ";".code: return TSemicolon;
|
case ";".code: return TSemicolon;
|
||||||
@@ -2133,7 +2285,10 @@ class Parser {
|
|||||||
case "}".code: return TBrClose;
|
case "}".code: return TBrClose;
|
||||||
case "[".code: return TBkOpen;
|
case "[".code: return TBkOpen;
|
||||||
case "]".code: return TBkClose;
|
case "]".code: return TBkClose;
|
||||||
case "'".code, '"'.code: return TConst( CString(readString(char)) );
|
case "'".code:
|
||||||
|
return TConst( CString(readString(char, false, true), true) );
|
||||||
|
case '"'.code:
|
||||||
|
return TConst( CString(readString(char), false) );
|
||||||
case "?".code:
|
case "?".code:
|
||||||
char = readChar();
|
char = readChar();
|
||||||
switch (char) {
|
switch (char) {
|
||||||
@@ -2189,17 +2344,19 @@ class Parser {
|
|||||||
invalidChar(char);
|
invalidChar(char);
|
||||||
default:
|
default:
|
||||||
if( ops[char] ) {
|
if( ops[char] ) {
|
||||||
var op:String = String.fromCharCode(char);
|
var buf = new StringBuf();
|
||||||
|
buf.addChar(char);
|
||||||
while( true ) {
|
while( true ) {
|
||||||
char = readChar();
|
char = readChar();
|
||||||
if( StringTools.isEof(char) ) char = 0;
|
if( StringTools.isEof(char) ) char = 0;
|
||||||
if( !ops[char] ) {
|
if( !ops[char] ) {
|
||||||
this.char = char;
|
this.char = char;
|
||||||
return TOp(op);
|
return TOp(buf.toString());
|
||||||
}
|
}
|
||||||
var pop = op;
|
var pop = buf.toString();
|
||||||
op += String.fromCharCode(char);
|
buf.addChar(char);
|
||||||
if( allowRegex && op == "~/") {
|
var op = buf.toString();
|
||||||
|
if( allowRegex && op == "~/" ) {
|
||||||
var e = readString(char, true);
|
var e = readString(char, true);
|
||||||
var f = readFlags();
|
var f = readFlags();
|
||||||
return TRegex(e, f);
|
return TRegex(e, f);
|
||||||
@@ -2213,16 +2370,17 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( idents[char] ) {
|
if( idents[char] ) {
|
||||||
var id = String.fromCharCode(char);
|
var buf = new StringBuf();
|
||||||
|
buf.addChar(char);
|
||||||
while( true ) {
|
while( true ) {
|
||||||
char = readChar();
|
char = readChar();
|
||||||
if( StringTools.isEof(char) ) char = 0;
|
if( StringTools.isEof(char) ) char = 0;
|
||||||
if( !idents[char] ) {
|
if( !idents[char] ) {
|
||||||
this.char = char;
|
this.char = char;
|
||||||
//if(id == "is") return TOp("is");
|
//if(id == "is") return TOp("is");
|
||||||
return TId(id);
|
return TId(buf.toString());
|
||||||
}
|
}
|
||||||
id += String.fromCharCode(char);
|
buf.addChar(char);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
invalidChar(char);
|
invalidChar(char);
|
||||||
@@ -2245,14 +2403,16 @@ class Parser {
|
|||||||
push(TPOpen);
|
push(TPOpen);
|
||||||
parseExpr();
|
parseExpr();
|
||||||
case TId(id):
|
case TId(id):
|
||||||
|
var buf = new StringBuf();
|
||||||
|
buf.add(id);
|
||||||
while(true) {
|
while(true) {
|
||||||
var tk = token();
|
var tk = token();
|
||||||
if(tk == TDot) {
|
if(tk == TDot) {
|
||||||
id += ".";
|
buf.add(".");
|
||||||
tk = token();
|
tk = token();
|
||||||
switch(tk) {
|
switch(tk) {
|
||||||
case TId(id2):
|
case TId(id2):
|
||||||
id += id2;
|
buf.add(id2);
|
||||||
default: unexpected(tk);
|
default: unexpected(tk);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -2260,9 +2420,9 @@ class Parser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mk(EIdent(id), tokenMin, tokenMax);
|
mk(EIdent(buf.toString()), tokenMin, tokenMax);
|
||||||
case TOp("!"):
|
case TOp("!"):
|
||||||
mk(EUnop("!", true, parsePreproCond()), tokenMin, tokenMax);
|
mk(EUnop(OpNot, true, parsePreproCond()), tokenMin, tokenMax);
|
||||||
default:
|
default:
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
}
|
}
|
||||||
@@ -2280,13 +2440,13 @@ class Parser {
|
|||||||
error(EInvalidPreprocessor("Can't eval " + expr(e).getName() + " with " + expr(e2).getName()), readPos, readPos);
|
error(EInvalidPreprocessor("Can't eval " + expr(e).getName() + " with " + expr(e2).getName()), readPos, readPos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case EUnop("!", _, e):
|
case EUnop(OpNot, _, e):
|
||||||
return !evalPreproCond(e);
|
return !evalPreproCond(e);
|
||||||
case EParent(e):
|
case EParent(e):
|
||||||
return evalPreproCond(e);
|
return evalPreproCond(e);
|
||||||
case EBinop("&&", e1, e2):
|
case EBinop(OpBoolAnd, e1, e2):
|
||||||
return evalPreproCond(e1) && evalPreproCond(e2);
|
return evalPreproCond(e1) && evalPreproCond(e2);
|
||||||
case EBinop("||", e1, e2):
|
case EBinop(OpBoolOr, e1, e2):
|
||||||
return evalPreproCond(e1) || evalPreproCond(e2);
|
return evalPreproCond(e1) || evalPreproCond(e2);
|
||||||
default:
|
default:
|
||||||
error(EInvalidPreprocessor("Can't eval " + expr(e).getName()), readPos, readPos);
|
error(EInvalidPreprocessor("Can't eval " + expr(e).getName()), readPos, readPos);
|
||||||
@@ -2394,7 +2554,7 @@ class Parser {
|
|||||||
return switch(c) {
|
return switch(c) {
|
||||||
case CInt(v): Std.string(v);
|
case CInt(v): Std.string(v);
|
||||||
case CFloat(f): Std.string(f);
|
case CFloat(f): Std.string(f);
|
||||||
case CString(s): s; // TODO : escape + quote
|
case CString(s, _): s; // TODO : escape + quote
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2418,7 +2578,7 @@ class Parser {
|
|||||||
case TDoubleDot: ":";
|
case TDoubleDot: ":";
|
||||||
case TMeta(id): "@" + id;
|
case TMeta(id): "@" + id;
|
||||||
case TPrepro(id): "#" + id;
|
case TPrepro(id): "#" + id;
|
||||||
case TRegex(e, f): '~/$e/${f == null ? '' : f}';
|
case TRegex(e, f): '~/$e/$f';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+494
-470
@@ -1,470 +1,494 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C)2008-2017 Haxe Foundation
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
* to deal in the Software without restriction, including without limitation
|
* to deal in the Software without restriction, including without limitation
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
import hscript.Expr;
|
import hscript.Expr;
|
||||||
|
|
||||||
class Printer {
|
class Printer {
|
||||||
|
|
||||||
var buf : StringBuf;
|
var buf : StringBuf;
|
||||||
var tabs : String;
|
var tabs : String;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exprToString( e : Expr ):String {
|
public function exprToString( e : Expr ):String {
|
||||||
buf = new StringBuf();
|
buf = new StringBuf();
|
||||||
tabs = "";
|
tabs = "";
|
||||||
expr(e);
|
expr(e);
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function typeToString( t : CType ):String {
|
public function typeToString( t : CType ):String {
|
||||||
buf = new StringBuf();
|
buf = new StringBuf();
|
||||||
tabs = "";
|
tabs = "";
|
||||||
type(t);
|
type(t);
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function add<T>(s:T):Void buf.add(s);
|
inline function add<T>(s:T):Void buf.add(s);
|
||||||
|
|
||||||
function type( t : CType ):Void {
|
function type( t : CType ):Void {
|
||||||
switch( t ) {
|
switch( t ) {
|
||||||
case CTOpt(t):
|
case CTOpt(t):
|
||||||
add('?');
|
add('?');
|
||||||
type(t);
|
type(t);
|
||||||
case CTPath(path, params):
|
case CTPath(path, params):
|
||||||
add(path.join("."));
|
add(path.join("."));
|
||||||
if( params != null ) {
|
if( params != null ) {
|
||||||
add("<");
|
add("<");
|
||||||
var first = true;
|
var first = true;
|
||||||
for( p in params ) {
|
for( p in params ) {
|
||||||
if( first ) first = false else add(", ");
|
if( first ) first = false else add(", ");
|
||||||
type(p);
|
type(p);
|
||||||
}
|
}
|
||||||
add(">");
|
add(">");
|
||||||
}
|
}
|
||||||
case CTNamed(name, t):
|
case CTNamed(name, t):
|
||||||
add(name);
|
add(name);
|
||||||
add(':');
|
add(':');
|
||||||
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('(');
|
||||||
for (a in args)
|
for (a in args)
|
||||||
switch a {
|
switch a {
|
||||||
case CTNamed(_, _): type(a);
|
case CTNamed(_, _): type(a);
|
||||||
default: type(CTNamed('_', a));
|
default: type(CTNamed('_', a));
|
||||||
}
|
}
|
||||||
add(')->');
|
add(')->');
|
||||||
type(ret);
|
type(ret);
|
||||||
case CTFun(args, ret):
|
case CTFun(args, ret):
|
||||||
if( args.length == 0 )
|
if( args.length == 0 )
|
||||||
add("Void -> ");
|
add("Void -> ");
|
||||||
else {
|
else {
|
||||||
for( a in args ) {
|
for( a in args ) {
|
||||||
type(a);
|
type(a);
|
||||||
add(" -> ");
|
add(" -> ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type(ret);
|
type(ret);
|
||||||
case CTAnon(fields):
|
case CTAnon(fields):
|
||||||
add("{");
|
add("{");
|
||||||
var first = true;
|
var first = true;
|
||||||
for( f in fields ) {
|
for( f in fields ) {
|
||||||
if( first ) { first = false; add(" "); } else add(", ");
|
if( first ) { first = false; add(" "); } else add(", ");
|
||||||
add(f.name + " : ");
|
add(f.name + " : ");
|
||||||
type(f.t);
|
type(f.t);
|
||||||
}
|
}
|
||||||
add(first ? "}" : " }");
|
add(first ? "}" : " }");
|
||||||
case CTParent(t):
|
case CTParent(t):
|
||||||
add("(");
|
add("(");
|
||||||
type(t);
|
type(t);
|
||||||
add(")");
|
add(")");
|
||||||
case CTExpr(e):
|
case CTExpr(e):
|
||||||
expr(e);
|
expr(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addType( t : CType ):Void {
|
function addType( t : CType ):Void {
|
||||||
if( t != null ) {
|
if( t != null ) {
|
||||||
add(" : ");
|
add(" : ");
|
||||||
type(t);
|
type(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function expr( e : Expr ):Void {
|
function expr( e : Expr ):Void {
|
||||||
if( e == null ) {
|
if( e == null ) {
|
||||||
add("??NULL??");
|
add("??NULL??");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch(Tools.expr(e)) {
|
switch(Tools.expr(e)) {
|
||||||
case EPackage(n):
|
case EPackage(n):
|
||||||
add('package');
|
add('package');
|
||||||
if(n != null)
|
if(n != null)
|
||||||
add(' $n');
|
add(' $n');
|
||||||
add(';\n');
|
add(';\n');
|
||||||
case EImport(c, n, u):
|
case EImport(c, n, u):
|
||||||
add('${u ? 'using' : 'import'} $c');
|
add('${u ? 'using' : 'import'} $c');
|
||||||
if(n != null)
|
if(n != null)
|
||||||
add(' as $n');
|
add(' as $n');
|
||||||
case EClass(name, fields, extend, interfaces, fnal):
|
case EClass(name, fields, extend, interfaces, fnal):
|
||||||
var isFinal = fnal != null && fnal;
|
var isFinal = fnal != null && fnal;
|
||||||
if(isFinal)
|
if(isFinal)
|
||||||
add('final ');
|
add('final ');
|
||||||
add('class $name');
|
add('class $name');
|
||||||
if (extend != null)
|
if (extend != null)
|
||||||
add(' extends $extend');
|
add(' extends $extend');
|
||||||
for(_interface in interfaces) {
|
for(_interface in interfaces) {
|
||||||
add(' implements $_interface');
|
add(' implements $_interface');
|
||||||
}
|
}
|
||||||
tabs += "\t";
|
tabs += "\t";
|
||||||
add(" {\n");
|
add(" {\n");
|
||||||
for( e in fields ) {
|
for( e in fields ) {
|
||||||
add(tabs);
|
add(tabs);
|
||||||
expr(e);
|
expr(e);
|
||||||
//add(";\n");
|
//add(";\n");
|
||||||
}
|
}
|
||||||
//for(field in fields) {
|
//for(field in fields) {
|
||||||
// expr(field);
|
// expr(field);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
tabs = tabs.substr(1);
|
tabs = tabs.substr(1);
|
||||||
add("}");
|
add("}");
|
||||||
case EEnum(en, _): // TODO: enum abstracts
|
case EEnum(en, isAbstract):
|
||||||
add('enum ${en.name}');
|
if(isAbstract) {
|
||||||
if(en.fields.length == 0) {
|
add('enum abstract ${en.name}(');
|
||||||
add(' {}');
|
if(en.underlyingType != null)
|
||||||
return;
|
type(en.underlyingType);
|
||||||
}
|
else
|
||||||
tabs += "\t";
|
add('Int');
|
||||||
add(" {\n");
|
add(')');
|
||||||
|
if(en.fields.length == 0) {
|
||||||
for(e in en.fields) {
|
add(' {}');
|
||||||
add(tabs);
|
return;
|
||||||
add(e.name);
|
}
|
||||||
if(e.args.length > 0) {
|
tabs += "\t";
|
||||||
add("(");
|
add(" {\n");
|
||||||
var first = true;
|
for(e in en.fields) {
|
||||||
for( a in e.args ) {
|
add(tabs);
|
||||||
if( first ) first = false else add(", ");
|
add(e.name);
|
||||||
if( a.opt ) add("?");
|
if(e.value != null) {
|
||||||
add(a.name);
|
add(" = ");
|
||||||
addType(a.t);
|
expr(e.value);
|
||||||
}
|
}
|
||||||
add(')');
|
add(";\n");
|
||||||
}
|
}
|
||||||
add(";\n");
|
tabs = tabs.substr(1);
|
||||||
}
|
add("}");
|
||||||
|
} else {
|
||||||
tabs = tabs.substr(1);
|
add('enum ${en.name}');
|
||||||
add("}");
|
if(en.fields.length == 0) {
|
||||||
case ECast(e, t):
|
add(' {}');
|
||||||
var safe = t != null;
|
return;
|
||||||
add("cast ");
|
}
|
||||||
if(safe) add("(");
|
tabs += "\t";
|
||||||
expr(e);
|
add(" {\n");
|
||||||
if(safe) {
|
for(e in en.fields) {
|
||||||
add(", ");
|
add(tabs);
|
||||||
addType(t);
|
add(e.name);
|
||||||
add(")");
|
if(e.args.length > 0) {
|
||||||
}
|
add("(");
|
||||||
case ERegex(e, f):
|
var first = true;
|
||||||
add('~/$e/$f');
|
for( a in e.args ) {
|
||||||
add(';\n');
|
if( first ) first = false else add(", ");
|
||||||
case EConst(c):
|
if( a.opt ) add("?");
|
||||||
switch( c ) {
|
add(a.name);
|
||||||
case CInt(i): add(i);
|
addType(a.t);
|
||||||
case CFloat(f): add(f);
|
}
|
||||||
case CString(s): add('"'); add(s.split('"').join('\\"').split("\n").join("\\n").split("\r").join("\\r").split("\t").join("\\t")); add('"');
|
add(')');
|
||||||
}
|
}
|
||||||
case EIdent(v):
|
add(";\n");
|
||||||
add(v);
|
}
|
||||||
case EVar(n, t, e, p, s, pr, isFinal, isInline, get, set, _):
|
tabs = tabs.substr(1);
|
||||||
if(p) add("public ");
|
add("}");
|
||||||
else if(pr) add("private ");
|
}
|
||||||
if(s) add("static ");
|
case ECast(e, t):
|
||||||
if(isInline) add("inline ");
|
var safe = t != null;
|
||||||
if(isFinal) add("final " + n);
|
add("cast ");
|
||||||
else add("var " + n);
|
if(safe) add("(");
|
||||||
|
expr(e);
|
||||||
if(get != null || set != null) {
|
if(safe) {
|
||||||
add("(");
|
add(", ");
|
||||||
switch(get) {
|
addType(t);
|
||||||
case ADefault: add("default, ");
|
add(")");
|
||||||
case ANull: add("null, ");
|
}
|
||||||
case AGet: add("get, ");
|
case ERegex(e, f):
|
||||||
case ADynamic: add("dynamic, ");
|
add('~/$e/$f');
|
||||||
case ANever: add("never, ");
|
add(';\n');
|
||||||
default:
|
case EConst(c):
|
||||||
}
|
switch( c ) {
|
||||||
switch(set) {
|
case CInt(i): add(i);
|
||||||
case ADefault: add("default");
|
case CFloat(f): add(f);
|
||||||
case ANull: add("null");
|
case CString(s): add('"'); add(s.split('"').join('\\"').split("\n").join("\\n").split("\r").join("\\r").split("\t").join("\\t")); add('"');
|
||||||
case ASet: add("set");
|
}
|
||||||
case ADynamic: add("dynamic");
|
case EIdent(v):
|
||||||
case ANever: add("never");
|
add(v);
|
||||||
default:
|
case EVar(n, t, e, p, s, pr, isFinal, isInline, get, set, _):
|
||||||
}
|
if(p) add("public ");
|
||||||
add(")");
|
else if(pr) add("private ");
|
||||||
}
|
if(s) add("static ");
|
||||||
|
if(isInline) add("inline ");
|
||||||
addType(t);
|
if(isFinal) add("final " + n);
|
||||||
if( e != null ) {
|
else add("var " + n);
|
||||||
add(" = ");
|
|
||||||
expr(e);
|
if(get != null || set != null) {
|
||||||
}
|
add("(");
|
||||||
case EParent(e):
|
switch(get) {
|
||||||
add("("); expr(e); add(")");
|
case ADefault: add("default, ");
|
||||||
case EBlock(el):
|
case ANull: add("null, ");
|
||||||
if( el.length == 0 ) {
|
case AGet: add("get, ");
|
||||||
add("{}");
|
case ADynamic: add("dynamic, ");
|
||||||
} else {
|
case ANever: add("never, ");
|
||||||
tabs += "\t";
|
default:
|
||||||
add("{\n");
|
}
|
||||||
for( e in el ) {
|
switch(set) {
|
||||||
add(tabs);
|
case ADefault: add("default");
|
||||||
expr(e);
|
case ANull: add("null");
|
||||||
add(";\n");
|
case ASet: add("set");
|
||||||
}
|
case ADynamic: add("dynamic");
|
||||||
tabs = tabs.substr(1);
|
case ANever: add("never");
|
||||||
add("}");
|
default:
|
||||||
}
|
}
|
||||||
case EField(e, f, s):
|
add(")");
|
||||||
expr(e);
|
}
|
||||||
add((s == true ? "?." : ".") + f);
|
|
||||||
case EBinop(op, e1, e2):
|
addType(t);
|
||||||
expr(e1);
|
if( e != null ) {
|
||||||
add(" " + op + " ");
|
add(" = ");
|
||||||
expr(e2);
|
expr(e);
|
||||||
case EUnop(op, pre, e):
|
}
|
||||||
if( pre ) {
|
case EParent(e):
|
||||||
add(op);
|
add("("); expr(e); add(")");
|
||||||
expr(e);
|
case EBlock(el):
|
||||||
} else {
|
if( el.length == 0 ) {
|
||||||
expr(e);
|
add("{}");
|
||||||
add(op);
|
} else {
|
||||||
}
|
tabs += "\t";
|
||||||
case ECall(e, args):
|
add("{\n");
|
||||||
if( e == null )
|
for( e in el ) {
|
||||||
expr(e);
|
add(tabs);
|
||||||
else switch( Tools.expr(e)) {
|
expr(e);
|
||||||
case EField(_), EIdent(_), EConst(_):
|
add(";\n");
|
||||||
expr(e);
|
}
|
||||||
default:
|
tabs = tabs.substr(1);
|
||||||
add("(");
|
add("}");
|
||||||
expr(e);
|
}
|
||||||
add(")");
|
case EField(e, f, s):
|
||||||
}
|
expr(e);
|
||||||
add("(");
|
add((s == true ? "?." : ".") + f);
|
||||||
var first = true;
|
case EBinop(op, e1, e2):
|
||||||
for( a in args ) {
|
expr(e1);
|
||||||
if( first ) first = false else add(", ");
|
add(" " + op.toString() + " ");
|
||||||
expr(a);
|
expr(e2);
|
||||||
}
|
case EUnop(op, pre, e):
|
||||||
add(")");
|
if( pre ) {
|
||||||
case EIf(cond,e1,e2):
|
add(op);
|
||||||
add("if( ");
|
expr(e);
|
||||||
expr(cond);
|
} else {
|
||||||
add(" ) ");
|
expr(e);
|
||||||
expr(e1);
|
add(op);
|
||||||
if( e2 != null ) {
|
}
|
||||||
add(" else ");
|
case ECall(e, args):
|
||||||
expr(e2);
|
if( e == null )
|
||||||
}
|
expr(e);
|
||||||
case EWhile(cond,e):
|
else switch( Tools.expr(e)) {
|
||||||
add("while( ");
|
case EField(_), EIdent(_), EConst(_):
|
||||||
expr(cond);
|
expr(e);
|
||||||
add(" ) ");
|
default:
|
||||||
expr(e);
|
add("(");
|
||||||
case EDoWhile(cond,e):
|
expr(e);
|
||||||
add("do ");
|
add(")");
|
||||||
expr(e);
|
}
|
||||||
add(" while ( ");
|
add("(");
|
||||||
expr(cond);
|
var first = true;
|
||||||
add(" )");
|
for( a in args ) {
|
||||||
case EFor(v, it, e, ithv):
|
if( first ) first = false else add(", ");
|
||||||
if(ithv != null)
|
expr(a);
|
||||||
add("for( "+ithv+" => "+v+" in ");
|
}
|
||||||
else
|
add(")");
|
||||||
add("for( "+v+" in ");
|
case EIf(cond,e1,e2):
|
||||||
expr(it);
|
add("if( ");
|
||||||
add(" ) ");
|
expr(cond);
|
||||||
expr(e);
|
add(" ) ");
|
||||||
case EBreak:
|
expr(e1);
|
||||||
add("break");
|
if( e2 != null ) {
|
||||||
case EContinue:
|
add(" else ");
|
||||||
add("continue");
|
expr(e2);
|
||||||
case EFunction(params, e, name, ret): // TODO: static, public, override
|
}
|
||||||
add("function");
|
case EWhile(cond,e):
|
||||||
if( name != null )
|
add("while( ");
|
||||||
add(" " + name);
|
expr(cond);
|
||||||
add("(");
|
add(" ) ");
|
||||||
var first = true;
|
expr(e);
|
||||||
for( a in params ) {
|
case EDoWhile(cond,e):
|
||||||
if( first ) first = false else add(", ");
|
add("do ");
|
||||||
if( a.opt ) add("?");
|
expr(e);
|
||||||
add(a.name);
|
add(" while ( ");
|
||||||
addType(a.t);
|
expr(cond);
|
||||||
}
|
add(" )");
|
||||||
add(")");
|
case EFor(v, it, e, ithv):
|
||||||
addType(ret);
|
if(ithv != null)
|
||||||
add(" ");
|
add("for( "+ithv+" => "+v+" in ");
|
||||||
expr(e);
|
else
|
||||||
case EReturn(e):
|
add("for( "+v+" in ");
|
||||||
add("return");
|
expr(it);
|
||||||
if( e != null ) {
|
add(" ) ");
|
||||||
add(" ");
|
expr(e);
|
||||||
expr(e);
|
case EBreak:
|
||||||
}
|
add("break");
|
||||||
case EArray(e,index):
|
case EContinue:
|
||||||
expr(e);
|
add("continue");
|
||||||
add("[");
|
case EFunction(params, e, name, ret): // TODO: static, public, override
|
||||||
expr(index);
|
add("function");
|
||||||
add("]");
|
if( name != null )
|
||||||
case EArrayDecl(el, _):
|
add(" " + name);
|
||||||
add("[");
|
add("(");
|
||||||
var first = true;
|
var first = true;
|
||||||
for( e in el ) {
|
for( a in params ) {
|
||||||
if( first ) first = false else add(", ");
|
if( first ) first = false else add(", ");
|
||||||
expr(e);
|
if( a.opt ) add("?");
|
||||||
}
|
add(a.name);
|
||||||
add("]");
|
addType(a.t);
|
||||||
case ENew(cl, args, params):
|
}
|
||||||
add("new " + cl);
|
add(")");
|
||||||
if(params != null) {
|
addType(ret);
|
||||||
add("<");
|
add(" ");
|
||||||
var first = true;
|
expr(e);
|
||||||
for( p in params ) {
|
case EReturn(e):
|
||||||
if( first ) first = false else add(", ");
|
add("return");
|
||||||
type(p);
|
if( e != null ) {
|
||||||
}
|
add(" ");
|
||||||
add(">");
|
expr(e);
|
||||||
}
|
}
|
||||||
add("(");
|
case EArray(e,index):
|
||||||
var first = true;
|
expr(e);
|
||||||
for( e in args ) {
|
add("[");
|
||||||
if( first ) first = false else add(", ");
|
expr(index);
|
||||||
expr(e);
|
add("]");
|
||||||
}
|
case EArrayDecl(el, _):
|
||||||
add(")");
|
add("[");
|
||||||
case EThrow(e):
|
var first = true;
|
||||||
add("throw ");
|
for( e in el ) {
|
||||||
expr(e);
|
if( first ) first = false else add(", ");
|
||||||
case ETry(e, v, t, ecatch):
|
expr(e);
|
||||||
add("try ");
|
}
|
||||||
expr(e);
|
add("]");
|
||||||
add(" catch( " + v);
|
case ENew(cl, args, params):
|
||||||
addType(t);
|
add("new " + cl);
|
||||||
add(") ");
|
if(params != null) {
|
||||||
expr(ecatch);
|
add("<");
|
||||||
case EObject(fl):
|
var first = true;
|
||||||
if( fl.length == 0 ) {
|
for( p in params ) {
|
||||||
add("{}");
|
if( first ) first = false else add(", ");
|
||||||
} else {
|
type(p);
|
||||||
tabs += "\t";
|
}
|
||||||
add("{\n");
|
add(">");
|
||||||
for( f in fl ) {
|
}
|
||||||
add(tabs);
|
add("(");
|
||||||
add(f.name+" : ");
|
var first = true;
|
||||||
expr(f.e);
|
for( e in args ) {
|
||||||
add(",\n");
|
if( first ) first = false else add(", ");
|
||||||
}
|
expr(e);
|
||||||
tabs = tabs.substr(1);
|
}
|
||||||
add("}");
|
add(")");
|
||||||
}
|
case EThrow(e):
|
||||||
case ETernary(c,e1,e2):
|
add("throw ");
|
||||||
expr(c);
|
expr(e);
|
||||||
add(" ? ");
|
case ETry(e, v, t, ecatch):
|
||||||
expr(e1);
|
add("try ");
|
||||||
add(" : ");
|
expr(e);
|
||||||
expr(e2);
|
add(" catch( " + v);
|
||||||
case ESwitch(e, cases, def):
|
addType(t);
|
||||||
add("switch( ");
|
add(") ");
|
||||||
expr(e);
|
expr(ecatch);
|
||||||
add(") {");
|
case EObject(fl):
|
||||||
for( c in cases ) {
|
if( fl.length == 0 ) {
|
||||||
add("case ");
|
add("{}");
|
||||||
var first = true;
|
} else {
|
||||||
for( v in c.values ) {
|
tabs += "\t";
|
||||||
if( first ) first = false else add(", ");
|
add("{\n");
|
||||||
expr(v);
|
for( f in fl ) {
|
||||||
}
|
add(tabs);
|
||||||
add(": ");
|
add(f.name+" : ");
|
||||||
expr(c.expr);
|
expr(f.e);
|
||||||
add(";\n");
|
add(",\n");
|
||||||
}
|
}
|
||||||
if( def != null ) {
|
tabs = tabs.substr(1);
|
||||||
add("default: ");
|
add("}");
|
||||||
expr(def);
|
}
|
||||||
add(";\n");
|
case ETernary(c,e1,e2):
|
||||||
}
|
expr(c);
|
||||||
add("}");
|
add(" ? ");
|
||||||
case EMeta(name, args, e):
|
expr(e1);
|
||||||
add("@");
|
add(" : ");
|
||||||
add(name);
|
expr(e2);
|
||||||
if( args != null && args.length > 0 ) {
|
case ESwitch(e, cases, def):
|
||||||
add("(");
|
add("switch( ");
|
||||||
var first = true;
|
expr(e);
|
||||||
for( a in args ) {
|
add(") {");
|
||||||
if( first ) first = false else add(", ");
|
for( c in cases ) {
|
||||||
expr(e);
|
add("case ");
|
||||||
}
|
var first = true;
|
||||||
add(")");
|
for( v in c.values ) {
|
||||||
}
|
if( first ) first = false else add(", ");
|
||||||
add(" ");
|
expr(v);
|
||||||
expr(e);
|
}
|
||||||
case ECheckType(e, t):
|
add(": ");
|
||||||
add("(");
|
expr(c.expr);
|
||||||
expr(e);
|
add(";\n");
|
||||||
add(" : ");
|
}
|
||||||
addType(t);
|
if( def != null ) {
|
||||||
add(")");
|
add("default: ");
|
||||||
}
|
expr(def);
|
||||||
}
|
add(";\n");
|
||||||
|
}
|
||||||
public static function toString( e : Expr ):String {
|
add("}");
|
||||||
return new Printer().exprToString(e);
|
case EMeta(name, args, e):
|
||||||
}
|
add("@");
|
||||||
|
add(name);
|
||||||
public static function errorToString( e : Expr.Error ):String {
|
if( args != null && args.length > 0 ) {
|
||||||
var message = switch( #if hscriptPos e.e #else e #end ) {
|
add("(");
|
||||||
case EInvalidChar(c): "Invalid character: '"+(StringTools.isEof(c) ? "EOF (End Of File)" : String.fromCharCode(c))+"' ("+c+")";
|
var first = true;
|
||||||
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
for( a in args ) {
|
||||||
case EUnterminatedString: "Unterminated string";
|
if( first ) first = false else add(", ");
|
||||||
case EUnterminatedComment: "Unterminated comment";
|
expr(e);
|
||||||
case EInvalidPreprocessor(str): "Invalid preprocessor (" + str + ")";
|
}
|
||||||
case EUnknownVariable(v): "Unknown variable: "+v;
|
add(")");
|
||||||
case EInvalidIterator(v): "Invalid iterator: "+v;
|
}
|
||||||
case EInvalidOp(op): "Invalid operator: "+op;
|
add(" ");
|
||||||
case EInvalidAccess(f): "Invalid access to field " + f;
|
expr(e);
|
||||||
case ECustom(msg): msg;
|
case ECheckType(e, t):
|
||||||
case EInvalidClass(cla): "Invalid class: " + cla + " was not found.";
|
add("(");
|
||||||
case EAlreadyExistingClass(cla): 'Custom Class named $cla already exists.';
|
expr(e);
|
||||||
};
|
add(" : ");
|
||||||
#if hscriptPos
|
addType(t);
|
||||||
return e.origin + ":" + e.line + ": " + message;
|
add(")");
|
||||||
#else
|
}
|
||||||
return message;
|
}
|
||||||
#end
|
|
||||||
}
|
public static function toString( e : Expr ):String {
|
||||||
|
return new Printer().exprToString(e);
|
||||||
|
}
|
||||||
}
|
|
||||||
|
public static function errorToString( e : Expr.Error ):String {
|
||||||
|
var message = switch( #if hscriptPos e.e #else e #end ) {
|
||||||
|
case EInvalidChar(c): "Invalid character: '"+(StringTools.isEof(c) ? "EOF (End Of File)" : String.fromCharCode(c))+"' ("+c+")";
|
||||||
|
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
||||||
|
case EUnterminatedString: "Unterminated string";
|
||||||
|
case EUnterminatedComment: "Unterminated comment";
|
||||||
|
case EInvalidPreprocessor(str): "Invalid preprocessor (" + str + ")";
|
||||||
|
case EUnknownVariable(v): "Unknown variable: "+v;
|
||||||
|
case EInvalidIterator(v): "Invalid iterator: "+v;
|
||||||
|
case EInvalidOp(op): "Invalid operator: "+op;
|
||||||
|
case EInvalidAccess(f): "Invalid access to field " + f;
|
||||||
|
case ECustom(msg): msg;
|
||||||
|
case EInvalidClass(cla): "Invalid class: " + cla + " was not found.";
|
||||||
|
case EAlreadyExistingClass(cla): 'Custom Class named $cla already exists.';
|
||||||
|
};
|
||||||
|
#if hscriptPos
|
||||||
|
return e.origin + ":" + e.line + ": " + message;
|
||||||
|
#else
|
||||||
|
return message;
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
+68
-18
@@ -26,15 +26,33 @@ import hscript.Expr.FieldPropertyAccess;
|
|||||||
* @see https://haxe.org/manual/class-field-property.html
|
* @see https://haxe.org/manual/class-field-property.html
|
||||||
*/
|
*/
|
||||||
@:access(hscript.Interp)
|
@:access(hscript.Interp)
|
||||||
@:structInit
|
|
||||||
class Property {
|
class Property {
|
||||||
private static inline var GET = 'get_';
|
private static inline var GET = 'get_';
|
||||||
private static inline var SET = 'set_';
|
private static inline var SET = 'set_';
|
||||||
|
|
||||||
public var r:Dynamic;
|
/**
|
||||||
public var getter:FieldPropertyAccess;
|
* Name of the attached field.
|
||||||
public var setter:FieldPropertyAccess;
|
*/
|
||||||
|
public final name:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current value. If isn't initialized, it's always `null`.
|
||||||
|
*/
|
||||||
|
public var r:Dynamic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The getter property kind
|
||||||
|
*/
|
||||||
|
public final getter:FieldPropertyAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The setter property kind
|
||||||
|
*/
|
||||||
|
public final setter:FieldPropertyAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the field is declared as static.
|
||||||
|
*/
|
||||||
public var isStatic(get, never):Bool;
|
public var isStatic(get, never):Bool;
|
||||||
function get_isStatic() {
|
function get_isStatic() {
|
||||||
return __isStatic && interp.allowStaticVariables;
|
return __isStatic && interp.allowStaticVariables;
|
||||||
@@ -43,7 +61,20 @@ class Property {
|
|||||||
var isVar:Bool;
|
var isVar:Bool;
|
||||||
var interp:Interp;
|
var interp:Interp;
|
||||||
|
|
||||||
public function new(r:Dynamic, getter:FieldPropertyAccess, setter:FieldPropertyAccess, isVar:Bool, isStatic:Bool, interp:Interp) {
|
@:allow(hscript.Interp)
|
||||||
|
private var getterFunc(get, never):String;
|
||||||
|
private inline function get_getterFunc():String {
|
||||||
|
return '$GET$name';
|
||||||
|
}
|
||||||
|
|
||||||
|
@:allow(hscript.Interp)
|
||||||
|
private var setterFunc(get, never):String;
|
||||||
|
private inline function get_setterFunc():String {
|
||||||
|
return '$SET$name';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function new(name:String, r:Dynamic, getter:FieldPropertyAccess, setter:FieldPropertyAccess, isVar:Bool, isStatic:Bool, interp:Interp) {
|
||||||
|
this.name = name;
|
||||||
this.r = r;
|
this.r = r;
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
@@ -52,23 +83,41 @@ class Property {
|
|||||||
this.interp = interp;
|
this.interp = interp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal flags to gain access to the current field value (if isn't a property field)
|
||||||
var __allowReadAccess:Bool = false;
|
var __allowReadAccess:Bool = false;
|
||||||
var __allowWriteAccess:Bool = false;
|
var __allowWriteAccess:Bool = false;
|
||||||
var __allowSetGet:Null<Bool> = null;
|
// Internal flag to gain access if the field is accessed with @:bypassAccessor
|
||||||
|
var __allowSetGet:Bool = true;
|
||||||
|
|
||||||
final __isStatic:Bool = false;
|
final __isStatic:Bool = false;
|
||||||
|
|
||||||
public function callGetter(name:String) {
|
public function get(isBypassAccessor:Bool) {
|
||||||
|
if(isBypassAccessor) __allowSetGet = false;
|
||||||
|
var r:Dynamic = callGetter();
|
||||||
|
if(isBypassAccessor) __allowSetGet = true;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set(value:Dynamic, isBypassAccessor:Bool) {
|
||||||
|
if(isBypassAccessor) __allowSetGet = false;
|
||||||
|
var r:Dynamic = callSetter(value);
|
||||||
|
if(isBypassAccessor) __allowSetGet = true;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function callGetter():Dynamic {
|
||||||
switch (getter) {
|
switch (getter) {
|
||||||
case AGet | ADynamic:
|
case AGet | ADynamic:
|
||||||
var fName:String = '$GET$name';
|
var fName:String = getterFunc;
|
||||||
if (!__allowReadAccess && (__allowSetGet != null && __allowSetGet || !interp.isBypassAccessor)) {
|
if (!__allowReadAccess && __allowSetGet) {
|
||||||
if (varExists(fName)) {
|
if (varExists(fName)) {
|
||||||
return callAccessor(fName);
|
return callAccessor(fName);
|
||||||
} else
|
} else
|
||||||
interp.error(ECustom('Method $fName required by property $name is missing'));
|
interp.error(ECustom('Method $fName required by property $name is missing'));
|
||||||
} else {
|
} else {
|
||||||
if ((setter == ADefault || setter == ANull) || isVar)
|
if ((setter == ADefault || setter == ANull) || isVar) {
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
||||||
}
|
}
|
||||||
@@ -80,18 +129,19 @@ class Property {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function callSetter(name:String, val:Dynamic) {
|
private function callSetter(val:Dynamic):Dynamic {
|
||||||
switch (setter) {
|
switch (setter) {
|
||||||
case ASet | ADynamic:
|
case ASet | ADynamic:
|
||||||
var fName:String = '$SET$name';
|
var fName:String = setterFunc;
|
||||||
if (!__allowWriteAccess && (__allowSetGet != null && __allowSetGet || !interp.isBypassAccessor)) {
|
if (!__allowWriteAccess && __allowSetGet) {
|
||||||
if (varExists(fName))
|
if (varExists(fName))
|
||||||
return callAccessor(fName, [val], true);
|
return callAccessor(fName, true, val);
|
||||||
else
|
else
|
||||||
interp.error(ECustom('Method $fName required by property $name is missing'));
|
interp.error(ECustom('Method $fName required by property $name is missing'));
|
||||||
} else {
|
} else {
|
||||||
if ((getter == ADefault || getter == ANull) || isVar)
|
if ((getter == ADefault || getter == ANull) || isVar) {
|
||||||
return r = val;
|
return r = val;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
||||||
}
|
}
|
||||||
@@ -103,14 +153,14 @@ class Property {
|
|||||||
return r = val;
|
return r = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function callAccessor(f:String, ?args:Array<Dynamic>, isWrite:Bool = false):Dynamic {
|
private function callAccessor(f:String, isWrite:Bool = false, ?value:Dynamic):Dynamic {
|
||||||
var fn = isStatic ? interp.staticVariables.get(f) : interp.variables.get(f);
|
var fn = isStatic ? interp.staticVariables.get(f) : interp.variables.get(f);
|
||||||
var rt:Dynamic = null;
|
var rt:Dynamic = null;
|
||||||
if (fn != null && Reflect.isFunction(fn)) {
|
if (fn != null && Reflect.isFunction(fn)) {
|
||||||
if (isWrite) __allowWriteAccess = true;
|
if (isWrite) __allowWriteAccess = true;
|
||||||
else __allowReadAccess = true;
|
else __allowReadAccess = true;
|
||||||
|
|
||||||
rt = UnsafeReflect.callMethodUnsafe(null, fn, args == null ? [] : args);
|
rt = UnsafeReflect.callMethodUnsafe(null, fn, isWrite ? [value] : []);
|
||||||
|
|
||||||
if (isWrite) __allowWriteAccess = false;
|
if (isWrite) __allowWriteAccess = false;
|
||||||
else __allowReadAccess = false;
|
else __allowReadAccess = false;
|
||||||
@@ -122,7 +172,7 @@ class Property {
|
|||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function varExists(n:String) {
|
private inline function varExists(n:String) {
|
||||||
return isStatic ? interp.staticVariables.exists(n) : interp.variables.exists(n);
|
return isStatic ? interp.staticVariables.exists(n) : interp.variables.exists(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+143
-136
@@ -1,137 +1,144 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C)2008-2017 Haxe Foundation
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
* to deal in the Software without restriction, including without limitation
|
* to deal in the Software without restriction, including without limitation
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
import hscript.Expr;
|
import hscript.Expr;
|
||||||
|
|
||||||
class Tools {
|
class Tools {
|
||||||
|
|
||||||
public static function iter( e : Expr, f : Expr -> Void ):Void {
|
public static function iter( e : Expr, f : Expr -> Void ):Void {
|
||||||
switch( expr(e) ) {
|
switch( expr(e) ) {
|
||||||
case EConst(_), EIdent(_):
|
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 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 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);
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function map( e : Expr, f : Expr -> Expr ):Expr {
|
public static function map( e : Expr, f : Expr -> 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, isPublic, isStatic, isPrivate): EVar(n, t, if( e != null ) f(e) else null, isPublic, isStatic, isPrivate);
|
case EVar(n, t, e, isPublic, isStatic, isPrivate): EVar(n, t, if( e != null ) f(e) else null, isPublic, isStatic, isPrivate);
|
||||||
case EParent(e): EParent(f(e));
|
case EParent(e): EParent(f(e));
|
||||||
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
||||||
case EField(e, fi): EField(f(e),fi);
|
case EField(e, fi): EField(f(e),fi);
|
||||||
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 EFunction(args, e, name, t, isPublic, isStatic, isOverride, isPrivate): EFunction(args, f(e), name, t, isPublic, isStatic, isOverride, isPrivate);
|
case EFunction(args, e, name, t, isPublic, isStatic, isOverride, isPrivate): EFunction(args, f(e), name, t, isPublic, isStatic, isOverride, isPrivate);
|
||||||
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 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 ) { name : fi.name, e : f(fi.e) }]);
|
case EObject(fl): EObject([for( fi in fl ) { name : fi.name, e : 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 ) { values : [for( v in c.values ) f(v)], expr : 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): EImport(c);
|
case EImport(c): EImport(c);
|
||||||
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);
|
||||||
default: expr(e);
|
default: expr(e);
|
||||||
}
|
}
|
||||||
return mk(edef, e);
|
return mk(edef, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static inline function expr( e : Expr ) : ExprDef {
|
public static inline function expr( e : Expr ) : ExprDef {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return e.e;
|
return e.e;
|
||||||
#else
|
#else
|
||||||
return e;
|
return e;
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
public static inline function mk( e : ExprDef, p : Expr ):Expr {
|
public static inline function mk( e : ExprDef, p : Expr ):Expr {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return { e : e, pmin : p.pmin, pmax : p.pmax, origin : p.origin, line : p.line };
|
return { e : e, pmin : p.pmin, pmax : p.pmax, origin : p.origin, line : p.line };
|
||||||
#else
|
#else
|
||||||
return e;
|
return e;
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DO NOT USE INLINE ON THIS FUNCTION
|
* DO NOT USE INLINE ON THIS FUNCTION
|
||||||
**/
|
**/
|
||||||
public static function argCount(func: haxe.Constraints.Function): Int {
|
public static function argCount(func: haxe.Constraints.Function): Int {
|
||||||
// https://github.com/pisayesiwsi/hscript-iris/blob/dev/crowplexus/hscript/Tools.hx#L206
|
// https://github.com/pisayesiwsi/hscript-iris/blob/dev/crowplexus/hscript/Tools.hx#L206
|
||||||
#if cpp
|
#if cpp
|
||||||
return untyped __cpp__("{0}->__ArgCount()", func);
|
return untyped __cpp__("{0}->__ArgCount()", func);
|
||||||
#elseif js
|
#elseif js
|
||||||
return untyped js.Syntax.code("{0}.length", func);
|
return untyped js.Syntax.code("{0}.length", func);
|
||||||
#elseif hl
|
#elseif hl
|
||||||
var ft = hl.Type.getDynamic(func);
|
var ft = hl.Type.getDynamic(func);
|
||||||
if (ft.kind != HFun)
|
if (ft.kind != HFun)
|
||||||
return -1;
|
return -1;
|
||||||
return ft.getArgsCount();
|
return ft.getArgsCount();
|
||||||
#else
|
#else
|
||||||
return -1;
|
return -1;
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
public static inline function isCustomAbstract(obj:Dynamic):Bool
|
public static function isUppercase(s:String) {
|
||||||
return obj != null && obj is IHScriptAbstractBehaviour;
|
if(s.length == 0) return false;
|
||||||
|
var c:Int = StringTools.fastCodeAt(s, 0);
|
||||||
|
if(StringTools.isEof(c)) return false; // Just in case :3
|
||||||
|
return c >= 65 && c <= 90; // A-Z
|
||||||
|
}
|
||||||
|
|
||||||
|
public static inline function isCustomAbstract(obj:Dynamic):Bool
|
||||||
|
return obj != null && obj is IHScriptAbstractBehaviour;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -12,12 +12,14 @@ using StringTools;
|
|||||||
|
|
||||||
class AbstractHandler {
|
class AbstractHandler {
|
||||||
public static function init() {
|
public static function init() {
|
||||||
|
#if HSCRIPT_ABSTRACT_SUPPORT
|
||||||
#if !display
|
#if !display
|
||||||
if(Context.defined("display")) return;
|
if(Context.defined("display")) return;
|
||||||
for(apply in Config.ALLOWED_ABSTRACT_AND_ENUM) {
|
for(apply in Config.ALLOWED_ABSTRACT_AND_ENUM) {
|
||||||
Compiler.addGlobalMetadata(apply, '@:build(hscript.macros.AbstractHandler.build())');
|
Compiler.addGlobalMetadata(apply, '@:build(hscript.macros.AbstractHandler.build())');
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function build():Array<Field> {
|
public static function build():Array<Field> {
|
||||||
|
|||||||
@@ -483,8 +483,9 @@ class ClassExtendMacro {
|
|||||||
if (__interp != null) {
|
if (__interp != null) {
|
||||||
if(__class__fields.contains(name)) {
|
if(__class__fields.contains(name)) {
|
||||||
var v:Dynamic = __interp.variables.get(name);
|
var v:Dynamic = __interp.variables.get(name);
|
||||||
|
var ba:Bool = @:privateAccess __interp.isBypassAccessor;
|
||||||
if(v != null && v is hscript.Property)
|
if(v != null && v is hscript.Property)
|
||||||
return cast(v, hscript.Property).callGetter(name);
|
return cast(v, hscript.Property).get(ba);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
else @:privateAccess {
|
else @:privateAccess {
|
||||||
@@ -508,8 +509,9 @@ class ClassExtendMacro {
|
|||||||
if (__interp != null) {
|
if (__interp != null) {
|
||||||
if(__class__fields.contains(name)) {
|
if(__class__fields.contains(name)) {
|
||||||
var v:Dynamic = __interp.variables.get(name);
|
var v:Dynamic = __interp.variables.get(name);
|
||||||
|
var ba:Bool = @:privateAccess __interp.isBypassAccessor;
|
||||||
if(v != null && v is hscript.Property)
|
if(v != null && v is hscript.Property)
|
||||||
return cast(v, hscript.Property).callGetter(name);
|
return cast(v, hscript.Property).get(ba);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
else @:privateAccess {
|
else @:privateAccess {
|
||||||
@@ -535,8 +537,9 @@ class ClassExtendMacro {
|
|||||||
if (__interp != null) {
|
if (__interp != null) {
|
||||||
if(__class__fields.contains(name)) {
|
if(__class__fields.contains(name)) {
|
||||||
var v:Dynamic = __interp.variables.get(name);
|
var v:Dynamic = __interp.variables.get(name);
|
||||||
|
var ba:Bool = @:privateAccess __interp.isBypassAccessor;
|
||||||
if(v != null && v is hscript.Property)
|
if(v != null && v is hscript.Property)
|
||||||
return cast(v, hscript.Property).callSetter(name, val);
|
return cast(v, hscript.Property).set(val, ba);
|
||||||
__interp.variables.set(name, val);
|
__interp.variables.set(name, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@@ -565,8 +568,9 @@ class ClassExtendMacro {
|
|||||||
if (__interp != null) {
|
if (__interp != null) {
|
||||||
if(__class__fields.contains(name)) {
|
if(__class__fields.contains(name)) {
|
||||||
var v:Dynamic = __interp.variables.get(name);
|
var v:Dynamic = __interp.variables.get(name);
|
||||||
|
var ba:Bool = @:privateAccess __interp.isBypassAccessor;
|
||||||
if(v != null && v is hscript.Property)
|
if(v != null && v is hscript.Property)
|
||||||
return cast(v, hscript.Property).callSetter(name, val);
|
return cast(v, hscript.Property).set(val, ba);
|
||||||
__interp.variables.set(name, val);
|
__interp.variables.set(name, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class UsingHandler {
|
|||||||
usingEntries.set(name, {call: entry, fields: fields});
|
usingEntries.set(name, {call: entry, fields: fields});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entryExists(name:String):Bool {
|
public inline function entryExists(name:String):Bool {
|
||||||
return usingEntries.exists(name);
|
return usingEntries.exists(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user