Fix fork() for projects that use Kiss as a haxelib

This commit is contained in:
2020-12-09 18:16:22 -07:00
parent 646f10f52b
commit cfd3147337
25 changed files with 12 additions and 267 deletions

View File

@@ -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;

View 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;
}
}

View 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.

View 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;
}
}

View File

@@ -0,0 +1,12 @@
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE.md)
[![TravisCI Build Status](https://travis-ci.org/thomasuster/cloner.svg?branch=master)](https://travis-ci.org/thomasuster/cloner)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/thomasuster/cloner?branch=master&svg=true)](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);
```