exprReturn repair

This commit is contained in:
HEIHUAa
2026-04-09 20:12:53 +08:00
parent aa38e73beb
commit 61edb9cc5c
4 changed files with 708 additions and 641 deletions
+63
View File
@@ -0,0 +1,63 @@
import haxe.Timer;
import hscript.Interp;
import hscript.Parser;
class PerfTest {
static function main() {
var parser = new Parser();
parser.allowTypes = true;
var testScript = "
var sum = 0;
var a = 1;
var b = 2;
var c = 3;
for (i in 0...10000) {
sum = sum + a * b + c - a / b;
a = a + 1;
b = b + 1;
c = c + 1;
if (sum > 1000000) sum = 0;
if (a > 100) a = 1;
if (b > 200) b = 2;
if (c > 300) c = 3;
}
sum;
";
var program = parser.parseString(testScript);
var interp = new Interp();
interp.variables.set("Math", Math);
var iterations = 100;
Sys.println("=== Fast Binops (switch) Mode ===");
var totalTests = 5;
var times:Array<Float> = [];
for (testNum in 0...totalTests) {
var interp = new Interp();
interp.variables.set("Math", Math);
var startTime = Timer.stamp();
for (i in 0...iterations) {
interp.execute(program);
}
var endTime = Timer.stamp();
var elapsed = endTime - startTime;
times.push(elapsed);
Sys.println('Test ${testNum + 1}: ${Std.string(elapsed * 1000).substr(0, 8)} ms');
}
var avg = Lambda.fold(times, function(a, b) return a + b, 0.0) / times.length;
var minTime = Lambda.fold(times, function(a, b) return a < b ? a : b, times[0]);
var maxTime = Lambda.fold(times, function(a, b) return a > b ? a : b, times[0]);
Sys.println("");
Sys.println('Average: ${Std.string(avg * 1000).substr(0, 8)} ms');
Sys.println('Min: ${Std.string(minTime * 1000).substr(0, 8)} ms');
Sys.println('Max: ${Std.string(maxTime * 1000).substr(0, 8)} ms');
}
}
+8 -4
View File
@@ -538,11 +538,15 @@ class Interp {
}
return null;
} catch (e:Dynamic) {
if (printCallStack) {
var stack = CallStack.exceptionStack(true);
error(ECustom(Std.string(e) + "\n" + CallStack.toString(stack)));
var errStr = printCallStack ? Std.string(e) + "\n" + CallStack.toString(CallStack.exceptionStack(true)) : Std.string(e);
if (errorHandler != null) {
#if hscriptPos
errorHandler(new Error(ECustom(errStr), curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line));
#else
errorHandler(new Error(ECustom(errStr)));
#end
} else {
error(ECustom(Std.string(e)));
throw e;
}
return null;
}
+494 -494
View File
@@ -1,494 +1,494 @@
/*
* Copyright (C)2008-2017 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 hscript;
import hscript.Expr;
class Printer {
var buf : StringBuf;
var tabs : String;
public function new() {
}
public function exprToString( e : Expr ):String {
buf = new StringBuf();
tabs = "";
expr(e);
return buf.toString();
}
public function typeToString( t : CType ):String {
buf = new StringBuf();
tabs = "";
type(t);
return buf.toString();
}
inline function add<T>(s:T):Void buf.add(s);
function type( t : CType ):Void {
switch( t ) {
case CTOpt(t):
add('?');
type(t);
case CTPath(path, params):
add(path.join("."));
if( params != null ) {
add("<");
var first = true;
for( p in params ) {
if( first ) first = false else add(", ");
type(p);
}
add(">");
}
case CTNamed(name, t):
add(name);
add(':');
type(t);
case CTFun(args, ret) if (Lambda.exists(args, function (a) return a.match(CTNamed(_, _)))):
add('(');
for (a in args)
switch a {
case CTNamed(_, _): type(a);
default: type(CTNamed('_', a));
}
add(')->');
type(ret);
case CTFun(args, ret):
if( args.length == 0 )
add("Void -> ");
else {
for( a in args ) {
type(a);
add(" -> ");
}
}
type(ret);
case CTAnon(fields):
add("{");
var first = true;
for( f in fields ) {
if( first ) { first = false; add(" "); } else add(", ");
add(f.name + " : ");
type(f.t);
}
add(first ? "}" : " }");
case CTParent(t):
add("(");
type(t);
add(")");
case CTExpr(e):
expr(e);
}
}
function addType( t : CType ):Void {
if( t != null ) {
add(" : ");
type(t);
}
}
function expr( e : Expr ):Void {
if( e == null ) {
add("??NULL??");
return;
}
switch(Tools.expr(e)) {
case EPackage(n):
add('package');
if(n != null)
add(' $n');
add(';\n');
case EImport(c, n, u):
add('${u ? 'using' : 'import'} $c');
if(n != null)
add(' as $n');
case EClass(name, fields, extend, interfaces, fnal):
var isFinal = fnal != null && fnal;
if(isFinal)
add('final ');
add('class $name');
if (extend != null)
add(' extends $extend');
for(_interface in interfaces) {
add(' implements $_interface');
}
tabs += "\t";
add(" {\n");
for( e in fields ) {
add(tabs);
expr(e);
//add(";\n");
}
//for(field in fields) {
// expr(field);
//}
tabs = tabs.substr(1);
add("}");
case EEnum(en, isAbstract):
if(isAbstract) {
add('enum abstract ${en.name}(');
if(en.underlyingType != null)
type(en.underlyingType);
else
add('Int');
add(')');
if(en.fields.length == 0) {
add(' {}');
return;
}
tabs += "\t";
add(" {\n");
for(e in en.fields) {
add(tabs);
add(e.name);
if(e.value != null) {
add(" = ");
expr(e.value);
}
add(";\n");
}
tabs = tabs.substr(1);
add("}");
} else {
add('enum ${en.name}');
if(en.fields.length == 0) {
add(' {}');
return;
}
tabs += "\t";
add(" {\n");
for(e in en.fields) {
add(tabs);
add(e.name);
if(e.args.length > 0) {
add("(");
var first = true;
for( a in e.args ) {
if( first ) first = false else add(", ");
if( a.opt ) add("?");
add(a.name);
addType(a.t);
}
add(')');
}
add(";\n");
}
tabs = tabs.substr(1);
add("}");
}
case ECast(e, t):
var safe = t != null;
add("cast ");
if(safe) add("(");
expr(e);
if(safe) {
add(", ");
addType(t);
add(")");
}
case ERegex(e, f):
add('~/$e/$f');
add(';\n');
case EConst(c):
switch( c ) {
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('"');
}
case EIdent(v):
add(v);
case EVar(n, t, e, p, s, pr, isFinal, isInline, get, set, _):
if(p) add("public ");
else if(pr) add("private ");
if(s) add("static ");
if(isInline) add("inline ");
if(isFinal) add("final " + n);
else add("var " + n);
if(get != null || set != null) {
add("(");
switch(get) {
case ADefault: add("default, ");
case ANull: add("null, ");
case AGet: add("get, ");
case ADynamic: add("dynamic, ");
case ANever: add("never, ");
default:
}
switch(set) {
case ADefault: add("default");
case ANull: add("null");
case ASet: add("set");
case ADynamic: add("dynamic");
case ANever: add("never");
default:
}
add(")");
}
addType(t);
if( e != null ) {
add(" = ");
expr(e);
}
case EParent(e):
add("("); expr(e); add(")");
case EBlock(el):
if( el.length == 0 ) {
add("{}");
} else {
tabs += "\t";
add("{\n");
for( e in el ) {
add(tabs);
expr(e);
add(";\n");
}
tabs = tabs.substr(1);
add("}");
}
case EField(e, f, s):
expr(e);
add((s == true ? "?." : ".") + f);
case EBinop(op, e1, e2):
expr(e1);
add(" " + op.toString() + " ");
expr(e2);
case EUnop(op, pre, e):
if( pre ) {
add(op);
expr(e);
} else {
expr(e);
add(op);
}
case ECall(e, args):
if( e == null )
expr(e);
else switch( Tools.expr(e)) {
case EField(_), EIdent(_), EConst(_):
expr(e);
default:
add("(");
expr(e);
add(")");
}
add("(");
var first = true;
for( a in args ) {
if( first ) first = false else add(", ");
expr(a);
}
add(")");
case EIf(cond,e1,e2):
add("if( ");
expr(cond);
add(" ) ");
expr(e1);
if( e2 != null ) {
add(" else ");
expr(e2);
}
case EWhile(cond,e):
add("while( ");
expr(cond);
add(" ) ");
expr(e);
case EDoWhile(cond,e):
add("do ");
expr(e);
add(" while ( ");
expr(cond);
add(" )");
case EFor(v, it, e, ithv):
if(ithv != null)
add("for( "+ithv+" => "+v+" in ");
else
add("for( "+v+" in ");
expr(it);
add(" ) ");
expr(e);
case EBreak:
add("break");
case EContinue:
add("continue");
case EFunction(params, e, name, ret): // TODO: static, public, override
add("function");
if( name != null )
add(" " + name);
add("(");
var first = true;
for( a in params ) {
if( first ) first = false else add(", ");
if( a.opt ) add("?");
add(a.name);
addType(a.t);
}
add(")");
addType(ret);
add(" ");
expr(e);
case EReturn(e):
add("return");
if( e != null ) {
add(" ");
expr(e);
}
case EArray(e,index):
expr(e);
add("[");
expr(index);
add("]");
case EArrayDecl(el, _):
add("[");
var first = true;
for( e in el ) {
if( first ) first = false else add(", ");
expr(e);
}
add("]");
case ENew(cl, args, params):
add("new " + cl);
if(params != null) {
add("<");
var first = true;
for( p in params ) {
if( first ) first = false else add(", ");
type(p);
}
add(">");
}
add("(");
var first = true;
for( e in args ) {
if( first ) first = false else add(", ");
expr(e);
}
add(")");
case EThrow(e):
add("throw ");
expr(e);
case ETry(e, v, t, ecatch):
add("try ");
expr(e);
add(" catch( " + v);
addType(t);
add(") ");
expr(ecatch);
case EObject(fl):
if( fl.length == 0 ) {
add("{}");
} else {
tabs += "\t";
add("{\n");
for( f in fl ) {
add(tabs);
add(f.name+" : ");
expr(f.e);
add(",\n");
}
tabs = tabs.substr(1);
add("}");
}
case ETernary(c,e1,e2):
expr(c);
add(" ? ");
expr(e1);
add(" : ");
expr(e2);
case ESwitch(e, cases, def):
add("switch( ");
expr(e);
add(") {");
for( c in cases ) {
add("case ");
var first = true;
for( v in c.values ) {
if( first ) first = false else add(", ");
expr(v);
}
add(": ");
expr(c.expr);
add(";\n");
}
if( def != null ) {
add("default: ");
expr(def);
add(";\n");
}
add("}");
case EMeta(name, args, e):
add("@");
add(name);
if( args != null && args.length > 0 ) {
add("(");
var first = true;
for( a in args ) {
if( first ) first = false else add(", ");
expr(e);
}
add(")");
}
add(" ");
expr(e);
case ECheckType(e, t):
add("(");
expr(e);
add(" : ");
addType(t);
add(")");
}
}
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
}
}
/*
* Copyright (C)2008-2017 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 hscript;
import hscript.Expr;
class Printer {
var buf : StringBuf;
var tabs : String;
public function new() {
}
public function exprToString( e : Expr ):String {
buf = new StringBuf();
tabs = "";
expr(e);
return buf.toString();
}
public function typeToString( t : CType ):String {
buf = new StringBuf();
tabs = "";
type(t);
return buf.toString();
}
inline function add<T>(s:T):Void buf.add(s);
function type( t : CType ):Void {
switch( t ) {
case CTOpt(t):
add('?');
type(t);
case CTPath(path, params):
add(path.join("."));
if( params != null ) {
add("<");
var first = true;
for( p in params ) {
if( first ) first = false else add(", ");
type(p);
}
add(">");
}
case CTNamed(name, t):
add(name);
add(':');
type(t);
case CTFun(args, ret) if (Lambda.exists(args, function (a) return a.match(CTNamed(_, _)))):
add('(');
for (a in args)
switch a {
case CTNamed(_, _): type(a);
default: type(CTNamed('_', a));
}
add(')->');
type(ret);
case CTFun(args, ret):
if( args.length == 0 )
add("Void -> ");
else {
for( a in args ) {
type(a);
add(" -> ");
}
}
type(ret);
case CTAnon(fields):
add("{");
var first = true;
for( f in fields ) {
if( first ) { first = false; add(" "); } else add(", ");
add(f.name + " : ");
type(f.t);
}
add(first ? "}" : " }");
case CTParent(t):
add("(");
type(t);
add(")");
case CTExpr(e):
expr(e);
}
}
function addType( t : CType ):Void {
if( t != null ) {
add(" : ");
type(t);
}
}
function expr( e : Expr ):Void {
if( e == null ) {
add("??NULL??");
return;
}
switch(Tools.expr(e)) {
case EPackage(n):
add('package');
if(n != null)
add(' $n');
add(';\n');
case EImport(c, n, u):
add('${u ? 'using' : 'import'} $c');
if(n != null)
add(' as $n');
case EClass(name, fields, extend, interfaces, fnal):
var isFinal = fnal != null && fnal;
if(isFinal)
add('final ');
add('class $name');
if (extend != null)
add(' extends $extend');
for(_interface in interfaces) {
add(' implements $_interface');
}
tabs += "\t";
add(" {\n");
for( e in fields ) {
add(tabs);
expr(e);
//add(";\n");
}
//for(field in fields) {
// expr(field);
//}
tabs = tabs.substr(1);
add("}");
case EEnum(en, isAbstract):
if(isAbstract) {
add('enum abstract ${en.name}(');
if(en.underlyingType != null)
type(en.underlyingType);
else
add('Int');
add(')');
if(en.fields.length == 0) {
add(' {}');
return;
}
tabs += "\t";
add(" {\n");
for(e in en.fields) {
add(tabs);
add(e.name);
if(e.value != null) {
add(" = ");
expr(e.value);
}
add(";\n");
}
tabs = tabs.substr(1);
add("}");
} else {
add('enum ${en.name}');
if(en.fields.length == 0) {
add(' {}');
return;
}
tabs += "\t";
add(" {\n");
for(e in en.fields) {
add(tabs);
add(e.name);
if(e.args.length > 0) {
add("(");
var first = true;
for( a in e.args ) {
if( first ) first = false else add(", ");
if( a.opt ) add("?");
add(a.name);
addType(a.t);
}
add(')');
}
add(";\n");
}
tabs = tabs.substr(1);
add("}");
}
case ECast(e, t):
var safe = t != null;
add("cast ");
if(safe) add("(");
expr(e);
if(safe) {
add(", ");
addType(t);
add(")");
}
case ERegex(e, f):
add('~/$e/$f');
add(';\n');
case EConst(c):
switch( c ) {
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('"');
}
case EIdent(v):
add(v);
case EVar(n, t, e, p, s, pr, isFinal, isInline, get, set, _):
if(p) add("public ");
else if(pr) add("private ");
if(s) add("static ");
if(isInline) add("inline ");
if(isFinal) add("final " + n);
else add("var " + n);
if(get != null || set != null) {
add("(");
switch(get) {
case ADefault: add("default, ");
case ANull: add("null, ");
case AGet: add("get, ");
case ADynamic: add("dynamic, ");
case ANever: add("never, ");
default:
}
switch(set) {
case ADefault: add("default");
case ANull: add("null");
case ASet: add("set");
case ADynamic: add("dynamic");
case ANever: add("never");
default:
}
add(")");
}
addType(t);
if( e != null ) {
add(" = ");
expr(e);
}
case EParent(e):
add("("); expr(e); add(")");
case EBlock(el):
if( el.length == 0 ) {
add("{}");
} else {
tabs += "\t";
add("{\n");
for( e in el ) {
add(tabs);
expr(e);
add(";\n");
}
tabs = tabs.substr(1);
add("}");
}
case EField(e, f, s):
expr(e);
add((s == true ? "?." : ".") + f);
case EBinop(op, e1, e2):
expr(e1);
add(" " + op.toString() + " ");
expr(e2);
case EUnop(op, pre, e):
if( pre ) {
add(op);
expr(e);
} else {
expr(e);
add(op);
}
case ECall(e, args):
if( e == null )
expr(e);
else switch( Tools.expr(e)) {
case EField(_), EIdent(_), EConst(_):
expr(e);
default:
add("(");
expr(e);
add(")");
}
add("(");
var first = true;
for( a in args ) {
if( first ) first = false else add(", ");
expr(a);
}
add(")");
case EIf(cond,e1,e2):
add("if( ");
expr(cond);
add(" ) ");
expr(e1);
if( e2 != null ) {
add(" else ");
expr(e2);
}
case EWhile(cond,e):
add("while( ");
expr(cond);
add(" ) ");
expr(e);
case EDoWhile(cond,e):
add("do ");
expr(e);
add(" while ( ");
expr(cond);
add(" )");
case EFor(v, it, e, ithv):
if(ithv != null)
add("for( "+ithv+" => "+v+" in ");
else
add("for( "+v+" in ");
expr(it);
add(" ) ");
expr(e);
case EBreak:
add("break");
case EContinue:
add("continue");
case EFunction(params, e, name, ret): // TODO: static, public, override
add("function");
if( name != null )
add(" " + name);
add("(");
var first = true;
for( a in params ) {
if( first ) first = false else add(", ");
if( a.opt ) add("?");
add(a.name);
addType(a.t);
}
add(")");
addType(ret);
add(" ");
expr(e);
case EReturn(e):
add("return");
if( e != null ) {
add(" ");
expr(e);
}
case EArray(e,index):
expr(e);
add("[");
expr(index);
add("]");
case EArrayDecl(el, _):
add("[");
var first = true;
for( e in el ) {
if( first ) first = false else add(", ");
expr(e);
}
add("]");
case ENew(cl, args, params):
add("new " + cl);
if(params != null) {
add("<");
var first = true;
for( p in params ) {
if( first ) first = false else add(", ");
type(p);
}
add(">");
}
add("(");
var first = true;
for( e in args ) {
if( first ) first = false else add(", ");
expr(e);
}
add(")");
case EThrow(e):
add("throw ");
expr(e);
case ETry(e, v, t, ecatch):
add("try ");
expr(e);
add(" catch( " + v);
addType(t);
add(") ");
expr(ecatch);
case EObject(fl):
if( fl.length == 0 ) {
add("{}");
} else {
tabs += "\t";
add("{\n");
for( f in fl ) {
add(tabs);
add(f.name+" : ");
expr(f.e);
add(",\n");
}
tabs = tabs.substr(1);
add("}");
}
case ETernary(c,e1,e2):
expr(c);
add(" ? ");
expr(e1);
add(" : ");
expr(e2);
case ESwitch(e, cases, def):
add("switch( ");
expr(e);
add(") {");
for( c in cases ) {
add("case ");
var first = true;
for( v in c.values ) {
if( first ) first = false else add(", ");
expr(v);
}
add(": ");
expr(c.expr);
add(";\n");
}
if( def != null ) {
add("default: ");
expr(def);
add(";\n");
}
add("}");
case EMeta(name, args, e):
add("@");
add(name);
if( args != null && args.length > 0 ) {
add("(");
var first = true;
for( a in args ) {
if( first ) first = false else add(", ");
expr(e);
}
add(")");
}
add(" ");
expr(e);
case ECheckType(e, t):
add("(");
expr(e);
add(" : ");
addType(t);
add(")");
}
}
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
}
}
+143 -143
View File
@@ -1,144 +1,144 @@
/*
* Copyright (C)2008-2017 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 hscript;
import hscript.Expr;
class Tools {
public static function iter( e : Expr, f : Expr -> Void ):Void {
switch( expr(e) ) {
case EConst(_), EIdent(_):
case EImport(c): f(e);
case EClass(_, e, _, _): for( a in e ) f(a);
case EVar(_, _, e): if( e != null ) f(e);
case EParent(e): f(e);
case EBlock(el): for( e in el ) f(e);
case EField(e, _): f(e);
case EBinop(_, e1, e2): f(e1); f(e2);
case EUnop(_, _, e): f(e);
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 EWhile(c, e): f(c); f(e);
case EDoWhile(c, e): f(c); f(e);
case EFor(_, it, e): f(it); f(e);
case EBreak,EContinue:
case EFunction(_, e, _, _): f(e);
case EReturn(e): if( e != null ) f(e);
case EArray(e, i): f(e); f(i);
case EArrayDecl(el): for( e in el ) f(e);
case ENew(_,el): for( e in el ) f(e);
case EThrow(e): f(e);
case ETry(e, _, _, c): f(e); f(c);
case EObject(fl): for( fi in fl ) f(fi.e);
case ETernary(c, e1, e2): f(c); f(e1); f(e2);
case ESwitch(e, cases, def):
f(e);
for( c in cases ) {
for( v in c.values ) f(v);
f(c.expr);
}
if( def != null ) f(def);
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
case ECheckType(e,_): f(e);
default:
}
}
public static function map( e : Expr, f : Expr -> Expr ):Expr {
var edef = switch( 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 EParent(e): EParent(f(e));
case EBlock(el): EBlock([for( e in el ) f(e)]);
case EField(e, fi): EField(f(e),fi);
case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2));
case EUnop(op, pre, e): EUnop(op, pre, f(e));
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 EWhile(c, e): EWhile(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 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 EArray(e, i): EArray(f(e),f(i));
case EArrayDecl(el): EArrayDecl([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 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 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 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 EImport(c): EImport(c);
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
default: expr(e);
}
return mk(edef, e);
}
public static inline function expr( e : Expr ) : ExprDef {
#if hscriptPos
return e.e;
#else
return e;
#end
}
public static inline function mk( e : ExprDef, p : Expr ):Expr {
#if hscriptPos
return { e : e, pmin : p.pmin, pmax : p.pmax, origin : p.origin, line : p.line };
#else
return e;
#end
}
/**
* DO NOT USE INLINE ON THIS FUNCTION
**/
public static function argCount(func: haxe.Constraints.Function): Int {
// https://github.com/pisayesiwsi/hscript-iris/blob/dev/crowplexus/hscript/Tools.hx#L206
#if cpp
return untyped __cpp__("{0}->__ArgCount()", func);
#elseif js
return untyped js.Syntax.code("{0}.length", func);
#elseif hl
var ft = hl.Type.getDynamic(func);
if (ft.kind != HFun)
return -1;
return ft.getArgsCount();
#else
return -1;
#end
}
public static function isUppercase(s:String) {
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;
/*
* Copyright (C)2008-2017 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 hscript;
import hscript.Expr;
class Tools {
public static function iter( e : Expr, f : Expr -> Void ):Void {
switch( expr(e) ) {
case EConst(_), EIdent(_):
case EImport(c): f(e);
case EClass(_, e, _, _): for( a in e ) f(a);
case EVar(_, _, e): if( e != null ) f(e);
case EParent(e): f(e);
case EBlock(el): for( e in el ) f(e);
case EField(e, _): f(e);
case EBinop(_, e1, e2): f(e1); f(e2);
case EUnop(_, _, e): f(e);
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 EWhile(c, e): f(c); f(e);
case EDoWhile(c, e): f(c); f(e);
case EFor(_, it, e): f(it); f(e);
case EBreak,EContinue:
case EFunction(_, e, _, _): f(e);
case EReturn(e): if( e != null ) f(e);
case EArray(e, i): f(e); f(i);
case EArrayDecl(el): for( e in el ) f(e);
case ENew(_,el): for( e in el ) f(e);
case EThrow(e): f(e);
case ETry(e, _, _, c): f(e); f(c);
case EObject(fl): for( fi in fl ) f(fi.e);
case ETernary(c, e1, e2): f(c); f(e1); f(e2);
case ESwitch(e, cases, def):
f(e);
for( c in cases ) {
for( v in c.values ) f(v);
f(c.expr);
}
if( def != null ) f(def);
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
case ECheckType(e,_): f(e);
default:
}
}
public static function map( e : Expr, f : Expr -> Expr ):Expr {
var edef = switch( 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 EParent(e): EParent(f(e));
case EBlock(el): EBlock([for( e in el ) f(e)]);
case EField(e, fi): EField(f(e),fi);
case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2));
case EUnop(op, pre, e): EUnop(op, pre, f(e));
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 EWhile(c, e): EWhile(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 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 EArray(e, i): EArray(f(e),f(i));
case EArrayDecl(el): EArrayDecl([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 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 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 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 EImport(c): EImport(c);
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
default: expr(e);
}
return mk(edef, e);
}
public static inline function expr( e : Expr ) : ExprDef {
#if hscriptPos
return e.e;
#else
return e;
#end
}
public static inline function mk( e : ExprDef, p : Expr ):Expr {
#if hscriptPos
return { e : e, pmin : p.pmin, pmax : p.pmax, origin : p.origin, line : p.line };
#else
return e;
#end
}
/**
* DO NOT USE INLINE ON THIS FUNCTION
**/
public static function argCount(func: haxe.Constraints.Function): Int {
// https://github.com/pisayesiwsi/hscript-iris/blob/dev/crowplexus/hscript/Tools.hx#L206
#if cpp
return untyped __cpp__("{0}->__ArgCount()", func);
#elseif js
return untyped js.Syntax.code("{0}.length", func);
#elseif hl
var ft = hl.Type.getDynamic(func);
if (ft.kind != HFun)
return -1;
return ft.getArgsCount();
#else
return -1;
#end
}
public static function isUppercase(s:String) {
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;
}