Compare commits
43
Commits
@@ -1,6 +1,8 @@
|
|||||||
hscript-improved
|
hscript-improved
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
- [Features](docs/FEATURES.md)
|
||||||
|
|
||||||
How to install
|
How to install
|
||||||
```
|
```
|
||||||
haxelib git hscript-improved https://github.com/CodenameCrew/hscript-improved.git
|
haxelib git hscript-improved https://github.com/CodenameCrew/hscript-improved.git
|
||||||
@@ -18,7 +20,9 @@ or set this in build.hxml
|
|||||||
-D CUSTOM_CLASSES
|
-D CUSTOM_CLASSES
|
||||||
```
|
```
|
||||||
|
|
||||||
Warning: custom class system is still in development, would like help to test it. 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. Also you cannot create custom classes that extends a typed class (those ones that has `<T>`), this will be implemented in the future.
|
Current Custom Class Limitations :
|
||||||
|
|
||||||
|
- You cannot create custom classes that extends a typed class (those ones that has `<T>`), this will be implemented in the future.
|
||||||
|
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# FEATURES
|
||||||
|
|
||||||
|
- Custom Classes
|
||||||
|
- Final Classes
|
||||||
|
- Static Classes
|
||||||
|
- Allow for type check (`is`)
|
||||||
|
- Allow extending other custom classes
|
||||||
|
- Enums
|
||||||
|
|
||||||
|
```haxe
|
||||||
|
enum TypeValue {
|
||||||
|
NUMBER(n:Int);
|
||||||
|
DECIMAL(d:Float, ?p:Int);
|
||||||
|
CHARACTER(s:String);
|
||||||
|
BOOLEAN(b:Bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = TypeValue.DECIMAL(10.1234, 2);
|
||||||
|
// You need to type the full enum field for each case
|
||||||
|
// i.e. you can't type the enum field directly (limitation for now)
|
||||||
|
switch(type) {
|
||||||
|
case TypeValue.NUMBER(number):
|
||||||
|
trace("number: " + number);
|
||||||
|
case TypeValue.DECIMAL(decimal, precision):
|
||||||
|
if(precision != null)
|
||||||
|
trace("decimal: " + decimal + " | rounded decimal: " + roundDecimal(decimal, precision));
|
||||||
|
else
|
||||||
|
trace("decimal: " + decimal);
|
||||||
|
case TypeValue.CHARACTER(char):
|
||||||
|
trace("character: " + char);
|
||||||
|
default:
|
||||||
|
trace("unknown type");
|
||||||
|
}
|
||||||
|
|
||||||
|
function roundDecimal(Value:Float, Precision:Int) {
|
||||||
|
var mult:Float = Math.pow(10, Precision);
|
||||||
|
return Math.fround(Value * mult) / mult;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Enum matching with arguments for switch statements (for real and scripted enums)
|
||||||
|
- Property Fields (`(get, set)` variables)
|
||||||
|
|
||||||
|
```haxe
|
||||||
|
public var myvar(get, set):Int;
|
||||||
|
var _myvar:Int = 10;
|
||||||
|
|
||||||
|
function get_myvar():Int {
|
||||||
|
return _myvar;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_myvar(val:Int):Int {
|
||||||
|
if(val > 10) return _myvar = val;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `@:isVar` metadata support
|
||||||
|
|
||||||
|
- Static extension (`using`)
|
||||||
|
|
||||||
|
```haxe
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
class IntExtender {
|
||||||
|
static public function triple(i:Int) {
|
||||||
|
return i * 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to create/import the custom class
|
||||||
|
// before setting the extension (limitation for now)
|
||||||
|
using IntExtender;
|
||||||
|
|
||||||
|
var str = " Hello World! ";
|
||||||
|
trace(str.trim()); // "Hello World!"
|
||||||
|
trace(12.triple()); // 36
|
||||||
|
```
|
||||||
|
|
||||||
|
- Support for real and custom classes
|
||||||
|
- Misc.
|
||||||
|
- Allow using type parameters for creating objects (i.e. `var a = new TypedObject<Int>();`)
|
||||||
|
- Allow `package` declaration. Ignored by the interpreter.
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "hscript",
|
"name": "hscript-improved",
|
||||||
"url": "https://github.com/HaxeFoundation/hscript",
|
"url": "https://github.com/HaxeFoundation/hscript",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
|
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
|
||||||
|
|||||||
+536
-536
File diff suppressed because it is too large
Load Diff
+8
-4
@@ -124,6 +124,8 @@ class Bytes {
|
|||||||
#end
|
#end
|
||||||
bout.addByte(Type.enumIndex(e));
|
bout.addByte(Type.enumIndex(e));
|
||||||
switch( e ) {
|
switch( e ) {
|
||||||
|
case EPackage(n):
|
||||||
|
// TODO
|
||||||
case EImport(c):
|
case EImport(c):
|
||||||
// TODO
|
// TODO
|
||||||
case EClass(_, _, _, _):
|
case EClass(_, _, _, _):
|
||||||
@@ -132,6 +134,8 @@ class Bytes {
|
|||||||
// TODO
|
// TODO
|
||||||
case ECast(e, _):
|
case ECast(e, _):
|
||||||
// TODO
|
// TODO
|
||||||
|
case ERegex(e, f):
|
||||||
|
// TODO
|
||||||
case EConst(c):
|
case EConst(c):
|
||||||
doEncodeConst(c);
|
doEncodeConst(c);
|
||||||
case EIdent(v):
|
case EIdent(v):
|
||||||
@@ -152,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):
|
||||||
@@ -274,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"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
+37
-21
@@ -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;
|
||||||
|
|
||||||
@@ -48,6 +47,12 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
__interp.staticVariables = __class.ogInterp.staticVariables;
|
__interp.staticVariables = __class.ogInterp.staticVariables;
|
||||||
__interp.customClasses = __class.ogInterp.customClasses;
|
__interp.customClasses = __class.ogInterp.customClasses;
|
||||||
|
|
||||||
|
for(f => v in __class.__interp.variables) {
|
||||||
|
if(f == 'new') continue;
|
||||||
|
if (!__interp.variables.exists(f))
|
||||||
|
__interp.variables.set(f, v);
|
||||||
|
}
|
||||||
|
|
||||||
for (f in __class.fields) {
|
for (f in __class.fields) {
|
||||||
switch (Tools.expr(f)) {
|
switch (Tools.expr(f)) {
|
||||||
case EVar(n): __class__fields.push(n);
|
case EVar(n): __class__fields.push(n);
|
||||||
@@ -59,11 +64,6 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
@:privateAccess __interp.exprReturn(f);
|
@:privateAccess __interp.exprReturn(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (f => v in __class.__interp.variables) {
|
|
||||||
if (!__interp.variables.exists(f))
|
|
||||||
__interp.variables.set(f, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
__interp.scriptObject = this;
|
__interp.scriptObject = this;
|
||||||
|
|
||||||
initializing = true;
|
initializing = true;
|
||||||
@@ -124,25 +124,40 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
if(__cachedFieldSet != null)
|
if(__cachedFieldSet != null)
|
||||||
UnsafeReflect.setField(__class.cl, "__cachedFieldSet", __cachedFieldSet);
|
UnsafeReflect.setField(__class.cl, "__cachedFieldSet", __cachedFieldSet);
|
||||||
|
|
||||||
var disallowCopy = Type.getInstanceFields(__class.cl);
|
|
||||||
__superClass = Type.createInstance(__class.cl, args);
|
__superClass = Type.createInstance(__class.cl, args);
|
||||||
__superClass.__real_fields = disallowCopy;
|
var disallowCopy:Array<String> = {
|
||||||
|
var fieldMap:Map<String, String> = []; // Prevent duplicate values
|
||||||
|
for(f in Reflect.fields(__superClass).concat(Type.getInstanceFields(Type.getClass(__superClass))))
|
||||||
|
fieldMap.set(f, f);
|
||||||
|
|
||||||
|
fieldMap.array();
|
||||||
|
}
|
||||||
|
this.__real_fields = disallowCopy;
|
||||||
|
@:privateAccess __interp.__instanceFields = __interp.__instanceFields.concat(disallowCopy);
|
||||||
|
__superClass.__real_fields = this.__real_fields;
|
||||||
__superClass.__class__fields = this.__class__fields;
|
__superClass.__class__fields = this.__class__fields;
|
||||||
__superClass.__interp = this.__interp;
|
__superClass.__interp = this.__interp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function call(name:String, ?args:Array<Dynamic>, ?toSuper:Bool = false):Dynamic {
|
public function call(name:String, ?args:Array<Dynamic>, ?toSuper:Bool = false):Dynamic {
|
||||||
// TODO: optimize this
|
var superFnName:Null<String> = toSuper ? '_HX_SUPER__$name' : null;
|
||||||
var fnName = toSuper ? '_HX_SUPER__$name' : name;
|
var fn:Dynamic = {
|
||||||
var fn:Dynamic = __interp.variables.get(fnName);
|
if(toSuper && __interp.variables.exists(superFnName)) {
|
||||||
if(toSuper && fn == null)
|
__interp.variables.get(superFnName);
|
||||||
fn = __interp.variables.get(name);
|
}
|
||||||
|
else
|
||||||
|
__interp.variables.get(name);
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,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;
|
||||||
@@ -170,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);
|
||||||
@@ -338,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,39 +56,35 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
__interp.staticVariables = ogInterp.staticVariables;
|
__interp.staticVariables = ogInterp.staticVariables;
|
||||||
__interp.customClasses = ogInterp.customClasses;
|
__interp.customClasses = ogInterp.customClasses;
|
||||||
|
|
||||||
for(e in fields.copy()) {
|
for(f => v in ogInterp.variables)
|
||||||
var validField:Bool = false;
|
if(!__interp.variables.exists(f))
|
||||||
|
__interp.variables.set(f, v);
|
||||||
|
|
||||||
|
for(i => e in fields.copy()) {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(f => v in ogInterp.variables)
|
|
||||||
if(!__interp.variables.exists(f))
|
|
||||||
__interp.variables.set(f, v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hnew(args:Array<Dynamic>):Dynamic
|
public function hnew(args:Array<Dynamic>):Dynamic
|
||||||
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);
|
||||||
@@ -118,6 +114,12 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function hget(name:String):Dynamic {
|
public function hget(name:String):Dynamic {
|
||||||
|
if(name == 'new') {
|
||||||
|
return Reflect.makeVarArgs(function(args:Array<Dynamic>):Dynamic {
|
||||||
|
return inline this.hnew(args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if(hasField(name)) {
|
if(hasField(name)) {
|
||||||
return getField(name);
|
return getField(name);
|
||||||
}
|
}
|
||||||
|
|||||||
+403
-242
@@ -1,242 +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;
|
||||||
EImport( c : String, ?asname:String, ?isUsing:Bool );
|
case ">>": OpShr;
|
||||||
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String>, ?isFinal:Bool, ?isPrivate:Bool );
|
case ">>>": OpUshr;
|
||||||
EEnum( en:EnumDecl, ?isAbstract:Bool );
|
case "==": OpEq;
|
||||||
ECast(e:Expr, ?t:CType);
|
case "!=": OpNeq;
|
||||||
}
|
case ">=": OpGte;
|
||||||
|
case "<=": OpLte;
|
||||||
@:structInit
|
case ">": OpGt;
|
||||||
final class ObjectField {
|
case "<": OpLt;
|
||||||
public var name : String;
|
case "||": OpBoolOr;
|
||||||
public var e : Expr;
|
case "&&": OpBoolAnd;
|
||||||
}
|
case "is": OpIs;
|
||||||
|
case "=": OpAssign;
|
||||||
@:structInit
|
case "??": OpNcoal;
|
||||||
final class SwitchCase {
|
case "...": OpInterval;
|
||||||
public var values : Array<Expr>;
|
case "->": OpArrow;
|
||||||
public var expr : Expr;
|
case "=>": OpArrowFn;
|
||||||
}
|
case "+=": OpAddAssign;
|
||||||
|
case "-=": OpSubAssign;
|
||||||
@:structInit
|
case "*=": OpMultAssign;
|
||||||
final class Argument {
|
case "/=": OpDivAssign;
|
||||||
public var name : String;
|
case "%=": OpModAssign;
|
||||||
public var t : CType;
|
case "&=": OpAndAssign;
|
||||||
public var opt : Bool;
|
case "|=": OpOrAssign;
|
||||||
public var value : Expr;
|
case "^=": OpXorAssign;
|
||||||
}
|
case "<<=": OpShlAssign;
|
||||||
|
case ">>=": OpShrAssign;
|
||||||
@:structInit
|
case ">>>=": OpUshrAssign;
|
||||||
final class MetadataEntry {
|
case _ if (s == "??" + "="): OpNcoalAssign;
|
||||||
public var name : String;
|
default: -1;
|
||||||
public var params : Array<Expr>;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Metadata = Array<MetadataEntry>;
|
public inline function toString():String {
|
||||||
|
return switch(this) {
|
||||||
@:structInit
|
case OpAdd: "+";
|
||||||
final class EnumDecl {
|
case OpSub: "-";
|
||||||
public var name : String;
|
case OpMult: "*";
|
||||||
public var fields : Array<EnumField>;
|
case OpDiv: "/";
|
||||||
}
|
case OpMod: "%";
|
||||||
|
case OpAnd: "&";
|
||||||
@:structInit
|
case OpOr: "|";
|
||||||
final class EnumField {
|
case OpXor: "^";
|
||||||
public var name : String;
|
case OpShl: "<<";
|
||||||
public var args : Array<Argument>;
|
case OpShr: ">>";
|
||||||
}
|
case OpUshr: ">>>";
|
||||||
|
case OpEq: "==";
|
||||||
enum CType {
|
case OpNeq: "!=";
|
||||||
CTPath( path : Array<String>, ?params : Array<CType> );
|
case OpGte: ">=";
|
||||||
CTFun( args : Array<CType>, ret : CType );
|
case OpLte: "<=";
|
||||||
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
|
case OpGt: ">";
|
||||||
CTParent( t : CType );
|
case OpLt: "<";
|
||||||
CTOpt( t : CType );
|
case OpBoolOr: "||";
|
||||||
CTNamed( n : String, t : CType );
|
case OpBoolAnd: "&&";
|
||||||
CTExpr( e : Expr ); // for type parameters only
|
case OpIs: "is";
|
||||||
}
|
case OpAssign: "=";
|
||||||
|
case OpNcoal: "??";
|
||||||
#if hscriptPos
|
case OpInterval: "...";
|
||||||
class Error {
|
case OpArrow: "->";
|
||||||
public var e : ErrorDef;
|
case OpArrowFn: "=>";
|
||||||
public var pmin : Int;
|
case OpAddAssign: "+=";
|
||||||
public var pmax : Int;
|
case OpSubAssign: "-=";
|
||||||
public var origin : String;
|
case OpMultAssign: "*=";
|
||||||
public var line : Int;
|
case OpDivAssign: "/=";
|
||||||
public function new(e, pmin, pmax, origin, line) {
|
case OpModAssign: "%=";
|
||||||
this.e = e;
|
case OpAndAssign: "&=";
|
||||||
this.pmin = pmin;
|
case OpOrAssign: "|=";
|
||||||
this.pmax = pmax;
|
case OpXorAssign: "^=";
|
||||||
this.origin = origin;
|
case OpShlAssign: "<<=";
|
||||||
this.line = line;
|
case OpShrAssign: ">>=";
|
||||||
}
|
case OpUshrAssign: ">>>=";
|
||||||
public function toString(): String {
|
case OpNcoalAssign: "??" + "=";
|
||||||
return Printer.errorToString(this);
|
default: "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enum ErrorDef {
|
}
|
||||||
#else
|
|
||||||
enum Error {
|
enum abstract Unop(Int) from Int to Int {
|
||||||
#end
|
var OpNot = 0;
|
||||||
EInvalidChar( c : Int );
|
var OpNeg = 1;
|
||||||
EUnexpected( s : String );
|
var OpIncrement = 2;
|
||||||
EUnterminatedString;
|
var OpDecrement = 3;
|
||||||
EUnterminatedComment;
|
var OpNegBits = 4;
|
||||||
EInvalidPreprocessor( msg : String );
|
|
||||||
EUnknownVariable( v : String );
|
public static inline function fromString(s:String):Unop {
|
||||||
EInvalidIterator( v : String );
|
return switch(s) {
|
||||||
EInvalidOp( op : String );
|
case "!": OpNot;
|
||||||
EInvalidAccess( f : String );
|
case "-": OpNeg;
|
||||||
ECustom( msg : String );
|
case "++": OpIncrement;
|
||||||
EInvalidClass( className : String);
|
case "--": OpDecrement;
|
||||||
EAlreadyExistingClass( className : String);
|
case "~": OpNegBits;
|
||||||
}
|
default: -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
enum ModuleDecl {
|
|
||||||
DPackage( path : Array<String> );
|
public inline function toString():String {
|
||||||
DImport( path : Array<String>, ?everything : Bool );
|
return switch(this) {
|
||||||
DClass( c : ClassDecl );
|
case OpNot: "!";
|
||||||
DTypedef( c : TypeDecl );
|
case OpNeg: "-";
|
||||||
}
|
case OpIncrement: "++";
|
||||||
|
case OpDecrement: "--";
|
||||||
typedef ModuleType = {
|
case OpNegBits: "~";
|
||||||
var name : String;
|
default: "?";
|
||||||
var params : {}; // TODO : not yet parsed
|
}
|
||||||
var meta : Metadata;
|
}
|
||||||
var isPrivate : Bool;
|
}
|
||||||
}
|
|
||||||
|
typedef UInt32 = #if cpp cpp.UInt32 #else Int #end;
|
||||||
typedef ClassDecl = {> ModuleType,
|
typedef UInt64 = #if cpp cpp.UInt64 #else Int #end;
|
||||||
var extend : Null<CType>;
|
|
||||||
var implement : Array<CType>;
|
enum Const {
|
||||||
var fields : Array<FieldDecl>;
|
CInt( v : Int );
|
||||||
var isExtern : Bool;
|
CFloat( f : Float );
|
||||||
}
|
CString( s : String, ?i : Bool );
|
||||||
|
}
|
||||||
typedef TypeDecl = {> ModuleType,
|
|
||||||
var t : CType;
|
#if hscriptPos
|
||||||
}
|
@:structInit
|
||||||
|
final class Expr {
|
||||||
typedef FieldDecl = {
|
public var e : ExprDef;
|
||||||
var name : String;
|
public var pmin : Int;
|
||||||
var meta : Metadata;
|
public var pmax : Int;
|
||||||
var kind : FieldKind;
|
public var origin : String;
|
||||||
var access : Array<FieldAccess>;
|
public var line : Int;
|
||||||
}
|
}
|
||||||
|
enum ExprDef {
|
||||||
enum abstract FieldAccess(UInt8) {
|
#else
|
||||||
var APublic;
|
typedef ExprDef = Expr;
|
||||||
var APrivate;
|
enum Expr {
|
||||||
var AInline;
|
#end
|
||||||
var AOverride;
|
EConst( c : Const );
|
||||||
var AStatic;
|
EIdent( v : String );
|
||||||
var AMacro;
|
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool, ?get : FieldPropertyAccess, ?set : FieldPropertyAccess, ?isVar:Bool );
|
||||||
}
|
EParent( e : Expr );
|
||||||
|
EBlock( e : Array<Expr> );
|
||||||
enum abstract FieldPropertyAccess(UInt8) {
|
EField( e : Expr, f : String , ?safe : Bool );
|
||||||
var ADefault;
|
EBinop( op : Binop, e1 : Expr, e2 : Expr );
|
||||||
var ANull;
|
EUnop( op : Unop, prefix : Bool, e : Expr );
|
||||||
var AGet;
|
ECall( e : Expr, params : Array<Expr> );
|
||||||
var ASet;
|
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
||||||
var ADynamic;
|
EWhile( cond : Expr, e : Expr );
|
||||||
var ANever;
|
EFor( v : String, it : Expr, e : Expr, ?ithv: String);
|
||||||
}
|
EBreak;
|
||||||
|
EContinue;
|
||||||
enum FieldKind {
|
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool );
|
||||||
KFunction( f : FunctionDecl );
|
EReturn( ?e : Expr );
|
||||||
KVar( v : VarDecl );
|
EArray( e : Expr, index : Expr );
|
||||||
}
|
EArrayDecl( e : Array<Expr>, ?wantedType: CType );
|
||||||
|
ENew( cl : String, params : Array<Expr>, ?paramType:Array<CType> );
|
||||||
@:structInit
|
EThrow( e : Expr );
|
||||||
final class FunctionDecl {
|
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||||
public var args : Array<Argument>;
|
EObject( fl : Array<ObjectField> );
|
||||||
public var body : Expr;
|
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||||
public var ret : Null<CType>;
|
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
||||||
}
|
EDoWhile( cond : Expr, e : Expr);
|
||||||
|
EMeta( name : String, args : Array<Expr>, e : Expr );
|
||||||
typedef VarDecl = {
|
ECheckType( e : Expr, t : CType );
|
||||||
var get : Null<String>;
|
|
||||||
var set : Null<String>;
|
EPackage( ?n:String );
|
||||||
var expr : Null<Expr>;
|
EImport( c : String, ?asname:String, ?isUsing:Bool );
|
||||||
var type : Null<CType>;
|
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String>, ?isFinal:Bool, ?isPrivate:Bool );
|
||||||
}
|
EEnum( en:EnumDecl, ?isAbstract:Bool );
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+529
-311
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));
|
||||||
|
|||||||
+391
-172
@@ -43,6 +43,7 @@ enum Token {
|
|||||||
TDoubleDot;
|
TDoubleDot;
|
||||||
TMeta( s : String );
|
TMeta( s : String );
|
||||||
TPrepro( s : String );
|
TPrepro( s : String );
|
||||||
|
TRegex( e : String, f:String );
|
||||||
}
|
}
|
||||||
|
|
||||||
@:structInit
|
@:structInit
|
||||||
@@ -72,6 +73,11 @@ class Parser {
|
|||||||
**/
|
**/
|
||||||
public var allowJSON : Bool;
|
public var allowJSON : Bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
activate Regular Expression parsing
|
||||||
|
**/
|
||||||
|
public var allowRegex : Bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
allow types declarations
|
allow types declarations
|
||||||
**/
|
**/
|
||||||
@@ -115,6 +121,8 @@ class Parser {
|
|||||||
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
static inline var regexFlags: String = "igmsu";
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
line = 1;
|
line = 1;
|
||||||
opChars = "+*/-=!><&|^%~";
|
opChars = "+*/-=!><&|^%~";
|
||||||
@@ -207,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;
|
||||||
@@ -217,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;
|
||||||
@@ -245,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
|
||||||
@@ -253,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
|
||||||
@@ -261,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
|
||||||
@@ -269,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;
|
||||||
@@ -280,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;
|
||||||
@@ -300,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);
|
||||||
|
|
||||||
@@ -332,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:
|
||||||
@@ -363,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();
|
||||||
@@ -513,6 +526,8 @@ class Parser {
|
|||||||
var e = parseExpr();
|
var e = parseExpr();
|
||||||
isVar = false;
|
isVar = false;
|
||||||
return mk(EMeta(id, args, e),p1);
|
return mk(EMeta(id, args, e),p1);
|
||||||
|
case TRegex(e, f) if(allowRegex):
|
||||||
|
return mk(ERegex(e, f), p1);
|
||||||
default:
|
default:
|
||||||
return unexpected(tk);
|
return unexpected(tk);
|
||||||
}
|
}
|
||||||
@@ -589,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -957,6 +973,16 @@ class Parser {
|
|||||||
var tk = token();
|
var tk = token();
|
||||||
push(tk);
|
push(tk);
|
||||||
mk(EFunction(inf.args, inf.body, name, inf.ret, nextIsPublic, nextIsStatic, nextIsOverride, nextIsPrivate, nextIsFinal, nextIsInline),p1,pmax(inf.body));
|
mk(EFunction(inf.args, inf.body, name, inf.ret, nextIsPublic, nextIsStatic, nextIsOverride, nextIsPrivate, nextIsFinal, nextIsInline),p1,pmax(inf.body));
|
||||||
|
case "package":
|
||||||
|
var tk = token();
|
||||||
|
push(tk);
|
||||||
|
if(tk == TSemicolon)
|
||||||
|
return mk(EPackage(null), p1);
|
||||||
|
|
||||||
|
var pkg:String = parsePath().join('.');
|
||||||
|
ensure(TSemicolon);
|
||||||
|
push(TSemicolon);
|
||||||
|
mk(EPackage(pkg), p1);
|
||||||
case "import" | "using":
|
case "import" | "using":
|
||||||
var isUsing = id == "using";
|
var isUsing = id == "using";
|
||||||
var oldReadPos = readPos;
|
var oldReadPos = readPos;
|
||||||
@@ -1021,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);
|
||||||
@@ -1102,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;
|
||||||
@@ -1144,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;
|
||||||
@@ -1160,14 +1201,15 @@ class Parser {
|
|||||||
e = parseExpr();
|
e = parseExpr();
|
||||||
}
|
}
|
||||||
|
|
||||||
mk(ECast(e, t));
|
mk(ECast(e, t), p1);
|
||||||
case "return":
|
case "return":
|
||||||
var tk = token();
|
var tk = token();
|
||||||
push(tk);
|
push(tk);
|
||||||
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 ) {
|
||||||
@@ -1344,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) ):
|
||||||
@@ -1376,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);
|
||||||
@@ -1401,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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1454,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:
|
||||||
@@ -1608,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
|
||||||
@@ -1853,8 +1978,9 @@ class Parser {
|
|||||||
return StringTools.fastCodeAt(input, readPos++);
|
return StringTools.fastCodeAt(input, readPos++);
|
||||||
}
|
}
|
||||||
|
|
||||||
function readString( until:Int ):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;
|
||||||
@@ -1901,18 +2027,93 @@ class Parser {
|
|||||||
b.addChar(k);
|
b.addChar(k);
|
||||||
default: invalidChar(c);
|
default: invalidChar(c);
|
||||||
}
|
}
|
||||||
} else if( c == 92 )
|
} 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readFlags():String {
|
||||||
|
if(!allowRegex) return null;
|
||||||
|
var c = 0;
|
||||||
|
var b = new StringBuf();
|
||||||
|
var old = line;
|
||||||
|
var s = input;
|
||||||
|
#if hscriptPos
|
||||||
|
var p1 = readPos - 1;
|
||||||
|
#end
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
var c = readChar();
|
||||||
|
if( StringTools.isEof(c) ) {
|
||||||
|
line = old;
|
||||||
|
error(EUnterminatedString, p1, p1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// semicolon
|
||||||
|
if(c == 59) {
|
||||||
|
this.char = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var f = String.fromCharCode(c);
|
||||||
|
if(regexFlags.indexOf(f) != -1)
|
||||||
|
b.addChar(c);
|
||||||
|
else
|
||||||
|
invalidChar(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
function token():Token {
|
function token():Token {
|
||||||
//function token(?infos : Null<haxe.PosInfos>) {
|
//function token(?infos : Null<haxe.PosInfos>) {
|
||||||
//function ttrace(v:Dynamic, ?infos : Null<haxe.PosInfos>) {
|
//function ttrace(v:Dynamic, ?infos : Null<haxe.PosInfos>) {
|
||||||
@@ -1975,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;
|
||||||
@@ -2004,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;
|
||||||
@@ -2080,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) {
|
||||||
@@ -2136,16 +2344,23 @@ class Parser {
|
|||||||
invalidChar(char);
|
invalidChar(char);
|
||||||
default:
|
default:
|
||||||
if( ops[char] ) {
|
if( ops[char] ) {
|
||||||
var op = 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 = buf.toString();
|
||||||
|
buf.addChar(char);
|
||||||
|
var op = buf.toString();
|
||||||
|
if( allowRegex && op == "~/" ) {
|
||||||
|
var e = readString(char, true);
|
||||||
|
var f = readFlags();
|
||||||
|
return TRegex(e, f);
|
||||||
}
|
}
|
||||||
var pop = op;
|
|
||||||
op += String.fromCharCode(char);
|
|
||||||
if( !opPriority.exists(op) && opPriority.exists(pop) ) {
|
if( !opPriority.exists(op) && opPriority.exists(pop) ) {
|
||||||
if( op == "//" || op == "/*" )
|
if( op == "//" || op == "/*" )
|
||||||
return tokenComment(op,char);
|
return tokenComment(op,char);
|
||||||
@@ -2155,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);
|
||||||
@@ -2187,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 {
|
||||||
@@ -2202,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);
|
||||||
}
|
}
|
||||||
@@ -2222,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);
|
||||||
@@ -2336,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2360,6 +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';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+494
-462
@@ -1,462 +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 EImport(c, n, u):
|
case EPackage(n):
|
||||||
add('${u ? 'using' : 'import'} $c');
|
add('package');
|
||||||
if(n != null)
|
if(n != null)
|
||||||
add(' as $n');
|
add(' $n');
|
||||||
case EClass(name, fields, extend, interfaces, fnal):
|
add(';\n');
|
||||||
var isFinal = fnal != null && fnal;
|
case EImport(c, n, u):
|
||||||
if(isFinal)
|
add('${u ? 'using' : 'import'} $c');
|
||||||
add('final ');
|
if(n != null)
|
||||||
add('class $name');
|
add(' as $n');
|
||||||
if (extend != null)
|
case EClass(name, fields, extend, interfaces, fnal):
|
||||||
add(' extends $extend');
|
var isFinal = fnal != null && fnal;
|
||||||
for(_interface in interfaces) {
|
if(isFinal)
|
||||||
add(' implements $_interface');
|
add('final ');
|
||||||
}
|
add('class $name');
|
||||||
tabs += "\t";
|
if (extend != null)
|
||||||
add(" {\n");
|
add(' extends $extend');
|
||||||
for( e in fields ) {
|
for(_interface in interfaces) {
|
||||||
add(tabs);
|
add(' implements $_interface');
|
||||||
expr(e);
|
}
|
||||||
//add(";\n");
|
tabs += "\t";
|
||||||
}
|
add(" {\n");
|
||||||
//for(field in fields) {
|
for( e in fields ) {
|
||||||
// expr(field);
|
add(tabs);
|
||||||
//}
|
expr(e);
|
||||||
|
//add(";\n");
|
||||||
tabs = tabs.substr(1);
|
}
|
||||||
add("}");
|
//for(field in fields) {
|
||||||
case EEnum(en, _): // TODO: enum abstracts
|
// expr(field);
|
||||||
add('enum ${en.name}');
|
//}
|
||||||
if(en.fields.length == 0) {
|
|
||||||
add(' {}');
|
tabs = tabs.substr(1);
|
||||||
return;
|
add("}");
|
||||||
}
|
case EEnum(en, isAbstract):
|
||||||
tabs += "\t";
|
if(isAbstract) {
|
||||||
add(" {\n");
|
add('enum abstract ${en.name}(');
|
||||||
|
if(en.underlyingType != null)
|
||||||
for(e in en.fields) {
|
type(en.underlyingType);
|
||||||
add(tabs);
|
else
|
||||||
add(e.name);
|
add('Int');
|
||||||
if(e.args.length > 0) {
|
add(')');
|
||||||
add("(");
|
if(en.fields.length == 0) {
|
||||||
var first = true;
|
add(' {}');
|
||||||
for( a in e.args ) {
|
return;
|
||||||
if( first ) first = false else add(", ");
|
}
|
||||||
if( a.opt ) add("?");
|
tabs += "\t";
|
||||||
add(a.name);
|
add(" {\n");
|
||||||
addType(a.t);
|
for(e in en.fields) {
|
||||||
}
|
add(tabs);
|
||||||
add(')');
|
add(e.name);
|
||||||
}
|
if(e.value != null) {
|
||||||
add(";\n");
|
add(" = ");
|
||||||
}
|
expr(e.value);
|
||||||
|
}
|
||||||
tabs = tabs.substr(1);
|
add(";\n");
|
||||||
add("}");
|
}
|
||||||
case ECast(e, t):
|
tabs = tabs.substr(1);
|
||||||
var safe = t != null;
|
add("}");
|
||||||
add("cast ");
|
} else {
|
||||||
if(safe) add("(");
|
add('enum ${en.name}');
|
||||||
expr(e);
|
if(en.fields.length == 0) {
|
||||||
if(safe) {
|
add(' {}');
|
||||||
add(", ");
|
return;
|
||||||
addType(t);
|
}
|
||||||
add(")");
|
tabs += "\t";
|
||||||
}
|
add(" {\n");
|
||||||
case EConst(c):
|
for(e in en.fields) {
|
||||||
switch( c ) {
|
add(tabs);
|
||||||
case CInt(i): add(i);
|
add(e.name);
|
||||||
case CFloat(f): add(f);
|
if(e.args.length > 0) {
|
||||||
case CString(s): add('"'); add(s.split('"').join('\\"').split("\n").join("\\n").split("\r").join("\\r").split("\t").join("\\t")); add('"');
|
add("(");
|
||||||
}
|
var first = true;
|
||||||
case EIdent(v):
|
for( a in e.args ) {
|
||||||
add(v);
|
if( first ) first = false else add(", ");
|
||||||
case EVar(n, t, e, p, s, pr, isFinal, isInline, get, set, _):
|
if( a.opt ) add("?");
|
||||||
if(p) add("public ");
|
add(a.name);
|
||||||
else if(pr) add("private ");
|
addType(a.t);
|
||||||
if(s) add("static ");
|
}
|
||||||
if(isInline) add("inline ");
|
add(')');
|
||||||
if(isFinal) add("final " + n);
|
}
|
||||||
else add("var " + n);
|
add(";\n");
|
||||||
|
}
|
||||||
if(get != null || set != null) {
|
tabs = tabs.substr(1);
|
||||||
add("(");
|
add("}");
|
||||||
switch(get) {
|
}
|
||||||
case ADefault: add("default, ");
|
case ECast(e, t):
|
||||||
case ANull: add("null, ");
|
var safe = t != null;
|
||||||
case AGet: add("get, ");
|
add("cast ");
|
||||||
case ADynamic: add("dynamic, ");
|
if(safe) add("(");
|
||||||
case ANever: add("never, ");
|
expr(e);
|
||||||
default:
|
if(safe) {
|
||||||
}
|
add(", ");
|
||||||
switch(set) {
|
addType(t);
|
||||||
case ADefault: add("default");
|
add(")");
|
||||||
case ANull: add("null");
|
}
|
||||||
case ASet: add("set");
|
case ERegex(e, f):
|
||||||
case ADynamic: add("dynamic");
|
add('~/$e/$f');
|
||||||
case ANever: add("never");
|
add(';\n');
|
||||||
default:
|
case EConst(c):
|
||||||
}
|
switch( c ) {
|
||||||
add(")");
|
case CInt(i): add(i);
|
||||||
}
|
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('"');
|
||||||
addType(t);
|
}
|
||||||
if( e != null ) {
|
case EIdent(v):
|
||||||
add(" = ");
|
add(v);
|
||||||
expr(e);
|
case EVar(n, t, e, p, s, pr, isFinal, isInline, get, set, _):
|
||||||
}
|
if(p) add("public ");
|
||||||
case EParent(e):
|
else if(pr) add("private ");
|
||||||
add("("); expr(e); add(")");
|
if(s) add("static ");
|
||||||
case EBlock(el):
|
if(isInline) add("inline ");
|
||||||
if( el.length == 0 ) {
|
if(isFinal) add("final " + n);
|
||||||
add("{}");
|
else add("var " + n);
|
||||||
} else {
|
|
||||||
tabs += "\t";
|
if(get != null || set != null) {
|
||||||
add("{\n");
|
add("(");
|
||||||
for( e in el ) {
|
switch(get) {
|
||||||
add(tabs);
|
case ADefault: add("default, ");
|
||||||
expr(e);
|
case ANull: add("null, ");
|
||||||
add(";\n");
|
case AGet: add("get, ");
|
||||||
}
|
case ADynamic: add("dynamic, ");
|
||||||
tabs = tabs.substr(1);
|
case ANever: add("never, ");
|
||||||
add("}");
|
default:
|
||||||
}
|
}
|
||||||
case EField(e, f, s):
|
switch(set) {
|
||||||
expr(e);
|
case ADefault: add("default");
|
||||||
add((s == true ? "?." : ".") + f);
|
case ANull: add("null");
|
||||||
case EBinop(op, e1, e2):
|
case ASet: add("set");
|
||||||
expr(e1);
|
case ADynamic: add("dynamic");
|
||||||
add(" " + op + " ");
|
case ANever: add("never");
|
||||||
expr(e2);
|
default:
|
||||||
case EUnop(op, pre, e):
|
}
|
||||||
if( pre ) {
|
add(")");
|
||||||
add(op);
|
}
|
||||||
expr(e);
|
|
||||||
} else {
|
addType(t);
|
||||||
expr(e);
|
if( e != null ) {
|
||||||
add(op);
|
add(" = ");
|
||||||
}
|
expr(e);
|
||||||
case ECall(e, args):
|
}
|
||||||
if( e == null )
|
case EParent(e):
|
||||||
expr(e);
|
add("("); expr(e); add(")");
|
||||||
else switch( Tools.expr(e)) {
|
case EBlock(el):
|
||||||
case EField(_), EIdent(_), EConst(_):
|
if( el.length == 0 ) {
|
||||||
expr(e);
|
add("{}");
|
||||||
default:
|
} else {
|
||||||
add("(");
|
tabs += "\t";
|
||||||
expr(e);
|
add("{\n");
|
||||||
add(")");
|
for( e in el ) {
|
||||||
}
|
add(tabs);
|
||||||
add("(");
|
expr(e);
|
||||||
var first = true;
|
add(";\n");
|
||||||
for( a in args ) {
|
}
|
||||||
if( first ) first = false else add(", ");
|
tabs = tabs.substr(1);
|
||||||
expr(a);
|
add("}");
|
||||||
}
|
}
|
||||||
add(")");
|
case EField(e, f, s):
|
||||||
case EIf(cond,e1,e2):
|
expr(e);
|
||||||
add("if( ");
|
add((s == true ? "?." : ".") + f);
|
||||||
expr(cond);
|
case EBinop(op, e1, e2):
|
||||||
add(" ) ");
|
expr(e1);
|
||||||
expr(e1);
|
add(" " + op.toString() + " ");
|
||||||
if( e2 != null ) {
|
expr(e2);
|
||||||
add(" else ");
|
case EUnop(op, pre, e):
|
||||||
expr(e2);
|
if( pre ) {
|
||||||
}
|
add(op);
|
||||||
case EWhile(cond,e):
|
expr(e);
|
||||||
add("while( ");
|
} else {
|
||||||
expr(cond);
|
expr(e);
|
||||||
add(" ) ");
|
add(op);
|
||||||
expr(e);
|
}
|
||||||
case EDoWhile(cond,e):
|
case ECall(e, args):
|
||||||
add("do ");
|
if( e == null )
|
||||||
expr(e);
|
expr(e);
|
||||||
add(" while ( ");
|
else switch( Tools.expr(e)) {
|
||||||
expr(cond);
|
case EField(_), EIdent(_), EConst(_):
|
||||||
add(" )");
|
expr(e);
|
||||||
case EFor(v, it, e, ithv):
|
default:
|
||||||
if(ithv != null)
|
add("(");
|
||||||
add("for( "+ithv+" => "+v+" in ");
|
expr(e);
|
||||||
else
|
add(")");
|
||||||
add("for( "+v+" in ");
|
}
|
||||||
expr(it);
|
add("(");
|
||||||
add(" ) ");
|
var first = true;
|
||||||
expr(e);
|
for( a in args ) {
|
||||||
case EBreak:
|
if( first ) first = false else add(", ");
|
||||||
add("break");
|
expr(a);
|
||||||
case EContinue:
|
}
|
||||||
add("continue");
|
add(")");
|
||||||
case EFunction(params, e, name, ret): // TODO: static, public, override
|
case EIf(cond,e1,e2):
|
||||||
add("function");
|
add("if( ");
|
||||||
if( name != null )
|
expr(cond);
|
||||||
add(" " + name);
|
add(" ) ");
|
||||||
add("(");
|
expr(e1);
|
||||||
var first = true;
|
if( e2 != null ) {
|
||||||
for( a in params ) {
|
add(" else ");
|
||||||
if( first ) first = false else add(", ");
|
expr(e2);
|
||||||
if( a.opt ) add("?");
|
}
|
||||||
add(a.name);
|
case EWhile(cond,e):
|
||||||
addType(a.t);
|
add("while( ");
|
||||||
}
|
expr(cond);
|
||||||
add(")");
|
add(" ) ");
|
||||||
addType(ret);
|
expr(e);
|
||||||
add(" ");
|
case EDoWhile(cond,e):
|
||||||
expr(e);
|
add("do ");
|
||||||
case EReturn(e):
|
expr(e);
|
||||||
add("return");
|
add(" while ( ");
|
||||||
if( e != null ) {
|
expr(cond);
|
||||||
add(" ");
|
add(" )");
|
||||||
expr(e);
|
case EFor(v, it, e, ithv):
|
||||||
}
|
if(ithv != null)
|
||||||
case EArray(e,index):
|
add("for( "+ithv+" => "+v+" in ");
|
||||||
expr(e);
|
else
|
||||||
add("[");
|
add("for( "+v+" in ");
|
||||||
expr(index);
|
expr(it);
|
||||||
add("]");
|
add(" ) ");
|
||||||
case EArrayDecl(el, _):
|
expr(e);
|
||||||
add("[");
|
case EBreak:
|
||||||
var first = true;
|
add("break");
|
||||||
for( e in el ) {
|
case EContinue:
|
||||||
if( first ) first = false else add(", ");
|
add("continue");
|
||||||
expr(e);
|
case EFunction(params, e, name, ret): // TODO: static, public, override
|
||||||
}
|
add("function");
|
||||||
add("]");
|
if( name != null )
|
||||||
case ENew(cl, args, params):
|
add(" " + name);
|
||||||
add("new " + cl);
|
add("(");
|
||||||
if(params != null) {
|
var first = true;
|
||||||
add("<");
|
for( a in params ) {
|
||||||
var first = true;
|
if( first ) first = false else add(", ");
|
||||||
for( p in params ) {
|
if( a.opt ) add("?");
|
||||||
if( first ) first = false else add(", ");
|
add(a.name);
|
||||||
type(p);
|
addType(a.t);
|
||||||
}
|
}
|
||||||
add(">");
|
add(")");
|
||||||
}
|
addType(ret);
|
||||||
add("(");
|
add(" ");
|
||||||
var first = true;
|
expr(e);
|
||||||
for( e in args ) {
|
case EReturn(e):
|
||||||
if( first ) first = false else add(", ");
|
add("return");
|
||||||
expr(e);
|
if( e != null ) {
|
||||||
}
|
add(" ");
|
||||||
add(")");
|
expr(e);
|
||||||
case EThrow(e):
|
}
|
||||||
add("throw ");
|
case EArray(e,index):
|
||||||
expr(e);
|
expr(e);
|
||||||
case ETry(e, v, t, ecatch):
|
add("[");
|
||||||
add("try ");
|
expr(index);
|
||||||
expr(e);
|
add("]");
|
||||||
add(" catch( " + v);
|
case EArrayDecl(el, _):
|
||||||
addType(t);
|
add("[");
|
||||||
add(") ");
|
var first = true;
|
||||||
expr(ecatch);
|
for( e in el ) {
|
||||||
case EObject(fl):
|
if( first ) first = false else add(", ");
|
||||||
if( fl.length == 0 ) {
|
expr(e);
|
||||||
add("{}");
|
}
|
||||||
} else {
|
add("]");
|
||||||
tabs += "\t";
|
case ENew(cl, args, params):
|
||||||
add("{\n");
|
add("new " + cl);
|
||||||
for( f in fl ) {
|
if(params != null) {
|
||||||
add(tabs);
|
add("<");
|
||||||
add(f.name+" : ");
|
var first = true;
|
||||||
expr(f.e);
|
for( p in params ) {
|
||||||
add(",\n");
|
if( first ) first = false else add(", ");
|
||||||
}
|
type(p);
|
||||||
tabs = tabs.substr(1);
|
}
|
||||||
add("}");
|
add(">");
|
||||||
}
|
}
|
||||||
case ETernary(c,e1,e2):
|
add("(");
|
||||||
expr(c);
|
var first = true;
|
||||||
add(" ? ");
|
for( e in args ) {
|
||||||
expr(e1);
|
if( first ) first = false else add(", ");
|
||||||
add(" : ");
|
expr(e);
|
||||||
expr(e2);
|
}
|
||||||
case ESwitch(e, cases, def):
|
add(")");
|
||||||
add("switch( ");
|
case EThrow(e):
|
||||||
expr(e);
|
add("throw ");
|
||||||
add(") {");
|
expr(e);
|
||||||
for( c in cases ) {
|
case ETry(e, v, t, ecatch):
|
||||||
add("case ");
|
add("try ");
|
||||||
var first = true;
|
expr(e);
|
||||||
for( v in c.values ) {
|
add(" catch( " + v);
|
||||||
if( first ) first = false else add(", ");
|
addType(t);
|
||||||
expr(v);
|
add(") ");
|
||||||
}
|
expr(ecatch);
|
||||||
add(": ");
|
case EObject(fl):
|
||||||
expr(c.expr);
|
if( fl.length == 0 ) {
|
||||||
add(";\n");
|
add("{}");
|
||||||
}
|
} else {
|
||||||
if( def != null ) {
|
tabs += "\t";
|
||||||
add("default: ");
|
add("{\n");
|
||||||
expr(def);
|
for( f in fl ) {
|
||||||
add(";\n");
|
add(tabs);
|
||||||
}
|
add(f.name+" : ");
|
||||||
add("}");
|
expr(f.e);
|
||||||
case EMeta(name, args, e):
|
add(",\n");
|
||||||
add("@");
|
}
|
||||||
add(name);
|
tabs = tabs.substr(1);
|
||||||
if( args != null && args.length > 0 ) {
|
add("}");
|
||||||
add("(");
|
}
|
||||||
var first = true;
|
case ETernary(c,e1,e2):
|
||||||
for( a in args ) {
|
expr(c);
|
||||||
if( first ) first = false else add(", ");
|
add(" ? ");
|
||||||
expr(e);
|
expr(e1);
|
||||||
}
|
add(" : ");
|
||||||
add(")");
|
expr(e2);
|
||||||
}
|
case ESwitch(e, cases, def):
|
||||||
add(" ");
|
add("switch( ");
|
||||||
expr(e);
|
expr(e);
|
||||||
case ECheckType(e, t):
|
add(") {");
|
||||||
add("(");
|
for( c in cases ) {
|
||||||
expr(e);
|
add("case ");
|
||||||
add(" : ");
|
var first = true;
|
||||||
addType(t);
|
for( v in c.values ) {
|
||||||
add(")");
|
if( first ) first = false else add(", ");
|
||||||
}
|
expr(v);
|
||||||
}
|
}
|
||||||
|
add(": ");
|
||||||
public static function toString( e : Expr ):String {
|
expr(c.expr);
|
||||||
return new Printer().exprToString(e);
|
add(";\n");
|
||||||
}
|
}
|
||||||
|
if( def != null ) {
|
||||||
public static function errorToString( e : Expr.Error ):String {
|
add("default: ");
|
||||||
var message = switch( #if hscriptPos e.e #else e #end ) {
|
expr(def);
|
||||||
case EInvalidChar(c): "Invalid character: '"+(StringTools.isEof(c) ? "EOF (End Of File)" : String.fromCharCode(c))+"' ("+c+")";
|
add(";\n");
|
||||||
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
}
|
||||||
case EUnterminatedString: "Unterminated string";
|
add("}");
|
||||||
case EUnterminatedComment: "Unterminated comment";
|
case EMeta(name, args, e):
|
||||||
case EInvalidPreprocessor(str): "Invalid preprocessor (" + str + ")";
|
add("@");
|
||||||
case EUnknownVariable(v): "Unknown variable: "+v;
|
add(name);
|
||||||
case EInvalidIterator(v): "Invalid iterator: "+v;
|
if( args != null && args.length > 0 ) {
|
||||||
case EInvalidOp(op): "Invalid operator: "+op;
|
add("(");
|
||||||
case EInvalidAccess(f): "Invalid access to field " + f;
|
var first = true;
|
||||||
case ECustom(msg): msg;
|
for( a in args ) {
|
||||||
case EInvalidClass(cla): "Invalid class: " + cla + " was not found.";
|
if( first ) first = false else add(", ");
|
||||||
case EAlreadyExistingClass(cla): 'Custom Class named $cla already exists.';
|
expr(e);
|
||||||
};
|
}
|
||||||
#if hscriptPos
|
add(")");
|
||||||
return e.origin + ":" + e.line + ": " + message;
|
}
|
||||||
#else
|
add(" ");
|
||||||
return message;
|
expr(e);
|
||||||
#end
|
case ECheckType(e, t):
|
||||||
}
|
add("(");
|
||||||
|
expr(e);
|
||||||
|
add(" : ");
|
||||||
}
|
addType(t);
|
||||||
|
add(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
+83
-19
@@ -26,39 +26,98 @@ 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 SET = 'set_';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the attached field.
|
||||||
|
*/
|
||||||
|
public final name:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current value. If isn't initialized, it's always `null`.
|
||||||
|
*/
|
||||||
public var r:Dynamic;
|
public var r:Dynamic;
|
||||||
public var getter:FieldPropertyAccess;
|
|
||||||
public var setter:FieldPropertyAccess;
|
/**
|
||||||
|
* 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;
|
||||||
|
function get_isStatic() {
|
||||||
|
return __isStatic && interp.allowStaticVariables;
|
||||||
|
}
|
||||||
|
|
||||||
var isVar:Bool;
|
var isVar:Bool;
|
||||||
var interp:Interp;
|
var interp:Interp;
|
||||||
|
|
||||||
public function new(r:Dynamic, getter:FieldPropertyAccess, setter:FieldPropertyAccess, isVar: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;
|
||||||
this.isVar = isVar;
|
this.isVar = isVar;
|
||||||
|
this.__isStatic = isStatic;
|
||||||
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;
|
||||||
|
|
||||||
public function callGetter(name:String) {
|
final __isStatic:Bool = false;
|
||||||
|
|
||||||
|
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 (interp.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' : ''}'));
|
||||||
}
|
}
|
||||||
@@ -70,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 (interp.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' : ''}'));
|
||||||
}
|
}
|
||||||
@@ -93,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 = 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;
|
||||||
@@ -111,4 +171,8 @@ class Property {
|
|||||||
|
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline function varExists(n:String) {
|
||||||
|
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