Fix fork() for projects that use Kiss as a haxelib
This commit is contained in:
@@ -7,7 +7,7 @@ import haxe.macro.PositionTools;
|
||||
import sys.io.File;
|
||||
#end
|
||||
import kiss.Kiss;
|
||||
import cloner.Cloner;
|
||||
import kiss.cloner.Cloner;
|
||||
|
||||
typedef Command = () -> Void;
|
||||
|
||||
@@ -183,7 +183,7 @@ class EmbeddedScript {
|
||||
for (command in commands) {
|
||||
// a fork needs to be a thorough copy that includes all of the EmbeddedScript subclass's
|
||||
// fields, otherwise DSL state will be lost when forking, which is unacceptable
|
||||
var fork = new cloner.Cloner().clone(this);
|
||||
var fork = new kiss.cloner.Cloner().clone(this);
|
||||
fork.instructions[instructionPointer] = command;
|
||||
fork.run();
|
||||
fork;
|
||||
|
115
kiss/src/kiss/cloner/Cloner.hx
Normal file
115
kiss/src/kiss/cloner/Cloner.hx
Normal file
@@ -0,0 +1,115 @@
|
||||
package kiss.cloner;
|
||||
import Array;
|
||||
import haxe.ds.ObjectMap;
|
||||
import Type.ValueType;
|
||||
import haxe.ds.IntMap;
|
||||
import haxe.ds.StringMap;
|
||||
class Cloner {
|
||||
|
||||
var cache:ObjectMap<Dynamic,Dynamic>;
|
||||
var classHandles:Map<String,Dynamic->Dynamic>;
|
||||
var stringMapCloner:MapCloner<String>;
|
||||
var intMapCloner:MapCloner<Int>;
|
||||
|
||||
public function new():Void {
|
||||
stringMapCloner = new MapCloner(this,StringMap);
|
||||
intMapCloner = new MapCloner(this,IntMap);
|
||||
classHandles = new Map<String,Dynamic->Dynamic>();
|
||||
classHandles.set('String',returnString);
|
||||
classHandles.set('Array',cloneArray);
|
||||
classHandles.set('haxe.ds.StringMap',stringMapCloner.clone);
|
||||
classHandles.set('haxe.ds.IntMap',intMapCloner.clone);
|
||||
}
|
||||
|
||||
function returnString(v:String):String {
|
||||
return v;
|
||||
}
|
||||
|
||||
public function clone <T> (v:T):T {
|
||||
cache = new ObjectMap<Dynamic,Dynamic>();
|
||||
var outcome:T = _clone(v);
|
||||
cache = null;
|
||||
return outcome;
|
||||
}
|
||||
|
||||
public function _clone <T> (v:T):T {
|
||||
#if js
|
||||
if(Std.is(v, String))
|
||||
return v;
|
||||
#end
|
||||
|
||||
#if neko
|
||||
try {
|
||||
if(Type.getClassName(cast v) != null)
|
||||
return v;
|
||||
}catch(e:Dynamic) {}
|
||||
#else
|
||||
if(Type.getClassName(cast v) != null)
|
||||
return v;
|
||||
#end
|
||||
switch(Type.typeof(v)){
|
||||
case TNull:
|
||||
return null;
|
||||
case TInt:
|
||||
return v;
|
||||
case TFloat:
|
||||
return v;
|
||||
case TBool:
|
||||
return v;
|
||||
case TObject:
|
||||
return handleAnonymous(v);
|
||||
case TFunction:
|
||||
return v;
|
||||
case TClass(c):
|
||||
if(!cache.exists(v))
|
||||
cache.set(v,handleClass(c, v));
|
||||
return cache.get(v);
|
||||
case TEnum(e):
|
||||
return v;
|
||||
case TUnknown:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function handleAnonymous (v:Dynamic):Dynamic {
|
||||
var properties:Array<String> = Reflect.fields(v);
|
||||
var anonymous:Dynamic = {};
|
||||
for (i in 0...properties.length) {
|
||||
var property:String = properties[i];
|
||||
Reflect.setField(anonymous, property, _clone(Reflect.getProperty(v, property)));
|
||||
}
|
||||
return anonymous;
|
||||
}
|
||||
|
||||
function handleClass <T> (c:Class<T>,inValue:T):T {
|
||||
var handle:T->T = classHandles.get(Type.getClassName(c));
|
||||
if(handle == null)
|
||||
handle = cloneClass;
|
||||
return handle(inValue);
|
||||
}
|
||||
|
||||
function cloneArray <T> (inValue:Array<T>):Array<T> {
|
||||
var array:Array<T> = inValue.copy();
|
||||
for (i in 0...array.length)
|
||||
array[i] = _clone(array[i]);
|
||||
return array;
|
||||
}
|
||||
|
||||
function cloneClass <T> (inValue:T):T {
|
||||
var classValue = Type.getClass(inValue);
|
||||
var outValue:T = Type.createEmptyInstance(classValue);
|
||||
var fields:Array<String> = Type.getInstanceFields(classValue);
|
||||
for (i in 0...fields.length) {
|
||||
var field = fields[i];
|
||||
var property = Reflect.getProperty(inValue, field);
|
||||
try {
|
||||
Reflect.setField(outValue, field, _clone(property));
|
||||
} catch (s) {
|
||||
// There will be errors on C++ when trying to assign to a member function.
|
||||
// They're not important, because the function will already be on the clone.
|
||||
}
|
||||
}
|
||||
return outValue;
|
||||
}
|
||||
|
||||
}
|
24
kiss/src/kiss/cloner/LICENSE.md
Normal file
24
kiss/src/kiss/cloner/LICENSE.md
Normal file
@@ -0,0 +1,24 @@
|
||||
License
|
||||
=======
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Thomas Uster
|
||||
|
||||
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.
|
25
kiss/src/kiss/cloner/MapCloner.hx
Normal file
25
kiss/src/kiss/cloner/MapCloner.hx
Normal file
@@ -0,0 +1,25 @@
|
||||
package kiss.cloner;
|
||||
import haxe.Constraints.IMap;
|
||||
import kiss.cloner.Cloner;
|
||||
import Type.ValueType;
|
||||
class MapCloner<K>{
|
||||
|
||||
var cloner:Cloner;
|
||||
var type:Class<IMap<K,Dynamic>>;
|
||||
var noArgs:Array<Dynamic>;
|
||||
|
||||
public function new(cloner:Cloner, type:Class<IMap<K,Dynamic>>):Void {
|
||||
this.cloner = cloner;
|
||||
this.type = type;
|
||||
noArgs = [];
|
||||
}
|
||||
|
||||
public function clone <K,Dynamic> (inValue:IMap<K,Dynamic>):IMap<K,Dynamic> {
|
||||
var inMap:IMap<K,Dynamic> = inValue;
|
||||
var map:IMap<K,Dynamic> = cast Type.createInstance(type, noArgs);
|
||||
for (key in inMap.keys()) {
|
||||
map.set(key, cloner._clone(inMap.get(key)));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
12
kiss/src/kiss/cloner/README.md
Normal file
12
kiss/src/kiss/cloner/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
[](LICENSE.md)
|
||||
[](https://travis-ci.org/thomasuster/cloner)
|
||||
[](https://ci.appveyor.com/project/thomasuster/cloner)
|
||||
|
||||
```
|
||||
git clone https://github.com/thomasuster/cloner.git
|
||||
haxelib dev cloner cloner/src
|
||||
```
|
||||
```
|
||||
var cloner:Cloner = new Cloner();
|
||||
var clone = cloner.clone(mostAnything);
|
||||
```
|
Reference in New Issue
Block a user