diff --git a/.gitignore b/.gitignore index a9d6a723..23f95c20 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,8 @@ src/Amalgam/AmalgamVersion.h .envrc .env -## Amalgam metadata files +## Amalgam binary files +*.caml *.mdam ## Build results diff --git a/CMakeLists.txt b/CMakeLists.txt index 854dc6cf..24cb8a2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,6 +134,8 @@ set(COMMON_SOURCE src/Amalgam/FilenameEscapeProcessor.h src/Amalgam/GeneralizedDistance.h src/Amalgam/HashMaps.h + src/Amalgam/importexport/FileSupportCAML.cpp + src/Amalgam/importexport/FileSupportCAML.h src/Amalgam/importexport/FileSupportCSV.cpp src/Amalgam/importexport/FileSupportCSV.h src/Amalgam/importexport/FileSupportJSON.cpp @@ -176,8 +178,6 @@ set(COMMON_SOURCE src/Amalgam/string/StringInternPool.h src/Amalgam/string/StringManipulation.cpp src/Amalgam/string/StringManipulation.h - # Add out.txt so it shows up in IDE - src/Amalgam/out.txt ) set(COMMON_SOURCE_THREADS ${COMMON_SOURCE} @@ -206,6 +206,8 @@ source_group(TREE ${CMAKE_SOURCE_DIR} FILES ${AMALGAM_ALL_SOURCE}) # Get all files we care about for easy access in projects (mainly IDEs) file(GLOB_RECURSE ALL_FILES "${CMAKE_SOURCE_DIR}/*") list(FILTER ALL_FILES EXCLUDE REGEX "(.*/.git/.*|.*/out/.*|.*/src/.*|.*/test/.*|.*Amalgam\.sln.*)") +file(GLOB_RECURSE ADDITIONAL_FILES "${CMAKE_SOURCE_DIR}/src/Amalgam/out.txt" "${CMAKE_SOURCE_DIR}/src/Amalgam/amlg_code/*") +list(APPEND ALL_FILES ${ADDITIONAL_FILES}) source_group(TREE ${CMAKE_SOURCE_DIR} FILES ${ALL_FILES}) list(APPEND AMALGAM_APP_ONLY_SOURCE ${ALL_FILES}) diff --git a/docs/language.js b/docs/language.js index bd9e1dda..eebc7a51 100644 --- a/docs/language.js +++ b/docs/language.js @@ -1332,7 +1332,7 @@ var data = [ "parameter" : "load string file_path [bool escape_filename] [string file_type]", "output" : "*", "permissions" : "r", - "description" : "Loads the data specified by the resource in string. Attempts to load the file type and parse it into appropriate data and evaluate to the corresponding code. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. If file_type is specified and not null, it will use the file_type specified instead of the extension of the file_path. File formats supported are amlg, json, yaml, csv, cstl, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings.", + "description" : "Loads the data specified by the resource in string. Attempts to load the file type and parse it into appropriate data and evaluate to the corresponding code. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. If file_type is specified and not null, it will use the file_type specified instead of the extension of the file_path. File formats supported are amlg, json, yaml, csv, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings.", "example" : "(print (load \"my_directory/MyModule.amlg\"))" }, @@ -1340,7 +1340,7 @@ var data = [ "parameter" : "load_entity string file_path [id entity] [bool escape_filename] [bool escape_contained_filenames] [string file_type]", "output" : "id", "permissions" : "r", - "description" : "Loads an entity specified by the resource in string. Attempts to load the file type and parse it into appropriate data and store it in the entity specified by id, following the same id creation rules as create_entities, except that if no id is specified, it may default to a name based on the resource if available. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. If escape_contained_filenames is true, which is its default, it will also escape contained entity filenames. If file_type is specified and not null, it will use the file_type specified instead of the extension of the file_path. File formats supported are amlg, json, yaml, csv, cstl, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings.", + "description" : "Loads an entity specified by the resource in string. Attempts to load the file type and parse it into appropriate data and store it in the entity specified by id, following the same id creation rules as create_entities, except that if no id is specified, it may default to a name based on the resource if available. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. If escape_contained_filenames is true, which is its default, it will also escape contained entity filenames. If file_type is specified and not null, it will use the file_type specified instead of the extension of the file_path. File formats supported are amlg, json, yaml, csv, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings.", "example" : "(load_entity \"my_directory/MyModule.amlg\" \"MyModule\")" }, @@ -1348,7 +1348,7 @@ var data = [ "parameter" : "load_persistent_entity string file_path [id entity] [bool escape_filename]", "output" : "id", "permissions" : "r", - "description" : "Loads an entity specified by the resource in string. Attempts to load the file type and parse it into appropriate data and store it in the entity specified by id, following the same id creation rules as create_entities. Any modifications to the entity or any entity contained within it will be written out to the resource, so that the memory and persistent storage are synchronized. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. This command will escape contained filenames. The file type of a persisted entity must match the extension of the file of the main entity. File formats supported are amlg, json, yaml, csv, cstl, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings.\n\nWARNING: Loading the same file as a persistent entity in more than one place will overwrite the file each time either entity is altered, but changes will not be propogated between the entities.", + "description" : "Loads an entity specified by the resource in string. Attempts to load the file type and parse it into appropriate data and store it in the entity specified by id, following the same id creation rules as create_entities. Any modifications to the entity or any entity contained within it will be written out to the resource, so that the memory and persistent storage are synchronized. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. This command will escape contained filenames. The file type of a persisted entity must match the extension of the file of the main entity. File formats supported are amlg, json, yaml, csv, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings.\n\nWARNING: Loading the same file as a persistent entity in more than one place will overwrite the file each time either entity is altered, but changes will not be propogated between the entities.", "example" : "(load_persistent_entity \"my_directory/MyModule.amlg\" \"MyModule\")" }, @@ -1356,7 +1356,7 @@ var data = [ "parameter" : "store string file_path * node [bool escape_filename] [string file_type] [assoc params]", "output" : "bool", "permissions" : "r", - "description" : "Stores the code specified by * to the resource in string. Returns true if successful, false if not. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. If file_type is specified and not null, it will use the file_type specified instead of the extension of the file_path. File formats supported are amlg, json, yaml, csv, cstl, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings. If params is specified, it is an assoc that contains key-value pairs describing the format. The key \"sort_keys\" can be used to specify a boolean value, if true, then it will sort the keys, otherwise the default behavior is to emit the keys based on memory layout.", + "description" : "Stores the code specified by * to the resource in string. Returns true if successful, false if not. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. If file_type is specified and not null, it will use the file_type specified instead of the extension of the file_path. File formats supported are amlg, json, yaml, csv, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings. If params is specified, it is an assoc that contains key-value pairs describing the format. The key \"sort_keys\" can be used to specify a boolean value, if true, then it will sort the keys, otherwise the default behavior is to emit the keys based on memory layout.", "example" : "(store \"my_directory/MyData.amlg\" (list 1 2 3))" }, @@ -1364,7 +1364,7 @@ var data = [ "parameter" : "store_entity string file_path id entity [bool escape_filename] [bool escape_contained_filenames] [string file_type] [assoc params]", "output" : "bool", "permissions" : "r", - "description" : "Stores the entity specified by the id to the resource in string. Returns true if successful, false if not. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. If escape_contained_filenames is true, which is its default, it will also escape contained entity filenames. If file_type is specified and not null, it will use the file_type specified instead of the extension of the file_path. File formats supported are amlg, json, yaml, csv, cstl, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings. If params is specified, it is an assoc that contains key-value pairs describing the format. The key \"sort_keys\" can be used to specify a boolean value, if true, then it will sort the keys, otherwise the default behavior is to emit the keys based on memory layout.", + "description" : "Stores the entity specified by the id to the resource in string. Returns true if successful, false if not. The parameter escape_filename defaults to false, but if it is true, it will agressively escape filenames using only alphanumeric characters and the underscore, using underscore as an escape character. If escape_contained_filenames is true, which is its default, it will also escape contained entity filenames. If file_type is specified and not null, it will use the file_type specified instead of the extension of the file_path. File formats supported are amlg, json, yaml, csv, and caml; anything not in this list will be loaded as a binary string. Note that loading from a non-'.amlg' extension will only ever provide lists, assocs, numbers, and strings. If params is specified, it is an assoc that contains key-value pairs describing the format. The key \"sort_keys\" can be used to specify a boolean value, if true, then it will sort the keys, otherwise the default behavior is to emit the keys based on memory layout.", "example" : "(store_entity \"my_directory/MyData.amlg\" \"MyData\")" }, diff --git a/examples/README.md b/examples/README.md index c80ed2f2..469330f7 100644 --- a/examples/README.md +++ b/examples/README.md @@ -11,5 +11,6 @@ A collection of notable and neat/fun examples written in Amalgam located in dire * [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) * [Fractals](https://en.wikipedia.org/wiki/Mandelbrot_set) -* [Quine](https://en.wikipedia.org/wiki/Quine_(computing)) * [Hello, World!](https://en.wikipedia.org/wiki/%22Hello,_World!%22_program) +* [Quine](https://en.wikipedia.org/wiki/Quine_(computing)) +* [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) \ No newline at end of file diff --git a/examples/json_search/json-combine.amlg b/examples/json_search/json-combine.amlg index 6361387f..e0b06776 100644 --- a/examples/json_search/json-combine.amlg +++ b/examples/json_search/json-combine.amlg @@ -1,4 +1,4 @@ -#!./amalgam-mt +#!amalgam-mt (seq (declare (assoc file_a (get argv 1) diff --git a/examples/repl/repl.amlg b/examples/repl/repl.amlg new file mode 100644 index 00000000..e026a570 --- /dev/null +++ b/examples/repl/repl.amlg @@ -0,0 +1,7 @@ +(while (true) + (system "printline" "> ") + (let + (assoc input (system "readline") ) + (print (call (parse input)) "\n") + ) +) \ No newline at end of file diff --git a/src/Amalgam/Amalgam.h b/src/Amalgam/Amalgam.h index 17e4c9bc..2208cd2e 100644 --- a/src/Amalgam/Amalgam.h +++ b/src/Amalgam/Amalgam.h @@ -1,7 +1,8 @@ #pragma once //system headers: -#include +#include +#include #if defined(_MSC_VER) //Microsoft @@ -15,8 +16,19 @@ extern "C" { + //status from LoadEntity + struct LoadEntityStatus + { + bool loaded; + char *message; + char *version; + }; + //loads the entity specified into handle - AMALGAM_EXPORT bool LoadEntity(char *handle, char *path, bool persistent, bool load_contained_entities, char *write_log_filename, char *print_log_filename); + AMALGAM_EXPORT LoadEntityStatus LoadEntity(char *handle, char *path, bool persistent, bool load_contained_entities, char *write_log_filename, char *print_log_filename); + + //verifies the entity specified by path. Uses LoadEntityStatus to return any errors and version + AMALGAM_EXPORT LoadEntityStatus VerifyEntity(char *path); //stores the entity specified by handle into path AMALGAM_EXPORT void StoreEntity(char *handle, char *path, bool update_persistence_location = false, bool store_contained_entities = true); @@ -37,7 +49,6 @@ extern "C" AMALGAM_EXPORT void AppendNumberValue(char *handle, char *label, double value); AMALGAM_EXPORT void SetNumberValue(char *handle, char *label, double value); - AMALGAM_EXPORT size_t PrepStringValueToTransferBuffer(char *handle, char *label); AMALGAM_EXPORT void AppendStringValue(char *handle, char *label, char *value); AMALGAM_EXPORT void SetStringValue(char *handle, char *label, char *value); @@ -55,7 +66,7 @@ extern "C" AMALGAM_EXPORT void AppendStringList(char *handle, char *label, char **list, size_t len); AMALGAM_EXPORT void SetStringList(char *handle, char *label, char **list, size_t len); - AMALGAM_EXPORT void SetJSONToLabel(char *handle, char *label, char *json); + AMALGAM_EXPORT void SetJSONToLabel(char *handle, char *label, char *json); AMALGAM_EXPORT wchar_t *GetJSONPtrFromLabelWide(char *handle, char *label); AMALGAM_EXPORT char *GetJSONPtrFromLabel(char *handle, char *label); diff --git a/src/Amalgam/Amalgam.vcxproj b/src/Amalgam/Amalgam.vcxproj index b45ad26d..402e8eec 100644 --- a/src/Amalgam/Amalgam.vcxproj +++ b/src/Amalgam/Amalgam.vcxproj @@ -569,6 +569,7 @@ + @@ -634,6 +635,7 @@ + diff --git a/src/Amalgam/Amalgam.vcxproj.filters b/src/Amalgam/Amalgam.vcxproj.filters index 818c83f1..7e94ccea 100644 --- a/src/Amalgam/Amalgam.vcxproj.filters +++ b/src/Amalgam/Amalgam.vcxproj.filters @@ -42,6 +42,9 @@ Source Files + + Source Files + Source Files @@ -191,6 +194,9 @@ Header Files + + Header Files + Header Files diff --git a/src/Amalgam/AmalgamAPI.cpp b/src/Amalgam/AmalgamAPI.cpp index 98eec179..7ab224a6 100644 --- a/src/Amalgam/AmalgamAPI.cpp +++ b/src/Amalgam/AmalgamAPI.cpp @@ -6,11 +6,6 @@ #include "EntityQueries.h" //system headers: -#include -#include -#include -#include -#include #include //Workaround because GCC doesn't support strcpy_s @@ -77,18 +72,34 @@ extern "C" return wct; } + LoadEntityStatus ConvertLoadStatusToCStatus(EntityExternalInterface::LoadEntityStatus &status) + { + return { + status.loaded, + StringToCharPtr(status.message), + StringToCharPtr(status.version) + }; + } + // ************************************ // api methods // ************************************ - bool LoadEntity(char *handle, char *path, bool persistent, bool load_contained_entities, char *write_log_filename, char *print_log_filename) + LoadEntityStatus LoadEntity(char *handle, char *path, bool persistent, bool load_contained_entities, char *write_log_filename, char *print_log_filename) { std::string h(handle); std::string p(path); std::string wlfname(write_log_filename); std::string plfname(print_log_filename); + auto status = entint.LoadEntity(h, p, persistent, load_contained_entities, wlfname, plfname); + return ConvertLoadStatusToCStatus(status); + } - return entint.LoadEntity(h, p, persistent, load_contained_entities, wlfname, plfname); + LoadEntityStatus VerifyEntity(char *path) + { + std::string p(path); + auto status = entint.VerifyEntity(p); + return ConvertLoadStatusToCStatus(status); } void StoreEntity(char *handle, char *path, bool update_persistence_location, bool store_contained_entities) diff --git a/src/Amalgam/AmalgamMain.cpp b/src/Amalgam/AmalgamMain.cpp index 19b1250b..22e22152 100644 --- a/src/Amalgam/AmalgamMain.cpp +++ b/src/Amalgam/AmalgamMain.cpp @@ -229,10 +229,11 @@ PLATFORM_MAIN_CONSOLE else { //run the standard amlg command line interface + EntityExternalInterface::LoadEntityStatus status; std::string file_type = ""; - Entity *entity = asset_manager.LoadEntityFromResourcePath(amlg_file_to_run, file_type, false, true, false, true, random_seed); - if(entity == nullptr) - return 0; + Entity *entity = asset_manager.LoadEntityFromResourcePath(amlg_file_to_run, file_type, false, true, false, true, random_seed, status); + if(!status.loaded) + return 1; asset_manager.SetRootPermission(entity, true); diff --git a/src/Amalgam/AmalgamTrace.cpp b/src/Amalgam/AmalgamTrace.cpp index 4ad91ef8..78f572f0 100644 --- a/src/Amalgam/AmalgamTrace.cpp +++ b/src/Amalgam/AmalgamTrace.cpp @@ -1,13 +1,7 @@ //project headers: -#include "Amalgam.h" #include "AmalgamVersion.h" #include "AssetManager.h" -#include "Entity.h" #include "EntityExternalInterface.h" -#include "EntityQueries.h" -#include "EvaluableNode.h" -#include "Parser.h" -#include "PerformanceProfiler.h" #include "PlatformSpecific.h" #include "RandomStream.h" @@ -75,8 +69,8 @@ int32_t RunAmalgamTrace(std::istream *in_stream, std::ostream *out_stream, std:: transaction_listener_path = ""; std::string new_rand_seed = random_stream.CreateOtherStreamStateViaString("trace"); - bool result = entint.LoadEntity(handle, data, persistent == "true", use_contained == "true", transaction_listener_path, print_listener_path, new_rand_seed); - response = result ? SUCCESS_RESPONSE : FAILURE_RESPONSE; + auto status = entint.LoadEntity(handle, data, persistent == "true", use_contained == "true", transaction_listener_path, print_listener_path, new_rand_seed); + response = status.loaded ? SUCCESS_RESPONSE : FAILURE_RESPONSE; } else { diff --git a/src/Amalgam/AssetManager.cpp b/src/Amalgam/AssetManager.cpp index 96d9dd96..6eebebf3 100644 --- a/src/Amalgam/AssetManager.cpp +++ b/src/Amalgam/AssetManager.cpp @@ -1,6 +1,10 @@ //project headers: -#include "BinaryPacking.h" #include "AssetManager.h" + +#include "Amalgam.h" +#include "AmalgamVersion.h" +#include "BinaryPacking.h" +#include "EntityExternalInterface.h" #include "EvaluableNode.h" #include "FilenameEscapeProcessor.h" #include "FileSupportCSV.h" @@ -9,16 +13,16 @@ #include "PlatformSpecific.h" //system headers: -#include +#include #include -#include #include -#include +#include +#include AssetManager asset_manager; EvaluableNodeReference AssetManager::LoadResourcePath(std::string &resource_path, - std::string &resource_base_path, std::string &file_type, EvaluableNodeManager *enm, bool escape_filename) + std::string &resource_base_path, std::string &file_type, EvaluableNodeManager *enm, bool escape_filename, EntityExternalInterface::LoadEntityStatus &status) { //get file path based on the file loaded std::string path, file_base, extension; @@ -47,6 +51,7 @@ EvaluableNodeReference AssetManager::LoadResourcePath(std::string &resource_path auto [code, code_success] = Platform_OpenFileAsString(processed_resource_path); if(!code_success) { + status.SetStatus(false, code); if(file_type == FILE_EXTENSION_AMALGAM) std::cerr << code << std::endl; return EvaluableNodeReference::Null(); @@ -66,33 +71,20 @@ EvaluableNodeReference AssetManager::LoadResourcePath(std::string &resource_path return Parser::Parse(code, enm, &resource_path); } else if(file_type == FILE_EXTENSION_JSON) - return EvaluableNodeReference(EvaluableNodeJSONTranslation::Load(processed_resource_path, enm), true); + return EvaluableNodeReference(EvaluableNodeJSONTranslation::Load(processed_resource_path, enm, status), true); else if(file_type == FILE_EXTENSION_YAML) - return EvaluableNodeReference(EvaluableNodeYAMLTranslation::Load(processed_resource_path, enm), true); + return EvaluableNodeReference(EvaluableNodeYAMLTranslation::Load(processed_resource_path, enm, status), true); else if(file_type == FILE_EXTENSION_CSV) - return EvaluableNodeReference(FileSupportCSV::Load(processed_resource_path, enm), true); - else if(file_type == FILE_EXTENSION_COMPRESSED_STRING_LIST) - { - BinaryData compressed_data; - if(!LoadFileToBuffer(processed_resource_path, compressed_data)) - return EvaluableNodeReference::Null(); - - OffsetIndex cur_offset = 0; - auto strings = DecompressStrings(compressed_data, cur_offset); - - //transform the decompressed strings into a list of strings - EvaluableNode *list_of_strings = enm->AllocListNodeWithOrderedChildNodes(ENT_STRING, strings.size()); - auto &list_ocn = list_of_strings->GetOrderedChildNodes(); - for(size_t i = 0; i < strings.size(); i++) - list_ocn[i]->SetStringValue(strings[i]); - - return EvaluableNodeReference(list_of_strings, true); - } + return EvaluableNodeReference(FileSupportCSV::Load(processed_resource_path, enm, status), true); else if(file_type == FILE_EXTENSION_COMPRESSED_AMALGAM_CODE) { BinaryData compressed_data; - if(!LoadFileToBuffer(processed_resource_path, compressed_data)) + auto [error_mesg, version, success] = LoadFileToBuffer(processed_resource_path, file_type, compressed_data); + if(!success) + { + status.SetStatus(false, error_mesg, version); return EvaluableNodeReference::Null(); + } OffsetIndex cur_offset = 0; auto strings = DecompressStrings(compressed_data, cur_offset); @@ -107,10 +99,14 @@ EvaluableNodeReference AssetManager::LoadResourcePath(std::string &resource_path else //just load the file as a string { std::string s; - if(LoadFileToBuffer(processed_resource_path, s)) + auto [error_mesg, version, success] = LoadFileToBuffer(processed_resource_path, file_type, s); + if(success) return EvaluableNodeReference(enm->AllocNode(ENT_STRING, s), true); else + { + status.SetStatus(false, error_mesg, version); return EvaluableNodeReference::Null(); + } } } @@ -156,24 +152,6 @@ bool AssetManager::StoreResourcePath(EvaluableNode *code, std::string &resource_ return EvaluableNodeYAMLTranslation::Store(code, processed_resource_path, enm, sort_keys); else if(file_type == FILE_EXTENSION_CSV) return FileSupportCSV::Store(code, processed_resource_path, enm); - else if(file_type == FILE_EXTENSION_COMPRESSED_STRING_LIST) - { - //translate list of strings into a map required for compression - size_t cur_index = 0; - CompactHashMap string_map; - if(code != nullptr) - { - for(auto &cn : code->GetOrderedChildNodes()) - string_map[EvaluableNode::ToStringPreservingOpcodeType(cn)] = cur_index++; - } - - //compress and store - BinaryData compressed_data = CompressStrings(string_map); - if(StoreFileFromBuffer(processed_resource_path, compressed_data)) - return EvaluableNodeReference(enm->AllocNode(ENT_TRUE), true); - else - return EvaluableNodeReference::Null(); - } else if(file_type == FILE_EXTENSION_COMPRESSED_AMALGAM_CODE) { std::string code_string = Parser::Unparse(code, enm, false, true, sort_keys); @@ -184,7 +162,7 @@ bool AssetManager::StoreResourcePath(EvaluableNode *code, std::string &resource_ //compress and store BinaryData compressed_data = CompressStrings(string_map); - if(StoreFileFromBuffer(processed_resource_path, compressed_data)) + if(StoreFileFromBuffer(processed_resource_path, file_type, compressed_data)) return EvaluableNodeReference(enm->AllocNode(ENT_TRUE), true); else return EvaluableNodeReference::Null(); @@ -192,7 +170,7 @@ bool AssetManager::StoreResourcePath(EvaluableNode *code, std::string &resource_ else //binary string { std::string s = EvaluableNode::ToStringPreservingOpcodeType(code); - if(StoreFileFromBuffer(processed_resource_path, s)) + if(StoreFileFromBuffer(processed_resource_path, file_type, s)) return EvaluableNodeReference(enm->AllocNode(ENT_TRUE), true); else return EvaluableNodeReference::Null(); @@ -202,13 +180,14 @@ bool AssetManager::StoreResourcePath(EvaluableNode *code, std::string &resource_ } Entity *AssetManager::LoadEntityFromResourcePath(std::string &resource_path, std::string &file_type, - bool persistent, bool load_contained_entities, bool escape_filename, bool escape_contained_filenames, std::string default_random_seed) + bool persistent, bool load_contained_entities, bool escape_filename, bool escape_contained_filenames, + std::string default_random_seed, EntityExternalInterface::LoadEntityStatus &status) { std::string resource_base_path; Entity *new_entity = new Entity(); - EvaluableNodeReference code = LoadResourcePath(resource_path, resource_base_path, file_type, &new_entity->evaluableNodeManager, escape_filename); - if(code == nullptr) + EvaluableNodeReference code = LoadResourcePath(resource_path, resource_base_path, file_type, &new_entity->evaluableNodeManager, escape_filename, status); + if(!status.loaded) { delete new_entity; return nullptr; @@ -219,15 +198,34 @@ Entity *AssetManager::LoadEntityFromResourcePath(std::string &resource_path, std std::string metadata_filename = resource_base_path + "." + FILE_EXTENSION_AMLG_METADATA; std::string metadata_base_path; std::string metadata_extension; - EvaluableNode *metadata = LoadResourcePath(metadata_filename, metadata_base_path, metadata_extension, &new_entity->evaluableNodeManager, escape_filename); - if(metadata != nullptr) + EntityExternalInterface::LoadEntityStatus metadata_status; + EvaluableNode *metadata = LoadResourcePath(metadata_filename, metadata_base_path, metadata_extension, &new_entity->evaluableNodeManager, escape_filename, metadata_status); + if(metadata_status.loaded) { if(EvaluableNode::IsAssociativeArray(metadata)) { EvaluableNode **seed = metadata->GetMappedChildNode(ENBISI_rand_seed); if(seed != nullptr) default_random_seed = EvaluableNode::ToStringPreservingOpcodeType(*seed); + + EvaluableNode **version = metadata->GetMappedChildNode(ENBISI_version); + if(version != nullptr) + { + auto [tostr_success, version_str] = EvaluableNode::ToString(*version); + if(tostr_success) + { + auto [error_message, success] = AssetManager::ValidateVersionAgainstAmalgam(version_str); + if(!success) + { + status.SetStatus(false, error_message, version_str); + delete new_entity; + return nullptr; + } + } + } } + + new_entity->evaluableNodeManager.FreeNodeTree(metadata); } new_entity->SetRandomState(default_random_seed, true); @@ -258,12 +256,16 @@ Entity *AssetManager::LoadEntityFromResourcePath(std::string &resource_path, std else entity_name = ce_file_base; - //don't escape filename again because it's already escaped in this loop std::string default_seed = new_entity->CreateRandomStreamFromStringAndRand(entity_name); std::string contained_resource_path = resource_base_path + ce_file_base + "." + ce_extension; Entity *contained_entity = LoadEntityFromResourcePath(contained_resource_path, file_type, - false, true, false, escape_contained_filenames, default_seed); + false, true, false, escape_contained_filenames, default_seed, status); + if(!status.loaded) + { + delete new_entity; + return nullptr; + } new_entity->AddContainedEntity(contained_entity, entity_name); } @@ -286,7 +288,9 @@ bool AssetManager::StoreEntityToResourcePath(Entity *entity, std::string &resour std::string metadata_filename = resource_base_path + "." + FILE_EXTENSION_AMLG_METADATA; EvaluableNode en_assoc(ENT_ASSOC); EvaluableNode en_rand_seed(ENT_STRING, entity->GetRandomState()); + EvaluableNode en_version(ENT_STRING, AMALGAM_VERSION_STRING); en_assoc.SetMappedChildNode(ENBISI_rand_seed, &en_rand_seed); + en_assoc.SetMappedChildNode(ENBISI_version, &en_version); std::string metadata_base_path; std::string metadata_extension; @@ -297,7 +301,7 @@ bool AssetManager::StoreEntityToResourcePath(Entity *entity, std::string &resour if(store_contained_entities && entity->GetContainedEntities().size() > 0) { //create directory in case it doesn't exist - std::filesystem::create_directory(resource_base_path); + std::filesystem::create_directories(resource_base_path); //store any contained entities resource_base_path.append("/"); @@ -425,6 +429,35 @@ void AssetManager::SetRootPermission(Entity *entity, bool permission) rootEntities.erase(entity); } +std::pair AssetManager::ValidateVersionAgainstAmalgam(std::string &version) +{ + auto semver = StringManipulation::Split(version, '-'); //split on postfix + auto version_split = StringManipulation::Split(semver[0], '.'); //ignore postfix + if(version_split.size() != 3) + return std::make_pair("Invalid version number", false); + + uint32_t major = atoi(version_split[0].c_str()); + uint32_t minor = atoi(version_split[1].c_str()); + uint32_t patch = atoi(version_split[2].c_str()); + if( + (major > AMALGAM_VERSION_MAJOR) || + (major == AMALGAM_VERSION_MAJOR && minor > AMALGAM_VERSION_MINOR) || + (major == AMALGAM_VERSION_MAJOR && minor == AMALGAM_VERSION_MINOR && patch > AMALGAM_VERSION_PATCH)) + { + std::string err_msg = "Reading newer version not supported"; + std::cerr << err_msg << ", version=" << version << std::endl; + return std::make_pair(err_msg, false); + } + else if(AMALGAM_VERSION_MAJOR > major) + { + std::string err_msg = "Newer Amalgam cannot read older versions"; + std::cerr << err_msg << ", version=" << version << std::endl; + return std::make_pair(err_msg, false); + } + + return std::make_pair("", true); +} + std::string AssetManager::GetEvaluableNodeSourceFromComments(EvaluableNode *en) { std::string source; diff --git a/src/Amalgam/AssetManager.h b/src/Amalgam/AssetManager.h index b6cb8773..5540449d 100644 --- a/src/Amalgam/AssetManager.h +++ b/src/Amalgam/AssetManager.h @@ -2,22 +2,24 @@ //project headers: #include "Entity.h" +#include "EntityExternalInterface.h" #include "EvaluableNode.h" +#include "FileSupportCAML.h" #include "HashMaps.h" //system headers: #include -#include const std::string FILE_EXTENSION_AMLG_METADATA("mdam"); const std::string FILE_EXTENSION_AMALGAM("amlg"); const std::string FILE_EXTENSION_JSON("json"); const std::string FILE_EXTENSION_YAML("yaml"); const std::string FILE_EXTENSION_CSV("csv"); -const std::string FILE_EXTENSION_COMPRESSED_STRING_LIST("cstl"); const std::string FILE_EXTENSION_COMPRESSED_AMALGAM_CODE("caml"); +//forward declarations: class AssetManager; + extern AssetManager asset_manager; class AssetManager @@ -31,7 +33,7 @@ class AssetManager // sets resource_base_path to the resource path without the extension //if file_type is not an empty string, it will use the specified file_type instead of the filename's extension EvaluableNodeReference LoadResourcePath(std::string &resource_path, std::string &resource_base_path, - std::string &file_type, EvaluableNodeManager *enm, bool escape_filename); + std::string &file_type, EvaluableNodeManager *enm, bool escape_filename, EntityExternalInterface::LoadEntityStatus &status); //Stores the code to the corresponding resource path // sets resource_base_path to the resource path without the extension, and extension accordingly @@ -44,7 +46,7 @@ class AssetManager // if persistent is true, then it will keep the resource updated based on any calls to UpdateEntity //if the resource does not have a metadata file, will use default_random_seed as its seed Entity *LoadEntityFromResourcePath(std::string &resource_path, std::string &file_type, bool persistent, bool load_contained_entities, - bool escape_filename, bool escape_contained_filenames, std::string default_random_seed); + bool escape_filename, bool escape_contained_filenames, std::string default_random_seed, EntityExternalInterface::LoadEntityStatus &status); //Stores an entity, including contained entites, etc. from the resource path specified //if file_type is not an empty string, it will use the specified file_type instead of the filename's extension @@ -106,35 +108,59 @@ class AssetManager return rootEntities.find(entity) != end(rootEntities); } - //loads filename into the buffer specified by b (of type BufferType of elements BufferElementType), returns true if successful, false if not + //loads filename into the buffer specified by b (of type BufferType of elements BufferElementType) + //if successful, returns no error message, file version (if available), and true + //if failure, returns error message, file version (if available) and false template - static bool LoadFileToBuffer(const std::string &filename, BufferType &b) + static std::tuple LoadFileToBuffer(const std::string &filename, std::string &file_type, BufferType &b) { std::ifstream f(filename, std::fstream::binary | std::fstream::in); if(!f.good()) - return false; + return std::make_tuple("Cannot open file", "", false); + + size_t header_size = 0; + std::string file_version; + if(file_type == FILE_EXTENSION_COMPRESSED_AMALGAM_CODE) + { + auto [error_string, version, success] = FileSupportCAML::ReadHeader(f, header_size); + if(!success) + return std::make_tuple(error_string, version, false); + else + file_version = version; + } f.seekg(0, std::ios::end); - b.reserve(f.tellg()); - f.seekg(0, std::ios::beg); + b.reserve(static_cast(f.tellg()) - header_size); + f.seekg(header_size, std::ios::beg); b.assign(std::istreambuf_iterator(f), std::istreambuf_iterator()); - return true; + return std::make_tuple("", file_version, true); } //stores buffer b (of type BufferType of elements BufferElementType) into the filename, returns true if successful, false if not template - static bool StoreFileFromBuffer(const std::string &filename, BufferType &b) + static bool StoreFileFromBuffer(const std::string &filename, std::string &file_type, BufferType &b) { std::ofstream f(filename, std::fstream::binary | std::fstream::out); if(!f.good()) return false; + if(file_type == FILE_EXTENSION_COMPRESSED_AMALGAM_CODE) + { + if(!FileSupportCAML::WriteHeader(f)) + return false; + } + f.write(reinterpret_cast(&b[0]), sizeof(char) * b.size()); return true; } + //validates given asset version against Amalgam version + //if successful: returns empty string and true + //if failure: returns error message and false + static std::pair ValidateVersionAgainstAmalgam(std::string &version); + //returns a string representing en's source, empty string if debugSources is false std::string GetEvaluableNodeSourceFromComments(EvaluableNode *en); diff --git a/src/Amalgam/Opcodes.cpp b/src/Amalgam/Opcodes.cpp index 0243143a..4c86ecdd 100644 --- a/src/Amalgam/Opcodes.cpp +++ b/src/Amalgam/Opcodes.cpp @@ -303,6 +303,7 @@ void StringInternPool::InitializeStaticStrings() //config file parameters EmplaceStaticString(ENBISI_rand_seed, "rand_seed"); + EmplaceStaticString(ENBISI_version, "version"); //substr parameters EmplaceStaticString(ENBISI_all, "all"); diff --git a/src/Amalgam/Opcodes.h b/src/Amalgam/Opcodes.h index dc1c1c24..92e8153d 100644 --- a/src/Amalgam/Opcodes.h +++ b/src/Amalgam/Opcodes.h @@ -522,6 +522,7 @@ enum EvaluableNodeBuiltInStringId //config file parameters ENBISI_rand_seed, + ENBISI_version, //substr parameters ENBISI_all, diff --git a/src/Amalgam/amlg_code/full_test.amlg b/src/Amalgam/amlg_code/full_test.amlg index b27e0b35..b0d28947 100644 --- a/src/Amalgam/amlg_code/full_test.amlg +++ b/src/Amalgam/amlg_code/full_test.amlg @@ -2007,7 +2007,6 @@ (call_entity "ModuleTest" "hello") (print (flatten_entity "ModuleTest")) - (print "--load_persistent_entity--\n") (load_persistent_entity "amlg_code/persist_module_test.amlg" "PersistModuleTest") (assign_to_entities "PersistModuleTest" (assoc a 8)) @@ -2026,9 +2025,9 @@ (create_entities (list "pt" "child") (list 5 6 7)) (create_entities (list "pt" "child" "doublechild1") (list 8 9)) (create_entities (list "pt" "child" "doublechild2") (list 10 11)) - (store_entity "amlg_code/pt.amlg" "pt") + (store_entity "amlg_code/test_output/pt.amlg" "pt") (destroy_entities "pt") - (load_persistent_entity "amlg_code/pt.amlg" "ptl") + (load_persistent_entity "amlg_code/test_output/pt.amlg" "ptl") (destroy_entities (list "ptl" "child")) ; persistent grandchild test @@ -2046,12 +2045,12 @@ (load_entity "amlg_code/persistent_tree_test_leaf.amlg" (list "PersistTreeRoot" "leaf_backup")) (call_entity "PersistTreeRoot" "kill_inter") - (store_entity "amlg_code/persistent_tree_test_leaf.amlg" (list "PersistTreeRoot" "leaf_backup")) + (store_entity "amlg_code/test_output/persistent_tree_test_leaf.amlg" (list "PersistTreeRoot" "leaf_backup")) (call_entity "PersistTreeRoot" "clean_backup") (print "--store--\n") - (store "amlg_code/store_test.amlg" (list 1 2 3 4)) - (print (load "amlg_code/store_test.amlg")) + (store "amlg_code/test_output/store_test.amlg" (list 1 2 3 4)) + (print (load "amlg_code/test_output/store_test.amlg")) ;test escaped labels (declare (assoc @@ -2067,21 +2066,18 @@ (print (retrieve_entity_root entity 1)) (print "retrieved: " (retrieve_from_entity entity ".#blah") "\n\n") - (store_entity "amlg_code/escaped_label.amlg" entity) - (load_entity "amlg_code/escaped_label.amlg" "escaped_label") + (store_entity "amlg_code/test_output/escaped_label.amlg" entity) + (load_entity "amlg_code/test_output/escaped_label.amlg" "escaped_label") (print "loaded from file:\n" (retrieve_entity_root "escaped_label" 1)) (print "retrieved: " (retrieve_from_entity "escaped_label" ".#blah") "\n") (print "--store other file formats---\n") - (store "amlg_code/text_store_test.txt" "This is text!") - (print "[" (load "amlg_code/text_store_test.txt") "]\n") - - (store "amlg_code/cstl_store_test.cstl" (list "String 1." "String 2." "String 3.")) - (print (load "amlg_code/cstl_store_test.cstl") "\n") + (store "amlg_code/test_output/text_store_test.txt" "This is text!") + (print "[" (load "amlg_code/test_output/text_store_test.txt") "]\n") - (store "amlg_code/caml_store_test.caml" (lambda (seq (print "hello"))) ) - (print (load "amlg_code/caml_store_test.caml") "\n") + (store "amlg_code/test_output/caml_store_test.caml" (lambda (seq (print "hello"))) ) + (print (load "amlg_code/test_output/caml_store_test.caml") "\n") ;test escaping contained entity filenames (create_entities "quackerz?" "test") @@ -2090,8 +2086,8 @@ (print "contained entities in quackers before file: " (contained_entities "quackerz?") "\n") - (store_entity "amlg_code/!quackerz.amlg" "quackerz?" (true)) - (load_entity "amlg_code/!quackerz.amlg" "read-back quackers" (true)) + (store_entity "amlg_code/test_output/!quackerz.amlg" "quackerz?" (true)) + (load_entity "amlg_code/test_output/!quackerz.amlg" "read-back quackers" (true)) (print "contained entity in quackers2 loaded back from file: " (contained_entities "read-back quackers") "\n") @@ -2106,30 +2102,30 @@ (list 4.4 3.2 1.3 0.2 "setosa") ) )) - (store "amlg_code/csv_store_test.csv" csv_data) - (print (load "amlg_code/csv_store_test.csv") ) + (store "amlg_code/test_output/csv_store_test.csv" csv_data) + (print (load "amlg_code/test_output/csv_store_test.csv") ) (print "--store_entity--\n") (print "store to .amlg:\n") (assign_to_entities "ModuleTest" (assoc a 2)) (print (unparse (retrieve_from_entity "ModuleTest" "a") (true) (true))) - (store_entity "amlg_code/module_test2.amlg" "ModuleTest") - (load_entity "amlg_code/module_test2.amlg" "ModuleTest2") + (store_entity "amlg_code/test_output/module_test2.amlg" "ModuleTest") + (load_entity "amlg_code/test_output/module_test2.amlg" "ModuleTest2") (print (unparse (retrieve_from_entity "ModuleTest" "a") (true) (true))) (assign_to_entities "ModuleTest" (assoc a 1)) - (store_entity "amlg_code/module_test2.amlg" "ModuleTest") + (store_entity "amlg_code/test_output/module_test2.amlg" "ModuleTest") - (store_entity "amlg_code/module_testc.caml" "ModuleTest") - (load_entity "amlg_code/module_test_c.caml" "ModuleTestDecompressed") + (store_entity "amlg_code/test_output/module_testc.caml" "ModuleTest") + (load_entity "amlg_code/test_output/module_test_c.caml" "ModuleTestDecompressed") (print "Compression difference: [" (difference_entities "ModuleTest" "ModuleTestDecompressed") "]\n") (print "store to .json in amlg format\n") - (store "amlg_code/module_test.json" (list (assoc a 3 b 4) (assoc c "c" d (null))) (false) "amlg") - (print (load "amlg_code/module_test.json" (false) "amlg")) + (store "amlg_code/test_output/module_test.json" (list (assoc a 3 b 4) (assoc c "c" d (null))) (false) "amlg") + (print (load "amlg_code/test_output/module_test.json" (false) "amlg")) (print "store to .json normally\n") - (store "amlg_code/module_test.json" (list (assoc a 3 b 4) (assoc c "c" d (null)))) - (print (load "amlg_code/module_test.json")) + (store "amlg_code/test_output/module_test.json" (list (assoc a 3 b 4) (assoc c "c" d (null)))) + (print (load "amlg_code/test_output/module_test.json")) (print "--contains_entity--\n") @@ -4021,6 +4017,17 @@ ;make sure the lists match up and none were lost (print "concurrent entity writes successful: " (= (range 1 1000) (sort concurrent_ent_writes)) "\n") + (print "--clean-up test files--\n") + (declare (assoc rmdir "rmdir /s /q " rmfile "del /s /q " slash "\\")) + (if (!= (system "os") "Windows") + (assign (assoc rmdir "rm -r " rmfile "rm " slash "/")) + ) + (system "system" (concat rmdir "amlg_code" slash "test_output")) + (system "system" (concat rmdir "amlg_code" slash "persistent_tree_test_root")) + (system "system" (concat rmfile "amlg_code" slash "persist_module_test" slash "psm.mdam")) + (system "system" (concat rmfile "amlg_code" slash "persist_module_test.mdam")) + (system "system" (concat rmfile "amlg_code" slash "persistent_tree_test_leaf.mdam")) + (print "--total execution time--\n") (print (- (system_time) start_time) "\n") -) +) \ No newline at end of file diff --git a/src/Amalgam/amlg_code/module_test2.amlg b/src/Amalgam/amlg_code/module_test2.amlg deleted file mode 100644 index 91ec7e06..00000000 --- a/src/Amalgam/amlg_code/module_test2.amlg +++ /dev/null @@ -1,8 +0,0 @@ -(assoc - b #b (true) - a #a 1 - hello #hello - (print "hello\n") - d #d 100000000 - c #c 0.1 -) diff --git a/src/Amalgam/amlg_code/module_test2/submoduletest.amlg b/src/Amalgam/amlg_code/module_test2/submoduletest.amlg deleted file mode 100644 index 025683ac..00000000 --- a/src/Amalgam/amlg_code/module_test2/submoduletest.amlg +++ /dev/null @@ -1,5 +0,0 @@ -(parallel - #a 7 - #hello - (print "sub hello\n") -) diff --git a/src/Amalgam/amlg_code/module_test2/submoduletest2.amlg b/src/Amalgam/amlg_code/module_test2/submoduletest2.amlg deleted file mode 100644 index d8efc524..00000000 --- a/src/Amalgam/amlg_code/module_test2/submoduletest2.amlg +++ /dev/null @@ -1,5 +0,0 @@ -(parallel - #a 8 - #hello - (print "sub hello 2\n") -) diff --git a/src/Amalgam/amlg_code/repl.amlg b/src/Amalgam/amlg_code/repl.amlg deleted file mode 100644 index 4401ed7f..00000000 --- a/src/Amalgam/amlg_code/repl.amlg +++ /dev/null @@ -1,13 +0,0 @@ -(while 1 - (system "printline" "> ") - ;(print (call (parse (system "readline"))) "\n") - (let (assoc input (system "readline")) - (if - (= "(" (first (explode input)) ) - (print (call (parse input)) "\n") - (print (call - (parse (concat "(" input ")")) - ) "\n") - ) - ) -) diff --git a/src/Amalgam/amlg_code/store_test.amlg b/src/Amalgam/amlg_code/store_test.amlg deleted file mode 100644 index e20ee0dc..00000000 --- a/src/Amalgam/amlg_code/store_test.amlg +++ /dev/null @@ -1 +0,0 @@ -(list 1 2 3 4) diff --git a/src/Amalgam/entity/EntityExternalInterface.cpp b/src/Amalgam/entity/EntityExternalInterface.cpp index 24c002b8..651cd06c 100644 --- a/src/Amalgam/entity/EntityExternalInterface.cpp +++ b/src/Amalgam/entity/EntityExternalInterface.cpp @@ -1,13 +1,39 @@ //project headers: #include "EntityExternalInterface.h" -#include "EntityQueries.h" + +#include "AssetManager.h" +#include "Entity.h" #include "EntityWriteListener.h" +#include "FileSupportCAML.h" #include "FileSupportJSON.h" #include "Interpreter.h" -bool EntityExternalInterface::LoadEntity(std::string &handle, std::string &path, bool persistent, bool load_contained_entities, +//system headers: +#include +#include + +EntityExternalInterface::LoadEntityStatus::LoadEntityStatus() +{ + SetStatus(true); +} + +EntityExternalInterface::LoadEntityStatus::LoadEntityStatus(bool loaded, std::string message, std::string version) +{ + SetStatus(loaded, message, version); +} + +void EntityExternalInterface::LoadEntityStatus::SetStatus(bool loaded_in, std::string message_in, std::string version_in) +{ + loaded = loaded_in; + message = std::move(message_in); + version = std::move(version_in); +} + +EntityExternalInterface::LoadEntityStatus EntityExternalInterface::LoadEntity(std::string &handle, std::string &path, bool persistent, bool load_contained_entities, std::string &write_log_filename, std::string &print_log_filename, std::string rand_seed) { + LoadEntityStatus status; + if(rand_seed == "") { typedef std::chrono::steady_clock clk; @@ -16,11 +42,11 @@ bool EntityExternalInterface::LoadEntity(std::string &handle, std::string &path, } std::string file_type = ""; - Entity *entity = asset_manager.LoadEntityFromResourcePath(path, file_type, persistent, load_contained_entities, false, true, rand_seed); - asset_manager.SetRootPermission(entity, true); + Entity *entity = asset_manager.LoadEntityFromResourcePath(path, file_type, persistent, load_contained_entities, false, true, rand_seed, status); + if(!status.loaded) + return status; - if(entity == nullptr) - return false; + asset_manager.SetRootPermission(entity, true); PrintListener *pl = nullptr; std::vector wl; @@ -36,7 +62,22 @@ bool EntityExternalInterface::LoadEntity(std::string &handle, std::string &path, AddEntityBundle(handle, new EntityListenerBundle(entity, wl, pl)); - return true; + return status; +} + +EntityExternalInterface::LoadEntityStatus EntityExternalInterface::VerifyEntity(std::string &path) +{ + std::ifstream f(path, std::fstream::binary | std::fstream::in); + + if(!f.good()) + return EntityExternalInterface::LoadEntityStatus(false, "Cannot open file", ""); + + size_t header_size = 0; + auto [error_string, version, success] = FileSupportCAML::ReadHeader(f, header_size); + if(!success) + return EntityExternalInterface::LoadEntityStatus(false, error_string, version); + + return EntityExternalInterface::LoadEntityStatus(false, "", version); } void EntityExternalInterface::StoreEntity(std::string &handle, std::string &path, bool update_persistence_location, bool store_contained_entities) @@ -573,3 +614,17 @@ bool EntityExternalInterface::EntityListenerBundle::SetEntityValueAtLabel(std::s return success; } + +EntityExternalInterface::EntityListenerBundle::~EntityListenerBundle() +{ + if(entity != nullptr) + { + asset_manager.DestroyEntity(entity); + delete entity; + } + + if(printListener != nullptr) + delete printListener; + if(writeListeners.size() > 0 && writeListeners[0] != nullptr) + delete writeListeners[0]; +} diff --git a/src/Amalgam/entity/EntityExternalInterface.h b/src/Amalgam/entity/EntityExternalInterface.h index 5c49cc0f..099b594c 100644 --- a/src/Amalgam/entity/EntityExternalInterface.h +++ b/src/Amalgam/entity/EntityExternalInterface.h @@ -1,7 +1,6 @@ #pragma once -//project headers: -#include "AssetManager.h" +//project headers: #include "Entity.h" #include "EntityWriteListener.h" #include "HashMaps.h" @@ -23,8 +22,23 @@ class EntityExternalInterface { public: - bool LoadEntity(std::string &handle, std::string &path, bool persistent, bool load_contained_entities, + + //status from LoadEntity + class LoadEntityStatus + { + public: + LoadEntityStatus(); + LoadEntityStatus(bool loaded, std::string message = std::string(), std::string version = std::string()); + void SetStatus(bool loaded_in, std::string message_in = std::string(), std::string version_in = std::string()); + + bool loaded; + std::string message; + std::string version; + }; + + LoadEntityStatus LoadEntity(std::string &handle, std::string &path, bool persistent, bool load_contained_entities, std::string &write_log_filename, std::string &print_log_filename, std::string rand_seed = std::string("")); + LoadEntityStatus VerifyEntity(std::string &path); void StoreEntity(std::string &handle, std::string &path, bool update_persistence_location, bool store_contained_entities); void ExecuteEntity(std::string &handle, std::string &label); void DestroyEntity(std::string &handle); @@ -74,19 +88,7 @@ class EntityExternalInterface printListener = pl; } - ~EntityListenerBundle() - { - if(entity != nullptr) - { - asset_manager.DestroyEntity(entity); - delete entity; - } - - if(printListener != nullptr) - delete printListener; - if(writeListeners.size() > 0 && writeListeners[0] != nullptr) - delete writeListeners[0]; - } + ~EntityListenerBundle(); //Wraps around Entity::SetValueAtLabel but accepts a string for label name bool SetEntityValueAtLabel(std::string &label_name, EvaluableNodeReference new_value); diff --git a/src/Amalgam/importexport/FileSupportCAML.cpp b/src/Amalgam/importexport/FileSupportCAML.cpp new file mode 100644 index 00000000..09d3e04d --- /dev/null +++ b/src/Amalgam/importexport/FileSupportCAML.cpp @@ -0,0 +1,102 @@ +//project headers: +#include "FileSupportCAML.h" + +#include "AmalgamVersion.h" +#include "AssetManager.h" + +//system headers: +#include +#include +#include +#include +#include +#include + +//magic number written at beginning of CAML file +static const uint8_t s_magic_number[] = { 'c', 'a', 'm', 'l' }; + +bool ReadBigEndian(std::ifstream &stream, uint32_t &val) +{ + uint8_t buffer[4] = { 0 }; + if(!stream.read(reinterpret_cast(buffer), sizeof(uint32_t))) + return false; + + auto num_bytes_read = stream.gcount(); + if(num_bytes_read != sizeof(uint32_t)) + return false; + + val = static_cast((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); + + return true; +} + +bool WriteBigEndian(std::ofstream &stream, const uint32_t &val) +{ + uint8_t buffer[4] = { 0 }; + buffer[0] = (val >> 24) & 0xFF; + buffer[1] = (val >> 16) & 0xFF; + buffer[2] = (val >> 8) & 0xFF; + buffer[3] = val & 0xFF; + stream.write(reinterpret_cast(buffer), sizeof(buffer)); + + return true; +} + +bool ReadVersion(std::ifstream &stream, uint32_t &major, uint32_t &minor, uint32_t &patch) +{ + if(!ReadBigEndian(stream, major)) + return false; + if(!ReadBigEndian(stream, minor)) + return false; + if(!ReadBigEndian(stream, patch)) + return false; + + return true; +} + +bool WriteVersion(std::ofstream &stream) +{ + if(!WriteBigEndian(stream, AMALGAM_VERSION_MAJOR)) + return false; + if(!WriteBigEndian(stream, AMALGAM_VERSION_MINOR)) + return false; + if(!WriteBigEndian(stream, AMALGAM_VERSION_PATCH)) + return false; + + return true; +} + +std::tuple FileSupportCAML::ReadHeader(std::ifstream &stream, size_t &header_size) +{ + uint8_t magic[4] = { 0 }; + if(!stream.read(reinterpret_cast(magic), sizeof(magic))) + return std::make_tuple("Cannot read CAML header", "", false); + header_size += sizeof(magic); + + auto num_bytes_read = stream.gcount(); + if(num_bytes_read != sizeof(magic)) + return std::make_tuple("Cannot read CAML header", "", false); + else if(memcmp(magic, s_magic_number, sizeof(magic)) == 0) + { + uint32_t major = 0, minor = 0, patch = 0; + if(!ReadVersion(stream, major, minor, patch)) + return std::make_tuple("Cannot read CAML version", "", false); + header_size += sizeof(major) * 3; + std::string version = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(patch); + + //validate version + auto [error_message, success] = AssetManager::ValidateVersionAgainstAmalgam(version); + if(!success) + return std::make_tuple(error_message, version, false); + } + + return std::make_tuple("", "", true); +} + +bool FileSupportCAML::WriteHeader(std::ofstream &stream) +{ + if(!stream.write(reinterpret_cast(s_magic_number), sizeof(s_magic_number))) + return false; + + return WriteVersion(stream); +} \ No newline at end of file diff --git a/src/Amalgam/importexport/FileSupportCAML.h b/src/Amalgam/importexport/FileSupportCAML.h new file mode 100644 index 00000000..7331e9e6 --- /dev/null +++ b/src/Amalgam/importexport/FileSupportCAML.h @@ -0,0 +1,18 @@ +#pragma once + +//system headers: +#include +#include +#include +#include + +namespace FileSupportCAML +{ + //read the header from the stream + //if successfully: returns empty strings and true + //if failure: returns error message, file version, and false + std::tuple ReadHeader(std::ifstream &stream, size_t &header_size); + + //write the header to the stream + bool WriteHeader(std::ofstream &stream); +}; \ No newline at end of file diff --git a/src/Amalgam/importexport/FileSupportCSV.cpp b/src/Amalgam/importexport/FileSupportCSV.cpp index 8d78b03f..1114d3b9 100644 --- a/src/Amalgam/importexport/FileSupportCSV.cpp +++ b/src/Amalgam/importexport/FileSupportCSV.cpp @@ -6,11 +6,12 @@ #include #include -EvaluableNode *FileSupportCSV::Load(const std::string &resource_path, EvaluableNodeManager *enm) +EvaluableNode *FileSupportCSV::Load(const std::string &resource_path, EvaluableNodeManager *enm, EntityExternalInterface::LoadEntityStatus &status) { auto [data, data_success] = Platform_OpenFileAsString(resource_path); if(!data_success) { + status.SetStatus(false, data); std::cerr << data << std::endl; return EvaluableNodeReference::Null(); } diff --git a/src/Amalgam/importexport/FileSupportCSV.h b/src/Amalgam/importexport/FileSupportCSV.h index ed7b01a1..34a6e084 100644 --- a/src/Amalgam/importexport/FileSupportCSV.h +++ b/src/Amalgam/importexport/FileSupportCSV.h @@ -1,12 +1,12 @@ #pragma once //project headers: +#include "EntityExternalInterface.h" #include "EvaluableNode.h" #include "EvaluableNodeManagement.h" -class FileSupportCSV +namespace FileSupportCSV { -public: - static EvaluableNode *Load(const std::string &resource_path, EvaluableNodeManager *enm); - static bool Store(EvaluableNode *code, const std::string &resource_path, EvaluableNodeManager *enm); + EvaluableNode *Load(const std::string &resource_path, EvaluableNodeManager *enm, EntityExternalInterface::LoadEntityStatus &status); + bool Store(EvaluableNode *code, const std::string &resource_path, EvaluableNodeManager *enm); }; diff --git a/src/Amalgam/importexport/FileSupportJSON.cpp b/src/Amalgam/importexport/FileSupportJSON.cpp index 305ba964..77379bd7 100644 --- a/src/Amalgam/importexport/FileSupportJSON.cpp +++ b/src/Amalgam/importexport/FileSupportJSON.cpp @@ -1,7 +1,7 @@ //project headers: #include "FileSupportJSON.h" -#include "EvaluableNodeTreeFunctions.h" +#include "EntityExternalInterface.h" #include "FastMath.h" #include "PlatformSpecific.h" #include "StringManipulation.h" @@ -10,7 +10,6 @@ #include "simdjson/simdjson.h" //system headers: -#include #include #include @@ -335,12 +334,14 @@ std::pair EvaluableNodeJSONTranslation::EvaluableNodeToJson(E return std::make_pair("", false); } -EvaluableNode *EvaluableNodeJSONTranslation::Load(const std::string &resource_path, EvaluableNodeManager *enm) +EvaluableNode *EvaluableNodeJSONTranslation::Load(const std::string &resource_path, EvaluableNodeManager *enm, EntityExternalInterface::LoadEntityStatus &status) { std::string error_string; if(!Platform_IsResourcePathAccessible(resource_path, true, error_string)) { - std::cerr << "Error loading JSON: " << error_string << std::endl; + std::string err = "Error loading JSON: " + error_string; + status.SetStatus(false, err); + std::cerr << err << std::endl; return nullptr; } @@ -355,7 +356,9 @@ EvaluableNode *EvaluableNodeJSONTranslation::Load(const std::string &resource_pa { //get rid of unused variable warning (void)e; - std::cerr << "Error loading JSON, malformatted file " << resource_path << std::endl; + std::string err = "Error loading JSON, malformatted file " + resource_path; + status.SetStatus(false, err); + std::cerr << err << std::endl; return nullptr; } } diff --git a/src/Amalgam/importexport/FileSupportJSON.h b/src/Amalgam/importexport/FileSupportJSON.h index 2e9b74fd..1a6a493e 100644 --- a/src/Amalgam/importexport/FileSupportJSON.h +++ b/src/Amalgam/importexport/FileSupportJSON.h @@ -1,6 +1,7 @@ #pragma once //project headers: +#include "EntityExternalInterface.h" #include "EvaluableNode.h" #include "EvaluableNodeManagement.h" @@ -17,7 +18,7 @@ namespace EvaluableNodeJSONTranslation std::pair EvaluableNodeToJson(EvaluableNode *code, bool sort_keys = false); //loads json file to EvaluableNode tree - EvaluableNode *Load(const std::string &resource_path, EvaluableNodeManager *enm); + EvaluableNode *Load(const std::string &resource_path, EvaluableNodeManager *enm, EntityExternalInterface::LoadEntityStatus &status); //stores EvaluableNode tree to json file bool Store(EvaluableNode *code, const std::string &resource_path, EvaluableNodeManager *enm, bool sort_keys); diff --git a/src/Amalgam/importexport/FileSupportYAML.cpp b/src/Amalgam/importexport/FileSupportYAML.cpp index 7233751f..96143b03 100644 --- a/src/Amalgam/importexport/FileSupportYAML.cpp +++ b/src/Amalgam/importexport/FileSupportYAML.cpp @@ -1,10 +1,7 @@ //project headers: #include "FileSupportYAML.h" -#include "EvaluableNodeTreeFunctions.h" -#include "FastMath.h" #include "PlatformSpecific.h" -#include "StringManipulation.h" //3rd party headers: #define RYML_SINGLE_HDR_DEFINE_NOW @@ -175,11 +172,12 @@ std::pair EvaluableNodeYAMLTranslation::EvaluableNodeToYaml(E return std::make_pair("", false); } -EvaluableNode *EvaluableNodeYAMLTranslation::Load(const std::string &resource_path, EvaluableNodeManager *enm) +EvaluableNode *EvaluableNodeYAMLTranslation::Load(const std::string &resource_path, EvaluableNodeManager *enm, EntityExternalInterface::LoadEntityStatus &status) { auto [data, data_success] = Platform_OpenFileAsString(resource_path); if(!data_success) { + status.SetStatus(false, data); std::cerr << data << std::endl; return EvaluableNodeReference::Null(); } @@ -188,7 +186,11 @@ EvaluableNode *EvaluableNodeYAMLTranslation::Load(const std::string &resource_pa ryml::ConstNodeRef yaml_top_element = tree.rootref(); - return YamlToEvaluableNodeRecurse(enm, yaml_top_element); + auto en = YamlToEvaluableNodeRecurse(enm, yaml_top_element); + if(en == nullptr) + status.SetStatus(false, "Cannot convert YAML to Amalgam node"); + + return en; } bool EvaluableNodeYAMLTranslation::Store(EvaluableNode *code, const std::string &resource_path, EvaluableNodeManager *enm, bool sort_keys) diff --git a/src/Amalgam/importexport/FileSupportYAML.h b/src/Amalgam/importexport/FileSupportYAML.h index 1eceab39..4dee6e2d 100644 --- a/src/Amalgam/importexport/FileSupportYAML.h +++ b/src/Amalgam/importexport/FileSupportYAML.h @@ -1,6 +1,7 @@ #pragma once //project headers: +#include "EntityExternalInterface.h" #include "EvaluableNode.h" #include "EvaluableNodeManagement.h" @@ -17,7 +18,7 @@ namespace EvaluableNodeYAMLTranslation std::pair EvaluableNodeToYaml(EvaluableNode *code, bool sort_keys = false); //loads yaml file to EvaluableNode tree - EvaluableNode *Load(const std::string &resource_path, EvaluableNodeManager *enm); + EvaluableNode *Load(const std::string &resource_path, EvaluableNodeManager *enm, EntityExternalInterface::LoadEntityStatus &status); //stores EvaluableNode tree to yaml file bool Store(EvaluableNode *code, const std::string &resource_path, EvaluableNodeManager *enm, bool sort_keys); diff --git a/src/Amalgam/interpreter/InterpreterOpcodesEntityControl.cpp b/src/Amalgam/interpreter/InterpreterOpcodesEntityControl.cpp index 2af64828..4daddc4a 100644 --- a/src/Amalgam/interpreter/InterpreterOpcodesEntityControl.cpp +++ b/src/Amalgam/interpreter/InterpreterOpcodesEntityControl.cpp @@ -1,8 +1,8 @@ //project headers: #include "Interpreter.h" -#include "AmalgamVersion.h" #include "AssetManager.h" +#include "EntityExternalInterface.h" #include "EntityManipulation.h" #include "EntityQueries.h" #include "EvaluableNodeTreeFunctions.h" @@ -568,8 +568,9 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_LOAD(EvaluableNode *en, bo file_type = file_type_temp; } + EntityExternalInterface::LoadEntityStatus status; std::string resource_base_path; - return asset_manager.LoadResourcePath(resource_name, resource_base_path, file_type, evaluableNodeManager, escape_filename); + return asset_manager.LoadResourcePath(resource_name, resource_base_path, file_type, evaluableNodeManager, escape_filename, status); } EvaluableNodeReference Interpreter::InterpretNode_ENT_LOAD_ENTITY_and_LOAD_PERSISTENT_ENTITY(EvaluableNode *en, bool immediate_result) @@ -615,16 +616,18 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_LOAD_ENTITY_and_LOAD_PERSI file_type = file_type_temp; } + EntityExternalInterface::LoadEntityStatus status; std::string random_seed = destination_entity_parent->CreateRandomStreamFromStringAndRand(resource_name); Entity *loaded_entity = asset_manager.LoadEntityFromResourcePath(resource_name, file_type, - persistent, true, escape_filename, escape_contained_filenames, random_seed); + persistent, true, escape_filename, escape_contained_filenames, random_seed, status); //handle errors - if(loaded_entity == nullptr) + if(!status.loaded) return EvaluableNodeReference::Null(); if(new_entity_id == StringInternPool::NOT_A_STRING_ID) { - delete loaded_entity; + if(loaded_entity != nullptr) + delete loaded_entity; return EvaluableNodeReference::Null(); } diff --git a/src/Amalgam/out.txt b/src/Amalgam/out.txt index a9be143b..8846cfef 100644 --- a/src/Amalgam/out.txt +++ b/src/Amalgam/out.txt @@ -1,13 +1,13 @@ ---Amalgam Version-- -0.0.0 ---system_time-- ---label-- -hello world: 12 and 2 -hello world: 12 and 2 ---non-keyword token-- -6 -notakeyword ---get_defaults-- +--Amalgam Version-- +47.1.4-alpha+local.dev +--system_time-- +--label-- +hello world: 12 and 2 +hello world: 12 and 2 +--non-keyword token-- +6 +notakeyword +--get_defaults-- (assoc != 0.65 !~ 0.1 @@ -229,62 +229,62 @@ notakeyword insert 0.23 swap_elements 0.24 ) ---parse and unparse-- -(print "hello") +--parse and unparse-- +(print "hello") (list .nan .nan .infinity -.infinity) - -(assoc b 2 a 1 c (list "alpha" "beta" "gamma")) + +(assoc b 2 a 1 c (list "alpha" "beta" "gamma")) (assoc b 2 a 1 c (list "alpha" "beta" "gamma") ) - ---if-- -if 1 -if 2 -4 ---seq-- -1 -2 -3 ---lambda and call-- + +--if-- +if 1 +if 2 +4 +--seq-- +1 +2 +3 +--lambda and call-- (declare (assoc x 6) (+ x 2) ) -5 +5 (lambda (+ 1 2) ) ---call_sandboxed-- -7 -.nan ---while-- -1 -2 -3 -4 -5 -6 -7 -8 -9 ---conclude-- -seq1 success -while1 success -let1 success -declare1 success -142 ---declare-- -7 -7 ---let-- -10 -11 ---assign-- -10 -20 +--call_sandboxed-- +7 +.nan +--while-- +1 +2 +3 +4 +5 +6 +7 +8 +9 +--conclude-- +seq1 success +while1 success +let1 success +declare1 success +142 +--declare-- +7 +7 +--let-- +10 +11 +--assign-- +10 +20 (list 0 1 @@ -307,12 +307,12 @@ declare1 success c (list "c attribute") ) ) ---accum-- -10 -11 -abcdef +--accum-- +10 +11 +abcdef (list 1 2 3 4 5 6) - + (list 1 2 @@ -323,14 +323,14 @@ abcdef "7" 8 ) - + (assoc a 1 b 2 c 3 d 4 ) - + (assoc a 1 b 2 @@ -338,37 +338,37 @@ abcdef d 4 e 5 ) - -5 + +5 (list 0 2 2 (assoc a 1 b 2 c 3) ) - ---retrieve-- -1 -1 + +--retrieve-- +1 +1 (list 1 2) (assoc raaa 2 rwww 1) ---assign-- -8 -12 +--assign-- +8 +12 (list 0 1 10 3 4) (assoc a 3 b 2) ---+-- -10 ------ --8 --3 ---*-- -24 ---/-- -0.041666666666666664 ---mod-- -1 ---get_digits-- +--+-- +10 +----- +-8 +-3 +--*-- +24 +--/-- +0.041666666666666664 +--mod-- +1 +--get_digits-- (list 1 2 @@ -449,154 +449,154 @@ abcdef 0 0 ) ---set_digits-- -5554567.8 -1234567.555 -4 -1.5 -3 -1.5 -55501234567.8 -2.25 -5555567.8 -1234555.55 -5.555567800000001e+100 -1.2345555499999999e+100 -1.23456585e+100 +--set_digits-- +5554567.8 +1234567.555 +4 +1.5 +3 +1.5 +55501234567.8 +2.25 +5555567.8 +1234555.55 +5.555567800000001e+100 +1.2345555499999999e+100 +1.23456585e+100 (list 1 0 1 0) (list 1 0 1 0) (list 1 0 1 0) ---floor-- -1 ---ceil-- -2 ---round-- -13 -10 -123.46 -120 -120 -123.46 -123 -0 -1.2 -0 -0.012 -0.01 -0 -0.012345678 -0.6 -0.6 -0.3 ---exp-- -1.6487212707001282 ---log-- --0.6931471805599453 -4 ---sin-- -0.479425538604203 ---asin-- -0.5235987755982989 ---cos-- -0.8775825618903728 ---acos-- -1.0471975511965979 ---tan-- -0.5463024898437905 ---atan-- -0.4636476090008061 -0.7853981633974483 ---sinh-- -0.5210953054937474 ---asinh-- -0.48121182505960347 ---cosh-- -1.1276259652063807 ---acosh-- -.nan ---tanh-- -0.46211715726000974 ---atanh-- -0.5493061443340549 ---erf-- -0.5204998778130465 ---tgamma-- -1.772453850905516 ---lgamma-- -0.5723649429247001 ---sqrt-- -0.7071067811865476 ---pow-- -0.25 ---abs-- -0.5 ---max-- -9 -8 -(null) ---min-- --5 -4 ---dot_product-- -6 -6 -6 ---generalized_distance-- - 0 2.0874003024080013e+234 - 1 1 - 2 5 - 3 3 - 4 1.9210176984148622e-48 - 5 5 - 6 3.5355339059327378 - 7 3.5 - 8 3.482050807568877 - 9 3.467687001077147 -10 3.4644599990846436 -11 3.4641374518767565 -12 3.4641016151377544 -13 .infinity -14 .infinity -15 .infinity -16 .infinity -17 2 -18 8 -19 8 -20 0.6666 -21 2.6664 -22 2.6664 -23 1.9997999999999998 -24 92.6574 -25 2.2360679796198744 -26 2.23606797749979 -27 3.0000000031604355 -28 3 -29 .nan -30 6 -31 4 -32 4 -33 4 -34 2 -35 2.6009928340740736 -36 0 -37 0 -38 1.6766764161830636 -39 2.197224577336219 ---entropy-- -0.6931471805599453 -0.14384103622589045 -0.14384103622589045 -0.14384103622589045 -1.6739764335716716 -0.14384103622589045 ---first-- -4 -2 -1 -0 -a -.nas ---tail-- +--floor-- +1 +--ceil-- +2 +--round-- +13 +10 +123.46 +120 +120 +123.46 +123 +0 +1.2 +0 +0.012 +0.01 +0 +0.012345678 +0.6 +0.6 +0.3 +--exp-- +1.6487212707001282 +--log-- +-0.6931471805599453 +4 +--sin-- +0.479425538604203 +--asin-- +0.5235987755982989 +--cos-- +0.8775825618903728 +--acos-- +1.0471975511965979 +--tan-- +0.5463024898437905 +--atan-- +0.4636476090008061 +0.7853981633974483 +--sinh-- +0.5210953054937474 +--asinh-- +0.48121182505960347 +--cosh-- +1.1276259652063807 +--acosh-- +.nan +--tanh-- +0.46211715726000974 +--atanh-- +0.5493061443340549 +--erf-- +0.5204998778130465 +--tgamma-- +1.772453850905516 +--lgamma-- +0.5723649429247001 +--sqrt-- +0.7071067811865476 +--pow-- +0.25 +--abs-- +0.5 +--max-- +9 +8 +(null) +--min-- +-5 +4 +--dot_product-- +6 +6 +6 +--generalized_distance-- + 0 2.0874003024080013e+234 + 1 1 + 2 5 + 3 3 + 4 1.9210176984148622e-48 + 5 5 + 6 3.5355339059327378 + 7 3.5 + 8 3.482050807568877 + 9 3.467687001077147 +10 3.4644599990846436 +11 3.4641374518767565 +12 3.4641016151377544 +13 .infinity +14 .infinity +15 .infinity +16 .infinity +17 2 +18 8 +19 8 +20 0.6666 +21 2.6664 +22 2.6664 +23 1.9997999999999998 +24 92.6574 +25 2.2360679796198744 +26 2.23606797749979 +27 3.0000000031604355 +28 3 +29 .nan +30 6 +31 4 +32 4 +33 4 +34 2 +35 2.6009928340740736 +36 0 +37 0 +38 1.6766764161830636 +39 2.197224577336219 +--entropy-- +0.6931471805599453 +0.14384103622589045 +0.14384103622589045 +0.14384103622589045 +1.6739764335716716 +0.14384103622589045 +--first-- +4 +2 +1 +0 +a +.nas +--tail-- (list 9.2 "this") (list 2 3 4 5 6) (list 5 6) @@ -628,24 +628,24 @@ a f 6 ) (assoc) -2 -0 -bcdef -ef -cdef -abcdef - -abcdef - -.nas ---last-- -this -2 -1 -0 -c -.nas ---trunc-- +2 +0 +bcdef +ef +cdef +abcdef + +abcdef + +.nas +--last-- +this +2 +1 +0 +c +.nas +--trunc-- (list 4 9.2) (list 1 2 3 4 5) (list 1 2) @@ -677,17 +677,17 @@ c f 6 ) (assoc) -2 -0 -abcde -ab -abcd -abcdef - -abcdef - -.nas ---append-- +2 +0 +abcde +ab +abcd +abcdef + +abcdef + +.nas +--append-- (list 1 2 @@ -719,11 +719,11 @@ abcdef 2 "this" 3 "end" ) ---size-- -3 -4 -5 ---range-- +--size-- +3 +4 +5 +--range-- (list 0 1 @@ -755,7 +755,7 @@ abcdef (list 12 12 12 12 12 12) (list 1 2 3 4 5 6) (list 1 2 3 4 5 6) ---replace-- +--replace-- (list (assoc a 13) ) @@ -772,7 +772,7 @@ abcdef (list (assoc a 1 b 2) ) ---rewrite-- +--rewrite-- (list (assoc a 14) ) @@ -791,7 +791,7 @@ abcdef 8 ) (+ 17 a) ---map-- +--map-- (list 2 4 6 8) (list 10 @@ -818,7 +818,7 @@ abcdef 3 .nan a .nan ) ---filter-- +--filter-- (list 3 4) (list 10 1 20) (assoc 10 1) @@ -850,15 +850,15 @@ abcdef f 3 h 4 ) ---weave-- +--weave-- (list 1 2 3) - + (list 1 2 3 4 5 6) - + (list 2 (null) 4 (null) 6 (null)) - + (list "a" 2 @(get (target 0) 0) 4 @(get (target 0) 0) 6) - + (list 1 2 @@ -870,7 +870,7 @@ abcdef 8 9 ) - + (list 1 2 @@ -885,7 +885,7 @@ abcdef 11 12 ) - + (list 1 2 @@ -900,7 +900,7 @@ abcdef 11 12 ) - + (list 2 4 @@ -915,9 +915,9 @@ abcdef 22 24 ) - + (list 1 2 3 4 5 6) - + (list 1 2 @@ -929,18 +929,18 @@ abcdef 6 7 ) - + (list 3 4 5) ---reduce-- -24 -24 ---apply-- -10 -15 -10 ---reverse-- +--reduce-- +24 +24 +--apply-- +10 +15 +10 +--reverse-- (list 5 4 3 2 1) ---sort-- +--sort-- (list 1 3 4 5 9) (list 1 @@ -1011,8 +1011,8 @@ abcdef "2020-06-08 lunes 11.33.47" "2020-06-08 lunes 11.33.48" ) ---indices-- -(list "b" "a" "4" "c") +--indices-- +(list "b" "4" "a" "c") (list 0 1 @@ -1023,8 +1023,8 @@ abcdef 6 7 ) ---values-- -(list 2 1 "d" 3) +--values-- +(list 2 "d" 1 3) (list "a" 1 @@ -1045,7 +1045,7 @@ abcdef 4 "d" ) -(list 2 1 "d" 0 3) +(list 2 "d" 1 0 3) (list 1 2 @@ -1068,31 +1068,31 @@ abcdef 19 20 ) ---contains_index-- +--contains_index-- (true) - + (false) - + (true) - + (false) - ---contains_value-- + +--contains_value-- (true) - + (false) - + (true) - + (false) - + (true) (true) (true) (true) (false) (true) ---remove-- +--remove-- (assoc a 1 b 2 c 3) (list "a" @@ -1117,7 +1117,7 @@ abcdef (list 0 1 2 3 4) (list 1 2 3 4) (list) ---keep-- +--keep-- (assoc 4 "d") (list "c") (assoc 4 "d" a 1) @@ -1126,7 +1126,7 @@ abcdef (list 5) (list 0 5) (list 0 1 2 3 4 5) ---zip-- +--zip-- (assoc a 1 b 2 @@ -1178,21 +1178,21 @@ abcdef "b" ) ) ---unzip-- +--unzip-- (list 1 2) (list 1 3 2) ---get-- +--get-- (list 4 9.2 "this") -9.2 -3 -1 +9.2 +3 +1 (list 9.2 "this") - -2: 2 -(null): (null) -(null): (null) -3 ---set-- + +2: 2 +(null): (null) +(null): (null) +3 +--set-- (assoc 4 "d" a 1 @@ -1202,23 +1202,23 @@ abcdef ) (list 0 1 10 3 4) (assoc a 3 b 2) ---target-- +--target-- (list 1 2 3) ---current_index-- -3 -(null) -(null) -(null) ---current_value-- -(null) ---previous_result-- -current_index: 0 -(null) -current_index: 1 -0 -current_index: 2 -1 ---stack-- +--current_index-- +3 +(null) +(null) +(null) +--current_value-- +(null) +--previous_result-- +current_index: 0 +(null) +current_index: 1 +0 +current_index: 2 +1 +--stack-- (list (assoc abcdefghijklmnop 1 @@ -1240,7 +1240,7 @@ current_index: 2 8 ) accum_string "abcdef" - argv (list "C:\\Users\\ChristopherHazard\\Desktop\\Howso_repos\\amalgam\\src\\Amalgam\\./amlg_code/full_test.amlg") + argv (list "C:\\Users\\CalebWherry\\projects\\repos\\howso\\github\\amalgam\\src\\Amalgam\\amlg_code\\full_test.amlg") bar (declare (assoc x 6) (+ x 2) @@ -1253,16 +1253,16 @@ current_index: 2 A (assoc B 2) B 2 ) - interpreter "C:\\Users\\ChristopherHazard\\Desktop\\Howso_repos\\amalgam\\x64\\MT_Release_EXE\\Amalgam.exe" + interpreter "C:\\Users\\CalebWherry\\projects\\repos\\howso\\github\\amalgam\\out\\build\\amd64-windows-vs\\release\\amalgam-mt.exe" raaa 2 rwww 1 - start_time 1708396859.21913 + start_time 1706741674.726239 www 1 x 12 zz 10 ) ) ---args-- +--args-- (assoc abcdefghijklmnop 1 accum_assoc (assoc @@ -1283,7 +1283,7 @@ current_index: 2 8 ) accum_string "abcdef" - argv (list "C:\\Users\\ChristopherHazard\\Desktop\\Howso_repos\\amalgam\\src\\Amalgam\\./amlg_code/full_test.amlg") + argv (list "C:\\Users\\CalebWherry\\projects\\repos\\howso\\github\\amalgam\\src\\Amalgam\\amlg_code\\full_test.amlg") bar (declare (assoc x 6) (+ x 2) @@ -1296,10 +1296,10 @@ current_index: 2 A (assoc B 2) B 2 ) - interpreter "C:\\Users\\ChristopherHazard\\Desktop\\Howso_repos\\amalgam\\x64\\MT_Release_EXE\\Amalgam.exe" + interpreter "C:\\Users\\CalebWherry\\projects\\repos\\howso\\github\\amalgam\\out\\build\\amd64-windows-vs\\release\\amalgam-mt.exe" raaa 2 rwww 1 - start_time 1708396859.21913 + start_time 1706741674.726239 www 1 x 12 zz 10 @@ -1325,7 +1325,7 @@ current_index: 2 8 ) accum_string "abcdef" - argv (list "C:\\Users\\ChristopherHazard\\Desktop\\Howso_repos\\amalgam\\src\\Amalgam\\./amlg_code/full_test.amlg") + argv (list "C:\\Users\\CalebWherry\\projects\\repos\\howso\\github\\amalgam\\src\\Amalgam\\amlg_code\\full_test.amlg") bar (declare (assoc x 6) (+ x 2) @@ -1338,125 +1338,125 @@ current_index: 2 A (assoc B 2) B 2 ) - interpreter "C:\\Users\\ChristopherHazard\\Desktop\\Howso_repos\\amalgam\\x64\\MT_Release_EXE\\Amalgam.exe" + interpreter "C:\\Users\\CalebWherry\\projects\\repos\\howso\\github\\amalgam\\out\\build\\amd64-windows-vs\\release\\amalgam-mt.exe" raaa 2 rwww 1 - start_time 1708396859.21913 + start_time 1706741674.726239 www 1 x 12 zz 10 ) ---and-- -true +--and-- +true (false) - ---or-- -1 -1 + +--or-- +1 +1 (false) - ---xor-- + +--xor-- (true) - + (false) - ---not-- + +--not-- (false) - + (true) - ---=-- + +--=-- (false) - + (true) - + (true) - + (true) - + (true) - + (false) - ---!=-- + +--!=-- (false) - + (true) - + (false) - + (false) - + (false) - + (false) - + (true) - ---<-- + +--<-- (true) - + (false) - + (true) - + (false) - ---<=-- + +--<=-- (true) - + (true) - + (true) - + (false) - + (false) - + (false) - --->-- + +-->-- (true) - + (false) - + (true) - + (false) - --->=-- + +-->=-- (true) - + (true) - + (true) - + (false) - + (false) - + (false) - ---~-- + +--~-- (true) - + (false) - ---!~-- + +--!~-- (false) - + (true) - ---rand-- -0.5392467821223486 -0.9942253561203879 -24.52361533058883 -4 -2 + +--rand-- +0.5392467821223486 +0.9942253561203879 +24.52361533058883 +4 +2 (list) - + (list 8) - + (list 9 4 @@ -1469,82 +1469,82 @@ true 7 6 ) - + (list 25.7161630409425 2.06111894792399 11.116455397472219 15.888330007965623) - ---weighted_rand-- -b + +--weighted_rand-- +b (list "b" "b" "b" "b") - -b + +b (list "a" "b" @(get (target 0) 0) @(get (target 0) 1)) - + (list "a" @(get (target 0) 0) "b" @(get (target 0) 2)) - + infinity test c or d: (list "c" "c" "c" "d") - + infinity test c or d: (list "c" @(get (target 0) 0) "d" @(get (target 0) 0)) - + (assoc a 30 b 46 c 24) - + (assoc a 29 b 44 c 27) - -(list "7" "2" "1") - ---get_rand_seed-- -ȼ\KOaVT z ---set_rand_seed-- -0.25443726063281735 -0.1603572451200187 -0.25443726063281735 -0.1603572451200187 ---true-- + +(list "1" "2" "6") + +--get_rand_seed-- +��ȼ�\�KOaV�T z� +--set_rand_seed-- +0.25443726063281735 +0.1603572451200187 +0.25443726063281735 +0.1603572451200187 +--true-- (true) - ---false-- + +--false-- (false) - ---null-- + +--null-- (null) - + (null (+ 3 5) 7 ) ---node null-- +--node null-- #nulltest (null) ---infinity-- -.infinity --.infinity ---nan-- -.nan ---list-- +--infinity-- +.infinity +-.infinity +--nan-- +.nan +--list-- (list "a" 1 "b") ---associate-- +--associate-- (assoc 4 "d" a 1 b 2 c 3 ) ---assoc-- +--assoc-- (assoc b 2 c 3) ---get_type-- +--get_type-- (+) ---get_type_string-- -+ -string ---set_type-- +--get_type_string-- ++ +string +--set_type-- (- 3 4) (list "b" 3 "a" 4) (list "b" 3 "a" 4) (assoc a 4 b 3) -8.7 +8.7 (parallel #react (+ 3 4) ) ---format-- +--format-- (list 97 98 @@ -1562,79 +1562,79 @@ string -49 -95 ) -1: A -2: -100 -3: -100 -4: 100 -5: 365779719 -6: 123456789 -7: 14294967296 -8: 65 -9: 8.740783264876139e+294 -10: 6.409830999309918e-10 -11: 54 -12: 32 -13: 414141 -14: AAA -15: TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu -16: TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsuLg== -17: TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsuLi4= -18: Many hands make light work. -19: Many hands make light work.. -19: Many hands make light work... +1: A +2: -100 +3: -100 +4: 100 +5: 365779719 +6: 123456789 +7: 14294967296 +8: 65 +9: 8.740783264876139e+294 +10: 6.409830999309918e-10 +11: 54 +12: 32 +13: 414141 +14: AAA +15: TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu +16: TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsuLg== +17: TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsuLi4= +18: Many hands make light work. +19: Many hands make light work.. +19: Many hands make light work... 20: (list (assoc a 3 b 4) (assoc c "c") ) -21: [{"b":4,"a":3},{"d":null,"c":"c"}] -22: [{"a":3,"b":4},{"c":"c","d":null}] -23: b: 2 -a: 1 -e: - - a - - b - - .nan - - .inf -d: 4 -c: 3 - -24: a: 1 -b: 2 -c: 3 -d: 4 -e: - - a - - b - - .nan - - .inf - +21: [{"b":4,"a":3},{"d":null,"c":"c"}] +22: [{"a":3,"b":4},{"c":"c","d":null}] +23: b: 2 +a: 1 +e: + - a + - b + - .nan + - .inf +d: 4 +c: 3 + +24: a: 1 +b: 2 +c: 3 +d: 4 +e: + - a + - b + - .nan + - .inf + 25: (assoc a 1) -current date-time in epoch: 2024-02-19-21.40.59.2694320 -2020-06-07 00:22:59 -1391230800 -1391230800 -1391230800 --6053-05-28 00:24:29 -2020-06-05 00:21:45 -06/05/20 00:21:45 EDT -45 - 5 - s - s -FriJun06/05/20 00:21:4505 5 f -jueves, ene. 01, 1970 -Sunday, Jun 07, 2020 -domingo, jun. 07, 2020 -1591502400 -Jun 07, 2020 -domingo, jun. 07, 2020 -664428 --314954772 -1960-01-08 11.33.48 -1960-01-08 11.33.48.0100000 ---get_labels-- +current date-time in epoch: 2024-01-31-17.54.34.8031830 +2020-06-07 00:22:59 +1391230800 +1391230800 +1391230800 +-6053-05-28 00:24:29 +2020-06-05 00:21:45 +06/05/20 00:21:45 EDT +45 + 5 + s + s +FriJun06/05/20 00:21:4505 5 f +jueves, ene. 01, 1970 +Sunday, Jun 07, 2020 +domingo, jun. 07, 2020 +1591502400 +Jun 07, 2020 +domingo, jun. 07, 2020 +664428 +-314954772 +1960-01-08 11.33.48 +1960-01-08 11.33.48.0100000 +--get_labels-- (list "labelB") ---get_all_labels-- +--get_all_labels-- (assoc label-number-22 #label-number-22 3 label21 #label21 @@ -1692,38 +1692,38 @@ domingo, jun. 07, 2020 "labelA" ) ) ---set_labels-- +--set_labels-- #labelD #labelE (true) ---zip_labels-- +--zip_labels-- (list #l1 1 #l2 2 #l3 3 ) ---get_comments-- -comment too ---set_comments-- +--get_comments-- +comment too +--set_comments-- ;new comment (true) ---get_concurrency-- +--get_concurrency-- (false) - + (true) - + (true) - ---set_concurrency-- + +--set_concurrency-- ||(print "hello") - + ;complex test #somelabel ||(assoc a "hello" b 4) - ---get_value-- + +--get_value-- (true) ---set_value-- -3 ---explode-- +--set_value-- +3 +--explode-- (list "a" "b" @@ -1744,28 +1744,28 @@ comment too "e" "f" "g" - "" - "" - "" - "" - "" - "" - "" - "" + "�" + "�" + "�" + "�" + "�" + "�" + "�" + "�" ) (list "ab" "cd" "ef" - "g" - "" - "" - "" - "" -) -(list "abc" "def" "g" "" "ϡ") -(list "abcd" "efg" "" "ϡ") ---split-- + "g�" + "��" + "�" + "��" + "�" +) +(list "abc" "def" "g�" "��" "�ϡ") +(list "abcd" "efg�" "���" "�ϡ") +--split-- (list "hello world") (list "hello" "world") (list "hello" "world" "!") @@ -1776,64 +1776,64 @@ comment too (list "abc" "de" "fgﬗꭖϡ") (list "abc" "de fgﬗꭖϡ") (list "abc de fgﬗꭖϡ") ---substr-- -hello world -ello world -ello wo -ello world -ello worl -orl -orl -hxlo world -e -he +--substr-- +hello world +ello world +ello wo +ello world +ello worl +orl +orl +hxlo world +e +he (list "he") - + (list "he" "wo") - + (list "he" "wo") - + (list (list "he" "e") ) - + (list (list "he" "e") (list "wo" "o") ) - + (list (list "he" "he" "h" "e") (list "wo" "wo" "w" "o") ) - + (list (list "he" "h") (list "wo" "w") ) - + (list) - -h[e]ll[o] w[o]rld -h[e]ll[o] world -abcdefgﬗꭖϡ -bcdefgﬗꭖϡ -bcdefgﬗ -bcdefgﬗꭖϡ -bcdefgﬗꭖ -gﬗꭖ - -axdefgﬗꭖϡ ---concat-- -hello world ---crypto_sign and crypto_sign_verify-- + +h[e]ll[o] w[o]rld +h[e]ll[o] world +abcdefgﬗꭖϡ +bcdefgﬗꭖϡ +bcdefgﬗ� +bcdefgﬗꭖϡ +bcdefgﬗꭖ +gﬗꭖ +��� +axdefgﬗꭖϡ +--concat-- +hello world +--crypto_sign and crypto_sign_verify-- valid signature: (true) ---encrypt and decrypt-- -symmetric key encryption -decrypted: hello -public key encryption -decrypted: hello ---print-- +--encrypt and decrypt-- +symmetric key encryption +decrypted: hello +public key encryption +decrypted: hello +--print-- (list 0 1 @@ -1874,15 +1874,15 @@ decrypted: hello -1.23456789e-05 -1.2345e-149 ) -.nan -.infinity +.nan +.infinity (true) - + (false) - ---total_size-- -10 ---mutate-- + +--total_size-- +10 +--mutate-- (list 1 -2.781487486378118 @@ -1916,31 +1916,31 @@ decrypted: hello (list 10 11 12) ) ) ---commonality-- -3 -15 -0.25 -0.25 -1 -0.25 -1 -5 -0.48512352272000003 -2 -2 -4 -4 -3.125 ---edit_distance-- -3 -2 -0 -0 -1.02975295456 -3 -3 -1 ---intersect-- +--commonality-- +3 +15 +0.25 +0.25 +1 +0.25 +1 +5 +0.48512352272000003 +2 +2 +4 +4 +3.125 +--edit_distance-- +3 +2 +0 +0 +1.02975295456 +3 +3 +1 +--intersect-- (list 1 (- 4 2) @@ -1969,14 +1969,14 @@ decrypted: hello ) (replace 4 2 6 1 7) (list - + ;comment 2 ;comment 3 1 ) (list 1 2 3) - ---union-- + +--union-- (seq 2 (get_entity_comments) 1 4 (get_entity_comments)) (list 1 @@ -2006,13 +2006,13 @@ decrypted: hello (list 3 4 2) (list 3 2 4 3) (list - + ;comment 1 ;comment 2 ;comment 3 ;comment 4 1 - + ;comment x 2 4 @@ -2031,16 +2031,16 @@ decrypted: hello (list (list 1 2 3) ) - + (list (list 1 2 3) ) - + (parallel (list 1 2 3) ) - ---difference-- + +--difference-- (declare (assoc _ (null)) (replace @@ -2341,7 +2341,7 @@ decrypted: hello 4 ) ) ---mix-- +--mix-- (list 2 3.5 @@ -2352,7 +2352,7 @@ decrypted: hello 13.5 ) (list - + ;comment 1 ;comment 2 ;comment 3 @@ -2405,14 +2405,14 @@ decrypted: hello ) (list 3.5 5.5 7.5 9.5 11.5 13.5) (list 5 8 10 12 11 13) -4 -4 -2.5 -2.5 -abcmxyz -abcmxyz -abcdmxyz ---mix_labels-- +4 +4 +2.5 +2.5 +abcmxyz +abcmxyz +abcdmxyz +--mix_labels-- (list 1 #mixtest1 2 @@ -2430,17 +2430,17 @@ abcdmxyz ) (list 5 6) ) ---total_entity_size-- -37 -45 ---flatten_entity-- -0.4476445420518951 -iA;@VOV- -0.9810549023242581 -0.9810549023242581 -0.5142400294051881 -0.5142400294051881 -flatten restore with seeds test +--total_entity_size-- +37 +45 +--flatten_entity-- +0.4476445420518951 +i��A�;@V��OV-� +0.9810549023242581 +0.9810549023242581 +0.5142400294051881 +0.5142400294051881 +flatten restore with seeds test (let (assoc new_entity (first @@ -2453,7 +2453,7 @@ flatten restore with seeds test ) ) ) - (set_entity_rand_seed new_entity "£=mVOV-") + (set_entity_rand_seed new_entity "��£=�mV��OV-�") (set_entity_rand_seed (first (create_entities @@ -2465,7 +2465,7 @@ flatten restore with seeds test ) ) ) - "aE&K\"(X&\0" + "�aE&K\"���(X&�\0�" ) new_entity ) @@ -2481,7 +2481,7 @@ flatten restore with seeds test ) ) ) - (set_entity_rand_seed new_entity "M:pVVOV-") + (set_entity_rand_seed new_entity "�M:��p�VV��OV-�") (set_entity_rand_seed (first (create_entities @@ -2493,7 +2493,7 @@ flatten restore with seeds test ) ) ) - "aE&K\"(X&\0" + "�aE&K\"���(X&�\0�" ) new_entity ) @@ -2501,7 +2501,7 @@ flatten restore with seeds test (assoc _ (null)) (clone_entities _) ) -flatten restore without seeds test +flatten restore without seeds test (let (assoc new_entity (first @@ -2536,7 +2536,7 @@ flatten restore without seeds test ) ) ) - (set_entity_rand_seed new_entity "R} ]ْͫ") + (set_entity_rand_seed new_entity "����R}� �]�ْͫ�") (set_entity_rand_seed (first (create_entities @@ -2548,7 +2548,7 @@ flatten restore without seeds test ) ) ) - "Qv&rS ˙" + "Q��v��&r�S��� ˙�" ) new_entity ) @@ -2556,7 +2556,7 @@ flatten restore without seeds test (assoc _ (null)) (clone_entities _) ) -flatten restore with parallel +flatten restore with parallel (let (assoc new_entity (first @@ -2569,7 +2569,7 @@ flatten restore with parallel ) ) ) - (set_entity_rand_seed new_entity "£=mVOV-") + (set_entity_rand_seed new_entity "��£=�mV��OV-�") ||(parallel (set_entity_rand_seed (first @@ -2582,7 +2582,7 @@ flatten restore with parallel ) ) ) - "aE&K\"(X&\0" + "�aE&K\"���(X&�\0�" ) ) ||(parallel) @@ -2600,7 +2600,7 @@ flatten restore with parallel ) ) ) - (set_entity_rand_seed new_entity "M:pVVOV-") + (set_entity_rand_seed new_entity "�M:��p�VV��OV-�") (set_entity_rand_seed (first (create_entities @@ -2612,7 +2612,7 @@ flatten restore with parallel ) ) ) - "aE&K\"(X&\0" + "�aE&K\"���(X&�\0�" ) new_entity ) @@ -2620,7 +2620,7 @@ flatten restore with parallel (assoc _ (null)) (clone_entities _) ) ---mutate_entity-- +--mutate_entity-- (list 1 2 @@ -2638,7 +2638,7 @@ flatten restore with parallel -6.182472379158481 (associate (call) 1 (retrieve_from_entity) "a") ) - + (list (trunc) (list) @@ -2656,7 +2656,7 @@ flatten restore with parallel (>) 2 ) - + (list (-) 2 @@ -2674,26 +2674,26 @@ flatten restore with parallel (+) (associate (+) 1 "b" (+)) ) - ---commonality_entities-- -23.367956500877984 ---edit_distance_entities-- -35.26408699824403 ---intersect_entities-- + +--commonality_entities-- +23.367956500877984 +--edit_distance_entities-- +35.26408699824403 +--intersect_entities-- (associate "b" 4) -MergeEntityChild1 +MergeEntityChild1 (associate "x" 3 "y" 4) -MergeEntityChild2 +MergeEntityChild2 (associate "p" 3 "q" 4) -_2280722175 -(associate "E" 3 "F" 4) -_2169689611 +_2169689611 (associate "e" 3 "f" 4) ---union_entities-- +_2280722175 +(associate "E" 3 "F" 4) +--union_entities-- (associate "b" 4 "a" 3 "c" 3) -MergeEntityChild1 +MergeEntityChild1 (associate "x" 3 "y" 4 "z" 5) -MergeEntityChild2 +MergeEntityChild2 (associate "p" 3 @@ -2706,18 +2706,7 @@ MergeEntityChild2 "w" 7 ) -_2280722175 -(associate - "E" - 3 - "F" - 4 - "G" - 5 - "H" - 6 -) -_2169689611 +_2169689611 (associate "e" 3 @@ -2728,11 +2717,7 @@ _2169689611 "h" 6 ) -(parallel - ##p - (list "_3990396532" "_3330773578" "_3990396532" "_3330773578") -) -_3990396532 +_2280722175 (associate "E" 3 @@ -2743,7 +2728,11 @@ _3990396532 "H" 6 ) -_3330773578 +(parallel + ##p + (list "_3990396532" "_3330773578" "_3990396532" "_3330773578") +) +_3330773578 (associate "e" 3 @@ -2754,7 +2743,18 @@ _3330773578 "h" 6 ) ---difference_entities-- +_3990396532 +(associate + "E" + 3 + "F" + 4 + "G" + 5 + "H" + 6 +) +--difference_entities-- (declare (assoc _ (null)) (clone_entities _) @@ -2986,7 +2986,7 @@ _3330773578 new_entity ) ) -_432807187 +_432807187 (list "DiffEntityChild1" "OnlyIn2" "_350925375" "_2742810479") (declare (assoc _ (null)) @@ -3201,7 +3201,7 @@ _432807187 new_entity ) ) -_41032496 +_41032496 (associate "c" 3 "b" 4) (associate "x" 3 "y" 4 "z" 5) (list "DiffEntityChild1" "OnlyIn2" "_350925375" "_2742810479") @@ -3365,34 +3365,34 @@ _41032496 new_entity ) ) -_3128546630 +_3128546630 (associate "c" 3 "b" 4) (associate "x" 3 "y" 4 "z" 6) (list "OnlyIn2" "_3631850880" "_1938178219" "DiffEntityChild1") ---mix_entities-- +--mix_entities-- (associate "b" 4 "a" 3 "c" 3) -MergeEntityChild1 +MergeEntityChild1 (associate "x" 3 "y" 4 "z" 5) -MergeEntityChild2 +MergeEntityChild2 (associate "p" 3 "q" 4 "u" 5) -_2280722175 -(associate "E" 3 "F" 4) -_2169689611 +_2169689611 +(associate "e" 3 "f" 4) +_2280722175 (associate - "e" + "E" 3 - "f" + "F" 4 - "g" + "G" 5 - "h" + "H" 6 ) ---get_entity_comments-- +--get_entity_comments-- Full test This is a suite of unit tests. - This is the second line of the unit test description. -this is a fully described entity + This is the second line of the unit test description. +this is a fully described entity (assoc foo "the function foo" get_api "returns the api details" publicvar "some public variable") (assoc x "the value of x\r\nthe default value of x" y "the value of y") (assoc @@ -3406,7 +3406,7 @@ this is a fully described entity publicvar (assoc description "some public variable" parameters (null)) ) ) ---retrieve_entity_root-- +--retrieve_entity_root-- (list 1 2 @@ -3417,9 +3417,9 @@ this is a fully described entity 2 #three 3 ) ---assign_entity_roots-- +--assign_entity_roots-- (list 4 5 6) ---accum_entity_roots-- +--accum_entity_roots-- (null #a 1 #b 2 @@ -3428,43 +3428,43 @@ this is a fully described entity (null #c 3 ) ---get_entity_rand_seed-- -0.8630628998576303 -TFJKxs{ ---set_entity_rand_seed-- -0.24310795234706906 -0.24310795234706906 -deep sets -0.4287046636426344 -0.4287046636426344 ---get_entity_root_permission-- +--get_entity_rand_seed-- +0.8630628998576303 +T�FJ�Kx�s��{� +--set_entity_rand_seed-- +0.24310795234706906 +0.24310795234706906 +deep sets +0.4287046636426344 +0.4287046636426344 +--get_entity_root_permission-- (false) - ---set_entity_root_permission-- -RootTest -1708396859.443937 + +--set_entity_root_permission-- +RootTest +1706741674.951646 (true) - -RootTest -(null) + +RootTest +(null) (false) - ---create_entities-- + +--create_entities-- (list "MyLibrary") - ---nested create_entities-- + +--nested create_entities-- (list "Child1" "Child2") (list "MultipleTest1") - + (list "MultipleTest2") - ---clone_entities-- + +--clone_entities-- (list "MyNewLibrary") - ---move_entities-- + +--move_entities-- (list "MyLibrary2") - ---destroy_entities-- + +--destroy_entities-- (list "MergeEntity1" "MergeEntity2" @@ -3575,7 +3575,7 @@ RootTest "MyNewLibrary" "EntityWithChildren" ) ---load-- +--load-- (assoc a #a 1 b #b (true) @@ -3584,12 +3584,12 @@ RootTest hello #hello (print "hello\n") ) -load from .json: +load from .json: (list (assoc a 3 b 4) (assoc c "c" d (null)) ) -load from .yaml: +load from .yaml: (list (assoc a 123 @@ -3598,9 +3598,9 @@ load from .yaml: d "true" ) ) ---load_entity-- -load from .amlg: -hello +--load_entity-- +load from .amlg: +hello (let (assoc new_entity (first @@ -3618,7 +3618,7 @@ hello ) ) ) - (set_entity_rand_seed new_entity "ŔK@\\F*") + (set_entity_rand_seed new_entity "ŔK@����\\��F�*�") (set_entity_rand_seed (first (create_entities @@ -3632,7 +3632,7 @@ hello ) ) ) - "B!\\,T*&" + "�B�!\\��,�T*�&�" ) (set_entity_rand_seed (first @@ -3647,11 +3647,11 @@ hello ) ) ) - "!|.Vq" + "�!���|��.�V��q�" ) new_entity ) ---load_persistent_entity-- +--load_persistent_entity-- (let (assoc new_entity (first @@ -3666,7 +3666,7 @@ hello ) ) ) - (set_entity_rand_seed new_entity ")|{0є-I") + (set_entity_rand_seed new_entity "@�,3��!�GM�0h��") (set_entity_rand_seed (first (create_entities @@ -3676,7 +3676,7 @@ hello ) ) ) - "Ϥ\nVyz" + "M������k��,ي��" ) (set_entity_rand_seed (first @@ -3691,7 +3691,7 @@ hello ) ) ) - "do3@^°\nt" + "�x<�^����.��V0��" ) new_entity ) @@ -3709,7 +3709,7 @@ hello ) ) ) - (set_entity_rand_seed new_entity ")|{0є-I") + (set_entity_rand_seed new_entity "@�,3��!�GM�0h��") (set_entity_rand_seed (first (create_entities @@ -3723,54 +3723,52 @@ hello ) ) ) - "do3@^°\nt" + "�x<�^����.��V0��" ) new_entity ) -Load Root: -PersistTreeRoot -Load Inter: +Load Root: +PersistTreeRoot +Load Inter: (list "PersistTreeRoot" "PersistTreeInter") - -Load Leaf: + +Load Leaf: (list "PersistTreeRoot" "PersistTreeInter" "PersistTreeLeaf") - -Root contained: + +Root contained: (list "PersistTreeInter") - -Root b: -2 -Inter contained: + +Root b: +2 +Inter contained: (list "PersistTreeLeaf") - -Leaf f: -2 -Leaf f: -6 ---store-- + +Leaf f: +2 +Leaf f: +6 +--store-- (list 1 2 3 4) (parallel #".#blah" 1 ) -retrieved: 1 - -loaded from file: +retrieved: 1 + +loaded from file: (parallel #".#blah" 1 ) -retrieved: 1 ---store other file formats--- -[This is text!] -(list "String 1." "String 2." "String 3.") - +retrieved: 1 +--store other file formats--- +[This is text!] (seq (print "hello") ) - + contained entities in quackers before file: (list "!@#$%^&*)(_+=-'][{}.marbles" "buklulu is good.amlg") - + contained entity in quackers2 loaded back from file: (list "buklulu is good.amlg" "!@#$%^&*)(_+=-'][{}.marbles") - + (list (list 6.4 2.8 5.6 2.2 "virginica") (list 4.9 2.5 4.5 1.7 "virg\"inica") @@ -3779,27 +3777,27 @@ contained entity in quackers2 loaded back from file: (list "buklulu is good.amlg (list 4.9 3.1 1.5 0.1 "set\nosa" 3) (list 4.4 3.2 1.3 0.2 "setosa") ) ---store_entity-- -store to .amlg: +--store_entity-- +store to .amlg: 2 2 -Compression difference: [(null)] -store to .json in amlg format +Compression difference: [(null)] +store to .json in amlg format (list (assoc a 3 b 4) (assoc c "c" d (null)) ) -store to .json normally +store to .json normally (list (assoc a 3 b 4) (assoc c "c" d (null)) ) ---contains_entity-- +--contains_entity-- (true) - + (false) - ---contained_entities-- + +--contained_entities-- (list "Child1" "Child2" @@ -3809,7 +3807,7 @@ store to .json normally "Child6" "Child7" ) ---query_select-- +--query_select-- (list "Child1" "Child2" "Child3") (list "Child2" "Child3" "Child4") (list "Child3" "Child4" "Child5" "Child6" "Child7") @@ -3819,12 +3817,12 @@ store to .json normally (list "Child1" "Child3" "Child5" "Child6") (list "Child1" "Child5" "Child6" "Child7") (list "Child4" "Child6") ---query_sample-- +--query_sample-- (list "Child4") (list "Child2" "Child3") (list "Child1") (list "Child1") ---query_weighted_sample-- +--query_weighted_sample-- (list "Child1") (list "Child2") (list @@ -3884,48 +3882,48 @@ store to .json normally "Child2" ) (list "Child2") ---query_in_entity_list-- +--query_in_entity_list-- (list "Child6" "Child7") ---query_not_in_entity_list-- +--query_not_in_entity_list-- (list "Child1" "Child2" "Child3" "Child4" "Child5") ---query_count-- -7 -6 ---query_exists-- +--query_count-- +7 +6 +--query_exists-- (list "Child5") (list) (list "Child5") ---query_not_exists-- +--query_not_exists-- (list "Child1" "Child2" "Child3" "Child4" "Child6" "Child7") (list "Child5") ---query_equals-- +--query_equals-- (list "Child5") (list "Child5") ---query_not_equals-- +--query_not_equals-- (list "Child1" "Child2" "Child6" "Child7") (list "Child1" "Child2" "Child6" "Child7") (list "Child5") (list "Child1" "Child2" "Child6" "Child7") ---query_between-- +--query_between-- (list "Child1" "Child6" "Child7") (list "Child1" "Child6" "Child7") (list "Child2") ---query_not_between-- +--query_not_between-- (list "Child2" "Child3" "Child4") (list "Child5") (list "Child6") cascading global query: (list "Child3" "Child4" "Child7") ---query_among-- +--query_among-- among x = 0, 100: (list "Child3" "Child4" "Child7") among x = 0, 100: (list "Child3" "Child4" "Child7") among bar = not crunchy: (list "Child6") among bar = not crunchy: (list "Child6") ---query_not_among-- +--query_not_among-- not_among x = 0, 100: (list "Child1" "Child2" "Child6") not_among x = 0, 100: (list "Child1" "Child2" "Child6") not_among bar = not crunchy: (list "Child5") not_among bar = not crunchy: (list) ---query_nearest_generalized_distance-- +--query_nearest_generalized_distance-- cascading query_not_equals: (list "Child1" "Child6") cascading query_not_in_entity_list: (list "Child6" "Child7") unweighted query: (assoc @@ -3979,51 +3977,51 @@ weighted query list of lists with multiple values: (list 1.9999999999999991 ) ) -test code and string distances +test code and string distances 1: (list "Child1" "Child4") 2: (list "Child1" "Child2" "Child4" "Child5") 3: (list "Child1" "Child2" "Child4" "Child5") 4: (list "Child1" "Child2" "Child4" "Child5") 5: (list "Child1" "Child2" "Child6") ---query_max-- +--query_max-- (list "Child1" "Child3" "Child4") (list "Child1" "Child3" "Child4") ---query_min-- +--query_min-- (list "Child2" "Child7") (list "Child2" "Child7") ---query_sum-- -203 -4.92 ---query_mode-- -100 -3 ---query_quantile-- -2 -2 -1.0851063829787235 -0.24999999999999994 -0.24999999999999994 -75.74999999999999 ---query_generalized_mean-- -33.833333333333336 -0.048681937895234305 -0.027510917030567687 -57.750901868859735 -5.020408163265306 -0.32960535729865875 -44.11111111111111 -2190.472222222222 -41.65478060964195 -7197131.469907404 ---query_min_difference-- -1 -0.43 -0 -0.02 ---query_max_difference-- -97 -199 ---query_value_masses-- +--query_sum-- +203 +4.92 +--query_mode-- +100 +3 +--query_quantile-- +2 +2 +1.0851063829787235 +0.24999999999999994 +0.24999999999999994 +75.74999999999999 +--query_generalized_mean-- +33.833333333333336 +0.048681937895234305 +0.027510917030567687 +57.750901868859735 +5.020408163265306 +0.32960535729865875 +44.11111111111111 +2190.472222222222 +41.65478060964195 +7197131.469907404 +--query_min_difference-- +1 +0.43 +0 +0.02 +--query_max_difference-- +97 +199 +--query_value_masses-- (assoc -1 1 0 1 @@ -4031,7 +4029,7 @@ test code and string distances 3 1 100 2 ) - + (assoc -1 0.45 0 0.02 @@ -4039,19 +4037,19 @@ test code and string distances 3 0.45 100 0.04 ) - + (assoc crunchy 1 "not crunchy" 1) - ---query_less_or_equal_to-- + +--query_less_or_equal_to-- (list "Child1" "Child2" "Child6" "Child7") (list "Child1" "Child2" "Child6" "Child7") ---query_greater_or_equal_to-- +--query_greater_or_equal_to-- (list "Child3" "Child4") (list "Child3" "Child4") ---query_within_generalized_distance-- +--query_within_generalized_distance-- (list "Child1" "Child2" "Child4" "Child6" "Child7") (list "Child1" "Child2" "Child4" "Child6" "Child7") ---query_nearest_generalized_distance-- +--query_nearest_generalized_distance-- (list "Child2" "Child4") (list "Child2" "Child4") (list "Child1" "Child2" "Child4" "Child6" "Child7") @@ -4061,10 +4059,10 @@ test code and string distances (list "Child2" "Child4" "Child7") assoc-based: (list "Child2" "Child4" "Child7") (list "Child2" "Child4" "Child7") ---contained_entities caching and permissions-- +--contained_entities caching and permissions-- (false) - -(null) + +(null) (parallel ##^a 3 ##b (contained_entities) @@ -4080,11 +4078,11 @@ assoc-based: (list "Child2" "Child4" "Child7") ##x 4 ##y 5 ) - -1 -0 -0 -1 + +1 +0 +0 +1 (list (parallel ##x 0 @@ -4127,7 +4125,7 @@ assoc-based: (list "Child2" "Child4" "Child7") ##y 1 ) ) ---compute_on_contained_entities-- +--compute_on_contained_entities-- (assoc Child5 (assoc q (+ @@ -4151,8 +4149,8 @@ assoc-based: (list "Child2" "Child4" "Child7") Child7 10 ) (assoc Child2 2 Child4 -200) ---compute_entity_convictions-- -case convictions: +--compute_entity_convictions-- +case convictions: (assoc entity1 1.8849070781661639 entity2 0.6863118922121982 @@ -4160,7 +4158,7 @@ case convictions: entity4 1.9468118839925106 entity5 0.7797040417153973 ) -case convictions: +case convictions: (assoc entity1 0.655877894152981 entity2 4.719518200776451 @@ -4168,7 +4166,7 @@ case convictions: entity4 0.6588967213280371 entity5 0.7011374455603876 ) -case convictions unweighted: +case convictions unweighted: (assoc entity1 2.2695667753739017 entity2 0.6731896181878543 @@ -4176,7 +4174,7 @@ case convictions unweighted: entity4 38.384973496395396 entity5 0.45815851485891435 ) -case convictions weighted by object (with erroneously long nominal): +case convictions weighted by object (with erroneously long nominal): (assoc TestContainerExec 0.28356810230095286 vert0 1.3005955468751227 @@ -4186,26 +4184,26 @@ case convictions weighted by object (with erroneously long nominal): vert4 73.971185205438 vert5 3.8897264529001325 ) -case convictions x exists before: +case convictions x exists before: (assoc entity3 1.0000000933277426 entity4 0.9999998458521889 entity5 1.0000000608201045) -case convictions x exists after: +case convictions x exists after: (assoc entity3 (assoc x 16) entity4 (assoc x 8) entity5 (assoc x 32) ) -case convictions object = 1: +case convictions object = 1: (assoc vert0 0.9999999999999484 vert1 0.9999999999999976 vert2 1.0000000000000566 vert3 0.9999999999999976 ) -case convictions on a subset: +case convictions on a subset: (assoc vert0 0.5 vert3 0) ---compute_entity_group_kl_divergence-- -0.01228960638554566 ---compute_entity_distance_contributions-- +--compute_entity_group_kl_divergence-- +0.01228960638554566 +--compute_entity_distance_contributions-- (assoc TestContainerExec 4.721359549995793 vert0 0.8284271247461902 @@ -4215,7 +4213,7 @@ case convictions on a subset: vert4 0.7071067811865476 vert5 1.17157287525381 ) -(these values should match the values of the subset of these keys in the previous assoc): +(these values should match the values of the subset of these keys in the previous assoc): (assoc vert0 0.8284271247461902 vert1 0.8284271247461902 vert2 0.8284271247461902) (assoc vert0 0.8284271247461902 @@ -4225,9 +4223,9 @@ case convictions on a subset: vert4 0.7071067811865476 vert5 1.17157287525381 ) -(these values should match the values of the subset of these keys in the previous assoc): +(these values should match the values of the subset of these keys in the previous assoc): (assoc vert4 0.7071067811865476 vert5 1.17157287525381) ---compute_entity_kl_divergences-- +--compute_entity_kl_divergences-- (assoc vert0 0.00018681393615961172 vert1 0.0003526679446349979 @@ -4237,7 +4235,7 @@ case convictions on a subset: vert5 0.010670757326457676 ) (these values should match the values of the subset of these keys in the previous assoc):(assoc vert0 0.00018681393615961172 vert3 0) -additional conviction calculations: +additional conviction calculations: case conviction:(assoc vert0 0.8000570855094574 vert1 0.7468655552274358 @@ -4251,32 +4249,32 @@ case conviction:(assoc vert5 0.6604923501807921 ) cyclic feature nearest neighbors: (assoc cyclic1 1 cyclic5 0.5) -cyclic test expected: 155, 200, 190 ... deg values of 0 8 and 12: -190: 0.045454545454545456 (null - ##deg 12 +cyclic test expected: 155, 200, 190 ... deg values of 0 8 and 12: +155: 0.1 (null + ##deg 0 ) 200: 0.05555555555555555 (null ##deg 8 ) -155: 0.1 (null - ##deg 0 +190: 0.045454545454545456 (null + ##deg 12 ) ---contains_label-- +--contains_label-- (true) - + (false) - + (true) - + (false) - ---assign_to_entities-- + +--assign_to_entities-- #a2e (null) " or " 3 (true) 5 -(parallel #asgn_test 12) +(parallel #asgn_test 12) (true) 4 (parallel @@ -4288,25 +4286,25 @@ cyclic test expected: 155, 200, 190 ... deg values of 0 8 and 12: ##three 12 4 ) ---direct_assign_to_entities-- +--direct_assign_to_entities-- #a 12 (true) #a 7 ---accum_to_entities-- -7 +--accum_to_entities-- +7 #i2e2 (list 1 2 3 4) - ---retrieve_from_entity-- + +--retrieve_from_entity-- " and " 12 12 (list 12 13) (assoc a 12 b 13) ---direct_retrieve_from_entity-- +--direct_retrieve_from_entity-- 7 #a 7 ---call_entity-- +--call_entity-- (list "Child1" "Child2" @@ -4342,7 +4340,7 @@ cyclic test expected: 155, 200, 190 ... deg values of 0 8 and 12: "Child7" ) 6 ---call_entity_get_changes-- +--call_entity_get_changes-- 4 6 (list @@ -4371,16 +4369,16 @@ cyclic test expected: 155, 200, 190 ... deg values of 0 8 and 12: ) ) ) ---call_container-- -8 -8 -(null) ---circular, repeated, and preevaluated references-- +--call_container-- +8 +8 +(null) +--circular, repeated, and preevaluated references-- (assoc a 1 b 2) (associate "a" 1 "b" 2) -(null) -1 -a +(null) +1 +a (list (assoc a 1) @(get @@ -4397,18 +4395,18 @@ a ) 1 ) ---nan equality tests-- +--nan equality tests-- (= (null) .nan): (false) - + (= (+ (null)) .nan): (true) - + (list "Entity3") (list "EntityNaN") (list "EntityNull") (list "Entity3" "EntityNull" "EntityNaN") ---combo tests-- -4.5 -5 +--combo tests-- +4.5 +5 (null #A 10 #duped @@ -4418,22 +4416,22 @@ a 1 ) ) - + (list "hello" "!") (assoc a1 1.4142135623730951 a2 2 a3 1.4142135623730951) (assoc a1 1.4142135623730951 a3 1.4142135623730951) (assoc a3 1.4142135623730951) (assoc a1 5.0990195135927845 a2 2 a3 5.0990195135927845) (assoc a1 1 a3 1 a4 0) ---accuracy tests-- -256.5114465493462 -expected: 256.5114466 -8.037178667714414 -expected: 8.037178684 -3.621729247632793e-35 -expected: 0.14362593 +--accuracy tests-- +256.5114465493462 +expected: 256.5114466 +8.037178667714414 +expected: 8.037178684 +3.621729247632793e-35 +expected: 0.14362593 (assoc point1 256.5114465493462 point2 273.1247383899543 point3 256.5114465493462) -distance symmetry tests +distance symmetry tests (list (list "B" @@ -4478,7 +4476,7 @@ distance symmetry tests 1024 ) ) -distance contributions +distance contributions dc: (list (list "vert0" "vert1" "vert2" "vert3") (list 1 1 1 1.4142135623730951) @@ -4489,7 +4487,7 @@ weighted dc: (assoc vert2 1 vert3 1.4142135623730951 ) -removal conviction +removal conviction kl: (assoc vert0 0.012498962161828123 vert1 0.0014999155151563248 @@ -4520,9 +4518,9 @@ weighted convictions: (assoc vert2 0.8564735401170989 vert3 59.98601454701778 ) -group kl divergence: 0.0014999155151563318 -weighted group kl divergence: 0.012150145528158986 -addition conviction +group kl divergence: 0.0014999155151563318 +weighted group kl divergence: 0.012150145528158986 +addition conviction kl: (assoc vert0 0.0118919309314467 vert1 0.0015341620278852101 @@ -4553,9 +4551,9 @@ weighted convictions: (assoc vert2 0.8457062465879276 vert3 60.753888021808535 ) -group kl divergence: 0.0015341620278852813 -weighted group kl divergence: 0.013070224898692494 -adding a case +group kl divergence: 0.0015341620278852813 +weighted group kl divergence: 0.013070224898692494 +adding a case noncyclic KL: (assoc vert0 0.01467982549299679 vert1 0.0027281364373075885 @@ -4563,7 +4561,7 @@ noncyclic KL: (assoc vert3 0.016383251387214498 vert4 0.0051662807478393205 ) -noncyclic group kl divergence: 0.005166280747839411 +noncyclic group kl divergence: 0.005166280747839411 cyclic KL: (assoc vert0 0.06449882851689671 vert1 0.0020695242435298626 @@ -4578,84 +4576,85 @@ cyclic conviction: (assoc vert3 0.9032229616532002 vert4 0.5571220443569613 ) -cyclic group kl divergence: 0.05872535496117583 -surprisal transforms +cyclic group kl divergence: 0.05872535496117583 +surprisal transforms probabilities: (list (list "vert0" "vert1" "vert2" "vert3") (list 2.7535180455541748e-05 2.7535180455541748e-05 5.043471233780792e-07 9.237449443012879e-09) ) - + weighted probabilities: (list (list "vert0" "vert2" "vert3" "vert1") (list 5.506960272483319e-05 5.043471233780792e-07 9.237449443012879e-09 0) ) - + surprisal contribution: (assoc testvert 9.797630298091489) weighted surprisal contribution: (assoc testvert 9.797630298091489) ---concurrency tests-- -hello -hello -+ : 45 -- : 0 -* : 24 -/ : 1 -mod : 1 -max : 10 -min : 1 +--concurrency tests-- +hello +hello ++ : 45 +- : 0 +* : 24 +/ : 1 +mod : 1 +max : 10 +min : 1 and : (true) - + or : (true) - + xor : (true) - + = : (false) - + != : (false) - + < : (false) - + <= : (true) - + > : (false) - + >= : (false) - + ~ : (true) - + list : (list 1 1 1 2) - + associate : (assoc a 1 b 1 c 1 d 2 ) - + assoc : (assoc a 1 b 1 c 1 d 2 ) - + map list : (list 2 4 6 8) - + map assoc : (assoc a 2 b 4 c 6 d 8 ) - + filter list : (list 3 4) - + filter assoc : (assoc 10 1) - + filter assoc 2 : (assoc 10 1 20 2) - -Expecting 1000: 1000 ---concurrent entity writes-- + +Expecting 1000: 1000 +--concurrent entity writes-- concurrent entity writes successful: (true) - ---total execution time-- -1.991008996963501 + +--clean-up test files-- +--total execution time-- +1.8731050491333008 diff --git a/src/Amalgam/string/StringManipulation.cpp b/src/Amalgam/string/StringManipulation.cpp index cde705af..6b1f05d2 100644 --- a/src/Amalgam/string/StringManipulation.cpp +++ b/src/Amalgam/string/StringManipulation.cpp @@ -8,6 +8,8 @@ //system headers: #include +#include +#include std::string StringManipulation::NumberToString(double value) { @@ -69,6 +71,18 @@ std::string StringManipulation::RemoveFirstWord(std::string &str) return first_token; } +std::vector StringManipulation::Split(std::string &s, char delim) +{ + std::vector ret; + std::stringstream ss { s }; + std::string item; + + while(std::getline(ss, item, delim)) + ret.push_back(item); + + return ret; +} + std::string StringManipulation::BinaryStringToBase16(std::string &binary_string) { std::string base16_string; diff --git a/src/Amalgam/string/StringManipulation.h b/src/Amalgam/string/StringManipulation.h index e71e2d14..484c25c1 100644 --- a/src/Amalgam/string/StringManipulation.h +++ b/src/Amalgam/string/StringManipulation.h @@ -15,6 +15,8 @@ namespace StringManipulation //removes the first word from str and return the removed word std::string RemoveFirstWord(std::string &str); + std::vector Split(std::string &s, char delim); + //returns true if the character in the string s starting at position is whitespace inline bool IsUtf8Whitespace(std::string &s, size_t position) { diff --git a/test/lib_smoke_test/main.cpp b/test/lib_smoke_test/main.cpp index 9ac97ca4..b0c2e667 100644 --- a/test/lib_smoke_test/main.cpp +++ b/test/lib_smoke_test/main.cpp @@ -19,7 +19,8 @@ int main(int argc, char* argv[]) char* file = (argc > 1) ? argv[1] : (char*)"test.amlg"; char write_log[] = ""; char print_log[] = ""; - if(LoadEntity(handle, file, false, true, write_log, print_log)) + auto status = LoadEntity(handle, file, false, true, write_log, print_log); + if(status.loaded) { char label[] = "test"; ExecuteEntity(handle, label);