committed by
Nicolas Cannasse
parent
bdd55483f9
commit
a1af1ec29e
@@ -1,3 +1,5 @@
|
||||
import haxe.ds.EnumValueMap;
|
||||
import haxe.ds.Option;
|
||||
import hscript.Macro;
|
||||
import haxe.unit.*;
|
||||
|
||||
@@ -94,6 +96,55 @@ class Test extends TestCase {
|
||||
assertScript("/**/0", 0);
|
||||
assertScript("x=1;x*=-2", -2);
|
||||
}
|
||||
|
||||
function testMap():Void {
|
||||
var objKey = { ok:true };
|
||||
var vars = {
|
||||
stringMap: ["foo" => "Foo", "bar" => "Bar"],
|
||||
intMap:[100 => "one hundred"],
|
||||
objKey: objKey,
|
||||
objMap:[objKey => "ok"],
|
||||
enumKey:Option.Some("some"),
|
||||
enumMap:new EnumValueMap<Option<String>, String>(),
|
||||
stringIntMap: ["foo" => 100]
|
||||
}
|
||||
vars.enumMap.set(vars.enumKey, "ok");
|
||||
|
||||
assertScript('stringMap["foo"]', "Foo", vars);
|
||||
assertScript('intMap[100]', "one hundred", vars);
|
||||
assertScript('objMap[objKey]', "ok", vars);
|
||||
assertScript('enumMap[enumKey]', "ok", vars);
|
||||
assertScript('stringMap["a"] = "A"; stringMap["a"]', "A", vars);
|
||||
assertScript('intMap[200] = objMap[{foo:false}] = enumMap[enumKey] = "A"', "A", vars);
|
||||
assertEquals('A', vars.intMap[200]);
|
||||
assertEquals('A', vars.enumMap.get(vars.enumKey));
|
||||
for (key in vars.objMap.keys()) {
|
||||
if (key != objKey) {
|
||||
assertEquals(false, (key:Dynamic).foo);
|
||||
assertEquals('A', vars.objMap[key]);
|
||||
}
|
||||
}
|
||||
|
||||
#if (!php || (haxe_ver >= 3.3))
|
||||
assertScript('
|
||||
var keys = [];
|
||||
for (key in stringMap.keys()) keys.push(key);
|
||||
keys.sort(function(s1, s2) return s1 > s2 ? 1 : (s2 > s1 ? -1 : 0));
|
||||
keys.join("_");
|
||||
', 'a_bar_foo', vars);
|
||||
#end
|
||||
assertScript('stringMap.remove("foo"); stringMap.exists("foo");', false, vars);
|
||||
assertScript('stringMap["foo"] = "a"; stringMap["foo"] += "b"', 'ab', vars);
|
||||
assertEquals('ab', vars.stringMap['foo']);
|
||||
assertScript('stringIntMap["foo"]++', 100, vars);
|
||||
assertEquals(101, vars.stringIntMap['foo']);
|
||||
assertScript('++stringIntMap["foo"]', 102, vars);
|
||||
assertScript('var newMap = ["foo"=>"foo"]; newMap["foo"];', 'foo', vars);
|
||||
#if (!php || (haxe_ver >= 3.3))
|
||||
assertScript('var newMap = [enumKey=>"foo"]; newMap[enumKey];', 'foo', vars);
|
||||
#end
|
||||
assertScript('var newMap = [{a:"a"}=>"foo", objKey=>"bar"]; newMap[objKey];', 'bar', vars);
|
||||
}
|
||||
|
||||
static function main() {
|
||||
var runner = new TestRunner();
|
||||
|
||||
+120
-35
@@ -119,8 +119,16 @@ class Interp {
|
||||
l.r = v;
|
||||
case EField(e,f):
|
||||
v = set(expr(e),f,v);
|
||||
case EArray(e,index):
|
||||
expr(e)[expr(index)] = v;
|
||||
case EArray(e, index):
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
setMapValue(arr, index, v);
|
||||
}
|
||||
else {
|
||||
arr[index] = v;
|
||||
}
|
||||
|
||||
default:
|
||||
error(EInvalidOp("="));
|
||||
}
|
||||
@@ -146,11 +154,17 @@ class Interp {
|
||||
var obj = expr(e);
|
||||
v = fop(get(obj,f),expr(e2));
|
||||
v = set(obj,f,v);
|
||||
case EArray(e,index):
|
||||
var arr = expr(e);
|
||||
var index = expr(index);
|
||||
v = fop(arr[index],expr(e2));
|
||||
arr[index] = v;
|
||||
case EArray(e, index):
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
v = fop(getMapValue(arr, index), expr(e2));
|
||||
setMapValue(arr, index, v);
|
||||
}
|
||||
else {
|
||||
v = fop(arr[index],expr(e2));
|
||||
arr[index] = v;
|
||||
}
|
||||
default:
|
||||
return error(EInvalidOp(op));
|
||||
}
|
||||
@@ -181,16 +195,29 @@ class Interp {
|
||||
} else
|
||||
set(obj,f,v + delta);
|
||||
return v;
|
||||
case EArray(e,index):
|
||||
var arr = expr(e);
|
||||
var index = expr(index);
|
||||
var v = arr[index];
|
||||
if( prefix ) {
|
||||
v += delta;
|
||||
arr[index] = v;
|
||||
} else
|
||||
arr[index] = v + delta;
|
||||
return v;
|
||||
case EArray(e, index):
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
var v = getMapValue(arr, index);
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
setMapValue(arr, index, v);
|
||||
}
|
||||
else {
|
||||
setMapValue(arr, index, v + delta);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
var v = arr[index];
|
||||
if( prefix ) {
|
||||
v += delta;
|
||||
arr[index] = v;
|
||||
} else
|
||||
arr[index] = v + delta;
|
||||
return v;
|
||||
}
|
||||
default:
|
||||
return error(EInvalidOp((delta > 0)?"++":"--"));
|
||||
}
|
||||
@@ -417,12 +444,56 @@ class Interp {
|
||||
}
|
||||
return f;
|
||||
case EArrayDecl(arr):
|
||||
var a = new Array();
|
||||
for( e in arr )
|
||||
a.push(expr(e));
|
||||
return a;
|
||||
case EArray(e,index):
|
||||
return expr(e)[expr(index)];
|
||||
if (arr.length > 0 && arr[0].match(Expr.EBinop("=>", _))) {
|
||||
var isAllString:Bool = true;
|
||||
var isAllInt:Bool = true;
|
||||
var isAllObject:Bool = true;
|
||||
var isAllEnum:Bool = true;
|
||||
var keys:Array<Dynamic> = [];
|
||||
var values:Array<Dynamic> = [];
|
||||
for (e in arr) {
|
||||
switch(e) {
|
||||
case Expr.EBinop("=>", eKey, eValue): {
|
||||
var key:Dynamic = expr(eKey);
|
||||
var value:Dynamic = expr(eValue);
|
||||
isAllString = isAllString && Std.is(key, String);
|
||||
isAllInt = isAllInt && Std.is(key, Int);
|
||||
isAllObject = isAllObject && Reflect.isObject(key);
|
||||
isAllEnum = isAllEnum && Reflect.isEnumValue(key);
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
}
|
||||
default: throw("=> expected");
|
||||
}
|
||||
}
|
||||
var map:Dynamic = {
|
||||
if (isAllInt) new haxe.ds.IntMap<Dynamic>();
|
||||
else if (isAllString) new haxe.ds.StringMap<Dynamic>();
|
||||
else if (isAllEnum) new haxe.ds.EnumValueMap<Dynamic, Dynamic>();
|
||||
else if (isAllObject) new haxe.ds.ObjectMap<Dynamic, Dynamic>();
|
||||
else throw 'Inconsistent key types';
|
||||
}
|
||||
for (n in 0...keys.length) {
|
||||
setMapValue(map, keys[n], values[n]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
else {
|
||||
var a = new Array();
|
||||
for ( e in arr ) {
|
||||
a.push(expr(e));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
case EArray(e, index):
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
return getMapValue(arr, index);
|
||||
}
|
||||
else {
|
||||
return arr[index];
|
||||
}
|
||||
case ENew(cl,params):
|
||||
var a = new Array();
|
||||
for( e in params )
|
||||
@@ -498,8 +569,8 @@ class Interp {
|
||||
}
|
||||
|
||||
function makeIterator( v : Dynamic ) : Iterator<Dynamic> {
|
||||
#if (flash && !flash9)
|
||||
if( v.iterator != null ) v = v.iterator();
|
||||
#if ((flash && !flash9) || php)
|
||||
if ( v.iterator != null ) v = v.iterator();
|
||||
#else
|
||||
try v = v.iterator() catch( e : Dynamic ) {};
|
||||
#end
|
||||
@@ -526,18 +597,32 @@ class Interp {
|
||||
restore(old);
|
||||
}
|
||||
|
||||
inline function isMap(o:Dynamic):Bool {
|
||||
return Std.is(o, haxe.Constraints.IMap);
|
||||
}
|
||||
|
||||
inline function getMapValue(map:Dynamic, key:Dynamic):Dynamic {
|
||||
return cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).get(key);
|
||||
}
|
||||
|
||||
inline function setMapValue(map:Dynamic, key:Dynamic, value:Dynamic):Void {
|
||||
cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).set(key, value);
|
||||
}
|
||||
|
||||
function get( o : Dynamic, f : String ) : Dynamic {
|
||||
if( o == null ) error(EInvalidAccess(f));
|
||||
#if php
|
||||
// https://github.com/HaxeFoundation/haxe/issues/4915
|
||||
return try {
|
||||
if ( o == null ) error(EInvalidAccess(f));
|
||||
return {
|
||||
#if php
|
||||
// https://github.com/HaxeFoundation/haxe/issues/4915
|
||||
try {
|
||||
Reflect.getProperty(o, f);
|
||||
} catch (e:Dynamic) {
|
||||
Reflect.field(o, f);
|
||||
}
|
||||
#else
|
||||
Reflect.getProperty(o, f);
|
||||
} catch (e:Dynamic) {
|
||||
Reflect.field(o, f);
|
||||
}
|
||||
#else
|
||||
return Reflect.getProperty(o, f);
|
||||
#end
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
function set( o : Dynamic, f : String, v : Dynamic ) : Dynamic {
|
||||
|
||||
+3
-1
@@ -111,7 +111,7 @@ class Parser {
|
||||
["..."],
|
||||
["&&"],
|
||||
["||"],
|
||||
["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^="],
|
||||
["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^=","=>"],
|
||||
];
|
||||
#if haxe3
|
||||
opPriority = new Map();
|
||||
@@ -1062,6 +1062,8 @@ class Parser {
|
||||
char = readChar();
|
||||
if( char == '='.code )
|
||||
return TOp("==");
|
||||
else if ( char == '>'.code )
|
||||
return TOp("=>");
|
||||
this.char = char;
|
||||
return TOp("=");
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user