├── version ├── test ├── share │ ├── README │ └── md5.txt ├── bytecode │ ├── test1.aun │ ├── test1.aub │ └── test2.aub ├── lib │ ├── README │ ├── dlc_lib.cpp │ └── CMakeLists.txt ├── src │ ├── tool_c_stdio.c │ ├── tool_c_hash.c │ ├── tool_hash.cpp │ ├── it_init.cpp │ ├── tool_mem.cpp │ ├── core_down_msg.cpp │ ├── README │ ├── core_env_var.cpp │ ├── tool_logger.cpp │ ├── tool_md5.cpp │ ├── tool_exit.cpp │ ├── tool_regex.cpp │ ├── tool_utf.cpp │ ├── core_up_msg.cpp │ ├── tool_dlc.cpp │ ├── code_create.cpp │ ├── parser_reader.cpp │ ├── parser_lexical.cpp │ ├── tool_byte.cpp │ └── CMakeLists.txt ├── CMakeLists.txt └── cmake │ └── function.cmake ├── version-info ├── cmake ├── _void_p_test.c ├── tool.cmake ├── filename.cmake ├── export_head.cmake ├── FindFFlags.cmake ├── deps.cmake ├── info.cmake ├── deps_install.cmake ├── directory.cmake └── aFunlangConfig.cmake.in ├── src ├── core │ ├── logger.cpp │ ├── CMakeLists.txt │ ├── environment.cpp │ ├── message_stream.cpp │ ├── object.cpp │ ├── inter.cpp │ └── env_var.cpp ├── code │ ├── logger.cpp │ └── CMakeLists.txt ├── runtime │ ├── logger.cpp │ ├── func_object.cpp │ ├── callback_var_object.cpp │ ├── top_activation.h │ ├── top_activation.cpp │ ├── normal_message.cpp │ ├── error_message.cpp │ ├── var_object.cpp │ ├── exe_activation.cpp │ ├── CMakeLists.txt │ └── varspace_object.cpp ├── parser │ ├── logger.cpp │ ├── CMakeLists.txt │ └── reader.cpp ├── tool │ ├── logger.cpp │ ├── exception.cpp │ ├── hash.cpp │ ├── __md5.h │ ├── encoding.cpp │ ├── dlc.cpp │ ├── string.cpp │ ├── byte.cpp │ ├── time.cpp │ ├── regex.cpp │ ├── CMakeLists.txt │ ├── exit.cpp │ └── file.cpp ├── interface │ ├── init.cpp │ ├── reader.cpp │ └── CMakeLists.txt └── CMakeLists.txt ├── include ├── code │ ├── aFuncode.h │ ├── code_logger.inline.h │ ├── code_logger.h │ ├── code.inline.h │ └── code.h ├── interface │ ├── aFunit.h │ ├── init.inline.h │ ├── init.h │ ├── it_exception.inline.h │ ├── it_exception.h │ ├── it_reader.inline.h │ └── it_reader.h ├── parser │ ├── aFunparser.h │ ├── parser_logger.inline.h │ ├── parser_logger.h │ ├── parser_reader.inline.h │ ├── parser_syntax.inline.h │ └── parser_reader.h ├── tool │ ├── tool_mem.h │ ├── tool_logger.inline.h │ ├── tool_encoding.inline.h │ ├── tool_hash.h │ ├── tool_log.inline.h │ ├── tool_logger.h │ ├── tool_encoding.h │ ├── tool_time.h │ ├── tool_str.h │ ├── tool_regex.inline.h │ ├── aFuntool.h │ ├── tool.h │ ├── tool_file.h │ ├── tool_exit.h │ ├── tool_macro.h │ ├── tool_md5.h │ ├── tool_regex.h │ ├── tool_directory.h │ ├── tool_path.h │ ├── tool_exception.inline.h │ ├── tool_byte.h │ ├── tool_mem.template.h │ ├── tool_exception.h │ ├── tool_byte.template.h │ ├── tool_dlc.template.h │ ├── tool_dlc.inline.h │ ├── tool_dlc.h │ └── tool_log_macro.h ├── core │ ├── core_logger.inline.h │ ├── core_environment.inline.h │ ├── core_env_var.inline.h │ ├── core_logger.h │ ├── aFuncore.h │ ├── core_message.h │ ├── core_exception.inline.h │ ├── core_exception.h │ ├── core_object.inline.h │ ├── core_activation.h │ ├── core_environment.h │ ├── core_message_stream.template.h │ ├── core_env_var.h │ ├── core_object.h │ ├── core_inter.inline.h │ ├── core_message_stream.h │ └── core_inter.h └── runtime │ ├── rt_logger.inline.h │ ├── rt_top_activation.inline.h │ ├── rt_logger.h │ ├── rt_func_activation.inline.h │ ├── rt_top_message.h │ ├── rt_normal_message.inline.h │ ├── rt_normal_activation.template.h │ ├── rt_literaler_object.h │ ├── rt_varspace_object.inline.h │ ├── rt_callback_var_object.h │ ├── aFunrt.h │ ├── rt_exception.inline.h │ ├── rt_exe_activation.inline.h │ ├── rt_top_activation.h │ ├── rt_var_object.h │ ├── rt_normal_message.h │ ├── rt_exception.h │ ├── rt_error_message.inline.h │ ├── rt_varspace_object.template.h │ ├── rt_func_object.inline.h │ ├── rt_exe_activation.h │ ├── rt_error_message.h │ ├── rt_normal_activation.inline.h │ ├── rt_func_activation.h │ ├── rt_func_object.h │ ├── rt_varspace_object.h │ └── rt_normal_activation.h ├── .gitmodules ├── .gitignore ├── lang ├── tr │ ├── base.py │ └── zh_cn.py └── hgt.cmake ├── LICENSE ├── deps └── CMakeLists.txt └── README.md /version: -------------------------------------------------------------------------------- 1 | 0.0.2 -------------------------------------------------------------------------------- /test/share/README: -------------------------------------------------------------------------------- 1 | 目录: share 2 | 存放共享的测试文件 -------------------------------------------------------------------------------- /test/share/md5.txt: -------------------------------------------------------------------------------- 1 | This is a md5 test file. -------------------------------------------------------------------------------- /test/bytecode/test1.aun: -------------------------------------------------------------------------------- 1 | {import aFun-1.0} 2 | -------------------------------------------------------------------------------- /version-info: -------------------------------------------------------------------------------- 1 | Changeable, aFunlang development version. -------------------------------------------------------------------------------- /test/lib/README: -------------------------------------------------------------------------------- 1 | 目录: lib 2 | 存放test使用了动态库文件 3 | 4 | dlc_lib.c tool_dlc 所使用的动态库 -------------------------------------------------------------------------------- /cmake/_void_p_test.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | int p = sizeof(void *); 3 | return p; 4 | } -------------------------------------------------------------------------------- /test/lib/dlc_lib.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | int num = 100; 3 | 4 | int test(int a){ 5 | return 10 + a; 6 | } 7 | } -------------------------------------------------------------------------------- /src/core/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "core_logger.h" 2 | 3 | namespace aFuncore { 4 | aFuntool::Logger *aFunCoreLogger = nullptr; 5 | } -------------------------------------------------------------------------------- /src/code/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "code_logger.h" 2 | 3 | namespace aFuncode { 4 | aFuntool::Logger *aFunCodeLogger = nullptr; 5 | } 6 | -------------------------------------------------------------------------------- /src/runtime/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_logger.h" 2 | 3 | namespace aFunrt { 4 | aFuntool::Logger *aFunRuntimeLogger = nullptr; 5 | } 6 | -------------------------------------------------------------------------------- /test/bytecode/test1.aub: -------------------------------------------------------------------------------- 1 | aFun-BytecodeFile ffffffff6268ff12ffffffffffffffffeglobalm{estr -------------------------------------------------------------------------------- /test/bytecode/test2.aub: -------------------------------------------------------------------------------- 1 | aFun-BytecodeFile ffffffff6268ff12ffffffffffffffffeglobalm{estr -------------------------------------------------------------------------------- /test/src/tool_c_stdio.c: -------------------------------------------------------------------------------- 1 | #include "aFuntool.h" 2 | 3 | int main() { 4 | printf_stdout(0, "Hello, aFun\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /src/parser/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "parser_logger.h" 2 | 3 | namespace aFunparser { 4 | aFuntool::Logger *aFunParserLogger = nullptr; 5 | } -------------------------------------------------------------------------------- /test/src/tool_c_hash.c: -------------------------------------------------------------------------------- 1 | #include "aFuntool.h" 2 | 3 | int main() { 4 | printf("%ld\n", time33("HelloWorld")); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /src/runtime/func_object.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_func_object.h" 2 | 3 | namespace aFunrt { 4 | bool Function::isInfix() { 5 | return false; 6 | } 7 | } -------------------------------------------------------------------------------- /test/src/tool_hash.cpp: -------------------------------------------------------------------------------- 1 | #include "aFuntool.h" 2 | 3 | int main() { 4 | std::cout << aFuntool::time33("HelloWorld") << std::endl; 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /include/code/aFuncode.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_AFUNCODE_H 2 | #define AFUN_AFUNCODE_H 3 | 4 | #include "code.h" 5 | #include "code_logger.h" 6 | 7 | #endif //AFUN_AFUNCODE_H 8 | -------------------------------------------------------------------------------- /include/interface/aFunit.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_AFUNIT_H 2 | #define AFUN_AFUNIT_H 3 | 4 | #include "init.h" 5 | #include "it_reader.h" 6 | #include "it_exception.h" 7 | 8 | #endif //AFUN_AFUNIT_H 9 | -------------------------------------------------------------------------------- /src/tool/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_logger.h" 2 | 3 | #ifndef AFUN_TOOL_C 4 | namespace aFuntool { 5 | #endif 6 | 7 | Logger *aFunSysLogger = nullptr; 8 | 9 | #ifndef AFUN_TOOL_C 10 | } 11 | #endif -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/pcre2"] 2 | path = deps/pcre2 3 | url = git@github.com:aFun-org/pcre2.git 4 | [submodule "deps/dlfcn-win32"] 5 | path = deps/dlfcn-win32 6 | url = git@github.com:aFun-org/dlfcn-win32.git 7 | -------------------------------------------------------------------------------- /include/parser/aFunparser.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_AFUNPARSER_H 2 | #define AFUN_AFUNPARSER_H 3 | 4 | #include "parser_logger.h" 5 | #include "parser_syntax.h" 6 | #include "parser_reader.h" 7 | 8 | #endif //AFUN_AFUNPARSER_H 9 | -------------------------------------------------------------------------------- /src/runtime/callback_var_object.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_callback_var_object.h" 2 | 3 | namespace aFunrt { 4 | bool CallBackVar::isCallBack(aFuncore::Inter &, aFuncore::Activation &) { 5 | return true; 6 | } 7 | } -------------------------------------------------------------------------------- /include/tool/tool_mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 文件名: mem.h 3 | * 目标: 内存管理工具的头文件 4 | */ 5 | 6 | #ifndef AFUN_TOOL_MEM_H 7 | #define AFUN_TOOL_MEM_H 8 | 9 | #include "tool_mem.template.h" 10 | 11 | #endif // AFUN_TOOL_MEM_H 12 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") 2 | include(function) 3 | 4 | if (_build_test) 5 | message(STATUS "Build CTest") 6 | add_subdirectory(lib) 7 | add_subdirectory(src) 8 | endif() -------------------------------------------------------------------------------- /test/src/it_init.cpp: -------------------------------------------------------------------------------- 1 | #include "init.h" 2 | 3 | int main() { 4 | if (!aFunit::aFunInit()) { 5 | aFuntool::printf_stderr(0, "aFunlang init error."); 6 | aFuntool::aFunExitReal(EXIT_FAILURE); 7 | } 8 | return 0; 9 | } -------------------------------------------------------------------------------- /src/runtime/top_activation.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jimso on 2022/2/13. 3 | // 4 | 5 | #ifndef AFUN_TOP_ACTIVATION_H 6 | #define AFUN_TOP_ACTIVATION_H 7 | 8 | 9 | class top_activation { 10 | 11 | }; 12 | 13 | 14 | #endif //AFUN_TOP_ACTIVATION_H 15 | -------------------------------------------------------------------------------- /src/runtime/top_activation.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_top_activation.h" 2 | #include "rt_normal_message.h" 3 | 4 | namespace aFunrt { 5 | TopActivation::TopActivation(const aFuncode::Code &code, aFuncore::Inter &inter_) : ExeActivation(code, inter_), base{code} { 6 | 7 | } 8 | } -------------------------------------------------------------------------------- /cmake/tool.cmake: -------------------------------------------------------------------------------- 1 | function(to_native_path in out) 2 | if (WIN32 AND NOT CYGWIN) 3 | string(REPLACE "/" "\\\\" _out ${in}) # 转义 4 | set(${out} ${_out} PARENT_SCOPE) 5 | else() 6 | set(${out} ${in} PARENT_SCOPE) 7 | endif() 8 | endfunction() 9 | -------------------------------------------------------------------------------- /src/tool/exception.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_exception.h" 2 | 3 | #ifndef AFUN_TOOL_C 4 | namespace aFuntool { 5 | #endif 6 | 7 | const char *aFunException::what() const noexcept { 8 | return message.c_str(); 9 | } 10 | 11 | #ifndef AFUN_TOOL_C 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /test/src/tool_mem.cpp: -------------------------------------------------------------------------------- 1 | #include "aFuntool.h" 2 | 3 | int main() { 4 | int *p = aFuntool::safeCalloc(); 5 | *p = 10; 6 | aFuntool::safeFree(p); 7 | 8 | p = aFuntool::safeCalloc(1); 9 | *p = 10; 10 | aFuntool::safeFree(p); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /include/interface/init.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_INIT_INLINE_H 2 | #define AFUN_INIT_INLINE_H 3 | 4 | #include "init.h" 5 | 6 | namespace aFunit { 7 | void setAFunLogger(aFuntool::Logger *log) { 8 | aFunLogger = log; 9 | } 10 | } 11 | 12 | 13 | #endif //AFUN_INIT_INLINE_H 14 | -------------------------------------------------------------------------------- /test/src/core_down_msg.cpp: -------------------------------------------------------------------------------- 1 | #include "core_message_stream.h" 2 | int main() { 3 | auto *um = new aFuncore::DownMessageStream(); 4 | um->pushMessage("test-1", new aFuncore::Message()); 5 | std::cout << um->getMessage("test-1") << std::endl; 6 | delete um; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/interface/init.cpp: -------------------------------------------------------------------------------- 1 | #include "init.h" 2 | 3 | namespace aFunit { 4 | aFuntool::Logger *aFunLogger = nullptr; 5 | 6 | bool aFunInit() { 7 | aFuntool::getEndian(); 8 | if (setlocale(LC_ALL, "") == nullptr) 9 | return false; 10 | return true; 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /include/code/code_logger.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CODE_LOGGER_INLINE_H 2 | #define AFUN_CODE_LOGGER_INLINE_H 3 | #include "code_logger.h" 4 | 5 | namespace aFuncode { 6 | void setCodeLogger(aFuntool::Logger *log) { 7 | aFunCodeLogger = log; 8 | } 9 | } 10 | 11 | #endif //AFUN_CODE_LOGGER_INLINE_H 12 | -------------------------------------------------------------------------------- /include/core/core_logger.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_LOGGER_INLINE_H 2 | #define AFUN_CORE_LOGGER_INLINE_H 3 | 4 | #include "core_logger.h" 5 | 6 | namespace aFuncore { 7 | void setCoreLogger(aFuntool::Logger *log) { 8 | aFunCoreLogger = log; 9 | } 10 | } 11 | 12 | #endif //AFUN_CORE_LOGGER_INLINE_H 13 | -------------------------------------------------------------------------------- /include/runtime/rt_logger.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_LOGGER_INLINE_H 2 | #define AFUN_RT_LOGGER_INLINE_H 3 | 4 | #include "rt_logger.h" 5 | 6 | namespace aFunrt { 7 | void setRuntimeLogger(aFuntool::Logger *log) { 8 | aFunRuntimeLogger = log; 9 | } 10 | } 11 | 12 | #endif //AFUN_RT_LOGGER_INLINE_H 13 | -------------------------------------------------------------------------------- /include/core/core_environment.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_ENVIRONMENT_INLINE_H 2 | #define AFUN_CORE_ENVIRONMENT_INLINE_H 3 | #include "core_environment.h" 4 | 5 | namespace aFuncore { 6 | EnvVarSpace &Environment::getEnvVarSpace() { 7 | return env_var; 8 | } 9 | } 10 | 11 | #endif //AFUN_CORE_ENVIRONMENT_INLINE_H 12 | -------------------------------------------------------------------------------- /include/parser/parser_logger.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_PARSER_LOGGER_INLINE_H 2 | #define AFUN_PARSER_LOGGER_INLINE_H 3 | #include "parser_logger.h" 4 | 5 | namespace aFunparser { 6 | void setParserLogger(aFuntool::Logger *log) { 7 | aFunParserLogger = log; 8 | } 9 | } 10 | 11 | #endif //AFUN_PARSER_LOGGER_INLINE_H 12 | -------------------------------------------------------------------------------- /test/src/README: -------------------------------------------------------------------------------- 1 | 目录: src 2 | 存放简单测试的源文件 3 | 简单测试: 即仅一个`.c`文件的测试 4 | 5 | tool_mem 测试内存管理函数 6 | tool_dlc 测试动态库导入函数 dlc 7 | tool_regex 测试正则表达式库 8 | tool_byte 测试字节 IO 函数 9 | tool_md5 测试 md5 函数 10 | 11 | byte_code 测试字节码写入读取 12 | reader 测试文件读取 13 | 14 | lexical 测试词法分析 15 | syntactic 测试语法分析 16 | 17 | env_init 测试-环境初始化 18 | run_code 测试-代码运行 -------------------------------------------------------------------------------- /include/runtime/rt_top_activation.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_TOP_ACTIVATION_INLINE_H 2 | #define AFUN_RT_TOP_ACTIVATION_INLINE_H 3 | #include "rt_top_activation.h" 4 | 5 | namespace aFunrt { 6 | const aFuncode::Code &TopActivation::getBase() const { 7 | return base; 8 | } 9 | } 10 | 11 | #endif //AFUN_RT_TOP_ACTIVATION_INLINE_H 12 | -------------------------------------------------------------------------------- /include/core/core_env_var.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_ENV_VAR_INLINE_H 2 | #define AFUN_CORE_ENV_VAR_INLINE_H 3 | #include "core_env_var.h" 4 | 5 | namespace aFuncore { 6 | size_t EnvVarSpace::getCount() { 7 | std::unique_lock mutex{lock}; 8 | return var.size(); 9 | } 10 | } 11 | 12 | #endif //AFUN_CORE_ENV_VAR_INLINE_H 13 | -------------------------------------------------------------------------------- /include/core/core_logger.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_LOGGER_H 2 | #define AFUN_CORE_LOGGER_H 3 | #include "aFuntool.h" 4 | #include "aFunCoreExport.h" 5 | 6 | namespace aFuncore { 7 | AFUN_CORE_EXPORT extern aFuntool::Logger *aFunCoreLogger; 8 | AFUN_STATIC void setCoreLogger(aFuntool::Logger *log); 9 | } 10 | 11 | #include "core_logger.inline.h" 12 | 13 | #endif //AFUN_TOOL_LOGGER_H -------------------------------------------------------------------------------- /include/runtime/rt_logger.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_LOGGER_H 2 | #define AFUN_RT_LOGGER_H 3 | #include "aFunRuntimeExport.h" 4 | #include "aFuntool.h" 5 | 6 | namespace aFunrt { 7 | AFUN_RT_EXPORT extern aFuntool::Logger *aFunRuntimeLogger; 8 | AFUN_STATIC void setRuntimeLogger(aFuntool::Logger *log); 9 | } 10 | 11 | #include "rt_logger.inline.h" 12 | #endif //AFUN_RT_LOGGER_H 13 | -------------------------------------------------------------------------------- /include/code/code_logger.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CODE_LOGGER_H 2 | #define AFUN_CODE_LOGGER_H 3 | #include "aFunCodeExport.h" 4 | #include "aFuntool.h" 5 | 6 | namespace aFuncode { 7 | AFUN_CODE_EXPORT extern aFuntool::Logger *aFunCodeLogger; 8 | AFUN_STATIC void setCodeLogger(aFuntool::Logger *log); 9 | } 10 | 11 | #include "code_logger.inline.h" 12 | 13 | #endif //AFUN_CODE_LOGGER_H 14 | -------------------------------------------------------------------------------- /include/core/aFuncore.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_AFUNCORE_H 2 | #define AFUN_AFUNCORE_H 3 | 4 | #include "core_logger.h" 5 | #include "core_message.h" 6 | #include "core_message_stream.h" 7 | #include "core_env_var.h" 8 | #include "core_environment.h" 9 | #include "core_inter.h" 10 | #include "core_object.h" 11 | #include "core_activation.h" 12 | #include "core_exception.h" 13 | 14 | #endif //AFUN_AFUNCORE_H 15 | -------------------------------------------------------------------------------- /include/parser/parser_logger.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_PARSER_LOGGER_H 2 | #define AFUN_PARSER_LOGGER_H 3 | #include "aFunParserExport.h" 4 | #include "aFuntool.h" 5 | 6 | namespace aFunparser { 7 | AFUN_PARSER_EXPORT extern aFuntool::Logger *aFunParserLogger; 8 | AFUN_STATIC void setParserLogger(aFuntool::Logger *log); 9 | } 10 | 11 | #include "parser_logger.inline.h" 12 | #endif //AFUN_PARSER_LOGGER_H 13 | -------------------------------------------------------------------------------- /include/runtime/rt_func_activation.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_FUNC_ACTIVATION_INLINE_H 2 | #define AFUN_RT_FUNC_ACTIVATION_INLINE_H 3 | #include "rt_func_activation.h" 4 | 5 | namespace aFunrt { 6 | FuncActivation::FuncActivation(const aFuncode::Code::ByteCode *code, aFuncore::Inter &inter_) : NormalActivation(inter_), call{code} { 7 | 8 | } 9 | } 10 | 11 | #endif //AFUN_RT_FUNC_ACTIVATION_INLINE_H 12 | -------------------------------------------------------------------------------- /include/runtime/rt_top_message.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_TOP_MESSAGE_H 2 | #define AFUN_RT_TOP_MESSAGE_H 3 | #include "aFunRuntimeExport.h" 4 | #include "aFuncore.h" 5 | 6 | namespace aFunrt { 7 | class TopMessage : public virtual aFuncore::Message { 8 | public: 9 | virtual void topProgress(aFuncore::Inter &inter, aFuncore::Activation &activation) = 0; 10 | }; 11 | } 12 | 13 | #endif //AFUN_RT_TOP_MESSAGE_H 14 | -------------------------------------------------------------------------------- /cmake/filename.cmake: -------------------------------------------------------------------------------- 1 | function(define_filename targetname) 2 | get_target_property(source_files "${targetname}" SOURCES) 3 | foreach(sourcefile ${source_files}) 4 | get_filename_component(basename "${sourcefile}" NAME) 5 | set_property( 6 | SOURCE "${sourcefile}" APPEND 7 | PROPERTY COMPILE_DEFINITIONS "__FILENAME__=\"${basename}\"") 8 | endforeach() 9 | endfunction() 10 | -------------------------------------------------------------------------------- /include/tool/tool_logger.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_LOGGER_INLINE_H 2 | #define AFUN_TOOL_LOGGER_INLINE_H 3 | #ifdef __cplusplus 4 | 5 | #include "tool_logger.h" 6 | 7 | #ifndef AFUN_TOOL_C 8 | namespace aFuntool { 9 | #endif 10 | 11 | void setSysLogger(Logger *log) { 12 | aFunSysLogger = log; 13 | } 14 | 15 | #ifndef AFUN_TOOL_C 16 | } 17 | #endif 18 | 19 | #endif 20 | #endif //AFUN_TOOL_LOGGER_INLINE_H 21 | -------------------------------------------------------------------------------- /test/src/core_env_var.cpp: -------------------------------------------------------------------------------- 1 | #include "core_env_var.h" 2 | 3 | int main() { 4 | auto *evs = new aFuncore::EnvVarSpace(); 5 | 6 | evs->setString("a", "string"); 7 | evs->setNumber("a", 20); 8 | 9 | std::string s; 10 | int32_t n; 11 | 12 | evs->findString("a", s); 13 | evs->findNumber("a", n); 14 | 15 | std::cout << "a = " << s << ", " << n << std::endl; 16 | 17 | delete evs; 18 | return 0; 19 | } -------------------------------------------------------------------------------- /test/src/tool_logger.cpp: -------------------------------------------------------------------------------- 1 | #include "aFuntool.h" 2 | 3 | int main() { 4 | auto factor = aFuntool::LogFactory(std::string(".") + aFuntool::SEP + "aFunlog", true); 5 | auto logger = aFuntool::Logger(factor, "aFun"); 6 | debugLog(&logger, "I am debug\n"); 7 | infoLog(&logger, "I am info\n"); 8 | warningLog(&logger, "I am warning\n"); 9 | errorLog(&logger, "I am error\n"); 10 | aFuntool::aFunExitReal(EXIT_SUCCESS); 11 | } -------------------------------------------------------------------------------- /test/src/tool_md5.cpp: -------------------------------------------------------------------------------- 1 | #include "aFuntool.h" 2 | 3 | int main(int argc, char **argv) { 4 | if (argc != 3) 5 | return 1; 6 | 7 | char *md5_answer = argv[1]; 8 | char *file_path = argv[2]; 9 | char *my_md5 = aFuntool::getFileMd5(file_path); 10 | 11 | bool ret = !strcmp(my_md5, md5_answer); 12 | aFuntool::safeFree(my_md5); 13 | 14 | if (ret) 15 | return 0; 16 | return 1; // 不相等, 表示错误 17 | } 18 | -------------------------------------------------------------------------------- /include/core/core_message.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_MESSAGE_H 2 | #define AFUN_CORE_MESSAGE_H 3 | #include "aFuntool.h" 4 | #include "aFunCoreExport.h" 5 | 6 | namespace aFuncore { 7 | class AFUN_CORE_EXPORT Message { 8 | public: 9 | AFUN_INLINE explicit Message() = default; 10 | virtual ~Message() = default; 11 | Message &operator=(const Message &)=delete; 12 | }; 13 | } 14 | 15 | #endif //AFUN_CORE_MESSAGE_H 16 | -------------------------------------------------------------------------------- /include/tool/tool_encoding.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_ENCODING_INLINE_H 2 | #define AFUN_TOOL_ENCODING_INLINE_H 3 | #ifdef __cplusplus 4 | 5 | #include "tool_encoding.h" 6 | 7 | #ifndef AFUN_TOOL_C 8 | namespace aFuntool { 9 | #endif 10 | 11 | bool isCharUTF8(const std::string &str) { 12 | return isCharUTF8(str.c_str()); 13 | } 14 | 15 | #ifndef AFUN_TOOL_C 16 | } 17 | #endif 18 | 19 | #endif 20 | #endif //AFUN_TOOL_ENCODING_INLINE_H 21 | -------------------------------------------------------------------------------- /include/runtime/rt_normal_message.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_NORMAL_MESSAGE_INLINE_H 2 | #define AFUN_RT_NORMAL_MESSAGE_INLINE_H 3 | #include "rt_normal_message.h" 4 | 5 | namespace aFunrt { 6 | NormalMessage::NormalMessage(NormalMessage &&msg) noexcept : obj {msg.obj}{ 7 | msg.obj = nullptr; 8 | } 9 | 10 | aFuncore::Object *NormalMessage::getObject() { 11 | return obj; 12 | } 13 | } 14 | 15 | #endif //AFUN_RT_NORMAL_MESSAGE_INLINE_H 16 | -------------------------------------------------------------------------------- /include/interface/init.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_INIT_H 2 | #define AFUN_INIT_H 3 | #include "aFunlangExport.h" 4 | #include "aFuncore.h" 5 | #include "aFunparser.h" 6 | #include "aFuncode.h" 7 | #include "aFuntool.h" 8 | 9 | namespace aFunit { 10 | AFUN_LANG_EXPORT extern aFuntool::Logger *aFunLogger; 11 | AFUN_LANG_EXPORT bool aFunInit(); 12 | AFUN_STATIC void setAFunLogger(aFuntool::Logger *log); 13 | } 14 | 15 | #include "init.inline.h" 16 | 17 | #endif //AFUN_INIT_H 18 | -------------------------------------------------------------------------------- /include/runtime/rt_normal_activation.template.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_NORMAL_ACTIVATION_TEMPLATE_H 2 | #define AFUN_RT_NORMAL_ACTIVATION_TEMPLATE_H 3 | #include "rt_normal_activation.h" 4 | 5 | namespace aFunrt { 6 | template 7 | void NormalActivation::VarList::forEach(Callable func, T...arg) { 8 | for (auto &vs : varspace) 9 | func(vs, arg...); 10 | } 11 | } 12 | 13 | 14 | #endif //AFUN_RT_NORMAL_ACTIVATION_TEMPLATE_H 15 | -------------------------------------------------------------------------------- /include/tool/tool_hash.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_HASH_H 2 | #define AFUN_TOOL_HASH_H 3 | #include "aFunToolExport.h" 4 | 5 | /* 哈希工具 */ 6 | #ifndef AFUN_TOOL_C 7 | namespace aFuntool { 8 | #endif 9 | 10 | typedef long int time33_t; 11 | AFUN_TOOL_C_EXPORT_FUNC time33_t time33(const char *str); 12 | #ifdef __cplusplus 13 | AFUN_TOOL_EXPORT time33_t time33(const std::string &str); 14 | #endif 15 | 16 | #ifndef AFUN_TOOL_C 17 | } 18 | #endif 19 | 20 | #endif //AFUN_TOOL_HASH_H 21 | -------------------------------------------------------------------------------- /include/interface/it_exception.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_IT_EXCEPTION_INLINE_H 2 | #define AFUN_IT_EXCEPTION_INLINE_H 3 | 4 | #include "it_exception.h" 5 | 6 | namespace aFunit { 7 | aFunitException::aFunitException(const std::string &msg) : aFunException{msg} { 8 | 9 | } 10 | 11 | readerFileOpenError::readerFileOpenError(const aFuntool::FilePath &file) 12 | : aFunitException("Reader cannot open file: " + file) { 13 | 14 | } 15 | } 16 | 17 | #endif //AFUN_IT_EXCEPTION_INLINE_H 18 | -------------------------------------------------------------------------------- /include/core/core_exception.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_EXCEPTION_INLINE_H 2 | #define AFUN_CORE_EXCEPTION_INLINE_H 3 | #include 4 | 5 | #include "core_exception.h" 6 | 7 | namespace aFuncore { 8 | aFuncoreException::aFuncoreException(const std::string &msg) : aFunException{msg} { 9 | 10 | } 11 | 12 | EnvironmentDestructException::EnvironmentDestructException() : aFuncoreException("Environment Destruct Error") { 13 | 14 | } 15 | } 16 | 17 | #endif //AFUN_CORE_EXCEPTION_INLINE_H 18 | -------------------------------------------------------------------------------- /test/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB src_list RELATIVE ${CMAKE_CURRENT_LIST_DIR} 2 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 3 | 4 | foreach(src IN LISTS src_list) 5 | cmake_path(GET src STEM file_name) 6 | string(REPLACE "_" "-" target_name ${file_name}) 7 | add_library(${target_name} SHARED ${src}) 8 | set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "test_${file_name}") 9 | define_filename(${target_name}) 10 | unset(file_name) 11 | unset(target_name) 12 | endforeach() 13 | -------------------------------------------------------------------------------- /include/runtime/rt_literaler_object.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_LITERALER_OBJECT_H 2 | #define AFUN_RT_LITERALER_OBJECT_H 3 | #include 4 | #include "aFunRuntimeExport.h" 5 | #include "aFuncore.h" 6 | 7 | namespace aFunrt { 8 | class AFUN_RT_EXPORT Literaler : public virtual aFuncore::Object { 9 | public: 10 | virtual void getObject(const std::string &literal, char prefix, aFuncore::Inter &inter, aFuncore::Activation &activation) = 0; 11 | }; 12 | } 13 | 14 | #endif //AFUN_RT_LITERALER_OBJECT_H 15 | -------------------------------------------------------------------------------- /include/tool/tool_log.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_LOG_INLINE_H 2 | #define AFUN_TOOL_LOG_INLINE_H 3 | #ifdef __cplusplus 4 | 5 | #include "tool_log.h" 6 | 7 | #ifndef AFUN_TOOL_C 8 | namespace aFuntool { 9 | #endif 10 | 11 | Logger::Logger(LogFactory &factor, std::string id, LogLevel level, bool exit) noexcept 12 | : factor_{factor}, id_{std::move(id)}, level_{level}, exit_{exit} { 13 | 14 | } 15 | 16 | #ifndef AFUN_TOOL_C 17 | } 18 | #endif 19 | 20 | #endif 21 | #endif //AFUN_TOOL_LOG_INLINE_H 22 | -------------------------------------------------------------------------------- /include/tool/tool_logger.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_LOGGER_H 2 | #define AFUN_TOOL_LOGGER_H 3 | #ifdef __cplusplus 4 | 5 | #include "aFunToolExport.h" 6 | #include "tool_macro.h" 7 | 8 | #ifndef AFUN_TOOL_C 9 | namespace aFuntool { 10 | #endif 11 | 12 | class Logger; 13 | extern AFUN_TOOL_EXPORT class Logger *aFunSysLogger; 14 | 15 | AFUN_STATIC void setSysLogger(Logger *log); 16 | 17 | #ifndef AFUN_TOOL_C 18 | } 19 | #endif 20 | 21 | #include "tool_logger.inline.h" 22 | 23 | #endif 24 | #endif //AFUN_TOOL_LOGGER_H 25 | -------------------------------------------------------------------------------- /include/core/core_exception.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_EXCEPTION_H 2 | #define AFUN_CORE_EXCEPTION_H 3 | #include "aFuntool.h" 4 | 5 | namespace aFuncore { 6 | class aFuncoreException : public aFuntool::aFunException { 7 | public: 8 | AFUN_INLINE explicit aFuncoreException(const std::string &msg); 9 | }; 10 | 11 | class EnvironmentDestructException : public aFuncoreException { 12 | public: 13 | AFUN_INLINE EnvironmentDestructException(); 14 | }; 15 | } 16 | 17 | #include "core_exception.inline.h" 18 | 19 | #endif //AFUN_CORE_EXCEPTION_H 20 | -------------------------------------------------------------------------------- /include/runtime/rt_varspace_object.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_VARSPACE_OBJECT_INLINE_H 2 | #define AFUN_RT_VARSPACE_OBJECT_INLINE_H 3 | 4 | #include "rt_varspace_object.h" 5 | 6 | namespace aFunrt { 7 | size_t VarSpace::getCount() { 8 | std::unique_lock mutex{lock}; 9 | return var.size(); 10 | } 11 | 12 | aFuncore::Object *VarSpace::findObject(const std::string &name) { 13 | Var *ret = findVar(name); 14 | return ret ? ret->getData() : nullptr; 15 | } 16 | } 17 | 18 | 19 | #endif //AFUN_RT_VARSPACE_OBJECT_INLINE_H 20 | -------------------------------------------------------------------------------- /include/runtime/rt_callback_var_object.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_CALLBACK_VAR_OBJECT_H 2 | #define AFUN_RT_CALLBACK_VAR_OBJECT_H 3 | #include 4 | #include "aFunRuntimeExport.h" 5 | #include "aFuncore.h" 6 | 7 | namespace aFunrt { 8 | class AFUN_RT_EXPORT CallBackVar : public virtual aFuncore::Object { 9 | public: 10 | virtual bool isCallBack(aFuncore::Inter &inter, aFuncore::Activation &activation); 11 | virtual void callBack(aFuncore::Inter &inter, aFuncore::Activation &activation) = 0; 12 | }; 13 | } 14 | 15 | #endif //AFUN_RT_CALLBACK_VAR_OBJECT_H 16 | -------------------------------------------------------------------------------- /include/interface/it_exception.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_IT_EXCEPTION_H 2 | #define AFUN_IT_EXCEPTION_H 3 | #include "aFuntool.h" 4 | 5 | namespace aFunit { 6 | class aFunitException : public aFuntool::aFunException { 7 | public: 8 | AFUN_INLINE explicit aFunitException(const std::string &msg); 9 | }; 10 | 11 | class readerFileOpenError : public aFunitException { 12 | public: 13 | AFUN_INLINE explicit readerFileOpenError(const aFuntool::FilePath &file); 14 | }; 15 | 16 | } 17 | 18 | #include "it_exception.inline.h" 19 | 20 | #endif //AFUN_IT_EXCEPTION_H 21 | -------------------------------------------------------------------------------- /include/runtime/aFunrt.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_AFUNRT_H 2 | #define AFUN_AFUNRT_H 3 | 4 | #include "rt_logger.h" 5 | #include "rt_normal_activation.h" 6 | #include "rt_exe_activation.h" 7 | #include "rt_top_activation.h" 8 | #include "rt_func_activation.h" 9 | #include "rt_top_message.h" 10 | #include "rt_normal_message.h" 11 | #include "rt_error_message.h" 12 | #include "rt_func_object.h" 13 | #include "rt_literaler_object.h" 14 | #include "rt_callback_var_object.h" 15 | #include "rt_var_object.h" 16 | #include "rt_varspace_object.h" 17 | #include "rt_exception.h" 18 | 19 | #endif //AFUN_AFUNRT_H 20 | -------------------------------------------------------------------------------- /src/runtime/normal_message.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_normal_message.h" 2 | 3 | namespace aFunrt { 4 | NormalMessage::NormalMessage(aFuncore::Object *obj_) : obj {obj_} { 5 | obj->addReference(); 6 | } 7 | 8 | NormalMessage::~NormalMessage(){ 9 | if (obj != nullptr) { 10 | obj->delReference(); 11 | obj = nullptr; 12 | } 13 | } 14 | 15 | void NormalMessage::topProgress(aFuncore::Inter &inter, aFuncore::Activation &){ 16 | inter.getOutMessageStream().pushMessage("NORMAL", new NormalMessage(std::move(*this))); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /include/tool/tool_encoding.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_ENCODING_H 2 | #define AFUN_TOOL_ENCODING_H 3 | #include "aFunToolExport.h" 4 | #include "tool_macro.h" 5 | 6 | #ifdef __cplusplus 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | #ifndef AFUN_TOOL_C 13 | namespace aFuntool { 14 | #endif 15 | 16 | AFUN_TOOL_C_EXPORT_FUNC bool isCharUTF8(const char *str); 17 | #ifdef __cplusplus 18 | AFUN_INLINE bool isCharUTF8(const std::string &str); 19 | #endif 20 | 21 | #ifndef AFUN_TOOL_C 22 | } 23 | #endif 24 | 25 | #include "tool_encoding.inline.h" 26 | 27 | #endif //AFUN_TOOL_ENCODING_H 28 | -------------------------------------------------------------------------------- /include/tool/tool_time.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TIME_H 2 | #define AFUN_TIME_H 3 | #include "aFunToolExport.h" 4 | 5 | #if __cplusplus 6 | #include 7 | #else 8 | #include "time.h" 9 | #endif 10 | 11 | /* 时间工具 */ 12 | #ifndef AFUN_TOOL_C 13 | namespace aFuntool { 14 | #endif 15 | 16 | AFUN_TOOL_C_EXPORT_FUNC void safeSleep(double ms); 17 | AFUN_TOOL_C_EXPORT_FUNC char *getTime(time_t *t, const char *format); 18 | 19 | #ifdef __cplusplus 20 | AFUN_TOOL_EXPORT std::string getTime(time_t *t, const std::string &format); 21 | #endif 22 | 23 | #ifndef AFUN_TOOL_C 24 | } 25 | #endif 26 | #endif //AFUN_TIME_H 27 | -------------------------------------------------------------------------------- /test/src/tool_exit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "aFuntool.h" 3 | 4 | void exit_func_push1(void *) { 5 | std::cout << "I am exit push-1" << std::endl; 6 | } 7 | 8 | void exit_func_push2(void *) { 9 | std::cout << "I am exit push-2" << std::endl; 10 | } 11 | 12 | int main() { 13 | int exit_code = 0; 14 | try { 15 | aFuntool::aFunAtExit(exit_func_push1, nullptr); 16 | aFuntool::aFunAtExit(exit_func_push2, nullptr); 17 | aFuntool::aFunExit(0); 18 | } catch (aFuntool::Exit &e) { 19 | exit_code = e.getExitCode(); 20 | } 21 | aFuntool::aFunExitReal(exit_code); 22 | } 23 | -------------------------------------------------------------------------------- /include/core/core_object.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_OBJECT_INLINE_H 2 | #define AFUN_CORE_OBJECT_INLINE_H 3 | #include "core_object.h" 4 | 5 | namespace aFuncore { 6 | void Object::addReference() { 7 | std::unique_lock mutex{lock}; 8 | reference++; 9 | } 10 | 11 | void Object::delReference() { 12 | std::unique_lock mutex{lock}; 13 | reference--; 14 | } 15 | 16 | GcCount Object::getReference() const { 17 | return reference; 18 | } 19 | 20 | void Object::setClear(bool clear) { 21 | not_clear=!clear; 22 | } 23 | } 24 | 25 | #endif //AFUN_CORE_OBJECT_INLINE_H 26 | -------------------------------------------------------------------------------- /include/tool/tool_str.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_STR_H 2 | #define AFUN_TOOL_STR_H 3 | #include "aFunToolExport.h" 4 | 5 | #ifdef __cplusplus 6 | #include 7 | #include 8 | #else 9 | #include 10 | #include 11 | #endif 12 | 13 | /* 字符串工具 */ 14 | 15 | #ifndef AFUN_TOOL_C 16 | namespace aFuntool { 17 | #endif 18 | 19 | AFUN_TOOL_C_EXPORT_FUNC char *charToStr(char ch); 20 | AFUN_TOOL_C_EXPORT_FUNC char *strCopy(const char *str); 21 | AFUN_TOOL_C_EXPORT_FUNC char *strJoin(const char *first, const char *second, bool free_first, bool free_last); 22 | 23 | #ifndef AFUN_TOOL_C 24 | } 25 | #endif 26 | 27 | #endif //AFUN_TOOL_STR_H 28 | -------------------------------------------------------------------------------- /include/interface/it_reader.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_IT_READER_INLINE_H 2 | #define AFUN_IT_READER_INLINE_H 3 | #include "it_reader.h" 4 | #include "it_exception.h" 5 | 6 | namespace aFunit { 7 | StringReader::StringReader(std::string str_, const aFuntool::FilePath &path_) 8 | : Reader{path_, 0}, str{std::move(str_)}, index{0}, len{str.size()} { 9 | 10 | } 11 | 12 | FileReader::FileReader(const aFuntool::FilePath &path_) 13 | : Reader{path_, 0}, file{aFuntool::fileOpen(path_, "rb")}, no_first{false} { 14 | if (file == nullptr) 15 | throw readerFileOpenError(path_); 16 | } 17 | } 18 | 19 | #endif //AFUN_IT_READER_INLINE_H 20 | -------------------------------------------------------------------------------- /include/runtime/rt_exception.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_EXCEPTION_INLINE_H 2 | #define AFUN_RT_EXCEPTION_INLINE_H 3 | #include "rt_exception.h" 4 | 5 | namespace aFunrt { 6 | aFunrtException::aFunrtException(const std::string &msg) : aFunException{msg} { 7 | 8 | } 9 | 10 | RuntimeError::RuntimeError(const std::string &msg, std::string type_) : aFunrtException(msg), type{std::move(type_)} { 11 | 12 | } 13 | 14 | const std::string &RuntimeError::getType() const { 15 | return type; 16 | } 17 | 18 | ArgumentError::ArgumentError() : RuntimeError("Argument mismatch", "ArgumentError") { 19 | 20 | } 21 | } 22 | 23 | #endif //AFUN_RT_EXCEPTION_INLINE_H 24 | -------------------------------------------------------------------------------- /src/tool/hash.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 文件名: hash.c 3 | * 目标: 关于哈希表的实用函数 4 | */ 5 | 6 | #include "tool.h" 7 | #include "tool_hash.h" 8 | 9 | #ifndef AFUN_TOOL_C 10 | namespace aFuntool { 11 | #endif 12 | 13 | time33_t time33(const char *str){ 14 | unsigned int hash = 5381; 15 | while (*str) 16 | hash += (hash << 5) + (*str++); 17 | return (hash & 0x7FFFFFFF); // NOLINT 18 | } 19 | 20 | time33_t time33(const std::string &str){ 21 | unsigned int hash = 5381; 22 | for (auto ch: str) 23 | hash += (hash << 5) + ch; 24 | return (hash & 0x7FFFFFFF); // NOLINT 25 | } 26 | 27 | #ifndef AFUN_TOOL_C 28 | } 29 | #endif 30 | -------------------------------------------------------------------------------- /include/tool/tool_regex.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_REGEX_INLINE_H 2 | #define AFUN_TOOL_REGEX_INLINE_H 3 | #ifdef __cplusplus 4 | 5 | #include "tool_regex.h" 6 | 7 | #ifndef AFUN_TOOL_C 8 | namespace aFuntool { 9 | #endif 10 | 11 | Regex::Regex(const Regex ®ex) noexcept: Regex(regex.pattern) { 12 | 13 | } 14 | 15 | Regex::Regex(Regex &®ex) noexcept : pattern {std::move(regex.pattern)}, re {regex.re} { 16 | regex.re = nullptr; 17 | } 18 | 19 | Regex::~Regex() noexcept { 20 | if (re != nullptr) 21 | pcre2_code_free(re); 22 | } 23 | 24 | #ifndef AFUN_TOOL_C 25 | } 26 | #endif 27 | 28 | #endif 29 | #endif //AFUN_TOOL_REGEX_INLINE_H 30 | -------------------------------------------------------------------------------- /include/runtime/rt_exe_activation.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_EXE_ACTIVATION_INLINE_H 2 | #define AFUN_RT_EXE_ACTIVATION_INLINE_H 3 | #include "rt_exe_activation.h" 4 | 5 | namespace aFunrt { 6 | ExeActivation::ExeActivation(const aFuncode::Code &code, aFuncore::Inter &inter_) : NormalActivation(inter_), start{code.getByteCode()}, next{code.getByteCode()} { 7 | 8 | } 9 | 10 | ExeActivation::ExeActivation(const aFuncode::Code::ByteCode *code, aFuncore::Inter &inter_) : NormalActivation(inter_), start{code}, next{code} { 11 | 12 | } 13 | 14 | const aFuncode::Code::ByteCode *ExeActivation::getStart() const{ 15 | return start; 16 | } 17 | } 18 | 19 | #endif //AFUN_RT_EXE_ACTIVATION_INLINE_H 20 | -------------------------------------------------------------------------------- /include/runtime/rt_top_activation.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_TOP_ACTIVATION_H 2 | #define AFUN_RT_TOP_ACTIVATION_H 3 | #include "aFunRuntimeExport.h" 4 | #include "aFuncore.h" 5 | #include "rt_func_object.h" 6 | #include "rt_exe_activation.h" 7 | 8 | namespace aFunrt { 9 | class AFUN_RT_EXPORT TopActivation : public ExeActivation { 10 | public: 11 | explicit TopActivation(const aFuncode::Code &code, aFuncore::Inter &inter_); 12 | ~TopActivation() override = default; 13 | [[nodiscard]] AFUN_INLINE const aFuncode::Code &getBase() const; 14 | 15 | private: 16 | const aFuncode::Code &base; 17 | }; 18 | } 19 | 20 | #include "rt_top_activation.inline.h" 21 | #endif //AFUN_RT_TOP_ACTIVATION_H 22 | -------------------------------------------------------------------------------- /test/cmake/function.cmake: -------------------------------------------------------------------------------- 1 | function(add_new_test name) 2 | set(oneValueArgs WORK) 3 | set(multiValueArgs COMMAND PROPERTIES) 4 | cmake_parse_arguments(ant "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 5 | 6 | if (ant_WORK) 7 | set(work ${ant_WORK}) 8 | else() 9 | set(work ${CMAKE_BINARY_DIR}) 10 | endif() 11 | 12 | add_test(NAME ${name} COMMAND ${ant_COMMAND} WORKING_DIRECTORY ${work}) 13 | 14 | if (ant_PROPERTIES) 15 | set_tests_properties(${name} PROPERTIES ${ant_PROPERTIES}) 16 | endif() 17 | endfunction() 18 | 19 | function(set_test_label label) 20 | set(test ${ARGN}) 21 | set_tests_properties(${test} PROPERTIES LABELS "${label}") 22 | endfunction() 23 | -------------------------------------------------------------------------------- /include/tool/aFuntool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 文件名: tool.h 3 | * 目标: aFun tool公共API 4 | * aFunTool是aFun实用工具库, 内含aFun调用的实用函数 5 | */ 6 | 7 | #ifndef AFUN_AFUNTOOL_H 8 | #define AFUN_AFUNTOOL_H 9 | 10 | #include "tool_macro.h" 11 | 12 | #include "tool.h" 13 | #include "aFunToolExport.h" 14 | 15 | #include "tool_exception.h" 16 | #include "tool_stdio.h" 17 | #include "tool_exit.h" 18 | #include "tool_byte.h" 19 | #include "tool_dlc.h" 20 | #include "tool_directory.h" 21 | #include "tool_encoding.h" 22 | #include "tool_file.h" 23 | #include "tool_hash.h" 24 | #include "tool_md5.h" 25 | #include "tool_path.h" 26 | #include "tool_regex.h" 27 | #include "tool_str.h" 28 | #include "tool_time.h" 29 | #include "tool_log.h" 30 | 31 | #endif //AFUN_AFUNTOOL_H 32 | -------------------------------------------------------------------------------- /src/runtime/error_message.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_error_message.h" 2 | 3 | namespace aFunrt { 4 | ErrorMessage::ErrorMessage(std::string error_type_, std::string error_info_, aFuncore::Inter &inter) 5 | : inter{inter}, error_type{std::move(error_type_)}, error_info{std::move(error_info_)} { 6 | for (const auto activation : inter.getStack()) { 7 | if (activation->getFileLine() != 0) 8 | trackback.push_front({activation->getFilePath(), activation->getFileLine()}); 9 | } 10 | } 11 | 12 | void ErrorMessage::topProgress(aFuncore::Inter &inter_, aFuncore::Activation &){ 13 | inter_.getOutMessageStream().pushMessage("ERROR", new ErrorMessage(std::move(*this))); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/runtime/var_object.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_var_object.h" 2 | 3 | namespace aFunrt { 4 | Var::Var(Object *data_, aFuncore::Inter &inter) : Object("Var", inter), env{inter.getEnvironment()}, data{data_}{ 5 | 6 | } 7 | 8 | Var::Var(Object *data_, aFuncore::Environment &env_) : Object("Var", env_), env{env_}, data{data_}{ 9 | 10 | } 11 | 12 | void Var::linkObject(std::queue &queue) { 13 | queue.push(getData()); 14 | } 15 | 16 | aFuncore::Object *Var::getData() { 17 | std::unique_lock mutex{lock}; 18 | return data; 19 | } 20 | 21 | void Var::setData(Object *data_) { 22 | std::unique_lock mutex{lock}; 23 | data = data_; 24 | } 25 | } -------------------------------------------------------------------------------- /include/runtime/rt_var_object.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_VAR_OBJECT_H 2 | #define AFUN_VAR_OBJECT_H 3 | #include 4 | #include "aFunRuntimeExport.h" 5 | #include "aFuncore.h" 6 | 7 | namespace aFunrt { 8 | class AFUN_RT_EXPORT Var : public aFuncore::Object { 9 | public: 10 | aFuncore::Environment &env; 11 | 12 | Var(Object *data_, aFuncore::Inter &inter); 13 | Var(Object *data_, aFuncore::Environment &env_); 14 | ~Var() override = default; 15 | 16 | [[nodiscard]] virtual Object *getData(); 17 | virtual void setData(Object *data_); 18 | void linkObject(std::queue &queue) override; 19 | 20 | private: 21 | Object *data; 22 | }; 23 | } 24 | 25 | #endif //AFUN_VAR_OBJECT_H 26 | -------------------------------------------------------------------------------- /test/src/tool_regex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "aFuntool.h" 4 | 5 | int main() { 6 | aFuntool::Regex rg {"Hello嘿.*d"}; 7 | int rc1 = rg.match("Hello嘿World"); 8 | int rc2 = rg.match("Nossss"); 9 | 10 | if (rc1 != 1 || rc2 != 0) { 11 | printf("Failed rg1: %d/1, %d/0\n", rc1, rc2); 12 | return 1; 13 | } else 14 | printf("rg1 success\n"); 15 | 16 | aFuntool::Regex rg2 {"你|好"}; 17 | int rc3 = rg2.match("你"); 18 | int rc4 = rg2.match("Nosssss"); 19 | 20 | if (rc3 != 1 || rc4 != 0) { 21 | printf("Failed rg2: %d/1, %d/0\n", rc1, rc2); 22 | return 1; 23 | } else 24 | printf("rg2 success\n"); 25 | 26 | printf("All success\n"); 27 | return 0; 28 | } -------------------------------------------------------------------------------- /include/runtime/rt_normal_message.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_NORMAL_MESSAGE_H 2 | #define AFUN_RT_NORMAL_MESSAGE_H 3 | #include "aFunRuntimeExport.h" 4 | #include "aFuncore.h" 5 | #include "rt_top_message.h" 6 | 7 | namespace aFunrt { 8 | class AFUN_RT_EXPORT NormalMessage : public TopMessage { 9 | public: 10 | explicit NormalMessage(aFuncore::Object *obj_); 11 | AFUN_INLINE NormalMessage(NormalMessage &&msg) noexcept; 12 | ~NormalMessage() override; 13 | void topProgress(aFuncore::Inter &inter, aFuncore::Activation &activation) override; 14 | AFUN_INLINE aFuncore::Object *getObject(); 15 | 16 | private: 17 | aFuncore::Object *obj; 18 | }; 19 | } 20 | 21 | #include "rt_normal_message.inline.h" 22 | #endif //AFUN_RT_NORMAL_MESSAGE_H 23 | -------------------------------------------------------------------------------- /test/src/tool_utf.cpp: -------------------------------------------------------------------------------- 1 | #include "aFuntool.h" 2 | #include 3 | 4 | int main() { 5 | setlocale(LC_ALL, ""); 6 | 7 | #ifdef AFUN_WIN32_NO_CYGWIN 8 | wchar_t *tmp; 9 | const wchar_t *tmp2 = L"你好"; 10 | const char *tmp3 = "你好"; 11 | 12 | aFuntool::convertWideByte(&tmp, tmp3, CP_UTF8); 13 | 14 | std::wcout << tmp << std::endl; 15 | std::wcout << tmp2 << std::endl; 16 | 17 | for (size_t i = 0; i < wcslen(tmp); i++) 18 | printf("%x ", tmp[i]); 19 | printf("\n"); 20 | 21 | for (size_t i = 0; i < wcslen(tmp2); i++) 22 | printf("%x ", tmp2[i]); 23 | printf("\n"); 24 | 25 | for (size_t i = 0; i < strlen(tmp3); i++) 26 | printf("%x ", (unsigned int)tmp3[i]); 27 | printf("\n"); 28 | #endif 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /include/tool/tool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 文件名: macro.h 3 | * 目标: 定义公共宏 和 公共头文件 4 | */ 5 | 6 | #ifndef AFUN_TOOL_H 7 | #define AFUN_TOOL_H 8 | #include "tool_macro.h" 9 | 10 | #ifdef __cplusplus 11 | #include 12 | #include 13 | #include 14 | #else 15 | #include 16 | #include 17 | #include 18 | #endif 19 | 20 | #ifndef AFUN_TOOL_C 21 | namespace aFuntool { 22 | #endif 23 | 24 | #ifndef __cplusplus 25 | #include "stdbool.h" 26 | #endif 27 | 28 | AFUN_STATIC const char NUL = 0; 29 | typedef uint32_t FileLine; // 文件行号 30 | 31 | #ifdef __cplusplus 32 | typedef std::string FilePath; // 文件路径 33 | #endif 34 | 35 | #ifndef AFUN_TOOL_C 36 | } 37 | #endif 38 | 39 | #include "tool_mem.h" // 该定义需要放到下面 40 | 41 | #endif //AFUN_TOOL_H 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # C Language 2 | # Prerequisites 3 | *.d 4 | 5 | # Object files 6 | *.o 7 | *.ko 8 | *.obj 9 | *.elf 10 | 11 | # Linker output 12 | *.ilk 13 | *.map 14 | *.exp 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | 26 | # Shared objects (inc. Windows DLLs) 27 | *.dll 28 | *.so 29 | *.so.* 30 | *.dylib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | *.i*86 37 | *.x86_64 38 | *.hex 39 | 40 | # Debug files 41 | *.dSYM/ 42 | *.su 43 | *.idb 44 | *.pdb 45 | 46 | # Kernel Module Compile Results 47 | *.mod* 48 | *.cmd 49 | .tmp_versions/ 50 | modules.order 51 | Module.symvers 52 | Mkfile.old_sigset 53 | dkms.conf 54 | 55 | #IDE 56 | .idea 57 | .vs 58 | .vscode 59 | cmake-* 60 | out 61 | CMakePresets.json 62 | CMakeSettings.json -------------------------------------------------------------------------------- /include/runtime/rt_exception.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_EXCEPTION_H 2 | #define AFUN_RT_EXCEPTION_H 3 | #include "aFuntool.h" 4 | 5 | namespace aFunrt { 6 | class aFunrtException : public aFuntool::aFunException { 7 | public: 8 | AFUN_INLINE explicit aFunrtException(const std::string &msg); 9 | }; 10 | 11 | class RuntimeError : public aFunrtException { 12 | std::string type; 13 | public: 14 | AFUN_INLINE RuntimeError(const std::string &msg, std::string type); 15 | AFUN_INLINE const std::string &getType() const; 16 | }; 17 | 18 | class ArgumentError : public RuntimeError { 19 | std::string type; 20 | public: 21 | AFUN_INLINE ArgumentError(); 22 | }; 23 | } 24 | 25 | #include "rt_exception.inline.h" 26 | 27 | #endif //AFUN_RT_EXCEPTION_H 28 | -------------------------------------------------------------------------------- /include/runtime/rt_error_message.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_ERROR_MESSAGE_INLINE_H 2 | #define AFUN_RT_ERROR_MESSAGE_INLINE_H 3 | #include "rt_error_message.h" 4 | 5 | namespace aFunrt { 6 | ErrorMessage::ErrorMessage(ErrorMessage &&msg) noexcept 7 | : inter{msg.inter}, error_type{std::move(msg.error_type)}, 8 | error_info{std::move(msg.error_info)}, trackback{std::move(msg.trackback)}{ 9 | 10 | } 11 | 12 | std::string ErrorMessage::getErrorType() const { 13 | return error_type; 14 | } 15 | 16 | std::string ErrorMessage::getErrorInfo() const { 17 | return error_info; 18 | } 19 | 20 | const std::list &ErrorMessage::getTrackBack() const { 21 | return trackback; 22 | } 23 | } 24 | 25 | #endif //AFUN_RT_ERROR_MESSAGE_INLINE_H 26 | -------------------------------------------------------------------------------- /include/runtime/rt_varspace_object.template.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_VARSPACE_OBJECT_TEMPLATE_H 2 | #define AFUN_RT_VARSPACE_OBJECT_TEMPLATE_H 3 | 4 | #include "rt_varspace_object.h" 5 | 6 | namespace aFunrt { 7 | template 8 | void VarSpace::forEach(Callable func, T...arg) { 9 | std::unique_lock mutex{lock}; 10 | for (auto &tmp : var) { 11 | mutex.unlock(); 12 | func(tmp.second, arg...); 13 | mutex.lock(); 14 | } 15 | } 16 | 17 | template 18 | void VarSpace::forEachLock(Callable func, T...arg) { 19 | std::unique_lock mutex{lock}; 20 | for (auto &tmp : var) 21 | func(tmp.second, arg...); 22 | } 23 | } 24 | 25 | #endif //AFUN_RT_VARSPACE_OBJECT_TEMPLATE_H 26 | -------------------------------------------------------------------------------- /include/tool/tool_file.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_FILE_H 2 | #define AFUN_TOOL_FILE_H 3 | #include "aFunToolExport.h" 4 | 5 | #ifdef __cplusplus 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | /* 文件处理工具 */ 12 | #ifndef AFUN_TOOL_C 13 | namespace aFuntool { 14 | #endif 15 | 16 | #ifdef __cplusplus 17 | AFUN_TOOL_C_EXPORT_FUNC int checkFile(const std::string &path); 18 | AFUN_TOOL_C_EXPORT_FUNC time_t getFileMTime(const std::string &path); 19 | AFUN_TOOL_C_EXPORT_FUNC uintmax_t getFileSize(const std::string &path); 20 | AFUN_TOOL_EXPORT FILE *fileOpen(const std::string &path_, const char *mode_); 21 | #endif 22 | AFUN_TOOL_C_EXPORT_FUNC FILE *fileOpen(const char *path_, const char *mode_); 23 | AFUN_TOOL_C_EXPORT_FUNC int fileClose(FILE *file); 24 | 25 | #ifndef AFUN_TOOL_C 26 | } 27 | #endif 28 | 29 | #endif //AFUN_TOOL_FILE_H 30 | -------------------------------------------------------------------------------- /src/runtime/exe_activation.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_exe_activation.h" 2 | #include "rt_exception.h" 3 | #include "rt_normal_message.h" 4 | #include "rt_error_message.h" 5 | #include "rt_logger.h" 6 | 7 | namespace aFunrt { 8 | NormalActivation::ActivationStatus ExeActivation::getCode(const aFuncode::Code::ByteCode *&code){ 9 | code = next; 10 | if (code == nullptr) 11 | return as_end; 12 | 13 | if (!first) { 14 | auto msg = down.getMessage("NORMAL"); 15 | if (msg == nullptr) 16 | return as_end; 17 | else 18 | down.popMessage("NORMAL"); 19 | delete msg; 20 | } 21 | 22 | first = false; 23 | line = code->getFileLine(); 24 | path = code->getFilePath(); 25 | next = code->toNext(); 26 | return as_run; 27 | } 28 | } -------------------------------------------------------------------------------- /lang/tr/base.py: -------------------------------------------------------------------------------- 1 | help_info = r'''[option] 2 | help 3 | -v Show version info 4 | -h Show help page 5 | run 6 | The first parameter is the running file 7 | The following parameters are command line parameters 8 | cl 9 | -e/--eval Run argument as code 10 | -f/--file Run file (.aun or .aub) 11 | -s/--source Run source file 12 | -b/--byte Run byte-code file 13 | --no-aub Do not save byte-code after run source file 14 | --no-cl Do not use command line 15 | The free parameter before -- will be interpreted as the -f parameter 16 | The free parameter after -- will be interpreted as the command line parameters 17 | build 18 | -o File output path 19 | -p File output dir 20 | -f Force build 21 | 22 | [Github page] 23 | ''' -------------------------------------------------------------------------------- /include/runtime/rt_func_object.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_FUNC_OBJECT_INLINE_H 2 | #define AFUN_RT_FUNC_OBJECT_INLINE_H 3 | #include "rt_func_object.h" 4 | 5 | namespace aFunrt { 6 | Function::CallFunction::ArgCodeList::ArgCodeList(const aFuncode::Code::ByteCode *code_) : code{code_}, ret{nullptr} { 7 | 8 | } 9 | 10 | Function::CallFunction::ArgCodeList::~ArgCodeList() { 11 | if (ret != nullptr) 12 | ret->delReference(); 13 | } 14 | 15 | aFuncore::Object *Function::CallFunction::ArgCodeList::setObject(Object *res) { 16 | Object *obj = ret; 17 | ret = res; 18 | if (ret != nullptr) 19 | ret->addReference(); 20 | return obj; 21 | } 22 | 23 | aFuncore::Object *Function::CallFunction::ArgCodeList::getObject() { 24 | return ret; 25 | } 26 | }; 27 | 28 | 29 | #endif //AFUN_RT_FUNC_OBJECT_INLINE_H 30 | -------------------------------------------------------------------------------- /include/tool/tool_exit.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_EXIT_H 2 | #define AFUN_EXIT_H 3 | #ifdef __cplusplus 4 | 5 | #include 6 | #include "aFunToolExport.h" 7 | #include "tool_macro.h" 8 | 9 | #ifndef AFUN_TOOL_C 10 | namespace aFuntool { 11 | #endif 12 | 13 | typedef std::function aFunExitFunc; 14 | typedef std::function ExitFunc; 15 | 16 | AFUN_TOOL_EXPORT void aFunExit(int exit_code) noexcept(false); 17 | [[noreturn]] AFUN_TOOL_EXPORT void aFunExitReal(int exit_code); 18 | AFUN_TOOL_EXPORT bool aFunTryExitPseudo(); 19 | AFUN_TOOL_EXPORT void aFunExitPseudo(); 20 | 21 | AFUN_TOOL_EXPORT bool aFunAtExitTry(const aFunExitFunc &func, void *data); 22 | AFUN_TOOL_EXPORT void aFunAtExit(const aFunExitFunc &func, void *data); 23 | AFUN_TOOL_EXPORT void aFunAtExit(const ExitFunc& func); 24 | 25 | #ifndef AFUN_TOOL_C 26 | } 27 | #endif 28 | 29 | #endif 30 | #endif //AFUN_EXIT_H 31 | -------------------------------------------------------------------------------- /include/tool/tool_macro.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_MACRO_H 2 | #define AFUN_TOOL_MACRO_H 3 | 4 | #ifdef __cplusplus 5 | #define AFUN_STATIC [[maybe_unused]] static 6 | #define AFUN_INLINE [[maybe_unused]] inline 7 | #else 8 | #ifdef _MSC_VER 9 | #define AFUN_STATIC static 10 | #define AFUN_INLINE inline 11 | #else 12 | #define AFUN_STATIC __attribute__((unused)) static 13 | #define AFUN_INLINE __attribute__((unused)) inline 14 | #endif 15 | #endif 16 | 17 | #define AFUN_NULL ((void)0) 18 | 19 | #ifdef __cplusplus 20 | #ifdef AFUN_TOOL_C 21 | #define AFUN_TOOL_C_EXPORT_FUNC extern "C" 22 | #define AFUN_TOOL_C_EXPORT_VAR extern "C" 23 | #else 24 | #define AFUN_TOOL_C_EXPORT_FUNC AFUN_TOOL_EXPORT 25 | #define AFUN_TOOL_C_EXPORT_VAR AFUN_TOOL_EXPORT extern 26 | #endif 27 | #else 28 | #define AFUN_TOOL_C_EXPORT_FUNC AFUN_TOOL_EXPORT 29 | #define AFUN_TOOL_C_EXPORT_VAR AFUN_TOOL_EXPORT extern 30 | #endif 31 | 32 | #endif //AFUN_TOOL_MACRO_H 33 | -------------------------------------------------------------------------------- /include/tool/tool_md5.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_MD5_H 2 | #define AFUN_TOOL_MD5_H 3 | #include "aFunToolExport.h" 4 | #include "tool_macro.h" 5 | 6 | /* md5计算工具 */ 7 | 8 | #ifndef AFUN_TOOL_C 9 | namespace aFuntool { 10 | #endif 11 | 12 | AFUN_STATIC const size_t READ_DATA_SIZE = 1024; 13 | AFUN_STATIC const size_t MD5_SIZE = 16; 14 | AFUN_STATIC const size_t MD5_STR_LEN = 16 * 2; 15 | AFUN_STATIC const size_t MD5_STRING = (16 * 2) + 1; 16 | 17 | typedef struct MD5_CTX MD5_CTX; 18 | 19 | AFUN_TOOL_C_EXPORT_FUNC MD5_CTX *MD5Init(); 20 | AFUN_TOOL_C_EXPORT_FUNC void MD5Final(MD5_CTX *context, unsigned char digest[16]); 21 | AFUN_TOOL_C_EXPORT_FUNC void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int input_len); 22 | 23 | #ifdef __cplusplus 24 | template 25 | T getFileMd5 (T &path) noexcept(false) ; 26 | #endif 27 | 28 | #ifndef AFUN_TOOL_C 29 | } 30 | #endif 31 | 32 | #endif //AFUN_TOOL_MD5_H 33 | -------------------------------------------------------------------------------- /include/runtime/rt_exe_activation.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_EXE_ACTIVATION_H 2 | #define AFUN_RT_EXE_ACTIVATION_H 3 | #include "aFunRuntimeExport.h" 4 | #include "aFuncore.h" 5 | #include "rt_func_object.h" 6 | #include "rt_normal_activation.h" 7 | 8 | namespace aFunrt { 9 | class AFUN_RT_EXPORT ExeActivation : public NormalActivation { 10 | public: 11 | AFUN_INLINE ExeActivation(const aFuncode::Code &code, aFuncore::Inter &inter_); 12 | AFUN_INLINE ExeActivation(const aFuncode::Code::ByteCode *code, aFuncore::Inter &inter_); 13 | ActivationStatus getCode(const aFuncode::Code::ByteCode *&code) override; 14 | [[nodiscard]] AFUN_INLINE const aFuncode::Code::ByteCode *getStart() const; 15 | 16 | private: 17 | const aFuncode::Code::ByteCode *start; 18 | const aFuncode::Code::ByteCode *next; 19 | bool first=true; 20 | }; 21 | } 22 | 23 | #include "rt_exe_activation.inline.h" 24 | #endif //AFUN_RT_EXE_ACTIVATION_H 25 | -------------------------------------------------------------------------------- /include/parser/parser_reader.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_PARSER_READER_INLINE_H 2 | #define AFUN_PARSER_READER_INLINE_H 3 | #include "parser_reader.h" 4 | 5 | namespace aFunparser { 6 | Reader::Reader(aFuntool::FilePath path_, aFuntool::FileLine line_) 7 | : buf{aFuntool::safeCalloc(DEFAULT_BUF_SIZE + 1)}, buf_size{DEFAULT_BUF_SIZE}, read{buf}, read_end{false}, 8 | read_error{false}, line{line_}, path{std::move(path_)} { 9 | 10 | } 11 | 12 | size_t Reader::countRead() const { 13 | return read - buf; 14 | } 15 | 16 | bool Reader::isEnd() const { 17 | return read_end; 18 | } 19 | 20 | bool Reader::isError() const { 21 | return read_error; 22 | } 23 | 24 | aFuntool::FileLine Reader::getFileLine() const { 25 | return line; 26 | } 27 | 28 | const aFuntool::FilePath &Reader::getFilePath() const { 29 | return path; 30 | } 31 | } 32 | 33 | #endif //AFUN_PARSER_READER_INLINE_H 34 | -------------------------------------------------------------------------------- /test/src/core_up_msg.cpp: -------------------------------------------------------------------------------- 1 | #include "core_message_stream.h" 2 | 3 | int main() { 4 | auto *um = new aFuncore::UpMessageStream(nullptr); 5 | um->pushMessage("test-1", new aFuncore::Message()); 6 | std::cout << um->getMessage("test-1") << std::endl; 7 | 8 | auto *um2 = new aFuncore::UpMessageStream(um); 9 | um2->pushMessage("test-2", new aFuncore::Message()); 10 | std::cout << um2->getMessage("test-1") << std::endl; 11 | std::cout << um2->getMessage("test-2") << std::endl; 12 | 13 | auto msg1 = um2->popMessage("test-2"); 14 | auto msg2 = um2->popMessage("test-1"); 15 | 16 | std::cout << msg1 << ", " << msg2 << std::endl; 17 | 18 | delete msg1; 19 | delete msg2; 20 | delete um2; 21 | 22 | std::cout << um->getMessage("test-1") << std::endl; 23 | std::cout << um->getMessage("test-2") << std::endl; 24 | 25 | delete um; 26 | return 0; 27 | } -------------------------------------------------------------------------------- /test/src/tool_dlc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "aFuntool.h" 4 | 5 | int test_func() { 6 | return 100; 7 | } 8 | 9 | int main(int argc, char **argv) { 10 | atexit(aFuntool::DlcHandle::dlcExit); 11 | 12 | if (argc != 2) 13 | return EXIT_FAILURE; 14 | 15 | char *lib = argv[1]; 16 | aFuntool::DlcHandle dlc {lib, RTLD_NOW}; // TEST_LIB_PATH 传进来的分隔符 都是 "/" 17 | if (dlc.isOpen()) { 18 | fprintf(stderr, "libary not found!\n"); 19 | return EXIT_FAILURE; 20 | } 21 | 22 | typedef int (func)(int a); 23 | typedef int (test)(); 24 | 25 | auto a = dlc.getSymbol("num"); 26 | auto fun = dlc.getSymbol("test"); 27 | auto test_fun = aFuntool::DlcSymbol(test_func, nullptr); 28 | 29 | int test_func_result = test_fun.getSymbol()(); 30 | 31 | printf("a = %d, test = %d\n", *(a.getSymbol()), fun.getSymbol()(test_func_result)); 32 | 33 | dlc.close(); 34 | return EXIT_SUCCESS; 35 | } -------------------------------------------------------------------------------- /include/tool/tool_regex.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_REGEX 2 | #define AFUN_TOOL_REGEX 3 | #ifdef __cplusplus 4 | 5 | #define PCRE2_CODE_UNIT_WIDTH 8 6 | #include "pcre2.h" 7 | #include "tool_macro.h" 8 | 9 | #ifndef AFUN_TOOL_C 10 | namespace aFuntool { 11 | #endif 12 | 13 | class AFUN_TOOL_EXPORT Regex { // 整个对象都是inline的, 不需要Export符号 14 | std::string pattern; // 正则表达式的字符串 15 | pcre2_code *re; // 正则表达式 16 | public: 17 | explicit Regex(std::string pattern_) noexcept(false); 18 | AFUN_INLINE Regex(const Regex ®ex) noexcept; 19 | AFUN_INLINE Regex(Regex &®ex) noexcept; 20 | AFUN_INLINE ~Regex() noexcept; 21 | Regex &operator=(const Regex ®ex)=delete; 22 | Regex &operator=(Regex &®ex)=delete; 23 | 24 | [[nodiscard]] bool match(const std::string &subject) const; 25 | }; 26 | 27 | #ifndef AFUN_TOOL_C 28 | } 29 | #endif 30 | 31 | #include "tool_regex.inline.h" 32 | 33 | #endif 34 | #endif //AFUN_TOOL_REGEX 35 | -------------------------------------------------------------------------------- /include/tool/tool_directory.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_DIRECTORY_H 2 | #define AFUN_TOOL_DIRECTORY_H 3 | #ifdef __cplusplus 4 | #include 5 | #include "aFunToolExport.h" 6 | 7 | /* 文件处理工具 */ 8 | #ifndef AFUN_TOOL_C 9 | namespace aFuntool { 10 | #endif 11 | 12 | AFUN_TOOL_EXPORT std::string joinPath(const std::string &path, const std::string &name, const std::string &suffix); 13 | AFUN_TOOL_EXPORT std::string getFileName(const std::string &path); 14 | AFUN_TOOL_EXPORT std::string getFilePathName(const std::string &path); 15 | AFUN_TOOL_EXPORT std::string getFilePath(const std::string &path_1, int dep); 16 | AFUN_TOOL_EXPORT std::string getFileSuffix(const std::string &path); 17 | AFUN_TOOL_EXPORT std::string fileNameToVar(const std::string &name); 18 | AFUN_TOOL_EXPORT std::string findPath(const std::string &path, const std::string &env); 19 | AFUN_TOOL_EXPORT std::string getExePath(); 20 | 21 | #ifndef AFUN_TOOL_C 22 | } 23 | #endif 24 | 25 | #endif 26 | #endif //AFUN_TOOL_DIRECTORY_H 27 | -------------------------------------------------------------------------------- /include/interface/it_reader.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_IT_READER_H 2 | #define AFUN_IT_READER_H 3 | #include 4 | #include "aFunlangExport.h" 5 | #include "aFunparser.h" 6 | #include "init.h" 7 | 8 | namespace aFunit { 9 | class AFUN_LANG_EXPORT StringReader : public aFunparser::Reader { 10 | public: 11 | AFUN_INLINE StringReader(std::string str_, const aFuntool::FilePath &path_); 12 | size_t readText(char *dest, size_t read_len, ReadMode &mode) override; 13 | private: 14 | std::string str; 15 | size_t index; 16 | size_t len; 17 | }; 18 | 19 | class AFUN_LANG_EXPORT FileReader : public aFunparser::Reader { 20 | public: 21 | AFUN_INLINE explicit FileReader(const aFuntool::FilePath &path_) noexcept(false); 22 | size_t readText(char *dest, size_t read_len, ReadMode &mode) override; 23 | private: 24 | FILE *file; 25 | bool no_first; 26 | }; 27 | 28 | } 29 | 30 | #include "it_reader.inline.h" 31 | 32 | #endif //AFUN_IT_READER_H 33 | -------------------------------------------------------------------------------- /include/parser/parser_syntax.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_PARSER_SYNTAX_INLINE_H 2 | #define AFUN_PARSER_SYNTAX_INLINE_H 3 | #include "parser_syntax.h" 4 | 5 | namespace aFunparser { 6 | Parser::Parser(Reader &reader_) 7 | : reader{reader_}, 8 | lexical{lex_begin, TK_PREFIX, 0, 0, false, false}, 9 | syntactic{false, TK_PREFIX, "", false}{ 10 | 11 | reader.readFirstWord(); 12 | } 13 | 14 | Parser::ParserEvent Parser::popEvent() { 15 | ParserEvent pop = event.front(); 16 | event.pop(); 17 | return pop; 18 | } 19 | 20 | size_t Parser::countEvent() const { 21 | return event.size(); 22 | } 23 | 24 | void Parser::pushEvent(const ParserEvent &new_event) { 25 | event.push(new_event); 26 | } 27 | 28 | void Parser::pushEvent(ParserEvent &&new_event) { 29 | event.push(new_event); 30 | } 31 | 32 | const Parser::ParserEvent &Parser::checkEvent() const { 33 | return event.front(); 34 | } 35 | } 36 | 37 | #endif //AFUN_PARSER_SYNTAX_INLINE_H 38 | -------------------------------------------------------------------------------- /src/tool/__md5.h: -------------------------------------------------------------------------------- 1 | #ifndef TOOL_MD5_H_ 2 | #define TOOL_MD5_H_ 3 | 4 | #define F(x,y,z) ((x & y) | (~x & z)) 5 | #define G(x,y,z) ((x & z) | (y & ~z)) 6 | #define H(x,y,z) (x^y^z) 7 | #define I(x,y,z) (y ^ (x | ~z)) 8 | #define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) 9 | #define FF(a,b,c,d,x,s,ac) \ 10 | do { \ 11 | a += F(b,c,d) + x + ac; \ 12 | a = ROTATE_LEFT(a, (unsigned)s); \ 13 | a += b; \ 14 | } while(0) 15 | 16 | #define GG(a,b,c,d,x,s,ac) \ 17 | do { \ 18 | a += G(b,c,d) + x + ac; \ 19 | a = ROTATE_LEFT(a, (unsigned)s); \ 20 | a += b; \ 21 | } while(0) 22 | 23 | #define HH(a,b,c,d,x,s,ac) \ 24 | do { \ 25 | a += H(b,c,d) + x + ac; \ 26 | a = ROTATE_LEFT(a, (unsigned)s); \ 27 | a += b; \ 28 | } while(0) 29 | 30 | #define II(a,b,c,d,x,s,ac) \ 31 | do { \ 32 | a += I(b,c,d) + x + ac; \ 33 | a = ROTATE_LEFT(a, (unsigned)s); \ 34 | a += b; \ 35 | } while(0) 36 | 37 | #endif //TOOL_MD5_H_ 38 | -------------------------------------------------------------------------------- /include/tool/tool_path.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_PATH_H 2 | #define AFUN_TOOL_PATH_H 3 | #include "tool_macro.h" 4 | #include "tool.h" 5 | 6 | /* 路径工具 */ 7 | #ifdef AFUN_WIN32_NO_CYGWIN 8 | 9 | #ifndef AFUN_TOOL_C 10 | namespace aFuntool { 11 | #endif 12 | 13 | AFUN_STATIC const char *SEP = "\\"; 14 | AFUN_STATIC const char SEP_CH = '\\'; 15 | 16 | #ifndef AFUN_TOOL_C 17 | } 18 | #endif 19 | 20 | #else 21 | 22 | #ifndef AFUN_TOOL_C 23 | namespace aFuntool { 24 | #endif 25 | 26 | AFUN_STATIC const char *SEP = "/"; 27 | AFUN_STATIC const char SEP_CH = '/'; 28 | 29 | #ifndef AFUN_TOOL_C 30 | } 31 | #endif 32 | 33 | #endif 34 | 35 | #ifndef AFUN_TOOL_C 36 | namespace aFuntool { 37 | #endif 38 | 39 | AFUN_STATIC const char *SHARED_PREFIX = AFUN_SHARE_PREFIX; 40 | AFUN_STATIC const char *SHARED_SUFFIX = AFUN_SHARE_SUFFIX; 41 | 42 | AFUN_STATIC const char *STATIC_PREFIX = AFUN_STATIC_PREFIX; 43 | AFUN_STATIC const char *STATIC_SUFFIX = AFUN_STATIC_SUFFIX; 44 | 45 | AFUN_STATIC const char *EXE_SUFFIX = AFUN_EXE_SUFFIX; 46 | 47 | #ifndef AFUN_TOOL_C 48 | } 49 | #endif 50 | 51 | #endif //AFUN_TOOL_PATH_H 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 aFun-org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /include/runtime/rt_error_message.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_ERROR_MESSAGE_H 2 | #define AFUN_RT_ERROR_MESSAGE_H 3 | #include "aFunRuntimeExport.h" 4 | #include "aFuncore.h" 5 | #include "rt_top_message.h" 6 | 7 | namespace aFunrt { 8 | class AFUN_RT_EXPORT ErrorMessage : public TopMessage { 9 | public: 10 | struct TrackBack { 11 | const aFuntool::FilePath path; 12 | aFuntool::FileLine line; 13 | }; 14 | 15 | explicit ErrorMessage(std::string error_type_, std::string error_info_, aFuncore::Inter &inter); 16 | AFUN_INLINE ErrorMessage(ErrorMessage &&msg) noexcept; 17 | void topProgress(aFuncore::Inter &inter_, aFuncore::Activation &activation) override; 18 | [[nodiscard]] AFUN_INLINE std::string getErrorType() const; 19 | [[nodiscard]] AFUN_INLINE std::string getErrorInfo() const; 20 | [[nodiscard]] AFUN_INLINE const std::list &getTrackBack() const; 21 | 22 | private: 23 | aFuncore::Inter &inter; 24 | 25 | std::string error_type; 26 | std::string error_info; 27 | std::list trackback; 28 | }; 29 | } 30 | 31 | #include "rt_error_message.inline.h" 32 | #endif //AFUN_RT_ERROR_MESSAGE_H 33 | -------------------------------------------------------------------------------- /include/core/core_activation.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_ACTIVATION_H 2 | #define AFUN_CORE_ACTIVATION_H 3 | #include "aFuntool.h" 4 | #include "aFunCoreExport.h" 5 | #include "core_message_stream.h" 6 | #include "aFuncode.h" 7 | 8 | namespace aFuncore { 9 | class Activation { 10 | public: 11 | typedef enum ActivationStatus { 12 | as_run = 0, 13 | as_end = 1, 14 | as_end_run = 2, 15 | } ActivationStatus; 16 | 17 | Activation() = default; 18 | virtual ~Activation() = default; 19 | Activation(const Activation &) = delete; 20 | Activation &operator=(Activation &) = delete; 21 | 22 | virtual ActivationStatus getCode(const aFuncode::Code::ByteCode *&code) = 0; 23 | virtual void runCode(const aFuncode::Code::ByteCode *code) = 0; 24 | virtual void endRun() = 0; 25 | 26 | [[nodiscard]] virtual UpMessageStream &getUpStream() = 0; 27 | [[nodiscard]] virtual DownMessageStream &getDownStream() = 0; 28 | 29 | [[nodiscard]] virtual aFuntool::FileLine getFileLine() = 0; 30 | [[nodiscard]] virtual const aFuntool::FilePath &getFilePath() = 0; 31 | }; 32 | 33 | 34 | } 35 | 36 | #endif //AFUN_CORE_ACTIVATION_H 37 | -------------------------------------------------------------------------------- /include/tool/tool_exception.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_EXCEPTION_INLINE_H 2 | #define AFUN_TOOL_EXCEPTION_INLINE_H 3 | #ifdef __cplusplus 4 | 5 | #include "tool_exception.h" 6 | 7 | #ifndef AFUN_TOOL_C 8 | namespace aFuntool { 9 | #endif 10 | 11 | aFunException::aFunException(std::string msg) : message{std::move(msg)} { 12 | 13 | } 14 | 15 | const std::string &aFunException::getMessage() const { 16 | return message; 17 | } 18 | 19 | aFuntoolException::aFuntoolException(const std::string &msg) : aFunException{msg} { 20 | 21 | } 22 | 23 | FileOpenException::FileOpenException(const FilePath &file) : aFuntoolException("File cannot open: " + file) { 24 | 25 | } 26 | 27 | RegexException::RegexException(const std::string &msg) : aFuntoolException("Regex error: " + msg) { 28 | 29 | } 30 | 31 | LogFatalError::LogFatalError(const char *msg) : aFuntoolException(msg) { 32 | 33 | } 34 | 35 | Exit::Exit(int exit_code_) : aFuntoolException("Exit by user"), exit_code{exit_code_} { 36 | 37 | } 38 | 39 | int Exit::getExitCode() const { 40 | return exit_code; 41 | } 42 | 43 | #ifndef AFUN_TOOL_C 44 | } 45 | #endif 46 | 47 | #endif 48 | #endif //AFUN_TOOL_EXCEPTION_INLINE_H 49 | -------------------------------------------------------------------------------- /include/runtime/rt_normal_activation.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_NORMAL_ACTIVATION_INLINE_H 2 | #define AFUN_RT_NORMAL_ACTIVATION_INLINE_H 3 | 4 | #include "rt_normal_activation.h" 5 | 6 | namespace aFunrt { 7 | NormalActivation::VarList &NormalActivation::getVarlist(){ 8 | return varlist; 9 | } 10 | 11 | NormalActivation::VarList::VarList() : varspace{} { 12 | 13 | } 14 | 15 | NormalActivation::VarList::VarList(VarList &&new_varlist) noexcept : varspace{std::move(new_varlist.varspace)} { 16 | 17 | } 18 | 19 | NormalActivation::VarList &NormalActivation::VarList::operator=(VarList &&new_varlist) noexcept { 20 | clear(); 21 | varspace = std::move(new_varlist.varspace); 22 | return *this; 23 | } 24 | 25 | void NormalActivation::VarList::push(VarSpace *varspace_) { 26 | varspace_->addReference(); 27 | varspace.push_front(varspace_); 28 | } 29 | 30 | size_t NormalActivation::VarList::count() { 31 | return varspace.size(); 32 | } 33 | 34 | aFuncore::Object *NormalActivation::VarList::findObject(const std::string &name) { 35 | Var *var = findVar(name); 36 | return var ? var->getData() : nullptr; 37 | } 38 | } 39 | 40 | 41 | #endif //AFUN_RT_NORMAL_ACTIVATION_INLINE_H 42 | -------------------------------------------------------------------------------- /include/tool/tool_byte.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_BYTE_H 2 | #define AFUN_TOOL_BYTE_H 3 | #include "aFunToolExport.h" 4 | 5 | #ifdef __cplusplus 6 | #include // NOLINT 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | #ifndef AFUN_TOOL_C 13 | namespace aFuntool { 14 | #endif 15 | 16 | enum EndianType { 17 | little_endian = 0, 18 | big_endian 19 | }; 20 | 21 | AFUN_TOOL_C_EXPORT_VAR enum EndianType endian; 22 | AFUN_TOOL_C_EXPORT_VAR enum EndianType save_as; 23 | 24 | AFUN_TOOL_C_EXPORT_FUNC void getEndian(); 25 | 26 | #ifdef __cplusplus 27 | template 28 | bool byteWriteInt(FILE *file, T num); 29 | #endif 30 | 31 | AFUN_TOOL_C_EXPORT_FUNC bool byteWriteStr(FILE *file, const char *str); 32 | 33 | #ifdef __cplusplus 34 | AFUN_TOOL_EXPORT bool byteWriteStr(FILE *file, const std::string &str); 35 | #endif 36 | 37 | #ifdef __cplusplus 38 | template 39 | bool byteReadInt(FILE *file, T *num); 40 | #endif 41 | 42 | AFUN_TOOL_EXPORT bool byteReadStr(FILE *file, char **str); 43 | #ifdef __cplusplus 44 | AFUN_TOOL_C_EXPORT_FUNC bool byteReadStr(FILE *file, std::string &str); 45 | #endif 46 | 47 | #ifndef AFUN_TOOL_C 48 | } 49 | #endif 50 | 51 | #include "tool_byte.template.h" 52 | 53 | #endif //AFUN_TOOL_BYTE_H 54 | -------------------------------------------------------------------------------- /include/tool/tool_mem.template.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_MEM_TEMPLATE_H 2 | #define AFUN_TOOL_MEM_TEMPLATE_H 3 | #ifdef __cplusplus 4 | 5 | #include 6 | #include "tool_log.h" 7 | #include "tool_exit.h" 8 | #include "tool_logger.h" 9 | 10 | /* 取代calloc函数 */ 11 | #ifndef AFUN_TOOL_C 12 | namespace aFuntool { 13 | #endif 14 | 15 | template 16 | T *safeFree(T *ptr) {if (ptr != nullptr) free((void *)ptr); return nullptr;} 17 | 18 | template 19 | T *safeCalloc(size_t n, size_t size){ 20 | T *re = (T *)calloc(n, size); 21 | if (re == nullptr) { 22 | if (aFunSysLogger) 23 | fatalErrorLog(aFunSysLogger, EXIT_FAILURE, "The memory error"); 24 | else 25 | aFunExit(EXIT_FAILURE); 26 | } 27 | return re; 28 | } 29 | 30 | template 31 | T *safeCalloc(size_t n = 1){ 32 | T *re = (T *)calloc(n, sizeof(T)); // 自动推断类型 33 | if (re == nullptr) { 34 | if (aFunSysLogger) 35 | fatalErrorLog(aFunSysLogger, EXIT_FAILURE, "The memory error"); 36 | else 37 | aFunExit(EXIT_FAILURE); 38 | } 39 | return re; 40 | } 41 | 42 | #ifndef AFUN_TOOL_C 43 | } 44 | #endif 45 | 46 | #endif 47 | #endif //AFUN_TOOL_MEM_TEMPLATE_H 48 | -------------------------------------------------------------------------------- /cmake/export_head.cmake: -------------------------------------------------------------------------------- 1 | include(GenerateExportHeader) 2 | 3 | function(define_export_head shared static file_name base_name) 4 | generate_export_header(${shared} 5 | EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}/${file_name}.h" # 导出的位置 6 | BASE_NAME "${base_name}") 7 | target_compile_definitions(${static} PUBLIC "${base_name}_STATIC_DEFINE") 8 | set_property(TARGET ${shared} 9 | PROPERTY C_VISIBILITY_PRESET "hidden") 10 | set_property(TARGET ${shared} 11 | PROPERTY VISIBILITY_INLINES_HIDDEN TRUE) 12 | set_property(TARGET ${static} 13 | PROPERTY C_VISIBILITY_PRESET "default") 14 | set_property(TARGET ${static} 15 | PROPERTY VISIBILITY_INLINES_HIDDEN FALSE) 16 | endfunction() 17 | 18 | define_export_head(tool-shared tool-static aFunToolExport AFUN_TOOL) 19 | define_export_head(code-shared code-static aFunCodeExport AFUN_CODE) 20 | define_export_head(core-shared core-static aFunCoreExport AFUN_CORE) 21 | define_export_head(parser-shared parser-static aFunParserExport AFUN_PARSER) 22 | define_export_head(rt-shared rt-static aFunRuntimeExport AFUN_RT) 23 | define_export_head(it-shared it-static aFunlangExport AFUN_LANG) 24 | 25 | # 两个库需要额外定义 26 | target_compile_definitions(tool-static-c PUBLIC AFUN_TOOL_STATIC_DEFINE) 27 | target_compile_definitions(tool-shared-c PRIVATE tool_shared_EXPORTS) 28 | -------------------------------------------------------------------------------- /include/core/core_environment.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_ENVIRONMENT_H 2 | #define AFUN_CORE_ENVIRONMENT_H 3 | #include 4 | #include 5 | #include "aFunCoreExport.h" 6 | #include "aFuntool.h" 7 | #include "core_env_var.h" 8 | #include "core_activation.h" 9 | #include "core_object.h" 10 | 11 | namespace aFuncore { 12 | class Inter; 13 | 14 | class AFUN_CORE_EXPORT Environment { 15 | friend class Object; 16 | friend class Inter; 17 | 18 | public: 19 | explicit Environment(int argc = 0, char **argv = nullptr); 20 | ~Environment() noexcept(false); 21 | Environment(Environment &) = delete; 22 | Environment &operator=(Environment &) = delete; 23 | 24 | AFUN_INLINE size_t operator++(); 25 | AFUN_INLINE size_t operator--(); 26 | AFUN_INLINE size_t operator++(int); 27 | AFUN_INLINE size_t operator--(int); 28 | 29 | [[nodiscard]] AFUN_INLINE EnvVarSpace &getEnvVarSpace(); 30 | private: 31 | std::mutex lock; 32 | size_t reference; // 引用计数 33 | bool destruct; 34 | std::list gc; 35 | Inter &gc_inter; /* 需要在lock和reference后初始化 */ 36 | std::thread gc_thread; 37 | void gcThread(); 38 | 39 | protected: // 位于 mutex 之下 40 | EnvVarSpace &env_var; 41 | }; 42 | } 43 | 44 | 45 | #include "core_environment.inline.h" 46 | #endif //AFUN_CORE_ENVIRONMENT_H 47 | -------------------------------------------------------------------------------- /test/src/code_create.cpp: -------------------------------------------------------------------------------- 1 | #include "aFuncode.h" 2 | 3 | int main() { 4 | { 5 | auto start = aFuncode::Code("test.aun"); 6 | start.getByteCode()->connect(new aFuncode::Code::ByteCode(start, "Test", 1))->connect( 7 | new aFuncode::Code::ByteCode(start, 8 | aFuncode::Code::ByteCode::block_p, 9 | new aFuncode::Code::ByteCode(start, 10 | aFuncode::Code::ByteCode::block_p, 11 | new aFuncode::Code::ByteCode(start, 12 | "Test3", 13 | 2), 2), 2)); 14 | start.display(); 15 | std::string md5 = start.getMD5_v1(); 16 | printf("md5: %s\n", md5.c_str()); 17 | 18 | aFuntool::getEndian(); 19 | 20 | start.writeByteCode("test.aun"); 21 | } 22 | 23 | { 24 | aFuncode::Code start = aFuncode::Code("test.aun"); 25 | start.readByteCode("test.aun"); 26 | 27 | start.display(); 28 | std::string md5 = start.getMD5_v1(); 29 | printf("md5: %s\n", md5.c_str()); 30 | } 31 | 32 | return 0; 33 | } -------------------------------------------------------------------------------- /lang/tr/zh_cn.py: -------------------------------------------------------------------------------- 1 | help_info = r'''[参数] 2 | help 3 | -v 显示版本信息 4 | -h 显示帮助信息 5 | run 6 | 第一个参数为运行文件 7 | 其后参数为命令行参数 8 | cl 9 | -e/--eval 运行指定代码(来自参数) 10 | -f/--file 运行文件 (.aun or .aub) 11 | -s/--source 运行源代码 12 | -b/--byte 运行字节码 13 | --no-aub 不保存字节码 14 | --no-cl 不进入命令行模式 15 | -- 前的自由参数被解析为-f参数 16 | -- 后的自由参数被解析为命令行参数 17 | build 18 | -o/--out 文件输出位置(完整目录, 仅支持单个文件编译) 19 | -p/--path 文件输出位置(文件夹, 支持多个文件编译) 20 | -f/--fource 强制编译 21 | 22 | [Github page] 23 | ''' 24 | 25 | # command_line_n = '命令行' 26 | # command_line_tips = '在顶层活动空间运行输入的代码' 27 | # usage_n = '帮助' 28 | # cl_arg_error_e = '命令行参数错误' 29 | # cl_not_file_e = '没有代码需要被运行' 30 | # exit_code_n = '退出代码' 31 | # arg_conflict_n = '参数冲突' 32 | # build_not_src_e = '没有源码被编译' 33 | # build_many_src_e = '太多源码被编译 (不要使用 --out 参数)' 34 | # build_src_not_exists_e = '需要编译的文件不存在' 35 | # build_src_already = '已经编译' 36 | # build_use_f = '使用 --fource 强制编译' 37 | # build_file = '文件将被编译' 38 | # run_save_e = '字节码编译失败' 39 | # run_source_not_aub_e = '运行的文件不是.aun文件' 40 | # run_bt_not_aub_e = '运行的文件不是.aub文件' 41 | # run_load_bt_e = '字节码加载失败' 42 | # run_file_aun_aub_e = '运行的文件不是.aun或.aub文件' 43 | # run_file_not_exists_e = '需要运行的文件不存在' 44 | # build_in_aun_e = '被编译的文件不是.aun文件' 45 | # build_out_aub_e = '编译输出的文件不是.aun文件' 46 | # build_error_e = '编译失败' 47 | # Interrupt_n = '中断' -------------------------------------------------------------------------------- /include/runtime/rt_func_activation.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_FUNC_ACTIVATION_H 2 | #define AFUN_RT_FUNC_ACTIVATION_H 3 | #include "aFunRuntimeExport.h" 4 | #include "aFuncore.h" 5 | #include "rt_func_object.h" 6 | #include "rt_normal_activation.h" 7 | 8 | namespace aFunrt { 9 | class AFUN_RT_EXPORT FuncActivation : public NormalActivation { 10 | public: 11 | AFUN_INLINE explicit FuncActivation(const aFuncode::Code::ByteCode *code, aFuncore::Inter &inter_); 12 | explicit FuncActivation(Function *func, aFuncore::Inter &inter_); 13 | ~FuncActivation() override; 14 | ActivationStatus getCode(const aFuncode::Code::ByteCode *&code) override; 15 | void endRun() override; 16 | 17 | private: 18 | enum { 19 | func_first = 0, // 获取函数体前准备 20 | func_get_func = 1, // 获取函数体后,开始获取参数前 21 | func_get_arg = 2, // 获取参数过程 22 | } status = func_first; 23 | 24 | bool on_tail = false; 25 | const aFuncode::Code::ByteCode *call; 26 | 27 | Function *func = nullptr; 28 | Function::CallFunction *call_func = nullptr; 29 | 30 | std::list *acl = nullptr; 31 | std::list::iterator acl_begin; 32 | std::list::iterator acl_end; 33 | }; 34 | } 35 | 36 | #include "rt_func_activation.inline.h" 37 | #endif //AFUN_RT_FUNC_ACTIVATION_H 38 | -------------------------------------------------------------------------------- /include/core/core_message_stream.template.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_MESSAGE_STREAM_TEMPLATE_H 2 | #define AFUN_CORE_MESSAGE_STREAM_TEMPLATE_H 3 | #include "core_message_stream.h" 4 | 5 | namespace aFuncore { 6 | template 7 | T *MessageStream::getMessage(const std::string &type) const { 8 | Message *msg = this->_getMessage(type); 9 | T *ret = dynamic_cast(msg); 10 | return ret; 11 | } 12 | 13 | 14 | template 15 | void MessageStream::forEach(Callable func, T...arg) { 16 | for (auto &msg : stream) 17 | func(msg.second, arg...); 18 | } 19 | 20 | template 21 | void UpMessageStream::forEachAll(Callable func, T... arg) { 22 | for (const UpMessageStream *up = this; up != nullptr; up = up->old) 23 | up->MessageStream::forEach(func, arg...); 24 | } 25 | 26 | template 27 | void InterMessageStream::forEach(Callable func, T... arg) { 28 | std::unique_lock mutex{lock}; 29 | for (auto &msg : stream) { 30 | mutex.unlock(); 31 | func(msg.second, arg...); 32 | mutex.lock(); 33 | } 34 | } 35 | 36 | template 37 | void InterMessageStream::forEachLock(Callable func, T... arg) { 38 | std::unique_lock mutex{lock}; 39 | for (auto &msg : stream) 40 | func(msg.second, arg...); 41 | } 42 | } 43 | 44 | #endif //AFUN_CORE_MESSAGE_STREAM_TEMPLATE_H 45 | -------------------------------------------------------------------------------- /include/core/core_env_var.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_ENV_VAR_H 2 | #define AFUN_CORE_ENV_VAR_H 3 | #include 4 | #include 5 | #include 6 | #include "aFuntool.h" 7 | #include "aFunCoreExport.h" 8 | 9 | namespace aFuncore { 10 | class Object; 11 | 12 | class AFUN_CORE_EXPORT EnvVarSpace { // 环境变量 13 | public: 14 | EnvVarSpace() = default; 15 | ~EnvVarSpace(); 16 | EnvVarSpace(const EnvVarSpace &)=delete; 17 | EnvVarSpace &operator=(const EnvVarSpace &)=delete; 18 | 19 | [[nodiscard]] AFUN_INLINE size_t getCount(); 20 | bool findString(const std::string &name, std::string &str); 21 | bool findNumber(const std::string &name, int32_t &num); 22 | bool findObject(const std::string &name, Object *&obj); 23 | 24 | void setString(const std::string &name, const std::string &str); 25 | void setNumber(const std::string &name, int32_t num); 26 | void setObject(const std::string &name, Object *obj); 27 | 28 | void addString(const std::string &name, const std::string &str); 29 | void addNumber(const std::string &name, int32_t num); 30 | 31 | private: 32 | AFUN_STATIC const size_t ENV_VAR_HASH_SIZE = 100; // 环境变量哈希表大小 33 | struct EnvVar { // 环境变量 34 | std::string str; 35 | int32_t num; 36 | Object *object; 37 | }; 38 | 39 | std::unordered_map var; 40 | std::mutex lock; 41 | }; 42 | } 43 | 44 | #include "core_env_var.inline.h" 45 | 46 | #endif //AFUN_CORE_ENV_VAR_H 47 | -------------------------------------------------------------------------------- /include/runtime/rt_func_object.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_FUNC_OBJECT_H 2 | #define AFUN_RT_FUNC_OBJECT_H 3 | #include 4 | #include "aFunRuntimeExport.h" 5 | #include "aFuncore.h" 6 | 7 | namespace aFunrt { 8 | class AFUN_RT_EXPORT Function : public virtual aFuncore::Object { 9 | public: 10 | class AFUN_RT_EXPORT CallFunction; 11 | 12 | virtual CallFunction *getCallFunction(const aFuncode::Code::ByteCode *code, aFuncore::Inter &inter) = 0; 13 | virtual bool isInfix(); 14 | }; 15 | 16 | class AFUN_RT_EXPORT Function::CallFunction { 17 | public: 18 | class ArgCodeList; 19 | 20 | CallFunction() = default; 21 | virtual ~CallFunction() = default; 22 | CallFunction(const CallFunction &)=delete; 23 | CallFunction &operator=(const CallFunction &)=delete; 24 | 25 | virtual std::list *getArgCodeList(aFuncore::Inter &inter, aFuncore::Activation &activation, const aFuncode::Code::ByteCode *call) = 0; 26 | virtual void runFunction() = 0; 27 | }; 28 | 29 | class Function::CallFunction::ArgCodeList { 30 | public: 31 | const aFuncode::Code::ByteCode *code = nullptr; 32 | AFUN_INLINE explicit ArgCodeList(const aFuncode::Code::ByteCode *code = nullptr); 33 | AFUN_INLINE ~ArgCodeList(); 34 | AFUN_INLINE aFuncore::Object *setObject(aFuncore::Object *res); 35 | AFUN_INLINE aFuncore::Object *getObject(); 36 | private: 37 | aFuncore::Object *ret; 38 | }; 39 | } 40 | 41 | #include "rt_func_object.inline.h" 42 | 43 | #endif //AFUN_RT_FUNC_OBJECT_H 44 | -------------------------------------------------------------------------------- /src/tool/encoding.cpp: -------------------------------------------------------------------------------- 1 | #include "tool.h" 2 | #include "tool_encoding.h" 3 | 4 | #ifndef AFUN_TOOL_C 5 | namespace aFuntool { 6 | #endif 7 | 8 | /** 9 | * 检查给定字符串是否utf-8编码 10 | * @param str 字符串 11 | */ 12 | bool isCharUTF8(const char *str) { 13 | int code = 0; // utf-8 多字节数 14 | for (const char *ch = str; *ch != NUL; ch++) { 15 | unsigned char c = *ch; 16 | unsigned char c_ = ~c; 17 | 18 | assertFatalErrorLog(code >= 0 && code <= 5, aFunSysLogger, 2, "str = %s", str); 19 | if (code == 0) { 20 | if ((c_ & 0xFC) == 0 && (c & 0x02) == 0) // 检查是否为1111110x, 先对其取反, 使用0xFC掩码检查前6位是否为0, 然后单独检查倒数第二位是否为0 21 | code = 5; // 剩余 5 个字节 22 | else if ((c_ & 0xF8) == 0 && (c & 0x04) == 0) 23 | code = 4; // 剩余 4 个字节 24 | else if ((c_ & 0xF0) == 0 && (c & 0x08) == 0) 25 | code = 3; // 剩余 3 个字节 26 | else if ((c_ & 0xE0) == 0 && (c & 0x10) == 0) 27 | code = 2; // 剩余 2 个字节 28 | else if ((c_ & 0xC0) == 0 && (c & 0x20) == 0) 29 | code = 1; // 剩余 1 个字节 30 | else if ((c & 0x80) == 0) // 检查最高位是否为0 31 | code = 0; 32 | else 33 | return false; 34 | } else if ((c_ & 0x80) == 0 && (c & 0x40) == 0) 35 | code--; 36 | else 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | 43 | #ifndef AFUN_TOOL_C 44 | } 45 | #endif 46 | -------------------------------------------------------------------------------- /include/tool/tool_exception.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_EXCEPTION_H 2 | #define AFUN_TOOL_EXCEPTION_H 3 | #ifdef __cplusplus 4 | 5 | #include "aFunToolExport.h" 6 | #include "tool_macro.h" 7 | #include "tool.h" 8 | 9 | #ifndef AFUN_TOOL_C 10 | namespace aFuntool { 11 | #endif 12 | 13 | class AFUN_TOOL_EXPORT aFunException : public std::exception { 14 | std::string message; 15 | public: 16 | AFUN_INLINE explicit aFunException(std::string msg); 17 | [[nodiscard]] const char *what() const noexcept override; 18 | [[nodiscard]] AFUN_INLINE const std::string &getMessage() const; 19 | }; 20 | 21 | class aFuntoolException : public aFunException { 22 | public: 23 | AFUN_INLINE explicit aFuntoolException(const std::string &msg); 24 | }; 25 | 26 | class FileOpenException : public aFuntoolException { 27 | public: 28 | AFUN_INLINE explicit FileOpenException(const FilePath &file); 29 | }; 30 | 31 | class RegexException : public aFuntoolException { 32 | public: 33 | AFUN_INLINE explicit RegexException(const std::string &msg); 34 | }; 35 | 36 | class LogFatalError : public aFuntoolException { 37 | public: 38 | AFUN_INLINE explicit LogFatalError(const char *msg); 39 | }; 40 | 41 | class Exit : public aFuntoolException { 42 | int exit_code; 43 | public: 44 | AFUN_INLINE explicit Exit(int exit_code_); 45 | AFUN_INLINE int getExitCode() const; 46 | }; 47 | 48 | #ifndef AFUN_TOOL_C 49 | } 50 | #endif 51 | 52 | #include "tool_exception.inline.h" 53 | 54 | #endif 55 | #endif //AFUN_TOOL_EXCEPTION_H 56 | -------------------------------------------------------------------------------- /include/parser/parser_reader.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_PARSER_READER_H 2 | #define AFUN_PARSER_READER_H 3 | #include "aFuntool.h" 4 | #include "aFunParserExport.h" 5 | 6 | namespace aFunparser { 7 | class AFUN_PARSER_EXPORT Reader { 8 | public: 9 | typedef enum ReadMode { 10 | read_mode_normal = 0, 11 | read_mode_finished = 1, 12 | read_mode_error = 2, 13 | } ReadMode; 14 | 15 | AFUN_STATIC const size_t DEFAULT_BUF_SIZE = 1024; 16 | AFUN_STATIC const size_t NEW_BUF_SIZE = 512; 17 | 18 | AFUN_INLINE explicit Reader(aFuntool::FilePath path_, aFuntool::FileLine line_ = 1); 19 | Reader(const Reader &) = delete; 20 | virtual ~Reader(); 21 | Reader &operator=(const Reader &) = delete; 22 | 23 | virtual size_t readText(char *dest, size_t len, ReadMode &mode) = 0; 24 | 25 | [[nodiscard]] AFUN_INLINE size_t countRead() const; 26 | [[nodiscard]] AFUN_INLINE bool isEnd() const; 27 | [[nodiscard]] AFUN_INLINE bool isError() const; 28 | [[nodiscard]] AFUN_INLINE aFuntool::FileLine getFileLine() const; 29 | [[nodiscard]] AFUN_INLINE const aFuntool::FilePath &getFilePath() const; 30 | char *readWord(size_t del_index); 31 | void readFirstWord(); 32 | char getChar(); 33 | 34 | private: 35 | char *buf; 36 | size_t buf_size; // buf的长度-1 37 | char *read; 38 | bool read_end; 39 | bool read_error; 40 | 41 | aFuntool::FileLine line; 42 | aFuntool::FilePath path; 43 | }; 44 | } 45 | 46 | #include "parser_reader.inline.h" 47 | 48 | #endif //AFUN_PARSER_READER_H 49 | -------------------------------------------------------------------------------- /test/src/parser_reader.cpp: -------------------------------------------------------------------------------- 1 | #include "parser_reader.h" 2 | 3 | class ReaderText : public aFunparser::Reader { 4 | int count; 5 | public: 6 | ReaderText() : Reader{"Test", 0} { 7 | count = 0; 8 | } 9 | 10 | size_t readText(char *dest, size_t len, ReadMode &mode) override { 11 | count++; 12 | if (count == 1) { 13 | memset(dest, 's', len); 14 | return len; 15 | } else if (count == 2) { 16 | memset(dest, 'w', len - 5); 17 | return len - 5; 18 | } 19 | mode = read_mode_finished; 20 | return 0; 21 | } 22 | }; 23 | 24 | int main() { 25 | printf("HelloWorld\n"); 26 | 27 | { 28 | ReaderText test = ReaderText(); 29 | test.readFirstWord(); 30 | 31 | char ch; 32 | size_t count = 0; 33 | do { 34 | ch = test.getChar(); 35 | printf("%zu\t\tch = %c\n", count, ch); 36 | count++; 37 | } while (ch != aFuntool::NUL); 38 | 39 | } 40 | 41 | { 42 | ReaderText test = ReaderText(); 43 | test.readFirstWord(); 44 | 45 | char ch; 46 | for (size_t i = 0; i < 1000; i++) { 47 | ch = test.getChar(); 48 | printf("%zu\t\tch = %c\n", i, ch); 49 | } 50 | char *new_word = test.readWord(100); // 提取前面100个值 51 | aFuntool::safeFree(new_word); 52 | 53 | size_t count = 0; 54 | do { 55 | ch = test.getChar(); 56 | printf("%zu\t\tch = %c\n", count, ch); // 923-s 1019-w 57 | count++; 58 | } while (ch != aFuntool::NUL); 59 | } 60 | 61 | return 0; 62 | } -------------------------------------------------------------------------------- /cmake/FindFFlags.cmake: -------------------------------------------------------------------------------- 1 | include(FindPackageHandleStandardArgs) 2 | set(_root ${FFlags_ROOT}) 3 | 4 | if (_root) 5 | set(_root_include ${_root}/include) 6 | set(_root_lib ${_root}/lib) 7 | endif() 8 | 9 | # FFlags_ROOT 必须是 FFlags的安装目录 10 | 11 | # FFlags 12 | find_path(fflags_h NAMES fflags.h HINTS ${_root_include} DOC "FFlags include directory" NO_DEFAULT_PATH) 13 | find_library(fflags_lib NAMES FFlags libFFlags HINTS ${_root_lib} DOC "FFlags library" NO_DEFAULT_PATH) 14 | 15 | unset(_root_include) 16 | unset(_root_lib) 17 | 18 | set(fflags_INCLUDE_DIRS ${fflags_h}) 19 | set(fflags_LIBRARIES ${fflags_lib}) 20 | 21 | if (WIN32 AND NOT CYGWIN) 22 | find_file(fflags_dll NAMES FFlags.dll libFFlags.dll HINTS ${_root}/bin DOC "FFlags ddl" NO_DEFAULT_PATH) 23 | if (fflags_dll) 24 | set(fflags_DLL ${fflags_dll}) 25 | else() 26 | set(fflags_DLL) 27 | endif() 28 | else() 29 | set(fflags_DLL ${fflags_LIBRARIES}) 30 | endif() 31 | 32 | unset(fflags_h CACHE) 33 | unset(fflags_lib CACHE) 34 | unset(_root) 35 | 36 | find_package_handle_standard_args(FFlags 37 | FOUND_VAR FFlags_FOUND 38 | REQUIRED_VARS 39 | fflags_INCLUDE_DIRS 40 | fflags_LIBRARIES 41 | fflags_DLL) # 强制搜不到包 42 | 43 | if (FFlags_FOUND) 44 | add_library(FFlags::fflags STATIC IMPORTED) 45 | set_target_properties(FFlags::fflags PROPERTIES 46 | IMPORTED_IMPLIB "${fflags_DLL}" 47 | IMPORTED_LOCATION "${fflags_LIBRARIES}" 48 | INTERFACE_INCLUDE_DIRECTORIES "${fflags_INCLUDE_DIRS}" 49 | INTERFACE_SOURCES "${fflags_INCLUDE_DIRS}/fflags.h" 50 | PUBLIC_HEADER "${fflags_INCLUDE_DIRS}/fflags.h") 51 | endif() -------------------------------------------------------------------------------- /cmake/deps.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | include(deps_install) 3 | 4 | set(PRINT_DEPS_INFO ON CACHE BOOL "Print deps info.") # 默认设定为 ON 5 | set(_print ${PRINT_DEPS_INFO}) 6 | 7 | set(DEPS_FOUND TRUE) 8 | 9 | if (WIN32 AND NOT CYGWIN) # cygwin 不依赖 dl 10 | find_package(dlfcn-win32 QUIET) 11 | if (NOT dlfcn-win32_FOUND) 12 | set(DEPS_FOUND FALSE) 13 | message(WARNING "dlfcn-win32 not found. But you can try install it by the cmake program.") 14 | else() 15 | set(dlfcn_lib dlfcn-win32::dl) 16 | wi_install_import(TARGETS dlfcn-win32::dl) 17 | endif() 18 | else() 19 | set(DLFCN_AUTO_FIND FALSE CACHE BOOL "dlfcn auto find by compiler.") 20 | set(DLFCN_ROOT "" CACHE STRING "The directory of dl.") 21 | set(dlfcn_root ${DLFCN_ROOT}) 22 | if (dlfcn_root) 23 | find_library(dlfcn_path dl HINTS ${dlfcn_root}) 24 | else() 25 | find_library(dlfcn_path dl) 26 | endif() 27 | 28 | if (NOT dlfcn_path) 29 | if (DLFCN_AUTO_FIND) 30 | set(dlfcn_path "") 31 | else() 32 | set(DEPS_FOUND FALSE) 33 | message(SEND_ERROR "dlfcn not found.") 34 | endif() 35 | endif() 36 | 37 | unset(dlfcn_root) 38 | set(dlfcn_lib ${dlfcn_path}) 39 | endif() 40 | 41 | find_package(PCRE2 COMPONENTS 8BIT QUIET) 42 | if (NOT PCRE2_FOUND) 43 | set(DEPS_FOUND FALSE) 44 | message(WARNING "PCRE2 8BIT not found. But you can try install it by the cmake program.") 45 | else() 46 | wi_install_import(TARGETS PCRE2::8BIT) 47 | endif() 48 | 49 | find_package(Threads QUIET) 50 | if (NOT Threads_FOUND) 51 | set(DEPS_FOUND FALSE) 52 | message(SEND_ERROR "Threads library not found.") 53 | else() 54 | wi_install_import(TARGETS Threads::Threads) 55 | endif() 56 | -------------------------------------------------------------------------------- /src/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB source 2 | LIST_DIRECTORIES FALSE 3 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 4 | 5 | file(GLOB public_h 6 | LIST_DIRECTORIES FALSE 7 | RELATIVE "${build_include_core}" 8 | "${build_include_core}/*.h") 9 | 10 | set(public_h_build) 11 | set(public_h_install) 12 | 13 | foreach(h IN LISTS public_h) 14 | file(RELATIVE_PATH _path ${CMAKE_CURRENT_LIST_DIR} "${build_include_core}/${h}") 15 | list(APPEND public_h_build "$") # 相对路径的转换, 此处只能使用相对路径 16 | list(APPEND public_h_install "$") 17 | endforeach() 18 | 19 | add_library(core-shared SHARED "") 20 | add_library(core-static STATIC "") 21 | 22 | foreach(tgt core-shared core-static) 23 | target_sources(${tgt} PRIVATE ${source} PUBLIC ${public_h_build} ${public_h_install}) 24 | target_include_directories(${tgt} PUBLIC ${build_include} ${install_include}) 25 | set_target_properties(${tgt} PROPERTIES PUBLIC_HEADER "${public_h_build}") 26 | define_filename(${tgt}) 27 | endforeach() 28 | 29 | set_target_properties(core-shared PROPERTIES OUTPUT_NAME "aFuncore") 30 | set_target_properties(core-static PROPERTIES OUTPUT_NAME "aFuncore_s") 31 | 32 | target_link_libraries(core-shared PUBLIC tool-shared code-shared) 33 | target_link_libraries(core-static PUBLIC tool-static code-static) 34 | # 35 | #install(TARGETS core-shared core-static 36 | # EXPORT aFunlang 37 | # RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT base-runtime 38 | # ARCHIVE DESTINATION ${INSTALL_LIBDIR} COMPONENT dev 39 | # LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT base-runtime 40 | # PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev) -------------------------------------------------------------------------------- /src/code/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB source 2 | LIST_DIRECTORIES FALSE 3 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 4 | 5 | file(GLOB public_h 6 | LIST_DIRECTORIES FALSE 7 | RELATIVE "${build_include_code}" 8 | "${build_include_code}/*.h") 9 | 10 | set(public_h_build) 11 | set(public_h_install) 12 | 13 | foreach(h IN LISTS public_h) 14 | file(RELATIVE_PATH _path ${CMAKE_CURRENT_LIST_DIR} "${build_include_code}/${h}") 15 | list(APPEND public_h_build "$") # 相对路径的转换, 此处只能使用相对路径 16 | list(APPEND public_h_install "$") 17 | endforeach() 18 | 19 | add_library(code-shared SHARED "") 20 | add_library(code-static STATIC "") 21 | 22 | foreach(tgt code-shared code-static) 23 | target_sources(${tgt} PRIVATE ${source} PUBLIC ${public_h_build} ${public_h_install}) 24 | target_include_directories(${tgt} PUBLIC ${build_include} ${install_include}) 25 | set_target_properties(${tgt} PROPERTIES 26 | PUBLIC_HEADER "${public_h_build}") 27 | define_filename(${tgt}) 28 | endforeach() 29 | 30 | set_target_properties(code-shared PROPERTIES OUTPUT_NAME "aFuncode") 31 | set_target_properties(code-static PROPERTIES OUTPUT_NAME "aFuncode_s") 32 | 33 | target_link_libraries(code-shared PUBLIC tool-shared) 34 | target_link_libraries(code-static PUBLIC tool-static) 35 | # 36 | #install(TARGETS code-shared code-static 37 | # EXPORT aFunlang 38 | # RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT base-runtime 39 | # ARCHIVE DESTINATION ${INSTALL_LIBDIR} COMPONENT dev 40 | # LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT base-runtime 41 | # PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev) -------------------------------------------------------------------------------- /src/runtime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB source 2 | LIST_DIRECTORIES FALSE 3 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 4 | 5 | file(GLOB public_h 6 | LIST_DIRECTORIES FALSE 7 | RELATIVE "${build_include_rt}" 8 | "${build_include_rt}/*.h") 9 | 10 | set(public_h_build) 11 | set(public_h_install) 12 | 13 | foreach(h IN LISTS public_h) 14 | file(RELATIVE_PATH _path ${CMAKE_CURRENT_LIST_DIR} "${build_include_rt}/${h}") 15 | list(APPEND public_h_build "$") # 相对路径的转换, 此处只能使用相对路径 16 | list(APPEND public_h_install "$") 17 | endforeach() 18 | 19 | add_library(rt-shared SHARED "") 20 | add_library(rt-static STATIC "") 21 | 22 | foreach(tgt rt-shared rt-static) 23 | target_sources(${tgt} PRIVATE ${source} PUBLIC ${public_h_build} ${public_h_install}) 24 | target_include_directories(${tgt} PUBLIC ${build_include} ${install_include}) 25 | set_target_properties(${tgt} PROPERTIES PUBLIC_HEADER "${public_h_build}") 26 | define_filename(${tgt}) 27 | endforeach() 28 | 29 | set_target_properties(rt-shared PROPERTIES OUTPUT_NAME "aFunrt") 30 | set_target_properties(rt-static PROPERTIES OUTPUT_NAME "aFunrt_s") 31 | 32 | target_link_libraries(rt-shared PUBLIC tool-shared code-shared core-shared) 33 | target_link_libraries(rt-static PUBLIC tool-static code-static core-static) 34 | 35 | #install(TARGETS rt-shared rt-static 36 | # EXPORT aFunlang 37 | # RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT base-runtime 38 | # ARCHIVE DESTINATION ${INSTALL_LIBDIR} COMPONENT dev 39 | # LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT base-runtime 40 | # PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev) -------------------------------------------------------------------------------- /src/parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB source 2 | LIST_DIRECTORIES FALSE 3 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 4 | 5 | file(GLOB public_h 6 | LIST_DIRECTORIES FALSE 7 | RELATIVE "${build_include_parser}" 8 | "${build_include_parser}/*.h") 9 | 10 | set(public_h_build) 11 | set(public_h_install) 12 | 13 | foreach(h IN LISTS public_h) 14 | file(RELATIVE_PATH _path ${CMAKE_CURRENT_LIST_DIR} "${build_include_parser}/${h}") 15 | list(APPEND public_h_build "$") # 相对路径的转换, 此处只能使用相对路径 16 | list(APPEND public_h_install "$") 17 | endforeach() 18 | 19 | add_library(parser-shared SHARED "") 20 | add_library(parser-static STATIC "") 21 | 22 | foreach(tgt parser-shared parser-static) 23 | target_sources(${tgt} PRIVATE ${source} PUBLIC ${public_h_build} ${public_h_install}) 24 | target_include_directories(${tgt} PUBLIC ${build_include} ${install_include}) 25 | set_target_properties(${tgt} PROPERTIES PUBLIC_HEADER "${public_h_build}") 26 | define_filename(${tgt}) 27 | endforeach() 28 | 29 | set_target_properties(parser-shared PROPERTIES OUTPUT_NAME "aFunparser") 30 | set_target_properties(parser-static PROPERTIES OUTPUT_NAME "aFunparser_s") 31 | 32 | target_link_libraries(parser-shared PUBLIC tool-shared code-shared) 33 | target_link_libraries(parser-static PUBLIC tool-static code-static) 34 | 35 | #install(TARGETS parser-shared parser-static 36 | # EXPORT aFunlang 37 | # RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT base-runtime 38 | # ARCHIVE DESTINATION ${INSTALL_LIBDIR} COMPONENT dev 39 | # LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT base-runtime 40 | # PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev) -------------------------------------------------------------------------------- /src/interface/reader.cpp: -------------------------------------------------------------------------------- 1 | #include "it_reader.h" 2 | #include "init.h" 3 | 4 | namespace aFunit { 5 | size_t StringReader::readText(char *dest, size_t read_len, ReadMode &mode) { 6 | if (index == len) // 读取到末尾 7 | return 0; 8 | 9 | if (index + read_len > len) { // 超出长度范围 10 | read_len = len - index; 11 | mode = read_mode_finished; 12 | } 13 | 14 | memcpy(dest, str.c_str() + index, read_len); 15 | index += read_len; 16 | return read_len; 17 | } 18 | 19 | size_t FileReader::readText(char *dest, size_t read_len, aFunparser::Reader::ReadMode &mode) { 20 | if (!no_first) { 21 | no_first = true; 22 | char ch; 23 | if (fread(&ch, sizeof(char), 1, file) != 1) { 24 | mode = read_mode_finished; 25 | return 0; 26 | } 27 | 28 | if ((unsigned char)ch == (unsigned char)0xEF) { 29 | /* 处理BOM编码 */ 30 | unsigned char ch_[2]; 31 | if (fread(ch_, sizeof(unsigned char), 2, file) != 2 32 | || ch_[0] != (unsigned char)0xBB 33 | || ch_[1] != (unsigned char)0xBF) { 34 | mode = read_mode_error; 35 | return 0; 36 | } 37 | trackLog(aFunLogger, "Parser utf-8 with BOM"); 38 | } else { 39 | ungetc(ch, file); 40 | trackLog(aFunLogger, "Parser utf-8 without BOM"); 41 | } 42 | } 43 | 44 | size_t len_r = fread(dest, sizeof(char), read_len, file); 45 | if (aFuntool::clear_ferror(file)) { 46 | mode = read_mode_error; 47 | } else if (feof(file)) 48 | mode = read_mode_finished; 49 | return len_r; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /include/code/code.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CODE_INLINE_H 2 | #define AFUN_CODE_INLINE_H 3 | #include "code.h" 4 | 5 | namespace aFuncode { 6 | Code::Code(aFuntool::FilePath file_) : code{new ByteCode(*this, 0)}, file{std::move(file_)} { 7 | 8 | } 9 | 10 | Code::ByteCode *Code::getByteCode() const{ 11 | return code; 12 | } 13 | 14 | const aFuntool::FilePath &Code::getFilePath() const{ 15 | return file; 16 | } 17 | 18 | Code::ByteCode::CodeType Code::ByteCode::getType() const { 19 | return type; 20 | } 21 | 22 | char Code::ByteCode::getPrefix() const { 23 | return prefix; 24 | } 25 | 26 | const char *Code::ByteCode::getElement() const { 27 | if (type != code_element) 28 | return ""; 29 | return data.element; 30 | } 31 | 32 | Code::ByteCode::BlockType Code::ByteCode::getBlockType() const { 33 | if (type != code_block) 34 | return block_p; 35 | return data.block.block_type; 36 | } 37 | 38 | Code::ByteCode *Code::ByteCode::getSon() const { 39 | if (type != code_block) 40 | return nullptr; 41 | return data.block.son; 42 | } 43 | 44 | Code::ByteCode *Code::ByteCode::toNext() const { 45 | return next; 46 | } 47 | 48 | Code::ByteCode *Code::ByteCode::toPrev() const { 49 | return prev; 50 | } 51 | 52 | Code::ByteCode *Code::ByteCode::toFather() const { 53 | return father; 54 | } 55 | 56 | aFuntool::FileLine Code::ByteCode::getFileLine() const { 57 | return line; 58 | } 59 | 60 | const aFuntool::FilePath &Code::ByteCode::getFilePath() const{ 61 | return belong.getFilePath(); 62 | } 63 | 64 | Code::ByteCode::CodeData::CodeData() : element{nullptr} { 65 | 66 | } 67 | } 68 | 69 | #endif //AFUN_CODE_INLINE_H 70 | -------------------------------------------------------------------------------- /deps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(DEPS_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "Deps install.") 2 | 3 | set(FFlags_ROOT ${DEPS_INSTALL_PREFIX} CACHE PATH "FFlags root.") 4 | set(dlfcn-win32_ROOT ${DEPS_INSTALL_PREFIX} CACHE PATH "FFlags root.") 5 | set(PCRE2_ROOT ${DEPS_INSTALL_PREFIX} CACHE PATH "pcre2 root.") 6 | set(PCRE2_USE_STATIC_LIBS ON CACHE BOOL "") 7 | 8 | if (WIN32 AND NOT CYGWIN) # cygwin 不依赖 dl 9 | execute_process( 10 | COMMAND ${CMAKE_COMMAND} -E make_directory dlfcn-win32 11 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 12 | ) 13 | 14 | add_custom_target(dlfcn-win32-build) 15 | add_custom_command(TARGET dlfcn-win32-build POST_BUILD 16 | COMMAND ${CMAKE_COMMAND} 17 | "${CMAKE_CURRENT_LIST_DIR}/dlfcn-win32" 18 | "-DCMAKE_INSTALL_PREFIX:PATH=${dlfcn-win32_ROOT}" 19 | "-G" "${CMAKE_GENERATOR}" 20 | COMMAND ${CMAKE_COMMAND} --build . 21 | COMMAND ${CMAKE_COMMAND} --install . 22 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/dlfcn-win32 23 | COMMENT "Build dlfcn-win32" 24 | VERBATIM) 25 | endif() 26 | 27 | execute_process( 28 | COMMAND ${CMAKE_COMMAND} -E make_directory pcre2 29 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 30 | ) 31 | 32 | add_custom_target(PCRE2-build) 33 | add_custom_command(TARGET PCRE2-build POST_BUILD 34 | COMMAND ${CMAKE_COMMAND} 35 | "${CMAKE_CURRENT_LIST_DIR}/pcre2" 36 | "-DCMAKE_INSTALL_PREFIX:PATH=${PCRE2_ROOT}" 37 | "-DPCRE2_STATIC_PIC=ON" 38 | "-DPCRE2_BUILD_TESTS=OFF" 39 | "-DPCRE2_BUILD_PCRE2GREP=OFF" 40 | "-G" "${CMAKE_GENERATOR}" 41 | COMMAND ${CMAKE_COMMAND} --build . 42 | COMMAND ${CMAKE_COMMAND} --install . 43 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pcre2 44 | COMMENT "Build PCRE2" 45 | VERBATIM) 46 | 47 | -------------------------------------------------------------------------------- /include/core/core_object.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_OBJECT_H 2 | #define AFUN_CORE_OBJECT_H 3 | #include 4 | #include 5 | #include "aFuntool.h" 6 | #include "aFunCoreExport.h" 7 | 8 | namespace aFuncore { 9 | typedef unsigned GcCount; 10 | class Inter; 11 | class Environment; 12 | 13 | class AFUN_CORE_EXPORT Object { 14 | public: 15 | Object(std::string type_, Inter &inter); 16 | Object(std::string type_, Environment &env_); 17 | virtual ~Object(); 18 | Object(const Object &) = delete; 19 | Object &operator=(const Object &) = delete; 20 | 21 | AFUN_INLINE void addReference(); 22 | AFUN_INLINE void delReference(); 23 | [[nodiscard]] AFUN_INLINE GcCount getReference() const; 24 | AFUN_INLINE void setClear(bool clear=false); 25 | 26 | AFUN_STATIC void checkReachable(std::list &list); 27 | AFUN_STATIC void setReachable(std::list &list, std::queue &des, std::queue &del); 28 | AFUN_STATIC void destructUnreachable(std::queue &des, Inter &gc_inter); 29 | AFUN_STATIC void deleteUnreachable(std::queue &del); 30 | AFUN_STATIC void destructAll(std::list &list, Inter &gc_inter); 31 | AFUN_STATIC void deleteAll(std::list &list); 32 | protected: 33 | Environment &env; 34 | const std::string type; // 标识 Object 的字符串 35 | 36 | std::mutex lock; 37 | 38 | virtual void destruct(Inter &gc_inter); 39 | virtual void linkObject(std::queue &queue); 40 | 41 | private: 42 | bool done_destruct; 43 | bool not_clear; // 不清除 44 | bool reachable; // 可达标记 [同时标识已迭代] 45 | GcCount reference; // 引用计数 46 | }; 47 | 48 | }; 49 | 50 | #include "core_object.inline.h" 51 | 52 | #endif //AFUN_CORE_OBJECT_H 53 | -------------------------------------------------------------------------------- /include/tool/tool_byte.template.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_BYTE_TEMPLATE_H 2 | #define AFUN_TOOL_BYTE_TEMPLATE_H 3 | #ifdef __cplusplus 4 | 5 | #include "tool_byte.h" 6 | 7 | #ifndef AFUN_TOOL_C 8 | namespace aFuntool { 9 | #endif 10 | 11 | /** 12 | * 写入一个整数 13 | * @tparam T 整数类型 14 | * @param file FILE 结构体 15 | * @param num 整数 16 | * @return 17 | */ 18 | template 19 | bool byteWriteInt(FILE *file, T num){ 20 | if (endian != save_as) { 21 | const size_t len = sizeof(T) / sizeof(uint8_t); // NOLINT 允许 size(T) / size(T) 22 | union { 23 | T a;//元素a,占2个字节 24 | uint8_t b[len];//元素b,占1个字节,b在内存中的地址为a最低字节的地址 25 | } in{.a = num}, out{}; 26 | 27 | for (size_t i = 0; i < len; i++) 28 | out.b[len - i] = in.b[i]; // 大小端序转换 29 | num = out.a; 30 | } 31 | 32 | return fwrite(&num, sizeof(T), 1, file) == 1; 33 | } 34 | 35 | /** 36 | * 读取一个整数 37 | * @tparam T 整数类型 38 | * @param file FILE 结构体 39 | * @param num 整数 40 | * @return 41 | */ 42 | template 43 | bool byteReadInt(FILE *file, T *num){ 44 | size_t re = fread(num, sizeof(T), 1, file); 45 | 46 | if (endian != save_as) { 47 | const size_t len = sizeof(T) / sizeof(uint8_t); // NOLINT 允许 size(T) / size(T) 48 | union { 49 | T a;//元素a,占2个字节 50 | uint8_t b[len];//元素b,占1个字节,b在内存中的地址为a最低字节的地址 51 | } in{.a = *num}, out{}; 52 | 53 | for (size_t i = 0; i < len; i++) 54 | out.b[len - i] = in.b[i]; // 大小端序转换 55 | *num = out.a; 56 | } 57 | 58 | return re == 1; 59 | } 60 | 61 | #ifndef AFUN_TOOL_C 62 | } 63 | #endif 64 | 65 | #endif // __cplusplus 66 | #endif // AFUN_TOOL_BYTE_TEMPLATE_H 67 | -------------------------------------------------------------------------------- /test/src/parser_lexical.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "parser_syntax.h" 3 | 4 | const char *str = "Hello_var\n" 5 | "10 20.32 100var\n" 6 | "|10 20.32|int->num\n" 7 | "|10||20.32|int->num\n" 8 | "{if true 10}\n" 9 | "of(HelloWorld)\n" 10 | "!(!) @(@) #(#)\n" 11 | "() [] {}\n" 12 | "Hello ;comment\n" 13 | "Hello ;;comment\n" 14 | "commment2;=\n" 15 | "var-200 ;; comment\n" 16 | ";; comment\n" 17 | ";= comment\n" 18 | ";= var-300\n"; 19 | 20 | class ReaderString : public aFunparser::Reader { 21 | std::string str; 22 | size_t index; 23 | size_t len; 24 | public: 25 | ReaderString(std::string str_, const aFuntool::FilePath &path_) : Reader{path_, 0}, str{std::move(str_)} { 26 | index = 0; 27 | len = str.size(); 28 | } 29 | 30 | size_t readText(char *dest, size_t read_len, ReadMode &mode) override { 31 | if (index == len) // 读取到末尾 32 | return 0; 33 | 34 | if (index + read_len > len) { // 超出长度范围 35 | read_len = len - index; 36 | mode = read_mode_finished; 37 | } 38 | 39 | memcpy(dest, str.c_str() + index, read_len); 40 | index += read_len; 41 | return read_len; 42 | } 43 | }; 44 | 45 | int main() { 46 | auto reader = ReaderString(str, "str"); 47 | auto parser = aFunparser::Parser(reader); 48 | 49 | aFunparser::Parser::TokenType tt; 50 | std::string text; 51 | 52 | do { 53 | tt = parser.getTokenFromLexical(text); 54 | printf("tt = %d, text = %s\n", tt, text.c_str()); 55 | } while (tt != aFunparser::Parser::TK_EOF && tt != aFunparser::Parser::TK_ERROR); 56 | 57 | return 0; 58 | } -------------------------------------------------------------------------------- /src/interface/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB source 2 | LIST_DIRECTORIES FALSE 3 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 4 | 5 | file(GLOB public_h 6 | LIST_DIRECTORIES FALSE 7 | RELATIVE "${build_include_runtime}" 8 | "${build_include_runtime}/*.h") 9 | 10 | set(public_h_build) 11 | set(public_h_install) 12 | 13 | foreach(h IN LISTS public_h) 14 | file(RELATIVE_PATH _path ${CMAKE_CURRENT_LIST_DIR} "${build_include_runtime}/${h}") 15 | list(APPEND public_h_build "$") # 相对路径的转换, 此处只能使用相对路径 16 | list(APPEND public_h_install "$") 17 | endforeach() 18 | 19 | add_library(it-shared SHARED "") # xx表示均为动态链接 core-share-t 20 | add_library(it-static STATIC "") # ct表示均静态链接 core-static 21 | 22 | foreach(tgt it-shared it-static) 23 | target_sources(${tgt} 24 | PRIVATE ${source} 25 | PUBLIC ${public_h_build} ${public_h_install}) 26 | target_include_directories(${tgt} PUBLIC ${build_include} ${install_include}) 27 | set_target_properties(${tgt} PROPERTIES PUBLIC_HEADER "${public_h_build}") 28 | define_filename(${tgt}) 29 | endforeach() 30 | 31 | set_target_properties(it-shared PROPERTIES OUTPUT_NAME "aFunit") 32 | set_target_properties(it-static PROPERTIES OUTPUT_NAME "aFunit_s") 33 | 34 | target_link_libraries(it-shared PUBLIC tool-shared code-shared core-shared parser-shared) 35 | target_link_libraries(it-static PUBLIC tool-static code-static core-static parser-static) 36 | 37 | #install(TARGETS it-shared it-static 38 | # EXPORT aFunlang 39 | # RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT base-runtime 40 | # ARCHIVE DESTINATION ${INSTALL_LIBDIR} COMPONENT dev 41 | # LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT base-runtime 42 | # PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev) -------------------------------------------------------------------------------- /include/runtime/rt_varspace_object.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_VARSPACE_OBJECT_H 2 | #define AFUN_VARSPACE_OBJECT_H 3 | #include 4 | #include "aFunRuntimeExport.h" 5 | #include "aFuncore.h" 6 | #include "rt_var_object.h" 7 | 8 | namespace aFunrt { 9 | class AFUN_RT_EXPORT VarSpace : public aFuncore::Object { 10 | public: 11 | typedef enum VarOperationFlat { 12 | vof_success = 0, // 成功 13 | vof_not_var = 1, // 变量不存在 14 | vof_redefine_var = 2, // 变量重复定义 15 | vof_fail = 3, // 存在其他错误 16 | } VarOperationFlat; 17 | 18 | aFuncore::Environment &env; 19 | 20 | explicit VarSpace(aFuncore::Inter &inter); 21 | explicit VarSpace(aFuncore::Environment &env_); 22 | ~VarSpace() override = default; 23 | 24 | template 25 | void forEach(Callable func, T...arg); 26 | 27 | template 28 | void forEachLock(Callable func, T...arg); 29 | 30 | [[nodiscard]] AFUN_INLINE size_t getCount(); 31 | [[nodiscard]] virtual Var *findVar(const std::string &name); 32 | virtual VarOperationFlat defineVar(const std::string &name, aFuncore::Object *data); 33 | virtual VarOperationFlat defineVar(const std::string &name, Var *data); 34 | virtual VarOperationFlat setVar(const std::string &name, aFuncore::Object *data); 35 | virtual VarOperationFlat delVar(const std::string &name); 36 | 37 | [[nodiscard]] AFUN_INLINE aFuncore::Object *findObject(const std::string &name); 38 | void linkObject(std::queue &queue) override; 39 | 40 | AFUN_STATIC const size_t VAR_HASH_SIZE = 100; // 环境变量哈希表大小 41 | 42 | private: 43 | std::unordered_map var; 44 | }; 45 | } 46 | 47 | #include "rt_varspace_object.inline.h" 48 | #include "rt_varspace_object.template.h" 49 | 50 | #endif //AFUN_VARSPACE_OBJECT_H 51 | -------------------------------------------------------------------------------- /src/tool/dlc.cpp: -------------------------------------------------------------------------------- 1 | #include "tool.h" 2 | #include "tool_dlc.h" 3 | 4 | #ifndef AFUN_TOOL_C 5 | namespace aFuntool { 6 | #endif 7 | 8 | DlcHandle::Handle *DlcHandle::dlc = nullptr; 9 | 10 | /** 11 | * 打开动态库 12 | * @param file 动态库路径 13 | * @param mode 模式 14 | * @return 15 | */ 16 | DlcHandle::DlcHandle(const char *file, int mode) noexcept: handle_{nullptr}{ 17 | void *handle = dlopen(file, mode); 18 | if (handle == nullptr) 19 | return; 20 | 21 | for (Handle *tmp = dlc; tmp != nullptr; tmp = tmp->next_) { 22 | if (tmp->handle_ == handle) { 23 | dlclose(handle); // 减少dlopen时对handle的引用计数 24 | (*tmp)++; 25 | handle_ = tmp; 26 | return; 27 | } 28 | } 29 | 30 | handle_ = new Handle(handle); 31 | (*handle_)++; 32 | } 33 | 34 | DlcHandle::Handle::Handle(void *handle) : handle_{handle}, link_{0}, next_{DlcHandle::dlc}, 35 | prev_{nullptr}{ 36 | if (DlcHandle::dlc != nullptr) 37 | DlcHandle::dlc->prev_ = dlc; 38 | DlcHandle::dlc = this; 39 | } 40 | 41 | 42 | DlcHandle::Handle::~Handle(){ 43 | dlclose(handle_); 44 | 45 | if (prev_ == nullptr) 46 | dlc = next_; 47 | else 48 | prev_->next_ = next_; 49 | 50 | if (next_ != nullptr) 51 | next_->prev_ = prev_; 52 | } 53 | 54 | 55 | int DlcHandle::Handle::operator++(int){ 56 | return link_++; 57 | } 58 | 59 | 60 | int DlcHandle::Handle::operator--(int){ 61 | int ret = link_--; 62 | if (link_ == 0) 63 | delete this; // 删除自己 64 | return ret; 65 | } 66 | 67 | /** 68 | * 退出函数 69 | * 需要使用at_exit注册 70 | */ 71 | void DlcHandle::dlcExit(){ 72 | while (dlc != nullptr) { 73 | auto next = dlc->next_; 74 | safeFree(dlc); 75 | dlc = next; 76 | } 77 | } 78 | 79 | #ifndef AFUN_TOOL_C 80 | } 81 | #endif 82 | -------------------------------------------------------------------------------- /cmake/info.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | # 显示编译器信息(1) 4 | message(STATUS "CMAKE_C_COMPILER = ${CMAKE_C_COMPILER}") # 显示C编译器的路径 5 | message(STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}") # 显示CPP编译器的路径 6 | message(STATUS "CMAKE_C_FLAGS = ${CMAKE_C_FLAGS}") # 显示C编译器的选项 7 | message(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}") # 显示C编译器的选项 8 | message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") # 当前的构建类型(若为设置则为空) 9 | 10 | # 显示CMake信息 11 | message(STATUS "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}") # 显示当前CMake文件的所在目录 12 | message(STATUS "CMAKE_BINARY_DIR = ${CMAKE_BINARY_DIR}") # 显示CMake的构建目录 13 | 14 | # 显示操作系统信息 15 | message(STATUS "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}") 16 | 17 | # 显示编译器信息(2) 18 | message(STATUS "CMAKE_C_COMPILER_ID = ${CMAKE_C_COMPILER_ID}") 19 | message(STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}") 20 | 21 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 22 | message(STATUS "Target is 64 bits") 23 | else() 24 | message(STATUS "Target is 32 bits") 25 | endif() 26 | 27 | message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR = ${CMAKE_HOST_SYSTEM_PROCESSOR}") 28 | 29 | set(PRINT_INFO ON CACHE BOOL "Print system info.") # 默认设定为 ON 即打印一次 30 | set(_print ${PRINT_INFO}) 31 | if (NOT _print) 32 | return() 33 | endif() 34 | 35 | # 查询主机信息 36 | foreach(key 37 | IN ITEMS 38 | NUMBER_OF_LOGICAL_CORES 39 | NUMBER_OF_PHYSICAL_CORES 40 | TOTAL_VIRTUAL_MEMORY 41 | AVAILABLE_VIRTUAL_MEMORY 42 | TOTAL_PHYSICAL_MEMORY 43 | AVAILABLE_PHYSICAL_MEMORY 44 | IS_64BIT 45 | HAS_FPU 46 | HAS_MMX 47 | HAS_MMX_PLUS 48 | HAS_SSE 49 | HAS_SSE2 50 | HAS_SSE_FP 51 | HAS_SSE_MMX 52 | HAS_AMD_3DNOW 53 | HAS_AMD_3DNOW_PLUS 54 | HAS_IA64 55 | OS_NAME 56 | OS_RELEASE 57 | OS_VERSION 58 | OS_PLATFORM 59 | ) 60 | cmake_host_system_information(RESULT re QUERY ${key}) 61 | message(STATUS "cmake_host_system_information ${key} = ${re}") 62 | endforeach() 63 | 64 | set(PRINT_INFO OFF CACHE BOOL "Print system info." FORCE) # 设置 PRINT_INFO 为 OFF -------------------------------------------------------------------------------- /include/tool/tool_dlc.template.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jimso on 2022/1/8. 3 | // 4 | 5 | #ifndef AFUN_TOOL_DLC_TEMPLATE_H 6 | #define AFUN_TOOL_DLC_TEMPLATE_H 7 | #ifdef __cplusplus 8 | 9 | #include "tool_dlc.h" 10 | 11 | #ifndef AFUN_TOOL_C 12 | namespace aFuntool { 13 | #endif 14 | 15 | /** 16 | * 符号句柄 17 | * 注意: 不适用符号后需要 delete 18 | * @tparam SYMBOL 符号类型 19 | */ 20 | template 21 | class DlcSymbol { 22 | public: 23 | DlcSymbol() noexcept = default; 24 | 25 | /** 26 | * 从句柄和符号指针创建一个符号 27 | * @param symbol 符号指针 28 | * @param dlc 句柄 29 | */ 30 | explicit DlcSymbol(SYMBOL *symbol_, DlcHandle::Handle *dlc_) noexcept : symbol_ {symbol_}, handle_ {dlc_} { 31 | if (this->handle_ != nullptr) 32 | (*handle_)++; 33 | } 34 | 35 | DlcSymbol(const DlcSymbol &dlc_symbol) noexcept : symbol_{dlc_symbol.symbol_}, handle_ {dlc_symbol.handle_} { 36 | if (handle_ != nullptr) 37 | (*handle_)++; 38 | } 39 | 40 | DlcSymbol(DlcSymbol &&dlc_symbol) noexcept : symbol_{dlc_symbol.symbol_}, handle_ {dlc_symbol.handle_} { 41 | dlc_symbol.handle_ = nullptr; 42 | } 43 | 44 | DlcSymbol &operator=(const DlcSymbol &dlc_symbol) noexcept { 45 | if (this == &dlc_symbol) 46 | return *this; 47 | 48 | if (handle_ != nullptr) 49 | (*handle_)--; 50 | symbol_ = dlc_symbol.symbol_; 51 | handle_ = dlc_symbol.handle_; 52 | if (handle_ != nullptr) 53 | (*handle_)++; 54 | return *this; 55 | } 56 | 57 | ~DlcSymbol() noexcept { 58 | if (handle_ != nullptr) 59 | (*handle_)--; 60 | } 61 | 62 | SYMBOL *getSymbol() const { 63 | return symbol_; 64 | } 65 | 66 | private: 67 | SYMBOL *symbol_ = nullptr; 68 | DlcHandle::Handle *handle_ = nullptr; 69 | }; 70 | 71 | #ifndef AFUN_TOOL_C 72 | } 73 | #endif 74 | 75 | #endif 76 | #endif //AFUN_TOOL_DLC_TEMPLATE_H 77 | -------------------------------------------------------------------------------- /src/tool/string.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 文件名: string.c 3 | * 目标: 关于char和wchar_t的实用函数 4 | */ 5 | 6 | #include 7 | #include 8 | #include "tool.h" 9 | #include "tool_str.h" 10 | 11 | #define NEW_STR(size) safeCalloc((size) + 1) 12 | #define STR_LEN(p) (((p) == NULL) ? 0 : strlen((p))) 13 | 14 | #ifndef AFUN_TOOL_C 15 | namespace aFuntool { 16 | #endif 17 | 18 | char *charToStr(char ch){ 19 | if (ch == NUL) 20 | return nullptr; 21 | char *tmp = NEW_STR(1); 22 | *tmp = ch; 23 | return tmp; 24 | } 25 | 26 | char *strCopy(const char *str){ 27 | if (str != nullptr) { 28 | auto size = STR_LEN(str); 29 | char *tmp = NEW_STR(size); 30 | #ifdef AFUN_WIN32_NO_CYGWIN 31 | strcpy_s(tmp, size + 1, str); 32 | #else 33 | strcpy(tmp, str); 34 | #endif 35 | return tmp; 36 | } 37 | return nullptr; 38 | } 39 | 40 | /** 41 | * 拼接两个字符串 42 | */ 43 | char *strJoin(const char *first, const char *second, bool free_first, bool free_last){ 44 | if (first == nullptr && second == nullptr) 45 | return nullptr; 46 | else if (first == nullptr) { 47 | first = second; 48 | second = nullptr; 49 | free_first = free_last; 50 | free_last = false; 51 | } 52 | 53 | auto size = STR_LEN(first) + STR_LEN(second); 54 | char *new_str = NEW_STR(size); 55 | #ifdef AFUN_WIN32_NO_CYGWIN 56 | strcat_s(new_str, size + 1, first); 57 | #else 58 | strcat(new_str, first); 59 | #endif 60 | if (second != nullptr) { 61 | #ifdef AFUN_WIN32_NO_CYGWIN 62 | strcat_s(new_str, size + 1, second); 63 | #else 64 | strcat(new_str, second); 65 | #endif 66 | } 67 | 68 | if (free_first) { 69 | auto free_ = const_cast(first); 70 | safeFree(free_); 71 | } 72 | 73 | if (free_last) { 74 | auto free_ = const_cast(second); 75 | safeFree(free_); 76 | } 77 | return new_str; 78 | } 79 | 80 | #ifndef AFUN_TOOL_C 81 | } 82 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aFunlang 编程语言 2 | 3 | ## aFun简介 4 | aFun是一款通用的动态解释型编程语言,具有函数式编程范式和面向对象编程范式。它可以与C语言联动,可以调用C的高效率函数,同时不失编程的抽象性。 5 | 6 | ### aFun的设计哲学 7 | 8 | * 保持简单 9 | * 和谐统一更优雅 10 | * 关注做什么而不是怎么做 11 | * 状态可在运行时被修改 12 | * 灵活性与安全可以并存 13 | * 注释和提示信息很重要 14 | * 计算机的时间比人的时间廉价 15 | 16 | **保持简单,可以使用更简洁的语法就不使用复杂的方法。** 17 | 1. 在编写aFun代码时,可以使用字面量解决的问题就不要使用函数回调; 18 | 2. 尽量为函数添加默认参数,简化函数调用时的参数负担; 19 | 3. 不是编写一个为用户完成所有决定的程序,相反程序应该有更多的参数供用户定制,但是需要一个合适的默认参数。 20 | 4. 扁平胜于嵌套,但若嵌套更能表现意思则应使用嵌套而非扁平。 21 | 5. 变量名应体现具体意思,可以利用符号。如`int->str`比`int_to_str`更优雅。 22 | 23 | **和谐统一更优雅,在aFun中追求和谐与统一。正是因为这种和谐、统一,令aFun有更少的公理,使得aFun更容易被理解与上手。** 24 | 1. 内置对象和非内置对象的地位是相同的,底层实现也是相似的、统一的。 25 | 2. if分支、for分支底层都是通过函数实现的,甚至可以添加任意新分支或去除任意分支。 26 | 3. 无论是用户拓展的字面量还是基础的字面量(如`int`),都是通过`.afg`文件中正则表达式实现匹配的。 27 | 4. 和谐与统一不应仅仅在表面上体现为统一,这往往会造成漏洞。 28 | 5. 和谐统一的界面、接口比混乱不堪明显更加优雅。 29 | 30 | **关注做什么而不是怎么做,合理的模块化代码,通过OOP将代码分类。同时,使用类库而不是自己造轮子。** 31 | 1. 例如,使用`map`函数用于遍历列表,而不是手写一个`for`循环遍历列表。 32 | 2. 例如,计算图形面积时,应该为不同图形封装一个类,而不是把所有图形面积计算的代码放在一个函数中。 33 | 3. 代码应该抽象,而不总是关注底层。 34 | 35 | **状态可在运行时被修改,代码的语义、对象的标识等都可在运行时被修改。** 36 | 1. 代码可以生成代码、分析代码、修改代码。 37 | 2. 前缀的语义可以在运行时被改变。 38 | 3. 对象的类型(如,是否可被继承、是否内联函数)可在运行时被修改。 39 | 4. 运行时状态修改有时候会带来灾难,但是一定程度上提高了灵活性。`afc`提供了大量的API供这种运行时状态修改。 40 | 41 | **灵活性与安全性并存,灵活性与安全性之间可以有所取舍和偏袒。** 42 | 1. 合约、权限限定等都是可选的。 43 | 2. 语言的动态性,运行时状态修改为aFun提供了很大的灵活性。 44 | 3. `afc`提供的API时aFun灵活性的有力支持。 45 | 4. 对象为`afc`提供的API是`afc`运行的有力支持。 46 | 5. 一次性任务的代码以及激进的大型项目代码应追求灵活性,而稳定的大型项目的代码应追求安全性。 47 | 48 | **注释和提示信息很重要,aFun会保存注释信息,而不仅仅是无视他。** 49 | 1. 使用函数前,查阅函数的注释信息。 50 | 2. 使用变量、函数前,查阅其合约信息以及权限信息。 51 | 3. aFun会将注释信息、合约信息、权限信息处理为一个文本,记录下来。 52 | 53 | **计算机的时间比人的时间廉价,编码时应思考问题的解决方案,而不是思考二进制代码。** 54 | 1. 为了提供逻辑与思维的便利,可以适度割让一定的效率。 55 | 2. 现在对硬件的浪费,在未来或许只是一种寻常事。 56 | 3. 与关注做什么而不是怎么做类似,怎么做是计算机的事情,aFun通常提供了高效的实现函数。 57 | 58 | ## 项目依赖 59 | ### PCRE2 60 | 项目依赖于`PCRE2`库,因此需要提前安装该库,并且在配置`CMAKE`时指定一下参数: 61 | ```text 62 | PCRE2_ROOT:PATH=<安装目录> # 不指定则按默认路径寻找 63 | PCRE2_USE_STATIC_LIBS:BOOL=<是否为静态库> # 不指定则默认为动态库 64 | ``` 65 | 66 | ### FFlags 67 | 项目依赖于`FFlags`库,因此需要提前安装该库,并且在配置`CMAKE`时指定一下参数: 68 | ```text 69 | FFlags_ROOT:PATH=<安装目录> # 必须指定 70 | ``` 71 | 72 | ### dlfcn-win32 73 | 在`windows`平台编译时依赖于`dlfcn-win32`库,因此需要提前安装该库,并且在配置`CMAKE`时指定一下参数: 74 | ```text 75 | dlfcn-win32_ROOT:PATH=<安装目录> # 不指定则按默认路径寻找 76 | ``` -------------------------------------------------------------------------------- /include/tool/tool_dlc.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_DLC_INLINE_H 2 | #define AFUN_TOOL_DLC_INLINE_H 3 | #ifdef __cplusplus 4 | 5 | #include "tool_dlc.h" 6 | 7 | #ifndef AFUN_TOOL_C 8 | namespace aFuntool { 9 | #endif 10 | 11 | template 12 | DlcSymbol DlcHandle::getSymbol(const std::string &name){ 13 | return handle_ != nullptr ? handle_->getSymbol(name) : DlcSymbol(); 14 | } 15 | 16 | DlcHandle::~DlcHandle() noexcept { 17 | this->close(); 18 | } 19 | 20 | bool DlcHandle::isOpen() const { 21 | return handle_ != nullptr ? handle_->isOpen() : false; 22 | } 23 | 24 | void DlcHandle::close(){ 25 | if (handle_ == nullptr) 26 | return; 27 | (*handle_)--; 28 | handle_ = nullptr; 29 | } 30 | 31 | int DlcHandle::operator++(int){ 32 | return (*handle_)++; 33 | } 34 | 35 | int DlcHandle::operator--(int){ 36 | return (*handle_)--; 37 | } 38 | 39 | DlcHandle &DlcHandle::operator=(const DlcHandle &dlc_handle) noexcept { 40 | if (&dlc_handle == this) 41 | return *this; 42 | 43 | this->close(); 44 | handle_ = dlc_handle.handle_; 45 | if (handle_ != nullptr) 46 | (*handle_)++; 47 | return *this; 48 | } 49 | 50 | DlcHandle::DlcHandle(const DlcHandle &dlc_handle) noexcept { 51 | handle_ = dlc_handle.handle_; 52 | if (handle_ != nullptr) 53 | (*handle_)++; 54 | } 55 | 56 | DlcHandle::DlcHandle(DlcHandle &&dlc_handle)noexcept { 57 | handle_ = dlc_handle.handle_; 58 | dlc_handle.handle_ = nullptr; 59 | } 60 | 61 | template 62 | DlcSymbol DlcHandle::Handle::getSymbol(const std::string &name){ 63 | if (handle_ == nullptr) 64 | return DlcSymbol(); 65 | auto symbol = (SYMBOL *)dlsym(handle_, name.c_str()); 66 | if (symbol == nullptr) 67 | return DlcSymbol(); 68 | return DlcSymbol(symbol, this); 69 | } 70 | 71 | bool DlcHandle::Handle::isOpen() const { 72 | return handle_ != nullptr; 73 | } 74 | 75 | #ifndef AFUN_TOOL_C 76 | } 77 | #endif 78 | 79 | #endif 80 | #endif //AFUN_TOOL_DLC_INLINE_H 81 | -------------------------------------------------------------------------------- /src/core/environment.cpp: -------------------------------------------------------------------------------- 1 | #include "core_inter.h" 2 | #include "core_object.h" 3 | #include "core_environment.h" 4 | #include "core_exception.h" 5 | 6 | namespace aFuncore { 7 | void Environment::gcThread() { 8 | while(true) { 9 | std::queue del; 10 | std::queue des; 11 | { 12 | std::unique_lock mutex{lock}; 13 | if (destruct) 14 | break; 15 | Object::checkReachable(gc); 16 | Object::setReachable(gc, des, del); 17 | } 18 | Object::deleteUnreachable(del); 19 | Object::destructUnreachable(des, gc_inter); 20 | 21 | int32_t intervals = 1000; 22 | env_var.findNumber("sys:gc-intervals", intervals); 23 | if (intervals < 100) 24 | intervals = 100; 25 | std::this_thread::sleep_for(std::chrono::milliseconds(intervals)); 26 | } 27 | 28 | Object::destructAll(gc, gc_inter); /* 不需要mutex锁 */ 29 | } 30 | 31 | Environment::Environment(int argc, char **argv) 32 | : reference{0}, destruct{false}, gc_inter{*(new Inter(*this))}, env_var{*new EnvVarSpace()} { 33 | /* 生成 gc_inter 后, reference == 1 */ 34 | 35 | env_var.setNumber("sys:gc-intervals", 1000); 36 | env_var.setNumber("sys:exit-code", 0); 37 | env_var.setNumber("sys:argc", argc); 38 | for (int i = 0; i < argc; i++) { 39 | char buf[20]; 40 | snprintf(buf, 10, "sys:arg%d", i); 41 | env_var.setString(buf, argv[i]); 42 | } 43 | 44 | gc_thread = std::thread([this](){this->gcThread();}); 45 | } 46 | 47 | Environment::~Environment() noexcept(false) { 48 | { /* 使用互斥锁, 防止与gc线程出现不同步的情况 */ 49 | std::unique_lock mutex{lock}; 50 | if (reference != 1) // gc_inter 有一个引用 51 | throw EnvironmentDestructException(); 52 | 53 | if (destruct) 54 | return; 55 | 56 | destruct = true; 57 | } 58 | 59 | gc_thread.join(); 60 | delete &gc_inter; 61 | delete &env_var; 62 | 63 | Object::deleteAll(gc); /* 不需要mutex锁 */ 64 | 65 | if (reference != 0) 66 | throw EnvironmentDestructException(); 67 | } 68 | } -------------------------------------------------------------------------------- /src/tool/byte.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "tool.h" 6 | #include "tool_byte.h" 7 | 8 | #ifndef AFUN_TOOL_C 9 | namespace aFuntool { 10 | #endif 11 | 12 | enum EndianType endian = little_endian; 13 | enum EndianType save_as = little_endian; // 默认以小端序存储 14 | 15 | /** 16 | * 获取机器字节序 17 | */ 18 | void getEndian(){ 19 | union { 20 | int16_t a;//元素a,占2个字节 21 | int8_t b;//元素b,占1个字节,b在内存中的地址为a最低字节的地址 22 | } test = {.a = 0x1234}; 23 | 24 | if (test.b == 0x34) 25 | endian = little_endian; 26 | else if (test.b == 0x12) 27 | endian = big_endian; 28 | else 29 | abort(); 30 | } 31 | 32 | /** 33 | * 写入一个C风格字符串 34 | */ 35 | bool byteWriteStr(FILE *file, const char *str){ 36 | if (!byteWriteInt(file, static_cast(strlen(str)))) 37 | return false; 38 | return fwrite(str, sizeof(char), strlen(str), file) == strlen(str); 39 | } 40 | 41 | 42 | /** 43 | * 写入一个C++风格字符串 44 | */ 45 | bool byteWriteStr(FILE *file, const std::string &str){ 46 | size_t size = str.size(); 47 | if (!byteWriteInt(file, static_cast(size))) 48 | return false; 49 | return fwrite(str.c_str(), sizeof(char), size, file) == size; 50 | } 51 | 52 | 53 | /** 54 | * 读取一个C风格字符串 55 | */ 56 | bool byteReadStr(FILE *file, char **str){ 57 | uint16_t len; 58 | if (!byteReadInt(file, &len)) 59 | return false; 60 | 61 | if (len == 0) { 62 | *str = nullptr; 63 | return true; 64 | } 65 | 66 | *str = safeCalloc(len + 1); 67 | return fread(*str, sizeof(char), len, file) == len; 68 | } 69 | 70 | /** 71 | * 读取一个C++风格字符串 72 | */ 73 | bool byteReadStr(FILE *file, std::string &str){ 74 | uint16_t len; 75 | if (!byteReadInt(file, &len)) 76 | return false; 77 | 78 | if (len == 0) { 79 | str = ""; 80 | return true; 81 | } 82 | 83 | char *tmp = safeCalloc(len + 1); 84 | size_t ret = fread(tmp, sizeof(char), len, file); 85 | str = tmp; 86 | safeFree(tmp); 87 | return ret == len; 88 | } 89 | 90 | #ifndef AFUN_TOOL_C 91 | } 92 | #endif 93 | -------------------------------------------------------------------------------- /include/core/core_inter.inline.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_INTER_INLINE_H 2 | #define AFUN_CORE_INTER_INLINE_H 3 | #include "core_inter.h" 4 | 5 | namespace aFuncore { 6 | Environment &Inter::getEnvironment() { 7 | return env; 8 | } 9 | 10 | void Inter::pushActivation(Activation *new_activation) { 11 | stack.push_front(new_activation); 12 | activation = new_activation; 13 | } 14 | 15 | Activation *Inter::popActivation() { 16 | if (activation == nullptr) 17 | return nullptr; 18 | 19 | Activation *ret = activation; 20 | stack.pop_front(); 21 | if (stack.empty()) 22 | activation = nullptr; 23 | else 24 | activation = stack.front(); 25 | return ret; 26 | } 27 | 28 | Inter::InterStatus Inter::getStatus() const { 29 | return status; 30 | } 31 | 32 | bool Inter::isInterStop() const { 33 | return (status == inter_exit || status == inter_stop); 34 | } 35 | 36 | bool Inter::isInterExit() const { 37 | return (status == inter_exit); 38 | } 39 | 40 | const std::list &Inter::getStack() const { 41 | return stack; 42 | } 43 | 44 | Activation *Inter::getActivation() const { 45 | return activation; 46 | } 47 | 48 | EnvVarSpace &Inter::getEnvVarSpace() { 49 | return env.env_var; 50 | } 51 | 52 | InterOutMessageStream &Inter::getOutMessageStream() { 53 | return out; 54 | } 55 | 56 | InterInMessageStream &Inter::getInMessageStream() { 57 | return in; 58 | } 59 | 60 | size_t Environment::operator++(){ 61 | std::unique_lock mutex{lock}; 62 | return ++reference; 63 | } 64 | 65 | size_t Environment::operator--(){ 66 | std::unique_lock mutex{lock}; 67 | return --reference; 68 | } 69 | 70 | size_t Environment::operator++(int){ 71 | std::unique_lock mutex{lock}; 72 | return reference++; 73 | } 74 | 75 | size_t Environment::operator--(int){ 76 | std::unique_lock mutex{lock}; 77 | return reference--; 78 | } 79 | 80 | Inter::InterStatus Inter::setInterStop() { 81 | InterStatus ret = status; 82 | if (status != inter_exit) 83 | status = inter_stop; 84 | return ret; 85 | } 86 | 87 | Inter::InterStatus Inter::setInterExit() { 88 | InterStatus ret = status; 89 | status = inter_exit; 90 | return ret; 91 | } 92 | } 93 | 94 | #endif //AFUN_CORE_INTER_INLINE_H 95 | -------------------------------------------------------------------------------- /src/runtime/varspace_object.cpp: -------------------------------------------------------------------------------- 1 | #include "rt_varspace_object.h" 2 | 3 | namespace aFunrt { 4 | VarSpace::VarSpace(aFuncore::Inter &inter) : Object("VarSpace", inter), env{inter.getEnvironment()}{ 5 | 6 | } 7 | 8 | VarSpace::VarSpace(aFuncore::Environment &env_) : Object("VarSpace", env_), env{env_}{ 9 | 10 | } 11 | 12 | /** 13 | * 访问指定变量 14 | * @param name 变量名 15 | * @return 16 | */ 17 | Var *VarSpace::findVar(const std::string &name){ 18 | std::unique_lock mutex{lock}; 19 | auto v = var.find(name); 20 | if (v == var.end()) 21 | return nullptr; 22 | return v->second; 23 | } 24 | 25 | /** 26 | * 定义变量 27 | * @param name 变量名 28 | * @param data 变量(Object) 29 | * @return 30 | */ 31 | VarSpace::VarOperationFlat VarSpace::defineVar(const std::string &name, Object *data) { 32 | std::unique_lock mutex{lock}; 33 | if (var.find(name) != var.end()) 34 | return vof_redefine_var; 35 | auto new_var = new Var(data, env); 36 | var.emplace(name, new_var); 37 | new_var->delReference(); 38 | return vof_success; 39 | } 40 | 41 | /** 42 | * 定义变量 43 | * @param name 变量名 44 | * @param data 变量(Var) 45 | * @return 46 | */ 47 | VarSpace::VarOperationFlat VarSpace::defineVar(const std::string &name, Var *data){ 48 | std::unique_lock mutex{lock}; 49 | if (var.find(name) != var.end()) 50 | return vof_redefine_var; 51 | var.emplace(name, data); 52 | return vof_success; 53 | } 54 | 55 | /** 56 | * 设定变量的值 57 | * @param name 变量名 58 | * @param data 变量 59 | * @return 60 | */ 61 | VarSpace::VarOperationFlat VarSpace::setVar(const std::string &name, Object *data){ 62 | std::unique_lock mutex{lock}; 63 | auto v = var.find(name); 64 | if (v == var.end()) 65 | return vof_not_var; 66 | v->second->setData(data); 67 | return vof_success; 68 | } 69 | 70 | /** 71 | * 删除变量 72 | * @param name 变量名 73 | * @return 74 | */ 75 | VarSpace::VarOperationFlat VarSpace::delVar(const std::string &name){ 76 | std::unique_lock mutex{lock}; 77 | auto v = var.find(name); 78 | if (v == var.end()) 79 | return vof_not_var; 80 | var.erase(v); 81 | return vof_success; 82 | } 83 | 84 | void VarSpace::linkObject(std::queue &queue) { 85 | for (auto tmp : var) 86 | queue.push(tmp.second); 87 | } 88 | } -------------------------------------------------------------------------------- /test/src/tool_byte.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "aFuntool.h" 3 | 4 | 5 | #define TEST_WRITE(test, type) do{\ 6 | if (!(test)) { \ 7 | fprintf(stderr, "Test write wrong: " #type "\n"); \ 8 | return EXIT_FAILURE; \ 9 | }}while(0) 10 | 11 | #define TEST_READ(test, type) do{\ 12 | if (!(test)) { \ 13 | fprintf(stderr, "Test read wrong: " #type "\n"); \ 14 | return EXIT_FAILURE; \ 15 | }}while(0) 16 | 17 | int main() { 18 | int8_t test8 = 10; 19 | int16_t test16 = 20; 20 | int32_t test32 = 30; 21 | int64_t test64 = 40; 22 | const std::string testStr = "test"; 23 | 24 | aFuntool::getEndian(); 25 | 26 | FILE *file = aFuntool::fileOpen("test.byte", "wb"); 27 | if (file == nullptr) { 28 | fprintf(stderr, "Can't not creat file: test.byte\n"); 29 | return EXIT_FAILURE; 30 | } 31 | 32 | TEST_WRITE(aFuntool::byteWriteInt(file, test8), uint8_t); 33 | TEST_WRITE(aFuntool::byteWriteInt(file, test16), uint16_t); 34 | TEST_WRITE(aFuntool::byteWriteInt(file, test32), uint32_t); 35 | TEST_WRITE(aFuntool::byteWriteInt(file, test64), uint64_t); 36 | TEST_WRITE(aFuntool::byteWriteStr(file, testStr), str); 37 | 38 | aFuntool::fileClose(file); 39 | 40 | int8_t rtest8; 41 | int16_t rtest16; 42 | int32_t rtest32; 43 | int64_t rtest64; 44 | std::string rtestStr; 45 | 46 | file = aFuntool::fileOpen("test.byte", "rb"); 47 | if (file == nullptr) { 48 | fprintf(stderr, "Can't not read file: test.byte\n"); 49 | return EXIT_FAILURE; 50 | } 51 | 52 | TEST_READ(aFuntool::byteReadInt(file, (uint8_t *)&rtest8), uint8_t); 53 | TEST_READ(aFuntool::byteReadInt(file, (uint16_t *)&rtest16), uint16_t); 54 | TEST_READ(aFuntool::byteReadInt(file, (uint32_t *)&rtest32), uint32_t); 55 | TEST_READ(aFuntool::byteReadInt(file, (uint64_t *)&rtest64), uint64_t); 56 | TEST_READ(aFuntool::byteReadStr(file, rtestStr), str); 57 | 58 | if (rtest8 != test8 || rtest16 != test16 || rtest32 != test32 || rtest64 != test64 || rtestStr != testStr) { 59 | printf("error.\n"); 60 | aFuntool::cout << "rtest8: " << rtest8 << ", test: " << test8 << "\n"; 61 | aFuntool::cout << "rtest16: " << rtest16 << ", test: " << test16 << "\n"; 62 | aFuntool::cout << "rtest32: " << rtest32 << ", test: " << test32 << "\n"; 63 | aFuntool::cout << "rtest64: " << rtest64 << ", test: " << test64 << "\n"; 64 | aFuntool::cout << "rtestStr: " << rtestStr << "\ntestStr: " << testStr << "\n"; 65 | return EXIT_FAILURE; 66 | } 67 | 68 | aFuntool::fileClose(file); 69 | printf("success.\n"); 70 | return EXIT_SUCCESS; 71 | } -------------------------------------------------------------------------------- /src/core/message_stream.cpp: -------------------------------------------------------------------------------- 1 | #include "core_message_stream.h" 2 | #include "core_activation.h" 3 | #include "core_inter.h" 4 | #include "core_env_var.h" 5 | 6 | namespace aFuncore { 7 | MessageStream::~MessageStream(){ 8 | for (auto &msg : stream) 9 | delete msg.second; 10 | } 11 | 12 | /** 13 | * 压入 Message 14 | * @param msg Message 15 | */ 16 | void MessageStream::pushMessage(const std::string &type, Message *msg){ 17 | stream.emplace(type, msg); 18 | } 19 | 20 | /** 21 | * 获取 Message 22 | * @param type 类型 23 | * @return Message 24 | */ 25 | Message *MessageStream::_getMessage(const std::string &type) const{ 26 | auto ret = stream.find(type); 27 | if (ret == stream.end()) 28 | return nullptr; 29 | return ret->second; 30 | } 31 | 32 | /** 33 | * 弹出Message (使Message脱离数据流) 34 | * @param type 类型 35 | * @return Message 36 | */ 37 | Message *MessageStream::popMessage(const std::string &type){ 38 | auto ret = stream.find(type); 39 | if (ret == stream.end()) 40 | return nullptr; 41 | Message *msg = ret->second; 42 | stream.erase(ret); 43 | return msg; 44 | } 45 | 46 | UpMessageStream::UpMessageStream(const UpMessageStream *old_) : MessageStream(), old{old_} { 47 | 48 | } 49 | 50 | Message *UpMessageStream::_getMessage(const std::string &type) const { 51 | for (const UpMessageStream *up = this; up != nullptr; up = up->old) { 52 | Message *ret = up->MessageStream::_getMessage(type); 53 | if (ret != nullptr) 54 | return ret; 55 | } 56 | return nullptr; 57 | } 58 | 59 | /** 60 | * 拼接数据流 (将this合并到msg) 61 | * @param msg 62 | */ 63 | void DownMessageStream::joinMsg(DownMessageStream &msg){ 64 | msg.stream.merge(stream); 65 | } 66 | 67 | Message *InterMessageStream::popFrontMessage(std::string &type) { 68 | std::unique_lock mutex{lock}; 69 | if (stream.empty()) 70 | return nullptr; 71 | Message *ret = stream.begin()->second; 72 | type = stream.begin()->first; 73 | stream.erase(stream.begin()); 74 | return ret; 75 | } 76 | 77 | Message *InterMessageStream::popMessage(const std::string &type) { 78 | std::unique_lock mutex{lock}; 79 | return MessageStream::popMessage(type); 80 | } 81 | 82 | void InterMessageStream::pushMessage(const std::string &type, Message *msg) { 83 | std::unique_lock mutex{lock}; 84 | MessageStream::pushMessage(type, msg); 85 | } 86 | } -------------------------------------------------------------------------------- /src/tool/time.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 文件名: time.c 3 | * 目标: 关于time的实用函数 4 | */ 5 | 6 | #include 7 | #include "tool.h" 8 | #include "tool_time.h" 9 | #include "tool_stdio.h" 10 | #include "tool_str.h" 11 | 12 | #ifndef AFUN_TOOL_C 13 | namespace aFuntool { 14 | #endif 15 | 16 | /** 17 | * 等待指定的秒数(ms) 支持小数 18 | */ 19 | void safeSleep(double ms){ 20 | time_t start = clock(); 21 | time_t now; 22 | time_t d_time; 23 | auto ms_t = (time_t) (ms * CLOCKS_PER_SEC); 24 | do { 25 | now = clock(); 26 | d_time = now - start; 27 | } while (d_time < ms_t); 28 | } 29 | 30 | /** 31 | * 格式化输出时间 32 | * 注意: 该函数不可以使用log模块 33 | */ 34 | char *getTime(time_t *t, const char *format){ 35 | time_t tmp; 36 | if (t == nullptr) 37 | t = &tmp; 38 | 39 | time(t); // 获取时间戳 40 | #ifdef AFUN_WIN32_NO_CYGWIN 41 | struct tm lt{}; 42 | if (localtime_s(<, t) != 0) 43 | return nullptr; 44 | wchar_t time_str[100]; 45 | wchar_t *format_ = nullptr; 46 | if (convertWideByte(&format_, format, CP_UTF8) == 0) 47 | return nullptr; 48 | wcsftime(time_str, 100, format_, <); 49 | safeFree(format_); 50 | 51 | char *re = nullptr; 52 | if (convertFromWideByte(&re, time_str, CP_UTF8) == 0) 53 | return nullptr; 54 | return re; 55 | #else 56 | struct tm *lt = localtime (t); 57 | char time_str[100]; 58 | strftime(time_str, 100, format, lt); 59 | return strCopy(time_str); 60 | #endif 61 | } 62 | 63 | std::string getTime(time_t *t, const std::string &format){ 64 | time_t tmp; 65 | if (t == nullptr) 66 | t = &tmp; 67 | 68 | time(t); // 获取时间戳 69 | #ifdef AFUN_WIN32_NO_CYGWIN 70 | struct tm lt{}; 71 | if (localtime_s(<, t) != 0) 72 | return ""; 73 | wchar_t time_str[100]; 74 | wchar_t *format_ = nullptr; 75 | if (convertWideByte(&format_, format.c_str(), CP_UTF8) == 0) 76 | return ""; 77 | wcsftime(time_str, 100, format_, <); 78 | safeFree(format_); 79 | 80 | char *tmp_ch = nullptr; 81 | if (convertFromWideByte(&tmp_ch, time_str, CP_UTF8) == 0) 82 | return ""; 83 | #else 84 | struct tm *lt = localtime (t); 85 | char time_str[100]; 86 | strftime(time_str, 100, format.c_str(), lt); 87 | char *tmp_ch = strCopy(time_str);; 88 | #endif 89 | std::string ret = tmp_ch; 90 | safeFree(tmp_ch); 91 | return ret; 92 | } 93 | 94 | #ifndef AFUN_TOOL_C 95 | } 96 | #endif 97 | -------------------------------------------------------------------------------- /include/core/core_message_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_MESSAGE_STREAM_H 2 | #define AFUN_CORE_MESSAGE_STREAM_H 3 | #include 4 | #include 5 | #include 6 | #include "aFuntool.h" 7 | #include "aFunCoreExport.h" 8 | #include "core_message.h" 9 | 10 | namespace aFuncore { 11 | class AFUN_CORE_EXPORT MessageStream { 12 | public: 13 | MessageStream() = default; 14 | virtual ~MessageStream(); 15 | MessageStream(const MessageStream &)=delete; 16 | MessageStream &operator=(const MessageStream &)=delete; 17 | 18 | template 19 | [[nodiscard]] T *getMessage(const std::string &type) const; 20 | 21 | Message *popMessage(const std::string &type); 22 | void pushMessage(const std::string &type, Message *msg); 23 | 24 | template 25 | void forEach(Callable func, T...arg); 26 | 27 | protected: 28 | std::map stream; 29 | [[nodiscard]] virtual Message *_getMessage(const std::string &type) const; 30 | }; 31 | 32 | class AFUN_CORE_EXPORT UpMessageStream : public MessageStream { 33 | public: 34 | explicit UpMessageStream(const UpMessageStream *old=nullptr); 35 | ~UpMessageStream() override = default; 36 | 37 | template 38 | void forEachAll(Callable func, T...arg); 39 | 40 | protected: 41 | const UpMessageStream *old; 42 | [[nodiscard]] Message *_getMessage(const std::string &type) const override; 43 | }; 44 | 45 | class AFUN_CORE_EXPORT DownMessageStream : public MessageStream { 46 | public: 47 | void joinMsg(DownMessageStream &msg); 48 | }; 49 | 50 | class AFUN_CORE_EXPORT InterMessageStream : public MessageStream { 51 | public: 52 | Message *popFrontMessage(std::string &type); 53 | Message *popMessage(const std::string &type); 54 | void pushMessage(const std::string &type, Message *msg); 55 | 56 | template 57 | void forEach(Callable func, T...arg); 58 | 59 | template 60 | void forEachLock(Callable func, T...arg); 61 | private: 62 | std::mutex lock; 63 | }; 64 | 65 | class InterOutMessageStream : public InterMessageStream { 66 | public: 67 | template 68 | [[nodiscard]] T *getMessage(const std::string &type) const = delete; // 对外不设置 getMessage 以避免线程问题 69 | }; 70 | 71 | class InterInMessageStream : public InterMessageStream { 72 | 73 | }; 74 | } 75 | 76 | #include "core_message_stream.template.h" 77 | 78 | #endif //AFUN_CORE_MESSAGE_STREAM_H 79 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(build_include_tool ${PROJECT_SOURCE_DIR}/include/tool) 2 | set(build_include_code ${PROJECT_SOURCE_DIR}/include/code) 3 | set(build_include_core ${PROJECT_SOURCE_DIR}/include/core) 4 | set(build_include_parser ${PROJECT_SOURCE_DIR}/include/parser) 5 | set(build_include_rt ${PROJECT_SOURCE_DIR}/include/runtime) 6 | set(build_include_interface ${PROJECT_SOURCE_DIR}/include/interface) 7 | 8 | set(install_include_tool ${INSTALL_INCLUDEDIR}) 9 | set(install_include_code ${INSTALL_INCLUDEDIR}) 10 | set(install_include_core ${INSTALL_INCLUDEDIR}) 11 | set(install_include_parser ${INSTALL_INCLUDEDIR}) 12 | set(install_include_rt ${INSTALL_INCLUDEDIR}) 13 | set(install_include_interface ${INSTALL_INCLUDEDIR}) 14 | 15 | set(build_include) 16 | foreach(dir 17 | ${hgt_dir} 18 | ${base_include_dir} 19 | ${build_include_tool} 20 | ${build_include_code} 21 | ${build_include_core} 22 | ${build_include_parser} 23 | ${build_include_rt} 24 | ${build_include_interface}) 25 | list(APPEND build_include $) 26 | endforeach() 27 | 28 | set(install_include $) 29 | 30 | add_subdirectory(tool) 31 | add_subdirectory(code) 32 | add_subdirectory(core) 33 | add_subdirectory(parser) 34 | add_subdirectory(runtime) 35 | add_subdirectory(interface) 36 | 37 | ## source在子目录中被使用, 为了避免子目录访问到source, 子目录将在此前面被执行 38 | #file(GLOB source 39 | # LIST_DIRECTORIES FALSE 40 | # ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 41 | # 42 | #file(GLOB private_h 43 | # LIST_DIRECTORIES FALSE 44 | # ${CMAKE_CURRENT_LIST_DIR}/*.h) 45 | # 46 | #add_executable(aFun-xx "") # xx表示均为动态链接 47 | #add_executable(aFun-ct "") # ct表示均静态链接 48 | #set(aFunList aFun-xx aFun-ct) 49 | # 50 | #foreach(tgt IN LISTS aFunList) 51 | # target_sources(${tgt} PRIVATE ${source} ${private_h} ${include_h}) 52 | # target_include_directories(${tgt} PRIVATE ${PROJECT_SOURCE_DIR}/include) 53 | # target_compile_definitions(${tgt} 54 | # PRIVATE 55 | # AFUN_VERSION="${PROJECT_VERSION}" 56 | # AFUN_DESCRIPTION="${PROJECT_DESCRIPTION}" 57 | # AFUN_MAJOR_VERSION=${PROJECT_VERSION_MAJOR} 58 | # AFUN_MINOR_VERSION=${PROJECT_VERSION_MINOR} 59 | # AFUN_PATCH_VERSION=${PROJECT_VERSION_PATCH}) 60 | # define_filename(${tgt}) 61 | #endforeach() 62 | # 63 | #target_link_libraries(aFun-xx PUBLIC it-shared FFlags::fflags) 64 | #target_link_libraries(aFun-ct PUBLIC it-static FFlags::fflags) 65 | # 66 | #install(TARGETS aFun-xx aFun-ct 67 | # RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT dev 68 | # PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev 69 | # PRIVATE_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev) 70 | -------------------------------------------------------------------------------- /include/core/core_inter.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CORE_INTER_H 2 | #define AFUN_CORE_INTER_H 3 | #include 4 | #include 5 | #include "aFunCoreExport.h" 6 | #include "aFuntool.h" 7 | #include "aFuncode.h" 8 | #include "core_env_var.h" 9 | #include "core_message_stream.h" 10 | #include "core_activation.h" 11 | #include "core_object.h" 12 | #include "core_environment.h" 13 | 14 | namespace aFuncore { 15 | class Inter; 16 | 17 | class AFUN_CORE_EXPORT Inter { 18 | friend class Activation; 19 | 20 | struct LiteralRegex; 21 | public: 22 | typedef enum InterStatus { 23 | inter_init = 0, // 执行初始化程序 24 | inter_normal = 1, // 正常执行 25 | inter_stop = 2, // 当前运算退出 26 | inter_exit = 3, // 解释器退出 27 | } InterStatus; 28 | 29 | explicit Inter(Environment &env_); 30 | Inter(const Inter &base_inter); 31 | ~Inter(); 32 | Inter &operator=(const Inter &) = delete; 33 | 34 | void enable(); 35 | 36 | [[nodiscard]] AFUN_INLINE InterStatus getStatus() const; 37 | [[nodiscard]] AFUN_INLINE bool isInterStop() const; 38 | [[nodiscard]] AFUN_INLINE bool isInterExit() const; 39 | [[nodiscard]] AFUN_INLINE Environment &getEnvironment(); 40 | [[nodiscard]] AFUN_INLINE const std::list &getStack() const; 41 | [[nodiscard]] AFUN_INLINE Activation *getActivation() const; 42 | [[nodiscard]] bool checkLiteral(const std::string &element) const; 43 | [[nodiscard]] bool checkLiteral(const std::string &element, std::string &literaler, bool &in_protect) const; 44 | [[nodiscard]] AFUN_INLINE EnvVarSpace &getEnvVarSpace(); 45 | [[nodiscard]] AFUN_INLINE InterOutMessageStream &getOutMessageStream(); 46 | [[nodiscard]] AFUN_INLINE InterInMessageStream &getInMessageStream(); 47 | 48 | bool pushLiteral(const std::string &pattern, const std::string &literaler, bool in_protect); 49 | 50 | AFUN_INLINE void pushActivation(Activation *new_activation); 51 | AFUN_INLINE Activation *popActivation(); 52 | 53 | bool runCode(); 54 | 55 | AFUN_INLINE InterStatus setInterStop(); 56 | AFUN_INLINE InterStatus setInterExit(); 57 | private: 58 | InterStatus status; 59 | 60 | Environment &env; 61 | 62 | std::list stack; 63 | Activation *activation; // 活动记录 64 | 65 | InterOutMessageStream out; 66 | InterInMessageStream in; 67 | 68 | std::list literal; 69 | }; 70 | 71 | struct Inter::LiteralRegex { 72 | aFuntool::Regex rg; 73 | std::string pattern; // 派生 LiteralRegex 时使用 74 | std::string literaler; // 调用的函数 75 | bool in_protect; // 是否在protect空间 76 | }; 77 | } 78 | 79 | #include "core_inter.inline.h" 80 | 81 | #endif //AFUN_CORE_INTER_H 82 | -------------------------------------------------------------------------------- /cmake/deps_install.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) # 防止二次导入 2 | 3 | # 安装 dll 4 | function(_wi_install_import_inline target run) 5 | if(WIN32 OR CYGWIN) 6 | get_target_property(imp ${target} IMPORTED_IMPLIB) 7 | get_target_property(imp_debug ${target} IMPORTED_IMPLIB_DEBUG) 8 | get_target_property(imp_release ${target} IMPORTED_IMPLIB_RELEASE) 9 | 10 | get_target_property(loc ${target} IMPORTED_LOCATION) 11 | get_target_property(loc_debug ${target} IMPORTED_LOCATION_DEBUG) 12 | get_target_property(loc_release ${target} IMPORTED_LOCATION_RELEASE) 13 | 14 | if(run) 15 | foreach(tmp ${imp} ${imp_debug} ${imp_release} ${loc} ${loc_debug} ${loc_release}) 16 | if (tmp AND tmp MATCHES ".+dll") 17 | install(FILES ${tmp} DESTINATION ${run}) 18 | endif() 19 | endforeach() 20 | endif() 21 | endif() 22 | endfunction() 23 | 24 | # 拷贝dll 25 | # 添加 target 26 | if (NOT TARGET deps-copy) 27 | add_custom_target(deps-copy COMMENT "Copy import target.") 28 | endif() 29 | 30 | macro(set_copy_command target a b) 31 | add_custom_command(TARGET ${target} POST_BUILD 32 | COMMAND "${CMAKE_COMMAND}" "-E" "copy_if_different" "${a}" "${b}" 33 | COMMENT "Copy ${a} to ${b}." 34 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 35 | VERBATIM) 36 | endmacro() 37 | 38 | function(_wi_build_import_inline target run) 39 | if(WIN32 OR CYGWIN) 40 | get_target_property(imp ${target} IMPORTED_IMPLIB) 41 | get_target_property(imp_debug ${target} IMPORTED_IMPLIB_DEBUG) 42 | get_target_property(imp_release ${target} IMPORTED_IMPLIB_RELEASE) 43 | 44 | get_target_property(loc ${target} IMPORTED_LOCATION) 45 | get_target_property(loc_debug ${target} IMPORTED_LOCATION_DEBUG) 46 | get_target_property(loc_release ${target} IMPORTED_LOCATION_RELEASE) 47 | 48 | if(run) 49 | foreach(tmp ${imp} ${imp_debug} ${imp_release} ${loc} ${loc_debug} ${loc_release}) 50 | if (tmp AND tmp MATCHES ".+dll") 51 | set_copy_command(deps-copy ${tmp} ${run}) 52 | endif() 53 | endforeach() 54 | endif() 55 | endif() 56 | endfunction() 57 | 58 | function(wi_install_import) 59 | cmake_parse_arguments(ii "" "RUNTIME" "TARGETS" ${ARGN}) 60 | if (NOT ii_RUNTIME) 61 | if (INSTALL_BINDIR) 62 | set(runtime ${INSTALL_BINDIR}) 63 | else() 64 | set(runtime ${CMAKE_INSTALL_BINDIR}) 65 | endif() 66 | else() 67 | set(runtime ${ii_RUNTIME}) 68 | endif() 69 | 70 | set(targets ${ii_TARGETS}) 71 | foreach(tgt IN LISTS targets) # 不需要 ${} 72 | _wi_install_import_inline(${tgt} ${runtime}) 73 | _wi_build_import_inline(${tgt} ${runtime}) 74 | endforeach() 75 | endfunction() 76 | -------------------------------------------------------------------------------- /src/tool/regex.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_exception.h" 2 | #include "tool_regex.h" 3 | #include "tool_encoding.h" 4 | #include "string" 5 | 6 | #ifndef AFUN_TOOL_C 7 | namespace aFuntool { 8 | #endif 9 | 10 | Regex::Regex(std::string pattern_) noexcept(false): pattern{std::move(pattern_)}, re{nullptr} { 11 | int error_code; 12 | size_t error_offset; 13 | pcre2_code *ret = pcre2_compile((PCRE2_SPTR) pattern.c_str(), PCRE2_ZERO_TERMINATED, 0, &error_code, 14 | &error_offset, nullptr); 15 | 16 | if (ret == nullptr) { 17 | if (error_code) { 18 | PCRE2_UCHAR buffer[256]; 19 | pcre2_get_error_message(error_code, buffer, sizeof(buffer)); 20 | char regex_error[1024]; 21 | snprintf(regex_error, sizeof(regex_error), "Regex failed: %d: %s\n", (int) error_offset, buffer); 22 | throw RegexException(regex_error); 23 | } else 24 | throw RegexException("Regex failed: unknown"); 25 | } 26 | 27 | if (!isCharUTF8(pattern)) { 28 | pcre2_code_free(ret); 29 | throw RegexException("Pattern not utf-8"); 30 | } 31 | 32 | re = ret; 33 | } 34 | 35 | bool Regex::match(const std::string &subject) const{ 36 | if (!isCharUTF8(subject)) 37 | throw RegexException("Subject not utf-8"); 38 | 39 | auto sub = (PCRE2_SPTR)subject.c_str(); 40 | PCRE2_SIZE sub_len = subject.size(); 41 | pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(re, nullptr); 42 | int rc = pcre2_match(re, sub, sub_len, 0, 0, match_data, nullptr); 43 | 44 | if (rc < 0) { 45 | pcre2_match_data_free(match_data); 46 | if (rc == PCRE2_ERROR_NOMATCH) 47 | return false; 48 | else { 49 | char regex_error[1024]; 50 | snprintf(regex_error, sizeof(regex_error), "Regex match '%s' failed by '%s'\n", subject.c_str(), pattern.c_str()); 51 | throw RegexException(regex_error); 52 | } 53 | } 54 | 55 | PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data); 56 | if (ovector[0] > ovector[1]) { 57 | char regex_error[1024]; 58 | snprintf(regex_error, sizeof(regex_error), 59 | "\\K was used in an assertion to set the match start after its end.\n" 60 | "From end to start the match was: %.*s\n", 61 | (int) (ovector[0] - ovector[1]), (char *) (subject.c_str() + ovector[1])); 62 | pcre2_match_data_free(match_data); 63 | throw RegexException(regex_error); 64 | } 65 | 66 | bool result = false; 67 | if (ovector[0] == 0 && ovector[1] == sub_len) // 完全匹配 68 | result = true; 69 | pcre2_match_data_free(match_data); 70 | return result; 71 | } 72 | 73 | #ifndef AFUN_TOOL_C 74 | } 75 | #endif -------------------------------------------------------------------------------- /include/runtime/rt_normal_activation.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_RT_NORMAL_ACTIVATION_H 2 | #define AFUN_RT_NORMAL_ACTIVATION_H 3 | #include "aFunRuntimeExport.h" 4 | #include "aFuncore.h" 5 | #include "rt_func_object.h" 6 | #include "rt_varspace_object.h" 7 | #include "rt_var_object.h" 8 | 9 | namespace aFunrt { 10 | class AFUN_RT_EXPORT NormalActivation : public aFuncore::Activation { 11 | public: 12 | class AFUN_RT_EXPORT VarList { 13 | public: 14 | AFUN_INLINE explicit VarList(); 15 | virtual ~VarList(); 16 | AFUN_INLINE VarList(VarList &&new_varlist) noexcept ; 17 | AFUN_INLINE VarList &operator=(VarList &&new_varlist) noexcept; 18 | VarList(const VarList &) = delete; 19 | VarList &operator=(const VarList &) = delete; 20 | 21 | void clear(); 22 | void connect(VarList &new_varlist); 23 | AFUN_INLINE void push(VarSpace *varspace_); 24 | AFUN_INLINE size_t count(); 25 | 26 | template 27 | void forEach(Callable func, T...arg); 28 | 29 | [[nodiscard]] virtual Var *findVar(const std::string &name); 30 | virtual bool defineVar(const std::string &name, aFuncore::Object *data); 31 | virtual bool defineVar(const std::string &name, Var *data); 32 | virtual bool setVar(const std::string &name, aFuncore::Object *data); 33 | virtual bool delVar(const std::string &name); 34 | [[nodiscard]] AFUN_INLINE aFuncore::Object *findObject(const std::string &name); 35 | 36 | private: 37 | std::list varspace; 38 | }; 39 | 40 | aFuncore::Inter &inter; 41 | 42 | explicit NormalActivation(aFuncore::Inter &inter_); 43 | ~NormalActivation() override; 44 | 45 | void runCode(const aFuncode::Code::ByteCode *code) override; 46 | void endRun() override; 47 | 48 | [[nodiscard]] AFUN_INLINE VarList &getVarlist(); 49 | [[nodiscard]] aFuncore::UpMessageStream &getUpStream() override; 50 | [[nodiscard]] aFuncore::DownMessageStream &getDownStream() override; 51 | [[nodiscard]] aFuntool::FileLine getFileLine() override; 52 | [[nodiscard]] const aFuntool::FilePath &getFilePath() override; 53 | 54 | protected: 55 | VarList varlist; 56 | 57 | aFuncore::UpMessageStream up; 58 | aFuncore::DownMessageStream down; 59 | 60 | aFuntool::FilePath path; 61 | aFuntool::FileLine line; 62 | 63 | virtual void runCodeElement(const aFuncode::Code::ByteCode *code); 64 | virtual void runCodeBlockP(const aFuncode::Code::ByteCode *code); 65 | virtual void runCodeBlockC(const aFuncode::Code::ByteCode *code); 66 | virtual void runCodeBlockB(const aFuncode::Code::ByteCode *code); 67 | }; 68 | } 69 | 70 | #include "rt_normal_activation.inline.h" 71 | #include "rt_normal_activation.template.h" 72 | 73 | #endif //AFUN_RT_NORMAL_ACTIVATION_H 74 | -------------------------------------------------------------------------------- /include/tool/tool_dlc.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_DLC_H 2 | #define AFUN_TOOL_DLC_H 3 | #ifdef __cplusplus 4 | 5 | #include 6 | #include "aFunToolExport.h" 7 | #include "tool_macro.h" 8 | #include "dlfcn.h" // CMake 处理 dlfcn.h 的位置 9 | 10 | /* 动态库工具(dlc): 处理动态库的使用 */ 11 | 12 | /* 13 | * NEW_DLC_SYMBOL: 用于定义指定类型的symbol结构体 14 | * DLC_SYMBOL: 指定类型的symbol结构体名 15 | * GET_SYMBOL: 访问symbol成员的值 16 | * MAKE_SYMBOL: 生成一个symbol 17 | * COPY_SYMBOL: 拷贝一个symbol(拷贝其引用) 18 | * READ_SYMBOL: 在dlc中获取一个symbol 19 | * FREE_SYMBOL: 释放symbol 20 | * 21 | * openLibary: 打开动态库 22 | * freeLibary: 释放动态库 23 | * dlcExit: 释放所有动态库 24 | */ 25 | 26 | #ifndef AFUN_TOOL_C 27 | namespace aFuntool { 28 | #endif 29 | 30 | class DlcHandle; 31 | 32 | template 33 | class DlcSymbol; 34 | 35 | AFUN_TOOL_EXPORT void dlcExit(); 36 | 37 | /** 38 | * DlcHandle: 动态库句柄 39 | * 注意: 仅能通过 openLibrary生成 40 | * 不需要 delete 释放 (自动管理释放) 41 | */ 42 | class AFUN_TOOL_EXPORT DlcHandle { 43 | public: 44 | DlcHandle(const char *file, int mode) noexcept; // 仅 openLibary 可用 45 | AFUN_INLINE DlcHandle(const DlcHandle &dlc_handle) noexcept; 46 | AFUN_INLINE DlcHandle(DlcHandle &&dlc_handle) noexcept; 47 | AFUN_INLINE ~DlcHandle() noexcept; 48 | AFUN_INLINE DlcHandle &operator=(const DlcHandle &dlc_handle) noexcept; 49 | 50 | [[nodiscard]] AFUN_INLINE bool isOpen() const; 51 | 52 | /** 53 | * 获得动态库中指定名字的符号 54 | * @tparam SYMBOL 符号类型 55 | * @param name 名字 56 | * @return 符号 57 | */ 58 | template 59 | DlcSymbol getSymbol(const std::string &name); 60 | 61 | /** 62 | * 关闭动态库句柄 63 | */ 64 | AFUN_INLINE void close(); 65 | AFUN_INLINE int operator++(int); 66 | AFUN_INLINE int operator--(int); 67 | 68 | AFUN_STATIC void dlcExit(); 69 | 70 | class AFUN_TOOL_EXPORT Handle { 71 | friend class DlcHandle; 72 | public: 73 | explicit Handle(void *handle); // 仅 openLibary 可用 74 | Handle(const Handle &dlc) = delete; 75 | Handle &operator=(const Handle *dlc) = delete; 76 | ~Handle(); 77 | 78 | [[nodiscard]] AFUN_INLINE bool isOpen() const; 79 | 80 | /** 81 | * 获得动态库中指定名字的符号 82 | * @tparam SYMBOL 符号类型 83 | * @param name 名字 84 | * @return 符号 85 | */ 86 | template 87 | DlcSymbol getSymbol(const std::string &name); 88 | 89 | int operator++(int); 90 | int operator--(int); 91 | 92 | private: 93 | void *handle_; 94 | int link_; // 引用计数 95 | class Handle *next_; 96 | class Handle *prev_; 97 | }; 98 | 99 | private: 100 | class Handle *handle_; 101 | AFUN_STATIC Handle *dlc; 102 | }; 103 | 104 | #ifndef AFUN_TOOL_C 105 | } 106 | #endif 107 | 108 | #include "tool_dlc.inline.h" 109 | #include "tool_dlc.template.h" 110 | 111 | #endif 112 | #endif //AFUN_TOOL_DLC_H 113 | -------------------------------------------------------------------------------- /src/core/object.cpp: -------------------------------------------------------------------------------- 1 | #include "core_object.h" 2 | #include "core_inter.h" 3 | #include "core_logger.h" 4 | 5 | namespace aFuncore { 6 | Object::Object(std::string type_, Inter &inter) 7 | : env{inter.getEnvironment()}, type{std::move(type_)}, done_destruct{false}, not_clear{false}, 8 | reachable{false}, reference{1}{ 9 | std::unique_lock mutex{env.lock}; 10 | env.gc.push_back(this); 11 | } 12 | 13 | Object::Object(std::string type_, Environment &env_) 14 | : env{env_}, type{std::move(type_)}, done_destruct{false}, not_clear{false}, 15 | reachable{false}, reference{1}{ 16 | std::unique_lock mutex{env.lock}; 17 | env.gc.push_back(this); 18 | } 19 | 20 | Object::~Object() { 21 | if (reference != 0) 22 | warningLog(aFunCoreLogger, "Object %p destruct reference: %d", this, getReference()); 23 | std::unique_lock mutex{env.lock}; 24 | env.gc.remove(this); 25 | } 26 | 27 | void Object::destructAll(std::list& list, Inter &gc_inter) { 28 | for (auto obj : list) 29 | if (!obj->done_destruct) { 30 | obj->done_destruct = true; 31 | obj->destruct(gc_inter); 32 | } 33 | } 34 | 35 | void Object::deleteAll(std::list& list) { 36 | while (!list.empty()) 37 | delete list.front(); /* 自带pop */ 38 | if (!list.empty()) 39 | warningLog(aFunCoreLogger, "After Object destructAll, list is not empty"); 40 | } 41 | 42 | void Object::destruct(Inter &) { 43 | /* 什么都不做, 但virtual函数不能是inline */ 44 | } 45 | 46 | void Object::linkObject(std::queue &) { 47 | /* 什么都不做, 但virtual函数不能是inline */ 48 | } 49 | 50 | void Object::checkReachable(std::list &list) { 51 | std::queue queue; 52 | 53 | for (auto *obj : list) { 54 | obj->reachable = false; 55 | if (obj->reference > 0 || obj->not_clear) 56 | queue.push(obj); 57 | } 58 | 59 | while (!queue.empty()) { 60 | auto obj = queue.front(); 61 | if (!obj->reachable) { 62 | obj->reachable = true; 63 | obj->linkObject(queue); 64 | } 65 | queue.pop(); 66 | } 67 | } 68 | 69 | void Object::setReachable(std::list &list, std::queue &des, 70 | std::queue &del) { 71 | for (auto *obj : list) { 72 | if (!obj->reachable) { 73 | if (obj->done_destruct) 74 | del.push(obj); 75 | else 76 | des.push(obj); 77 | } 78 | } 79 | } 80 | 81 | void Object::destructUnreachable(std::queue &des, Inter &gc_inter) { 82 | while (!des.empty()) { 83 | auto obj = des.front(); 84 | obj->done_destruct = true; 85 | obj->destruct(gc_inter); 86 | des.pop(); 87 | } 88 | } 89 | 90 | void Object::deleteUnreachable(std::queue &del) { 91 | while (!del.empty()) { 92 | auto obj = del.front(); 93 | del.pop(); 94 | delete obj; 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /test/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB src_list RELATIVE ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 2 | foreach(src IN LISTS src_list) 3 | cmake_path(GET src STEM file_name) 4 | string(REPLACE "_" "-" target_name ${file_name}) 5 | add_executable(${target_name}) 6 | target_sources(${target_name} PRIVATE ${src}) 7 | target_link_libraries(${target_name} PUBLIC tool-static code-static core-static parser-static rt-static it-static) # 链接静态库 (导出所有符号) 8 | set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "test_${file_name}") 9 | target_compile_definitions(${target_name} PRIVATE IN_CTEST) 10 | define_filename(${target_name}) 11 | unset(file_name) 12 | unset(target_name) 13 | endforeach() 14 | unset(src_list) 15 | 16 | file(GLOB src_list RELATIVE ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/*.c) 17 | foreach(src IN LISTS src_list) 18 | cmake_path(GET src STEM file_name) 19 | string(REPLACE "_" "-" target_name ${file_name}) 20 | add_executable(${target_name}) 21 | target_sources(${target_name} PRIVATE ${src}) 22 | target_link_libraries(${target_name} PUBLIC tool-static-c) # 链接静态库 (导出所有符号) 23 | set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "test_${file_name}") 24 | target_compile_definitions(${target_name} PRIVATE IN_CTEST) 25 | define_filename(${target_name}) 26 | unset(file_name) 27 | unset(target_name) 28 | endforeach() 29 | unset(src_list) 30 | 31 | # tool 相关测试 32 | file(MD5 "${CMAKE_CURRENT_LIST_DIR}/../share/md5.txt" TOOL_MD5_ANS) 33 | add_new_test(tool-mem COMMAND "$") 34 | add_new_test(tool-byte COMMAND "$") 35 | add_new_test(tool-dlc COMMAND "$" "$") 36 | add_new_test(tool-regex COMMAND "$") 37 | add_new_test(tool-md5 COMMAND "$" "${TOOL_MD5_ANS}" "${CMAKE_CURRENT_LIST_DIR}/../share/md5.txt") 38 | add_new_test(tool-utf COMMAND "$") 39 | add_new_test(tool-logger COMMAND "$") 40 | add_new_test(tool-exit COMMAND "$") 41 | add_new_test(tool-hash COMMAND "$") 42 | set_test_label(tool tool-mem tool-byte tool-dlc tool-regex tool-md5 tool-utf tool-logger tool-exit tool-hash) 43 | 44 | add_new_test(tool-c-hash COMMAND "$") 45 | add_new_test(tool-c-stdio COMMAND "$") 46 | set_test_label(tool-c tool-c-hash tool-c-stdio) 47 | 48 | add_new_test(code-create COMMAND "$") 49 | set_test_label(code code-create) 50 | 51 | add_new_test(core-env-var COMMAND "$") 52 | add_new_test(core-down-msg COMMAND "$") 53 | add_new_test(core-up-msg COMMAND "$") 54 | set_test_label(core core-env-var core-down-msg core-up-msg) 55 | 56 | add_new_test(parser-reader COMMAND "$") 57 | add_new_test(parser-lexical COMMAND "$") 58 | set_test_label(parser parser-reader parser-lexical) 59 | 60 | add_new_test(it-syntactic COMMAND "$") 61 | add_new_test(it-init COMMAND "$") 62 | set_test_label(it it-syntactic it-init) 63 | 64 | add_new_test(run-code COMMAND "$") 65 | set_test_label(aFun run-code) -------------------------------------------------------------------------------- /cmake/directory.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | 文件名: directory.cmake 3 | 设置安装路径的程序 4 | ]] 5 | 6 | include_guard(GLOBAL) # 防止二次导入 7 | 8 | function(wi_set_install_dir_quiet) 9 | if (NOT CMAKE_SIZEOF_VOID_P) # 如果还未设定CMAKE_SIZEOF_VOID_P, 则现在设定该值 10 | try_run(run_re com_re ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/_void_p_test.c) 11 | if (com_re) # 编译正常 12 | set(CMAKE_SIZEOF_VOID_P ${run_re} CACHE INTERNAL ”“ FORCE) 13 | endif() 14 | endif() 15 | 16 | cmake_parse_arguments(i "" "NAMES" "" ${ARGN}) 17 | 18 | if (i_NAMES) 19 | set(_names ${i_NAMES}) 20 | else() 21 | set(_names ${PROJECT_NAME}) 22 | endif() 23 | 24 | include(GNUInstallDirs) 25 | set(_lib ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) # 静态库的输出路径/动态库(或者动态库的导入文件)的输出路径 26 | set(_bin ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) # 可执行文件(以及.dll)的输出路径 27 | 28 | # 不能直接访问 PARENT_SCOPE 的参数, 因此设置_lib 29 | file(MAKE_DIRECTORY ${_lib}) 30 | file(MAKE_DIRECTORY ${_bin}) 31 | 32 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${_lib} PARENT_SCOPE) 33 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${_lib} PARENT_SCOPE) 34 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${_bin} PARENT_SCOPE) 35 | 36 | if(WIN32 OR CYGWIN) # cygwin和windows使用相同的文件结构 37 | set(DEF_INSTALL_CMAKEDIR cmake) 38 | set(DEF_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) 39 | set(DEF_INSTALL_RESOURCEDIR ${CMAKE_INSTALL_DATAROOTDIR}) # 关联文件 40 | else() 41 | # unix类系统(Unix, Linux, MacOS, Cygwin等)把cmake文件安装到指定的系统的cmake文件夹中 42 | set(DEF_INSTALL_CMAKEDIR ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${_names}) 43 | set(DEF_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/${_names}) 44 | set(DEF_INSTALL_RESOURCEDIR ${CMAKE_INSTALL_DATAROOTDIR}/${_names}) # 关联文件 CMAKE_INSTALL_DATAROOTDIR指: share 45 | endif() 46 | 47 | # 设定安装的目录 48 | set(INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Installation directory for executables") 49 | set(INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Installation directory for libraries") 50 | set(INSTALL_CMAKEDIR ${DEF_INSTALL_CMAKEDIR} CACHE PATH "Installation directory for CMake files") 51 | set(INSTALL_INCLUDEDIR ${DEF_INSTALL_INCLUDEDIR} CACHE PATH "Installation directory for header files") 52 | set(INSTALL_RESOURCEDIR ${DEF_INSTALL_RESOURCEDIR} CACHE PATH "Installation directory for resource files") # 关联文件 53 | 54 | unset(DEF_INSTALL_CMAKEDIR) 55 | unset(DEF_INSTALL_INCLUDEDIR) 56 | unset(DEF_INSTALL_RESOURCEDIR) 57 | endfunction() 58 | 59 | function(wi_set_install_dir) 60 | set(_argn ${ARGN}) 61 | wi_set_install_dir_quiet(${_argn}) 62 | 63 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} PARENT_SCOPE) # 静态库的输出路径 64 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} PARENT_SCOPE) # 动态库(或者动态库的导入文件)的输出路径 65 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} PARENT_SCOPE) # 可执行文件(以及.dll)的输出路径 66 | 67 | # 报告构建路径 68 | foreach(p ARCHIVE LIBRARY RUNTIME) 69 | message(STATUS "Build ${p} at ${CMAKE_${p}_OUTPUT_DIRECTORY}") 70 | endforeach() 71 | 72 | # 报告安装路径 73 | foreach(p LIB BIN INCLUDE RESOURCE CMAKE) 74 | message(STATUS "Install ${p} at ${CMAKE_INSTALL_PREFIX}/${INSTALL_${p}DIR}") 75 | endforeach() 76 | endfunction() 77 | -------------------------------------------------------------------------------- /cmake/aFunlangConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | # 以上为configure_package_config_file自动生成的初始化程序 4 | 5 | set_and_check(target ${CMAKE_CURRENT_LIST_DIR}/aFunlang.cmake) 6 | include(${target}) # 调用msgTargets.cmake导入模块 7 | 8 | set(components_list) # 记录组件的list 9 | 10 | # 检查是否存在对应 target 11 | if (TARGET aFunlang::tool-shared) 12 | list(APPEND components_list tool-shared) 13 | endif() 14 | 15 | if (TARGET aFunlang::tool-static) 16 | list(APPEND components_list tool-shared) 17 | endif() 18 | 19 | if (TARGET aFunlang::core-shared) 20 | list(APPEND components_list core-shared) 21 | endif() 22 | 23 | if (TARGET aFunlang::core-static) 24 | list(APPEND components_list core-static) 25 | endif() 26 | 27 | # 查找可执行程序 28 | set_and_check(aFunlang_ROOT @PACKAGE_INSTALL_DIR@) 29 | set_and_check(aFunlang_INCLUDE_DIRS @PACKAGE_INCLUDEDIR@) 30 | set_and_check(aFunlang_RUNTIME_DIRS @PACKAGE_BINDIR@) 31 | 32 | if(WIN32 OR CYGWIN) # cygwin 和 win32 一样使用.dll 33 | set_and_check(aFunlang_RUNTIME_LIBRARIES_DIRS @PACKAGE_BINDIR@) 34 | else() 35 | set_and_check(aFunlang_RUNTIME_LIBRARIES_DIRS @PACKAGE_LIBDIR@) 36 | endif() 37 | 38 | find_program(aFunlang_EXECUTABLE NAMES aFun aFun-ct aFun-ct aFun-xx HINTS ${aFunlang_RUNTIME_DIRS} DOC "aFun executable" NO_DEFAULT_PATH) 39 | find_program(aFunlang_ct_EXECUTABLE NAMES aFun-ct HINTS ${aFunlang_RUNTIME_DIRS} DOC "aFun-ct executable" NO_DEFAULT_PATH) 40 | find_program(aFunlang_cx_EXECUTABLE NAMES aFun-ct HINTS ${aFunlang_RUNTIME_DIRS} DOC "aFun-ct executable" NO_DEFAULT_PATH) 41 | find_program(aFunlang_xx_EXECUTABLE NAMES aFun-xx HINTS ${aFunlang_RUNTIME_DIRS} DOC "aFun-xx executable" NO_DEFAULT_PATH) 42 | 43 | if (aFunlang_EXECUTABLE) 44 | list(APPEND components_list aFun) 45 | endif() 46 | 47 | if (aFunlang_ct_EXECUTABLE) 48 | list(APPEND components_list aFun-ct) 49 | endif() 50 | 51 | if (aFunlang_cx_EXECUTABLE) 52 | list(APPEND components_list aFun-ct) 53 | endif() 54 | 55 | if (aFunlang_xx_EXECUTABLE) 56 | list(APPEND components_list aFun-xx) 57 | endif() 58 | 59 | # 用该函数取代find_package 避免变量污染 60 | function(find_package_safe) 61 | set(multiValueArgs PACKAGE VARS) 62 | cmake_parse_arguments(fp "" "" "${multiValueArgs}" ${ARGN}) 63 | 64 | set(_find_package_arg ${fp_PACKAGE}) 65 | set(_vars ${fp_VARS}) 66 | find_package(${_find_package_arg}) 67 | 68 | foreach(_var IN LISTS _vars) 69 | set(${_var} ${${_var}} PARENT_SCOPE) 70 | endforeach() 71 | endfunction() 72 | 73 | # 查找依赖 74 | if (WIN32 AND NOT CYGWIN) # cygwin 不需要 dl 75 | set_and_check(aFunlang_dlfcn_ROOT @PACKAGE_dlfcn_INSTALL_DIR@) 76 | find_package_safe(PACKAGE dlfcn-win32 QUIET HINTS @PACKAGE_dlfcn_CMAKEDIR@) # 指定路径 77 | if (NOT TARGET dlfcn-win32::dl) 78 | message(FATAL_ERROR "Target dlfcn-win32::dl not found.") # find_package的报错出自此处, 不需要REQUIRED 79 | endif() 80 | endif() 81 | 82 | set_and_check(aFunlang_fflags_ROOT @PACKAGE_fflags_INSTALL_DIR@) 83 | set(FFlags_ROOT ${aFunlang_fflags_ROOT}) 84 | set(_CMAKE_MODULE_PATH_bak ${CMAKE_MODULE_PATH}) 85 | list(APPEND CMAKE_MODULE_PATH @PACKAGE_fflags_CMAKEDIR@) 86 | find_package_safe(PACKAGE FFlags QUIET) 87 | if (NOT TARGET FFlags::fflags) 88 | message(FATAL_ERROR "Target FFlags::fflags not found.") 89 | endif() 90 | set(CMAKE_MODULE_PATH ${_CMAKE_MODULE_PATH_bak}) 91 | unset(_CMAKE_MODULE_PATH_bak) 92 | 93 | check_required_components(${components_list}) -------------------------------------------------------------------------------- /src/tool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(BUILD_SAFE_MEMORY ON CACHE BOOL "Build safe-memory tool") 2 | set(_build_mem ${BUILD_SAFE_MEMORY}) 3 | 4 | file(GLOB source 5 | LIST_DIRECTORIES FALSE 6 | ${CMAKE_CURRENT_LIST_DIR}/*.cpp) 7 | 8 | file(GLOB private_h 9 | LIST_DIRECTORIES FALSE 10 | ${CMAKE_CURRENT_LIST_DIR}/*.h) 11 | 12 | file(GLOB public_h 13 | LIST_DIRECTORIES FALSE 14 | RELATIVE "${build_include_tool}" 15 | "${build_include_tool}/*.h") 16 | 17 | set(public_h_build) 18 | set(public_h_install) 19 | 20 | foreach(h IN LISTS public_h) 21 | file(RELATIVE_PATH _path ${CMAKE_CURRENT_LIST_DIR} "${build_include_tool}/${h}") 22 | list(APPEND public_h_build "$") # 相对路径的转换, 此处只能使用相对路径 23 | list(APPEND public_h_install "$") 24 | endforeach() 25 | 26 | add_library(tool-shared SHARED "") 27 | add_library(tool-static STATIC "") 28 | add_library(tool-shared-c SHARED "") 29 | add_library(tool-static-c STATIC "") 30 | 31 | # 基础宏定义 32 | set(definitions 33 | SYSTEM_NAME="${CMAKE_SYSTEM_NAME}" 34 | COMPILER_CXX_ID="${CMAKE_CXX_COMPILER_ID}" 35 | COMPILER_C_ID="${CMAKE_C_COMPILER_ID}" 36 | AFUN_SHARE_PREFIX="${CMAKE_SHARED_LIBRARY_PREFIX}" 37 | AFUN_SHARE_SUFFIX="${CMAKE_SHARED_LIBRARY_SUFFIX}" 38 | AFUN_STATIC_PREFIX="${CMAKE_STATIC_LIBRARY_PREFIX}" 39 | AFUN_STATIC_SUFFIX="${CMAKE_STATIC_LIBRARY_SUFFIX}" 40 | AFUN_EXE_SUFFIX="${CMAKE_EXECUTABLE_SUFFIX}") 41 | if (WIN32 OR CYGWIN) 42 | list(APPEND definitions AFUN_WIN32) 43 | endif() 44 | if (WIN32 AND NOT CYGWIN) 45 | list(APPEND definitions AFUN_WIN32_NO_CYGWIN) 46 | endif() 47 | if (CYGWIN) 48 | list(APPEND definitions AFUN_CYGWIN) 49 | endif() 50 | if (CMAKE_BUILD_TYPE STREQUAL Debug) 51 | list(APPEND definitions AFUN_DEBUG) 52 | endif() 53 | 54 | foreach(tgt tool-shared tool-static tool-shared-c tool-static-c) 55 | target_sources(${tgt} PRIVATE ${source} ${private_h} PUBLIC ${public_h_build} ${public_h_install}) 56 | target_include_directories(${tgt} PUBLIC ${build_include} ${install_include}) 57 | target_compile_definitions(${tgt} PUBLIC ${definitions}) 58 | set_target_properties(${tgt} PROPERTIES PUBLIC_HEADER "${public_h_build}" PRIVATE_HEADER "${private_h}") 59 | target_link_libraries(${tgt} PUBLIC ${dlfcn_lib} PCRE2::8BIT Threads::Threads) 60 | define_filename(${tgt}) 61 | endforeach() 62 | 63 | foreach(tgt tool-shared tool-static) 64 | target_compile_definitions(${tgt} PUBLIC ${definitions}) 65 | endforeach() 66 | 67 | foreach(tgt tool-shared-c tool-static-c) 68 | target_compile_definitions(${tgt} PUBLIC ${definitions} AFUN_TOOL_C) 69 | endforeach() 70 | 71 | set_target_properties(tool-shared PROPERTIES OUTPUT_NAME "aFuntool") 72 | set_target_properties(tool-static PROPERTIES OUTPUT_NAME "aFuntool_s") 73 | set_target_properties(tool-shared-c PROPERTIES OUTPUT_NAME "aFuntool_c") 74 | set_target_properties(tool-static-c PROPERTIES OUTPUT_NAME "aFuntool_sc") 75 | 76 | #install(TARGETS tool-shared tool-static 77 | # EXPORT aFunlang 78 | # RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT runtime 79 | # ARCHIVE DESTINATION ${INSTALL_LIBDIR} COMPONENT dev 80 | # LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT runtime 81 | # PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev 82 | # PRIVATE_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT unsafe-dev) -------------------------------------------------------------------------------- /src/tool/exit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "tool_exit.h" 5 | #include "tool_exception.h" 6 | 7 | #ifndef AFUN_TOOL_C 8 | namespace aFuntool { 9 | #endif 10 | 11 | class ExitManager { 12 | public: 13 | ExitManager() noexcept : exit_mutex{}, data{} { 14 | /* 不能将改函数改为default, 15 | * 否则 (implicitly deleted because its exception-specification does not match the implicit ) */ 16 | } 17 | 18 | ~ExitManager() noexcept { 19 | runExitData(); 20 | } 21 | 22 | void runExitData() { 23 | std::unique_lock ul{exit_mutex}; 24 | while(!data.empty()) { 25 | auto tmp = data.top(); 26 | tmp.func(tmp.data); 27 | data.pop(); 28 | } 29 | } 30 | 31 | void pushExitData(aFunExitFunc func, void *data_) { 32 | std::unique_lock ul{exit_mutex}; 33 | data.push({std::move(func), data_}); 34 | } 35 | 36 | bool tryRunExitData() { 37 | if (!exit_mutex.try_lock()) 38 | return false; 39 | std::unique_lock ul{exit_mutex, std::adopt_lock}; 40 | while(!data.empty()) { 41 | auto tmp = data.top(); 42 | tmp.func(tmp.data); 43 | data.pop(); 44 | } 45 | return true; 46 | } 47 | 48 | bool tryPushExitData(aFunExitFunc func, void *data_) { 49 | if (!exit_mutex.try_lock()) 50 | return false; 51 | std::unique_lock ul{exit_mutex, std::adopt_lock}; 52 | data.push({std::move(func), data_}); 53 | return true; 54 | } 55 | 56 | private: 57 | std::mutex exit_mutex; 58 | struct ExitFuncData { 59 | aFunExitFunc func; 60 | void *data; 61 | }; 62 | std::stack data; 63 | } manager; 64 | 65 | /** 66 | * 退出程序 67 | * @param exit_code 退出代码 68 | */ 69 | void aFunExit(int exit_code) noexcept(false) { 70 | manager.runExitData(); 71 | throw Exit(exit_code); 72 | } 73 | 74 | /** 75 | * 退出程序 76 | * @param exit_code 退出代码 77 | */ 78 | [[noreturn]] void aFunExitReal(int exit_code) { 79 | manager.runExitData(); 80 | exit(exit_code); 81 | } 82 | 83 | 84 | /** 85 | * 尝试执行退出函数 86 | */ 87 | bool aFunTryExitPseudo(){ 88 | return manager.tryRunExitData(); 89 | } 90 | 91 | /** 92 | * 执行退出函数, 但不退出 93 | */ 94 | void aFunExitPseudo(){ 95 | manager.runExitData(); 96 | } 97 | 98 | /** 99 | * 尝试注册退出函数, 若锁占用则返回-1 100 | * @param func 退出函数 101 | * @param data 参数 102 | */ 103 | bool aFunAtExitTry(const aFunExitFunc &func, void *data){ 104 | return manager.tryPushExitData(func, data); 105 | } 106 | 107 | /** 108 | * 注册退出函数, aFun退出函数会在atexit退出函数之前执行 109 | * @param func 退出函数 110 | * @param data 参数 111 | * @return 112 | */ 113 | void aFunAtExit(const aFunExitFunc &func, void *data){ 114 | manager.pushExitData(func, data); 115 | } 116 | 117 | /** 118 | * 注册退出函数, aFun退出函数会在atexit退出函数之前执行 119 | * @param func 退出函数 120 | * @param data 参数 121 | * @return 122 | */ 123 | void aFunAtExit(const ExitFunc &func){ 124 | manager.pushExitData([func] (void *) {func();}, nullptr); 125 | } 126 | 127 | #ifndef AFUN_TOOL_C 128 | } 129 | #endif 130 | -------------------------------------------------------------------------------- /include/tool/tool_log_macro.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_TOOL_LOG_MACRO_H 2 | #define AFUN_TOOL_LOG_MACRO_H 3 | 4 | #if (defined aFunOFFAllLog || defined aFunOFFLog) 5 | 6 | #undef aFunWriteTrack 7 | #define aFunWriteTrack 0 /* 必须忽略Track */ 8 | 9 | #undef aFunWriteTrack 10 | #define aFunWriteDebug 0 /* 必须忽略Debug */ 11 | 12 | #undef aFunWriteTrack 13 | #define aFunWriteInfo 0 /* 必须忽略Info */ 14 | 15 | #undef aFunWriteTrack 16 | #define aFunIgnoreWarning 0 /* 必须忽略Warning */ 17 | 18 | #undef aFunWriteTrack 19 | #define aFunIgnoreError 0 /* 必须忽略Error */ 20 | 21 | #undef aFunWriteTrack 22 | #define aFunIgnoreSendError 0 /* 必须忽略SendError */ 23 | 24 | #undef aFunWriteTrack 25 | #define aFunIgnoreFatalError 0 /* 必须忽略FatalError */ 26 | 27 | #undef aFunWriteTrack 28 | #define aFunIgnoreFatalError 0 /* 必须忽略FatalError */ 29 | 30 | #elif defined AFUN_DEBUG 31 | 32 | #ifndef aFunWriteTrack 33 | #define aFunWriteTrack 1 /* 是否记录Track */ 34 | #endif 35 | 36 | #ifndef aFunWriteDebug 37 | #define aFunWriteDebug 1 /* 是否记录Debug */ 38 | #endif 39 | 40 | #ifndef aFunWriteInfo 41 | #define aFunWriteInfo 1 /* 是否记录Info */ 42 | #endif 43 | 44 | #ifndef aFunIgnoreWarning 45 | #define aFunIgnoreWarning 0 /* 是否忽略Warning */ 46 | #endif 47 | 48 | #ifndef aFunIgnoreError 49 | #define aFunIgnoreError 0 /* 是否忽略Error */ 50 | #endif 51 | 52 | #ifndef aFunIgnoreSendError 53 | #define aFunIgnoreSendError 0 /* 是否忽略SendError */ 54 | #endif 55 | 56 | #ifndef aFunIgnoreFatalError 57 | #define aFunIgnoreFatalError 0 /* 是否忽略FatalError */ 58 | #endif 59 | 60 | #else 61 | 62 | #undef aFunWriteTrack 63 | #define aFunWriteTrack 0 /* 必须忽略Track */ 64 | 65 | #ifndef aFunWriteDebug 66 | #define aFunWriteDebug 1 /* 是否记录Debug */ 67 | #endif 68 | 69 | #undef aFunConsoleDebug 70 | #define aFunConsoleDebug 0 71 | 72 | #ifndef aFunWriteInfo 73 | #define aFunWriteInfo 1 /* 是否记录Info */ 74 | #endif 75 | 76 | #undef aFunConsoleInfo 77 | #define aFunConsoleInfo 0 78 | 79 | #ifndef aFunIgnoreWarning 80 | #define aFunIgnoreWarning 0 /* 是否忽略Warning */ 81 | #endif 82 | 83 | #ifndef aFunIgnoreError 84 | #define aFunIgnoreError 0 /* 是否忽略Error */ 85 | #endif 86 | 87 | #ifndef aFunIgnoreSendError 88 | #define aFunIgnoreSendError 0 /* 是否忽略SendError */ 89 | #endif 90 | 91 | #ifndef aFunIgnoreFatalError 92 | #define aFunIgnoreFatalError 0 /* 是否忽略FatalError */ 93 | #endif 94 | 95 | #endif 96 | 97 | #if defined AFUN_DEBUG 98 | #undef aFunConsoleTrack 99 | #define aFunConsoleTrack 1 100 | #elif (!aFunWriteTrack || !defined aFunConsoleTrack) 101 | #undef aFunConsoleTrack 102 | #define aFunConsoleTrack 0 103 | #endif 104 | 105 | #if !aFunWriteDebug 106 | #undef aFunConsoleDebug 107 | #define aFunConsoleDebug 0 108 | #elif !defined aFunConsoleDebug 109 | #define aFunConsoleDebug 1 110 | #endif 111 | 112 | #if !aFunWriteInfo 113 | #undef aFunConsoleInfo 114 | #define aFunConsoleInfo 0 115 | #elif !defined aFunConsoleInfo 116 | #define aFunConsoleInfo 1 117 | #endif 118 | 119 | #if aFunIgnoreWarning 120 | #undef aFunConsoleWarning 121 | #define aFunConsoleWarning 0 122 | #elif !defined aFunConsoleWarning 123 | #define aFunConsoleWarning 1 124 | #endif 125 | 126 | #if aFunIgnoreError 127 | #undef aFunConsoleError 128 | #define aFunConsoleError 0 129 | #elif !defined aFunConsoleError 130 | #define aFunConsoleError 1 131 | #endif 132 | 133 | #if aFunIgnoreSendError 134 | #undef aFunConsoleSendError 135 | #define aFunConsoleSendError 0 136 | #elif !defined aFunConsoleSendError 137 | #define aFunConsoleSendError 1 138 | #endif 139 | 140 | #if aFunIgnoreFatalError 141 | #undef aFunConsoleFatalError 142 | #define aFunConsoleFatalError 0 143 | #elif !defined aFunConsoleFatalError 144 | #define aFunConsoleFatalError 1 145 | #endif 146 | 147 | #endif //AFUN_TOOL_LOG_MACRO_H 148 | -------------------------------------------------------------------------------- /src/tool/file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tool.h" 3 | #include "tool_file.h" 4 | #include "tool_stdio.h" 5 | 6 | #ifdef AFUN_WIN32_NO_CYGWIN 7 | #ifdef _MSC_VER 8 | #pragma warning(disable : 5105) // 关闭 5105 的警告输出 (Windows.h中使用) 9 | #endif 10 | #include 11 | #include 12 | #else 13 | #include 14 | #include 15 | #endif 16 | 17 | #ifndef S_ISREG 18 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 19 | #endif 20 | 21 | #ifndef S_ISDIR 22 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 23 | #endif 24 | 25 | #ifndef AFUN_TOOL_C 26 | namespace aFuntool { 27 | #endif 28 | 29 | #ifdef AFUN_WIN32_NO_CYGWIN 30 | typedef struct _stat64 aFun_stat; 31 | typedef wchar_t aFun_path; 32 | #else 33 | typedef struct stat aFun_stat; 34 | typedef char aFun_path; 35 | #endif 36 | 37 | /** 38 | * 获取文件的stat结构体 39 | * @param stat stat 保存地址 40 | * @param path 路径 (utf-8) 41 | * @return 42 | */ 43 | int get_stat(aFun_stat &stat_, const std::string &path_){ 44 | int re; 45 | #ifdef AFUN_WIN32_NO_CYGWIN 46 | aFun_path *tmp = nullptr; 47 | if (convertWideByte(&tmp, path_.c_str(), CP_UTF8) == 0) 48 | return -1; 49 | re = _wstat64(tmp, &stat_); 50 | safeFree(tmp); // 如果 path 为nullptr, 则释放最新生成的 wchat_t 51 | #else 52 | re = stat(path_.c_str(), &stat_); 53 | #endif 54 | return re; 55 | } 56 | 57 | /** 58 | * 目标判断文件类型, 若是普通文件返回1, 若是文件夹返回2, 其他遇到错误返回0 59 | */ 60 | int checkFile(const std::string &path){ 61 | if (path.empty()) 62 | return 0; 63 | 64 | int re = 0; 65 | aFun_stat stat; 66 | if (get_stat(stat, path) != 0) 67 | re = 0; 68 | else if (S_ISREG(stat.st_mode)) // 普通文件 69 | re = 1; 70 | else if (S_ISDIR(stat.st_mode)) 71 | re = 2; 72 | return re; 73 | } 74 | 75 | /** 76 | * 获取文件最后修改时间 77 | */ 78 | time_t getFileMTime(const std::string &path) { 79 | aFun_stat stat; 80 | if (path.empty() || get_stat(stat, path) != 0) 81 | return 0; 82 | return stat.st_mtime; 83 | } 84 | 85 | /** 86 | * @param path 文件路径 (utf-8) 87 | * @return 文件大小 88 | */ 89 | uintmax_t getFileSize(const std::string &path) { 90 | aFun_stat stat; 91 | int ret; 92 | ret = get_stat(stat, path); 93 | if(ret != 0) 94 | return 0; // 获取失败。 95 | return (uintmax_t)stat.st_size; // 返回文件大小 96 | } 97 | 98 | /** 99 | * 打开指定文件 100 | * @param path_ 路径 (utf-8) 101 | * @param mode_ 模式 102 | * @return 103 | */ 104 | FILE *fileOpen(const char *path_, const char *mode_) { 105 | if (strlen(mode_) >= 5) 106 | return nullptr; 107 | #ifdef AFUN_WIN32_NO_CYGWIN 108 | FILE *file = nullptr; 109 | wchar_t *path = nullptr; 110 | wchar_t mode[5]; 111 | if (convertWideByte(&path, path_, CP_UTF8) == 0) 112 | return nullptr; 113 | for (int i = 0; i < 5; i++) 114 | mode[i] = (wchar_t)mode_[i]; // ascii字符转换 115 | 116 | _wfopen_s(&file, path, mode); 117 | safeFree(path); 118 | return file; 119 | #else 120 | return fopen(path_, mode_); 121 | #endif 122 | } 123 | 124 | FILE *fileOpen(const std::string &path_, const char *mode_) { 125 | return fileOpen(path_.c_str(), mode_); 126 | } 127 | 128 | /** 129 | * 关闭文件, 本质和fclose一样 130 | * @param file FILE 131 | * @return 132 | */ 133 | int fileClose(FILE *file) { 134 | return fclose(file); 135 | } 136 | 137 | #ifndef AFUN_TOOL_C 138 | } 139 | #endif 140 | -------------------------------------------------------------------------------- /lang/hgt.cmake: -------------------------------------------------------------------------------- 1 | find_package(Python3 REQUIRED) 2 | 3 | set(hgt_dir ${CMAKE_BINARY_DIR}/hgt) # hgt 文件储存位置 4 | file(MAKE_DIRECTORY ${hgt_dir}) 5 | 6 | to_native_path(${hgt_dir} hgt_dir_n) # hgt 温江储存位置 7 | to_native_path(${CMAKE_CURRENT_LIST_DIR}/tr tr_n) # tr 文件储存位置 8 | to_native_path(${CMAKE_SOURCE_DIR}/src src_n) # src 文件储存位置 【需要遍历】 9 | to_native_path(${CMAKE_SOURCE_DIR}/include include_n) # include 文件位置 【需要遍历】 10 | set(hgt_name aFun) # ht 名称 11 | 12 | set(HGT_COMMAND 13 | "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/hgt.py" 14 | ${hgt_dir_n} 15 | baseHTExport 16 | BASEHT_EXPORT 17 | ${tr_n} 18 | ${hgt_name} 19 | ${src_n} 20 | ${include_n}) 21 | 22 | unset(hgt_dir_n) 23 | unset(tr_n) 24 | unset(src_n) 25 | unset(include_n) 26 | 27 | add_custom_target(hgt ALL) 28 | add_custom_command(TARGET hgt POST_BUILD 29 | COMMAND ${HGT_COMMAND} 30 | COMMENT "The hgt generate file: base" 31 | VERBATIM) 32 | 33 | execute_process(COMMAND ${HGT_COMMAND} 34 | RESULT_VARIABLE re 35 | OUTPUT_VARIABLE output 36 | ERROR_VARIABLE errput) 37 | 38 | if (re) 39 | # 运行失败 40 | message(FATAL_ERROR "hgt error[${re}]\n${errput}") 41 | endif() 42 | 43 | add_library(hgt-base SHARED) 44 | target_sources(hgt-base 45 | PRIVATE ${hgt_dir}/${hgt_name}_ht.c 46 | PUBLIC $ $) 47 | target_link_libraries(hgt-base ${dlfcn_lib}) 48 | add_dependencies(hgt-base hgt) 49 | 50 | include(GenerateExportHeader) 51 | generate_export_header(hgt-base EXPORT_FILE_NAME "${hgt_dir}/baseHTExport.h" BASE_NAME "baseHT") 52 | 53 | target_include_directories(hgt-base PUBLIC 54 | $ 55 | $) 56 | set_target_properties(hgt-base PROPERTIES 57 | PUBLIC_HEADER "${hgt_dir}/${hgt_name}_ht.h" 58 | OUTPUT_NAME "aFunlangTr") 59 | 60 | install(TARGETS hgt-base 61 | EXPORT aFunlang 62 | RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT runtime 63 | ARCHIVE DESTINATION ${INSTALL_LIBDIR} COMPONENT dev 64 | LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT runtime 65 | PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT dev 66 | PRIVATE_HEADER DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT unsafe-dev) 67 | 68 | file(GLOB tr 69 | LIST_DIRECTORIES FALSE 70 | ${hgt_dir}/tr/*.c) 71 | 72 | function(build_lang) 73 | foreach(src IN LISTS tr) 74 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${INSTALL_LANGDIR}) 75 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${INSTALL_LANGDIR}) 76 | 77 | cmake_path(GET src STEM name) 78 | add_library(hgt-${name} SHARED ${src}) 79 | add_dependencies(hgt-${name} hgt-base) 80 | add_custom_command(TARGET hgt-${name} POST_BUILD 81 | COMMAND ${CMAKE_COMMAND} -E echo "$" ">>" "LANG" 82 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/${INSTALL_LANGDIR}" 83 | COMMENT "Creat file ${CMAKE_BINARY_DIR}/${INSTALL_LANGDIR}/LANG") 84 | 85 | set_target_properties(hgt-${name} PROPERTIES OUTPUT_NAME "${name}") 86 | 87 | target_compile_definitions(hgt-${name} PRIVATE hgt_base_EXPORTS) 88 | target_include_directories(hgt-${name} PUBLIC ${hgt_dir}) 89 | 90 | install(TARGETS hgt-${name} 91 | RUNTIME DESTINATION ${INSTALL_LANGDIR} COMPONENT runtime 92 | LIBRARY DESTINATION ${INSTALL_LANGDIR} COMPONENT runtime) 93 | endforeach() 94 | endfunction() 95 | 96 | build_lang() # 使用函数防止 CMAKE_RUNTIME_OUTPUT_DIRECTORY 影响外部 97 | unset(hgt-name) 98 | -------------------------------------------------------------------------------- /src/core/inter.cpp: -------------------------------------------------------------------------------- 1 | #include "core_inter.h" 2 | #include "core_activation.h" 3 | #include "core_logger.h" 4 | #include "core_exception.h" 5 | 6 | namespace aFuncore { 7 | Inter::Inter(Environment &env_) 8 | : status{inter_init}, env{env_}, activation{nullptr}, out{}, in{} { 9 | env++; 10 | } 11 | 12 | Inter::Inter(const Inter &base_inter) 13 | : status{inter_init}, env{base_inter.env}, activation{nullptr}, out{}, in{}{ 14 | for (auto &i: base_inter.literal) 15 | literal.push_back(i); 16 | env++; 17 | } 18 | 19 | Inter::~Inter(){ 20 | env--; 21 | } 22 | 23 | /** 24 | * 使能 (激活解释器) 25 | */ 26 | void Inter::enable(){ 27 | if (status == inter_init) { 28 | status = inter_normal; 29 | } 30 | } 31 | 32 | /** 33 | * 运行代码(直接运行activation) 34 | * @return 35 | */ 36 | bool Inter::runCode(){ 37 | if (status == inter_stop) 38 | status = inter_normal; 39 | 40 | while (activation != nullptr) { 41 | if (isInterStop()) { 42 | while (activation != nullptr) 43 | delete popActivation(); 44 | return false; 45 | } 46 | 47 | const aFuncode::Code::ByteCode *code = nullptr; 48 | Activation::ActivationStatus as = activation->getCode(code); 49 | switch (as) { 50 | case Activation::as_end: { 51 | delete popActivation(); 52 | break; 53 | } 54 | case Activation::as_run: 55 | activation->runCode(code); 56 | break; 57 | case Activation::as_end_run: 58 | activation->endRun(); 59 | break; 60 | default: 61 | errorLog(aFunCoreLogger, "Error activation status."); 62 | delete popActivation(); 63 | break; 64 | } 65 | } 66 | return true; 67 | } 68 | 69 | /** 70 | * 检查字面量是否匹配 71 | * @param element 字面量 72 | * @return 73 | */ 74 | bool Inter::checkLiteral(const std::string &element) const{ 75 | if (literal.empty()) 76 | return false; 77 | 78 | for (auto &i: literal) { 79 | try { 80 | if (i.rg.match(element) != 1) 81 | continue; 82 | return true; 83 | } catch (aFuntool::RegexException &) { 84 | continue; 85 | } 86 | } 87 | return false; 88 | } 89 | 90 | /** 91 | * 检查字面量正则匹配 92 | * @param element 字面量 93 | * @param literaler 函数 94 | * @param in_protect 是否保护空间 95 | * @return 96 | */ 97 | bool Inter::checkLiteral(const std::string &element, std::string &literaler, bool &in_protect) const{ 98 | if (literal.empty()) 99 | return false; 100 | 101 | for (auto &i: literal) { 102 | try { 103 | if (i.rg.match(element) != 1) 104 | continue; 105 | literaler = i.literaler; 106 | in_protect = i.in_protect; 107 | return true; 108 | } catch (aFuntool::RegexException &) { 109 | continue; 110 | } 111 | } 112 | return false; 113 | } 114 | 115 | bool Inter::pushLiteral(const std::string &pattern, const std::string &literaler, bool in_protect){ 116 | try { 117 | literal.push_front({aFuntool::Regex(pattern), pattern, literaler, in_protect}); 118 | } catch (aFuntool::RegexException &) { 119 | return false; 120 | } 121 | return true; 122 | } 123 | } -------------------------------------------------------------------------------- /src/core/env_var.cpp: -------------------------------------------------------------------------------- 1 | #include "core_env_var.h" 2 | #include "core_object.h" 3 | 4 | namespace aFuncore { 5 | EnvVarSpace::~EnvVarSpace() { 6 | for (auto &i : var) { 7 | if (i.second.object != nullptr) 8 | i.second.object->delReference(); 9 | } 10 | } 11 | 12 | /** 13 | * 获取环境变量文本 14 | * @param name 变量名 15 | * @param str 文本 16 | * @return 是否成功 17 | */ 18 | bool EnvVarSpace::findString(const std::string &name, std::string &str) { 19 | std::unique_lock mutex{lock}; 20 | auto env_var = var.find(name); 21 | if (env_var == var.end()) 22 | return false; 23 | str = env_var->second.str; 24 | return true; 25 | } 26 | 27 | /** 28 | * 获取环境变量数值 29 | * @param name 变量名 30 | * @param num 文本 31 | * @return 是否成功 32 | */ 33 | bool EnvVarSpace::findNumber(const std::string &name, int32_t &num) { 34 | std::unique_lock mutex{lock}; 35 | auto env_var = var.find(name); 36 | if (env_var == var.end()) 37 | return false; 38 | num = env_var->second.num; 39 | return true; 40 | } 41 | 42 | bool EnvVarSpace::findObject(const std::string &name, Object *&obj) { 43 | std::unique_lock mutex{lock}; 44 | auto env_var = var.find(name); 45 | if (env_var == var.end()) 46 | return false; 47 | obj = env_var->second.object; 48 | return true; 49 | } 50 | 51 | /** 52 | * 设置环境变量文本 53 | * @param name 变量名 54 | * @param str 文本 55 | */ 56 | void EnvVarSpace::setString(const std::string &name, const std::string &str){ 57 | std::unique_lock mutex{lock}; 58 | auto env_var = var.find(name); 59 | if (env_var == var.end()) 60 | var.insert({name, {str, 0, nullptr}}); 61 | else 62 | env_var->second.str = str; 63 | } 64 | 65 | /** 66 | * 设置环境变量数值 67 | * @param name 变量名 68 | * @param num 数值 69 | */ 70 | void EnvVarSpace::setNumber(const std::string &name, int32_t num){ 71 | std::unique_lock mutex{lock}; 72 | auto env_var = var.find(name); 73 | if (env_var == var.end()) 74 | var.insert({name, {"", num, nullptr}}); 75 | else 76 | env_var->second.num = num; 77 | } 78 | 79 | void EnvVarSpace::setObject(const std::string &name, Object *obj) { 80 | std::unique_lock mutex{lock}; 81 | obj->addReference(); 82 | auto env_var = var.find(name); 83 | if (env_var == var.end()) 84 | var.insert({name, {"", 0, obj}}); 85 | else { 86 | if (env_var->second.object != nullptr) 87 | env_var->second.object->delReference(); 88 | env_var->second.object = obj; 89 | } 90 | } 91 | 92 | /** 93 | * 设置环境变量文本 (加法) 94 | * @param name 变量名 95 | * @param str 文本 96 | */ 97 | void EnvVarSpace::addString(const std::string &name, const std::string &str){ 98 | std::unique_lock mutex{lock}; 99 | auto env_var = var.find(name); 100 | if (env_var == var.end()) 101 | var.insert({name, {str, 0, nullptr}}); 102 | else 103 | env_var->second.str += str; 104 | } 105 | 106 | /** 107 | * 设置环境变量数值 (加法) 108 | * @param name 变量名 109 | * @param num 数值 110 | */ 111 | void EnvVarSpace::addNumber(const std::string &name, int32_t num){ 112 | std::unique_lock mutex{lock}; 113 | auto env_var = var.find(name); 114 | if (env_var == var.end()) 115 | var.insert({name, {"", num, nullptr}}); 116 | else 117 | env_var->second.num += num; 118 | } 119 | } -------------------------------------------------------------------------------- /src/parser/reader.cpp: -------------------------------------------------------------------------------- 1 | #include "parser_reader.h" 2 | #include "parser_logger.h" 3 | 4 | namespace aFunparser { 5 | Reader::~Reader() { 6 | aFuntool::safeFree(buf); 7 | } 8 | 9 | char *Reader::readWord(size_t del_index) { 10 | char *re; 11 | ReadMode mode = read_mode_normal; 12 | read = buf; // 重置指针 13 | 14 | if (del_index == 0) 15 | return aFuntool::strCopy(""); // 返回空字符串 16 | 17 | re = aFuntool::safeCalloc(del_index + 1); 18 | memcpy(re, buf, del_index); // 复制旧字符串 19 | memmove(buf, buf + del_index, buf_size - del_index + 1); // +1是为了涵盖NUL 20 | 21 | if (!read_end) { // 没到尾部, 则写入数据 22 | char *write = buf + strlen(buf); // 数据写入的位置 23 | size_t len_ = buf_size - strlen(buf); 24 | size_t len = readText(write, len_, mode); 25 | if (len > len_) 26 | len = len_; 27 | *(write + len) = aFuntool::NUL; 28 | } 29 | 30 | if (mode == read_mode_finished) 31 | read_end = true; 32 | else if (mode == read_mode_error) { 33 | read_end = true; 34 | read_error = true; 35 | } 36 | 37 | /* 计算行号 */ 38 | for (char *tmp = re; *tmp != aFuntool::NUL; tmp ++) { 39 | if (*tmp == '\n') 40 | line++; 41 | } 42 | 43 | if (!aFuntool::isCharUTF8(re)) { 44 | aFuntool::safeFree(re); 45 | errorLog(aFunParserLogger, "Is not utf-8"); 46 | return nullptr; 47 | } 48 | 49 | return re; 50 | } 51 | 52 | void Reader::readFirstWord() { 53 | ReadMode mode = read_mode_normal; 54 | read = buf; // 重置指针 55 | 56 | char *write = buf + strlen(buf); // 数据写入的位置 57 | size_t len_ = buf_size - strlen(buf); 58 | size_t len = readText(write, len_, mode); 59 | if (len > len_) 60 | len = len_; 61 | *(write + len) = aFuntool::NUL; 62 | 63 | if (mode == read_mode_finished) 64 | read_end = true; 65 | else if (mode == read_mode_error) { 66 | read_end = true; 67 | read_error = true; 68 | } 69 | } 70 | 71 | char Reader::getChar() { 72 | char ch = *read; 73 | if (ch != aFuntool::NUL) { // 未读取到末尾 74 | read++; 75 | return ch; 76 | } else if (read_end) // 读取到末尾, 且无新内容 77 | return aFuntool::NUL; 78 | 79 | if (read == buf + buf_size) { 80 | char *new_buf = aFuntool::safeCalloc(buf_size + NEW_BUF_SIZE + 1); 81 | memcpy(new_buf, buf, buf_size); 82 | 83 | ReadMode mode = read_mode_normal; 84 | size_t len = readText(new_buf + buf_size, NEW_BUF_SIZE, mode); 85 | if (len > NEW_BUF_SIZE) 86 | len = NEW_BUF_SIZE; 87 | *(new_buf + buf_size + len) = aFuntool::NUL; 88 | 89 | if (mode == read_mode_finished) 90 | read_end = true; 91 | else if (mode == read_mode_error) { 92 | read_end = true; 93 | read_error = true; 94 | } 95 | 96 | aFuntool::safeFree(buf); 97 | buf = new_buf; 98 | buf_size = buf_size + NEW_BUF_SIZE; 99 | read = buf + buf_size - NEW_BUF_SIZE; // 当前读取的位置 100 | } else { 101 | ReadMode mode = read_mode_normal; 102 | size_t len_ = buf_size - (read - buf); // 总长度 - (已读取长度) = 剩余空白 103 | size_t len = readText(read, len_, mode); 104 | if (len > len_) 105 | len = len_; 106 | *(read + len) = aFuntool::NUL; 107 | } 108 | 109 | ch = *read; 110 | if (ch != aFuntool::NUL) 111 | read++; 112 | return ch; 113 | } 114 | } -------------------------------------------------------------------------------- /include/code/code.h: -------------------------------------------------------------------------------- 1 | #ifndef AFUN_CODE_H 2 | #define AFUN_CODE_H 3 | #include "aFuntool.h" 4 | #include "aFunCodeExport.h" 5 | 6 | namespace aFuncode { 7 | class AFUN_CODE_EXPORT Code { 8 | public: 9 | class ByteCode; 10 | 11 | AFUN_INLINE explicit Code(aFuntool::FilePath file_); 12 | ~Code(); 13 | Code &operator=(const Code &)=delete; 14 | 15 | [[nodiscard]] std::string getMD5_v1() const; 16 | bool writeByteCode(const aFuntool::FilePath &file_path, bool debug=false) const; // NOLINT 允许忽略返回值 17 | bool readByteCode(const aFuntool::FilePath &file_path); 18 | 19 | #ifdef AFUN_DEBUG 20 | void display() const; 21 | #endif 22 | 23 | [[nodiscard]] AFUN_INLINE const aFuntool::FilePath &getFilePath() const; 24 | [[nodiscard]] AFUN_INLINE ByteCode *getByteCode() const; 25 | private: 26 | ByteCode *code; 27 | aFuntool::FilePath file; 28 | 29 | bool write_v1(FILE *f, bool debug=false) const; 30 | bool read_v1(FILE *f, bool debug=false); 31 | }; 32 | 33 | class AFUN_CODE_EXPORT Code::ByteCode { 34 | friend class Code; 35 | public: 36 | typedef enum CodeType { 37 | code_start = 0, 38 | code_element = 1, 39 | code_block = 2, 40 | } CodeType; 41 | 42 | typedef enum BlockType { 43 | block_p = '(', 44 | block_b = '[', 45 | block_c = '{', 46 | } BlockType; 47 | 48 | AFUN_STATIC constexpr const char *E_PREFIX = "$`'"; /* element前缀 */ 49 | AFUN_STATIC constexpr const char *B_PREFIX = "$`'%^&"; /* block前缀 */ 50 | AFUN_STATIC constexpr const char *ALL_PREFIX = "$`'%^&"; /* 所有前缀 */ 51 | 52 | explicit ByteCode(Code &belong, aFuntool::FileLine line); 53 | ByteCode(Code &belong, const std::string &element, aFuntool::FileLine line, char prefix=aFuntool::NUL); 54 | ByteCode(Code &belong, BlockType block_type, ByteCode *son, aFuntool::FileLine line, char prefix=aFuntool::NUL); 55 | ByteCode &operator=(const ByteCode &)=delete; 56 | 57 | ByteCode *connect(ByteCode *new_code); 58 | bool write_v1(FILE *f, bool debug=false) const; 59 | ByteCode *read_v1(FILE *f, bool debug=false, int8_t read_type=code_element, bool to_son=false); 60 | [[nodiscard]] std::string getMD5_v1() const; 61 | 62 | #ifdef AFUN_DEBUG 63 | void display() const; 64 | #endif 65 | 66 | [[nodiscard]] AFUN_INLINE CodeType getType() const; 67 | [[nodiscard]] AFUN_INLINE char getPrefix() const; 68 | 69 | [[nodiscard]] AFUN_INLINE const char *getElement() const; 70 | [[nodiscard]] AFUN_INLINE BlockType getBlockType() const; 71 | [[nodiscard]] AFUN_INLINE ByteCode *getSon() const; 72 | [[nodiscard]] AFUN_INLINE aFuntool::FileLine getFileLine() const; 73 | [[nodiscard]] AFUN_INLINE const aFuntool::FilePath &getFilePath() const; 74 | 75 | [[nodiscard]] AFUN_INLINE ByteCode *toNext() const; 76 | [[nodiscard]] AFUN_INLINE ByteCode *toPrev() const; 77 | [[nodiscard]] AFUN_INLINE ByteCode *toFather() const; 78 | 79 | private: 80 | CodeType type; 81 | char prefix=aFuntool::NUL; 82 | 83 | union CodeData { 84 | char *element; // union 内不使用 std::string 85 | struct Block { // NOLINT 不需要初始化 86 | BlockType block_type; 87 | ByteCode *son; 88 | } block; 89 | AFUN_INLINE CodeData(); 90 | } data; 91 | 92 | ByteCode *father = nullptr; 93 | ByteCode *next = nullptr; 94 | ByteCode *prev = nullptr; 95 | 96 | Code &belong; 97 | aFuntool::FileLine line; 98 | 99 | ~ByteCode(); // 限制 ByteCode 只能建立在堆上 100 | }; 101 | } 102 | 103 | #include "code.inline.h" 104 | 105 | #endif //AFUN_CODE_H 106 | --------------------------------------------------------------------------------