<commit_before>import {Container} from './Container';
import {Value, IntValue, FloatValue, StringValue, DivertTargetValue, VariablePointerValue, ListValue} from './Value';
import {Glue, GlueType} from './Glue';
import {ControlCommand} from './ControlCommand';
import {PushPopType} from './PushPop';
import {Divert} from './Divert';
import {ChoicePoint} from './ChoicePoint';
import {VariableReference} from './VariableReference';
import {VariableAssignment} from './VariableAssignment';
import {NativeFunctionCall} from './NativeFunctionCall';
import {Void} from './Void';
import {Tag} from './Tag';
import {Path} from './Path';
import {Choice} from './Choice';
import {ListDefinition} from './ListDefinition';
import {ListDefinitionsOrigin} from './ListDefinitionsOrigin';
import {InkListItem, InkList} from './InkList';
import {Object as InkObject} from './Object';

export class JsonSerialisation{
	static ListToJArray(serialisables){
		var jArray = [];
		serialisables.forEach(s => {
			jArray.push(this.RuntimeObjectToJToken(s));
		});
		return jArray;
	}
	static JArrayToRuntimeObjList(jArray, skipLast){
		var count = jArray.length;
		if (skipLast) count--;
		
		var list = [];
		
		for (var i = 0; i < count; i++){
			var jTok = jArray[i];
			var runtimeObj = this.JTokenToRuntimeObject(jTok);
			list.push(runtimeObj);
		}
		
		return list;
	}
	static JObjectToDictionaryRuntimeObjs(jObject){
		var dict = {};

		for (var key in jObject){
			dict[key] = this.JTokenToRuntimeObject(jObject[key]);
		}

		return dict;
	}
	static DictionaryRuntimeObjsToJObject(dictionary){
		var jsonObj = {};

		for (var key in dictionary){
//			var runtimeObj = keyVal.Value as Runtime.Object;
			var runtimeObj = dictionary[key];
			if (runtimeObj instanceof InkObject)
				jsonObj[key] = this.RuntimeObjectToJToken(runtimeObj);
		}

		return jsonObj;
	}
	static JObjectToIntDictionary(jObject){
		var dict = {};
		for (var key in jObject){
			dict[key] = parseInt(jObject[key]);
		}
		return dict;
	}
	static IntDictionaryToJObject(dict){
		var jObj = {};
		for (var key in dict){
			jObj[key] = dict[key];
		}
		return jObj;
	}
	static JTokenToRuntimeObject(token){
		//@TODO probably find a more robust way to detect numbers, isNaN seems happy to accept things that really aren't numberish.
		if (!isNaN(token) && token !== "\n"){//JS thinks "\n" is a number
			return Value.Create(token);
		}
		
		if (typeof token === 'string'){
			var str = token.toString();

			// String value
			var firstChar = str[0];
			if (firstChar == '^')
				return new StringValue(str.substring(1));
			else if(firstChar == "\n" && str.length == 1)
				return new StringValue("\n");

			// Glue
			if (str == "<>")
				return new Glue(GlueType.Bidirectional);
			else if(str == "G<")
				return new Glue(GlueType.Left);
			else if(str == "G>")
				return new Glue(GlueType.Right);

			// Control commands (would looking up in a hash set be faster?)
			for (var i = 0; i < _controlCommandNames.length; ++i) {
				var cmdName = _controlCommandNames[i];
				if (str == cmdName) {
					return new ControlCommand(i);
				}
			}

			// Native functions
			if (str == "L^") str = "^";
			if( NativeFunctionCall.CallExistsWithName(str) )
				return NativeFunctionCall.CallWithName(str);

			// Pop
			if (str == "->->")
				return ControlCommand.PopTunnel();
			else if (str == "~ret")
				return ControlCommand.PopFunction();

			// Void
			if (str == "void")
				return new Void ();
		}
		
		if (typeof token === 'object' && token instanceof Array === false){
			var obj = token;
			var propValue;

			// Divert target value to path
			if (obj["^->"]){
				propValue = obj["^->"];
				return new DivertTargetValue(new Path(propValue.toString()));
			}
				
			// VariablePointerValue
			if (obj["^var"]) {
				propValue = obj["^var"];
				var varPtr = new VariablePointerValue(propValue.toString());
				if (obj["ci"]){
					propValue = obj["ci"];
					varPtr.contextIndex = parseInt(propValue);
				}
				return varPtr;
			}

			// Divert
			var isDivert = false;
			var pushesToStack = false;
			var divPushType = PushPopType.Function;
			var external = false;
			if (propValue = obj["->"]) {
				isDivert = true;
			}
			else if (propValue = obj["f()"]) {<commit_msg>Not handling the case where obj['ci'] = 0<commit_after>import {Container} from './Container';
import {Value, IntValue, FloatValue, StringValue, DivertTargetValue, VariablePointerValue, ListValue} from './Value';
import {Glue, GlueType} from './Glue';
import {ControlCommand} from './ControlCommand';
import {PushPopType} from './PushPop';
import {Divert} from './Divert';
import {ChoicePoint} from './ChoicePoint';
import {VariableReference} from './VariableReference';
import {VariableAssignment} from './VariableAssignment';
import {NativeFunctionCall} from './NativeFunctionCall';
import {Void} from './Void';
import {Tag} from './Tag';
import {Path} from './Path';
import {Choice} from './Choice';
import {ListDefinition} from './ListDefinition';
import {ListDefinitionsOrigin} from './ListDefinitionsOrigin';
import {InkListItem, InkList} from './InkList';
import {Object as InkObject} from './Object';

export class JsonSerialisation{
	static ListToJArray(serialisables){
		var jArray = [];
		serialisables.forEach(s => {
			jArray.push(this.RuntimeObjectToJToken(s));
		});
		return jArray;
	}
	static JArrayToRuntimeObjList(jArray, skipLast){
		var count = jArray.length;
		if (skipLast) count--;
		
		var list = [];
		
		for (var i = 0; i < count; i++){
			var jTok = jArray[i];
			var runtimeObj = this.JTokenToRuntimeObject(jTok);
			list.push(runtimeObj);
		}
		
		return list;
	}
	static JObjectToDictionaryRuntimeObjs(jObject){
		var dict = {};

		for (var key in jObject){
			dict[key] = this.JTokenToRuntimeObject(jObject[key]);
		}

		return dict;
	}
	static DictionaryRuntimeObjsToJObject(dictionary){
		var jsonObj = {};

		for (var key in dictionary){
//			var runtimeObj = keyVal.Value as Runtime.Object;
			var runtimeObj = dictionary[key];
			if (runtimeObj instanceof InkObject)
				jsonObj[key] = this.RuntimeObjectToJToken(runtimeObj);
		}

		return jsonObj;
	}
	static JObjectToIntDictionary(jObject){
		var dict = {};
		for (var key in jObject){
			dict[key] = parseInt(jObject[key]);
		}
		return dict;
	}
	static IntDictionaryToJObject(dict){
		var jObj = {};
		for (var key in dict){
			jObj[key] = dict[key];
		}
		return jObj;
	}
	static JTokenToRuntimeObject(token){
		//@TODO probably find a more robust way to detect numbers, isNaN seems happy to accept things that really aren't numberish.
		if (!isNaN(token) && token !== "\n"){//JS thinks "\n" is a number
			return Value.Create(token);
		}
		
		if (typeof token === 'string'){
			var str = token.toString();

			// String value
			var firstChar = str[0];
			if (firstChar == '^')
				return new StringValue(str.substring(1));
			else if(firstChar == "\n" && str.length == 1)
				return new StringValue("\n");

			// Glue
			if (str == "<>")
				return new Glue(GlueType.Bidirectional);
			else if(str == "G<")
				return new Glue(GlueType.Left);
			else if(str == "G>")
				return new Glue(GlueType.Right);

			// Control commands (would looking up in a hash set be faster?)
			for (var i = 0; i < _controlCommandNames.length; ++i) {
				var cmdName = _controlCommandNames[i];
				if (str == cmdName) {
					return new ControlCommand(i);
				}
			}

			// Native functions
			if (str == "L^") str = "^";
			if( NativeFunctionCall.CallExistsWithName(str) )
				return NativeFunctionCall.CallWithName(str);

			// Pop
			if (str == "->->")
				return ControlCommand.PopTunnel();
			else if (str == "~ret")
				return ControlCommand.PopFunction();

			// Void
			if (str == "void")
				return new Void ();
		}
		
		if (typeof token === 'object' && token instanceof Array === false){
			var obj = token;
			var propValue;

			// Divert target value to path
			if (obj["^->"]){
				propValue = obj["^->"];
				return new DivertTargetValue(new Path(propValue.toString()));
			}
				
			// VariablePointerValue
			if (obj["^var"]) {
				propValue = obj["^var"];
				var varPtr = new VariablePointerValue(propValue.toString());
				if ('ci' in obj){
					propValue = obj["ci"];
					varPtr.contextIndex = parseInt(propValue);
				}
				return varPtr;
			}

			// Divert
			var isDivert = false;
			var pushesToStack = false;
			var divPushType = PushPopType.Function;
			var external = false;
			if (propValue = obj["->"]) {
				isDivert = true;
			}
			else if (propValue = obj["f()"]) {
{'fraction_non_alphanumeric': 0.14888366627497063, 'fraction_numerical': 0.0012925969447708577, 'mean_word_length': 3.5562098501070665, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3799720', 'n_tokens_mistral': 3202, 'n_tokens_neox': 2700, 'n_words': 768}