forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
314
Kha/Tools/linux_arm64/std/haxe/macro/ExprTools.hx
Normal file
314
Kha/Tools/linux_arm64/std/haxe/macro/ExprTools.hx
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (C)2005-2019 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* 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:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package haxe.macro;
|
||||
|
||||
import haxe.macro.Expr;
|
||||
|
||||
using Lambda;
|
||||
|
||||
/**
|
||||
This class provides some utility methods to work with expressions. It is
|
||||
best used through 'using haxe.macro.ExprTools' syntax and then provides
|
||||
additional methods on haxe.macro.Expr instances.
|
||||
|
||||
While mainly intended to be used in macros, it works in non-macro code as
|
||||
well.
|
||||
**/
|
||||
class ExprTools {
|
||||
/**
|
||||
Converts expression `e` to a human-readable String representation.
|
||||
|
||||
The result is guaranteed to be valid Haxe code, but there may be
|
||||
differences from the original lexical syntax.
|
||||
**/
|
||||
static public function toString(e:Expr):String
|
||||
return new Printer().printExpr(e);
|
||||
|
||||
/**
|
||||
Calls function `f` on each sub-expression of `e`.
|
||||
|
||||
If `e` has no sub-expressions, this operation has no effect.
|
||||
|
||||
Otherwise `f` is called once per sub-expression of `e`, with the
|
||||
sub-expression as argument. These calls are done in order of the
|
||||
sub-expression declarations.
|
||||
|
||||
This method does not call itself recursively. It should instead be used
|
||||
in a recursive function which handles the expression nodes of interest.
|
||||
|
||||
Usage example:
|
||||
```haxe
|
||||
function findStrings(e:Expr) {
|
||||
switch(e.expr) {
|
||||
case EConst(CString(s)):
|
||||
// handle s
|
||||
case _:
|
||||
ExprTools.iter(e, findStrings);
|
||||
}
|
||||
}
|
||||
```
|
||||
**/
|
||||
static public function iter(e:Expr, f:Expr->Void):Void {
|
||||
switch (e.expr) {
|
||||
case EConst(_), EContinue, EBreak, EDisplayNew(_):
|
||||
case EField(e, _), EParenthesis(e), EUntyped(e), EThrow(e), EDisplay(e, _), ECheckType(e, _), EUnop(_, _, e), ECast(e, _), EIs(e, _) | EMeta(_, e):
|
||||
f(e);
|
||||
case EArray(e1, e2), EWhile(e1, e2, _), EBinop(_, e1, e2), EFor(e1, e2):
|
||||
f(e1);
|
||||
f(e2);
|
||||
case EVars(vl):
|
||||
for (v in vl)
|
||||
opt2(v.expr, f);
|
||||
case ETry(e, cl):
|
||||
f(e);
|
||||
for (c in cl)
|
||||
f(c.expr);
|
||||
case ETernary(e1, e2, e3) | EIf(e1, e2, e3):
|
||||
f(e1);
|
||||
f(e2);
|
||||
opt2(e3, f);
|
||||
case EArrayDecl(el), ENew(_, el), EBlock(el):
|
||||
ExprArrayTools.iter(el, f);
|
||||
case EObjectDecl(fl):
|
||||
for (fd in fl)
|
||||
f(fd.expr);
|
||||
case ECall(e, el):
|
||||
f(e);
|
||||
ExprArrayTools.iter(el, f);
|
||||
case EReturn(e):
|
||||
opt2(e, f);
|
||||
case EFunction(_, func):
|
||||
for (arg in func.args)
|
||||
opt2(arg.value, f);
|
||||
opt2(func.expr, f);
|
||||
case ESwitch(e, cl, edef):
|
||||
f(e);
|
||||
for (c in cl) {
|
||||
ExprArrayTools.iter(c.values, f);
|
||||
opt2(c.guard, f);
|
||||
opt2(c.expr, f);
|
||||
}
|
||||
if (edef != null && edef.expr != null)
|
||||
f(edef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Transforms the sub-expressions of `e` by calling `f` on each of them.
|
||||
|
||||
If `e` has no sub-expressions, this operation returns `e` unchanged.
|
||||
|
||||
Otherwise `f` is called once per sub-expression of `e`, with the
|
||||
sub-expression as argument. These calls are done in order of the
|
||||
sub-expression declarations.
|
||||
|
||||
This method does not call itself recursively. It should instead be used
|
||||
in a recursive function which handles the expression nodes of interest.
|
||||
|
||||
Usage example:
|
||||
```haxe
|
||||
function capitalizeStrings(e:Expr) {
|
||||
return switch(e.expr) {
|
||||
case EConst(CString(s)):
|
||||
{ expr: EConst(CString(s.toUpperCase())), pos: e.pos };
|
||||
case _:
|
||||
ExprTools.map(e, capitalizeStrings);
|
||||
}
|
||||
}
|
||||
```
|
||||
**/
|
||||
static public function map(e:Expr, f:Expr->Expr):Expr {
|
||||
return {
|
||||
pos: e.pos,
|
||||
expr: switch (e.expr) {
|
||||
case EConst(_): e.expr;
|
||||
case EArray(e1, e2): EArray(f(e1), f(e2));
|
||||
case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2));
|
||||
case EField(e, field): EField(f(e), field);
|
||||
case EParenthesis(e): EParenthesis(f(e));
|
||||
case EObjectDecl(fields):
|
||||
var ret = [];
|
||||
for (field in fields)
|
||||
ret.push({field: field.field, expr: f(field.expr), quotes: field.quotes});
|
||||
EObjectDecl(ret);
|
||||
case EArrayDecl(el): EArrayDecl(ExprArrayTools.map(el, f));
|
||||
case ECall(e, params): ECall(f(e), ExprArrayTools.map(params, f));
|
||||
case ENew(tp, params): ENew(tp, ExprArrayTools.map(params, f));
|
||||
case EUnop(op, postFix, e): EUnop(op, postFix, f(e));
|
||||
case EVars(vars):
|
||||
var ret = [];
|
||||
for (v in vars) {
|
||||
var v2:Var = {name: v.name, type: v.type, expr: opt(v.expr, f)};
|
||||
if (v.isFinal != null)
|
||||
v2.isFinal = v.isFinal;
|
||||
ret.push(v2);
|
||||
}
|
||||
EVars(ret);
|
||||
case EBlock(el): EBlock(ExprArrayTools.map(el, f));
|
||||
case EFor(it, expr): EFor(f(it), f(expr));
|
||||
case EIf(econd, eif, eelse): EIf(f(econd), f(eif), opt(eelse, f));
|
||||
case EWhile(econd, e, normalWhile): EWhile(f(econd), f(e), normalWhile);
|
||||
case EReturn(e): EReturn(opt(e, f));
|
||||
case EUntyped(e): EUntyped(f(e));
|
||||
case EThrow(e): EThrow(f(e));
|
||||
case ECast(e, t): ECast(f(e), t);
|
||||
case EIs(e, t): EIs(f(e), t);
|
||||
case EDisplay(e, dk): EDisplay(f(e), dk);
|
||||
case ETernary(econd, eif, eelse): ETernary(f(econd), f(eif), f(eelse));
|
||||
case ECheckType(e, t): ECheckType(f(e), t);
|
||||
case EDisplayNew(_), EContinue, EBreak:
|
||||
e.expr;
|
||||
case ETry(e, catches):
|
||||
var ret = [];
|
||||
for (c in catches)
|
||||
ret.push({name: c.name, type: c.type, expr: f(c.expr)});
|
||||
ETry(f(e), ret);
|
||||
case ESwitch(e, cases, edef):
|
||||
var ret = [];
|
||||
for (c in cases)
|
||||
ret.push({expr: opt(c.expr, f), guard: opt(c.guard, f), values: ExprArrayTools.map(c.values, f)});
|
||||
ESwitch(f(e), ret, edef == null || edef.expr == null ? edef : f(edef));
|
||||
case EFunction(kind, func):
|
||||
var ret = [];
|
||||
for (arg in func.args)
|
||||
ret.push({
|
||||
name: arg.name,
|
||||
opt: arg.opt,
|
||||
type: arg.type,
|
||||
value: opt(arg.value, f)
|
||||
});
|
||||
EFunction(kind, {
|
||||
args: ret,
|
||||
ret: func.ret,
|
||||
params: func.params,
|
||||
expr: f(func.expr)
|
||||
});
|
||||
case EMeta(m, e): EMeta(m, f(e));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value `e` represents.
|
||||
|
||||
Supported expressions are:
|
||||
|
||||
- `Int`, `Float` and `String` literals
|
||||
- identifiers `true`, `false` and `null`
|
||||
- structure declarations if all their fields are values
|
||||
- array declarations if all their elements are values
|
||||
- unary operators `-`, `!` and `~` if the operand is a value
|
||||
- binary operators except `=>`, `...` and assignments
|
||||
|
||||
Parentheses, metadata and the `untyped` keyword are ignored.
|
||||
|
||||
If any non-value is encountered, an exception of type `String` is
|
||||
thrown.
|
||||
|
||||
If `e` is null, the result is unspecified.
|
||||
**/
|
||||
static public function getValue(e:Expr):Dynamic {
|
||||
return switch (e.expr) {
|
||||
case EConst(CInt(v)): Std.parseInt(v);
|
||||
case EConst(CFloat(v)): Std.parseFloat(v);
|
||||
case EConst(CString(s)): s;
|
||||
case EConst(CIdent("true")): true;
|
||||
case EConst(CIdent("false")): false;
|
||||
case EConst(CIdent("null")): null;
|
||||
case EParenthesis(e1) | EUntyped(e1) | EMeta(_, e1): getValue(e1);
|
||||
case EObjectDecl(fields):
|
||||
var obj = {};
|
||||
for (field in fields) {
|
||||
Reflect.setField(obj, field.field, getValue(field.expr));
|
||||
}
|
||||
obj;
|
||||
case EArrayDecl(el): el.map(getValue);
|
||||
case EIf(econd, eif, eelse) | ETernary(econd, eif, eelse):
|
||||
if (eelse == null) {
|
||||
throw "If statements only have a value if the else clause is defined";
|
||||
} else {
|
||||
var econd:Dynamic = getValue(econd);
|
||||
econd ? getValue(eif) : getValue(eelse);
|
||||
}
|
||||
case EUnop(op, false, e1):
|
||||
var e1:Dynamic = getValue(e1);
|
||||
switch (op) {
|
||||
case OpNot: !e1;
|
||||
case OpNeg: -e1;
|
||||
case OpNegBits: ~e1;
|
||||
case _: throw 'Unsupported expression: $e';
|
||||
}
|
||||
case EBinop(op, e1, e2):
|
||||
var e1:Dynamic = getValue(e1);
|
||||
var e2:Dynamic = getValue(e2);
|
||||
switch (op) {
|
||||
case OpAdd: e1 + e2;
|
||||
case OpSub: e1 - e2;
|
||||
case OpMult: e1 * e2;
|
||||
case OpDiv: e1 / e2;
|
||||
case OpMod: e1 % e2;
|
||||
case OpEq: e1 == e2;
|
||||
case OpNotEq: e1 != e2;
|
||||
case OpLt: e1 < e2;
|
||||
case OpLte: e1 <= e2;
|
||||
case OpGt: e1 > e2;
|
||||
case OpGte: e1 >= e2;
|
||||
case OpOr: e1 | e2;
|
||||
case OpAnd: e1 & e2;
|
||||
case OpXor: e1 ^ e2;
|
||||
case OpBoolAnd: e1 && e2;
|
||||
case OpBoolOr: e1 || e2;
|
||||
case OpShl: e1 << e2;
|
||||
case OpShr: e1 >> e2;
|
||||
case OpUShr: e1 >>> e2;
|
||||
case _: throw 'Unsupported expression: $e';
|
||||
}
|
||||
case _: throw 'Unsupported expression: $e';
|
||||
}
|
||||
}
|
||||
|
||||
static inline function opt(e:Null<Expr>, f:Expr->Expr):Expr
|
||||
return e == null ? null : f(e);
|
||||
|
||||
static inline function opt2(e:Null<Expr>, f:Expr->Void):Void
|
||||
if (e != null)
|
||||
f(e);
|
||||
}
|
||||
|
||||
/**
|
||||
This class provides functions on expression arrays for convenience. For a
|
||||
detailed reference on each method, see the documentation of ExprTools.
|
||||
**/
|
||||
class ExprArrayTools {
|
||||
static public function map(el:Array<Expr>, f:Expr->Expr):Array<Expr> {
|
||||
var ret = [];
|
||||
for (e in el)
|
||||
ret.push(f(e));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static public function iter(el:Array<Expr>, f:Expr->Void):Void {
|
||||
for (e in el)
|
||||
f(e);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user