Turned stuffs to classes to reduce reflection

This commit is contained in:
NeeEoo
2024-04-23 15:02:15 +02:00
parent 10dd51ebe8
commit 6346f82edf
10 changed files with 217 additions and 44 deletions
+32 -11
View File
@@ -31,18 +31,26 @@ enum Const {
}
#if hscriptPos
typedef Expr = {
var e : ExprDef;
var pmin : Int;
var pmax : Int;
var origin : String;
var line : Int;
class Expr {
public var e : ExprDef;
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;
}
}
enum ExprDef {
enum ExprDef
#else
typedef ExprDef = Expr;
enum Expr {
enum Expr
#end
{
EConst( c : Const );
EIdent( v : String );
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
@@ -75,7 +83,19 @@ enum Expr {
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
}
typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
//typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
class Argument {
public var name : String;
public var t : Null<CType>;
public var opt : Bool;
public var value : Null<Expr>;
public function new(name, ?t, ?opt, ?value) {
this.name = name;
this.t = t;
this.opt = opt;
this.value = value;
}
}
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
@@ -106,10 +126,11 @@ class Error {
return Printer.errorToString(this);
}
}
enum ErrorDef {
enum ErrorDef
#else
enum Error {
enum Error
#end
{
EInvalidChar( c : Int );
EUnexpected( s : String );
EUnterminatedString;
+2
View File
@@ -631,8 +631,10 @@ class Interp {
return get(field, f);
case EBinop(op, e1, e2):
var fop = binops.get(op);
#if debug
if (fop == null)
error(EInvalidOp(op));
#end
return fop(e1, e2);
case EUnop(op, prefix, e):
switch (op) {
+23 -21
View File
@@ -269,7 +269,7 @@ class Parser {
if( e == null ) return null;
if( pmin == null ) pmin = tokenMin;
if( pmax == null ) pmax = tokenMax;
return { e : e, pmin : pmin, pmax : pmax, origin : origin, line : line };
return new Expr(e, pmin, pmax, origin, line);
#else
return e;
#end
@@ -389,14 +389,14 @@ class Parser {
return parseExprNext(mk(ECheckType(e,t),p1,tokenMax));
case TComma:
switch( expr(e) ) {
case EIdent(v): return parseLambda([{ name : v, t : t }], pmin(e));
case EIdent(v): return parseLambda([new Argument(v, t)], pmin(e));
default:
}
default:
}
case TComma:
switch( expr(e) ) {
case EIdent(v): return parseLambda([{name:v}], pmin(e));
case EIdent(v): return parseLambda([new Argument(v)], pmin(e));
default:
}
default:
@@ -504,7 +504,7 @@ class Parser {
while( true ) {
var id = getIdent();
var t = maybe(TDoubleDot) ? parseType() : null;
args.push({ name : id, t : t });
args.push(new Argument(id, t));
var tk = token();
switch( tk ) {
case TComma:
@@ -569,28 +569,30 @@ class Parser {
if( e == null && resumeErrors )
return null;
return switch( expr(e) ) {
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));
default: mk(EUnop(op,true,e),pmin(e),pmax(e));
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));
default: mk(EUnop(op,true,e),pmin(e),pmax(e));
}
}
function makeBinop( op, e1, e ) {
if(!Tools.isValidBinOp(op))
error(EInvalidOp(op),pmin(e1),pmax(e1));
if( e == null && resumeErrors )
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
return switch( expr(e) ) {
case EBinop(op2,e2,e3):
if( opPriority.get(op) <= opPriority.get(op2) && !opRightAssoc.exists(op) )
mk(EBinop(op2,makeBinop(op,e1,e2),e3),pmin(e1),pmax(e3));
else
mk(EBinop(op, e1, e), pmin(e1), pmax(e));
case ETernary(e2,e3,e4):
if( opRightAssoc.exists(op) )
case EBinop(op2,e2,e3):
if( opPriority.get(op) <= opPriority.get(op2) && !opRightAssoc.exists(op) )
mk(EBinop(op2,makeBinop(op,e1,e2),e3),pmin(e1),pmax(e3));
else
mk(EBinop(op, e1, e), pmin(e1), pmax(e));
case ETernary(e2,e3,e4):
if( opRightAssoc.exists(op) )
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
else
mk(ETernary(makeBinop(op, e1, e2), e3, e4), pmin(e1), pmax(e));
default:
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
else
mk(ETernary(makeBinop(op, e1, e2), e3, e4), pmin(e1), pmax(e));
default:
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
}
}
@@ -1045,10 +1047,10 @@ class Parser {
switch( expr(e1) ) {
case EIdent(i), EParent(expr(_) => EIdent(i)):
var eret = parseExpr();
return mk(EFunction([{ name : i }], mk(EReturn(eret),pmin(eret))), pmin(e1));
return mk(EFunction([new Argument(i)], mk(EReturn(eret),pmin(eret))), pmin(e1));
case ECheckType(expr(_) => EIdent(i), t):
var eret = parseExpr();
return mk(EFunction([{ name : i, t : t }], mk(EReturn(eret),pmin(eret))), pmin(e1));
return mk(EFunction([new Argument(i, t)], mk(EReturn(eret),pmin(eret))), pmin(e1));
default:
}
unexpected(tk);
@@ -1106,7 +1108,7 @@ class Parser {
unexpected(tk);
break;
}
var arg : Argument = { name : name };
var arg : Argument = new Argument(name);
args.push(arg);
if( opt ) arg.opt = true;
if( allowTypes ) {
+11 -2
View File
@@ -103,12 +103,21 @@ class Tools {
#end
}
public static inline function mk( e : ExprDef, p : Expr ) {
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 };
return new Expr(e, p.pmin, p.pmax, p.origin, p.line);
#else
return e;
#end
}
public static function isValidBinOp(op:String):Bool {
if(op == ("??"+"=")) return true;
return switch(op) {
case "+" | "-" | "*" | "/" | "%" | "&" | "|" | "^" | "<<" | ">>" | ">>>" | "==" | "!=" | ">=" | "<=" | ">" | "<" | "||" | "&&" | "is" | "=" | "??" | "..." | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | "<<=" | ">>=" | ">>>=": true;
case "=>": true;
default: false;
}
}
}
+13
View File
@@ -33,4 +33,17 @@ class HScriptRunner {
else
return interp.exprReturn(expr);
}
public function executeWithVars(script:String, vars:Dynamic):Dynamic {
var interp = clearPrevious ? getNewInterp() : this.interp;
var expr = Util.parse(headerCode + script + tailCode);
if(expr == null)
return "ERROR";
for(v in Reflect.fields(vars))
interp.variables.set(v, Reflect.field(vars, v));
if (clearPrevious)
return interp.execute(expr);
else
return interp.exprReturn(expr);
}
}
+7 -4
View File
@@ -3,16 +3,17 @@ import hscript.Expr.Error;
using StringTools;
class Util {
public static function assert(value:Bool, message:String) {
public static function assert(value:Bool, message:String, ?pos:haxe.PosInfos) {
if (value) {
passedTestUnits++;
} else {
Sys.println("Assertion failed: " + message);
Sys.println("> At " + pos.fileName + ":" + pos.lineNumber);
failedTestUnits++;
}
}
public static function assertEq(value:Dynamic, expected:Dynamic, message:String) {
public static function assertEq(value:Dynamic, expected:Dynamic, message:String, ?pos:haxe.PosInfos) {
var passed = value == expected;
if (Std.isOfType(value, Array) && Std.isOfType(expected, Array)) {
if (deepCompareArrays(value, expected))
@@ -27,11 +28,12 @@ class Util {
passedTestUnits++;
} else {
Sys.println("Assertion failed: " + message + " Expected: " + expected + " Got: " + value);
Sys.println("> At " + pos.fileName + ":" + pos.lineNumber);
failedTestUnits++;
}
}
public static function assertNeq(value:Dynamic, expected:Dynamic, message:String) {
public static function assertNeq(value:Dynamic, expected:Dynamic, message:String, ?pos:haxe.PosInfos) {
var passed = value != expected;
if (Std.isOfType(value, Array) && Std.isOfType(expected, Array)) {
if (!deepCompareArrays(value, expected))
@@ -44,6 +46,7 @@ class Util {
passedTestUnits++;
} else {
Sys.println("Assertion failed: " + message + " Expected: " + expected + " Got: " + value);
Sys.println("> At " + pos.fileName + ":" + pos.lineNumber);
failedTestUnits++;
}
}
@@ -154,7 +157,7 @@ class Util {
var err = error.toString();
if (err.startsWith(fn)) err = err.substr(fn.length);
Sys.println(fn + err);
Sys.println("ERROR: " + fn + err);
//Logs.traceColored([
// Logs.logText(fn, GREEN),
// Logs.logText(err, RED)
+2 -2
View File
@@ -15,10 +15,10 @@ class TestBenchmark extends Benchmark {
public var a:Array<Float> = [];
public override function haxeBenchmark() {
for (i in 0...1000) a.push(i);
for (i in 0...1000) a.push(i * 2 + 1 / 6);
}
public override function hscriptBenchmark() {
execute("var a:Array<Float> = []; for (i in 0...1000) a.push(i);");
execute("var a:Array<Float> = []; for (i in 0...1000) a.push(i * 2 + 1 / 6);");
}
}
+114
View File
@@ -5,6 +5,18 @@ class MiscCase extends TestCase {
super.setup();
}
override function getNewInterp() {
var interp = super.getNewInterp();
interp.variables.set("Std", Std);
interp.variables.set("String", String);
interp.variables.set("Bool", Bool);
interp.variables.set("Float", Float);
interp.variables.set("Array", Array);
interp.variables.set("Int", Int);
interp.variables.set("IntIterator", IntIterator);
return interp;
}
override function run() {
assertEq("", null);
assertEq("true", true);
@@ -19,6 +31,108 @@ class MiscCase extends TestCase {
var a = 1; var a = 2;
assertEq("var a = 1; var a = 2; a", a);
assertEq("0",0);
assertEq("0xFF", 255);
assertEq("0xFF_FF", 0xFFFF);
assertEq("0b101", 5); //assertEq("0b101", 0b101);
#if !(php || python)
#if haxe3
assertEq("0xBFFFFFFF", 0xBFFFFFFF);
assertEq("0x7FFFFFFF", 0x7FFFFFFF);
#elseif !neko
assertEq("n(0xBFFFFFFF)", 0xBFFFFFFF, { n : haxe.Int32.toNativeInt });
assertEq("n(0x7FFFFFFF)", 0x7FFFFFFF, { n : haxe.Int32.toNativeInt } );
#end
#end
assertEq("-123",-123);
assertEq("- 123",-123);
assertEq("1.546",1.546);
assertEq(".545",.545);
assertEq("'bla'","bla");
assertEq("null",null);
assertEq("true",true);
assertEq("false",false);
assertEq("1 == 2",false);
assertEq("1.3 == 1.3",true);
assertEq("5 > 3",true);
assertEq("0 < 0",false);
assertEq("-1 <= -1",true);
assertEq("1 + 2",3);
assertEq("~545",-546);
assertEq("'abc' + 55","abc55");
assertEq("'abc' + 'de'","abcde");
assertEq("-1 + 2",1);
assertEq("1 / 5",0.2);
assertEq("3 * 2 + 5",11);
assertEq("3 * (2 + 5)",21);
assertEq("3 * 2 // + 5 \n + 6",12);
assertEq("3 /* 2\n */ + 5",8);
assertEq("[55,66,77][1]",66);
assertEq("var a = [55]; a[0] *= 2; a[0]",110);
assertEq("x",55,{ x : 55 });
assertEq("var y = 33; y",33);
assertEq("{ 1; 2; 3; }",3);
assertEq("{ var x = 0; } x",55,{ x : 55 });
assertEq("o.val",55,{ o : { val : 55 } });
assertEq("o.val",null,{ o : {} });
assertEq("var a = 1; a++",1);
assertEq("var a = 1; a++; a",2);
assertEq("var a = 1; ++a",2);
assertEq("var a = 1; a *= 3",3);
assertEq("a = b = 3; a + b",6);
assertEq("add(1,2)",3,{ add : function(x,y) return x + y });
assertEq("a.push(5); a.pop() + a.pop()",{var a = [3]; a.push(5); a.pop() + a.pop();},{ a : [3] });
assertEq("if( true ) 1 else 2",1);
assertEq("if( false ) 1 else 2",2);
assertEq("var t = 0; for( x in [1,2,3] ) t += x; t",6);
assertEq("var a = new Array(); for( x in 0...5 ) a[x] = x; a.join('-')","0-1-2-3-4");
assertEq("(function(a,b) return a + b)(4,5)",9);
assertEq("var y = 0; var add = function(a) y += a; add(5); add(3); y", {var y = 0; var add = function(a) y += a; add(5); add(3); y;});
assertEq("var a = [1,[2,[3,[4,null]]]]; var t = 0; while( a != null ) { t += a[0]; a = a[1]; }; t",10);
assertEq("var a = false; do { a = true; } while (!a); a;",true);
assertEq("var t = 0; for( x in 1...10 ) t += x; t", 45);
#if haxe3
assertEq("var t = 0; for( x in new IntIterator(1,10) ) t +=x; t", 45);
#else
assertEq("var t = 0; for( x in new IntIter(1,10) ) t +=x; t", 45);
#end
assertEq("var x = 1; try { var x = 66; throw 789; } catch( e : Dynamic ) e + x",{var x = 1; try { var x = 66; throw 789; } catch( e : Dynamic ) e + x;});
assertEq("var x = 1; var f = function(x) throw x; try f(55) catch( e : Dynamic ) e + x",{
var x = 1;
var f:Dynamic = function(x) throw x;
try
f(55)
catch( e:Dynamic )
e + x;
});
assertEq("var i=2; if( true ) --i; i",1);
assertEq("var i=0; if( i++ > 0 ) i=3; i",1);
assertEq("var a = 5/2; a",2.5);
assertEq("{ x = 3; x; }", 3);
assertEq("{ x : 3, y : {} }.x", 3);
assertEq("function bug(){ \n }\nbug().x", null);
assertEq("1 + 2 == 3", true);
assertEq("-2 == 3 - 5", true);
assertEq("var x=-3; x", -3);
assertEq("var a:Array<Dynamic>=[1,2,4]; a[2]", 4);
assertEq("/**/0", 0);
assertEq("x=1;x*=-2", -2);
assertEq("var f = x -> x + 1; f(3)", 4);
assertEq("var f = () -> 55; f()", 55);
assertEq("var f = (x) -> x + 1; f(3)", 4);
assertEq("var f = (x:Int) -> x + 1; f(3)", 4);
assertEq("var f = (x,y) -> x + y; f(3,1)", 4);
assertEq("var f = (x,y:Int) -> x + y; f(3,1)", 4);
assertEq("var f = (x:Int,y:Int) -> x + y; f(3,1)", 4);
assertEq("var f:Int->Int->Int = (x:Int,y:Int) -> x + y; f(3,1)", {var f:Int->Int->Int = (x:Int,y:Int) -> x + y; f(3,1);});
assertEq("var f:(x:Int, y:Int)->Int = (x:Int,y:Int) -> x + y; f(3,1)", {var f:(x:Int, y:Int)->Int = (x:Int,y:Int) -> x + y; f(3,1);});
//assertEq("var f:(x:Int)->(y:Int, z:Int)->Int = (x:Int) -> (y:Int, z:Int) -> x + y + z; f(3)(1, 2)", {var f:(x:Int)->(y:Int, z:Int)->Int = (x:Int) -> (y:Int, z:Int) -> x + y + z; f(3)(1, 2);});
//assertEq("var f:(x:Int)->(Int, Int)->Int = (x:Int) -> (y:Int, z:Int) -> x + y + z; f(3)(1, 2)", {var f:(x:Int)->(Int, Int)->Int = (x:Int) -> (y:Int, z:Int) -> x + y + z; f(3)(1, 2);});
assertEq("var a = 10; var b = 5; a - -b", 15);
assertEq("var a = 10; var b = 5; a - b / 2", 7.5);
}
override function teardown() {
+1
View File
@@ -24,6 +24,7 @@ class SwitchCase extends TestCase {
assertEq("switch(5) { case 1|4: 'error'; case 5: 0; default: -1; }", switch(5) { case 1|4: 'error'; case 5: 0; default: -1; });
assertEq("switch(5) { case 1|4: 'error'; default: -1; }", switch(5) { case 1|4: 'error'; default: -1; });
assertEq("switch(5) { case (1|4): 'error'; default: -1; }", switch(5) { case (1|4): 'error'; default: -1; });
assertEq("switch(5) { case 1,4: 'error'; case 5: 0; default: -1; }", switch(5) { case 1,4: 'error'; case 5: 0; default: -1; });
}
+12 -4
View File
@@ -3,15 +3,23 @@ package tests;
@:access(hscript.Interp)
@:access(hscript.Parser)
class TestCase extends HScriptRunner {
public function assertEq(script:String, expected:Dynamic, ?message:String) {
public function assertEq(script:String, expected:Dynamic, ?message:String, ?vars:Dynamic, ?pos:haxe.PosInfos) {
if(message == null)
message = script;
Util.assertEq(execute(headerCode + script + tailCode), expected, message);
var result = if(vars != null)
executeWithVars(headerCode + script + tailCode, vars);
else
execute(headerCode + script + tailCode);
Util.assertEq(result, expected, message, pos);
}
public function assertNeq(script:String, expected:Dynamic, ?message:String) {
public function assertNeq(script:String, expected:Dynamic, ?message:String, ?vars:Dynamic, ?pos:haxe.PosInfos) {
if(message == null)
message = script;
Util.assertNeq(execute(headerCode + script + tailCode), expected, message);
var result = if(vars != null)
executeWithVars(headerCode + script + tailCode, vars);
else
execute(headerCode + script + tailCode);
Util.assertNeq(result, expected, message, pos);
}
}