Compare commits
22
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ad52138fe | ||
|
|
a616f2affe | ||
|
|
6721a838ca | ||
|
|
826f0184bf | ||
|
|
6c20ad3a8f | ||
|
|
fd5a2d9143 | ||
|
|
8da9ed942d | ||
|
|
f31f380602 | ||
|
|
85ea6c6f44 | ||
|
|
13bdf30055 | ||
|
|
6daea2fb5b | ||
|
|
f18c7a2210 | ||
|
|
123a7de64a | ||
|
|
bc8a59877e | ||
|
|
4347fe9305 | ||
|
|
e0e1436930 | ||
|
|
a41222328a | ||
|
|
080c441f24 | ||
|
|
d6d6e7a45e | ||
|
|
cb645d6bb1 | ||
|
|
5d58ea56c9 | ||
|
|
4170a4aafc |
@@ -1,2 +1,4 @@
|
||||
/hscript.swf
|
||||
/release.zip
|
||||
|
||||
tests/bin/*
|
||||
@@ -29,6 +29,10 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
}
|
||||
|
||||
public function hnew(args:Array<Dynamic>):Dynamic {
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
throw "todo: do all this lmao -lunar";
|
||||
return null;
|
||||
#else
|
||||
var interp = new Interp();
|
||||
interp.errorHandler = ogInterp.errorHandler;
|
||||
|
||||
@@ -53,8 +57,15 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
}
|
||||
}
|
||||
|
||||
var comparisonMap = new Map();
|
||||
for(key => value in interp.variables) {
|
||||
comparisonMap.set(key, value);
|
||||
}
|
||||
|
||||
_class.__custom__variables = interp.variables;
|
||||
|
||||
//trace(fields);
|
||||
|
||||
for(expr in fields) {
|
||||
@:privateAccess
|
||||
interp.exprReturn(expr);
|
||||
@@ -64,12 +75,27 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
|
||||
_class.__interp = interp; // TODO: Remove
|
||||
interp.scriptObject = _class;
|
||||
// get only variables that were not set before
|
||||
var classVariables = [for(key => value in interp.variables) if(!comparisonMap.exists(key) || comparisonMap[key] != value) key => value];
|
||||
for(variable => value in classVariables) {
|
||||
if(variable == "this" || variable == "super") continue;
|
||||
@:privateAccess
|
||||
if(!interp.__instanceFields.contains(variable)) {
|
||||
interp.__instanceFields.push(variable);
|
||||
}
|
||||
}
|
||||
|
||||
//trace([for(key => value in classVariables) key]);
|
||||
//@:privateAccess
|
||||
//trace(interp.__instanceFields);
|
||||
|
||||
_class.__allowSetGet = false;
|
||||
|
||||
for(variable => value in interp.variables) {
|
||||
if(variable == "this") continue;
|
||||
|
||||
if(variable.startsWith("set_") || variable.startsWith("get_")) {
|
||||
_class.__allowSetGet = false;
|
||||
_class.__allowSetGet = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +104,12 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
|
||||
}
|
||||
|
||||
var newFunc = interp.variables.get("new");
|
||||
if(newFunc != null) {
|
||||
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
|
||||
}
|
||||
return _class;
|
||||
#end
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
@@ -124,6 +155,6 @@ class TemplateClass implements IHScriptCustomClassBehaviour implements IHScriptC
|
||||
}
|
||||
}
|
||||
|
||||
class StaticHandler {
|
||||
final class StaticHandler {
|
||||
public function new() {}
|
||||
}
|
||||
+1
-1
@@ -62,7 +62,7 @@ enum Error_
|
||||
EInvalidEscape( s : String );
|
||||
}
|
||||
|
||||
enum abstract ErrorMessage(Int) from Int to Int {
|
||||
enum abstract ErrorMessage(Expr.UInt8) from Expr.UInt8 to Expr.UInt8 {
|
||||
final INVALID_CHAR_CODE_MULTI;
|
||||
final FROM_CHAR_CODE_NON_INT;
|
||||
final EMPTY_INTERPOLATION;
|
||||
|
||||
+221
-31
@@ -21,6 +21,16 @@
|
||||
*/
|
||||
package hscript;
|
||||
|
||||
typedef Int8 = #if cpp cpp.Int8 #else Int #end;
|
||||
typedef Int16 = #if cpp cpp.Int16 #else Int #end;
|
||||
typedef Int32 = #if cpp cpp.Int32 #else Int #end;
|
||||
typedef Int64 = #if cpp cpp.Int64 #else Int #end;
|
||||
|
||||
typedef UInt8 = #if cpp cpp.UInt8 #else Int #end;
|
||||
typedef UInt16 = #if cpp cpp.UInt16 #else Int #end;
|
||||
typedef UInt32 = #if cpp cpp.UInt32 #else Int #end;
|
||||
typedef UInt64 = #if cpp cpp.UInt64 #else Int #end;
|
||||
|
||||
enum Const {
|
||||
CInt( v : Int );
|
||||
CFloat( f : Float );
|
||||
@@ -30,12 +40,13 @@ enum Const {
|
||||
#end
|
||||
}
|
||||
|
||||
enum MapType {
|
||||
IntMap;
|
||||
StringMap;
|
||||
EnumMap;
|
||||
ObjectMap;
|
||||
UnknownMap;
|
||||
enum abstract MapType(UInt8) {
|
||||
var Null;
|
||||
var IntMap;
|
||||
var StringMap;
|
||||
var EnumMap;
|
||||
var ObjectMap;
|
||||
var UnknownMap;
|
||||
}
|
||||
|
||||
typedef Error = hscript.Error.Error_;
|
||||
@@ -62,28 +73,28 @@ enum Expr
|
||||
#end
|
||||
{
|
||||
EConst( c : Const );
|
||||
EIdent( v : String );
|
||||
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
|
||||
EIdent( v : VarN );
|
||||
EVar( n : VarN, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
|
||||
EParent( e : Expr, ?noOptimize : Bool );
|
||||
EBlock( e : Array<Expr> );
|
||||
EField( e : Expr, f : String , ?safe : Bool );
|
||||
EBinop( op : String, e1 : Expr, e2 : Expr );
|
||||
EUnop( op : String, prefix : Bool, e : Expr );
|
||||
EBinop( op : Binop, e1 : Expr, e2 : Expr );
|
||||
EUnop( op : Unop, prefix : Bool, e : Expr );
|
||||
ECall( e : Expr, params : Array<Expr> );
|
||||
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
||||
EWhile( cond : Expr, e : Expr );
|
||||
EFor( v : String, it : Expr, e : Expr);
|
||||
EForKeyValue( v : String, it : Expr, e : Expr, ithv: String);
|
||||
EFor( v : VarN, it : Expr, e : Expr);
|
||||
EForKeyValue( v : VarN, it : Expr, e : Expr, ithv: VarN);
|
||||
EBreak;
|
||||
EContinue;
|
||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||
EFunction( args : Array<Argument>, e : Expr, ?name : VarN, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||
EReturn( ?e : Expr );
|
||||
EArray( e : Expr, index : Expr );
|
||||
EMapDecl( type: MapType, keys: Array<Expr>, values: Array<Expr> );
|
||||
EArrayDecl( e : Array<Expr> );
|
||||
ENew( cl : String, params : Array<Expr> );
|
||||
ENew( cl : VarN, params : Array<Expr> );
|
||||
EThrow( e : Expr );
|
||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||
ETry( e : Expr, v : VarN, t : Null<CType>, ecatch : Expr );
|
||||
EObject( fl : Array<ObjectField> );
|
||||
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
||||
@@ -92,12 +103,186 @@ enum Expr
|
||||
ECheckType( e : Expr, t : CType );
|
||||
|
||||
EImport( c : String, mode: KImportMode );
|
||||
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
||||
EClass( name:VarN, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
||||
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
EInfo( info: InfoClass, e: Expr );
|
||||
#end
|
||||
}
|
||||
|
||||
enum Binop {
|
||||
/**
|
||||
`+`
|
||||
**/
|
||||
OpAdd;
|
||||
|
||||
/**
|
||||
`*`
|
||||
**/
|
||||
OpMult;
|
||||
|
||||
/**
|
||||
`/`
|
||||
**/
|
||||
OpDiv;
|
||||
|
||||
/**
|
||||
`-`
|
||||
**/
|
||||
OpSub;
|
||||
|
||||
/**
|
||||
`=`
|
||||
**/
|
||||
OpAssign;
|
||||
|
||||
/**
|
||||
`==`
|
||||
**/
|
||||
OpEq;
|
||||
|
||||
/**
|
||||
`!=`
|
||||
**/
|
||||
OpNotEq;
|
||||
|
||||
/**
|
||||
`>`
|
||||
**/
|
||||
OpGt;
|
||||
|
||||
/**
|
||||
`>=`
|
||||
**/
|
||||
OpGte;
|
||||
|
||||
/**
|
||||
`<`
|
||||
**/
|
||||
OpLt;
|
||||
|
||||
/**
|
||||
`<=`
|
||||
**/
|
||||
OpLte;
|
||||
|
||||
/**
|
||||
`&`
|
||||
**/
|
||||
OpAnd;
|
||||
|
||||
/**
|
||||
`|`
|
||||
**/
|
||||
OpOr;
|
||||
|
||||
/**
|
||||
`^`
|
||||
**/
|
||||
OpXor;
|
||||
|
||||
/**
|
||||
`&&`
|
||||
**/
|
||||
OpBoolAnd;
|
||||
|
||||
/**
|
||||
`||`
|
||||
**/
|
||||
OpBoolOr;
|
||||
|
||||
/**
|
||||
`<<`
|
||||
**/
|
||||
OpShl;
|
||||
|
||||
/**
|
||||
`>>`
|
||||
**/
|
||||
OpShr;
|
||||
|
||||
/**
|
||||
`>>>`
|
||||
**/
|
||||
OpUShr;
|
||||
|
||||
/**
|
||||
`%`
|
||||
**/
|
||||
OpMod;
|
||||
|
||||
/**
|
||||
`+=` `-=` `/=` `*=` `<<=` `>>=` `>>>=` `|=` `&=` `^=` `%=`
|
||||
**/
|
||||
OpAssignOp(op:Binop);
|
||||
|
||||
/**
|
||||
`...`
|
||||
**/
|
||||
OpInterval;
|
||||
|
||||
/**
|
||||
`=>`
|
||||
**/
|
||||
OpArrow;
|
||||
|
||||
/**
|
||||
`is`
|
||||
**/
|
||||
OpIs; // used to be OpIn, but our system treats that differently
|
||||
|
||||
/**
|
||||
`??`
|
||||
**/
|
||||
OpNullCoal;
|
||||
}
|
||||
|
||||
enum abstract Unop(UInt8) {
|
||||
/**
|
||||
`++`
|
||||
**/
|
||||
var OpIncrement;
|
||||
|
||||
/**
|
||||
`--`
|
||||
**/
|
||||
var OpDecrement;
|
||||
|
||||
/**
|
||||
`!`
|
||||
**/
|
||||
var OpNot;
|
||||
|
||||
/**
|
||||
`-`
|
||||
**/
|
||||
var OpNeg;
|
||||
|
||||
/**
|
||||
`~`
|
||||
**/
|
||||
var OpNegBits;
|
||||
|
||||
/**
|
||||
`...`
|
||||
**/
|
||||
var OpSpread;
|
||||
}
|
||||
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
class InfoClass {
|
||||
public var variables:Array<String>;
|
||||
|
||||
public function new(variables:Array<String>) {
|
||||
this.variables = variables;
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
enum KImportMode {
|
||||
INormal;
|
||||
IAs( name : String );
|
||||
IAsReturn;
|
||||
IAll;
|
||||
}
|
||||
|
||||
@@ -111,20 +296,15 @@ class ObjectField {
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchCase {
|
||||
@:structInit
|
||||
final class SwitchCase {
|
||||
public var values : Array<Expr>;
|
||||
public var expr : Expr;
|
||||
|
||||
public function new(values, expr) {
|
||||
this.values = values;
|
||||
this.expr = expr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
||||
class Argument {
|
||||
public var name : String;
|
||||
public var name : VarN;
|
||||
public var t : Null<CType>;
|
||||
public var opt : Bool;
|
||||
public var value : Null<Expr>;
|
||||
@@ -134,6 +314,10 @@ class Argument {
|
||||
this.opt = opt;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public function toString() {
|
||||
return (opt ? "?" : "") + name + (t != null ? ":" + Printer.convertTypeToString(t) : "") + (value != null ? "=" + Printer.convertExprToString(value) : "");
|
||||
}
|
||||
}
|
||||
|
||||
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
|
||||
@@ -179,13 +363,13 @@ typedef FieldDecl = {
|
||||
var access : Array<FieldAccess>;
|
||||
}
|
||||
|
||||
enum FieldAccess {
|
||||
APublic;
|
||||
APrivate;
|
||||
AInline;
|
||||
AOverride;
|
||||
AStatic;
|
||||
AMacro;
|
||||
enum abstract FieldAccess(UInt8) {
|
||||
var APublic;
|
||||
var APrivate;
|
||||
var AInline;
|
||||
var AOverride;
|
||||
var AStatic;
|
||||
var AMacro;
|
||||
}
|
||||
|
||||
enum FieldKind {
|
||||
@@ -205,3 +389,9 @@ typedef VarDecl = {
|
||||
var expr : Null<Expr>;
|
||||
var type : Null<CType>;
|
||||
}
|
||||
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
abstract VarN(Dynamic) from Int from String to Int to String {}
|
||||
#else
|
||||
typedef VarN = String;
|
||||
#end
|
||||
+601
-130
File diff suppressed because it is too large
Load Diff
+34
-31
@@ -50,6 +50,7 @@ class Optimizer {
|
||||
newExprs.push(e);
|
||||
}
|
||||
}
|
||||
|
||||
return mk(EBlock(newExprs), s);
|
||||
|
||||
case EIf(econd, e1, e2):
|
||||
@@ -73,7 +74,7 @@ class Optimizer {
|
||||
var c2 = getBool(e2);
|
||||
|
||||
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
||||
return optimize(mk(EUnop("!", true, econd), s));
|
||||
return optimize(mk(EUnop(OpNot, true, econd), s));
|
||||
}
|
||||
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
||||
return optimize(mk(Tools.expr(econd), s));
|
||||
@@ -112,7 +113,7 @@ class Optimizer {
|
||||
var c2 = getBool(e2);
|
||||
|
||||
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
||||
return optimize(mk(EUnop("!", true, econd), s));
|
||||
return optimize(mk(EUnop(OpNot, true, econd), s));
|
||||
}
|
||||
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
||||
return optimize(mk(Tools.expr(econd), s));
|
||||
@@ -390,9 +391,9 @@ class Optimizer {
|
||||
// Possible bugs here
|
||||
if(isNumber(e1) && !isConstant(e2)) {
|
||||
var c1 = getNumber(e1);
|
||||
if(compareNumber(c1, 0) && op == "+")
|
||||
if(compareNumber(c1, 0) && op == OpAdd)
|
||||
return mk(Tools.expr(e2), s);
|
||||
if(compareNumber(c1, 1) && op == "*")
|
||||
if(compareNumber(c1, 1) && op == OpMult)
|
||||
return mk(Tools.expr(e2), s);
|
||||
//if(compareNumber(c1, 0) && op == "*")
|
||||
// return mk(convertConstant(0), s);
|
||||
@@ -400,11 +401,11 @@ class Optimizer {
|
||||
|
||||
if(!isConstant(e1) && isNumber(e2)) {
|
||||
var c2 = getNumber(e2);
|
||||
if(op == "+" && compareNumber(c2, 0))
|
||||
if(op == OpAdd && compareNumber(c2, 0))
|
||||
return mk(Tools.expr(e1), s);
|
||||
if(op == "/" && compareNumber(c2, 1))
|
||||
if(op == OpDiv && compareNumber(c2, 1))
|
||||
return mk(Tools.expr(e1), s);
|
||||
if(op == "*" && compareNumber(c2, 1))
|
||||
if(op == OpMult && compareNumber(c2, 1))
|
||||
return mk(Tools.expr(e1), s);
|
||||
//if(op == "*" && compareNumber(c2, 0))
|
||||
// return mk(convertConstant(0), s);
|
||||
@@ -418,11 +419,12 @@ class Optimizer {
|
||||
if(isConstant(e) && prefix) {
|
||||
var constant:Dynamic = getConstant(e);
|
||||
switch(op) {
|
||||
case "-": return mk(convertConstant(-constant), s);
|
||||
case "!": return mk(convertConstant(!constant), s);
|
||||
case "~":
|
||||
case OpNeg: return mk(convertConstant(-constant), s);
|
||||
case OpNot: return mk(convertConstant(!constant), s);
|
||||
case OpNegBits:
|
||||
var complement = #if (neko && !haxe3) haxe.Int32.complement(constant) #else ~constant #end;
|
||||
return mk(convertConstant(complement), s);
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,6 +432,7 @@ class Optimizer {
|
||||
default:
|
||||
Sys.println("Unknown expr: " + e);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -603,29 +606,29 @@ class Optimizer {
|
||||
#end
|
||||
}
|
||||
|
||||
static function optimizeOp(op, f1:Dynamic, f2:Dynamic):Dynamic {
|
||||
static function optimizeOp(op:Binop, f1:Dynamic, f2:Dynamic):Dynamic {
|
||||
//trace("Optimizing " + f1 + " " + op + " " + f2);
|
||||
return switch(op) {
|
||||
case "+": f1 + f2;
|
||||
case "-": f1 - f2;
|
||||
case "*": f1 * f2;
|
||||
case "/": f1 / f2;
|
||||
case "%": f1 % f2;
|
||||
case "&": f1 & f2;
|
||||
case "|": f1 | f2;
|
||||
case "^": f1 ^ f2;
|
||||
case "<<": f1 << f2;
|
||||
case ">>": f1 >> f2;
|
||||
case ">>>": f1 >>> f2;
|
||||
case "==": f1 == f2;
|
||||
case "!=": f1 != f2;
|
||||
case ">=": f1 >= f2;
|
||||
case "<=": f1 <= f2;
|
||||
case ">": f1 > f2;
|
||||
case "<": f1 < f2;
|
||||
case "||": f1 == true || f2 == true;
|
||||
case "&&": f1 == true && f2 == true;
|
||||
case "??": f1 == null ? f2 : f1;
|
||||
case OpAdd: f1 + f2;
|
||||
case OpSub: f1 - f2;
|
||||
case OpMult: f1 * f2;
|
||||
case OpDiv: f1 / f2;
|
||||
case OpMod: f1 % f2;
|
||||
case OpAnd: f1 & f2;
|
||||
case OpOr: f1 | f2;
|
||||
case OpXor: f1 ^ f2;
|
||||
case OpShl: f1 << f2;
|
||||
case OpShr: f1 >> f2;
|
||||
case OpUShr: f1 >>> f2;
|
||||
case OpEq: f1 == f2;
|
||||
case OpNotEq: f1 != f2;
|
||||
case OpGte: f1 >= f2;
|
||||
case OpLte: f1 <= f2;
|
||||
case OpGt: f1 > f2;
|
||||
case OpLt: f1 < f2;
|
||||
case OpBoolOr: f1 == true || f2 == true;
|
||||
case OpBoolAnd: f1 == true && f2 == true;
|
||||
case OpNullCoal: f1 == null ? f2 : f1;
|
||||
default: null;
|
||||
}
|
||||
}
|
||||
|
||||
+51
-30
@@ -225,11 +225,13 @@ class Parser {
|
||||
}
|
||||
var expr = if( a.length == 1 ) a[0] else mk(EBlock(a),0);
|
||||
expr = Preprocessor.process(expr);
|
||||
if(Parser.optimize) {
|
||||
if(Parser.optimize)
|
||||
expr = Optimizer.optimize(expr);
|
||||
trace("INPUT: " + s);
|
||||
trace("OUTPUT: " + Printer.toString(expr));
|
||||
}
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
expr = Postprocessor.processvars(expr);
|
||||
#end
|
||||
// trace("INPUT: " + s); // useful for debugging
|
||||
//trace("OUTPUT: " + Printer.toString(expr));
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -465,7 +467,7 @@ class Parser {
|
||||
}
|
||||
default:
|
||||
}
|
||||
e = mk(EBinop("+", e, er));
|
||||
e = mk(EBinop(OpAdd, e, er));
|
||||
//e = mk(EParent(e));
|
||||
}
|
||||
while(tg.length > 0) {
|
||||
@@ -628,7 +630,7 @@ class Parser {
|
||||
var isTypeMap = (nextType != null) && nextType.match(CTPath(["Map"], [_, _]));
|
||||
var isMap = isTypeMap;
|
||||
if(!isMap) {
|
||||
isMap = Lambda.exists(a, (e) -> Tools.expr(e).match(EBinop("=>", _))); // Check if any element is a => b
|
||||
isMap = Lambda.exists(a, (e) -> Tools.expr(e).match(EBinop(OpArrow, _))); // Check if any element is a => b
|
||||
}
|
||||
if(isMap) {
|
||||
// TODO: clean up this code more
|
||||
@@ -640,7 +642,7 @@ class Parser {
|
||||
var values:Array<Expr> = [];
|
||||
for (e in a) {
|
||||
switch (Tools.expr(e)) {
|
||||
case EBinop("=>", eKey, eValue): {
|
||||
case EBinop(OpArrow, eKey, eValue): {
|
||||
switch(Tools.expr(eKey)) {
|
||||
case EConst(CInt(_)):// | EConst(CFloat(_)):
|
||||
isKeyInt = true;
|
||||
@@ -674,14 +676,14 @@ class Parser {
|
||||
|
||||
var t = b2i(isKeyString) + b2i(isKeyInt) + b2i(isKeyObject) + b2i(isKeyEnum);
|
||||
|
||||
var type:MapType = null;
|
||||
var type:MapType = Null;
|
||||
if(t != 1) type = UnknownMap;
|
||||
else if(isKeyInt) type = IntMap;
|
||||
else if(isKeyString) type = StringMap;
|
||||
else if(isKeyEnum) type = EnumMap;
|
||||
else if(isKeyObject) type = ObjectMap;
|
||||
|
||||
if(type == null)
|
||||
if(type == Null)
|
||||
error(EPreset(UNKNOWN_MAP_TYPE), p1, p1);
|
||||
|
||||
return parseExprNext(mk(EMapDecl(type, keys, values), p1));
|
||||
@@ -695,7 +697,12 @@ class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
#if cpp
|
||||
static inline function b2i(b:Bool) return untyped __cpp__("({0} ? 1 : 0)", b);
|
||||
//static inline function b2i(b:Bool) return untyped __cpp__("(int)({0})", b);
|
||||
#else
|
||||
static inline function b2i(b:Bool) return b ? 1 : 0;
|
||||
#end
|
||||
|
||||
function parseLambda( args : Array<Argument>, pmin ) {
|
||||
while( true ) {
|
||||
@@ -790,7 +797,7 @@ class Parser {
|
||||
default:
|
||||
// tmp.set(k, v);
|
||||
switch( Tools.expr(e) ) {
|
||||
case EBinop("=>", e1, e2):
|
||||
case EBinop(OpArrow, e1, e2):
|
||||
//ECall( mk(EField(mk(EIdent(tmp), pmin(e), pmax(e)), "set"), pmin(e), pmax(e)), [e1, e2]);
|
||||
ECall( mk(EIdent(tmp), pmin(e), pmax(e)), [e1, e2]);
|
||||
default: // default incase of error
|
||||
@@ -823,37 +830,48 @@ class Parser {
|
||||
isMapCompr(e2);
|
||||
default:
|
||||
// tmp.set(k, v);
|
||||
return Tools.expr(e).match(EBinop("=>", _));
|
||||
return Tools.expr(e).match(EBinop(OpArrow, _));
|
||||
}
|
||||
}
|
||||
|
||||
function makeUnop( op, e ) {
|
||||
function makeUnop( op:String, e:Expr ):Expr {
|
||||
var op = Tools.getUnopEnum(op);
|
||||
return _makeUnop(op, e);
|
||||
}
|
||||
|
||||
function _makeUnop( op:Unop, e:Expr ):Expr {
|
||||
if( e == null && resumeErrors )
|
||||
return null;
|
||||
return switch( Tools.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));
|
||||
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 ) {
|
||||
function makeBinop( op:String, e1:Expr, e:Expr ) {
|
||||
// TODO: clean this up
|
||||
if(!Tools.isValidBinOp(op))
|
||||
error(EInvalidOp(op),pmin(e1),pmax(e1));
|
||||
var op = Tools.getOpEnum(op);
|
||||
return _makeBinop(op, e1, e);
|
||||
}
|
||||
|
||||
function _makeBinop( op:Binop, e1:Expr, e:Expr ) {
|
||||
// TODO: clean this up
|
||||
if( e == null && resumeErrors )
|
||||
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
|
||||
return switch( Tools.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));
|
||||
if( opPriority.get(Printer.getBinaryOp(op)) <= opPriority.get(Printer.getBinaryOp(op2)) && !opRightAssoc.exists(Printer.getBinaryOp(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) )
|
||||
if( opRightAssoc.exists(Printer.getBinaryOp(op)) )
|
||||
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
||||
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:
|
||||
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
||||
}
|
||||
@@ -1167,10 +1185,12 @@ class Parser {
|
||||
|
||||
var fields = [];
|
||||
ensure(TBrOpen);
|
||||
while( !maybe(TBrClose) ) {
|
||||
if(token() == TSemicolon) continue;
|
||||
var a = parseExpr();
|
||||
fields.push(a);
|
||||
while( true ) {
|
||||
parseFullExpr(fields);
|
||||
tk = token();
|
||||
if( tk == TBrClose || (resumeErrors && tk == TEof) )
|
||||
break;
|
||||
push(tk);
|
||||
}
|
||||
|
||||
var tk = token();
|
||||
@@ -1224,7 +1244,7 @@ class Parser {
|
||||
var tk = token();
|
||||
switch( tk ) {
|
||||
case TId("case"):
|
||||
var c = new SwitchCase([], null);
|
||||
var c:SwitchCase = { values : [], expr : null };
|
||||
cases.push(c);
|
||||
disableOrOp = true;
|
||||
while( true ) {
|
||||
@@ -1327,7 +1347,7 @@ class Parser {
|
||||
push(tk);
|
||||
return e1;
|
||||
}
|
||||
return parseExprNext(mk(EUnop(op,false,e1),pmin(e1)));
|
||||
return parseExprNext(mk(EUnop(Tools.getUnopEnum(op),false,e1),pmin(e1)));
|
||||
}
|
||||
return makeBinop(op,e1,parseExpr());
|
||||
case TDot | TQuestionDot:
|
||||
@@ -2072,6 +2092,7 @@ class Parser {
|
||||
oldTokenMax = tokenMax;
|
||||
tokenMin = (this.char < 0) ? readPos : readPos - 1;
|
||||
var t = _token();
|
||||
//trace(t, infos);
|
||||
//ttrace(t, infos);
|
||||
tokenMax = (this.char < 0) ? readPos - 1 : readPos - 2;
|
||||
return t;
|
||||
@@ -2269,7 +2290,7 @@ class Parser {
|
||||
case '?'.code:
|
||||
var orp = readPos;
|
||||
if (readChar() == '='.code)
|
||||
return TOp("??"+"=");
|
||||
return TOp("??" + "=");
|
||||
|
||||
this.readPos = orp;
|
||||
return TOp("??");
|
||||
@@ -2458,7 +2479,7 @@ class Parser {
|
||||
}
|
||||
mk(EIdent(id), tokenMin, tokenMax);
|
||||
case TOp("!"):
|
||||
mk(EUnop("!", true, parsePreproCond()), tokenMin, tokenMax);
|
||||
mk(EUnop(OpNot, true, parsePreproCond()), tokenMin, tokenMax);
|
||||
default:
|
||||
unexpected(tk);
|
||||
}
|
||||
@@ -2476,13 +2497,13 @@ class Parser {
|
||||
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName() + " with " + Tools.expr(e2).getName()), readPos, readPos);
|
||||
return false;
|
||||
}
|
||||
case EUnop("!", _, e):
|
||||
case EUnop(OpNot, _, e):
|
||||
return !evalPreproCond(e);
|
||||
case EParent(e):
|
||||
return evalPreproCond(e);
|
||||
case EBinop("&&", e1, e2):
|
||||
case EBinop(OpBoolAnd, e1, e2):
|
||||
return evalPreproCond(e1) && evalPreproCond(e2);
|
||||
case EBinop("||", e1, e2):
|
||||
case EBinop(OpBoolOr, e1, e2):
|
||||
return evalPreproCond(e1) || evalPreproCond(e2);
|
||||
default:
|
||||
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName()), readPos, readPos);
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
package hscript;
|
||||
|
||||
import hscript.Expr;
|
||||
import hscript.Error;
|
||||
import hscript.Tools;
|
||||
import hscript.Parser;
|
||||
|
||||
@:access(hscript.Parser)
|
||||
class Postprocessor {
|
||||
static inline function expr(e:Expr) return Tools.expr(e);
|
||||
|
||||
static function mk(e:ExprDef, s:Expr):Expr {
|
||||
#if hscriptPos
|
||||
return new Expr(e, s.pmin, s.pmax, s.origin, s.line);
|
||||
#else
|
||||
return e;
|
||||
#end
|
||||
}
|
||||
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
public static function processvars(e:Expr, ?vars:Array<String>) {
|
||||
if(vars == null) vars = [];
|
||||
for(v in getvars(e)) vars.push(v);
|
||||
e = _processvars(e, vars);
|
||||
|
||||
return mk(EInfo(new InfoClass(vars), e), e);
|
||||
}
|
||||
|
||||
private static function _processvars(e:Expr, vars:Array<String>):Expr {
|
||||
if(e == null) return null;
|
||||
var ge = e;
|
||||
var doExtra = true;
|
||||
var e = switch (expr(e)) {
|
||||
case EIdent(v) if (v is String):
|
||||
mk(EIdent(vars.indexOf(v)), e);
|
||||
case EVar(n, t, _e, p, s) if (n is String):
|
||||
mk(EVar(vars.indexOf(n), t, _e, p, s), e);
|
||||
case EImport(c, IAs(n)) if (n is String):
|
||||
mk(EVar(vars.indexOf(n), null, mk(EImport(c, IAsReturn), e), false, false), e);
|
||||
case EFunction(args, _e, n, r, p, s, o) if (n is String):
|
||||
var _args:Array<Argument> = [
|
||||
for (arg in args)
|
||||
new Argument(vars.indexOf(arg.name), arg.t, arg.opt, arg.value)
|
||||
];
|
||||
mk(EFunction(_args, _e, vars.indexOf(n), r, p, s, o), e);
|
||||
case EFunction(args, _e, null, r, p, s, o):
|
||||
var _args:Array<Argument> = [
|
||||
for (arg in args)
|
||||
new Argument(vars.indexOf(arg.name), arg.t, arg.opt, arg.value)
|
||||
];
|
||||
mk(EFunction(_args, _e, null, r, p, s, o), e);
|
||||
case ENew(cl, p) if (cl is String):
|
||||
var p = [for(arg in p) arg];
|
||||
mk(ENew(vars.indexOf(cl), p), e);
|
||||
case EClass(n, fls, extnd, i) if (n is String):
|
||||
var fls:Array<Expr> = [for(f in fls) f];
|
||||
mk(EClass(vars.indexOf(n), fls, extnd, i), e);
|
||||
case ETry(_e, v, t, ec) if (v is String):
|
||||
mk(ETry(_e, vars.indexOf(v), t, ec), e);
|
||||
case EFor(v, it, _e) if (v is String):
|
||||
mk(EFor(vars.indexOf(v), it, _e), e);
|
||||
case EForKeyValue(v, it, _e, ithv) if (v is String && ithv is String):
|
||||
mk(EForKeyValue(vars.indexOf(v), it, _e, vars.indexOf(ithv)), e);
|
||||
default: {
|
||||
doExtra = false;
|
||||
e;
|
||||
}
|
||||
};
|
||||
|
||||
e = Tools.map(e, function(e) {
|
||||
return _processvars(e, vars);
|
||||
});
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
public static function getvars(se:Expr, ?vars:Array<String>):Array<String> {
|
||||
inline function pushVar(v:VarN) {
|
||||
if(v is String) {
|
||||
var v:String = cast v;
|
||||
if (!vars.contains(v))
|
||||
vars.push(v);
|
||||
}
|
||||
};
|
||||
|
||||
if(vars == null) vars = [];
|
||||
Tools.iterExprRecursive(se, (e) -> {
|
||||
switch (expr(e)) {
|
||||
case EVar(n, t, e, _,_): pushVar(n);
|
||||
case EIdent(v): pushVar(v);
|
||||
case EFunction(args,e,name,_,_,_,_):
|
||||
pushVar(name);
|
||||
for (a in args) {
|
||||
pushVar(a.name);
|
||||
}
|
||||
case EFor(v,it,e): pushVar(v);
|
||||
case EForKeyValue(v,it,e,ithv): pushVar(ithv); pushVar(v);
|
||||
case ETry(e, v, _, ec): pushVar(v);
|
||||
case ENew(cl, params): pushVar(cl);
|
||||
case EClass(name, fls,_,_): pushVar(name);
|
||||
default:
|
||||
}
|
||||
});
|
||||
return vars;
|
||||
}
|
||||
#end
|
||||
}
|
||||
+364
-294
@@ -49,6 +49,11 @@ class Printer {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static function convertTypeToString( t : CType ) {
|
||||
var printer = new Printer();
|
||||
return printer.typeToString(t);
|
||||
}
|
||||
|
||||
inline function add<T>(s:T) buf.add(s);
|
||||
|
||||
function type( t : CType ) {
|
||||
@@ -73,11 +78,14 @@ class Printer {
|
||||
type(t);
|
||||
case CTFun(args, ret) if (Lambda.exists(args, function (a) return a.match(CTNamed(_, _)))):
|
||||
add('(');
|
||||
for (a in args)
|
||||
var first = true;
|
||||
for (i=>a in args) {
|
||||
switch a {
|
||||
case CTNamed(_, _): type(a);
|
||||
default: type(CTNamed('_', a));
|
||||
}
|
||||
if( i != args.length - 1 ) add(", ");
|
||||
}
|
||||
add(')->');
|
||||
type(ret);
|
||||
case CTFun(args, ret):
|
||||
@@ -196,6 +204,59 @@ class Printer {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
function getVar(v:VarN) {
|
||||
if( v == null ) {
|
||||
return ("??NULL??");
|
||||
}
|
||||
|
||||
if(v is Int) {
|
||||
return ("$" + v);
|
||||
} else {
|
||||
return (v);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getBinaryOp(op:Binop) {
|
||||
return switch(op) {
|
||||
case OpAdd: "+";
|
||||
case OpSub: "-";
|
||||
case OpMult: "*";
|
||||
case OpDiv: "/";
|
||||
case OpMod: "%";
|
||||
case OpAnd: "&";
|
||||
case OpOr: "|";
|
||||
case OpXor: "^";
|
||||
case OpShl: "<<";
|
||||
case OpShr: ">>";
|
||||
case OpUShr: ">>>";
|
||||
case OpEq: "==";
|
||||
case OpNotEq: "!=";
|
||||
case OpGt: ">";
|
||||
case OpGte: ">=";
|
||||
case OpLt: "<";
|
||||
case OpLte: "<=";
|
||||
case OpBoolAnd: "&&";
|
||||
case OpBoolOr: "||";
|
||||
case OpIs: "is";
|
||||
case OpNullCoal: "??";
|
||||
case OpAssign: "=";
|
||||
case OpArrow: "=>";
|
||||
case OpInterval: "...";
|
||||
case OpAssignOp(op): getBinaryOp(op) + "=";
|
||||
}
|
||||
}
|
||||
|
||||
public static function getUnaryOp(op:Unop) {
|
||||
return switch(op) {
|
||||
case OpIncrement: "++";
|
||||
case OpDecrement: "--";
|
||||
case OpNot: "!";
|
||||
case OpNeg: "-";
|
||||
case OpNegBits: "~";
|
||||
case OpSpread: "...";
|
||||
}
|
||||
}
|
||||
|
||||
function expr( e : Expr ) {
|
||||
if( e == null ) {
|
||||
add("??NULL??");
|
||||
@@ -205,314 +266,323 @@ class Printer {
|
||||
// TODO: make else if print correctly
|
||||
|
||||
switch( Tools.expr(e) ) {
|
||||
case EImport(c, mode):
|
||||
add("import " + c);
|
||||
switch(mode) {
|
||||
case IAs(name): add(' as $name');
|
||||
case IAll: add('.*');
|
||||
default:
|
||||
}
|
||||
case EClass(name, fields, extend, interfaces):
|
||||
add('class $name');
|
||||
if (extend != null)
|
||||
add(' extends $extend');
|
||||
for(_interface in interfaces) {
|
||||
add(' implements $_interface');
|
||||
}
|
||||
add(' {\n');
|
||||
tabs += "\t";
|
||||
// TODO: Print fields
|
||||
//for(field in fields) {
|
||||
// expr(field);
|
||||
//}
|
||||
|
||||
tabs = tabs.substr(1);
|
||||
add("}");
|
||||
case EConst(c):
|
||||
switch( c ) {
|
||||
case CInt(i): add(i);
|
||||
case CFloat(f): add(f);
|
||||
case CString(s):
|
||||
add('"');
|
||||
add(getEscapedString(s));
|
||||
add('"');
|
||||
}
|
||||
case EIdent(v):
|
||||
add(v);
|
||||
case EVar(n, t, e): // TODO: static, public, override
|
||||
add("var " + n);
|
||||
if( t != null )
|
||||
addType(t);
|
||||
else
|
||||
switch( Tools.expr(e) ) {
|
||||
case EMapDecl(type, _, _):
|
||||
add(" : Map<");
|
||||
switch( type ) {
|
||||
case ObjectMap: add("Dynamic");
|
||||
case StringMap: add("String");
|
||||
case EnumMap: add("EnumValue");
|
||||
case IntMap: add("Int");
|
||||
case UnknownMap: add("?");
|
||||
}
|
||||
add(", Dynamic>");
|
||||
case EImport(c, mode):
|
||||
add("import " + c);
|
||||
switch(mode) {
|
||||
case IAs(name): add(' as $name');
|
||||
case IAll: add('.*');
|
||||
default:
|
||||
}
|
||||
if( e != null ) {
|
||||
add(" = ");
|
||||
expr(e);
|
||||
}
|
||||
case EParent(e):
|
||||
add("("); expr(e); add(")");
|
||||
case EBlock(el):
|
||||
if( el.length == 0 ) {
|
||||
add("{}");
|
||||
} else {
|
||||
case EClass(name, fields, extend, interfaces):
|
||||
add('class ${getVar(name)}');
|
||||
if (extend != null)
|
||||
add(' extends $extend');
|
||||
for(_interface in interfaces) {
|
||||
add(' implements $_interface');
|
||||
}
|
||||
add(' {\n');
|
||||
tabs += "\t";
|
||||
add("{\n");
|
||||
for( e in el ) {
|
||||
add(tabs);
|
||||
// TODO: Print fields
|
||||
//for(field in fields) {
|
||||
// expr(field);
|
||||
//}
|
||||
|
||||
tabs = tabs.substr(1);
|
||||
add("}");
|
||||
case EConst(c):
|
||||
switch( c ) {
|
||||
case CInt(i): add(i);
|
||||
case CFloat(f): add(f);
|
||||
case CString(s):
|
||||
add('"');
|
||||
add(getEscapedString(s));
|
||||
add('"');
|
||||
}
|
||||
case EIdent(v):
|
||||
add(getVar(v));
|
||||
case EVar(n, t, e): // TODO: static, public, override
|
||||
add("var " + getVar(n));
|
||||
if( t != null )
|
||||
addType(t);
|
||||
else
|
||||
switch( Tools.expr(e) ) {
|
||||
case EMapDecl(type, _, _):
|
||||
add(" : Map<");
|
||||
switch( type ) {
|
||||
case ObjectMap: add("Dynamic");
|
||||
case StringMap: add("String");
|
||||
case EnumMap: add("EnumValue");
|
||||
case IntMap: add("Int");
|
||||
case UnknownMap: add("?");
|
||||
case Null: add("Null");
|
||||
}
|
||||
add(", Dynamic>");
|
||||
default:
|
||||
}
|
||||
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(tabs);
|
||||
add("}");
|
||||
}
|
||||
case EField(e, f, s):
|
||||
expr(e);
|
||||
add((s == true ? "?." : ".") + f);
|
||||
case EBinop(op, e1, e2):
|
||||
/*var op1 = switch(Tools.expr(e1)) {
|
||||
case EBinop(op, _, _): op;
|
||||
case EConst(_): "_";
|
||||
case EIdent(_): "_";
|
||||
default: null;
|
||||
}
|
||||
var op2 = switch(Tools.expr(e2)) {
|
||||
case EBinop(op, _, _): op;
|
||||
case EConst(_): "_";
|
||||
case EIdent(_): "_";
|
||||
default: null;
|
||||
}
|
||||
var paran = Tools.checkOpPrecedence(op, op1, op2);*/
|
||||
var paran = 2;
|
||||
|
||||
var op = getBinaryOp(op);
|
||||
|
||||
if(paran == 0 || paran == 2) {
|
||||
add("(");
|
||||
expr(e1);
|
||||
add(")");
|
||||
} else {
|
||||
expr(e1);
|
||||
}
|
||||
if(op == "...")
|
||||
add(op);
|
||||
else
|
||||
add(" " + op + " ");
|
||||
if(paran == 1 || paran == 2) {
|
||||
add("(");
|
||||
expr(e2);
|
||||
add(")");
|
||||
} else {
|
||||
expr(e2);
|
||||
}
|
||||
case EUnop(op, pre, e):
|
||||
var op = getUnaryOp(op);
|
||||
|
||||
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(" )");
|
||||
var wasBlock = block(e1, true);
|
||||
|
||||
if( e2 != null ) {
|
||||
if(!wasBlock) add("\n" + tabs);
|
||||
add(" else ");
|
||||
block(e2);
|
||||
}
|
||||
case EWhile(cond,e):
|
||||
add("while( ");
|
||||
expr(cond);
|
||||
add(" )");
|
||||
block(e, true);
|
||||
case EDoWhile(cond,e):
|
||||
add("do");
|
||||
block(e, true);
|
||||
add(" while ( ");
|
||||
expr(cond);
|
||||
add(" )");
|
||||
case EFor(v, it, e):
|
||||
add("for( "+getVar(v)+" in ");
|
||||
expr(it);
|
||||
add(" )");
|
||||
block(e, true);
|
||||
case EForKeyValue(v, it, e, ithv):
|
||||
add("for( "+getVar(ithv)+" => "+getVar(v)+" in ");
|
||||
expr(it);
|
||||
add(" )");
|
||||
block(e, true);
|
||||
case EBreak:
|
||||
add("break");
|
||||
case EContinue:
|
||||
add("continue");
|
||||
case EFunction(params, e, name, ret): // TODO: static, public, override
|
||||
add("function");
|
||||
if( name != null )
|
||||
add(" " + getVar(name));
|
||||
add("(");
|
||||
var first = true;
|
||||
for( a in params ) {
|
||||
if( first ) first = false else add(", ");
|
||||
if( a.opt ) add("?");
|
||||
add(getVar(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 EMapDecl(type, keys, values):
|
||||
add("[");
|
||||
var first = true;
|
||||
for( i in 0...keys.length ) {
|
||||
if( first ) first = false else add(", ");
|
||||
expr(keys[i]);
|
||||
add(" => ");
|
||||
expr(values[i]);
|
||||
}
|
||||
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):
|
||||
add("new " + getVar(cl) + "(");
|
||||
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");
|
||||
var wasBlock = block(e);
|
||||
if( !wasBlock ) {
|
||||
add("\n" + tabs);
|
||||
} else add(" ");
|
||||
add("catch( " + v);
|
||||
addType(t);
|
||||
add(" )");
|
||||
block(ecatch);
|
||||
case EObject(fl):
|
||||
if( fl.length == 0 ) {
|
||||
add("{}");
|
||||
} else {
|
||||
tabs += "\t";
|
||||
add("{\n");
|
||||
for( i=>f in fl ) {
|
||||
add(tabs);
|
||||
var name = isJson(f.name) ? "\"" + f.name + "\"" : f.name;
|
||||
add(name+" : ");
|
||||
expr(f.e);
|
||||
if( i != fl.length - 1 ) add(",");
|
||||
add("\n");
|
||||
}
|
||||
tabs = tabs.substr(1);
|
||||
add(tabs);
|
||||
add("}");
|
||||
}
|
||||
case ETernary(c,e1,e2):
|
||||
expr(c);
|
||||
add(" ? ");
|
||||
expr(e1);
|
||||
add(" : ");
|
||||
expr(e2);
|
||||
case ESwitch(e, cases, def):
|
||||
add("switch( ");
|
||||
expr(e);
|
||||
add(" ) {\n");
|
||||
tabs += "\t";
|
||||
for( c in cases ) {
|
||||
add(tabs);
|
||||
add("case ");
|
||||
var first = true;
|
||||
for( v in c.values ) {
|
||||
if( first ) first = false else add(", ");
|
||||
expr(v);
|
||||
}
|
||||
add(":");
|
||||
block(c.expr, true);
|
||||
add(";\n");
|
||||
}
|
||||
if( def != null ) {
|
||||
add(tabs);
|
||||
add("default: ");
|
||||
block(def, true);
|
||||
add(";\n");
|
||||
}
|
||||
tabs = tabs.substr(1);
|
||||
add(tabs);
|
||||
add("}");
|
||||
}
|
||||
case EField(e, f, s):
|
||||
expr(e);
|
||||
add((s == true ? "?." : ".") + f);
|
||||
case EBinop(op, e1, e2):
|
||||
var shouldParen = false;
|
||||
var op1 = switch(Tools.expr(e1)) {
|
||||
case EBinop(op, _, _): op;
|
||||
case EConst(_): "_";
|
||||
case EIdent(_): "_";
|
||||
default: null;
|
||||
}
|
||||
var op2 = switch(Tools.expr(e2)) {
|
||||
case EBinop(op, _, _): op;
|
||||
case EConst(_): "_";
|
||||
case EIdent(_): "_";
|
||||
default: null;
|
||||
}
|
||||
var paran = Tools.checkOpPrecedence(op, op1, op2);
|
||||
|
||||
if(paran == 0 || paran == 2) {
|
||||
add("(");
|
||||
expr(e1);
|
||||
add(")");
|
||||
} else {
|
||||
expr(e1);
|
||||
}
|
||||
if(op == "...")
|
||||
add(op);
|
||||
else
|
||||
add(" " + op + " ");
|
||||
if(paran == 1 || paran == 2) {
|
||||
add("(");
|
||||
expr(e2);
|
||||
add(")");
|
||||
} else {
|
||||
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:
|
||||
case EMeta(name, args, e):
|
||||
add("@");
|
||||
add(name);
|
||||
if( args != null && args.length > 0 ) {
|
||||
add("(");
|
||||
expr(e);
|
||||
var first = true;
|
||||
for( a in args ) {
|
||||
if( first ) first = false else 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(" )");
|
||||
var wasBlock = block(e1, true);
|
||||
|
||||
if( e2 != null ) {
|
||||
if(!wasBlock) add("\n" + tabs);
|
||||
add(" else ");
|
||||
block(e2);
|
||||
}
|
||||
case EWhile(cond,e):
|
||||
add("while( ");
|
||||
expr(cond);
|
||||
add(" )");
|
||||
block(e, true);
|
||||
case EDoWhile(cond,e):
|
||||
add("do");
|
||||
block(e, true);
|
||||
add(" while ( ");
|
||||
expr(cond);
|
||||
add(" )");
|
||||
case EFor(v, it, e):
|
||||
add("for( "+v+" in ");
|
||||
expr(it);
|
||||
add(" )");
|
||||
block(e, true);
|
||||
case EForKeyValue(v, it, e, ithv):
|
||||
add("for( "+ithv+" => "+v+" in ");
|
||||
expr(it);
|
||||
add(" )");
|
||||
block(e, true);
|
||||
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 EMapDecl(type, keys, values):
|
||||
add("[");
|
||||
var first = true;
|
||||
for( i in 0...keys.length ) {
|
||||
if( first ) first = false else add(", ");
|
||||
expr(keys[i]);
|
||||
add(" => ");
|
||||
expr(values[i]);
|
||||
}
|
||||
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):
|
||||
add("new " + cl + "(");
|
||||
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");
|
||||
var wasBlock = block(e);
|
||||
if( !wasBlock ) {
|
||||
add("\n" + tabs);
|
||||
} else add(" ");
|
||||
add("catch( " + v);
|
||||
addType(t);
|
||||
add(" )");
|
||||
block(ecatch);
|
||||
case EObject(fl):
|
||||
if( fl.length == 0 ) {
|
||||
add("{}");
|
||||
} else {
|
||||
tabs += "\t";
|
||||
add("{\n");
|
||||
for( i=>f in fl ) {
|
||||
add(tabs);
|
||||
var name = isJson(f.name) ? "\"" + f.name + "\"" : f.name;
|
||||
add(name+" : ");
|
||||
expr(f.e);
|
||||
if( i != fl.length - 1 ) add(",");
|
||||
add("\n");
|
||||
}
|
||||
tabs = tabs.substr(1);
|
||||
add(tabs);
|
||||
add("}");
|
||||
}
|
||||
case ETernary(c,e1,e2):
|
||||
expr(c);
|
||||
add(" ? ");
|
||||
expr(e1);
|
||||
add(" : ");
|
||||
expr(e2);
|
||||
case ESwitch(e, cases, def):
|
||||
add("switch( ");
|
||||
expr(e);
|
||||
add(" ) {\n");
|
||||
tabs += "\t";
|
||||
for( c in cases ) {
|
||||
add(tabs);
|
||||
add("case ");
|
||||
var first = true;
|
||||
for( v in c.values ) {
|
||||
if( first ) first = false else add(", ");
|
||||
expr(v);
|
||||
}
|
||||
add(":");
|
||||
block(c.expr, true);
|
||||
add(";\n");
|
||||
}
|
||||
if( def != null ) {
|
||||
add(tabs);
|
||||
add("default: ");
|
||||
block(def, true);
|
||||
add(";\n");
|
||||
}
|
||||
tabs = tabs.substr(1);
|
||||
add(tabs);
|
||||
add("}");
|
||||
case EMeta(name, args, e):
|
||||
add("@");
|
||||
add(name);
|
||||
if( args != null && args.length > 0 ) {
|
||||
case ECheckType(e, t):
|
||||
add("(");
|
||||
var first = true;
|
||||
for( a in args ) {
|
||||
if( first ) first = false else add(", ");
|
||||
expr(e);
|
||||
}
|
||||
expr(e);
|
||||
add(" : ");
|
||||
addType(t);
|
||||
add(")");
|
||||
}
|
||||
add(" ");
|
||||
expr(e);
|
||||
case ECheckType(e, t):
|
||||
add("(");
|
||||
expr(e);
|
||||
add(" : ");
|
||||
addType(t);
|
||||
add(")");
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
case EInfo(_, e):
|
||||
expr(e);
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+161
-63
@@ -27,75 +27,125 @@ class Tools {
|
||||
|
||||
public static function iter( e : Expr, f : Expr -> 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 EForKeyValue(_, 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 EMapDecl(type, keys, values): for( e in keys ) f(e); for( e in values ) f(e);
|
||||
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);
|
||||
case EConst(_), EIdent(_): f(e);
|
||||
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 EForKeyValue(_, 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 EMapDecl(type, keys, values): for( e in keys ) f(e); for( e in values ) f(e);
|
||||
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);
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
case EInfo(info, e): f(e);
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
public static function iterExprRecursive( ve : Expr, f : Expr -> Void ) {
|
||||
var rec = (e:Expr) -> iterExprRecursive(e, f);
|
||||
f(ve);
|
||||
switch( expr(ve) ) {
|
||||
case EConst(_), EIdent(_): {}
|
||||
case EImport(c, _): {}
|
||||
case EClass(_, e, _, _): for( a in e ) rec(a);
|
||||
case EVar(_, _, e): if( e != null ) rec(e);
|
||||
case EParent(e, _): rec(e);
|
||||
case EBlock(el): for( e in el ) rec(e);
|
||||
case EField(e, _): rec(e);
|
||||
case EBinop(_, e1, e2): rec(e1); rec(e2);
|
||||
case EUnop(_, _, e): rec(e);
|
||||
case ECall(e, args): rec(e); for( a in args ) rec(a);
|
||||
case EIf(c, e1, e2): rec(c); rec(e1); if( e2 != null ) rec(e2);
|
||||
case EWhile(c, e): rec(c); rec(e);
|
||||
case EDoWhile(c, e): rec(c); rec(e);
|
||||
case EFor(_, it, e): rec(it); rec(e);
|
||||
case EForKeyValue(_, it, e, _): rec(it); rec(e);
|
||||
case EBreak,EContinue: {}
|
||||
case EFunction(_, e, _, _): rec(e);
|
||||
case EReturn(e): if( e != null ) rec(e);
|
||||
case EArray(e, i): rec(e); rec(i);
|
||||
case EMapDecl(type, keys, values): for( e in keys ) rec(e); for( e in values ) rec(e);
|
||||
case EArrayDecl(el): for( e in el ) rec(e);
|
||||
case ENew(_,el): for( e in el ) rec(e);
|
||||
case EThrow(e): rec(e);
|
||||
case ETry(e, _, _, c): rec(e); rec(c);
|
||||
case EObject(fl): for( fi in fl ) rec(fi.e);
|
||||
case ETernary(c, e1, e2): rec(c); rec(e1); rec(e2);
|
||||
case ESwitch(e, cases, def):
|
||||
rec(e);
|
||||
for( c in cases ) {
|
||||
for( v in c.values ) rec(v);
|
||||
rec(c.expr);
|
||||
}
|
||||
if( def != null ) rec(def);
|
||||
case EMeta(name, args, e): if( args != null ) for( a in args ) rec(a); rec(e);
|
||||
case ECheckType(e,_): rec(e);
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
case EInfo(info, e): rec(e);
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
public static function map( e : Expr, f : Expr -> Expr ) {
|
||||
var edef = switch( expr(e) ) {
|
||||
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
|
||||
case EVar(n, t, e, p, s): EVar(n, t, if( e != null ) f(e) else null, p, s);
|
||||
case EParent(e, no): EParent(f(e), no);
|
||||
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
||||
case EField(e, fi, s): EField(f(e),fi,s);
|
||||
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 EForKeyValue(v, it, e, ithv): EForKeyValue(v, f(it), f(e), ithv);
|
||||
case EFunction(args, e, name, t, p, s, o): EFunction(args, f(e), name, t, p, s, o);
|
||||
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
||||
case EArray(e, i): EArray(f(e),f(i));
|
||||
case EMapDecl(type, keys, values): EMapDecl(type, [for( e in keys ) f(e)], [for( e in values ) 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 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 ) new ObjectField(fi.name, 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 ) new SwitchCase([for( v in c.values ) f(v)], 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, m): EImport(c, m);
|
||||
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
|
||||
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
|
||||
case EVar(n, t, e, p, s): EVar(n, t, if( e != null ) f(e) else null, p, s);
|
||||
case EParent(e, no): EParent(f(e), no);
|
||||
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
||||
case EField(e, fi, s): EField(f(e),fi,s);
|
||||
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 EForKeyValue(v, it, e, ithv): EForKeyValue(v, f(it), f(e), ithv);
|
||||
case EFunction(args, e, name, t, p, s, o): EFunction(args, f(e), name, t, p, s, o);
|
||||
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
||||
case EArray(e, i): EArray(f(e),f(i));
|
||||
case EMapDecl(type, keys, values): EMapDecl(type, [for( e in keys ) f(e)], [for( e in values ) 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 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 ) new ObjectField(fi.name, 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, m): EImport(c, m);
|
||||
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
|
||||
#if !HSCRIPT_NO_INT_VARS
|
||||
case EInfo(info, e): EInfo(info, f(e));
|
||||
#end
|
||||
}
|
||||
return mk(edef, e);
|
||||
}
|
||||
@@ -133,6 +183,54 @@ class Tools {
|
||||
}
|
||||
}
|
||||
|
||||
public static function getOpEnum(op:String):Binop {
|
||||
return switch(op) {
|
||||
case "+": OpAdd;
|
||||
case "-": OpSub;
|
||||
case "*": OpMult;
|
||||
case "/": OpDiv;
|
||||
case "%": OpMod;
|
||||
case "&": OpAnd;
|
||||
case "|": OpOr;
|
||||
case "^": OpXor;
|
||||
case "<<": OpShl;
|
||||
case ">>": OpShr;
|
||||
case ">>>": OpUShr;
|
||||
case "==": OpEq;
|
||||
case "!=": OpNotEq;
|
||||
case ">=": OpGte;
|
||||
case "<=": OpLte;
|
||||
case ">": OpGt;
|
||||
case "<": OpLt;
|
||||
case "||": OpBoolOr;
|
||||
case "&&": OpBoolAnd;
|
||||
case "is": OpIs;
|
||||
case "=": OpAssign;
|
||||
case "=>": OpArrow;
|
||||
case "??": OpNullCoal;
|
||||
case "...": OpInterval;
|
||||
default: {
|
||||
var op2 = op.substr(0, op.length - 1);
|
||||
if(isValidBinOp(op2)) {
|
||||
return OpAssignOp(getOpEnum(op2));
|
||||
}
|
||||
throw "Unknown binary operator: " + op;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getUnopEnum(op:String):Unop {
|
||||
return switch(op) {
|
||||
case "++": OpIncrement;
|
||||
case "--": OpDecrement;
|
||||
case "!": OpNot;
|
||||
case "-": OpNeg;
|
||||
case "~": OpNegBits;
|
||||
case "...": OpSpread;
|
||||
default: throw "Unknown unary operator: " + op;
|
||||
}
|
||||
}
|
||||
|
||||
static var priorities = [
|
||||
["%"],
|
||||
["*", "/"],
|
||||
|
||||
@@ -144,12 +144,16 @@ class ClassExtendMacro {
|
||||
|
||||
//trace(getModuleName(cl));
|
||||
|
||||
var hasNew = false;
|
||||
|
||||
for(_field in [fields.copy(), superFields.copy()])
|
||||
for(f in _field) {
|
||||
if (f == null)
|
||||
continue;
|
||||
if (f.name == "new")
|
||||
if (f.name == "new") {
|
||||
hasNew = true;
|
||||
continue;
|
||||
}
|
||||
if (f.name.startsWith(FUNC_PREFIX))
|
||||
continue;
|
||||
if (f.access.contains(ADynamic) || f.access.contains(AStatic) || f.access.contains(AExtern) || f.access.contains(AInline))
|
||||
@@ -183,10 +187,10 @@ class ClassExtendMacro {
|
||||
overrideExpr = macro {
|
||||
var name:String = $v{name};
|
||||
|
||||
if (__interp != null) {
|
||||
if (__custom__variables.exists(name)) {
|
||||
if (__custom__variables != null) {
|
||||
if(__custom__variables.exists(name)) {
|
||||
var v:Dynamic = null;
|
||||
if(Reflect.isFunction(v = __custom__variables.get(name))) {
|
||||
if (Reflect.isFunction(v = __custom__variables.get(name))) {
|
||||
return v($a{arguments});
|
||||
}
|
||||
}
|
||||
@@ -197,10 +201,10 @@ class ClassExtendMacro {
|
||||
overrideExpr = macro {
|
||||
var name:String = $v{name};
|
||||
|
||||
if (__interp != null) {
|
||||
if (__custom__variables.exists(name)) {
|
||||
if (__custom__variables != null) {
|
||||
if(__custom__variables.exists(name)) {
|
||||
var v:Dynamic = null;
|
||||
if(Reflect.isFunction(v = __custom__variables.get(name))) {
|
||||
if (Reflect.isFunction(v = __custom__variables.get(name))) {
|
||||
v($a{arguments});
|
||||
return;
|
||||
}
|
||||
@@ -257,6 +261,13 @@ class ClassExtendMacro {
|
||||
}
|
||||
}
|
||||
|
||||
var totalFields = definedFields.length;
|
||||
|
||||
if(totalFields == 0 && !hasNew) {
|
||||
//Sys.println(cl.pack.join(".") + "." + cl.name + ", " + totalFields);
|
||||
return fields;
|
||||
}
|
||||
|
||||
shadowClass.kind = TDClass({
|
||||
pack: cl.pack.copy(),
|
||||
name: cl.name
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@
|
||||
--define linux
|
||||
|
||||
# Copying the assets from source code to bin folder
|
||||
--cmd rm -rf bin/cpp/assets
|
||||
--cmd cp -r assets bin/cpp/assets
|
||||
# --cmd rm -rf bin/cpp/assets
|
||||
# --cmd cp -r assets bin/cpp/assets
|
||||
--cpp bin/cpp
|
||||
--cmd cd bin/cpp
|
||||
--cmd ./Main
|
||||
+2
-2
@@ -27,8 +27,8 @@
|
||||
|
||||
|
||||
# Copying the assets from source code to bin folder
|
||||
--cmd rm -rf bin/cpp/assets
|
||||
--cmd cp -r assets bin/cpp/assets
|
||||
# --cmd rm -rf bin/cpp/assets
|
||||
# --cmd cp -r assets bin/cpp/assets
|
||||
--cpp bin/cpp
|
||||
--cmd cd bin/cpp
|
||||
--cmd ./Main
|
||||
+29
-1
@@ -12,7 +12,35 @@ class Main {
|
||||
Sys.println("Running benchmark");
|
||||
|
||||
//new Benchmark("Test", 1000);
|
||||
new TestBenchmark();
|
||||
var haxeTotalTime:Float = 0;
|
||||
var hscriptTotalTime:Float = 0;
|
||||
|
||||
var haxeTimes:Array<Float> = [];
|
||||
var hscriptTimes:Array<Float> = [];
|
||||
|
||||
var iterations:Int = 10;
|
||||
for (i in 0...iterations) {
|
||||
var benchmark:TestBenchmark = new TestBenchmark();
|
||||
|
||||
haxeTimes.push(benchmark.haxeTotalTime);
|
||||
hscriptTimes.push(benchmark.hscriptTotalTime);
|
||||
|
||||
haxeTotalTime += benchmark.haxeTotalTime;
|
||||
hscriptTotalTime += benchmark.hscriptTotalTime;
|
||||
}
|
||||
|
||||
haxeTimes.sort((a, b) -> return a > b ? 1 : -1);
|
||||
hscriptTimes.sort((a, b) -> return a > b ? 1 : -1);
|
||||
|
||||
var slowestHaxeTime:Float = haxeTimes[haxeTimes.length-1];
|
||||
var slowestHscriptTime:Float = hscriptTimes[hscriptTimes.length-1];
|
||||
var fastestHaxeTime:Float = haxeTimes[0];
|
||||
var fastestHscriptTime:Float = hscriptTimes[0];
|
||||
|
||||
var haxeWon = hscriptTotalTime > haxeTotalTime;
|
||||
Sys.println('${haxeWon ? "Haxe" : "Hscript"} was faster overall (Faster by: ${Util.roundWith((haxeWon ? hscriptTotalTime/haxeTotalTime : haxeTotalTime/hscriptTotalTime), 100)}x)');
|
||||
Sys.println('Haxe average time: ${Util.convertToReadableTime(haxeTotalTime/iterations)} (Highest: ${Util.convertToReadableTime(slowestHaxeTime)}) (Lowest: ${Util.convertToReadableTime(fastestHaxeTime)})');
|
||||
Sys.println('Hscript average time: ${Util.convertToReadableTime(hscriptTotalTime/iterations)} (Highest: ${Util.convertToReadableTime(slowestHscriptTime)}) (Lowest: ${Util.convertToReadableTime(fastestHscriptTime)})');
|
||||
#else
|
||||
Sys.println("Beginning tests");
|
||||
if(!Main.SHOW_KNOWN_BUGS) {
|
||||
|
||||
@@ -210,6 +210,7 @@ class Util {
|
||||
// Print stack trace
|
||||
var stack = haxe.CallStack.toString(haxe.CallStack.exceptionStack());
|
||||
Sys.println("## Stack trace: " + stack);
|
||||
Sys.exit(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,10 @@ class Benchmark extends HScriptRunner {
|
||||
|
||||
public function new(name:String, iterations:Int) {
|
||||
super();
|
||||
doBenchmark(name, iterations);
|
||||
}
|
||||
|
||||
public function doBenchmark(name:String, iterations:Int) {
|
||||
haxeTimes = cast new haxe.ds.Vector<Float>(iterations);
|
||||
hscriptTimes = cast new haxe.ds.Vector<Float>(iterations);
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ class FinalCase extends TestCase {
|
||||
assertDisplay("(i - x) * 30 + 90", ((i-x) * 30) + 90);
|
||||
assertDisplay("i - x * 30 + 90", i-x * 30 + 90);
|
||||
|
||||
/*
|
||||
// Test operator precedence
|
||||
assertDisplay("i / x * 30 + 90", i / x * 30 + 90);
|
||||
assertDisplay("i / (x * 30) + 90", i / (x * 30) + 90);
|
||||
@@ -44,6 +45,7 @@ class FinalCase extends TestCase {
|
||||
bloomShader.dim = dim = .8 + (.3 * FlxMath.fastSin(__totalTime));
|
||||
bloomShader.size = size = 18 + (8 * FlxMath.fastSin(__totalTime));
|
||||
');
|
||||
*/
|
||||
|
||||
Util.parse('sprite.setPosition(codesList.x + (sprite.ID % 2 == 1 ? 240 : 67),codesList.y + (15 * sprite.ID) + (sprite.ID%2 == 1 ? 35 : 54));');
|
||||
|
||||
@@ -74,7 +76,6 @@ class FinalCase extends TestCase {
|
||||
|
||||
assertEq("[for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]", [for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]);
|
||||
assertEq("[for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]", [for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]);
|
||||
|
||||
headerCode = "function area(a:Int, b:Int):Int { return a * b; };";
|
||||
function area(a:Int, b:Int):Int { return a * b; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user