From 6ff2305a7497be4a31434960336337206b8ca400 Mon Sep 17 00:00:00 2001 From: joey <1166538+xtjoeytx@users.noreply.github.com> Date: Sat, 7 Feb 2026 11:53:35 -0500 Subject: [PATCH 1/6] Refactor file structure, cmake changes & memory improvements (#25) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Summary This PR modernizes and restructures the project layout, refactors build and interface code, and adds a faster arena-based allocation system for parser AST nodes. Legacy scripts and outdated test files were removed. ### Key Changes **Project & Build Updates** * Renamed the project from **gs2test** → **gs2parser** and improved build hygiene by using `${CMAKE_BINARY_DIR}` for outputs. * Reorganized source code into clear module subdirectories (`ast/`, `parser/`, `compiler/`, `memory/`, etc.). * Added automatic export header generation for proper shared library support. * Moved JS and C bindings into `bindings/js/` and `bindings/c/` with updated includes. **CI & Script Cleanup** * Updated `Jenkinsfile` and `package.json` to match new naming/output conventions. * Removed obsolete legacy/test scripts. **Parser & Memory Improvements** * Introduced a high-performance **ArenaAllocator** for AST node allocation. * Refactored `ParserContext` and parser code to allocate nodes through the arena, enabling fast bulk cleanup and better cache locality. * Simplified allocation/lifetime handling and added cleaner debug stats. **Codebase Refactoring** * Consolidated compiler logic under `src/compiler/`. * Updated visitor structure (`astvisitor.h` → `NodeVisitor.h`). * Renamed and reorganized Rust bindings and codegen/compiler files for consistency. * Removed fmtlib dependency from submodules ### Impact The repo is now cleaner and more modular, supporting multi-target builds (native, shared/static, JS, C, Rust). Parser performance and memory behavior are significantly improved, and CI/build outputs are more reliable. --- .gitignore | 21 +- .gitmodules | 3 - CMakeLists.txt | 148 +- Jenkinsfile | 17 +- {src => bindings/c}/c_interface.cpp | 2 +- {src => bindings/js}/js_interface.cpp | 2 +- Cargo.lock => bindings/rust/Cargo.lock | 0 Cargo.toml => bindings/rust/Cargo.toml | 3 + build.rs => bindings/rust/build.rs | 18 +- {src => bindings/rust}/lib.rs | 2 +- dependencies/fmtlib | 1 - package.json | 2 +- scripts/asd2.txt | 202 -- scripts/syntax-test.txt | 42 - scripts/testscript.txt | 1898 ----------------- src/CompilerThreadJob.h | 2 +- src/ast/{astvisitor.h => NodeVisitor.h} | 4 +- src/ast/ast.h | 2 +- src/{ => codegen}/GS2Bytecode.cpp | 0 src/{ => codegen}/GS2Bytecode.h | 0 src/{ => compiler}/GS2BuiltInFunctions.cpp | 0 src/{ => compiler}/GS2BuiltInFunctions.h | 0 .../GS2CompilerVisitor.cpp | 4 +- .../GS2CompilerVisitor.h | 2 +- src/{ => compiler}/GS2Context.cpp | 2 +- src/{ => compiler}/GS2Context.h | 3 +- src/main.cpp | 2 +- src/memory/ArenaAllocator.h | 120 ++ src/{ => parser}/Parser.cpp | 12 +- src/{ => parser}/Parser.h | 31 +- {generator => src/parser}/gs2parser.y | 0 {generator => src/parser}/gs2scanner.l | 0 .../ASTNodeVisitor.h} | 2 +- src/visitors/FunctionInspectVisitor.h | 2 +- test-workflow.sh | 197 -- tests/tools/run_tests.py | 1 + 36 files changed, 281 insertions(+), 2466 deletions(-) rename {src => bindings/c}/c_interface.cpp (99%) rename {src => bindings/js}/js_interface.cpp (97%) rename Cargo.lock => bindings/rust/Cargo.lock (100%) rename Cargo.toml => bindings/rust/Cargo.toml (86%) rename build.rs => bindings/rust/build.rs (72%) rename {src => bindings/rust}/lib.rs (99%) delete mode 160000 dependencies/fmtlib delete mode 100644 scripts/asd2.txt delete mode 100644 scripts/syntax-test.txt delete mode 100644 scripts/testscript.txt rename src/ast/{astvisitor.h => NodeVisitor.h} (96%) rename src/{ => codegen}/GS2Bytecode.cpp (100%) rename src/{ => codegen}/GS2Bytecode.h (100%) rename src/{ => compiler}/GS2BuiltInFunctions.cpp (100%) rename src/{ => compiler}/GS2BuiltInFunctions.h (100%) rename src/{visitors => compiler}/GS2CompilerVisitor.cpp (99%) rename src/{visitors => compiler}/GS2CompilerVisitor.h (99%) rename src/{ => compiler}/GS2Context.cpp (98%) rename src/{ => compiler}/GS2Context.h (96%) create mode 100644 src/memory/ArenaAllocator.h rename src/{ => parser}/Parser.cpp (94%) rename src/{ => parser}/Parser.h (89%) rename {generator => src/parser}/gs2parser.y (100%) rename {generator => src/parser}/gs2scanner.l (100%) rename src/{ast/astnodevisitor.h => visitors/ASTNodeVisitor.h} (99%) delete mode 100755 test-workflow.sh diff --git a/.gitignore b/.gitignore index dc30f00..9b3ee8c 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,24 @@ bin/ # CLion cmake-build-*/ - # Added by cargo - /target + +# act (GitHub Actions local testing) +.actrc +.secrets + +# GS2 bytecode files +*.gs2bc + +# Python cache +__pycache__/ +*.pyc +*.pyo + +# macOS +.DS_Store + +# Test artifacts (generated in build directory, but ignore strays) +tests/reports/*.json +tests/outputs/ diff --git a/.gitmodules b/.gitmodules index 5c96a90..0445495 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "dependencies/fmtlib"] - path = dependencies/fmtlib - url = https://github.com/fmtlib/fmt.git [submodule "dependencies/winflexbison"] path = dependencies/winflexbison url = https://github.com/lexxmark/winflexbison.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 25bb465..ec63432 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ -cmake_minimum_required(VERSION 3.10) -project(gs2test VERSION 1.0) +cmake_minimum_required(VERSION 3.14) +project(gs2parser VERSION 1.0) +include(GenerateExportHeader) set(CMAKE_DEBUG_POSTFIX _d) @@ -10,21 +11,19 @@ set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# Set up output directories -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/${BIN_DIR}) +# Set up output directories in the build tree +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${BIN_DIR}) # Second, for multi-config builds (e.g. msvc) foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) - set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_SOURCE_DIR}/lib ) - set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_SOURCE_DIR}/lib ) - set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${PROJECT_SOURCE_DIR}/${BIN_DIR} ) + set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib ) + set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib ) + set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${BIN_DIR} ) endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) -link_directories(${PROJECT_SOURCE_DIR}/lib) - if(WIN32 OR APPLE) set(CMAKE_SHARED_LIBRARY_PREFIX "") set(CMAKE_STATIC_LIBRARY_PREFIX "lib") @@ -44,76 +43,111 @@ endif(WIN32 AND NOT MINGW) find_package(BISON 3.4 REQUIRED) find_package(FLEX REQUIRED) -BISON_TARGET(GS2Parser generator/gs2parser.y ${CMAKE_CURRENT_BINARY_DIR}/gs2parser.tab.cc) -FLEX_TARGET(GS2Scanner generator/gs2scanner.l ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.cc DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.h COMPILE_FLAGS "${FLEX_FLAGS}") +BISON_TARGET(GS2Parser src/parser/gs2parser.y ${CMAKE_CURRENT_BINARY_DIR}/gs2parser.tab.cc) +FLEX_TARGET(GS2Scanner src/parser/gs2scanner.l ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.cc DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.h COMPILE_FLAGS "${FLEX_FLAGS}") ADD_FLEX_BISON_DEPENDENCY(GS2Scanner GS2Parser) -include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - src -) - -set(SOURCES_ALL +set(SOURCES + # AST src/ast/ast.cpp + + # Encoding src/encoding/buffer.cpp - src/visitors/GS2CompilerVisitor.cpp - src/GS2BuiltInFunctions.cpp - src/GS2Bytecode.cpp - src/GS2Context.cpp - src/Parser.cpp - src/c_interface.cpp + # Codegen + src/codegen/GS2Bytecode.cpp + + # Compiler + src/compiler/GS2BuiltInFunctions.cpp + src/compiler/GS2CompilerVisitor.cpp + src/compiler/GS2Context.cpp + + # Parser + src/parser/Parser.cpp + ${BISON_GS2Parser_OUTPUTS} + ${FLEX_GS2Scanner_OUTPUTS} +) + +set(HEADERS + # AST src/ast/ast.h - src/ast/astvisitor.h - src/ast/astnodevisitor.h src/ast/expressiontypes.h + src/ast/NodeVisitor.h + + # Encoding src/encoding/buffer.h src/encoding/graalencoding.h - src/utils/EventHandler.h - src/exceptions/GS2CompilerError.h - src/utils/ContextThreadPool.h + + # Codegen + src/codegen/GS2Bytecode.h + + # Compiler + src/compiler/GS2BuiltInFunctions.h + src/compiler/GS2CompilerVisitor.h + src/compiler/GS2Context.h + + # Parser + src/parser/Parser.h + ${BISON_GS2Parser_INPUT} + ${FLEX_GS2Scanner_INPUT} + + # Memory + src/memory/ArenaAllocator.h + + # Visitors + src/visitors/ASTNodeVisitor.h src/visitors/FunctionInspectVisitor.h - src/visitors/GS2CompilerVisitor.h src/visitors/GS2SourceVisitor.h + + # Utils / Misc src/CompilerThreadJob.h - src/GS2BuiltInFunctions.h - src/GS2Bytecode.h - src/GS2Context.h + src/exceptions/GS2CompilerError.h src/opcodes.h - src/Parser.h + src/utils/ContextThreadPool.h + src/utils/EventHandler.h +) - ${BISON_GS2Parser_INPUT} - ${FLEX_GS2Scanner_INPUT} - ${BISON_GS2Parser_OUTPUTS} - ${FLEX_GS2Scanner_OUTPUTS}) +set(SOURCES_ALL ${SOURCES} ${HEADERS}) -if (DEFINED EMSCRIPTEN) - add_executable(gs2test ${SOURCES_ALL} src/js_interface.cpp) - set_target_properties(gs2test PROPERTIES LINK_FLAGS "--embind-emit-tsd=gs2test.d.ts -s ENVIRONMENT=web -s DYNAMIC_EXECUTION=0 -s SINGLE_FILE=1 -s MODULARIZE -s 'EXPORT_NAME=GS2Compiler' --bind") -else() - add_executable(gs2test ${SOURCES_ALL} src/main.cpp) +# Use standard BUILD_SHARED_LIBS; Emscripten doesn't support shared libs +if(EMSCRIPTEN) + set(BUILD_SHARED_LIBS OFF) endif() +option(BUILD_SHARED_LIBS "Build shared libraries" ON) -if (STATIC) - add_library(gs2compiler STATIC ${SOURCES_ALL}) -else() - add_library(gs2compiler SHARED ${SOURCES_ALL}) +add_library(gs2compiler ${SOURCES_ALL} bindings/c/c_interface.cpp) +generate_export_header(gs2compiler + BASE_NAME GS2COMPILER + EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/gs2compiler_export.h +) + +target_include_directories(gs2compiler + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/parser + ${CMAKE_CURRENT_SOURCE_DIR}/src/codegen + ${CMAKE_CURRENT_SOURCE_DIR}/src/compiler + ${CMAKE_CURRENT_SOURCE_DIR}/src/encoding + ${CMAKE_CURRENT_SOURCE_DIR}/src/memory +) + +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(gs2compiler PUBLIC GS2COMPILER_STATIC_DEFINE) endif() if(WIN32 AND MINGW) target_compile_options(gs2compiler PRIVATE "-fno-rtti") endif() -set_property(TARGET gs2test PROPERTY CXX_STANDARD 23) -set_property(TARGET gs2compiler PROPERTY CXX_STANDARD 23) - -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - set(GS2COMPILER_INCLUDE_DIRECTORY - "${PROJECT_SOURCE_DIR}/include" - "${PROJECT_BINARY_DIR}/include" - "${PROJECT_SOURCE_DIR}/src" - PARENT_SCOPE) +if(EMSCRIPTEN) + add_executable(gs2test bindings/js/js_interface.cpp) + set_target_properties(gs2test PROPERTIES LINK_FLAGS "--embind-emit-tsd=gs2test.d.ts -s ENVIRONMENT=web -s DYNAMIC_EXECUTION=0 -s SINGLE_FILE=1 -s MODULARIZE -s 'EXPORT_NAME=GS2Compiler' --bind") +else() + add_executable(gs2test src/main.cpp) endif() +target_link_libraries(gs2test PRIVATE gs2compiler) # Test suite integration # Only configure tests if this is the main project (not a subproject) diff --git a/Jenkinsfile b/Jenkinsfile index ea62262..ee10ba0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -66,9 +66,7 @@ def buildStep(dockerImage, generator, os, osdir, defines) { } sh("mkdir -p build/"); - sh("mkdir -p lib/"); sh("rm -rfv build/*"); - sh("rm -rfv lib/*"); discordSend(description: "", footer: "", link: env.BUILD_URL, result: currentBuild.currentResult, title: "[${split_job_name[0]}] Starting ${os} build target...", webhookURL: env.GS2EMU_WEBHOOK); @@ -77,8 +75,8 @@ def buildStep(dockerImage, generator, os, osdir, defines) { sh("cmake --build . --config Release --target all -- -j `nproc`"); } - archiveArtifacts(artifacts: 'lib/*.dylib,lib/*.so,bin/*.dll', allowEmptyArchive: true); - stash(name: osdir, includes: 'lib/*.dylib,lib/*.so,bin/*.dll', allowEmpty: true); + archiveArtifacts(artifacts: 'build/lib/*.dylib,build/lib/*.so,build/bin/*.dll', allowEmptyArchive: true); + stash(name: osdir, includes: 'build/lib/*.dylib,build/lib/*.so,build/bin/*.dll', allowEmpty: true); discordSend(description: "", footer: "", link: env.BUILD_URL, result: currentBuild.currentResult, title: "[${split_job_name[0]}] Build ${fixed_job_name} #${env.BUILD_NUMBER} Target: ${os} successful!", webhookURL: env.GS2EMU_WEBHOOK); } @@ -277,12 +275,15 @@ killall_jobs(); dir("bindings/dotnet/cross-compile/${v.OSDir}/") { unstash(name: v.OSDir); try { - sh("mv -fv bin/* ."); - sh("rm -rf bin") + sh("mv -fv build/bin/* ."); + sh("rm -rf build/bin") } catch(err) { } try { - sh("mv -fv lib/* ."); - sh("rm -rf lib") + sh("mv -fv build/lib/* ."); + sh("rm -rf build/lib") + } catch(err) { } + try { + sh("rm -rf build") } catch(err) { } } } diff --git a/src/c_interface.cpp b/bindings/c/c_interface.cpp similarity index 99% rename from src/c_interface.cpp rename to bindings/c/c_interface.cpp index ed14848..d626e14 100644 --- a/src/c_interface.cpp +++ b/bindings/c/c_interface.cpp @@ -1,4 +1,4 @@ -#include "GS2Context.h" +#include "compiler/GS2Context.h" #ifdef _WIN32 #define DLL_EXPORT __declspec(dllexport) diff --git a/src/js_interface.cpp b/bindings/js/js_interface.cpp similarity index 97% rename from src/js_interface.cpp rename to bindings/js/js_interface.cpp index 2fa39b8..3d0578c 100644 --- a/src/js_interface.cpp +++ b/bindings/js/js_interface.cpp @@ -1,5 +1,5 @@ #include -#include "GS2Context.h" +#include "compiler/GS2Context.h" using namespace emscripten; EMSCRIPTEN_BINDINGS(module) { diff --git a/Cargo.lock b/bindings/rust/Cargo.lock similarity index 100% rename from Cargo.lock rename to bindings/rust/Cargo.lock diff --git a/Cargo.toml b/bindings/rust/Cargo.toml similarity index 86% rename from Cargo.toml rename to bindings/rust/Cargo.toml index f4417ba..9445203 100644 --- a/Cargo.toml +++ b/bindings/rust/Cargo.toml @@ -7,5 +7,8 @@ build = "build.rs" [dependencies] libc = "0.2.155" +[lib] +path = "lib.rs" + [build-dependencies] cmake = "0.1" \ No newline at end of file diff --git a/build.rs b/bindings/rust/build.rs similarity index 72% rename from build.rs rename to bindings/rust/build.rs index bba0957..6ce2d46 100644 --- a/build.rs +++ b/bindings/rust/build.rs @@ -4,23 +4,19 @@ use cmake::Config; // Constants for common library names const DEBUG_SUFFIX_GS2: &str = "_d"; -const DEBUG_SUFFIX_FMT: &str = "d"; -const STATIC_LIB_DIR: &str = "lib"; - fn main() { let profile = env::var("PROFILE").unwrap_or_else(|_| "release".to_string()); let target = env::var("TARGET").expect("TARGET environment variable not set"); // Determine the appropriate library names based on the profile and platform let gs2_compiler_lib = library_name("gs2compiler", &profile, DEBUG_SUFFIX_GS2, &target); - let fmt_lib = library_name("fmt", &profile, DEBUG_SUFFIX_FMT, &target); - let mut cmake_config = Config::new("."); - cmake_config.build_target("gs2compiler").define("STATIC", "ON"); + let mut cmake_config = Config::new("../.."); + cmake_config.build_target("gs2compiler").define("BUILD_SHARED_LIBS", "OFF"); let cpp_lib = configure_platform_specifics(&target, &mut cmake_config); - link_libraries(cmake_config.build(), cpp_lib, &gs2_compiler_lib, &fmt_lib); + link_libraries(cmake_config.build(), cpp_lib, &gs2_compiler_lib); } fn library_name(base: &str, profile: &str, debug_suffix: &str, target: &str) -> String { @@ -49,13 +45,11 @@ fn configure_platform_specifics(target: &str, cmake_config: &mut Config) -> &'st } } -fn link_libraries(lib_path: PathBuf, cpp_lib: &str, gs2_lib: &str, fmt_lib: &str) { - let lib_dir = env::current_dir().unwrap().join(STATIC_LIB_DIR); +fn link_libraries(lib_path: PathBuf, cpp_lib: &str, gs2_lib: &str) { + let build_lib_dir = lib_path.join("build").join("lib"); println!("cargo:rustc-link-lib=dylib={}", cpp_lib); - println!("cargo:rustc-link-search=native={}", lib_path.display()); - println!("cargo:rustc-link-search=native={}", lib_dir.display()); + println!("cargo:rustc-link-search=native={}", build_lib_dir.display()); println!("cargo:rustc-link-lib=static={}", gs2_lib); - println!("cargo:rustc-link-lib=static={}", fmt_lib); } diff --git a/src/lib.rs b/bindings/rust/lib.rs similarity index 99% rename from src/lib.rs rename to bindings/rust/lib.rs index f6d98d1..0d726d7 100644 --- a/src/lib.rs +++ b/bindings/rust/lib.rs @@ -11,7 +11,7 @@ pub struct Gs2CompilerResult { pub bytecode_size: u32, } -extern { +extern "C" { fn get_context() -> *mut c_void; fn compile_code_no_header(context: *mut c_void, code: *const c_char) -> Gs2CompilerResult; fn delete_context(context: *mut c_void); diff --git a/dependencies/fmtlib b/dependencies/fmtlib deleted file mode 160000 index 34caecd..0000000 --- a/dependencies/fmtlib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 34caecd6b6850adb3e57218dc28f14eaafd5cf0e diff --git a/package.json b/package.json index d92005f..5964d0c 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "dist/gs2test.js", "types": "dist/gs2test.d.ts", "scripts": { - "build": "mkdir -p dist && emcmake cmake -S. -Bbuild/ && cmake --build build/ -j$(nproc) && mv -fv ./bin/* ./dist/" + "build": "mkdir -p dist && emcmake cmake -S. -Bbuild/ && cmake --build build/ -j$(nproc) && mv -fv ./build/bin/* ./dist/" }, "keywords": [], "author": "xtjoeytx", diff --git a/scripts/asd2.txt b/scripts/asd2.txt deleted file mode 100644 index d692bd7..0000000 --- a/scripts/asd2.txt +++ /dev/null @@ -1,202 +0,0 @@ -//#CLIENTSIDE - -function onCreated() -{ - if (abcd == true && jfjf == false) { - dosomething(); - } - - continuething(); -} - -/* -// Variables -function onCreated() { - this.defaultGUI = "GUIContainer"; -} - -// Allows opening of GUIExplorer with -// Chat command: /guiexplorer - -function ChatBar.onAction() { - if (ChatBar.text == "/guiexplorer") { - ChatBar.text = ""; - createGUI(); - } -} - -// Create Main GUIExplorer - -function createGUI() { - new GuiWindowCtrl("GUIExplorer") { - profile = GuiBlueWindowProfile; - isexternal = true; - clientextent = true; - extent = "600,600"; - canresize = false; - destroyonhide = true; - text = "GUI Explorer"; - new GuiScrollCtrl("GUIExplorer_Scroll") { - profile = GuiBlueScrollProfile; - x = y = 10; - extent = "280,280"; - hScrollBar = "dynamic"; - vScrollBar = "dynamic"; - new GuiTreeViewCtrl("GUIExplorer_Tree") { - profile = GuiBlueTreeViewProfile; - x = y = 0; - fitparentwidth = true; - clearnodes(); - } - } - new GuiTextEditCtrl("GUIExplorer_Source") { - profile = GuiBlueTextEditProfile; - x = 10; - y = GUIExplorer.height - 56; - height = 20; - width = GUIExplorer.width - 32; - text = ""; - thiso.catchevent(this.name, "onAction", "onLoadSource"); - } - } - onLoadSource(GUIExplorer_Source); - - setTimer(0.05); -} - -// Create Object Dump GUI - -function createObjectDump(obj) { - new GuiWindowCtrl("GUIExplorerDump_" @ obj.name) { - profile = GuiBlueWindowProfile; - isexternal = true; - clientextent = true; - extent = "600,600"; - canresize = false; - destroyonhide = true; - text = "GUI Object Dump"; - new GuiScrollCtrl("GUIExplorerDump_Scroll_" @ obj.name) { - profile = GuiBlueScrollProfile; - x = y = 10; - extent = "570,550"; - hScrollBar = "dynamic"; - vScrollBar = "dynamic"; - new GuiMLTextCtrl("GUIExplorerDump_Text_" @ obj.name) { - profile = GuiBlueMLTextProfile; - x = y = 0; - width = 540; - height = 540; - text = ""; - temp.textobj = this; - } - } - } - - // Display Object Dump - temp.textobj.text = getDump(obj); -} - -// Sets Root Node and Repopulates Tree. - -function onLoadSource(obj) { - // Trim text - obj.text = obj.text.trim(); - // Default Text - if (obj.text == "") obj.text = this.defaultGUI; - // Populate Tree - GUIExplorer_Tree.clearnodes(); - populateNode(GUIExplorer_Tree, makevar(obj.text)); -} - -// Recursively populates node with children. - -function populateNode(parentNode, parentObj) { - // Idiot Protection - if (parentObj.name == "GUIExplorer_Tree") return; - // Check if parentObj is Object - if (parentObj.type() == 0) { - temp.node = parentNode.addNode("Could not locate object!"); - with (temp.node) { - image = selectedimage = 2; - } - return; - } - // Add Node - temp.newNode = parentNode.addNode(parentObj.name); - // Populate Children Data - if (parentObj.controls.size() > 0) { - // Children found - for (temp.childObj: parentObj.controls) { - populateNode(temp.newNode, temp.childObj); - } - } else { - // Does not have Children - with (temp.newNode) { - image = selectedimage = 2; - } - } -} - -// Opens Object Dump when a Node is Double-clicked. - -function GUIExplorer_Tree.onDblClick(node) { - // Avoid Error Node - if (node == "Could not locate object!") return; - // Display Dump - createObjectDump(makevar(node)); -} - -// Resizes Appropriately - -function GUIExplorer.onResize() { - with (GUIExplorer_Scroll) { - width = GUIExplorer.width - 20; - height = GUIExplorer.height - 40; - } - with (GUIExplorer_Source) { - y = GUIExplorer.height - 26; - width = GUIExplorer.width - 20; - } -} - -// Dump Functions -function getDump(obj) { - temp.dump = getVal(obj); - temp.dump = temp.dump @ " {\n"; - temp.vars = obj.getvarnames(); - for ( temp.i = 0; temp.i < temp.vars.size(); temp.i ++ ) - temp.dump = temp.dump @ " "@ temp.vars[i] @" = "@ getVal( obj.(@ temp.vars[i] ) ) @";\n"; - temp.dump = temp.dump @ "};"; - return temp.dump; -} - -// Credits to Novo for this function. -function getVal( val ) -{ - switch ( val.type() ) - { - case 0: case 1: - return "\""@ val @"\""; - break; - case 2: - return val.objecttype() @"("@ val.name @")"; - break; - case 3: - temp.dump = "{"; - temp.count = 0; - for ( temp.count = 0; temp.count < val.size(); temp.count ++ ) - { - if ( count != 0 ) - temp.dump = temp.dump @ ", "; - - temp.dump = temp.dump @ getVal( val[ temp.count ] ); - } - temp.dump = temp.dump @ "}"; - - return temp.dump; - break; - } - - return "\"\""; -} -*/ \ No newline at end of file diff --git a/scripts/syntax-test.txt b/scripts/syntax-test.txt deleted file mode 100644 index d49579e..0000000 --- a/scripts/syntax-test.txt +++ /dev/null @@ -1,42 +0,0 @@ -//#CLIENTSIDE -function onCreated() { - // syntax error 1 - temp.a = {}; - temp.a = {1, 2, 3, 5, 9}; - //temp.a = {1, 2, 3,,, 5, 9,}; // invalid - //temp.a = {,}; // invalid - - // syntax error 2 - temp.a = 1; - if (temp.a == 0) { - { - echo("e"); - } - - echo("t"); - } else if (temp.a == 1) { - echo("found"); - } - - // syntax error 3 - temp.a = 1; - if (temp.a == 0) { - { - } - - echo("t"); - } else if (temp.a == 1) { - echo("found"); - } - - // syntax error 4 - if (temp.a == 0) { - } else if (temp.a == 1) { - echo("found"); - } - - if (temp.a) - if (temp.b) - if (temp.c) - temp.d = 0; -} \ No newline at end of file diff --git a/scripts/testscript.txt b/scripts/testscript.txt deleted file mode 100644 index 1b7850e..0000000 --- a/scripts/testscript.txt +++ /dev/null @@ -1,1898 +0,0 @@ -/* -function[281] randomCommands -function[46] enumTest -function[203] testInCommand -function[77] objTest -function[1] onCreated -function[108] testFor -*/ - -//#CLIENTSIDE -// Enums directly replaced with incremented integers starting at 0 -enum { - EIDLE, - EWALK, - ESLASH -}; - -function onCreated() { - /* - 8, 5: temp. (189) - 9, 6: type(variable) (22) (Opcode: 0xF0) - variable[0](somethin) (byte) - 12, 7: member access (35) - 13, 8: type(array) (23) - 14, 9: type(variable) (22) (Opcode: 0xF0) - variable[1](objTest) (byte) - 17, 10: Call function (6) - 18, 11: "=" (50) - */ - temp.somethin = objTest(); - - randomCommands(); - testFor(); - testInCommand(); - enumTest(); - - /* - 43, 28: temp. (189) - 44, 29: type(variable) (22) (Opcode: 0xF0) - variable[0](somethin) (byte) - 47, 30: member access (35) - 48, 31: Convert to object (36) - 49, 32: type(variable) (22) (Opcode: 0xF0) - variable[6](pl) (byte) - 52, 33: member access (35) - 53, 34: Convert to object (36) - 54, 35: with (150) (Opcode: 0xF3) - double(43) (byte) - 57, 36: type(variable) (22) (Opcode: 0xF0) - variable[7](x) (byte) - 60, 37: Copy last operand (30) - 61, 38: Convert to float (33) - 62, 39: type(number) (20) (Opcode: 0xF3) - double(5) (byte) - 65, 40: + (60) - 66, 41: "=" (50) - 67, 42: End of with (151) - */ - with (temp.somethin.pl) { - x += 5; - } -} - -function enumTest() { - echo("Enum IDLE: " @ EIDLE); - echo("Enum WALK: " @ EWALK); - echo("Enum SLASH: " @ ESLASH); -} - -function objTest() { - /* - 133, 80: temp. (189) - 134, 81: type(variable) (22) (Opcode: 0xF0) - variable[12](a) (byte) - 137, 82: member access (35) - 138, 83: type(variable) (22) (Opcode: 0xF0) - variable[13](unknown_object) (byte) - 141, 84: type(string) (21) (Opcode: 0xF0) - variable[14](TStaticVar) (byte) - 144, 85: new Object? (42) - 145, 86: "=" (50) - */ - temp.a = new TStaticVar(); - - /* - 146, 87: temp. (189) - 147, 88: type(variable) (22) (Opcode: 0xF0) - variable[12](a) (byte) - 150, 89: member access (35) - 151, 90: Convert to object (36) - 152, 91: type(variable) (22) (Opcode: 0xF0) - variable[15](val) (byte) - 155, 92: member access (35) - 156, 93: type(number) (20) (Opcode: 0xF3) - double(2) (byte) - 159, 94: "=" (50) - */ - temp.a.val = 2; - - /* - 160, 95: temp. (189) - 161, 96: type(variable) (22) (Opcode: 0xF0) - variable[12](a) (byte) - 164, 97: member access (35) - 165, 98: Convert to object (36) - 166, 99: type(variable) (22) (Opcode: 0xF0) - variable[6](pl) (byte) - 169, 100: member access (35) - 170, 101: type(variable) (22) (Opcode: 0xF0) - variable[16](player) (byte) - 173, 102: "=" (50) - */ - temp.a.pl = player; - - /* - 174, 103: temp. (189) - 175, 104: type(variable) (22) (Opcode: 0xF0) - variable[12](a) (byte) - 178, 105: member access (35) - 179, 106: } //End of function code (7) - */ - return temp.a; -} - -function testFor() { - temp.arr = {"abc", "def", "gh", "ijk"}; - - echo("foreach"); - for (temp.a : temp.arr) { - echo(temp.a); - } - - echo("forloop"); - for (temp.i = 0; temp.i < temp.arr.size(); temp.i++) { - echo(temp.arr[temp.i]); - } - - /* - 343, 195: temp. (189) - 344, 196: type(variable) (22) (Opcode: 0xF0) - variable[17](arr) (byte) - 347, 197: member access (35) - 348, 198: Convert to object (36) - 349, 199: obj.clear() (141) - */ - // clear array - temp.arr.clear(); -} - -function testInCommand() { - /* - 362, 207: temp. (189) - 363, 208: type(variable) (22) (Opcode: 0xF0) - variable[17](arr) (byte) - 366, 209: member access (35) - 367, 210: type(array) (23) - 368, 211: type(string) (21) (Opcode: 0xF0) - variable[19](ijk) (byte) - 371, 212: type(string) (21) (Opcode: 0xF0) - variable[20](gh) (byte) - 374, 213: type(string) (21) (Opcode: 0xF0) - variable[21](def) (byte) - 377, 214: type(string) (21) (Opcode: 0xF0) - variable[22](abc) (byte) - 380, 215: End of array (37) - 381, 216: "=" (50) - */ - temp.arr = {"abc", "def", "gh", "ijk"}; - - /* - 382, 217: type(string) (21) (Opcode: 0xF0) - variable[20](gh) (byte) - 385, 218: temp. (189) - 386, 219: type(variable) (22) (Opcode: 0xF0) - variable[17](arr) (byte) - 389, 220: member access (35) - 390, 221: Convert to object (36) - 391, 222: in {} (81) - 392, 223: if (4) (Opcode: 0xF4) - double(229) (word) - 396, 224: type(array) (23) - 397, 225: type(string) (21) (Opcode: 0xF0) - variable[25](found) (byte) - 400, 226: type(variable) (22) (Opcode: 0xF0) - variable[9](echo) (byte) - 403, 227: Call function (6) - 404, 228: Decrease last operand index by 1 (32) - */ - if ("gh" in temp.arr) { - echo("found"); - } - - /* - 405, 229: temp. (189) - 406, 230: type(variable) (22) (Opcode: 0xF0) - variable[18](i) (byte) - 409, 231: member access (35) - 410, 232: type(array) (23) - 411, 233: player. (182) - 412, 234: type(variable) (22) (Opcode: 0xF0) - variable[26](y) (byte) - 415, 235: member access (35) - 416, 236: player. (182) - 417, 237: type(variable) (22) (Opcode: 0xF0) - variable[7](x) (byte) - 420, 238: member access (35) - 421, 239: End of array (37) - 422, 240: type(number) (20) (Opcode: 0xF3) - double(20) (byte) - 425, 241: type(number) (20) (Opcode: 0xF3) - double(40) (byte) - 428, 242: in <> (80) (Opcode: 0xF3) - double(3) (byte) - 431, 243: "=" (50) - */ - temp.i = ({playerx,playery} in <20,40>); - - /* - 432, 244: type(array) (23) - 433, 245: type(string) (21) (Opcode: 0xF0) - variable[27](valid: ) (byte) - 436, 246: temp. (189) - 437, 247: type(variable) (22) (Opcode: 0xF0) - variable[18](i) (byte) - 440, 248: member access (35) - 441, 249: Convert to string (34) - 442, 250: @ (113) - 443, 251: type(variable) (22) (Opcode: 0xF0) - variable[9](echo) (byte) - 446, 252: Call function (6) - 447, 253: Decrease last operand index by 1 (32) - */ - echo("valid: " @ temp.i); - - /* - 448, 254: type(variable) (22) (Opcode: 0xF0) - variable[28](v) (byte) - 451, 255: player. (182) - 452, 256: type(variable) (22) (Opcode: 0xF0) - variable[7](x) (byte) - 455, 257: member access (35) - 456, 258: type(number) (20) (Opcode: 0xF3) - double(20) (byte) - 459, 259: type(number) (20) (Opcode: 0xF3) - double(40) (byte) - 462, 260: in <> (80) (Opcode: 0xF3) - double(3) (byte) - 465, 261: && (5) (Opcode: 0xF4) - double(268) (word) - 469, 262: player. (182) - 470, 263: type(variable) (22) (Opcode: 0xF0) - variable[26](y) (byte) - 473, 264: member access (35) - 474, 265: type(number) (20) (Opcode: 0xF3) - double(20) (byte) - 477, 266: type(number) (20) (Opcode: 0xF3) - double(40) (byte) - 480, 267: in <> (80) (Opcode: 0xF3) - double(3) (byte) - 483, 268: End of inline conditional? (44) - 484, 269: "=" (50) - */ - v = (playerx in <20,40> && playery in <20,40>); - - /* - 485, 270: type(array) (23) - 486, 271: type(string) (21) (Opcode: 0xF0) - variable[27](valid: ) (byte) - 489, 272: type(variable) (22) (Opcode: 0xF0) - variable[28](v) (byte) - 492, 273: Convert to string (34) - 493, 274: @ (113) - 494, 275: type(variable) (22) (Opcode: 0xF0) - variable[9](echo) (byte) - 497, 276: Call function (6) - 498, 277: Decrease last operand index by 1 (32) - */ - echo("valid: " @ v); -} - -function randomCommands() { - // expect dec --- actual: was removed from bytecode - format("Hello, %s. You ate %i apples today!", "Mr. Skyld", 4); - - /* - 511, 285: this. (180) - 512, 286: type(variable) (22) (Opcode: 0xF0) - variable[29](str) (byte) - 515, 287: member access (35) - 516, 288: type(array) (23) - 517, 289: type(number) (20) (Opcode: 0xF3) - double(4) (byte) - 520, 290: type(string) (21) (Opcode: 0xF0) - variable[30](Mr. Skyld) (byte) - 523, 291: type(string) (21) (Opcode: 0xF0) - variable[31](Hello, %s. You ate %i apples today!) (byte) - 526, 292: format() (84) - 527, 293: "=" (50) - */ - this.str = format("Hello, %s. You ate %i apples today!", "Mr. Skyld", 4); - - /* - 528, 294: this. (180) - 529, 295: type(variable) (22) (Opcode: 0xF0) - variable[32](strpos) (byte) - 532, 296: member access (35) - 533, 297: this. (180) - 534, 298: type(variable) (22) (Opcode: 0xF0) - variable[29](str) (byte) - 537, 299: member access (35) - 538, 300: Convert to string (34) - 539, 301: type(string) (21) (Opcode: 0xF0) - variable[33](Skyld) (byte) - 542, 302: obj.pos() (112) - 543, 303: "=" (50) - */ - this.strpos = this.str.pos("Skyld"); - - /* - 544, 304: type(array) (23) - 545, 305: type(string) (21) (Opcode: 0xF0) - variable[34](pos: ) (byte) - 548, 306: this. (180) - 549, 307: type(variable) (22) (Opcode: 0xF0) - variable[32](strpos) (byte) - 552, 308: member access (35) - 553, 309: Convert to string (34) - 554, 310: @ (113) - 555, 311: type(variable) (22) (Opcode: 0xF0) - variable[9](echo) (byte) - 558, 312: Call function (6) - 559, 313: Decrease last operand index by 1 (32) - */ - echo("pos: " @ this.strpos); - - /* - 560, 314: thiso. (181) - 561, 315: type(variable) (22) (Opcode: 0xF0) - variable[17](arr) (byte) - 564, 316: member access (35) - 565, 317: type(array) (23) - 566, 318: type(string) (21) (Opcode: 0xF0) - variable[35](etc) (byte) - 569, 319: type(string) (21) (Opcode: 0xF0) - variable[36](second member) (byte) - 572, 320: type(string) (21) (Opcode: 0xF0) - variable[37](First member) (byte) - 575, 321: End of array (37) - 576, 322: "=" (50) - */ - thiso.arr = {"First member", "second member", "etc"}; - - /* - 577, 323: type(array) (23) - 578, 324: type(string) (21) (Opcode: 0xF0) - variable[38](size: ) (byte) - 581, 325: thiso. (181) - 582, 326: type(variable) (22) (Opcode: 0xF0) - variable[17](arr) (byte) - 585, 327: member access (35) - 586, 328: Convert to object (36) - 587, 329: obj.size() (130) - 588, 330: Convert to string (34) - 589, 331: @ (113) - 590, 332: type(variable) (22) (Opcode: 0xF0) - variable[9](echo) (byte) - 593, 333: Call function (6) - 594, 334: Decrease last operand index by 1 (32) - */ - echo("size: " @ thiso.arr.size()); - - /* - 595, 335: temp. (189) - 596, 336: type(variable) (22) (Opcode: 0xF0) - variable[39](num) (byte) - 599, 337: member access (35) - 600, 338: type(number) (20) (Opcode: 0xF3) - double(1) (byte) - 603, 339: type(number) (20) (Opcode: 0xF3) - double(10) (byte) - 606, 340: random() (87) - 607, 341: Convert to float (33) - 608, 342: type(number) (20) (Opcode: 0xF3) - double(7) (byte) - 611, 343: max() (94) - 612, 344: "=" (50) - */ - temp.num = max(random(1, 10), 7); - - /* - 613, 345: temp. (189) - 614, 346: type(variable) (22) (Opcode: 0xF0) - variable[40](tvar) (byte) - 617, 347: member access (35) - 618, 348: type(array) (23) - 619, 349: type(variable) (22) (Opcode: 0xF0) - variable[41](timevar2) (byte) - 622, 350: type(variable) (22) (Opcode: 0xF0) - variable[42](timevar) (byte) - 625, 351: End of array (37) - 626, 352: "=" (50) - */ - temp.tvar = {timevar, timevar2}; - - /* - 38: PushVariable this - 39: ConvertToString - 40: PushString foo - 41: PushNumber 7200 - 42: WaitFor - */ - waitfor(this, "foo", 7200); -} - -//=================================================== - -function onCreated() { - this.obj = {"abcd", "efgh", "i"}; - this.obj.add("test"); - this.obj.delete(0); - this.obj.remove("i"); - this.obj.insert(1, "alpha"); - this.obj.replace(2, "bravo"); - - this.teststr = "Teststr"; - this.teststr = this.teststr.lower(); - this.teststr = this.teststr.upper(); - - this.obj2 = {}; - temp.arr1 = {"abc", "def", "ghi"}; - temp.arr2 = {"jkl", "mno", "pqr"}; - this.obj2.addarray(temp.arr2); - this.obj2.insertarray(1, temp.arr1); - - this.test36 = "hi"; - temp.v = "36"; - echo(makevar("this.test" @ temp.v)); - - temp.val = serverr.someflag; - echo(temp.val); - - temp.randfloat = float("420.69"); - echo(temp.randfloat); - - temp.escapestr = "test',str"; - echo(temp.escapestr.escape()); - - sleep(0.1); - - arrayInit(); - testLoop(); -} - -function arrayInit() -{ - this.obj3 = new[4]; - this.obj3[1] = "hi"; - - this.obj4 = new[4][2][1]; - - this.obj5 = this.getfunctions(); - this.obj6 = this.getvarnames(); - this.obj7 = this.getdynamicvarnames(); - this.obj8 = this.geteditvarnames(); - this.obj9 = this.getstaticvarnames(); -} - -function testLoop() -{ - for (temp.v : this.obj) { - echo("T: " @ temp.v); - } -} - -//========================================= - -//#CLIENTSIDE -function onCreated() { -/* - 8, 5: this. (180) - 9, 6: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 12, 7: member access (35) - 13, 8: type(array) (23) - 14, 9: type(string) (21) (Opcode: 0xF0) - variable[1](i) (byte) - 17, 10: type(string) (21) (Opcode: 0xF0) - variable[2](efgh) (byte) - 20, 11: type(string) (21) (Opcode: 0xF0) - variable[3](abcd) (byte) - 23, 12: End of array (37) - 24, 13: "=" (50) -*/ - this.obj = {"abcd", "efgh", "i"}; - -/* - 25, 14: this. (180) - 26, 15: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 29, 16: member access (35) - 30, 17: Convert to object (36) - 31, 18: type(string) (21) (Opcode: 0xF0) - variable[4](test) (byte) - 34, 19: addstring() (136) -*/ - this.obj.add("test"); - -/* - 35, 20: this. (180) - 36, 21: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 39, 22: member access (35) - 40, 23: Convert to object (36) - 41, 24: type(number) (20) (Opcode: 0xF3) - double(0) (byte) - 44, 25: deletestring() (137) -*/ - this.obj.delete(0); - -/* - 45, 26: this. (180) - 46, 27: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 49, 28: member access (35) - 50, 29: Convert to object (36) - 51, 30: type(string) (21) (Opcode: 0xF0) - variable[1](i) (byte) - 54, 31: removestring() (138) -*/ - this.obj.remove("i"); - -/* - 55, 32: this. (180) - 56, 33: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 59, 34: member access (35) - 60, 35: Convert to object (36) - 61, 36: type(string) (21) (Opcode: 0xF0) - variable[5](alpha) (byte) - 64, 37: type(number) (20) (Opcode: 0xF3) - double(1) (byte) - 67, 38: insertstring() (140) -*/ - this.obj.insert(1, "alpha"); - -/* - 68, 39: this. (180) - 69, 40: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 72, 41: member access (35) - 73, 42: Convert to object (36) - 74, 43: type(string) (21) (Opcode: 0xF0) - variable[6](bravo) (byte) - 77, 44: type(number) (20) (Opcode: 0xF3) - double(2) (byte) - 80, 45: replacestring() (139) -*/ - this.obj.replace(2, "bravo"); - -/* - 81, 46: this. (180) - 82, 47: type(variable) (22) (Opcode: 0xF0) - variable[7](teststr) (byte) - 85, 48: member access (35) - 86, 49: type(string) (21) (Opcode: 0xF0) - variable[8](Teststr) (byte) - 89, 50: "=" (50) -*/ - this.teststr = "Teststr"; - -/* - 90, 51: this. (180) - 91, 52: type(variable) (22) (Opcode: 0xF0) - variable[7](teststr) (byte) - 94, 53: member access (35) - 95, 54: type(array) (23) - 96, 55: this. (180) - 97, 56: type(variable) (22) (Opcode: 0xF0) - variable[7](teststr) (byte) - 100, 57: member access (35) - 101, 58: Convert to string (34) - 102, 59: type(variable) (22) (Opcode: 0xF0) - variable[9](lowercase) (byte) - 105, 60: Call function (6) - 106, 61: "=" (50) -*/ - this.teststr = this.teststr.lower(); - -/* - 107, 62: this. (180) - 108, 63: type(variable) (22) (Opcode: 0xF0) - variable[7](teststr) (byte) - 111, 64: member access (35) - 112, 65: type(array) (23) - 113, 66: this. (180) - 114, 67: type(variable) (22) (Opcode: 0xF0) - variable[7](teststr) (byte) - 117, 68: member access (35) - 118, 69: Convert to string (34) - 119, 70: type(variable) (22) (Opcode: 0xF0) - variable[10](uppercase) (byte) - 122, 71: Call function (6) - 123, 72: "=" (50) -*/ - this.teststr = this.teststr.upper(); - -/* - 124, 73: this. (180) - 125, 74: type(variable) (22) (Opcode: 0xF0) - variable[11](obj2) (byte) - 128, 75: member access (35) - 129, 76: type(array) (23) - 130, 77: End of array (37) - 131, 78: "=" (50) -*/ - this.obj2 = {}; - -/* - 132, 79: temp. (189) - 133, 80: type(variable) (22) (Opcode: 0xF0) - variable[12](arr1) (byte) - 136, 81: member access (35) - 137, 82: type(array) (23) - 138, 83: type(string) (21) (Opcode: 0xF0) - variable[13](ghi) (byte) - 141, 84: type(string) (21) (Opcode: 0xF0) - variable[14](def) (byte) - 144, 85: type(string) (21) (Opcode: 0xF0) - variable[15](abc) (byte) - 147, 86: End of array (37) - 148, 87: "=" (50) -*/ - temp.arr1 = {"abc", "def", "ghi"}; - -/* - 149, 88: temp. (189) - 150, 89: type(variable) (22) (Opcode: 0xF0) - variable[16](arr2) (byte) - 153, 90: member access (35) - 154, 91: type(array) (23) - 155, 92: type(string) (21) (Opcode: 0xF0) - variable[17](pqr) (byte) - 158, 93: type(string) (21) (Opcode: 0xF0) - variable[18](mno) (byte) - 161, 94: type(string) (21) (Opcode: 0xF0) - variable[19](jkl) (byte) - 164, 95: End of array (37) - 165, 96: "=" (50) -*/ - temp.arr2 = {"jkl", "mno", "pqr"}; - -/* - 166, 97: type(array) (23) - 167, 98: temp. (189) - 168, 99: type(variable) (22) (Opcode: 0xF0) - variable[16](arr2) (byte) - 171, 100: member access (35) - 172, 101: this. (180) - 173, 102: type(variable) (22) (Opcode: 0xF0) - variable[11](obj2) (byte) - 176, 103: member access (35) - 177, 104: Convert to object (36) - 178, 105: type(variable) (22) (Opcode: 0xF0) - variable[20](addarray) (byte) - 181, 106: member access (35) - 182, 107: Call function (6) - 183, 108: Decrease last operand index by 1 (32) -*/ - this.obj2.addarray(temp.arr2); - -/* - 184, 109: type(array) (23) - 185, 110: temp. (189) - 186, 111: type(variable) (22) (Opcode: 0xF0) - variable[12](arr1) (byte) - 189, 112: member access (35) - 190, 113: type(number) (20) (Opcode: 0xF3) - double(1) (byte) - 193, 114: this. (180) - 194, 115: type(variable) (22) (Opcode: 0xF0) - variable[11](obj2) (byte) - 197, 116: member access (35) - 198, 117: Convert to object (36) - 199, 118: type(variable) (22) (Opcode: 0xF0) - variable[21](insertarray) (byte) - 202, 119: member access (35) - 203, 120: Call function (6) - 204, 121: Decrease last operand index by 1 (32) -*/ - this.obj2.insertarray(1, temp.arr1); - -/* - 205, 122: this. (180) - 206, 123: type(variable) (22) (Opcode: 0xF0) - variable[22](test36) (byte) - 209, 124: member access (35) - 210, 125: type(string) (21) (Opcode: 0xF0) - variable[23](hi) (byte) - 213, 126: "=" (50) -*/ - this.test36 = "hi"; - -/* - 214, 127: temp. (189) - 215, 128: type(variable) (22) (Opcode: 0xF0) - variable[24](v) (byte) - 218, 129: member access (35) - 219, 130: type(string) (21) (Opcode: 0xF0) - variable[25](36) (byte) - 222, 131: "=" (50) -*/ - temp.v = "36"; - -/* - 223, 132: type(array) (23) - 224, 133: type(string) (21) (Opcode: 0xF0) - variable[26](this.test) (byte) - 227, 134: temp. (189) - 228, 135: type(variable) (22) (Opcode: 0xF0) - variable[24](v) (byte) - 231, 136: member access (35) - 232, 137: Convert to string (34) - 233, 138: @ (113) - 234, 139: makevar() (41) - 235, 140: type(variable) (22) (Opcode: 0xF0) - variable[27](echo) (byte) - 238, 141: Call function (6) - 239, 142: Decrease last operand index by 1 (32) -*/ - echo(makevar("this.test" @ temp.v)); - -/* - 240, 143: temp. (189) - 241, 144: type(variable) (22) (Opcode: 0xF0) - variable[28](val) (byte) - 244, 145: member access (35) - 245, 146: type(variable) (22) (Opcode: 0xF0) - variable[29](serverr) (byte) - 248, 147: Convert to object (36) - 249, 148: type(variable) (22) (Opcode: 0xF0) - variable[30](someflag) (byte) - 252, 149: member access (35) - 253, 150: "=" (50) -*/ - temp.val = serverr.someflag; - echo(temp.val); - - temp.randfloat = float("420.69"); - echo(temp.randfloat); - - temp.escapestr = "test',str"; - echo(temp.escapestr.escape()); - -/* - 312, 187: type(number) (20) (Opcode: 0xF6) - double(0.1) (string) - 317, 188: sleep() (8) -*/ - sleep(0.1); - - arrayInit(); - testLoop(); -} - -function arrayInit() -{ -/* - 342, 204: this. (180) - 343, 205: type(variable) (22) (Opcode: 0xF0) - variable[38](obj3) (byte) - 346, 206: member access (35) - 347, 207: type(number) (20) (Opcode: 0xF3) - double(4) (byte) - 350, 208: new[] (38) - 351, 209: "=" (50) -*/ - this.obj3 = new[4]; - -/* - 352, 210: this. (180) - 353, 211: type(variable) (22) (Opcode: 0xF0) - variable[38](obj3) (byte) - 356, 212: member access (35) - 357, 213: Convert to object (36) - 358, 214: type(number) (20) (Opcode: 0xF3) - double(1) (byte) - 361, 215: type(string) (21) (Opcode: 0xF0) - variable[23](hi) (byte) - 364, 216: Array assignment (132) -*/ - this.obj3[1] = "hi"; - -/* - 365, 217: this. (180) - 366, 218: type(variable) (22) (Opcode: 0xF0) - variable[39](obj4) (byte) - 369, 219: member access (35) - 370, 220: type(number) (20) (Opcode: 0xF3) - double(4) (byte) - 373, 221: new[] (38) - 374, 222: type(number) (20) (Opcode: 0xF3) - double(2) (byte) - 377, 223: new[][] for each extra dimension (142) - 378, 224: type(number) (20) (Opcode: 0xF3) - double(1) (byte) - 381, 225: new[][] for each extra dimension (142) - 382, 226: "=" (50) -*/ - this.obj4 = new[4][2][1]; - -/* - 383, 227: this. (180) - 384, 228: type(variable) (22) (Opcode: 0xF0) - variable[40](obj5) (byte) - 387, 229: member access (35) - 388, 230: type(array) (23) - 389, 231: this. (180) - 390, 232: type(variable) (22) (Opcode: 0xF0) - variable[41](getfunctions) (byte) - 393, 233: member access (35) - 394, 234: Call function (6) - 395, 235: "=" (50) -*/ - this.obj5 = this.getfunctions(); - -/* - 396, 236: this. (180) - 397, 237: type(variable) (22) (Opcode: 0xF0) - variable[42](obj6) (byte) - 400, 238: member access (35) - 401, 239: type(array) (23) - 402, 240: this. (180) - 403, 241: type(variable) (22) (Opcode: 0xF0) - variable[43](getvarnames) (byte) - 406, 242: member access (35) - 407, 243: Call function (6) - 408, 244: "=" (50) -*/ - this.obj6 = this.getvarnames(); - -/* - 409, 245: this. (180) - 410, 246: type(variable) (22) (Opcode: 0xF0) - variable[44](obj7) (byte) - 413, 247: member access (35) - 414, 248: type(array) (23) - 415, 249: this. (180) - 416, 250: type(variable) (22) (Opcode: 0xF0) - variable[45](getdynamicvarnames) (byte) - 419, 251: member access (35) - 420, 252: Call function (6) - 421, 253: "=" (50) -*/ - this.obj7 = this.getdynamicvarnames(); - -/* - 422, 254: this. (180) - 423, 255: type(variable) (22) (Opcode: 0xF0) - variable[46](obj8) (byte) - 426, 256: member access (35) - 427, 257: type(array) (23) - 428, 258: this. (180) - 429, 259: type(variable) (22) (Opcode: 0xF0) - variable[47](geteditvarnames) (byte) - 432, 260: member access (35) - 433, 261: Call function (6) - 434, 262: "=" (50) -*/ - this.obj8 = this.geteditvarnames(); - -/* - 435, 263: this. (180) - 436, 264: type(variable) (22) (Opcode: 0xF0) - variable[48](obj9) (byte) - 439, 265: member access (35) - 440, 266: type(array) (23) - 441, 267: this. (180) - 442, 268: type(variable) (22) (Opcode: 0xF0) - variable[49](getstaticvarnames) (byte) - 445, 269: member access (35) - 446, 270: Call function (6) - 447, 271: "=" (50) -*/ - this.obj9 = this.getstaticvarnames(); -} - -/* - // loop var 0: temp.v - // loop var 1: echo - // loop var 2: this.obj - - 452, 274: Set operation index (1) (Opcode: 0xF4) - double(316) (word) - 456, 275: type(array) (23) - 457, 276: End of function definition parameters (51) - 458, 277: { //Start of function code? (10) - 459, 278: Start of function call? (9) - 460, 279: temp. (189) - 461, 280: type(variable) (22) (Opcode: 0xF0) - variable[24](v) (byte) - 464, 281: member access (35) - 465, 282: Mark as loop variable (47) - 466, 283: Assign loop variable index (45) (Opcode: 0xF3) - double(0) (byte) - 469, 284: Decrease last operand index by 1 (32) - 470, 285: type(variable) (22) (Opcode: 0xF0) - variable[27](echo) (byte) - 473, 286: Mark as loop variable (47) - 474, 287: Assign loop variable index (45) (Opcode: 0xF3) - double(1) (byte) - 477, 288: Decrease last operand index by 1 (32) - 478, 289: this. (180) - 479, 290: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 482, 291: member access (35) - 483, 292: Mark as loop variable (47) - 484, 293: Assign loop variable index (45) (Opcode: 0xF3) - double(2) (byte) - 487, 294: Decrease last operand index by 1 (32) - 488, 295: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 491, 296: Loop variable (46) (Opcode: 0xF3) - double(2) (byte) - 494, 297: Convert to object (36) - 495, 298: type(number) (20) (Opcode: 0xF3) - double(0) (byte) - 498, 299: for (a: b) (163) (Opcode: 0xF4) - double(311) (word) - - 502, 300: Start of function call? (9) - 503, 301: type(array) (23) - 504, 302: type(string) (21) (Opcode: 0xF0) - variable[50](T: ) (byte) - 507, 303: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 510, 304: Convert to string (34) - 511, 305: @ (113) - 512, 306: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 515, 307: Call function (6) - - 516, 308: Decrease last operand index by 1 (32) - 517, 309: Increment by 1 (52) - 518, 310: Set operation index (1) (Opcode: 0xF4) - double(299) (word) - 522, 311: Decrease last operand index by 1 (32) - 523, 312: Decrease last operand index by 1 (32) - 524, 313: Decrease last operand index by 1 (32) - 525, 314: type(number) (20) (Opcode: 0xF3) - double(0) (byte) - 528, 315: } //End of function code (7) -*/ - -function testLoop() -{ - for (temp.v : this.obj) { - echo("T: " @ temp.v); - } -} - - - -function onCreated() { -/* - 7, 5: type(array) (23) - 8, 6: type(string) (21) (Opcode: 0xF0) - variable[0](test: ) (byte) - 11, 7: player. (182) - 12, 8: type(variable) (22) (Opcode: 0xF0) - variable[1](x) (byte) - 15, 9: member access (35) - 16, 10: Convert to float (33) - 17, 11: type(number) (20) (Opcode: 0xF3) - double(5) (byte) - 20, 12: - binary (61) - 21, 13: Convert to string (34) - 22, 14: @ (113) - 23, 15: type(variable) (22) (Opcode: 0xF0) - variable[2](echo) (byte) - 26, 16: Call function (6) - 27, 17: Decrease last operand index by 1 (32) -*/ - echo("test: " @ (player.x - 5)); -} - - -//#CLIENTSIDE -function onCreated() -{ -/* - 7, 5: temp. (189) - 8, 6: type(variable) (22) (Opcode: 0xF0) - variable[0](g) (byte) - 11, 7: member access (35) - 12, 8: Mark as loop variable (47) - 13, 9: Assign loop variable index (45) (Opcode: 0xF3) - double(0) (byte) - 16, 10: Decrease last operand index by 1 (32) -*/ - - - -/* - 17, 11: temp. (189) - 18, 12: type(variable) (22) (Opcode: 0xF0) - variable[1](b) (byte) - 21, 13: member access (35) - 22, 14: type(variable) (22) (Opcode: 0xF0) - variable[2](unknown_object) (byte) - 25, 15: type(string) (21) (Opcode: 0xF0) - variable[3](TStaticVar) (byte) - 28, 16: new Object? (42) - 29, 17: "=" (50) -*/ - temp.b = new TStaticVar(); - -/* - 30, 18: temp. (189) - 31, 19: type(variable) (22) (Opcode: 0xF0) - variable[1](b) (byte) - 34, 20: member access (35) - 35, 21: Convert to object (36) - 36, 22: type(variable) (22) (Opcode: 0xF0) - variable[4](c) (byte) - 39, 23: member access (35) - 40, 24: type(string) (21) (Opcode: 0xF0) - variable[5](hi) (byte) - 43, 25: "=" (50) -*/ - temp.b.c = "hi"; - -/* - 44, 26: temp. (189) - 45, 27: type(variable) (22) (Opcode: 0xF0) - variable[6](a) (byte) - 48, 28: member access (35) - 49, 29: type(variable) (22) (Opcode: 0xF0) - variable[2](unknown_object) (byte) - 52, 30: type(string) (21) (Opcode: 0xF0) - variable[3](TStaticVar) (byte) - 55, 31: new Object? (42) - 56, 32: "=" (50) -*/ - temp.a = new TStaticVar("test", "djer", temp.b); - -/* - 57, 33: temp. (189) - 58, 34: type(variable) (22) (Opcode: 0xF0) - variable[6](a) (byte) - 61, 35: member access (35) - 62, 36: Convert to object (36) - 63, 37: type(variable) (22) (Opcode: 0xF0) - variable[7](ekjf) (byte) - 66, 38: member access (35) - 67, 39: type(string) (21) (Opcode: 0xF0) - variable[8](ee) (byte) - 70, 40: "=" (50) -*/ - temp.a.ekjf = "ee"; - -/* - 71, 41: temp. (189) - 72, 42: type(variable) (22) (Opcode: 0xF0) - variable[9](d) (byte) - 75, 43: member access (35) - 76, 44: type(variable) (22) (Opcode: 0xF0) - variable[10](Something) (byte) - 79, 45: inline new? (40) - 80, 46: type(string) (21) (Opcode: 0xF0) - variable[11](GuiButtonCtrl) (byte) - 83, 47: new Object? (42) - 84, 48: "=" (50) -*/ - temp.d = new GuiButtonCtrl(Something); - -/* - 85, 49: temp. (189) - 86, 50: type(variable) (22) (Opcode: 0xF0) - variable[9](d) (byte) - 89, 51: member access (35) - 90, 52: Convert to object (36) - 91, 53: type(variable) (22) (Opcode: 0xF0) - variable[12](text) (byte) - 94, 54: member access (35) - 95, 55: type(string) (21) (Opcode: 0xF0) - variable[13](test btn: ) (byte) - 98, 56: temp. (189) - 99, 57: type(variable) (22) (Opcode: 0xF0) - variable[6](a) (byte) - 102, 58: member access (35) - 103, 59: Convert to object (36) - 104, 60: type(variable) (22) (Opcode: 0xF0) - variable[7](ekjf) (byte) - 107, 61: member access (35) - 108, 62: Convert to string (34) - 109, 63: @ (113) - 110, 64: "=" (50) -*/ - temp.d.text = "test btn: " @ temp.a.ekjf; - -/* - 111, 65: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 114, 66: type(number) (20) (Opcode: 0xF3) - double(0) (byte) - 117, 67: "=" (50) - 118, 68: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 121, 69: Convert to float (33) - 122, 70: type(number) (20) (Opcode: 0xF3) - double(5) (byte) - 125, 71: < (72) - 126, 72: if (4) (Opcode: 0xF3) - double(78) (byte) - 129, 73: Start of function call? (9) - 130, 74: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 133, 75: Increment by 1 (52) - 134, 76: Decrease last operand index by 1 (32) - 135, 77: Set operation index (1) (Opcode: 0xF3) - double(68) (byte) -*/ - temp.g = 0; - while (temp.g < 5) { - temp.g++; - } - -/* - 138, 78: type(array) (23) - 139, 79: type(string) (21) (Opcode: 0xF0) - variable[14](Test: ) (byte) - 142, 80: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 145, 81: Convert to string (34) - 146, 82: @ (113) - 147, 83: type(variable) (22) (Opcode: 0xF0) - variable[15](echo) (byte) - 150, 84: Call function (6) - 151, 85: Decrease last operand index by 1 (32) -*/ - echo("Test: " @ temp.g); -} - - -function onCreated() { -/* - 7, 5: type(array) (23) - 8, 6: type(string) (21) (Opcode: 0xF0) - variable[0](--start) (byte) - 11, 7: type(variable) (22) (Opcode: 0xF0) - variable[1](echo) (byte) - 14, 8: Call function (6) - 15, 9: Decrease last operand index by 1 (32) -*/ - echo("--start"); - - -/* - 16, 10: type(variable) (22) (Opcode: 0xF0) - variable[2](ObjName) (byte) - 19, 11: inline new? (40) - 20, 12: Copy last operand (30) - 21, 13: Copy last operand (30) - 22, 14: Copy last operand (30) - 23, 15: type(string) (21) (Opcode: 0xF0) - variable[3](GuiButtonCtrl) (byte) - 26, 16: Convert to string (34) - 27, 17: new Object? (42) - 28, 18: "=" (50) -*/ - new GuiButtonCtrl(ObjName) - { -/* - 29, 19: Convert to object (36) - 30, 20: with (150) (Opcode: 0xF3) - double(43) (byte) - 33, 21: type(variable) (22) (Opcode: 0xF0) - variable[4](profile) (byte) - 36, 22: type(variable) (22) (Opcode: 0xF0) - variable[5](GuiBlueButtonProfile) (byte) - 39, 23: "=" (50) - 40, 24: type(variable) (22) (Opcode: 0xF0) - variable[6](text) (byte) - 43, 25: type(string) (21) (Opcode: 0xF0) - variable[7](button) (byte) - 46, 26: "=" (50) - 47, 27: type(variable) (22) (Opcode: 0xF0) - variable[8](x) (byte) - 50, 28: type(number) (20) (Opcode: 0xF3) - double(30) (byte) - 53, 29: "=" (50) - 54, 30: type(variable) (22) (Opcode: 0xF0) - variable[9](y) (byte) - 57, 31: type(number) (20) (Opcode: 0xF3) - double(30) (byte) - 60, 32: "=" (50) - 61, 33: type(variable) (22) (Opcode: 0xF0) - variable[10](width) (byte) - 64, 34: type(number) (20) (Opcode: 0xF4) - double(150) (word) - 68, 35: "=" (50) - 69, 36: type(variable) (22) (Opcode: 0xF0) - variable[11](height) (byte) - 72, 37: type(number) (20) (Opcode: 0xF4) - double(150) (word) - 76, 38: "=" (50) - 77, 39: type(variable) (22) (Opcode: 0xF0) - variable[12](visible) (byte) - 80, 40: type(number) (20) (Opcode: 0xF3) - double(1) (byte) - 83, 41: "=" (50) - 84, 42: End of with (151) -*/ - profile = GuiBlueButtonProfile; - text = "button"; - x = 30; - y = 30; - width = 150; - height = 150; - visible = 1; - }; - -/* - 85, 43: type(array) (23) - 86, 44: Swap last two operands (31) - 87, 45: type(variable) (22) (Opcode: 0xF0) - variable[13](addcontrol) (byte) - 90, 46: Call function (6) - 91, 47: Decrease last operand index by 1 (32) -*/ - -/* - 92, 48: type(array) (23) - 93, 49: type(string) (21) (Opcode: 0xF0) - variable[14](--end) (byte) - 96, 50: type(variable) (22) (Opcode: 0xF0) - variable[1](echo) (byte) - 99, 51: Call function (6) - 100, 52: Decrease last operand index by 1 (32) -*/ - echo("--end"); -} - - -/* -output: -Test 1: 4 -Test 2: 4 -Test 3: 4 -Test 4: 4 -Test 5: -5 -Test 6: 1 -Test 7: 0 -Test 8: 0 -*/ -function onCreated() -{ - temp.i = 5; -/* - 32, 18: type(array) (23) - 33, 19: type(string) (21) (Opcode: 0xF0) - variable[2](Test 1: ) (byte) - 36, 20: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 39, 21: Decrement by 1 (53) - 40, 22: Convert to string (34) - 41, 23: @ (113) - 42, 24: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 45, 25: Call function (6) - 46, 26: Decrease last operand index by 1 (32) -*/ - echo("Test 1: " @ --temp.i); - - /* - 47, 27: type(array) (23) - 48, 28: type(string) (21) (Opcode: 0xF0) - variable[3](Test 2: ) (byte) - 51, 29: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 54, 30: Copy last operand (30) - 55, 31: Convert to float (33) - 56, 32: Swap last two operands (31) - 57, 33: Decrement by 1 (53) - 58, 34: Decrease last operand index by 1 (32) - 59, 35: Convert to string (34) - 60, 36: @ (113) - 61, 37: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 64, 38: Call function (6) - 65, 39: Decrease last operand index by 1 (32) - */ - echo("Test 2: " @ temp.i--); - -/* - 66, 40: type(array) (23) - 67, 41: type(string) (21) (Opcode: 0xF0) - variable[4](Test 3: ) (byte) - 70, 42: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 73, 43: Increment by 1 (52) - 74, 44: Convert to string (34) - 75, 45: @ (113) - 76, 46: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 79, 47: Call function (6) - 80, 48: Decrease last operand index by 1 (32) -*/ - echo("Test 3: " @ ++temp.i); - -/* - 81, 49: type(array) (23) - 82, 50: type(string) (21) (Opcode: 0xF0) - variable[5](Test 4: ) (byte) - 85, 51: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 88, 52: Copy last operand (30) - 89, 53: Convert to float (33) - 90, 54: Swap last two operands (31) - 91, 55: Increment by 1 (52) - 92, 56: Decrease last operand index by 1 (32) - 93, 57: Convert to string (34) - 94, 58: @ (113) - 95, 59: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 98, 60: Call function (6) - 99, 61: Decrease last operand index by 1 (32) -*/ - echo("Test 4: " @ temp.i++); - -/* - 100, 62: type(array) (23) - 101, 63: type(string) (21) (Opcode: 0xF0) - variable[6](Test 5: ) (byte) - 104, 64: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 107, 65: Convert to float (33) - 108, 66: - unary (69) - 109, 67: Convert to string (34) - 110, 68: @ (113) - 111, 69: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 114, 70: Call function (6) - 115, 71: Decrease last operand index by 1 (32) -*/ - echo("Test 5: " @ -temp.i); - - temp.i = 0; - -/* - 123, 75: type(array) (23) - 124, 76: type(string) (21) (Opcode: 0xF0) - variable[7](Test 6: ) (byte) - 127, 77: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 130, 78: Convert to float (33) - 131, 79: ! (68) - 132, 80: Convert to string (34) - 133, 81: @ (113) - 134, 82: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 137, 83: Call function (6) - 138, 84: Decrease last operand index by 1 (32) -*/ - echo("Test 6: " @ !temp.i); - - temp.i = 1; - echo("Test 7: " @ !temp.i); - - temp.i = 2; - echo("Test 8: " @ !temp.i); -} - - - - -function onMouseDown(temp.mtype) -{ - if (temp.mtype == "left") { - this.pid = onFindPlayers(); - - if (this.pid >= 0) - { - if (this.pid == 0) - { - player.showProfile(); - } - else - { - onShowMenu(); - } - } - } -} - -function onFindPlayers() -{ - // Method 1 - UNTESTED - - /*temp.found = testplayer(mousex, mousey); - - if (temp.found) - { - return temp.found; - } - else - { - return -1; - }*/ - - // Method 2 - echo("searching"); - for (temp.I = 0; temp.I < players.size(); temp.I++) - { - echo("t: " @ players[temp.I].x @ ", " @ players[temp.I].y @ " vs " @ mousex @ "," @ mousey); - if (mousex in |players[temp.I].x, players[temp.I].x + 3|) { - if (mousey in |players[temp.I].y, players[temp.I].y + 3|) { - echo("found"); - return temp.I; - } - } - } - - return -1; -} - -function onMouseDown(temp.mtype) -{ -/* - 12, 8: type(variable) (22) (Opcode: 0xF0) - variable[1](mousex) (byte) - 15, 9: player. (182) - 16, 10: type(variable) (22) (Opcode: 0xF0) - variable[2](x) (byte) - 19, 11: member access (35) - 20, 12: Convert to float (33) - 21, 13: player. (182) - 22, 14: type(variable) (22) (Opcode: 0xF0) - variable[2](x) (byte) - 25, 15: member access (35) - 26, 16: Convert to float (33) - 27, 17: type(number) (20) (Opcode: 0xF3) - double(3) (byte) - 30, 18: + (60) - 31, 19: in <> (80) (Opcode: 0xF3) - double(0) (byte) - 34, 20: if (4) (Opcode: 0xF3) - double(26) (byte) - 37, 21: type(array) (23) - 38, 22: type(string) (21) (Opcode: 0xF0) - variable[3](in range) (byte) - 41, 23: type(variable) (22) (Opcode: 0xF0) - variable[4](echo) (byte) - 44, 24: Call function (6) - 45, 25: Decrease last operand index by 1 (32) -*/ - if (mousex in |player.x, player.x + 3|) { - echo("in range"); - } -} - -function onCreated() { - -/* - 7, 5: player. (182) - 8, 6: type(variable) (22) (Opcode: 0xF0) - variable[0](x) (byte) - 11, 7: member access (35) - 12, 8: Convert to float (33) - 13, 9: type(number) (20) (Opcode: 0xF3) - double(15) (byte) - 16, 10: > (73) - 17, 11: if (4) (Opcode: 0xF3) - double(24) (byte) - 20, 12: player. (182) - 21, 13: type(variable) (22) (Opcode: 0xF0) - variable[1](y) (byte) - 24, 14: member access (35) - 25, 15: Convert to float (33) - 26, 16: type(number) (20) (Opcode: 0xF3) - double(30) (byte) - 29, 17: < (72) - 30, 18: if (4) (Opcode: 0xF3) - double(24) (byte) - 33, 19: type(array) (23) - 34, 20: type(string) (21) (Opcode: 0xF0) - variable[2](and op) (byte) - 37, 21: type(variable) (22) (Opcode: 0xF0) - variable[3](echo) (byte) - 40, 22: Call function (6) - 41, 23: Decrease last operand index by 1 (32) -*/ - - if (player.x > 15 && player.y < 30) { - echo("and op"); - } - -/* - 42, 24: player. (182) - 43, 25: type(variable) (22) (Opcode: 0xF0) - variable[0](x) (byte) - 46, 26: member access (35) - 47, 27: Convert to float (33) - 48, 28: type(number) (20) (Opcode: 0xF3) - double(15) (byte) - 51, 29: > (73) - 52, 30: || (3) (Opcode: 0xF3) - double(37) (byte) - 55, 31: player. (182) - 56, 32: type(variable) (22) (Opcode: 0xF0) - variable[1](y) (byte) - 59, 33: member access (35) - 60, 34: Convert to float (33) - 61, 35: type(number) (20) (Opcode: 0xF3) - double(30) (byte) - 64, 36: < (72) - 65, 37: if (4) (Opcode: 0xF3) - double(43) (byte) - 68, 38: type(array) (23) - 69, 39: type(string) (21) (Opcode: 0xF0) - variable[4](or op) (byte) - 72, 40: type(variable) (22) (Opcode: 0xF0) - variable[3](echo) (byte) - 75, 41: Call function (6) - 76, 42: Decrease last operand index by 1 (32) -*/ - - if (player.x > 15 || player.y < 30) { - echo("or op"); - } -} - -//#CLIENTSIDE -function onCreated() -{ - this.commands = {"Profile"}; - echo("EE"); -} - -function onMouseDown(temp.mtype) -{ - this.pid = onFindPlayers(); - - if (this.pid >= 0) - { - //if (this.pid == 0) - { - //player.showProfile(); - } - // else - { - onShowMenu(); - } - } -} - -function onFindPlayers() -{ - // Method 1 - UNTESTED - - /*temp.found = testplayer(mousex, mousey); - - if (temp.found) - { - return temp.found; - } - else - { - return -1; - }*/ - - // Method 2 - for (temp.I = 0; temp.I < players.size(); temp.I++) - { - if (mousex in |players[temp.I].x, players[temp.I].x + 3| && mousey in |players[temp.I].y, players[temp.I].y + 3|) - { - return temp.I; - } - } - - return -1; -} - -function onShowMenu() -{ - new GuiContextMenuCtrl(Profile_Menu) - { - profile = "GuiBluePopUpMenuProfile"; - textprofile = "GuiBlueTextListProfile"; - text = players[thiso.pid].account; - width = 20; - - clearrows(); - - addRow(0, players[thiso.pid].account); - addrow(-1, "-"); - for (temp.I = 0; temp.I < thiso.commands.size(); temp.I++) - { - addRow(temp.I + 1, thiso.commands[temp.I]); - } - - open(mousescreenx, mousescreeny); - } -} - -function Profile_Menu.onSelect(entryid, text) -{ - switch (text) - { - case "Profile": - { - players[this.pid].showProfile(); - - break; - } - - case "test": - { - echo("test"); - break; - } - - case "kfkf": - { - echo("yes"); - say2("hi"); - break; - } - - default: - { - echo("fallthrough"); - break; - } - } - - Profile_Menu.destroy(); -} - - -function onCreated() { - temp.tst = {3, 5, 7, "ee", "fkfk", 5, 143, 5839, 96, 819, 941}; - - echo("Test 1: " @ this.commands[0]); - - if (this.commands[0] == "Profile") - echo("EE"); - - temp.idx = 0; - for (temp.v : temp.tst) { - temp.idx++; - echo("Loop index: " @ temp.idx @ " = " @ temp.v); - - if (temp.v == 143) - break; - if (temp.v == 5) - continue; - - echo("Val: " @ temp.v); - } -} - -//#CLIENTSIDE -function onCreated() { - temp.z = random(1, 20); - - temp.z++; - this.a = temp.z++; - this.b = ++temp.z; - this.c = temp.z--; - this.d = --temp.z; - - echo(format("%d, %d, %d, %d", this.a, this.b, this.c, this.d)); -} - - -//#CLIENTSIDE -function onCreated() { - temp.a = player.nick @ player.account; - temp.b = player.nick NL player.account; - temp.c = player.nick TAB player.account; - temp.d = player.nick SPC player.account; - - player.chat = temp.a @ temp.b @ temp.c @ temp.d; -} - -function onCreated() { -/* - 6, 4: this. (180) - 7, 5: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 10, 6: member access (35) - 11, 7: type(number) (20) (Opcode: 0xF3) - double(3) (byte) - 14, 8: new[] (38) - 15, 9: type(number) (20) (Opcode: 0xF3) - double(2) (byte) - 18, 10: new[][] for each extra dimension (142) - 19, 11: "=" (50) -*/ - this.obj = new[3][2]; - -/* - 20, 12: this. (180) - 21, 13: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 24, 14: member access (35) - 25, 15: Convert to object (36) - 26, 16: type(number) (20) (Opcode: 0xF3) - double(1) (byte) - 29, 17: type(number) (20) (Opcode: 0xF3) - double(2) (byte) - 32, 18: type(number) (20) (Opcode: 0xF3) - double(3) (byte) - 35, 19: [a,b] assignment (134) -*/ - this.obj[1,2] = 3; - -/* - 36, 20: temp. (189) - 37, 21: type(variable) (22) (Opcode: 0xF0) - variable[1](v) (byte) - 40, 22: member access (35) - 41, 23: type(variable) (22) (Opcode: 0xF0) - variable[2](tiles) (byte) - 44, 24: Convert to object (36) - 45, 25: type(number) (20) (Opcode: 0xF3) - double(17) (byte) - 48, 26: type(number) (20) (Opcode: 0xF3) - double(16) (byte) - 51, 27: [a,b] (133) - 52, 28: "=" (50) -*/ - temp.v = tiles[17,16]; - -/* - 53, 29: player. (182) - 54, 30: type(variable) (22) (Opcode: 0xF0) - variable[3](chat) (byte) - 57, 31: member access (35) - 58, 32: type(string) (21) (Opcode: 0xF0) - variable[4](T: ) (byte) - 61, 33: temp. (189) - 62, 34: type(variable) (22) (Opcode: 0xF0) - variable[1](v) (byte) - 65, 35: member access (35) - 66, 36: Convert to string (34) - 67, 37: @ (113) - 68, 38: "=" (50) -*/ - player.chat = "T: " @ temp.v; -} - -public function test() { - player.chat = this.obj; -} - - -function onCreated() -{ - temp.v = "test"; - temp.arr = new[3]; - - - // temp.dump = getVal( obj.(@ temp.vars[i] ) ); -} - -function onCreated() { -/* - 6, 4: temp. (189) - 7, 5: type(variable) (22) (Opcode: 0xF0) - variable[0](a) (byte) - 10, 6: member access (35) - 11, 7: type(true) (24) - 12, 8: "=" (50) -*/ - temp.a = true; - -/* - 13, 9: temp. (189) - 14, 10: type(variable) (22) (Opcode: 0xF0) - variable[1](b) (byte) - 17, 11: member access (35) - 18, 12: temp. (189) - 19, 13: type(variable) (22) (Opcode: 0xF0) - variable[0](a) (byte) - 22, 14: member access (35) - 23, 15: Convert to float (33) - 24, 16: || (3) (Opcode: 0xF3) - double(21) (byte) - 27, 17: temp. (189) - 28, 18: type(variable) (22) (Opcode: 0xF0) - variable[2](c) (byte) - 31, 19: member access (35) - 32, 20: Convert to float (33) - 33, 21: End of inline conditional? (44) - 34, 22: "=" (50) -*/ - temp.b = (temp.a || temp.c); - -/* - 35, 23: player. (182) - 36, 24: type(variable) (22) (Opcode: 0xF0) - variable[3](chat) (byte) - 39, 25: member access (35) - 40, 26: type(string) (21) (Opcode: 0xF0) - variable[4](Test: ) (byte) - 43, 27: temp. (189) - 44, 28: type(variable) (22) (Opcode: 0xF0) - variable[1](b) (byte) - 47, 29: member access (35) - 48, 30: Convert to string (34) - 49, 31: @ (113) - 50, 32: "=" (50) -*/ - player.chat = "Test: " @ temp.b; -} - - -function onCreated() { -/* - 7, 5: temp. (189) - 8, 6: type(variable) (22) (Opcode: 0xF0) - variable[0](b) (byte) - 11, 7: member access (35) - 12, 8: Mark as loop variable (47) - 13, 9: Assign loop variable index (45) (Opcode: 0xF3) - double(0) (byte) - 16, 10: Decrease last operand index by 1 (32) - 17, 11: temp. (189) - 18, 12: type(variable) (22) (Opcode: 0xF0) - variable[1](a) (byte) - 21, 13: member access (35) - 22, 14: Mark as loop variable (47) - 23, 15: Assign loop variable index (45) (Opcode: 0xF3) - double(1) (byte) - 26, 16: Decrease last operand index by 1 (32) -*/ - -/* - 27, 17: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 30, 18: type(true) (24) - 31, 19: "=" (50) -*/ - temp.a = true; - -/* - 32, 20: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 35, 21: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 38, 22: Convert to float (33) - 39, 23: && (5) (Opcode: 0xF3) - double(28) (byte) - 42, 24: temp. (189) - 43, 25: type(variable) (22) (Opcode: 0xF0) - variable[2](c) (byte) - 46, 26: member access (35) - 47, 27: Convert to float (33) - 48, 28: End of inline conditional? (44) - 49, 29: "=" (50) -*/ - temp.b = (temp.a && temp.c); - -/* - 50, 30: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 53, 31: Convert to float (33) - 54, 32: || (3) (Opcode: 0xF3) - double(35) (byte) - 57, 33: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 60, 34: Convert to float (33) - 61, 35: if (4) (Opcode: 0xF3) - double(41) (byte) - 64, 36: type(array) (23) - 65, 37: type(string) (21) (Opcode: 0xF0) - variable[3](One is true) (byte) - 68, 38: type(variable) (22) (Opcode: 0xF0) - variable[4](echo) (byte) - 71, 39: Call function (6) - 72, 40: Decrease last operand index by 1 (32) -*/ - if (temp.a || temp.b) { - echo("One is true"); - } - -/* - 73, 41: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 76, 42: Convert to float (33) - 77, 43: if (4) (Opcode: 0xF3) - double(52) (byte) - 80, 44: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 83, 45: Convert to float (33) - 84, 46: if (4) (Opcode: 0xF3) - double(52) (byte) - 87, 47: type(array) (23) - 88, 48: type(string) (21) (Opcode: 0xF0) - variable[5](Both is true) (byte) - 91, 49: type(variable) (22) (Opcode: 0xF0) - variable[4](echo) (byte) - 94, 50: Call function (6) - 95, 51: Decrease last operand index by 1 (32) -*/ - if (temp.a && temp.b) { - echo("Both is true"); - } - -/* - 96, 52: Loop variable (46) (Opcode: 0xF3) - double(1) (byte) - 99, 53: Convert to float (33) - 100, 54: if (4) (Opcode: 0xF3) - double(64) (byte) - 103, 55: Loop variable (46) (Opcode: 0xF3) - double(0) (byte) - 106, 56: Convert to float (33) - 107, 57: ! (68) - 108, 58: if (4) (Opcode: 0xF3) - double(64) (byte) - 111, 59: type(array) (23) - 112, 60: type(string) (21) (Opcode: 0xF0) - variable[6](Only temp.a is true) (byte) - 115, 61: type(variable) (22) (Opcode: 0xF0) - variable[4](echo) (byte) - 118, 62: Call function (6) - 119, 63: Decrease last operand index by 1 (32) -*/ - if (temp.a && !temp.b) { - echo("Only temp.a is true"); - } -} - - - -//#CLIENTSIDE -function onCreated() { -/* - 7, 5: temp. (189) - 8, 6: type(variable) (22) (Opcode: 0xF0) - variable[0](q) (byte) - 11, 7: member access (35) - 12, 8: type(array) (23) - 13, 9: type(string) (21) (Opcode: 0xF0) - variable[1](asdf) (byte) - 16, 10: type(string) (21) (Opcode: 0xF0) - variable[2](some) (byte) - 19, 11: End of array (37) - 20, 12: "=" (50) -*/ - - temp.q = { "some", "asdf" }; - -/* - 21, 13: temp. (189) - 22, 14: type(variable) (22) (Opcode: 0xF0) - variable[3](I) (byte) - 25, 15: member access (35) - 26, 16: type(number) (20) (Opcode: 0xF3) - double(3) (byte) - 29, 17: "=" (50) -*/ - temp.I = 3; - -/* - 30, 18: this. (180) - 31, 19: type(variable) (22) (Opcode: 0xF0) - variable[4](items2) (byte) - 34, 20: member access (35) - 35, 21: Convert to object (36) - 36, 22: type(number) (20) (Opcode: 0xF3) - double(4) (byte) - 39, 23: setarray() (39) -*/ - setarray(this.items2, 4); - -/* - 40, 24: this. (180) - 41, 25: type(variable) (22) (Opcode: 0xF0) - variable[5](items) (byte) - 44, 26: member access (35) - 45, 27: Convert to object (36) - 46, 28: obj.clear() (141) -*/ - this.items.clear(); - -/* - 47, 29: this. (180) - 48, 30: type(variable) (22) (Opcode: 0xF0) - variable[5](items) (byte) - 51, 31: member access (35) - 52, 32: Convert to object (36) - 53, 33: type(array) (23) - 54, 34: temp. (189) - 55, 35: type(variable) (22) (Opcode: 0xF0) - variable[0](q) (byte) - 58, 36: member access (35) - 59, 37: temp. (189) - 60, 38: type(variable) (22) (Opcode: 0xF0) - variable[3](I) (byte) - 63, 39: member access (35) - 64, 40: End of array (37) - 65, 41: addstring() (136) -*/ - this.items.add({temp.I, temp.q}); - -/* - 66, 42: type(array) (23) - 67, 43: type(string) (21) (Opcode: 0xF0) - variable[6](Test: ) (byte) - 70, 44: this. (180) - 71, 45: type(variable) (22) (Opcode: 0xF0) - variable[5](items) (byte) - 74, 46: member access (35) - 75, 47: Convert to object (36) - 76, 48: obj.size() (130) - 77, 49: Convert to string (34) - 78, 50: @ (113) - 79, 51: type(variable) (22) (Opcode: 0xF0) - variable[7](echo) (byte) - 82, 52: Call function (6) - 83, 53: Decrease last operand index by 1 (32) -*/ - echo("Test: " @ this.items.size()); -} - - -public function isHuman() { -/* - 6, 4: type(variable) (22) (Opcode: 0xF0) - variable[0](clientr) (byte) - 9, 5: Convert to object (36) - 10, 6: type(variable) (22) (Opcode: 0xF0) - variable[1](race) (byte) - 13, 7: member access (35) - 14, 8: type(string) (21) (Opcode: 0xF0) - variable[2](human) (byte) - 17, 9: == (70) - 18, 10: if (4) (Opcode: 0xF3) - double(13) (byte) - 21, 11: type(true) (24) - 22, 12: Set operation index (1) (Opcode: 0xF3) - double(14) (byte) - 25, 13: type(false) (25) -*/ - return (clientr.race == "human" ? true : false); -} - - -public function someFunction() { -/* - 7, 5: this. (180) - 8, 6: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 11, 7: member access (35) - 12, 8: type(number) (20) (Opcode: 0xF3) - double(6) (byte) - 15, 9: new[] (38) - 16, 10: "=" (50) - -*/ - this.obj = new[6]; - -/* - 17, 11: temp. (189) - 18, 12: type(variable) (22) (Opcode: 0xF0) - variable[1](str) (byte) - 21, 13: member access (35) - 22, 14: this. (180) - 23, 15: type(variable) (22) (Opcode: 0xF0) - variable[0](obj) (byte) - 26, 16: member access (35) - 27, 17: Convert to string (34) - 28, 18: type(string) (21) (Opcode: 0xF0) - variable[2]( ,) (byte) - 31, 19: obj.tokenize() (118) - 32, 20: "=" (50) -*/ - temp.str = this.obj.tokenize(); - -/* - 33, 21: type(array) (23) - 34, 22: type(string) (21) (Opcode: 0xF0) - variable[3](Test: ) (byte) - 37, 23: temp. (189) - 38, 24: type(variable) (22) (Opcode: 0xF0) - variable[1](str) (byte) - 41, 25: member access (35) - 42, 26: Convert to string (34) - 43, 27: @ (113) - 44, 28: type(variable) (22) (Opcode: 0xF0) - variable[4](echo) (byte) - 47, 29: Call function (6) - 48, 30: Decrease last operand index by 1 (32) - 49, 31: type(number) (20) (Opcode: 0xF3) - double(0) (byte) -*/ - echo("Test: " @ temp.str); -} - - - -/* -//#CLIENTSIDE -function onCreated() { - this.func = this.func1; - this.func(123); - - this.func2 = function() { - echo("nameless functions"); - }; - } - function func1(param) { - echo("param: " @ param); - } -*/ - - - - - - - - -//#CLIENTSIDE -function onCreated() -{ - /* - 496, 294: this. (180) - 497, 295: type(variable) (22) (Opcode: 0xF0) - variable[52](particleSystemEditor) (byte) - 500, 296: member access (35) - 501, 297: type(variable) (22) (Opcode: 0xF0) - variable[53](unknown_object) (byte) - 504, 298: type(string) (21) (Opcode: 0xF0) - variable[0](TParticleSystemEditor) (byte) - 507, 299: new Object? (42) - 508, 300: "=" (50) -*/ - this.particleSystemEditor = new TParticleSystemEditor(); - player.chat = "fired2: " @ ++this.i; - -/* - 527, 311: this. (180) - 528, 312: type(variable) (22) (Opcode: 0xF0) - variable[55](someobj) (byte) - 531, 313: member access (35) - 532, 314: type(variable) (22) (Opcode: 0xF0) - variable[53](unknown_object) (byte) - 535, 315: type(string) (21) (Opcode: 0xF0) - variable[16](GuiWindowCtrl) (byte) - 538, 316: new Object? (42) - 539, 317: "=" (50) -*/ - this.someobj = new GuiWindowCtrl(); - this.someobj.show(); - - player.chat = "fired2.1: " @ ++this.i; - -/* - 571, 337: this. (180) - 572, 338: type(variable) (22) (Opcode: 0xF0) - variable[58](someobj2) (byte) - 575, 339: member access (35) - 576, 340: type(string) (21) (Opcode: 0xF0) - variable[59](SomeWindow) (byte) - 579, 341: inline new? (40) - 580, 342: type(string) (21) (Opcode: 0xF0) - variable[16](GuiWindowCtrl) (byte) - 583, 343: new Object? (42) - 584, 344: "=" (50) -*/ - this.someobj2 = new GuiWindowCtrl("SomeWindow"); - this.someobj2.show(); - player.chat = "fired2.2: " @ ++this.i; - -/* - 616, 364: this. (180) - 617, 365: type(variable) (22) (Opcode: 0xF0) - variable[61](someobj3) (byte) - 620, 366: member access (35) - 621, 367: type(string) (21) (Opcode: 0xF0) - variable[62](arg1) (byte) - 624, 368: inline new? (40) - 625, 369: type(string) (21) (Opcode: 0xF0) - variable[0](TParticleSystemEditor) (byte) - 628, 370: new Object? (42) - 629, 371: "=" (50) -*/ - this.someobj3 = new TParticleSystemEditor("arg1"); - player.chat = "fired2.3: " @ ++this.i; - -/* - 648, 382: this. (180) - 649, 383: type(variable) (22) (Opcode: 0xF0) - variable[64](someobj4) (byte) - 652, 384: member access (35) - 653, 385: type(variable) (22) (Opcode: 0xF0) - variable[53](unknown_object) (byte) - 656, 386: type(string) (21) (Opcode: 0xF0) - variable[0](TParticleSystemEditor) (byte) - 659, 387: new Object? (42) - 660, 388: "=" (50) -*/ - this.someobj4 = new TParticleSystemEditor("arg1", "arg2", "arg3"); - player.chat = "fired3: " @ ++this.i; - -/* - 679, 399: this. (180) - 680, 400: type(variable) (22) (Opcode: 0xF0) - variable[66](anotherobj) (byte) - 683, 401: member access (35) - 684, 402: type(variable) (22) (Opcode: 0xF0) - variable[53](unknown_object) (byte) - 687, 403: type(string) (21) (Opcode: 0xF0) - variable[3](TStaticVar) (byte) - 690, 404: new Object? (42) - 691, 405: "=" (50) -*/ - this.anotherobj = new TStaticVar(); - player.chat = "fired4: " @ ++this.i; - -/* - 710, 416: this. (180) - 711, 417: type(variable) (22) (Opcode: 0xF0) - variable[68](anotherobj2) (byte) - 714, 418: member access (35) - 715, 419: type(string) (21) (Opcode: 0xF0) - variable[13](test) (byte) - 718, 420: inline new? (40) - 719, 421: type(string) (21) (Opcode: 0xF0) - variable[3](TStaticVar) (byte) - 722, 422: new Object? (42) - 723, 423: "=" (50) -*/ - this.anotherobj2 = new TStaticVar("test"); - player.chat = "fired5: " @ ++this.i; - -/* - 742, 434: this. (180) - 743, 435: type(variable) (22) (Opcode: 0xF0) - variable[70](anotherobj3) (byte) - 746, 436: member access (35) - 747, 437: type(variable) (22) (Opcode: 0xF0) - variable[53](unknown_object) (byte) - 750, 438: type(string) (21) (Opcode: 0xF0) - variable[3](TStaticVar) (byte) - 753, 439: new Object? (42) - 754, 440: "=" (50) -*/ - this.anotherobj3 = new TStaticVar("test", "abc"); - player.chat = "fired6: " @ ++this.i; - - this.particleSystemEditor.initialize(findImg(300)); - player.chat = "fired8: " @ ++this.i; -} - - diff --git a/src/CompilerThreadJob.h b/src/CompilerThreadJob.h index 1a4b883..673b773 100644 --- a/src/CompilerThreadJob.h +++ b/src/CompilerThreadJob.h @@ -8,7 +8,7 @@ #include #include "encoding/buffer.h" -#include "GS2Context.h" +#include "compiler/GS2Context.h" /////// This class will allow you to queue lambda functions into a threadpool diff --git a/src/ast/astvisitor.h b/src/ast/NodeVisitor.h similarity index 96% rename from src/ast/astvisitor.h rename to src/ast/NodeVisitor.h index 034707d..d606a7d 100644 --- a/src/ast/astvisitor.h +++ b/src/ast/NodeVisitor.h @@ -6,7 +6,9 @@ class NodeVisitor { public: - virtual void Visit(class Node *node) = 0; + virtual ~NodeVisitor() = default; + + virtual void Visit(class Node *node) = 0; virtual void Visit(class StatementNode *node) = 0; virtual void Visit(class StatementBlock *node) = 0; virtual void Visit(class StatementIfNode *node) = 0; diff --git a/src/ast/ast.h b/src/ast/ast.h index 5848232..9d539af 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -9,7 +9,7 @@ #include #include "ast/expressiontypes.h" -#include "ast/astvisitor.h" +#include "ast/NodeVisitor.h" #define _NodeName(name) \ inline static const char * NodeName = name; \ diff --git a/src/GS2Bytecode.cpp b/src/codegen/GS2Bytecode.cpp similarity index 100% rename from src/GS2Bytecode.cpp rename to src/codegen/GS2Bytecode.cpp diff --git a/src/GS2Bytecode.h b/src/codegen/GS2Bytecode.h similarity index 100% rename from src/GS2Bytecode.h rename to src/codegen/GS2Bytecode.h diff --git a/src/GS2BuiltInFunctions.cpp b/src/compiler/GS2BuiltInFunctions.cpp similarity index 100% rename from src/GS2BuiltInFunctions.cpp rename to src/compiler/GS2BuiltInFunctions.cpp diff --git a/src/GS2BuiltInFunctions.h b/src/compiler/GS2BuiltInFunctions.h similarity index 100% rename from src/GS2BuiltInFunctions.h rename to src/compiler/GS2BuiltInFunctions.h diff --git a/src/visitors/GS2CompilerVisitor.cpp b/src/compiler/GS2CompilerVisitor.cpp similarity index 99% rename from src/visitors/GS2CompilerVisitor.cpp rename to src/compiler/GS2CompilerVisitor.cpp index 138a720..8e5436b 100644 --- a/src/visitors/GS2CompilerVisitor.cpp +++ b/src/compiler/GS2CompilerVisitor.cpp @@ -4,8 +4,8 @@ #include "ast/ast.h" #include "visitors/FunctionInspectVisitor.h" -#include "visitors/GS2CompilerVisitor.h" -#include "Parser.h" +#include "compiler/GS2CompilerVisitor.h" +#include "parser/Parser.h" opcode::Opcode getExpressionOpCode(ExpressionOp op) { diff --git a/src/visitors/GS2CompilerVisitor.h b/src/compiler/GS2CompilerVisitor.h similarity index 99% rename from src/visitors/GS2CompilerVisitor.h rename to src/compiler/GS2CompilerVisitor.h index efd9eb4..504db0f 100644 --- a/src/visitors/GS2CompilerVisitor.h +++ b/src/compiler/GS2CompilerVisitor.h @@ -7,7 +7,7 @@ #include #include #include -#include "ast/astvisitor.h" +#include "ast/NodeVisitor.h" #include "GS2Bytecode.h" #include "GS2BuiltInFunctions.h" diff --git a/src/GS2Context.cpp b/src/compiler/GS2Context.cpp similarity index 98% rename from src/GS2Context.cpp rename to src/compiler/GS2Context.cpp index a863a6a..464a14b 100644 --- a/src/GS2Context.cpp +++ b/src/compiler/GS2Context.cpp @@ -1,7 +1,7 @@ #include #include "GS2Context.h" #include "encoding/graalencoding.h" -#include "visitors/GS2CompilerVisitor.h" +#include "compiler/GS2CompilerVisitor.h" #include "GS2Bytecode.h" #include "Parser.h" diff --git a/src/GS2Context.h b/src/compiler/GS2Context.h similarity index 96% rename from src/GS2Context.h rename to src/compiler/GS2Context.h index 56348af..8fb0699 100644 --- a/src/GS2Context.h +++ b/src/compiler/GS2Context.h @@ -5,6 +5,7 @@ #include #include +#include "gs2compiler_export.h" #include "encoding/buffer.h" #include "exceptions/GS2CompilerError.h" #include "GS2BuiltInFunctions.h" @@ -18,7 +19,7 @@ struct CompilerResponse std::set joinedClasses; }; -class GS2Context +class GS2COMPILER_EXPORT GS2Context { public: GS2Context(); diff --git a/src/main.cpp b/src/main.cpp index 80ad789..8278c94 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ #include #include #include -#include "GS2Context.h" +#include "compiler/GS2Context.h" struct Response { diff --git a/src/memory/ArenaAllocator.h b/src/memory/ArenaAllocator.h new file mode 100644 index 0000000..c7ff882 --- /dev/null +++ b/src/memory/ArenaAllocator.h @@ -0,0 +1,120 @@ +#pragma once + +#ifndef ARENAALLOCATOR_H +#define ARENAALLOCATOR_H + +#include +#include +#include +#include + +template +class ArenaAllocator { +public: + static constexpr size_t CHUNK_SIZE = DefaultChunkSize; + + ArenaAllocator() : current_(nullptr), remaining_(0) {} + ArenaAllocator(const ArenaAllocator&) = delete; + ArenaAllocator& operator=(const ArenaAllocator&) = delete; + + ArenaAllocator(ArenaAllocator&& other) noexcept + : chunks_(std::move(other.chunks_)), + current_(std::exchange(other.current_, nullptr)), + remaining_(std::exchange(other.remaining_, 0)) { + } + + ArenaAllocator& operator=(ArenaAllocator&& other) noexcept { + if (this != &other) { + chunks_ = std::move(other.chunks_); + current_ = std::exchange(other.current_, nullptr); + remaining_ = std::exchange(other.remaining_, 0); + } + return *this; + } + + ~ArenaAllocator() = default; + + /** + * Allocate and construct an object of type T + * + * @tparam T The type to allocate + * @tparam Args Constructor argument types + * @param args Constructor arguments + * @return Pointer to constructed object + */ + template + [[nodiscard]] T* allocate(Args&&... args) { + void* ptr = allocate_raw(sizeof(T), alignof(T)); + return std::construct_at(static_cast(ptr), std::forward(args)...); + } + + /** + * Reset the arena, freeing all allocated memory + */ + void reset() noexcept { + chunks_.clear(); + current_ = nullptr; + remaining_ = 0; + } + + /** + * Get total allocated memory (including overhead) + */ + [[nodiscard]] size_t total_allocated() const { + size_t total = 0; + for (const auto& chunk : chunks_) { + total += chunk.size; + } + return total; + } + + /** + * Get number of chunks allocated + */ + [[nodiscard]] size_t chunk_count() const { + return chunks_.size(); + } + +private: + /** + * Represents a memory chunk + */ + struct Chunk { + std::unique_ptr data; + size_t size{}; + }; + + /** + * Allocate raw memory with proper alignment + * + * @param size Number of bytes to allocate + * @param alignment Required alignment (must be power of 2) + * @return Pointer to allocated memory + */ + void* allocate_raw(size_t size, size_t alignment) { + void* ptr = current_; + size_t space = remaining_; + + if (!ptr || !std::align(alignment, size, ptr, space)) { + // Need a new chunk + size_t chunk_size = std::max(size + alignment, CHUNK_SIZE); + chunks_.push_back(Chunk{ + std::make_unique(chunk_size), + chunk_size + }); + ptr = current_ = chunks_.back().data.get(); + space = remaining_ = chunk_size; + std::align(alignment, size, ptr, space); + } + + current_ = static_cast(ptr) + size; + remaining_ = space - size; + return ptr; + } + + std::vector chunks_; + std::byte* current_; + size_t remaining_; +}; + +#endif // ARENAALLOCATOR_H diff --git a/src/Parser.cpp b/src/parser/Parser.cpp similarity index 94% rename from src/Parser.cpp rename to src/parser/Parser.cpp index baba284..413fa1a 100644 --- a/src/Parser.cpp +++ b/src/parser/Parser.cpp @@ -62,7 +62,7 @@ std::string unquoteString(std::string_view str) } ParserContext::ParserContext(GS2ErrorService& service) - : lineNumber(0), columnNumber(0), buffer(nullptr), failed(false), inputStringPtr(nullptr), + : lineNumber(0), columnNumber(0), scanner(nullptr), buffer(nullptr), failed(false), inputStringPtr(nullptr), lambdaFunctionCount(0), programNode(nullptr), errorService(service) { yylex_init_extra(this, &scanner); @@ -83,9 +83,13 @@ ParserContext::~ParserContext() void ParserContext::cleanup() { - for (auto& n : nodes) - delete n; - nodes.clear(); +#ifdef DBGALLOCATIONS + printf("Memory allocated for nodes: %zu bytes in %zu chunks\n", + nodeArena.total_allocated(), nodeArena.chunk_count()); +#endif + + // Reset arena - frees all nodes at once + nodeArena.reset(); } void ParserContext::reset() diff --git a/src/Parser.h b/src/parser/Parser.h similarity index 89% rename from src/Parser.h rename to src/parser/Parser.h index 4c4f6de..f993c5b 100644 --- a/src/Parser.h +++ b/src/parser/Parser.h @@ -14,6 +14,7 @@ #include #include "ast/ast.h" +#include "memory/ArenaAllocator.h" #include "exceptions/GS2CompilerError.h" typedef void* yyscan_t; @@ -111,14 +112,6 @@ class ParserContext template T *alloc(P&&... params); - /* - * Deallocate node instance, recommend avoid using - * as any node allocated with alloc() will be deallocated - * by a call to cleanup(), or in the destructor of the context - */ - template - void dealloc(T *n); - private: /** * Cleanup any nodes allocated @@ -141,7 +134,7 @@ class ParserContext std::unordered_map> stringTable; std::stack switchCases; - std::vector nodes; + ArenaAllocator<> nodeArena; StatementBlock* programNode; GS2ErrorService& errorService; }; @@ -204,27 +197,15 @@ inline void ParserContext::addError(GS2CompilerError error) /* * Memory Allocation for Nodes + * + * Uses arena allocator for fast allocation with excellent cache locality. + * All nodes are freed together when the ParserContext is destroyed or reset. */ template inline T *ParserContext::alloc(P && ...params) { - T *n = new T(std::forward

(params)...); - nodes.push_back(n); + T *n = nodeArena.allocate(std::forward

(params)...); return n; } -/* - * Memory Deallocation for Nodes - */ -template -inline void ParserContext::dealloc(T *n) -{ - if (n) - { - nodes.erase(std::remove(nodes.begin(), nodes.end(), n), nodes.end()); - delete n; - } -} - - #endif diff --git a/generator/gs2parser.y b/src/parser/gs2parser.y similarity index 100% rename from generator/gs2parser.y rename to src/parser/gs2parser.y diff --git a/generator/gs2scanner.l b/src/parser/gs2scanner.l similarity index 100% rename from generator/gs2scanner.l rename to src/parser/gs2scanner.l diff --git a/src/ast/astnodevisitor.h b/src/visitors/ASTNodeVisitor.h similarity index 99% rename from src/ast/astnodevisitor.h rename to src/visitors/ASTNodeVisitor.h index 6eecca5..881b6c1 100644 --- a/src/ast/astnodevisitor.h +++ b/src/visitors/ASTNodeVisitor.h @@ -3,7 +3,7 @@ #ifndef ASTVISITORIMPL_H #define ASTVISITORIMPL_H -#include "ast.h" +#include "../ast/ast.h" class ASTNodeVisitor : public NodeVisitor { diff --git a/src/visitors/FunctionInspectVisitor.h b/src/visitors/FunctionInspectVisitor.h index c915cd2..94bd145 100644 --- a/src/visitors/FunctionInspectVisitor.h +++ b/src/visitors/FunctionInspectVisitor.h @@ -3,7 +3,7 @@ #ifndef FUNCTIONINSPECTVISITOR_H #define FUNCTIONINSPECTVISITOR_H -#include "ast/astnodevisitor.h" +#include "ASTNodeVisitor.h" class FunctionInspectVisitor : public ASTNodeVisitor { diff --git a/test-workflow.sh b/test-workflow.sh deleted file mode 100755 index 470faaf..0000000 --- a/test-workflow.sh +++ /dev/null @@ -1,197 +0,0 @@ -#!/bin/bash -# Test GitHub Actions workflow locally using 'act' - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Check if act is installed -if ! command -v act &> /dev/null; then - echo -e "${RED}Error: 'act' is not installed${NC}" - echo "" - echo "Install act with:" - echo " macOS: brew install act" - echo " Linux: curl -s https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash" - echo " Windows: choco install act-cli" - echo "" - echo "Visit: https://github.com/nektos/act" - exit 1 -fi - -# Function to print usage -usage() { - echo -e "${BLUE}GitHub Actions Local Testing Tool${NC}" - echo "" - echo "Usage: $0 [command] [options]" - echo "" - echo "Commands:" - echo " list - List all available workflows and jobs" - echo " quick - Quick test (Ubuntu Release build only)" - echo " full - Full matrix test (all OS and build types)" - echo " ubuntu - Test Ubuntu builds (Debug + Release)" - echo " macos - Test macOS builds (Debug + Release)" - echo " windows - Test Windows builds (Debug + Release)" - echo " debug - Test Debug builds (all platforms)" - echo " release - Test Release builds (all platforms)" - echo " dry-run - Show what would run without executing" - echo " custom - Run custom act command (pass additional args)" - echo "" - echo "Options:" - echo " -v, --verbose - Verbose output" - echo " -h, --help - Show this help message" - echo "" - echo "Examples:" - echo " $0 quick # Fast test on Ubuntu Release" - echo " $0 ubuntu -v # Test Ubuntu with verbose output" - echo " $0 custom -j build-and-test --matrix os:macos-latest" - exit 0 -} - -# Parse global options -VERBOSE="" -while [[ $# -gt 0 ]]; do - case $1 in - -h|--help) - usage - ;; - -v|--verbose) - VERBOSE="-v" - shift - ;; - *) - break - ;; - esac -done - -COMMAND=${1:-quick} - -echo -e "${GREEN}Testing GitHub Actions workflow locally...${NC}" -echo "" - -case $COMMAND in - list) - echo -e "${YELLOW}Available workflows and jobs:${NC}" - act -l - ;; - - quick) - echo -e "${YELLOW}Running quick test (Ubuntu Release)...${NC}" - act --rm push -j build-and-test \ - --matrix os:ubuntu-latest \ - --matrix build_type:Release \ - -W .github/workflows/ci.yml \ - $VERBOSE - ;; - - full) - echo -e "${YELLOW}Running full matrix test (this will take a while)...${NC}" - echo -e "${RED}Warning: This will test all OS/build_type combinations${NC}" - read -p "Continue? (y/N) " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - act --rm --bind push -j build-and-test \ - -W .github/workflows/ci.yml \ - $VERBOSE - else - echo "Cancelled." - exit 0 - fi - ;; - - ubuntu) - echo -e "${YELLOW}Testing Ubuntu builds (Debug + Release)...${NC}" - echo "Running Release build..." - act --rm --bind push -j build-and-test \ - --matrix os:ubuntu-latest \ - --matrix build_type:Release \ - -W .github/workflows/ci.yml \ - $VERBOSE - - echo "" - echo "Running Debug build..." - act --rm --bind push -j build-and-test \ - --matrix os:ubuntu-latest \ - --matrix build_type:Debug \ - -W .github/workflows/ci.yml \ - $VERBOSE - ;; - - macos) - echo -e "${YELLOW}Testing macOS builds (Debug + Release)...${NC}" - echo "Running Release build..." - act --rm --bind push -j build-and-test \ - --matrix os:macos-latest \ - --matrix build_type:Release \ - -W .github/workflows/ci.yml \ - $VERBOSE - - echo "" - echo "Running Debug build..." - act --rm --bind push -j build-and-test \ - --matrix os:macos-latest \ - --matrix build_type:Debug \ - -W .github/workflows/ci.yml \ - $VERBOSE - ;; - - windows) - echo -e "${YELLOW}Testing Windows builds (Debug + Release)...${NC}" - echo "Running Release build..." - act --rm --bind push -j build-and-test \ - --matrix os:windows-latest \ - --matrix build_type:Release \ - -W .github/workflows/ci.yml \ - $VERBOSE - - echo "" - echo "Running Debug build..." - act --rm --bind push -j build-and-test \ - --matrix os:windows-latest \ - --matrix build_type:Debug \ - -W .github/workflows/ci.yml \ - $VERBOSE - ;; - - debug) - echo -e "${YELLOW}Testing Debug builds (all platforms)...${NC}" - act --rm --bind push -j build-and-test \ - --matrix build_type:Debug \ - -W .github/workflows/ci.yml \ - $VERBOSE - ;; - - release) - echo -e "${YELLOW}Testing Release builds (all platforms)...${NC}" - act --rm --bind push -j build-and-test \ - --matrix build_type:Release \ - -W .github/workflows/ci.yml \ - $VERBOSE - ;; - - dry-run) - echo -e "${YELLOW}Dry run - showing what would execute...${NC}" - act -n -W .github/workflows/ci.yml - ;; - - custom) - shift # Remove 'custom' from args - echo -e "${YELLOW}Running custom act command...${NC}" - echo "Command: act --rm --bind push -W .github/workflows/ci.yml $@" - act --rm --bind push -W .github/workflows/ci.yml "$@" - ;; - - *) - echo -e "${RED}Error: Unknown command '$COMMAND'${NC}" - echo "" - usage - ;; -esac - -echo "" -echo -e "${GREEN}Done!${NC}" \ No newline at end of file diff --git a/tests/tools/run_tests.py b/tests/tools/run_tests.py index 77ca6a3..b6e3afc 100755 --- a/tests/tools/run_tests.py +++ b/tests/tools/run_tests.py @@ -72,6 +72,7 @@ def _find_compiler(self) -> Path: """Find the GS2 compiler executable""" possible_paths = [ self.project_root / "bin" / "gs2test", + self.project_root / "build" / "bin" / "gs2test", self.project_root / "build" / "gs2test", self.project_root / "build" / "Debug" / "gs2test", self.project_root / "build" / "Release" / "gs2test", From b1579926d5ee44ead6879f7d803a1a35e266d170 Mon Sep 17 00:00:00 2001 From: joey <1166538+xtjoeytx@users.noreply.github.com> Date: Sat, 7 Feb 2026 16:23:20 -0500 Subject: [PATCH 2/6] Feature/cmake fetchcontent (#29) * arena allocator for ast node allocations & change directory structure * cmake changes * fix gs2test location * Attempt to fix windows build * ^ * ^ * ^ * package fix attempt * Fix rust build * Remove fmtlib dependency * cmake changes * fix osx? * ^ * ^ * ^ * ^ * Remove submodule winflexbison --- .gitmodules | 3 - CMakeLists.txt | 271 ++++++++++++++++++++------------------ dependencies/winflexbison | 1 - 3 files changed, 144 insertions(+), 131 deletions(-) delete mode 160000 dependencies/winflexbison diff --git a/.gitmodules b/.gitmodules index 0445495..a7a569e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "dependencies/winflexbison"] - path = dependencies/winflexbison - url = https://github.com/lexxmark/winflexbison.git [submodule "dependencies/emsdk"] path = dependencies/emsdk url = https://github.com/emscripten-core/emsdk.git diff --git a/CMakeLists.txt b/CMakeLists.txt index ec63432..8e06367 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,44 +1,54 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.28) project(gs2parser VERSION 1.0) include(GenerateExportHeader) +set(CMAKE_CXX_SCAN_FOR_MODULES OFF) -set(CMAKE_DEBUG_POSTFIX _d) +if(PROJECT_IS_TOP_LEVEL) + set(CMAKE_DEBUG_POSTFIX _d) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(BIN_DIR "bin" CACHE STRING "Binary output directory") + set(BIN_DIR "bin" CACHE STRING "Binary output directory") -# specify the C++ standard -set(CMAKE_CXX_STANDARD 23) -set(CMAKE_CXX_STANDARD_REQUIRED True) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) + # Set up output directories in the build tree + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${BIN_DIR}) -# Set up output directories in the build tree -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${BIN_DIR}) + # Second, for multi-config builds (e.g. msvc) + foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${BIN_DIR}) + endforeach() -# Second, for multi-config builds (e.g. msvc) -foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) - string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) - set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib ) - set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib ) - set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${BIN_DIR} ) -endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) - -if(WIN32 OR APPLE) - set(CMAKE_SHARED_LIBRARY_PREFIX "") - set(CMAKE_STATIC_LIBRARY_PREFIX "lib") -endif() - -if(APPLE) - set(CMAKE_OSX_DEPLOYMENT_TARGET "13.3") + if(APPLE) + set(CMAKE_OSX_DEPLOYMENT_TARGET "13.3") + endif() endif() if(WIN32 AND NOT MINGW) - execute_process(COMMAND ${CMAKE_COMMAND} -S${CMAKE_CURRENT_SOURCE_DIR}/dependencies/winflexbison -B${CMAKE_CURRENT_SOURCE_DIR}/dependencies/winflexbison/build-winflex-bison -GNinja -DCMAKE_BUILD_TYPE=Release) - execute_process(COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/winflexbison/build-winflex-bison --parallel 8) - LIST(APPEND CMAKE_PROGRAM_PATH ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/winflexbison/bin/Release) + include(FetchContent) + FetchContent_Declare(winflexbison + GIT_REPOSITORY https://github.com/lexxmark/winflexbison.git + GIT_TAG 2040672b690523e6a5b2e51480d90132a39d4c76 + ) + FetchContent_Populate(winflexbison) + execute_process( + COMMAND ${CMAKE_COMMAND} + -S ${winflexbison_SOURCE_DIR} + -B ${winflexbison_BINARY_DIR} + -G Ninja + -DCMAKE_BUILD_TYPE=Release + ) + execute_process( + COMMAND ${CMAKE_COMMAND} + --build ${winflexbison_BINARY_DIR} + --parallel + ) + list(APPEND CMAKE_PROGRAM_PATH ${winflexbison_SOURCE_DIR}/bin/Release) set(FLEX_FLAGS "--wincompat") -endif(WIN32 AND NOT MINGW) +endif() find_package(BISON 3.4 REQUIRED) find_package(FLEX REQUIRED) @@ -48,84 +58,96 @@ FLEX_TARGET(GS2Scanner src/parser/gs2scanner.l ${CMAKE_CURRENT_BINARY_DIR}/lex.y ADD_FLEX_BISON_DEPENDENCY(GS2Scanner GS2Parser) set(SOURCES - # AST - src/ast/ast.cpp + # AST + src/ast/ast.cpp - # Encoding - src/encoding/buffer.cpp + # Encoding + src/encoding/buffer.cpp - # Codegen - src/codegen/GS2Bytecode.cpp + # Codegen + src/codegen/GS2Bytecode.cpp - # Compiler - src/compiler/GS2BuiltInFunctions.cpp - src/compiler/GS2CompilerVisitor.cpp - src/compiler/GS2Context.cpp + # Compiler + src/compiler/GS2BuiltInFunctions.cpp + src/compiler/GS2CompilerVisitor.cpp + src/compiler/GS2Context.cpp - # Parser - src/parser/Parser.cpp - ${BISON_GS2Parser_OUTPUTS} - ${FLEX_GS2Scanner_OUTPUTS} + # Parser + src/parser/Parser.cpp + ${BISON_GS2Parser_OUTPUTS} + ${FLEX_GS2Scanner_OUTPUTS} ) set(HEADERS - # AST - src/ast/ast.h - src/ast/expressiontypes.h - src/ast/NodeVisitor.h - - # Encoding - src/encoding/buffer.h - src/encoding/graalencoding.h - - # Codegen - src/codegen/GS2Bytecode.h - - # Compiler - src/compiler/GS2BuiltInFunctions.h - src/compiler/GS2CompilerVisitor.h - src/compiler/GS2Context.h - - # Parser - src/parser/Parser.h - ${BISON_GS2Parser_INPUT} - ${FLEX_GS2Scanner_INPUT} - - # Memory - src/memory/ArenaAllocator.h - - # Visitors - src/visitors/ASTNodeVisitor.h - src/visitors/FunctionInspectVisitor.h - src/visitors/GS2SourceVisitor.h - - # Utils / Misc - src/CompilerThreadJob.h - src/exceptions/GS2CompilerError.h - src/opcodes.h - src/utils/ContextThreadPool.h - src/utils/EventHandler.h + # AST + src/ast/ast.h + src/ast/expressiontypes.h + src/ast/NodeVisitor.h + + # Encoding + src/encoding/buffer.h + src/encoding/graalencoding.h + + # Codegen + src/codegen/GS2Bytecode.h + + # Compiler + src/compiler/GS2BuiltInFunctions.h + src/compiler/GS2CompilerVisitor.h + src/compiler/GS2Context.h + + # Parser + src/parser/Parser.h + ${BISON_GS2Parser_INPUT} + ${FLEX_GS2Scanner_INPUT} + + # Memory + src/memory/ArenaAllocator.h + + # Visitors + src/visitors/ASTNodeVisitor.h + src/visitors/FunctionInspectVisitor.h + src/visitors/GS2SourceVisitor.h + + # Utils / Misc + src/CompilerThreadJob.h + src/exceptions/GS2CompilerError.h + src/opcodes.h + src/utils/ContextThreadPool.h + src/utils/EventHandler.h ) set(SOURCES_ALL ${SOURCES} ${HEADERS}) -# Use standard BUILD_SHARED_LIBS; Emscripten doesn't support shared libs +option(BUILD_SHARED_LIBS "Build shared libraries" ON) if(EMSCRIPTEN) - set(BUILD_SHARED_LIBS OFF) + set(BUILD_SHARED_LIBS OFF CACHE BOOL "Emscripten doesn't support shared libs" FORCE) endif() -option(BUILD_SHARED_LIBS "Build shared libraries" ON) add_library(gs2compiler ${SOURCES_ALL} bindings/c/c_interface.cpp) +add_library(gs2parser::gs2compiler ALIAS gs2compiler) generate_export_header(gs2compiler - BASE_NAME GS2COMPILER - EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/gs2compiler_export.h + BASE_NAME GS2COMPILER + EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/gs2compiler_export.h ) +target_compile_features(gs2compiler PUBLIC cxx_std_23) +set_target_properties(gs2compiler PROPERTIES + POSITION_INDEPENDENT_CODE ON + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN ON +) +if(WIN32 OR APPLE) + if(BUILD_SHARED_LIBS) + set_target_properties(gs2compiler PROPERTIES PREFIX "") + endif() +endif() + target_include_directories(gs2compiler - PUBLIC + PUBLIC $ $ - PRIVATE + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/parser ${CMAKE_CURRENT_SOURCE_DIR}/src/codegen ${CMAKE_CURRENT_SOURCE_DIR}/src/compiler @@ -141,17 +163,21 @@ if(WIN32 AND MINGW) target_compile_options(gs2compiler PRIVATE "-fno-rtti") endif() -if(EMSCRIPTEN) - add_executable(gs2test bindings/js/js_interface.cpp) - set_target_properties(gs2test PROPERTIES LINK_FLAGS "--embind-emit-tsd=gs2test.d.ts -s ENVIRONMENT=web -s DYNAMIC_EXECUTION=0 -s SINGLE_FILE=1 -s MODULARIZE -s 'EXPORT_NAME=GS2Compiler' --bind") -else() - add_executable(gs2test src/main.cpp) +option(GS2PARSER_BUILD_GS2TEST "Build gs2test executable" ${PROJECT_IS_TOP_LEVEL}) + +if(GS2PARSER_BUILD_GS2TEST) + if(EMSCRIPTEN) + add_executable(gs2test bindings/js/js_interface.cpp) + set_target_properties(gs2test PROPERTIES LINK_FLAGS "--embind-emit-tsd=gs2test.d.ts -s ENVIRONMENT=web -s DYNAMIC_EXECUTION=0 -s SINGLE_FILE=1 -s MODULARIZE -s 'EXPORT_NAME=GS2Compiler' --bind") + else() + add_executable(gs2test src/main.cpp) + endif() + target_link_libraries(gs2test PRIVATE gs2compiler) endif() -target_link_libraries(gs2test PRIVATE gs2compiler) # Test suite integration # Only configure tests if this is the main project (not a subproject) -if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) +if(PROJECT_IS_TOP_LEVEL) # Enable testing enable_testing() @@ -163,60 +189,51 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/tests/outputs) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/tests/reports) - # Custom target: Run all tests with verbose output - add_custom_target(run-tests - COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/tools/run_tests.py + set(TEST_RUNNER_CMD + ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/tools/run_tests.py --project-root ${CMAKE_CURRENT_SOURCE_DIR} --scripts-dir ${CMAKE_CURRENT_SOURCE_DIR}/tests/scripts --baselines-dir ${CMAKE_CURRENT_SOURCE_DIR}/tests/baselines --output-dir ${CMAKE_BINARY_DIR}/tests/outputs --reports-dir ${CMAKE_BINARY_DIR}/tests/reports - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Running test suite" - DEPENDS gs2test + ) + + add_custom_target(run-tests + COMMAND ${TEST_RUNNER_CMD} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running test suite" + DEPENDS gs2test ) # Custom target: Generate/update baselines add_custom_target(test-baselines - COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/tools/run_tests.py - --project-root ${CMAKE_CURRENT_SOURCE_DIR} - --scripts-dir ${CMAKE_CURRENT_SOURCE_DIR}/tests/scripts - --baselines-dir ${CMAKE_CURRENT_SOURCE_DIR}/tests/baselines - --output-dir ${CMAKE_BINARY_DIR}/tests/outputs - --reports-dir ${CMAKE_BINARY_DIR}/tests/reports - --update-baselines - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Generating test baselines" - DEPENDS gs2test + COMMAND ${TEST_RUNNER_CMD} --update-baselines + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating test baselines" + DEPENDS gs2test ) # Custom target: Clean test artifacts add_custom_target(test-clean - COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/tests/outputs - COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/tests/reports - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/tests/outputs - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/tests/reports - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Cleaning test artifacts" + COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/tests/outputs + COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/tests/reports + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/tests/outputs + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/tests/reports + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Cleaning test artifacts" ) # CTest integration for CI/CD add_test( - NAME regression_tests - COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/tools/run_tests.py - --project-root ${CMAKE_CURRENT_SOURCE_DIR} - --scripts-dir ${CMAKE_CURRENT_SOURCE_DIR}/tests/scripts - --baselines-dir ${CMAKE_CURRENT_SOURCE_DIR}/tests/baselines - --output-dir ${CMAKE_BINARY_DIR}/tests/outputs - --reports-dir ${CMAKE_BINARY_DIR}/tests/reports - --quiet - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + NAME regression_tests + COMMAND ${TEST_RUNNER_CMD} --quiet + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) # Set test properties set_tests_properties(regression_tests PROPERTIES - TIMEOUT 60 - FAIL_REGULAR_EXPRESSION "Regressions detected" + TIMEOUT 60 + FAIL_REGULAR_EXPRESSION "Regressions detected" ) message(STATUS "Test suite configured") diff --git a/dependencies/winflexbison b/dependencies/winflexbison deleted file mode 160000 index 9118533..0000000 --- a/dependencies/winflexbison +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 911853359017d3e817d638a0de18881eb7960de9 From 43ae0e4076ac30429e825412508ffc477b9ed205 Mon Sep 17 00:00:00 2001 From: joey <1166538+xtjoeytx@users.noreply.github.com> Date: Sat, 7 Feb 2026 16:50:58 -0500 Subject: [PATCH 3/6] fix merge (#31) --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0803c0f..8e06367 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,7 +142,6 @@ if(WIN32 OR APPLE) set_target_properties(gs2compiler PROPERTIES PREFIX "") endif() endif() -option(BUILD_SHARED_LIBS "Build shared libraries" ON) target_include_directories(gs2compiler PUBLIC @@ -175,7 +174,6 @@ if(GS2PARSER_BUILD_GS2TEST) endif() target_link_libraries(gs2test PRIVATE gs2compiler) endif() -target_link_libraries(gs2test PRIVATE gs2compiler) # Test suite integration # Only configure tests if this is the main project (not a subproject) From b2aa34938b789040b83577ea26ea37ff8c1e5c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=BB=E4=BD=93?= Date: Sun, 22 Feb 2026 15:41:13 +0100 Subject: [PATCH 4/6] Fix C-interface and add UnitTests for dotnet bindings to catch these errors in the future --- .gitignore | 3 + bindings/c/c_interface.cpp | 157 +++++++++--------- bindings/dotnet/CompilerResponse.cs | 13 +- bindings/dotnet/GS2Compiler.cs | 54 +++--- .../InterfacesTests.cs | 67 ++++++++ ...nal.Scripting.GS2Compiler.UnitTests.csproj | 35 ++++ .../Preagonal.Scripting.GS2Compiler.csproj | 48 +++++- .../Preagonal.Scripting.GS2Compiler.sln | 6 + ...onal.Scripting.GS2Compiler.sln.DotSettings | 2 + bindings/dotnet/Response.cs | 19 ++- 10 files changed, 279 insertions(+), 125 deletions(-) create mode 100644 bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/InterfacesTests.cs create mode 100644 bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/Preagonal.Scripting.GS2Compiler.UnitTests.csproj create mode 100644 bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln.DotSettings diff --git a/.gitignore b/.gitignore index 9b3ee8c..64b023b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# User files +*.user + # Prerequisites *.d diff --git a/bindings/c/c_interface.cpp b/bindings/c/c_interface.cpp index d626e14..6b5483d 100644 --- a/bindings/c/c_interface.cpp +++ b/bindings/c/c_interface.cpp @@ -1,92 +1,87 @@ #include "compiler/GS2Context.h" #ifdef _WIN32 -#define DLL_EXPORT __declspec(dllexport) + #define DLL_EXPORT extern "C" __declspec(dllexport) #else -#define DLL_EXPORT + #define DLL_EXPORT extern "C" __attribute__((visibility("default"))) #endif -extern "C" { - struct Response { - bool Success; - const char *ErrMsg; - unsigned char *ByteCode; - uint32_t ByteCodeSize; - }; - - DLL_EXPORT void *get_context() { - return new GS2Context(); +struct Response { + bool Success; + const char *ErrMsg; + unsigned char *ByteCode; + uint32_t ByteCodeSize; +}; + +DLL_EXPORT void *get_context() { + return new GS2Context(); +} + +DLL_EXPORT Response compile_code_no_header(void *context, const char *code) { + Response result{}; + result.Success = false; + + if (const auto gs2Context = static_cast(context); gs2Context != nullptr) { + const std::string script = code; + std::string errMsg; + const auto response = gs2Context->compile(script); + + if (!response.errors.empty()) { + errMsg.clear(); + for (const auto &err: response.errors) + errMsg.append(err.msg()).append("\n"); + + const int lenStr = errMsg.length() + 1; + result.ErrMsg = new char[lenStr]; + strcpy(const_cast(result.ErrMsg), errMsg.c_str()); + + result.ByteCode = nullptr; + result.ByteCodeSize = 0; + } else { + result.ErrMsg = nullptr; + result.ByteCode = new unsigned char[response.bytecode.length()]; // Allocate memory + memcpy(result.ByteCode, response.bytecode.buffer(), response.bytecode.length()); + result.ByteCodeSize = response.bytecode.length(); } - - DLL_EXPORT Response compile_code_no_header(void *context, const char *code) { - Response result{}; - result.Success = false; - - auto gs2Context = (GS2Context *) context; - - if (gs2Context != nullptr) { - std::string script = code; - std::string errMsg; - auto response = gs2Context->compile(script); - - if (!response.errors.empty()) { - errMsg.clear(); - for (const auto &err: response.errors) - errMsg.append(err.msg()).append("\n"); - - int lenStr = errMsg.length() + 1; - result.ErrMsg = new char[lenStr]; - strcpy(const_cast(result.ErrMsg), errMsg.c_str()); - - result.ByteCode = nullptr; - result.ByteCodeSize = 0; - } else { - result.ErrMsg = nullptr; - result.ByteCode = new unsigned char[response.bytecode.length()]; // Allocate memory - memcpy((void *) result.ByteCode, response.bytecode.buffer(), response.bytecode.length()); - result.ByteCodeSize = response.bytecode.length(); - } - result.Success = response.success; - } - - return result; + result.Success = response.success; + } + + return result; +} + +DLL_EXPORT Response compile_code(void *context, const char *code, const char *type, const char *name) { + Response result{}; + result.Success = false; + + if (const auto gs2Context = static_cast(context); + gs2Context != nullptr) { + const std::string script = code; + std::string errMsg; + const auto response = gs2Context->compile(script, type, name, true); + + if (!response.errors.empty()) { + errMsg.clear(); + for (const auto &err: response.errors) + errMsg.append(err.msg()).append("\n"); + + const int lenStr = errMsg.length() + 1; + result.ErrMsg = new char[lenStr]; + strcpy(const_cast(result.ErrMsg), errMsg.c_str()); + + result.ByteCode = nullptr; + result.ByteCodeSize = 0; + } else { + result.ErrMsg = nullptr; + result.ByteCode = new unsigned char[response.bytecode.length()]; // Allocate memory + memcpy(result.ByteCode, response.bytecode.buffer(), response.bytecode.length()); + result.ByteCodeSize = response.bytecode.length(); } + result.Success = response.success; + } - DLL_EXPORT Response compile_code(void *context, const char *code, const char *type, const char *name) { - Response result{}; - result.Success = false; - - auto gs2Context = (GS2Context *) context; - - if (gs2Context != nullptr) { - std::string script = code; - std::string errMsg; - auto response = gs2Context->compile(script, type, name, true); - - if (!response.errors.empty()) { - errMsg.clear(); - for (const auto &err: response.errors) - errMsg.append(err.msg()).append("\n"); - - int lenStr = errMsg.length() + 1; - result.ErrMsg = new char[lenStr]; - strcpy(const_cast(result.ErrMsg), errMsg.c_str()); - - result.ByteCode = nullptr; - result.ByteCodeSize = 0; - } else { - result.ErrMsg = nullptr; - result.ByteCode = new unsigned char[response.bytecode.length()]; // Allocate memory - memcpy((void *) result.ByteCode, response.bytecode.buffer(), response.bytecode.length()); - result.ByteCodeSize = response.bytecode.length(); - } - result.Success = response.success; - } - - return result; - } + return result; +} - DLL_EXPORT void delete_context(void *context) { - delete (GS2Context *) context; - } +DLL_EXPORT void delete_context(void *context) { + delete static_cast(context); } \ No newline at end of file diff --git a/bindings/dotnet/CompilerResponse.cs b/bindings/dotnet/CompilerResponse.cs index 89345ae..665499a 100644 --- a/bindings/dotnet/CompilerResponse.cs +++ b/bindings/dotnet/CompilerResponse.cs @@ -1,9 +1,8 @@ -namespace Preagonal.Scripting.GS2Compiler +namespace Preagonal.Scripting.GS2Compiler; + +public struct CompilerResponse { - public struct CompilerResponse - { - public bool Success; - public string? ErrMsg; - public byte[] ByteCode; - } + public bool Success; + public string? ErrMsg; + public byte[] ByteCode; } \ No newline at end of file diff --git a/bindings/dotnet/GS2Compiler.cs b/bindings/dotnet/GS2Compiler.cs index 4c683f1..0f9477d 100644 --- a/bindings/dotnet/GS2Compiler.cs +++ b/bindings/dotnet/GS2Compiler.cs @@ -1,38 +1,40 @@ using System.Runtime.InteropServices; -namespace Preagonal.Scripting.GS2Compiler +namespace Preagonal.Scripting.GS2Compiler; + +public static class Interface { - public static class Interface - { - [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr get_context(); + [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr get_context(); - [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] - private static extern Response compile_code(IntPtr context, string? code, string? type, string? name); + [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] + private static extern Response compile_code(IntPtr context, string? code, string? type, string? name); - [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] - private static extern void delete_context(IntPtr context); + [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] + private static extern Response compile_code_no_header(IntPtr context, string? code); - public static CompilerResponse CompileCode(string? code, string? type = "weapon", string? name = "npc") - { - IntPtr context = get_context(); - Response response = compile_code(context, code, type, name); + [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] + private static extern void delete_context(IntPtr context); - CompilerResponse compilerResponse = new() - { - Success = response.Success, - ErrMsg = response.ErrMsg, - }; - - if (response.ByteCodeSize > 0) - { - compilerResponse.ByteCode = new byte[response.ByteCodeSize]; - Marshal.Copy(response.ByteCode, compilerResponse.ByteCode, 0, (int)response.ByteCodeSize); - } + public static CompilerResponse CompileCode(string? code, string? type = "weapon", string? name = "npc", bool withHeader = true) + { + var context = get_context(); + var response = withHeader ? compile_code(context, code, type, name) : compile_code_no_header(context, code); - delete_context(context); + CompilerResponse compilerResponse = new() + { + Success = response.Success, + ErrMsg = response.ErrMsg, + }; - return compilerResponse; + if (response.ByteCodeSize > 0) + { + compilerResponse.ByteCode = new byte[response.ByteCodeSize]; + Marshal.Copy(response.ByteCode, compilerResponse.ByteCode, 0, (int)response.ByteCodeSize); } + + delete_context(context); + + return compilerResponse; } } \ No newline at end of file diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/InterfacesTests.cs b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/InterfacesTests.cs new file mode 100644 index 0000000..18b0105 --- /dev/null +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/InterfacesTests.cs @@ -0,0 +1,67 @@ +using Xunit; +using Xunit.Abstractions; + +namespace Preagonal.Scripting.GS2Compiler.UnitTests; + +public class InterfacesTests(ITestOutputHelper testOutputHelper) +{ + [Fact] + public void Given_script_that_is_faulty_When_compiling_Then_success_is_false_and_error_message_is_returned() + { + //Arrange + const string scriptText = + """ + //#CLIENTSIDE + function onCreated() + } + """; + + + //Act + var result = Interface.CompileCode(scriptText); + + //Assert + Assert.False(result.Success); + Assert.Equal("malformed input at line 3: \t\t\t}\n", result.ErrMsg); + } + + [Fact] + public void Given_script_that_is_correct_When_compiling_Then_success_is_true_and_bytecode_is_not_empty() + { + //Arrange + const string scriptText = + """ + //#CLIENTSIDE + function onCreated() { + } + """; + + + //Act + var result = Interface.CompileCode(scriptText); + + //Assert + Assert.True(result.Success); + Assert.NotEmpty(result.ByteCode); + } + + [Fact] + public void Given_script_that_is_correct_When_compiling_without_header_Then_success_is_true_and_bytecode_is_not_empty() + { + //Arrange + const string scriptText = + """ + //#CLIENTSIDE + function onCreated() { + } + """; + + + //Act + var result = Interface.CompileCode(scriptText, withHeader: false); + + //Assert + Assert.True(result.Success); + Assert.NotEmpty(result.ByteCode); + } +} \ No newline at end of file diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/Preagonal.Scripting.GS2Compiler.UnitTests.csproj b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/Preagonal.Scripting.GS2Compiler.UnitTests.csproj new file mode 100644 index 0000000..44300b6 --- /dev/null +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/Preagonal.Scripting.GS2Compiler.UnitTests.csproj @@ -0,0 +1,35 @@ + + + + net10.0 + enable + enable + + false + + default + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + \ No newline at end of file diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.csproj b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.csproj index 1ebabbb..9f5ec36 100644 --- a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.csproj +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.csproj @@ -12,7 +12,7 @@ 1.0.0 1.0.0 en-US - netstandard2.0 + netstandard2.1 Preagonal.Scripting.GS2Compiler Preagonal.Scripting.GS2Compiler Preagonal.Scripting.GS2Compiler @@ -26,12 +26,56 @@ true true - + + + + + + + + + + + true + + + + + libgs2compiler.so + PreserveNewest + + + + libgs2compiler.so + PreserveNewest + + + + gs2compiler.dll + PreserveNewest + + + + gs2compiler.dylib + PreserveNewest + + + + gs2compiler.dylib + PreserveNewest + + + diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln index 2d013aa..bb5ffc3 100644 --- a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln @@ -2,6 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Preagonal.Scripting.GS2Compiler", "Preagonal.Scripting.GS2Compiler.csproj", "{B47BCFF5-10F6-4D45-96B8-A6E2E7F40AFA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Preagonal.Scripting.GS2Compiler.UnitTests", "Preagonal.Scripting.GS2Compiler.UnitTests\Preagonal.Scripting.GS2Compiler.UnitTests.csproj", "{5C15D15C-91B0-446C-9B03-AE1440726EF8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +14,9 @@ Global {B47BCFF5-10F6-4D45-96B8-A6E2E7F40AFA}.Debug|Any CPU.Build.0 = Debug|Any CPU {B47BCFF5-10F6-4D45-96B8-A6E2E7F40AFA}.Release|Any CPU.ActiveCfg = Release|Any CPU {B47BCFF5-10F6-4D45-96B8-A6E2E7F40AFA}.Release|Any CPU.Build.0 = Release|Any CPU + {5C15D15C-91B0-446C-9B03-AE1440726EF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C15D15C-91B0-446C-9B03-AE1440726EF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C15D15C-91B0-446C-9B03-AE1440726EF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C15D15C-91B0-446C-9B03-AE1440726EF8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln.DotSettings b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln.DotSettings new file mode 100644 index 0000000..9c94afc --- /dev/null +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln.DotSettings @@ -0,0 +1,2 @@ + + GS \ No newline at end of file diff --git a/bindings/dotnet/Response.cs b/bindings/dotnet/Response.cs index 7ca512d..5c3f159 100644 --- a/bindings/dotnet/Response.cs +++ b/bindings/dotnet/Response.cs @@ -1,11 +1,12 @@ #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value -namespace Preagonal.Scripting.GS2Compiler +namespace Preagonal.Scripting.GS2Compiler; + +internal struct Response { - internal struct Response - { - public bool Success; - public string ErrMsg; - public IntPtr ByteCode; - public uint ByteCodeSize; - } -} \ No newline at end of file + public bool Success; + public string ErrMsg; + public IntPtr ByteCode; + public uint ByteCodeSize; +} + +#pragma warning restore CS0649 \ No newline at end of file From 83ca2503a0e4696f3d6850d63bc974356a0f0f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=BB=E4=BD=93?= Date: Sun, 22 Feb 2026 15:48:48 +0100 Subject: [PATCH 5/6] Add test step for dotnet bindings --- Jenkinsfile | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ee10ba0..fd748c3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -93,7 +93,7 @@ def buildStepDocker() { def split_job_name = env.JOB_NAME.split(/\/{1}/); def fixed_job_name = split_job_name[1].replace('%2F',' '); - def customImage = docker.image("mcr.microsoft.com/dotnet/sdk:9.0"); + def customImage = docker.image("mcr.microsoft.com/dotnet/sdk:10.0"); customImage.pull(); try { @@ -138,6 +138,51 @@ def buildStepDocker() { } } } + + stage("Run tests...") { + customImage.inside("-u 0") { + dir("bindings/dotnet/") { + try{ + sh("dotnet test --logger \"trx;LogFileName=../../Testing/unit_tests.xml\""); + sh("dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover"); + sh("chmod 777 -R ."); + } catch(err) { + currentBuild.result = 'FAILURE' + sh("chmod 777 -R ."); + discordSend(description: "Testing Failed: ${fixed_job_name} #${env.BUILD_NUMBER}", footer: "", link: env.BUILD_URL, result: currentBuild.currentResult, title: "[${split_job_name[0]}] Tests Failed: ${fixed_job_name} #${env.BUILD_NUMBER}", webhookURL: env.GS2EMU_WEBHOOK); + notify('Build failed') + } + + archiveArtifacts ( + artifacts: 'Testing/**.xml', + fingerprint: true + ) + + withCredentials([string(credentialsId: 'PREAGONAL_GS2ENGINE_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) { + sh("curl -s https://codecov.io/bash > codecov && chmod +x codecov && ./codecov -f \"Testing/unit_tests.xml\" -t ${env.CODECOV_TOKEN} && ./codecov -f \"Preagonal.Scripting.GS2Compiler.UnitTests/coverage.opencover.xml\" -t ${env.CODECOV_TOKEN}") + } + + stage("Xunit") { + xunit ( + testTimeMargin: '3000', + thresholdMode: 1, + thresholds: [ + skipped(failureThreshold: '1000'), + failed(failureThreshold: '0') + ], + tools: [MSTest( + pattern: 'Testing/**.xml', + deleteOutputFiles: true, + failIfNotNew: false, + skipNoTestFiles: true, + stopProcessingIfError: true + )], + skipPublishingChecks: false + ); + } + } + } + } def archive_date = sh ( script: 'date +"-%Y%m%d-%H%M"', @@ -266,7 +311,7 @@ killall_jobs(); parallel(branches); - def customImage = docker.image("mcr.microsoft.com/dotnet/sdk:9.0"); + def customImage = docker.image("mcr.microsoft.com/dotnet/sdk:10.0"); customImage.pull(); project.builds.each { v -> From 1638c38354c928aaf9d7d3469839999212fa222d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=BB=E4=BD=93?= <50087831+xx-shitai-xx@users.noreply.github.com> Date: Sun, 22 Feb 2026 17:45:09 +0100 Subject: [PATCH 6/6] Fix c interface and bindings (#34) * Fix C-interface and add UnitTests for dotnet bindings to catch these errors in the future * Add test step for dotnet bindings * Disable codecov for now --- .gitignore | 3 + Jenkinsfile | 51 +++++- bindings/c/c_interface.cpp | 157 +++++++++--------- bindings/dotnet/CompilerResponse.cs | 13 +- bindings/dotnet/GS2Compiler.cs | 54 +++--- .../InterfacesTests.cs | 67 ++++++++ ...nal.Scripting.GS2Compiler.UnitTests.csproj | 35 ++++ .../Preagonal.Scripting.GS2Compiler.csproj | 61 ++++++- .../Preagonal.Scripting.GS2Compiler.sln | 6 + ...onal.Scripting.GS2Compiler.sln.DotSettings | 2 + bindings/dotnet/Response.cs | 19 ++- 11 files changed, 340 insertions(+), 128 deletions(-) create mode 100644 bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/InterfacesTests.cs create mode 100644 bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/Preagonal.Scripting.GS2Compiler.UnitTests.csproj create mode 100644 bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln.DotSettings diff --git a/.gitignore b/.gitignore index 9b3ee8c..64b023b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# User files +*.user + # Prerequisites *.d diff --git a/Jenkinsfile b/Jenkinsfile index ee10ba0..c1fb07e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -93,7 +93,7 @@ def buildStepDocker() { def split_job_name = env.JOB_NAME.split(/\/{1}/); def fixed_job_name = split_job_name[1].replace('%2F',' '); - def customImage = docker.image("mcr.microsoft.com/dotnet/sdk:9.0"); + def customImage = docker.image("mcr.microsoft.com/dotnet/sdk:10.0"); customImage.pull(); try { @@ -138,6 +138,53 @@ def buildStepDocker() { } } } + + stage("Run tests...") { + customImage.inside("-u 0") { + dir("bindings/dotnet/") { + try{ + sh("dotnet test -c Debug -r linux-x64 --logger \"trx;LogFileName=../../Testing/unit_tests.xml\""); + sh("dotnet test -c Debug -r linux-x64 /p:CollectCoverage=true /p:CoverletOutputFormat=opencover"); + sh("chmod 777 -R ."); + } catch(err) { + currentBuild.result = 'FAILURE' + sh("chmod 777 -R ."); + discordSend(description: "Testing Failed: ${fixed_job_name} #${env.BUILD_NUMBER}", footer: "", link: env.BUILD_URL, result: currentBuild.currentResult, title: "[${split_job_name[0]}] Tests Failed: ${fixed_job_name} #${env.BUILD_NUMBER}", webhookURL: env.GS2EMU_WEBHOOK); + notify('Build failed') + } + + archiveArtifacts ( + artifacts: 'Testing/**.xml', + fingerprint: true + ) + + /* TODO: Enable when codecov is added to GS2Compiler project + withCredentials([string(credentialsId: 'PREAGONAL_GS2ENGINE_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) { + sh("curl -s https://codecov.io/bash > codecov && chmod +x codecov && ./codecov -f \"Testing/unit_tests.xml\" -t ${env.CODECOV_TOKEN} && ./codecov -f \"Preagonal.Scripting.GS2Compiler.UnitTests/coverage.opencover.xml\" -t ${env.CODECOV_TOKEN}") + } + */ + + stage("Xunit") { + xunit ( + testTimeMargin: '3000', + thresholdMode: 1, + thresholds: [ + skipped(failureThreshold: '1000'), + failed(failureThreshold: '0') + ], + tools: [MSTest( + pattern: 'Testing/**.xml', + deleteOutputFiles: true, + failIfNotNew: false, + skipNoTestFiles: true, + stopProcessingIfError: true + )], + skipPublishingChecks: false + ); + } + } + } + } def archive_date = sh ( script: 'date +"-%Y%m%d-%H%M"', @@ -266,7 +313,7 @@ killall_jobs(); parallel(branches); - def customImage = docker.image("mcr.microsoft.com/dotnet/sdk:9.0"); + def customImage = docker.image("mcr.microsoft.com/dotnet/sdk:10.0"); customImage.pull(); project.builds.each { v -> diff --git a/bindings/c/c_interface.cpp b/bindings/c/c_interface.cpp index d626e14..6b5483d 100644 --- a/bindings/c/c_interface.cpp +++ b/bindings/c/c_interface.cpp @@ -1,92 +1,87 @@ #include "compiler/GS2Context.h" #ifdef _WIN32 -#define DLL_EXPORT __declspec(dllexport) + #define DLL_EXPORT extern "C" __declspec(dllexport) #else -#define DLL_EXPORT + #define DLL_EXPORT extern "C" __attribute__((visibility("default"))) #endif -extern "C" { - struct Response { - bool Success; - const char *ErrMsg; - unsigned char *ByteCode; - uint32_t ByteCodeSize; - }; - - DLL_EXPORT void *get_context() { - return new GS2Context(); +struct Response { + bool Success; + const char *ErrMsg; + unsigned char *ByteCode; + uint32_t ByteCodeSize; +}; + +DLL_EXPORT void *get_context() { + return new GS2Context(); +} + +DLL_EXPORT Response compile_code_no_header(void *context, const char *code) { + Response result{}; + result.Success = false; + + if (const auto gs2Context = static_cast(context); gs2Context != nullptr) { + const std::string script = code; + std::string errMsg; + const auto response = gs2Context->compile(script); + + if (!response.errors.empty()) { + errMsg.clear(); + for (const auto &err: response.errors) + errMsg.append(err.msg()).append("\n"); + + const int lenStr = errMsg.length() + 1; + result.ErrMsg = new char[lenStr]; + strcpy(const_cast(result.ErrMsg), errMsg.c_str()); + + result.ByteCode = nullptr; + result.ByteCodeSize = 0; + } else { + result.ErrMsg = nullptr; + result.ByteCode = new unsigned char[response.bytecode.length()]; // Allocate memory + memcpy(result.ByteCode, response.bytecode.buffer(), response.bytecode.length()); + result.ByteCodeSize = response.bytecode.length(); } - - DLL_EXPORT Response compile_code_no_header(void *context, const char *code) { - Response result{}; - result.Success = false; - - auto gs2Context = (GS2Context *) context; - - if (gs2Context != nullptr) { - std::string script = code; - std::string errMsg; - auto response = gs2Context->compile(script); - - if (!response.errors.empty()) { - errMsg.clear(); - for (const auto &err: response.errors) - errMsg.append(err.msg()).append("\n"); - - int lenStr = errMsg.length() + 1; - result.ErrMsg = new char[lenStr]; - strcpy(const_cast(result.ErrMsg), errMsg.c_str()); - - result.ByteCode = nullptr; - result.ByteCodeSize = 0; - } else { - result.ErrMsg = nullptr; - result.ByteCode = new unsigned char[response.bytecode.length()]; // Allocate memory - memcpy((void *) result.ByteCode, response.bytecode.buffer(), response.bytecode.length()); - result.ByteCodeSize = response.bytecode.length(); - } - result.Success = response.success; - } - - return result; + result.Success = response.success; + } + + return result; +} + +DLL_EXPORT Response compile_code(void *context, const char *code, const char *type, const char *name) { + Response result{}; + result.Success = false; + + if (const auto gs2Context = static_cast(context); + gs2Context != nullptr) { + const std::string script = code; + std::string errMsg; + const auto response = gs2Context->compile(script, type, name, true); + + if (!response.errors.empty()) { + errMsg.clear(); + for (const auto &err: response.errors) + errMsg.append(err.msg()).append("\n"); + + const int lenStr = errMsg.length() + 1; + result.ErrMsg = new char[lenStr]; + strcpy(const_cast(result.ErrMsg), errMsg.c_str()); + + result.ByteCode = nullptr; + result.ByteCodeSize = 0; + } else { + result.ErrMsg = nullptr; + result.ByteCode = new unsigned char[response.bytecode.length()]; // Allocate memory + memcpy(result.ByteCode, response.bytecode.buffer(), response.bytecode.length()); + result.ByteCodeSize = response.bytecode.length(); } + result.Success = response.success; + } - DLL_EXPORT Response compile_code(void *context, const char *code, const char *type, const char *name) { - Response result{}; - result.Success = false; - - auto gs2Context = (GS2Context *) context; - - if (gs2Context != nullptr) { - std::string script = code; - std::string errMsg; - auto response = gs2Context->compile(script, type, name, true); - - if (!response.errors.empty()) { - errMsg.clear(); - for (const auto &err: response.errors) - errMsg.append(err.msg()).append("\n"); - - int lenStr = errMsg.length() + 1; - result.ErrMsg = new char[lenStr]; - strcpy(const_cast(result.ErrMsg), errMsg.c_str()); - - result.ByteCode = nullptr; - result.ByteCodeSize = 0; - } else { - result.ErrMsg = nullptr; - result.ByteCode = new unsigned char[response.bytecode.length()]; // Allocate memory - memcpy((void *) result.ByteCode, response.bytecode.buffer(), response.bytecode.length()); - result.ByteCodeSize = response.bytecode.length(); - } - result.Success = response.success; - } - - return result; - } + return result; +} - DLL_EXPORT void delete_context(void *context) { - delete (GS2Context *) context; - } +DLL_EXPORT void delete_context(void *context) { + delete static_cast(context); } \ No newline at end of file diff --git a/bindings/dotnet/CompilerResponse.cs b/bindings/dotnet/CompilerResponse.cs index 89345ae..665499a 100644 --- a/bindings/dotnet/CompilerResponse.cs +++ b/bindings/dotnet/CompilerResponse.cs @@ -1,9 +1,8 @@ -namespace Preagonal.Scripting.GS2Compiler +namespace Preagonal.Scripting.GS2Compiler; + +public struct CompilerResponse { - public struct CompilerResponse - { - public bool Success; - public string? ErrMsg; - public byte[] ByteCode; - } + public bool Success; + public string? ErrMsg; + public byte[] ByteCode; } \ No newline at end of file diff --git a/bindings/dotnet/GS2Compiler.cs b/bindings/dotnet/GS2Compiler.cs index 4c683f1..0f9477d 100644 --- a/bindings/dotnet/GS2Compiler.cs +++ b/bindings/dotnet/GS2Compiler.cs @@ -1,38 +1,40 @@ using System.Runtime.InteropServices; -namespace Preagonal.Scripting.GS2Compiler +namespace Preagonal.Scripting.GS2Compiler; + +public static class Interface { - public static class Interface - { - [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr get_context(); + [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr get_context(); - [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] - private static extern Response compile_code(IntPtr context, string? code, string? type, string? name); + [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] + private static extern Response compile_code(IntPtr context, string? code, string? type, string? name); - [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] - private static extern void delete_context(IntPtr context); + [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] + private static extern Response compile_code_no_header(IntPtr context, string? code); - public static CompilerResponse CompileCode(string? code, string? type = "weapon", string? name = "npc") - { - IntPtr context = get_context(); - Response response = compile_code(context, code, type, name); + [DllImport("gs2compiler", CallingConvention = CallingConvention.Cdecl)] + private static extern void delete_context(IntPtr context); - CompilerResponse compilerResponse = new() - { - Success = response.Success, - ErrMsg = response.ErrMsg, - }; - - if (response.ByteCodeSize > 0) - { - compilerResponse.ByteCode = new byte[response.ByteCodeSize]; - Marshal.Copy(response.ByteCode, compilerResponse.ByteCode, 0, (int)response.ByteCodeSize); - } + public static CompilerResponse CompileCode(string? code, string? type = "weapon", string? name = "npc", bool withHeader = true) + { + var context = get_context(); + var response = withHeader ? compile_code(context, code, type, name) : compile_code_no_header(context, code); - delete_context(context); + CompilerResponse compilerResponse = new() + { + Success = response.Success, + ErrMsg = response.ErrMsg, + }; - return compilerResponse; + if (response.ByteCodeSize > 0) + { + compilerResponse.ByteCode = new byte[response.ByteCodeSize]; + Marshal.Copy(response.ByteCode, compilerResponse.ByteCode, 0, (int)response.ByteCodeSize); } + + delete_context(context); + + return compilerResponse; } } \ No newline at end of file diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/InterfacesTests.cs b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/InterfacesTests.cs new file mode 100644 index 0000000..18b0105 --- /dev/null +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/InterfacesTests.cs @@ -0,0 +1,67 @@ +using Xunit; +using Xunit.Abstractions; + +namespace Preagonal.Scripting.GS2Compiler.UnitTests; + +public class InterfacesTests(ITestOutputHelper testOutputHelper) +{ + [Fact] + public void Given_script_that_is_faulty_When_compiling_Then_success_is_false_and_error_message_is_returned() + { + //Arrange + const string scriptText = + """ + //#CLIENTSIDE + function onCreated() + } + """; + + + //Act + var result = Interface.CompileCode(scriptText); + + //Assert + Assert.False(result.Success); + Assert.Equal("malformed input at line 3: \t\t\t}\n", result.ErrMsg); + } + + [Fact] + public void Given_script_that_is_correct_When_compiling_Then_success_is_true_and_bytecode_is_not_empty() + { + //Arrange + const string scriptText = + """ + //#CLIENTSIDE + function onCreated() { + } + """; + + + //Act + var result = Interface.CompileCode(scriptText); + + //Assert + Assert.True(result.Success); + Assert.NotEmpty(result.ByteCode); + } + + [Fact] + public void Given_script_that_is_correct_When_compiling_without_header_Then_success_is_true_and_bytecode_is_not_empty() + { + //Arrange + const string scriptText = + """ + //#CLIENTSIDE + function onCreated() { + } + """; + + + //Act + var result = Interface.CompileCode(scriptText, withHeader: false); + + //Assert + Assert.True(result.Success); + Assert.NotEmpty(result.ByteCode); + } +} \ No newline at end of file diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/Preagonal.Scripting.GS2Compiler.UnitTests.csproj b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/Preagonal.Scripting.GS2Compiler.UnitTests.csproj new file mode 100644 index 0000000..44300b6 --- /dev/null +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.UnitTests/Preagonal.Scripting.GS2Compiler.UnitTests.csproj @@ -0,0 +1,35 @@ + + + + net10.0 + enable + enable + + false + + default + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + \ No newline at end of file diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.csproj b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.csproj index 1ebabbb..2ccfec4 100644 --- a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.csproj +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.csproj @@ -12,7 +12,7 @@ 1.0.0 1.0.0 en-US - netstandard2.0 + netstandard2.1 Preagonal.Scripting.GS2Compiler Preagonal.Scripting.GS2Compiler Preagonal.Scripting.GS2Compiler @@ -26,12 +26,67 @@ true true - + + + + + + + + - + + + true + + + + + <_Rid>$(RuntimeIdentifier) + + + <_Rid Condition="'$(_Rid)'==''">$(NETCoreSdkRuntimeIdentifier) + + + + + + libgs2compiler.so + PreserveNewest + + + + libgs2compiler.so + PreserveNewest + + + + + gs2compiler.dll + PreserveNewest + + + + + gs2compiler.dylib + PreserveNewest + + + + gs2compiler.dylib + PreserveNewest + + + + \ No newline at end of file diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln index 2d013aa..bb5ffc3 100644 --- a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln @@ -2,6 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Preagonal.Scripting.GS2Compiler", "Preagonal.Scripting.GS2Compiler.csproj", "{B47BCFF5-10F6-4D45-96B8-A6E2E7F40AFA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Preagonal.Scripting.GS2Compiler.UnitTests", "Preagonal.Scripting.GS2Compiler.UnitTests\Preagonal.Scripting.GS2Compiler.UnitTests.csproj", "{5C15D15C-91B0-446C-9B03-AE1440726EF8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +14,9 @@ Global {B47BCFF5-10F6-4D45-96B8-A6E2E7F40AFA}.Debug|Any CPU.Build.0 = Debug|Any CPU {B47BCFF5-10F6-4D45-96B8-A6E2E7F40AFA}.Release|Any CPU.ActiveCfg = Release|Any CPU {B47BCFF5-10F6-4D45-96B8-A6E2E7F40AFA}.Release|Any CPU.Build.0 = Release|Any CPU + {5C15D15C-91B0-446C-9B03-AE1440726EF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C15D15C-91B0-446C-9B03-AE1440726EF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C15D15C-91B0-446C-9B03-AE1440726EF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C15D15C-91B0-446C-9B03-AE1440726EF8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln.DotSettings b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln.DotSettings new file mode 100644 index 0000000..9c94afc --- /dev/null +++ b/bindings/dotnet/Preagonal.Scripting.GS2Compiler.sln.DotSettings @@ -0,0 +1,2 @@ + + GS \ No newline at end of file diff --git a/bindings/dotnet/Response.cs b/bindings/dotnet/Response.cs index 7ca512d..5c3f159 100644 --- a/bindings/dotnet/Response.cs +++ b/bindings/dotnet/Response.cs @@ -1,11 +1,12 @@ #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value -namespace Preagonal.Scripting.GS2Compiler +namespace Preagonal.Scripting.GS2Compiler; + +internal struct Response { - internal struct Response - { - public bool Success; - public string ErrMsg; - public IntPtr ByteCode; - public uint ByteCodeSize; - } -} \ No newline at end of file + public bool Success; + public string ErrMsg; + public IntPtr ByteCode; + public uint ByteCodeSize; +} + +#pragma warning restore CS0649 \ No newline at end of file