diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 30dc2de8b4..7d6b566535 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -312,27 +312,27 @@ jobs: [ "${{ env.das_llvm_disabled }}" = "ON" ] || ./daScriptTest -jit ./daScriptTest # Use more time to pass UBSAN and disable leaks in JIT mode because we exit using exit(), and do not call destructors. - [ "${{ env.das_llvm_disabled }}" = "ON" ] || ASAN_OPTIONS=detect_leaks=0 ./daslang _dasroot_/dastest/dastest.das -jit -- --color --test ../tests || ASAN_OPTIONS=detect_leaks=0 ./daslang _dasroot_/dastest/dastest.das -jit -- --color --isolated-mode --timeout 1600 --test ../tests - ./daslang _dasroot_/dastest/dastest.das -- --color --test ../tests || ./daslang _dasroot_/dastest/dastest.das -- --color --isolated-mode --timeout 1200 --test ../tests + [ "${{ env.das_llvm_disabled }}" = "ON" ] || ASAN_OPTIONS=detect_leaks=0 ./daslang _dasroot_/dastest/dastest.das -jit -- --color --test ../tests || ASAN_OPTIONS=detect_leaks=0 ./daslang _dasroot_/dastest/dastest.das -jit -- --color --isolated-mode --timeout 4800 --test ../tests + ./daslang _dasroot_/dastest/dastest.das -- --color --test ../tests || ./daslang _dasroot_/dastest/dastest.das -- --color --isolated-mode --timeout 3600 --test ../tests ;; windows32) cd bin/"${{ matrix.cmake_preset }}" ./daScriptTest.exe - ./daslang _dasroot_/dastest/dastest.das -- --color --test ../../tests || ./daslang _dasroot_/dastest/dastest.das -- --color --isolated-mode --timeout 1200 --test ../../tests + ./daslang _dasroot_/dastest/dastest.das -- --color --test ../../tests || ./daslang _dasroot_/dastest/dastest.das -- --color --isolated-mode --timeout 3600 --test ../../tests ;; windows*) cd bin/"${{ matrix.cmake_preset }}" [ "${{ env.das_llvm_disabled }}" = "ON" ] || ./daScriptTest.exe -jit ./daScriptTest.exe - [ "${{ env.das_llvm_disabled }}" = "ON" ] || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --test ../../tests || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --isolated-mode --timeout 1200 --test ../../tests - ./daslang _dasroot_/dastest/dastest.das -- --color --test ../../tests || ./daslang _dasroot_/dastest/dastest.das -- --color --isolated-mode --timeout 1200 --test ../../tests + [ "${{ env.das_llvm_disabled }}" = "ON" ] || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --test ../../tests || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --isolated-mode --timeout 3600 --test ../../tests + ./daslang _dasroot_/dastest/dastest.das -- --color --test ../../tests || ./daslang _dasroot_/dastest/dastest.das -- --color --isolated-mode --timeout 3600 --test ../../tests ;; *) cd bin [ "${{ env.das_llvm_disabled }}" = "ON" ] || ./daScriptTest -jit ./daScriptTest - [ "${{ env.das_llvm_disabled }}" = "ON" ] || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --test ../tests || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --isolated-mode --timeout 1200 --test ../tests - ./daslang _dasroot_/dastest/dastest.das -- --color --test ../tests || ./daslang _dasroot_/dastest/dastest.das -- --color --isolated-mode --timeout 1200 --test ../tests + [ "${{ env.das_llvm_disabled }}" = "ON" ] || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --test ../tests || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --isolated-mode --timeout 3600 --test ../tests + ./daslang _dasroot_/dastest/dastest.das -- --color --test ../tests || ./daslang _dasroot_/dastest/dastest.das -- --color --isolated-mode --timeout 3600 --test ../tests ;; esac - name: "Install binaries" diff --git a/.gitmodules b/.gitmodules index 34223b7bc2..546f6f4a7d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,21 +4,12 @@ [submodule "modules/dasImgui"] path = modules/dasImgui url = https://github.com/borisbat/dasImgui.git -[submodule "modules/dasBGFX"] - path = modules/dasBGFX - url = https://github.com/borisbat/dasBGFX.git -[submodule "modules/dasXbyak"] - path = modules/dasXbyak - url = https://github.com/borisbat/dasXbyak.git [submodule "modules/dasMinfft"] path = modules/dasMinfft url = https://github.com/imp5imp5/dasMinfft.git [submodule "modules/dasHV"] path = modules/dasHV url = https://github.com/borisbat/dasHV.git -[submodule "modules/dasSFML"] - path = modules/dasSFML - url = https://github.com/borisbat/dasSFML.git [submodule "modules/dasQuirrel"] path = modules/dasQuirrel url = https://github.com/borisbat/dasQuirrel.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c2b74ec03..4e5e9e31a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,15 +16,12 @@ option(DAS_QUIRREL_DISABLED "Disable dasQuirrel (quirrel bindings)" ON) option(DAS_HV_DISABLED "Disable dasHV (websokets,http server and client)" ON) option(DAS_GLFW_DISABLED "Disable dasGLFW (GLFW window for graphics apps)" OFF) option(DAS_IMGUI_DISABLED "Disable dasIMGUI (IMGUI, IMNODES, IMGUI-NODE-EDITOR gui libraries)" ON) -option(DAS_BGFX_DISABLED "Disable dasBGFX (BGFX graphics API)" ON) -option(DAS_XBYAK_DISABLED "Disable dasXbyak (XBYAK and ZYDIS, x86 assembly, jit)" ON) option(DAS_MINFFT_DISABLED "Disable dasMinfft (Minimal FFT library)" ON) option(DAS_AUDIO_DISABLED "Disable dasAudio (Miniaudio sound library)" ON) option(DAS_OPENAI_DISABLED "Disable dasOpenAI (OpenAI site API)" ON) option(DAS_STDDLG_DISABLED "Disable dasStdDlg (File new,open,save etc dialogs)" OFF) option(DAS_STBIMAGE_DISABLED "Disable dasStbImage (StbImage bindings, image loading and saving)" OFF) option(DAS_STBTRUETYPE_DISABLED "Disable dasStbTrueType (StbTrueType bindings, ttf rasterization)" OFF) -option(DAS_SFML_DISABLED "Disable dasSFML (SFML multimedia library)" ON) option(DAS_PUGIXML_DISABLED "Disable dasPUGIXML (xml parsing library)" ON) option(DAS_SQLITE_DISABLED "Disable dasSQLITE (sqlite3 library)" ON) option(DAS_TELEGRAM_DISABLED "Disable dasTelegram (Telegram API bindings)" ON) diff --git a/daslib/_aot_generated/dasAotStub_export_constructor.das.cpp b/daslib/_aot_generated/dasAotStub_export_constructor.das.cpp deleted file mode 100644 index ad416a8951..0000000000 --- a/daslib/_aot_generated/dasAotStub_export_constructor.das.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#include "daScript/misc/platform.h" - -#include "daScript/simulate/simulate.h" -#include "daScript/simulate/aot.h" -#include "daScript/simulate/aot_library.h" - - // require builtin - // require rtti -#include "daScript/simulate/aot_builtin_rtti.h" -#include "daScript/ast/ast.h" -#include "daScript/ast/ast_handle.h" - // require strings -#include "daScript/simulate/aot_builtin_string.h" - // require ast -#include "daScript/ast/ast.h" -#include "daScript/simulate/aot_builtin_ast.h" -#include "daScript/ast/ast_generate.h" - // require math -#include "daScript/simulate/aot_builtin_math.h" - // require strings_boost - // require ast_boost - // require templates - // require contracts - // require array_boost - // require algorithm - // require templates_boost - // require export_constructor - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4100) // unreferenced formal parameter -#pragma warning(disable:4189) // local variable is initialized but not referenced -#pragma warning(disable:4244) // conversion from 'int32_t' to 'float', possible loss of data -#pragma warning(disable:4114) // same qualifier more than once -#pragma warning(disable:4623) // default constructor was implicitly defined as deleted -#pragma warning(disable:4946) // reinterpret_cast used between related classes -#pragma warning(disable:4269) // 'const' automatic data initialized with compiler generated default constructor produces unreliable results -#pragma warning(disable:4555) // result of expression not used -#endif -#if defined(__EDG__) -#pragma diag_suppress 826 -#elif defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wwrite-strings" -#pragma GCC diagnostic ignored "-Wreturn-local-addr" -#pragma GCC diagnostic ignored "-Wignored-qualifiers" -#pragma GCC diagnostic ignored "-Wsign-compare" -#pragma GCC diagnostic ignored "-Wsubobject-linkage" -#endif -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" -#pragma clang diagnostic ignored "-Wwritable-strings" -#pragma clang diagnostic ignored "-Wunused-variable" -#pragma clang diagnostic ignored "-Wunused-but-set-variable" -#pragma clang diagnostic ignored "-Wunsequenced" -#pragma clang diagnostic ignored "-Wunused-function" -#endif - -namespace das { -namespace _anon_12727810018246099894 { - -namespace export_constructor { struct ExportConstructor; }; -namespace ast { struct AstFunctionAnnotation; }; -namespace ast { struct AstBlockAnnotation; }; -namespace ast { struct AstStructureAnnotation; }; -namespace ast { struct AstPassMacro; }; -namespace ast { struct AstVariantMacro; }; -namespace ast { struct AstForLoopMacro; }; -namespace ast { struct AstCaptureMacro; }; -namespace ast { struct AstTypeMacro; }; -namespace ast { struct AstSimulateMacro; }; -namespace ast { struct AstReaderMacro; }; -namespace ast { struct AstCommentReader; }; -namespace ast { struct AstCallMacro; }; -namespace ast { struct AstTypeInfoMacro; }; -namespace ast { struct AstEnumerationAnnotation; }; -namespace ast { struct AstVisitor; }; -namespace ast_boost { struct MacroMacro; }; -namespace ast_boost { struct TagFunctionAnnotation; }; -namespace ast_boost { struct TagStructureAnnotation; }; -namespace ast_boost { struct SetupAnyAnnotation; }; -namespace ast_boost { struct SetupFunctionAnnotation; }; -namespace ast_boost { struct SetupBlockAnnotation; }; -namespace ast_boost { struct SetupStructureAnnotation; }; -namespace ast_boost { struct SetupEnumerationAnnotation; }; -namespace ast_boost { struct SetupContractAnnotation; }; -namespace ast_boost { struct SetupReaderMacro; }; -namespace ast_boost { struct SetupCommentReader; }; -namespace ast_boost { struct SetupVariantMacro; }; -namespace ast_boost { struct SetupForLoopMacro; }; -namespace ast_boost { struct SetupCaptureMacro; }; -namespace ast_boost { struct SetupTypeMacro; }; -namespace ast_boost { struct SetupSimulateMacro; }; -namespace ast_boost { struct SetupCallMacro; }; -namespace ast_boost { struct SetupTypeInfoMacro; }; -namespace ast_boost { struct SetupInferMacro; }; -namespace ast_boost { struct SetupDirtyInferMacro; }; -namespace ast_boost { struct SetupLintMacro; }; -namespace ast_boost { struct SetupGlobalLintMacro; }; -namespace ast_boost { struct SetupOptimizationMacro; }; -namespace ast_boost { struct TagFunctionMacro; }; -namespace ast_boost { struct BetterRttiVisitor; }; -namespace templates { struct DecltypeMacro; }; -namespace templates { struct DecltypeNoRefMacro; }; -namespace templates { struct TemplateMacro; }; -namespace contracts { struct IsAnyType; }; -namespace contracts { struct IsAnyArrayMacro; }; -namespace contracts { struct IsAnyEnumMacro; }; -namespace contracts { struct IsAnyBitfieldMacro; }; -namespace contracts { struct IsAnyVectorType; }; -namespace contracts { struct IsAnyStructMacro; }; -namespace contracts { struct IsAnyNumericMacro; }; -namespace contracts { struct IsAnyWorkhorse; }; -namespace contracts { struct IsAnyWorkhorseNonPtrMacro; }; -namespace contracts { struct IsAnyTupleNonPtrMacro; }; -namespace contracts { struct IsAnyVariantNonPtrMacro; }; -namespace contracts { struct IsAnyFunctionNonPtrMacro; }; -namespace contracts { struct IsAnyLambdaMacro; }; -namespace contracts { struct IsRefMacro; }; -namespace contracts { struct IsPointer; }; -namespace contracts { struct IsClass; }; -namespace contracts { struct IsValueHandle; }; -namespace templates_boost { struct Template; }; -namespace templates_boost { struct TemplateVisitor; }; -namespace templates_boost { struct RemoveDerefVisitor; }; -namespace templates_boost { struct QRulesVisitor; }; -namespace templates_boost { struct AstQCallMacro; }; -namespace templates_boost { struct QMacro; }; -namespace templates_boost { struct QBlockMacro; }; -namespace templates_boost { struct QBlockToArrayMacro; }; -namespace templates_boost { struct QBlockExprMacro; }; -namespace templates_boost { struct QTypeMacro; }; -namespace templates_boost { struct AstQNamedMacro; }; -namespace templates_boost { struct AstQFunctionMacro; }; -namespace templates_boost { struct AstQVariableMacro; }; -namespace templates_boost { struct AstQNamedClassMacro; }; -namespace templates_boost { struct AstQMethodMacro; }; -// unused enumeration CompilationError -// unused enumeration ConstMatters -// unused enumeration RefMatters -// unused enumeration TemporaryMatters -// unused enumeration Type -// unused enumeration ConversionResult -// unused enumeration CaptureMode -// unused enumeration SideEffects -// unused structure AstFunctionAnnotation -// unused structure AstBlockAnnotation -namespace ast { - -struct AstStructureAnnotation { - void * __rtti; - Func DAS_COMMENT((void,ast::AstStructureAnnotation)) __finalize; - Func DAS_COMMENT((bool,ast::AstStructureAnnotation,smart_ptr_raw,ModuleGroup,AnnotationArgumentList const ,das::string)) apply; - Func DAS_COMMENT((bool,ast::AstStructureAnnotation,smart_ptr_raw,ModuleGroup,AnnotationArgumentList const ,das::string)) finish; - Func DAS_COMMENT((bool,ast::AstStructureAnnotation,smart_ptr_raw,ModuleGroup,AnnotationArgumentList const ,das::string,bool &)) patch; - Func DAS_COMMENT((void,ast::AstStructureAnnotation,smart_ptr_raw,smart_ptr_raw)) complete; - Func DAS_COMMENT((void,ast::AstStructureAnnotation,smart_ptr_raw,AnnotationArgumentList const ,StringBuilderWriter)) aotPrefix; - Func DAS_COMMENT((void,ast::AstStructureAnnotation,smart_ptr_raw,AnnotationArgumentList const ,StringBuilderWriter)) aotBody; - Func DAS_COMMENT((void,ast::AstStructureAnnotation,smart_ptr_raw,AnnotationArgumentList const ,StringBuilderWriter)) aotSuffix; -}; -} -// unused structure AstPassMacro -// unused structure AstVariantMacro -// unused structure AstForLoopMacro -// unused structure AstCaptureMacro -// unused structure AstTypeMacro -// unused structure AstSimulateMacro -// unused structure AstReaderMacro -// unused structure AstCommentReader -// unused structure AstCallMacro -// unused structure AstTypeInfoMacro -// unused structure AstEnumerationAnnotation -// unused structure AstVisitor -// unused structure MacroMacro -// unused structure TagFunctionAnnotation -// unused structure TagStructureAnnotation -// unused structure SetupAnyAnnotation -// unused structure SetupFunctionAnnotation -// unused structure SetupBlockAnnotation -// unused structure SetupStructureAnnotation -// unused structure SetupEnumerationAnnotation -// unused structure SetupContractAnnotation -// unused structure SetupReaderMacro -// unused structure SetupCommentReader -// unused structure SetupVariantMacro -// unused structure SetupForLoopMacro -// unused structure SetupCaptureMacro -// unused structure SetupTypeMacro -// unused structure SetupSimulateMacro -// unused structure SetupCallMacro -// unused structure SetupTypeInfoMacro -// unused structure SetupInferMacro -// unused structure SetupDirtyInferMacro -// unused structure SetupLintMacro -// unused structure SetupGlobalLintMacro -// unused structure SetupOptimizationMacro -// unused structure TagFunctionMacro -// unused structure BetterRttiVisitor -// unused structure DecltypeMacro -// unused structure DecltypeNoRefMacro -// unused structure TemplateMacro -// unused structure IsAnyType -// unused structure IsAnyArrayMacro -// unused structure IsAnyEnumMacro -// unused structure IsAnyBitfieldMacro -// unused structure IsAnyVectorType -// unused structure IsAnyStructMacro -// unused structure IsAnyNumericMacro -// unused structure IsAnyWorkhorse -// unused structure IsAnyWorkhorseNonPtrMacro -// unused structure IsAnyTupleNonPtrMacro -// unused structure IsAnyVariantNonPtrMacro -// unused structure IsAnyFunctionNonPtrMacro -// unused structure IsAnyLambdaMacro -// unused structure IsRefMacro -// unused structure IsPointer -// unused structure IsClass -// unused structure IsValueHandle -// unused structure Template -// unused structure TemplateVisitor -// unused structure RemoveDerefVisitor -// unused structure QRulesVisitor -// unused structure AstQCallMacro -// unused structure QMacro -// unused structure QBlockMacro -// unused structure QBlockToArrayMacro -// unused structure QBlockExprMacro -// unused structure QTypeMacro -// unused structure AstQNamedMacro -// unused structure AstQFunctionMacro -// unused structure AstQVariableMacro -// unused structure AstQNamedClassMacro -// unused structure AstQMethodMacro -namespace export_constructor { - -struct ExportConstructor { - void * __rtti; - Func DAS_COMMENT((void,ast::AstStructureAnnotation)) __finalize; - Func DAS_COMMENT((bool,ast::AstStructureAnnotation,smart_ptr_raw,ModuleGroup,AnnotationArgumentList const ,das::string)) apply; - Func DAS_COMMENT((bool,ast::AstStructureAnnotation,smart_ptr_raw,ModuleGroup,AnnotationArgumentList const ,das::string)) finish; - Func DAS_COMMENT((bool,ast::AstStructureAnnotation,smart_ptr_raw,ModuleGroup,AnnotationArgumentList const ,das::string,bool &)) patch; - Func DAS_COMMENT((void,ast::AstStructureAnnotation,smart_ptr_raw,smart_ptr_raw)) complete; - Func DAS_COMMENT((void,ast::AstStructureAnnotation,smart_ptr_raw,AnnotationArgumentList const ,StringBuilderWriter)) aotPrefix; - Func DAS_COMMENT((void,ast::AstStructureAnnotation,smart_ptr_raw,AnnotationArgumentList const ,StringBuilderWriter)) aotBody; - Func DAS_COMMENT((void,ast::AstStructureAnnotation,smart_ptr_raw,AnnotationArgumentList const ,StringBuilderWriter)) aotSuffix; -}; -} - - -static void resolveTypeInfoAnnotations() -{ - vector annotations = {}; - for (auto& ann : annotations) { - ann.resolveAnnotation(); - } -} - - -inline void _FuncbuiltinTickpushTick10769833213962245646_e7238a72d1bb3ef6 ( Context * __context__, TArray & __Arr_rename_at_181_0, ast::AstStructureAnnotation * __value_rename_at_181_1 ); -inline StructInfo const * _FuncrttiTickclass_infoTick15801393167907430156_71b82f1696873196 ( Context * __context__, export_constructor::ExportConstructor const & __cl_rename_at_116_2 ); - -void __init_script ( Context * __context__, bool __init_shared ) -{ -} - -inline void _FuncbuiltinTickpushTick10769833213962245646_e7238a72d1bb3ef6 ( Context * __context__, TArray & __Arr_rename_at_181_0, ast::AstStructureAnnotation * __value_rename_at_181_1 ) -{ - das_copy(__Arr_rename_at_181_0(builtin_array_push_back(das_arg>::pass(__Arr_rename_at_181_0),8,__context__,((LineInfoArg *)(&LineInfo::g_LineInfoNULL))),__context__),__value_rename_at_181_1); -} - -inline StructInfo const * _FuncrttiTickclass_infoTick15801393167907430156_71b82f1696873196 ( Context * __context__, export_constructor::ExportConstructor const & __cl_rename_at_116_2 ) -{ - return das_auto_cast::cast(das_cast::cast(((das_deref(__context__,das_cast::cast(__cl_rename_at_116_2.__rtti))).getStructType()))); -} - -static void registerAotFunctions ( AotLibrary & aotLib ) { - aotLib[0xbbacadb2428c67e1] = +[](Context & ctx) -> SimNode* { - return ctx.code->makeNode>(); - }; - aotLib[0xb61ba7712162b523] = +[](Context & ctx) -> SimNode* { - return ctx.code->makeNode>(); - }; - resolveTypeInfoAnnotations(); -} - -} // namespace _anon_12727810018246099894 -AotListBase impl_aot_export_constructor(_anon_12727810018246099894::registerAotFunctions); -} // namespace das - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -#if defined(__EDG__) -#pragma diag_default 826 -#elif defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif -#if defined(__clang__) -#pragma clang diagnostic pop -#endif diff --git a/daslib/export_constructor.das b/daslib/export_constructor.das deleted file mode 100644 index e94b76d72f..0000000000 --- a/daslib/export_constructor.das +++ /dev/null @@ -1,34 +0,0 @@ -options gen2 -options indenting = 4 -options no_unused_block_arguments = false -options no_unused_function_arguments = false -options strict_smart_pointers = true - -module export_constructor shared private - -//! Auto-export default constructor annotation. -//! -//! Annotate a struct or class with ``[export_constructor]`` to automatically generate -//! and export a ``make`StructName`` function that creates a new instance. - -require ast -require rtti -require daslib/ast_boost -require daslib/templates_boost - -[structure_macro(name="export_constructor")] -class ExportConstructor : AstStructureAnnotation { - //! implements 'export_constructor' macro, adds function make`{StructureName} which makes a new instance of a class or structure - def override apply(var st : StructurePtr; var group : ModuleGroup; args : AnnotationArgumentList; var errors : das_string) : bool { - if (args |> length != 0) { - errors := "expecting [export_constructor] to have no arguments" - return false - } - var inscope qfn <- qmacro_function("make`{st.name}") { - return new <$t(st)>() - } - qfn.flags |= FunctionFlags.exports - add_function(st._module, qfn) - return true - } -} diff --git a/doc/reflections/das2rst.das b/doc/reflections/das2rst.das index 178732e457..40946259eb 100644 --- a/doc/reflections/das2rst.das +++ b/doc/reflections/das2rst.das @@ -50,7 +50,6 @@ require daslib/decs_boost require daslib/utf8_utils require daslib/coroutines require daslib/interfaces -require daslib/export_constructor require daslib/faker require daslib/fuzzer require daslib/match @@ -709,13 +708,6 @@ def document_module_interfaces(root : string) { document("Interfaces", mod, "interfaces.rst", groups) } -def document_module_export_constructor(root : string) { - var mod = find_module("export_constructor") - var groups <- array( - ) - document("Export constructor", mod, "export_constructor.rst", groups) -} - def document_module_faker(root : string) { var mod = find_module("faker") var groups <- array( @@ -1098,7 +1090,6 @@ def main { document_module_defer(root) document_module_dynamic_cast_rtti(root) document_module_enum_trait(root) - document_module_export_constructor(root) document_module_faker(root) document_module_flat_hash_table(root) document_module_functional(root) diff --git a/doc/reflections/gen_module_examples.py b/doc/reflections/gen_module_examples.py index f3d0d82144..c70fe350bc 100644 --- a/doc/reflections/gen_module_examples.py +++ b/doc/reflections/gen_module_examples.py @@ -938,13 +938,6 @@ def main() { "require daslib/dynamic_cast_rtti", ) -reg("export_constructor", - """The EXPORT_CONSTRUCTOR module provides the ``[export_constructor]`` annotation -for struct types. Annotated structs automatically generate an exported -constructor function that can be called from other modules or from C++ code.""", - "require daslib/export_constructor", -) - reg("faker", """Random test-data generator. diff --git a/doc/source/reference/tutorials.rst b/doc/source/reference/tutorials.rst index 847fa1f858..e21c878676 100644 --- a/doc/source/reference/tutorials.rst +++ b/doc/source/reference/tutorials.rst @@ -74,6 +74,7 @@ introduced in earlier tutorials. tutorials/44_compile_and_run.rst tutorials/45_debug_agents.rst tutorials/46_apply_in_context.rst + tutorials/47_data_walker.rst .. _tutorials_integration_c: diff --git a/doc/source/reference/tutorials/46_apply_in_context.rst b/doc/source/reference/tutorials/46_apply_in_context.rst index cb50907068..06f6dfaf51 100644 --- a/doc/source/reference/tutorials/46_apply_in_context.rst +++ b/doc/source/reference/tutorials/46_apply_in_context.rst @@ -241,3 +241,5 @@ Quick reference :ref:`Contexts ` — language reference for context semantics. Previous tutorial: :ref:`tutorial_debug_agents` + + Next tutorial: :ref:`tutorial_data_walker` diff --git a/doc/source/reference/tutorials/47_data_walker.rst b/doc/source/reference/tutorials/47_data_walker.rst new file mode 100644 index 0000000000..2c3eced358 --- /dev/null +++ b/doc/source/reference/tutorials/47_data_walker.rst @@ -0,0 +1,428 @@ +.. _tutorial_data_walker: + +======================================== +Data Walking with DapiDataWalker +======================================== + +.. index:: + single: Tutorial; DapiDataWalker + single: Tutorial; Data Walking + single: Tutorial; JSON Serializer + single: Tutorial; Runtime Introspection + +This tutorial covers ``DapiDataWalker`` — a visitor-pattern class for +inspecting and transforming daScript values at runtime. You subclass +it, override callbacks for the types you care about, and walk any data +through RTTI type information. + +Prerequisites: basic daScript knowledge (structs, arrays, tables, +enumerations, bitfields). + +.. code-block:: das + + options gen2 + options rtti + + require rtti + require debugapi + require daslib/strings_boost + + +Minimal walker — scalar types +============================== + +A ``DapiDataWalker`` subclass overrides only the callbacks you need. +All 87 methods default to no-ops, so a minimal walker that prints +integers, floats, strings, and booleans is very small: + +.. code-block:: das + + class ScalarPrinter : DapiDataWalker { + def override Int(var value : int&) : void { + print(" int: {value}\n") + } + def override Float(var value : float&) : void { + print(" float: {value}\n") + } + def override String(var value : string&) : void { + print(" string: \"{value}\"\n") + } + def override Bool(var value : bool&) : void { + print(" bool: {value}\n") + } + } + +To walk a value, create the walker, wrap it with ``make_data_walker``, +then call ``walk_data`` with a pointer and ``TypeInfo``: + +.. code-block:: das + + var walker = new ScalarPrinter() + var inscope adapter <- make_data_walker(walker) + + var x = 42 + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + +``typeinfo rtti_typeinfo(variable)`` is a compile-time intrinsic that +returns the RTTI ``TypeInfo`` for any variable or type expression. + + +Walking structures +=================== + +The walker calls ``beforeStructure``/``afterStructure`` around the +whole struct, and ``beforeStructureField``/``afterStructureField`` +around each field. ``StructInfo.name`` gives the struct type name, +``VarInfo.name`` gives the field name: + +.. code-block:: das + + struct Vec3 { + x : float + y : float + z : float + } + + struct Player { + name : string + health : int + pos : Vec3 + } + + class StructPrinter : DapiDataWalker { + indent : int = 0 + + def pad() { + for (_ in range(indent)) { + print(" ") + } + } + + def override beforeStructure(ps : void?; si : StructInfo) : void { + print("{si.name} \{\n") + indent++ + } + + def override afterStructure(ps : void?; si : StructInfo) : void { + indent-- + self->pad() + print("\}\n") + } + + def override beforeStructureField(ps : void?; si : StructInfo; + pv : void?; vi : VarInfo; last : bool) : void { + self->pad() + print("{vi.name} = ") + } + + // ... plus Int, Float, String overrides + } + +Walking a ``Player`` value produces indented output showing nested +structures: + +.. code-block:: text + + Player { + name = "Alice" + health = 100 + pos = Vec3 { + x = 1 + y = 2.5 + z = -3 + } + } + + +Arrays and tables +================== + +Dynamic arrays trigger ``beforeArrayData``/``afterArrayData`` plus +per-element callbacks. Tables trigger ``beforeTable``/``afterTable`` +with key/value pairs: + +.. code-block:: das + + class ContainerPrinter : DapiDataWalker { + indent : int = 0 + + def override beforeArrayData(ps : void?; stride : uint; + count : uint; ti : TypeInfo) : void { + self->pad() + print("array[{int(count)}] = [\n") + indent++ + } + + def override beforeArrayElement(ps : void?; ti : TypeInfo; + pe : void?; index : uint; last : bool) : void { + self->pad() + print("[{int(index)}] = ") + } + + def override beforeTable(pa : DapiTable; ti : TypeInfo) : void { + self->pad() + print("table[{int(pa.size)}] = \{\n") + indent++ + } + + // ... afterTable, beforeTableKey, afterTableKey, etc. + } + +Note that ``count``, ``index``, and ``pa.size`` are ``uint`` values +which print as hexadecimal by default — cast to ``int`` for decimal +output. + + +Tuples and variants +==================== + +Tuples walk each element by index. Variants walk only the active +alternative. ``beforeTupleEntry`` receives the element index, +``beforeVariant`` receives the ``TypeInfo`` of the active case: + +.. code-block:: das + + typedef Result = variant + + class TupleVariantPrinter : DapiDataWalker { + def override beforeTupleEntry(ps : void?; ti : TypeInfo; + pv : void?; idx : int; last : bool) : void { + self->pad() + print("_{idx} = ") + } + + def override beforeVariant(ps : void?; ti : TypeInfo) : void { + self->pad() + print("variant = ") + } + + // ... plus scalar overrides for Int, String, etc. + } + +Walking ``Result(ok = 42)`` prints ``variant = 42``. +Walking ``Result(err = "not found")`` prints ``variant = "not found"``. + + +Enumerations and bitfields +=========================== + +Enumerations trigger ``WalkEnumeration`` with an ``EnumInfo`` +containing value names. Bitfields trigger ``Bitfield`` with a +``TypeInfo`` containing field names: + +.. code-block:: das + + class EnumBitfieldPrinter : DapiDataWalker { + def override WalkEnumeration(var value : int&; ei : EnumInfo) : void { + for (i in range(ei.count)) { + unsafe { + if (int(ei.fields[i].value) == value) { + print(" enum {ei.name}.{ei.fields[i].name} ({value})\n") + return + } + } + } + print(" enum {ei.name} = {value}\n") + } + + def override Bitfield(var value : uint&; ti : TypeInfo) : void { + print(" bitfield = {value} [") + var first = true + for (i in range(ti.argCount)) { + if ((value & (1u << uint(i))) != 0u) { + if (!first) { + print(", ") + } + first = false + unsafe { + print("{ti.argNames[i]}") + } + } + } + print("]\n") + } + } + + +JSON serializer — putting it all together +=========================================== + +A practical walker that serializes any daScript value to JSON. +This combines structure, array, table, tuple, and scalar callbacks +into one coherent class. The walker writes to a ``StringBuilderWriter`` +for efficiency — no intermediate string concatenation: + +.. code-block:: das + + class JsonWalker : DapiDataWalker { + @do_not_delete writer : StringBuilderWriter? + indent : int = 0 + needComma : array + + // --- structures --- + def override beforeStructure(ps : void?; si : StructInfo) : void { + *writer |> write("\{") + indent++ + pushComma() + } + + def override beforeStructureField(ps : void?; si : StructInfo; + pv : void?; vi : VarInfo; last : bool) : void { + comma() + nl() + *writer |> write("\"") + *writer |> write(vi.name) + *writer |> write("\": ") + } + + // --- arrays --- + def override beforeArrayData(ps : void?; stride : uint; + count : uint; ti : TypeInfo) : void { + *writer |> write("[") + indent++ + pushComma() + } + + // ... tables, tuples, scalars + } + +The ``to_json`` helper wraps the walk in ``build_string``: + +.. code-block:: das + + def to_json(var value; tinfo : TypeInfo) : string { + var walker = new JsonWalker() + var inscope adapter <- make_data_walker(walker) + let res = build_string() $(var writer) { + unsafe { + walker.writer = addr(writer) + adapter |> walk_data(addr(value), tinfo) + } + } + unsafe { delete walker } + return res + } + +Walking an ``Inventory`` struct produces well-formatted JSON: + +.. code-block:: json + + { + "owner": "Alice", + "gold": 250, + "items": [ + { + "name": "Sword", + "weight": 3.5 + }, + { + "name": "Shield", + "weight": 5.2 + }, + { + "name": "Potion", + "weight": 0.5 + } + ], + "flags": { + "is_merchant": true, + "is_hostile": false + } + } + + +Filtering with canVisit +========================= + +All ``canVisit*`` methods return ``true`` by default. Override them +to return ``false`` and the walker skips that subtree entirely: + +.. code-block:: das + + class FilteringWalker : DapiDataWalker { + skipStructName : string + + def override canVisitStructure(ps : void?; si : StructInfo) : bool { + if (si.name == skipStructName) { + print("\n") + return false + } + return true + } + + // ... beforeStructure, afterStructure, field and scalar overrides + } + +Setting ``skipStructName = "Secret"`` skips the ``Secret`` struct +entirely, including all its fields: + +.. code-block:: text + + PublicRecord { + title = "Performance Review" + secret = + score = 95 + } + + +Mutating data in-place +======================== + +Scalar callbacks receive ``var value : T&`` — a mutable reference. +This means the walker can modify data during traversal: + +.. code-block:: das + + class FloatClamper : DapiDataWalker { + lo : float = 0.0 + hi : float = 1.0 + + def override Float(var value : float&) : void { + if (value < lo) { + value = lo + } + if (value > hi) { + value = hi + } + } + } + +Walking a ``Particle`` with out-of-range floats clamps them to +``[0..1]``: + +.. code-block:: text + + Before clamping: x=-0.5 y=0.3 z=1.7 alpha=0.8 + After clamping: x=0 y=0.3 z=1 alpha=0.8 + + +Quick reference +================ + +================================================= ==================================================== +``DapiDataWalker`` Base class — subclass and override callbacks +``make_data_walker(walker)`` Wrap class instance into ``smart_ptr`` +``walk_data(adapter, ptr, typeinfo)`` Walk data at ``ptr`` using RTTI ``TypeInfo`` +``typeinfo rtti_typeinfo(var)`` Get ``TypeInfo`` for any variable (compile-time) +``unsafe { addr(var) }`` Get ``void?`` pointer to a variable +``canVisit*(...)`` Return ``false`` to skip a subtree +``beforeX(...) / afterX(...)`` Container enter/exit callbacks +``Int, Float, String, Bool, ...`` Scalar value callbacks (mutable references) +``WalkEnumeration(value, EnumInfo)`` Enumeration callback with value metadata +``Bitfield(value, TypeInfo)`` Bitfield callback with field name metadata +================================================= ==================================================== + + +.. seealso:: + + Full source: :download:`tutorials/language/47_data_walker.das <../../../../tutorials/language/47_data_walker.das>` + + :ref:`stdlib_debugapi` — ``DapiDataWalker`` class reference and + ``make_data_walker`` / ``walk_data`` functions. + + :ref:`stdlib_rtti` — RTTI types (``TypeInfo``, ``StructInfo``, + ``VarInfo``, ``EnumInfo``). + + Previous tutorial: :ref:`tutorial_apply_in_context` diff --git a/doc/source/reference/tutorials/macros/06_structure_macro.rst b/doc/source/reference/tutorials/macros/06_structure_macro.rst index 72af00c423..1e4ffe0fab 100644 --- a/doc/source/reference/tutorials/macros/06_structure_macro.rst +++ b/doc/source/reference/tutorials/macros/06_structure_macro.rst @@ -496,7 +496,6 @@ Key takeaways Standard library examples: ``daslib/interfaces.das`` (``apply`` + ``finish``), - ``daslib/export_constructor.das`` (``apply`` only), ``daslib/decs_boost.das`` (``apply`` with field iteration) Language reference: :ref:`Macros ` — full macro system documentation diff --git a/doc/source/stdlib/debugapi.rst b/doc/source/stdlib/debugapi.rst index a05fcb7fe1..a5ffe5b124 100644 --- a/doc/source/stdlib/debugapi.rst +++ b/doc/source/stdlib/debugapi.rst @@ -12,7 +12,7 @@ and communicating with persistent debug agents that live in their own forked con It supports cross-context function invocation, agent method calls, log interception, data and stack walking, instrumentation, and breakpoint management. -See :ref:`tutorial_debug_agents` for a hands-on tutorial. +See :ref:`tutorial_debug_agents` and :ref:`tutorial_data_walker` for hands-on tutorials. All functions and symbols are in "debugapi" module, use require to get access to it. diff --git a/doc/source/stdlib/detail/export_constructor.rst b/doc/source/stdlib/detail/export_constructor.rst deleted file mode 100644 index 1fea6052f8..0000000000 --- a/doc/source/stdlib/detail/export_constructor.rst +++ /dev/null @@ -1,4 +0,0 @@ -.. |detail/class-export_constructor-ExportConstructor| replace:: to be documented in |detail/class-export_constructor-ExportConstructor|.rst - -.. |detail/method-export_constructor-ExportConstructor.apply| replace:: to be documented in |detail/method-export_constructor-ExportConstructor.apply|.rst - diff --git a/doc/source/stdlib/export_constructor.rst b/doc/source/stdlib/export_constructor.rst deleted file mode 100644 index cc1e4e9be2..0000000000 --- a/doc/source/stdlib/export_constructor.rst +++ /dev/null @@ -1,33 +0,0 @@ - -.. _stdlib_export_constructor: - -================== -Export constructor -================== - -.. das:module:: export_constructor - -The EXPORT_CONSTRUCTOR module provides the ``[export_constructor]`` annotation -for struct types. Annotated structs automatically generate an exported -constructor function that can be called from other modules or from C++ code. - -All functions and symbols are in "export_constructor" module, use require to get access to it. - -.. code-block:: das - - require daslib/export_constructor - - - -++++++++++++++++ -Structure macros -++++++++++++++++ - -.. _handle-export_constructor-export_constructor: - -.. das:attribute:: export_constructor - -implements 'export_constructor' macro, adds function make`{StructureName} which makes a new instance of a class or structure - - - diff --git a/doc/source/stdlib/handmade/module-debugapi.rst b/doc/source/stdlib/handmade/module-debugapi.rst index e481e5449c..a98e7a70ec 100644 --- a/doc/source/stdlib/handmade/module-debugapi.rst +++ b/doc/source/stdlib/handmade/module-debugapi.rst @@ -3,7 +3,7 @@ and communicating with persistent debug agents that live in their own forked con It supports cross-context function invocation, agent method calls, log interception, data and stack walking, instrumentation, and breakpoint management. -See :ref:`tutorial_debug_agents` for a hands-on tutorial. +See :ref:`tutorial_debug_agents` and :ref:`tutorial_data_walker` for hands-on tutorials. All functions and symbols are in "debugapi" module, use require to get access to it. diff --git a/doc/source/stdlib/handmade/module-export_constructor.rst b/doc/source/stdlib/handmade/module-export_constructor.rst deleted file mode 100644 index 3ccdf45ac0..0000000000 --- a/doc/source/stdlib/handmade/module-export_constructor.rst +++ /dev/null @@ -1,9 +0,0 @@ -The EXPORT_CONSTRUCTOR module provides the ``[export_constructor]`` annotation -for struct types. Annotated structs automatically generate an exported -constructor function that can be called from other modules or from C++ code. - -All functions and symbols are in "export_constructor" module, use require to get access to it. - -.. code-block:: das - - require daslib/export_constructor diff --git a/doc/source/stdlib/introduction.rst b/doc/source/stdlib/introduction.rst index e6c6e356f5..c128b8dbaa 100644 --- a/doc/source/stdlib/introduction.rst +++ b/doc/source/stdlib/introduction.rst @@ -117,7 +117,6 @@ Control flow macros * :doc:`assert_once ` — ``assert_once`` — assertion that fires only on first failure * :doc:`unroll ` — compile-time loop unrolling macro * :doc:`instance_function ` — ``[instance_function]`` annotation for struct method binding -* :doc:`export_constructor ` — auto-export default constructors for annotated structs * :doc:`array_boost ` — ``temp_array``, ``array_view``, and ``empty`` helpers * :doc:`heartbeat ` — periodic heartbeat callback injection diff --git a/doc/source/stdlib/sec_classes.rst b/doc/source/stdlib/sec_classes.rst index 4a085c68c2..9b47e73a19 100644 --- a/doc/source/stdlib/sec_classes.rst +++ b/doc/source/stdlib/sec_classes.rst @@ -11,7 +11,6 @@ constructor/method helpers. class_boost.rst instance_function.rst - export_constructor.rst interfaces.rst dynamic_cast_rtti.rst generic_return.rst diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000000..96b391ed36 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,69 @@ +# Examples + +Runnable daslang examples organized by topic. + +## Getting Started + +``` +daslang.exe examples/hello_world.das +``` + +| File | Description | +|------|-------------| +| `hello_world.das` | Minimal hello-world program | + +## debugapi/ — Debug Agent Examples + +Debug agents let you inspect and control program execution at runtime: +allocation tracking, breakpoints, instrumentation, and stack walking. + +All examples require `options debugger = true`. + +| File | Description | +|------|-------------| +| `allocation_tracking.das` | Heap allocation callbacks (`onAllocate`, `onReallocate`, `onFree`, `onAllocateString`, `onFreeString`) | +| `heartbeat.das` | Periodic callback injection via `daslib/heartbeat` — watchdog, progress reporting | +| `hw_breakpoint.das` | Hardware data breakpoints that fire when a memory address is written | +| `instrumentation.das` | Line-level and function-level instrumentation hooks for profiling and tracing | +| `stack_walker.das` | `DapiStackWalker` for call-stack inspection and diagnostic collection | + +## dasbind/ — Foreign Function Interface + +| File | Description | +|------|-------------| +| `dasbind_example.das` | Calling external C functions (Win32 API) via `[extern]` annotations | + +## pathTracer/ — Path Tracer Demo + +A toy path tracer implemented in daslang, with OpenGL visualization variants. +Requires the `stbimage` module and (for OpenGL variants) `dasGlfw` / `dasImgui`. + +| File | Description | +|------|-------------| +| `path_tracer.das` | Core path-tracing module (shared code) | +| `toy_path_tracer.das` | Console path tracer — renders to a `.bmp` file | +| `toy_pathtracer_opengl_basic.das` | Real-time path tracer with basic OpenGL display | +| `toy_path_tracer_opengl.das` | Real-time path tracer with progressive accumulation | +| `toy_path_tracer_opengl_hdr.das` | Real-time path tracer with HDR tonemapping | +| `toy_path_tracer_profile.das` | Path tracer performance benchmark | + +## profile/ — Performance Benchmarks + +A benchmark suite comparing daslang against C++ and other languages. +Built as a C++ executable that compiles and runs `.das` benchmark scripts. + +## uncategorized/ — Miscellaneous Examples + +Standalone examples that don't fit neatly into other categories. + +| File | Description | +|------|-------------| +| `base64_generators.das` | Base64 encoder built as a chain of composable generators (deliberately slow — demonstrates generator composition, not production encoding) | +| `shader_like_validation.das` | Shader-like mode demo — shows how `options shader_like` rejects heap-allocating constructs (arrays, lambdas, `new`) at simulation time | + +## test/ — Test Harness & Unit Tests + +The compiler/runtime test suite (`daScriptTest`). Contains unit tests, +compilation failure tests, runtime error tests, optimization tests, and +module-specific test directories. This is a C++ test executable — not +standalone `.das` scripts. Will be reorganized later. diff --git a/examples/contDev/doc-main.das b/examples/contDev/doc-main.das deleted file mode 100644 index 7b25718670..0000000000 --- a/examples/contDev/doc-main.das +++ /dev/null @@ -1,44 +0,0 @@ -options gen2 -// options logNodes=true, logStack=true -// options logCpp=true, onlyFastAot=true - -require fio -require rtti - - -def getModuleDoc(modName : string) { - let pMod = rtti::get_module(modName) - if (pMod == null) { - print("module {modName} not found\n") - return - } - rtti::module_for_each_structure(pMod) <| $(info) { - print("struct {info.name}\n") - } - rtti::module_for_each_function(pMod) <| $(info) { - print("def {info.name}") - if ((info.flags & FUNCINFO_BUILTIN) == FUNCINFO_BUILTIN) { - print(" // {info.cppName=="" ? "WARNING: no CPP name" : info.cppName}") - } - print("\n") - } - rtti::module_for_each_generic(pMod) <| $(info) { - print("def {info.name} // generic\n") - } -} - -[export] -def main { - let args <- get_command_line_arguments() - let fn = args[1] - print("module documentatoin generator\n") - // getModuleDoc("$") // builtin - getModuleDoc("fio") - print("ok\n") - let main_time = stat(fn).mtime - while (stat(fn).mtime == main_time) { - sleep(1000u) - } - return true -} - diff --git a/examples/contDev/main.das b/examples/contDev/main.das deleted file mode 100644 index cbf299c12d..0000000000 --- a/examples/contDev/main.das +++ /dev/null @@ -1,332 +0,0 @@ -options gen2 -// options logNodes=true, logStack=true -require fio -require rtti -require strings - -let { - INDENT = " " -} - -def findArg(field, argName, argType) : AnnotationArgument const? const { - if (field.annotation_arguments != null) { - for (arg in deref(field.annotation_arguments)) { - if (string(arg.name) == argName) { - if (arg.basicType == argType) { - return unsafe(addr(arg)) - } else { - print("error: {field.name} {argName} argument must be {argType}\n") - } - } - } - } - return null -} - - -def cppTypeAttr(field) : string { - let arg = findArg(field, "cppType", Type.tString) - return arg != null ? string(arg.sValue) : "" -} - -def isBaseCoreAttr(field) { - let arg = findArg(field, "skipCpp", Type.tBool) - return arg != null -} - -def cppBaseTypeName(bt) { - if (bt == Type.tInt) { - return "int32_t" - } elif (bt == Type.tInt8) { - return "int8_t" - } elif (bt == Type.tInt16) { - return "int16_t" - } elif (bt == Type.tUInt8) { - return "uint8_t" - } elif (bt == Type.tUInt16) { - return "uint16_t" - } elif (bt == Type.tInt2) { - return "int2" - } elif (bt == Type.tInt3) { - return "int3" - } elif (bt == Type.tInt4) { - return "int4" - } elif (bt == Type.tUInt) { - return "uint32_t" - } elif (bt == Type.tFloat) { - return "float" - } elif (bt == Type.tFloat2) { - return "float2" - } elif (bt == Type.tFloat3) { - return "float3" - } elif (bt == Type.tFloat4) { - return "float4" - } elif (bt == Type.tString) { - return "string" - } elif (bt == Type.tPointer) { - return "void*" - } else { - return "/*undefined*/" - } -} - -def cppTypeDim(info) { - var res = "" - if (info.dimSize != 0u) { - for (index in range(int(info.dimSize))) { - let d = get_dim(info, index) - res += "[{d}]" - } - } - return res -} - -def cppTypeName(info : VarInfo) { - var res = cppTypeAttr(info) - if (res == "") { - res = info.isConst ? "const " : "" - if (info.basicType == Type.tHandle) { - res += string(info.annotation.name) - } elif (info.basicType == Type.tStructure) { - res += info.structType.name - } else { - res += cppBaseTypeName(info.basicType) - } - } - return res -} - -def dumpAnnotations(file : FILE const?; info) { - rtti::structure_for_each_annotation(info) <| $(ann, annArg) { - fprint(file, "// struct {info.name} annotation {ann.name}\n") - for (arg in annArg) { - fprint(file, "{INDENT}// {arg.name} = ") - if (arg.basicType == Type.tInt) { - fprint(file, "{arg.iValue}") - } elif (arg.basicType == Type.tFloat) { - fprint(file, "{arg.fValue}") - } elif (arg.basicType == Type.tBool) { - fprint(file, "{arg.bValue}") - } elif (arg.basicType == Type.tString) { - fprint(file, "{arg.sValue}") - } - fprint(file, "\n") - } - } -} - -def generateSquirrelBinding(file : FILE const?; info) { - if (info.name == "BaseCoreEvent") { - return - } - let argsN = "{info.name}::NUMBER_OF_FIELDS" - fprint(file, "{INDENT}\{\n") - fprint(file, "{INDENT}{INDENT}Sqrat::DerivedClass<{info.name}, ecs::Event> sqEvent(vm, \"{info.name}\");\n") - fprint(file, "{INDENT}{INDENT}sqEvent\n") - fprint(file, "{INDENT}{INDENT}{INDENT}.Ctor()\n") - fprint(file, "{INDENT}{INDENT}{INDENT}.Ctor()\n") - fprint(file, "{INDENT}{INDENT}{INDENT}.SquirrelFunc(\"_get\", das_evt_get, 2, \"xi\")\n") - fprint(file, "{INDENT}{INDENT}{INDENT}.SquirrelFunc(\"_in\", das_evt_in<{argsN}>, 2, \"xi\")\n") - fprint(file, "{INDENT}{INDENT}{INDENT}.GlobalFunc(\"len\", das_evt_len<{argsN}>)\n") - fprint(file, "{INDENT}{INDENT}{INDENT}.SquirrelFunc(\"_nexti\", das_evt_nexti<{argsN}>, 2, \"xi|o\")\n") - for (field in info) { - if (isBaseCoreAttr(field)) { - continue - } - fprint(file, "{INDENT}{INDENT}{INDENT}.Var(\"{field.name}\", &{info.name}::{field.name})\n") - } - // fprint(file,"{INDENT}{INDENT}.Var(\"data\", &ecs::SQEvent::data)\n") - fprint(file, "{INDENT}{INDENT};\n") - fprint(file, "{INDENT}{INDENT}eventsBinding.emplace_back(\"{info.name}\", Sqrat::Object(sqEvent.GetObject(), vm));\n") - fprint(file, "{INDENT}}\n\n") -} - - -def printArguments(file : FILE const?; info, prefix) { - var cArg = 0 - for (field in info) { - cArg++ - if (isBaseCoreAttr(field)) { - continue - } - fprint(file, "{INDENT}{INDENT}{INDENT}{field.name}(eastl::move({prefix}{field.name}))") - if (cArg != int(info.count)) { - fprint(file, ",\n") - } - } -} - -def generateCppEvent(file : FILE const?; info) { - if (info.name == "BaseCoreEvent") { - return - } - fprint(file, "class {info.name} final: public Event\n") - fprint(file, "\{\n") - fprint(file, "public:\n") - var argCount = 0 - for (field in info) { - if (!isBaseCoreAttr(field)) { - argCount++ - } - } - fprint(file, "{INDENT}enum \{NUMBER_OF_FIELDS = {int(argCount)}\};\n") - fprint(file, "{INDENT}{info.name}(") - var first = true - for (field in info) { - if (isBaseCoreAttr(field)) { - continue - } - if (first) { - first = false - } else { - fprint(file, ", ") - } - fprint(file, "{cppTypeName(field)} &&_{field.name}") - } - fprint(file, ")\n{INDENT}{INDENT}: Event(ECS_HASH(\"{info.name}\"))") - if (argCount != 0) { - fprint(file, ",\n") - printArguments(file, info, "_") - fprint(file, "\n{INDENT}\{}\n") - } else { - fprint(file, "\{\}\n") - } - for (field in info) { - if (isBaseCoreAttr(field)) { - continue - } - fprint(file, "{INDENT}{cppTypeName(field)} {field.name}{cppTypeDim(field)};\n") - } - if (argCount != 0) { - fprint(file, "{INDENT}Event *moveHeap()&& override\n{INDENT}\{\n{INDENT}{INDENT}return new {info.name}(\n") - printArguments(file, info, "") - fprint(file, "\n{INDENT}{INDENT});\n{INDENT}\}\n") - fprint(file, "{INDENT}template const T& get() const;\n") - var count = 0 - for (field in info) { - if (isBaseCoreAttr(field)) { - continue - } - fprint(file, "{INDENT}template<> const {cppTypeName(field)}{cppTypeDim(field)} & get<{count++}>() const \{ return {field.name}; \};\n") - } - } else { - fprint(file, "{INDENT}Event *moveHeap()&& override\{return new {info.name};\}\n") - } - - //fprint(file,"{INDENT}{INDENT}{INDENT}eastl::move(*this)"); - - fprint(file, "\};\n\n") -} - -def process(fname : string; hf, cppf : FILE const?) { - print("processing {fname}\n") - var inscope access := make_file_access("") - using <| $(var mg : ModuleGroup) { - using <| $(var cop : CodeOfPolicies) { - rtti::compile_file(fname, access, unsafe(addr(mg)), cop) <| $(ok, program, issues) { - if (ok) { - let thisModule = rtti::get_this_module(program) - rtti::module_for_each_structure(thisModule) <| $(info) { - dumpAnnotations(hf, info) - generateCppEvent(hf, info) - generateSquirrelBinding(cppf, info) - } - } else { - print("{fname} failed to compile\n{issues}\n") - } - } - } - } -} - -def generate(atdir) { - var fh, fcpp : FILE const? - let eventListName = base_name(atdir) - let EVENTS_HEADER_FILE = "./{eventListName}.h" - let EVENTS_CPP_FILE = "./{eventListName}.cpp" - - fh = fopen(EVENTS_HEADER_FILE, "wb") - if (fh == null) { - print("can't open {EVENTS_HEADER_FILE}\n") - return - } - fcpp = fopen(EVENTS_CPP_FILE, "wb") - if (fcpp == null) { - print("can't open {EVENTS_CPP_FILE}\n") - return - } - // coreEvents.h header - fprint(fh, "#ifndef _DAGOR_GAMELIB_DAECS_CORE_{to_upper(eventListName)}_H_\n") - fprint(fh, "#define _DAGOR_GAMELIB_DAECS_CORE_{to_upper(eventListName)}_H_\n") - fprint(fh, "#pragma once\n\n") - fprint(fh, "#include \n\n") - fprint(fh, "namespace ecs\n") - fprint(fh, "\{\n\n") - - // coreEvents.cpp header - fprint(fcpp, "#include \n") - fprint(fcpp, "#include \n") - fprint(fcpp, "\nnamespace ecs\n") - fprint(fcpp, "\{\n\n") - fprint(fcpp, "void ecs_register_sq_das_binding_{eventListName}(HSQUIRRELVM vm)\n\{\n") - fprint(fcpp, "{INDENT}ecs::sq::EventsBindingType eventsBinding;\n\n") - - dir(atdir) <| $(fname) { - let fileName = atdir + "/" + fname - var st : FStat - if (stat(fileName, st)) { - if (st.is_reg) { - process(fileName, fh, fcpp) - } - } - } - - // coreEvent.h footer - fprint(fh, "void ecs_register_sq_das_binding_{eventListName}(HSQUIRRELVM vm);\n\n") - fprint(fh, "}\n\n") - fprint(fh, "#endif\n\n") - - // coreEvents.cpp footer - fprint(fcpp, "}\n\n}\n\n") - fprint(fcpp, "#endif\n\n") -} finally { - fclose(fh) - fclose(fcpp) -} - -[export] -def main { - let args <- get_command_line_arguments() - let fn = args[1] - let atdir = "./src" - print("{fn}\ndas network message generator at {atdir}\n") - let main_time = stat(fn).mtime - var ttab : table - while (stat(fn).mtime == main_time) { - var any = false - dir(atdir) <| $(fname) { - let fileName = atdir + "/" + fname - var st : FStat - if (stat(fileName, st)) { - if (st.is_reg) { - let fmt = st.mtime - let tmt = ttab[fname] - if (tmt != fmt) { - ttab.insert(fname, fmt) - process(fileName, fstdout(), fstdout()) - any = true - } - } - } else { - print("can't stat {fileName}\n") - } - } - if (any) { - generate(atdir) - } - sleep(1000u) - } - print("ok\n") - return true -} - diff --git a/examples/contDev/src/baseCoreEvent.das b/examples/contDev/src/baseCoreEvent.das deleted file mode 100644 index 4dff08bb8e..0000000000 --- a/examples/contDev/src/baseCoreEvent.das +++ /dev/null @@ -1,6 +0,0 @@ - -struct BaseCoreEvent { - @skipCpp = true vtbl__ : uint? - @skipCpp = true eventName : string - @skipCpp = true eventType : uint -} diff --git a/examples/contDev/src/events.das b/examples/contDev/src/events.das deleted file mode 100644 index 75a52e19c7..0000000000 --- a/examples/contDev/src/events.das +++ /dev/null @@ -1,16 +0,0 @@ -options gen2 -require baseCoreEvent - -struct EventComponentChanged : BaseCoreEvent { - @cppType = "const_string" name : string - flags : uint - @cppType = "component_t" hash : uint - @cppType = "component_index_t" index : uint8 -} - -struct EventAnyComponentChanged : BaseCoreEvent { - @cppType = "const_string" name : string - flags : uint - @cppType = "component_t" hash : uint - @cppType = "component_index_t" index : uint8 -} diff --git a/examples/contDev/src/test.das b/examples/contDev/src/test.das deleted file mode 100644 index 55e78b3731..0000000000 --- a/examples/contDev/src/test.das +++ /dev/null @@ -1,36 +0,0 @@ -options gen2 -//require baseCoreEvent//not working! - -struct BaseCoreEvent { - @skipCpp = true vtbl__ : uint? - @skipCpp = true eventName : string - @skipCpp = true eventType : uint -} -/* -struct SomeEvent { - pos,vel:float3 -} - -struct TestEvent { - i :int - i2:int2 - i3:int3 - i4:int4 - ui:uint - f :float - f2:float2 - f3:float3 - f4:float4 - s:string - m3x4:float3x4 - m4x4:float4x4 - ev:SomeEvent - ai:int[2] - aai:int[3][4] -} -*/ - - -[comment(sValue="hello,world", iValue=5, fValue=2.0, bValue=true)] -struct Dummy {} - diff --git a/examples/dasbind/dasbind_example.das b/examples/dasbind/dasbind_example.das index 11c9385a4e..c40717b9be 100644 --- a/examples/dasbind/dasbind_example.das +++ b/examples/dasbind/dasbind_example.das @@ -1,22 +1,87 @@ +// Foreign Function Binding -- Calling Native DLL Functions +// +// The `[extern]` annotation lets you call C functions from shared +// libraries (DLLs on Windows, .so on Linux, .dylib on macOS) +// directly from daslang, without writing any C++ glue code. +// +// Annotation syntax: +// [extern(convention, name="CName", library="LibName")] +// def DasName(args) : ReturnType { return default_value; } +// +// Parameters: +// convention -- calling convention: stdcall (aka WINAPI), cdecl, opengl +// name -- the exported symbol name in the library +// library -- DLL / shared library to load +// +// The function body is a stub (never executed) -- the annotation +// replaces it with a direct call to the native function at link time. +// +// Platform-specific libraries can be specified: +// [extern(cdecl, name="foo", +// windows_library="foo.dll", +// macos_library="libfoo.dylib", +// linux_library="libfoo.so")] +// +// Add `late` to defer symbol resolution until first call: +// [extern(cdecl, late, name="foo", library="plugin.dll")] +// +// Limitations: +// - Vector types (float2/float3/float4) are not supported as arguments +// - Maximum ~13 arguments per function (platform-dependent) +// - Requires `require dasbind` module +// +// This example calls Win32 API functions from Kernel32.dll. +// Run (Windows only): daslang.exe examples/dasbind/dasbind_example.das + options gen2 require dasbind +// --- Win32 API bindings --- +// Each function declares the calling convention (stdcall for Win32), +// the exported C name, and the DLL that contains it. +// The function body is a stub -- it is never executed. + +// Returns the processor number the current thread is running on. [extern(stdcall, name="GetCurrentProcessorNumber", library="Kernel32")] -def GetCurrentProcessorNumber : int { return -1; } +def GetCurrentProcessorNumber() : int { return -1; } + +// Sets the title of the console window. +[extern(stdcall, name="SetConsoleTitleA", library="Kernel32")] +def SetConsoleTitle(lpConsoleTitle : string) : bool { return false; } + +// Returns the current process ID. +[extern(stdcall, name="GetCurrentProcessId", library="Kernel32")] +def GetCurrentProcessId() : uint { return 0u; } +// Retrieves the number of milliseconds since the system was started. +[extern(stdcall, name="GetTickCount", library="Kernel32")] +def GetTickCount() : uint { return 0u; } + +// Terminates the current process immediately. [extern(stdcall, name="ExitProcess", library="Kernel32")] -def ExitProcess(code : int) {} +def ExitProcess(uExitCode : uint) {} -[extern(stdcall, name="SetConsoleTitleA", library="Kernel32")] -def SetConsoleTitle(lpConsoleTitle : string) {} +// --- Main --- [export] -def main { - let proc_n = GetCurrentProcessorNumber() - print("current processor {proc_n}\n") - SetConsoleTitle("hello, console title\n") - ExitProcess(1234) -} +def main() { + // Query system information + let proc_num = GetCurrentProcessorNumber() + let pid = int(GetCurrentProcessId()) + let uptime_ms = int(GetTickCount()) + print("processor number : {proc_num}\n") + print("process ID : {pid}\n") + print("system uptime : {uptime_ms} ms\n") + // Modify the console window title + SetConsoleTitle("daslang -- dasbind example") + print("(console title changed)\n") + // ExitProcess terminates immediately -- nothing after it runs. + // Uncomment to see: the process exits with code 42, skipping + // any cleanup or finally blocks. + // ExitProcess(42u) + + print("done\n") +} diff --git a/examples/debugapi/allocation_tracking.das b/examples/debugapi/allocation_tracking.das new file mode 100644 index 0000000000..fda1124db8 --- /dev/null +++ b/examples/debugapi/allocation_tracking.das @@ -0,0 +1,181 @@ +// Allocation Tracking via Debug Agent +// +// Demonstrates memory allocation callbacks in DapiDebugAgent: +// onAllocate — called on every heap allocation +// onReallocate — called when a heap block is resized +// onFree — called when a heap block is freed +// onAllocateString — called when a string is allocated +// onFreeString — called when a string is freed +// +// These callbacks enable: +// - Memory leak detection (track unmatched alloc/free pairs) +// - Allocation profiling (measure total bytes, allocation counts) +// - Memory budget enforcement (cap allocations per frame/phase) +// +// The callbacks fire for the instrumented context only. Enable +// tracking with `instrument_context_allocations(ctx, true)` and +// disable with `instrument_context_allocations(ctx, false)`. +// +// Each callback receives a `Context` reference and a `LineInfo` +// telling you where in the source code the allocation happened. +// +// Important: allocation callbacks are dispatched to the +// *thread-local* debug agent, so you must install with +// `install_new_thread_local_debug_agent` — not the global +// `install_new_debug_agent`. +// +// Run: daslang.exe examples/debugapi/allocation_tracking.das + +options gen2 +options persistent_heap = true +options debugger = true + +require rtti +require debugapi +require strings + +// ============================================================ +// A simple allocation tracker +// ============================================================ +// Logs every heap and string allocation with source location. +// Tracks counts and total bytes for a summary at the end. + +class AllocationTracker : DapiDebugAgent { + heap_allocs : int = 0 + heap_frees : int = 0 + total_bytes : uint64 = uint64(0) + string_allocs : int = 0 + string_frees : int = 0 + + def override onAllocate(var ctx : Context; data : void?; size : uint64; + at : LineInfo) : void { + heap_allocs++ + total_bytes += size + print(" [alloc] {size} bytes at {describe(at)}\n") + } + + def override onReallocate(var ctx : Context; data : void?; size : uint64; + newData : void?; newSize : uint64; at : LineInfo) : void { + total_bytes += newSize - size + print(" [realloc] {size} -> {newSize} bytes at {describe(at)}\n") + } + + def override onFree(var ctx : Context; data : void?; at : LineInfo) : void { + heap_frees++ + print(" [free] at {describe(at)}\n") + } + + def override onAllocateString(var ctx : Context; data : void?; size : uint64; + tempString : bool; at : LineInfo) : void { + string_allocs++ + let str = escape(unsafe(reinterpret data)) + let kind = tempString ? "temp" : "heap" + print(" [str+] ({kind}) '{str}' {size} bytes at {describe(at)}\n") + } + + def override onFreeString(var ctx : Context; data : void?; tempString : bool; + at : LineInfo) : void { + string_frees++ + } + + def print_summary() { + print("\n === allocation summary ===\n") + print(" heap: {heap_allocs} allocs, {heap_frees} frees, {total_bytes} bytes total\n") + print(" string: {string_allocs} allocs, {string_frees} frees\n") + } +} + +// ============================================================ +// Agent installation +// ============================================================ +// Thread-local agent — allocation callbacks are dispatched to +// thread-local agents only, not global named agents. +// We also install as a named global agent so we can access +// the agent context later via `get_debug_agent_context`. + +var tracker : AllocationTracker? + +[export] +def install_tracker(ctx : Context) { + assert(this_context().category.debug_context) + var agent = new AllocationTracker() + tracker = agent + // Thread-local: receives allocation callbacks + install_new_thread_local_debug_agent(agent) + // Named global: allows `get_debug_agent_context` access + install_new_debug_agent(new DapiDebugAgent(), "alloc_tracker") +} + +// Helper invoked in the agent context to print the summary +[export, pinvoke] +def print_tracker_summary() { + if (tracker != null) { + tracker.print_summary() + } +} + +// ============================================================ +// Application code that produces allocations +// ============================================================ + +struct Particle { + x : float + y : float + name : string +} + +def do_allocations() { + // Array push triggers heap allocations as the array grows + var arr : array + for (i in range(10)) { + arr |> push(i) + } + delete arr + + // String interpolation allocates on the string heap + var greeting = "hello world #{42}" + print(" computed: {greeting}\n") + + // `new` allocates a struct on the heap + var p = new Particle(x = 1.0, y = 2.0, name = "spark") + unsafe { + delete p + } +} + +// ============================================================ +// Main — demonstrates the full workflow +// ============================================================ + +[export] +def main() { + print("=== allocation tracking ===\n\n") + + // 1. Install the tracker agent (thread-local) + fork_debug_agent_context(@@install_tracker) + + // 2. Enable allocation instrumentation for this context + instrument_context_allocations(this_context(), true) + + print("--- tracked allocations ---\n") + do_allocations() + print("--- end tracked ---\n") + + // 3. Disable tracking + instrument_context_allocations(this_context(), false) + + // These allocations are NOT tracked (instrumentation is off) + print("\n(tracking disabled -- these allocations are silent)\n") + var silent : array + silent |> push(1) + delete silent + + // 4. Print summary — tracker lives in the agent context, + // so we invoke our helper there via the named agent + unsafe { + invoke_in_context(get_debug_agent_context("alloc_tracker"), + "print_tracker_summary") + } + + delete_debug_agent_context("alloc_tracker") +} diff --git a/examples/debugapi/heartbeat.das b/examples/debugapi/heartbeat.das new file mode 100644 index 0000000000..70749f3c96 --- /dev/null +++ b/examples/debugapi/heartbeat.das @@ -0,0 +1,147 @@ +// Heartbeat — Periodic Callback Injection +// +// Demonstrates `daslib/heartbeat` — a compile-time macro that +// automatically injects `heartbeat()` calls into every function +// body and every loop (for/while). This lets you run a callback +// periodically even inside long-running or infinite loops. +// +// Use cases: +// - Cooperative multitasking (yield to scheduler) +// - Watchdog / timeout detection (break infinite loops) +// - Progress reporting during heavy computation +// - Frame budget enforcement in game loops +// +// How it works: +// 1. `require daslib/heartbeat` activates a macro pass that +// adds `heartbeat()` calls to function entries and loop bodies +// 2. `set_heartbeat(callback)` registers a lambda to be called +// on each injected heartbeat point +// 3. The callback fires on every function call and every loop +// iteration — use a counter to throttle expensive work +// +// Note: lambda captures are by-copy for value types, so shared +// counters and flags must be module-level variables. +// +// Run: daslang.exe examples/debugapi/heartbeat.das + +options gen2 + +require daslib/heartbeat + +// Module-level state shared between heartbeat callbacks and code. +// Lambda captures copy value types, so locals can't be shared +// with the callback — use module-level vars instead. +var hb_count : int = 0 +var hb_should_stop : bool = false + +// ============================================================ +// Example 1: Watchdog for infinite loops +// ============================================================ +// The heartbeat fires on every loop iteration. After a +// threshold, the callback sets a flag that the loop checks. + +def demo_infinite_loop_watchdog() { + print("=== heartbeat: watchdog for infinite loops ===\n") + + hb_count = 0 + hb_should_stop = false + let max_iterations = 50 + + set_heartbeat() @ { + hb_count++ + if (hb_count >= max_iterations) { + hb_should_stop = true + } + } + + // Without the heartbeat watchdog, this runs forever. + // The heartbeat macro injects `heartbeat()` at the top of + // the loop body, so our callback fires every iteration. + var sum = 0 + while (!hb_should_stop) { + sum += 1 + } + print(" watchdog stopped loop after {hb_count} heartbeats, sum={sum}\n") +} + +// ============================================================ +// Example 2: Progress reporting during computation +// ============================================================ +// Throttle the heartbeat callback to report every N beats. + +def heavy_computation() : int { + var result = 0 + for (i in range(1000)) { + result += i * i + } + return result +} + +def demo_progress_reporting() { + print("\n=== heartbeat: progress reporting ===\n") + + hb_count = 0 + + set_heartbeat() @ { + hb_count++ + if (hb_count % 200 == 0) { + print(" ... {hb_count} heartbeats so far\n") + } + } + + let result = heavy_computation() + print(" computation result = {result}\n") + print(" total heartbeats = {hb_count}\n") +} + +// ============================================================ +// Example 3: Nested function calls +// ============================================================ +// Heartbeat fires at the start of EVERY function body, +// not just loops. + +def inner() { + // heartbeat() is injected here automatically + pass +} + +def middle() { + // heartbeat() is injected here automatically + inner() + inner() +} + +def outer() { + // heartbeat() is injected here automatically + middle() +} + +def demo_nested_calls() { + print("\n=== heartbeat: nested function calls ===\n") + + hb_count = 0 + set_heartbeat() @ { + hb_count++ + } + + outer() + // outer(1) + middle(1) + inner(1) + inner(1) = 4 + // (plus heartbeats from other function entries) + print(" heartbeats from outer->middle->inner: {hb_count}\n") +} + +// ============================================================ +// Main +// ============================================================ + +[export] +def main() { + demo_infinite_loop_watchdog() + demo_progress_reporting() + demo_nested_calls() + + // Clear the heartbeat by setting a no-op callback + set_heartbeat() @ { + pass + } +} diff --git a/examples/debugapi/hw_breakpoint.das b/examples/debugapi/hw_breakpoint.das new file mode 100644 index 0000000000..b942d4e5ab --- /dev/null +++ b/examples/debugapi/hw_breakpoint.das @@ -0,0 +1,186 @@ +// Hardware Breakpoints — Data Watchpoints +// +// Demonstrates `set_hw_breakpoint` and `clear_hw_breakpoint` — +// hardware data breakpoints that fire when a memory location is +// modified. This is a powerful debugging tool for tracking down +// unexpected writes to variables. +// +// How it works: +// - `set_hw_breakpoint(ctx, addr, size, writeOnly)` installs +// a hardware breakpoint on `size` bytes starting at `addr`. +// `writeOnly=true` triggers only on writes (not reads). +// Returns a breakpoint handle (int). +// - When the watched memory is written to, the debug agent's +// `onBreakpoint` is called at the NEXT line after the write +// (the write has already happened by then). +// - `clear_hw_breakpoint(handle)` removes the breakpoint. +// +// Requirements: +// - `options debugger = true` — enables the debug infrastructure +// - `require daslib/debug` — provides the debug agent that +// handles breakpoint events (or write your own agent) +// - A debug agent must be installed to receive breakpoint events +// +// Use cases: +// - Finding who modifies a variable unexpectedly +// - Tracking state corruption in complex systems +// - Implementing conditional data breakpoints in custom debuggers +// +// Run: daslang.exe examples/debugapi/hw_breakpoint.das + +options gen2 +options debugger = true + +require rtti +require debugapi + +// ============================================================ +// A debug agent that reports hardware breakpoint hits +// ============================================================ + +class BreakpointAgent : DapiDebugAgent { + hit_count : int = 0 + last_line : int = 0 + + def override onBreakpoint(var ctx : Context; at : LineInfo; + reason, text : string) : void { + hit_count++ + last_line = int(at.line) + print(" [breakpoint #{hit_count}] {reason} at line {int(at.line)}: {text}\n") + } +} + +[export] +def install_bp_agent(ctx : Context) { + assert(this_context().category.debug_context) + install_new_debug_agent(new BreakpointAgent(), "bp_agent") +} + +// ============================================================ +// Example 1: Watching a single integer variable +// ============================================================ + +def demo_watch_int() { + print("=== hw breakpoint: watching an int ===\n") + + var target = 10 + print(" initial target = {target}\n") + + // Set a hardware breakpoint on 4 bytes (sizeof int) at &target + var bp = 0 + unsafe { + bp = set_hw_breakpoint(this_context(), addr(target), 4, true) + } + print(" breakpoint installed (handle={bp})\n") + + // Each write to `target` triggers the breakpoint. + // The agent's onBreakpoint fires on the NEXT line after + // the write — by then the new value is already stored. + target = 20 + print(" after write: target = {target}\n") + + target = 30 + print(" after write: target = {target}\n") + + target = 40 + print(" after write: target = {target}\n") + + // Clear the breakpoint — further writes are silent + unsafe { + clear_hw_breakpoint(bp) + } + print(" breakpoint cleared\n") + + target = 50 + print(" after cleared write: target = {target} (no breakpoint)\n") +} + +// ============================================================ +// Example 2: Watching a struct field +// ============================================================ + +struct Position { + x : float + y : float +} + +def demo_watch_struct_field() { + print("\n=== hw breakpoint: watching a struct field ===\n") + + var pos = Position(x = 0.0, y = 0.0) + + // Watch only the `y` field — 4 bytes at offset of `y` + var bp = 0 + unsafe { + bp = set_hw_breakpoint(this_context(), addr(pos.y), 4, true) + } + print(" watching pos.y\n") + + // Writing to pos.x does NOT trigger the breakpoint + pos.x = 1.0 + print(" pos.x = {pos.x} (no trigger)\n") + + // Writing to pos.y DOES trigger it + pos.y = 2.0 + print(" pos.y = {pos.y} (triggered)\n") + + pos.y = 3.0 + print(" pos.y = {pos.y} (triggered again)\n") + + unsafe { + clear_hw_breakpoint(bp) + } + print(" breakpoint cleared\n") +} + +// ============================================================ +// Example 3: Scoped breakpoint pattern +// ============================================================ +// A helper that installs a breakpoint for a block scope and +// automatically clears it when the block exits. + +def watch_variable(var ctx : Context; data : void?; size : int; blk : block) { + var bp = 0 + unsafe { + bp = set_hw_breakpoint(ctx, data, size, true) + } + invoke(blk) + unsafe { + clear_hw_breakpoint(bp) + } +} + +def demo_scoped_breakpoint() { + print("\n=== hw breakpoint: scoped pattern ===\n") + + var value = 100 + + unsafe { + watch_variable(this_context(), addr(value), 4) { + value = 200 + print(" inside scope: value = {value}\n") + value = 300 + print(" inside scope: value = {value}\n") + } + } + + // After the scope, no breakpoint — writes are silent + value = 400 + print(" outside scope: value = {value} (no trigger)\n") +} + +// ============================================================ +// Main +// ============================================================ + +[export] +def main() { + // Install the debug agent first + fork_debug_agent_context(@@install_bp_agent) + + demo_watch_int() + demo_watch_struct_field() + demo_scoped_breakpoint() + + delete_debug_agent_context("bp_agent") +} diff --git a/examples/debugapi/instrumentation.das b/examples/debugapi/instrumentation.das new file mode 100644 index 0000000000..8a5cd7dff8 --- /dev/null +++ b/examples/debugapi/instrumentation.das @@ -0,0 +1,217 @@ +// Instrumentation — Line-Level and Function-Level Hooks +// +// Demonstrates two instrumentation mechanisms: +// +// 1. Line-level instrumentation (`instrument_node`) +// Marks specific source lines to trigger `onInstrument` and +// optionally `onSingleStep` in the debug agent. Use this +// for conditional breakpoints, coverage tracking, or tracing +// specific code regions. +// +// 2. Function-level instrumentation (`instrument_all_functions`) +// Registers a callback for every function entry and exit via +// `onInstrumentFunction`. Each function gets a user-defined +// `userData` value (e.g. an index for profiling). Use this +// for call graphs, profiling, or entrance/exit logging. +// +// Both mechanisms require a debug agent to receive callbacks. +// +// Key API: +// instrument_node(ctx, enable) <| $(at) { return should_instrument } +// — filter which lines to instrument; return true to mark a line +// set_single_step(ctx, enable) +// — enable/disable single-stepping after a breakpoint/instrument hit +// instrument_all_functions(ctx) <| $(fn, sfn) { return userData } +// — instrument all functions; return per-function userData +// onInstrument(ctx, at) +// — called when execution reaches an instrumented line +// onSingleStep(ctx, at) +// — called on every line when single-stepping is active +// onInstrumentFunction(ctx, fun, entering, userData) +// — called on function enter (entering=true) and exit (entering=false) +// +// Run: daslang.exe examples/debugapi/instrumentation.das + +options gen2 +options debugger = true + +require rtti +require debugapi +require strings +require math + +// ============================================================ +// Section 1: Line-level instrumentation +// ============================================================ +// This agent demonstrates selective line instrumentation. +// When a breakpoint fires, it instruments a specific line +// ahead in the same file. When execution reaches that line, +// onInstrument fires. We then enable single-stepping to +// trace a few lines. + +class LineInstrumentAgent : DapiDebugAgent { + steps_remaining : int = 0 + + def override onBreakpoint(var ctx : Context; at : LineInfo; + reason, text : string) : void { + print(" [breakpoint] line {int(at.line)}\n") + + // Instrument lines within the next 5 lines of the same file + let target_start = at.line + 2u + let target_end = at.line + 5u + instrument_node(ctx, true) <| $(line_at) { + if (line_at.fileInfo == at.fileInfo) { + if (line_at.line >= target_start && line_at.line <= target_end) { + return true + } + } + return false + } + } + + def override onInstrument(var ctx : Context; at : LineInfo) : void { + print(" [instrument] line {int(at.line)} -- enabling single-step\n") + set_single_step(ctx, true) + steps_remaining = 3 + } + + def override onSingleStep(var ctx : Context; at : LineInfo) : void { + print(" [step] line {int(at.line)}\n") + steps_remaining-- + if (steps_remaining <= 0) { + set_single_step(ctx, false) + print(" [step] stopped single-stepping\n") + } + } +} + +[export] +def install_line_agent(ctx : Context) { + install_new_debug_agent(new LineInstrumentAgent(), "line_inst") +} + +def target_function(n : int) : int { + var result = 0 + for (i in range(n)) { + result += i + } + result *= 2 + result += 1 + return result +} + +def demo_line_instrumentation() { + print("=== line-level instrumentation ===\n") + + fork_debug_agent_context(@@install_line_agent) + + // The breakpoint triggers our agent, which instruments + // lines ahead of it, and then single-steps a few lines. + breakpoint() + print(" line after breakpoint\n") + let r = target_function(5) + print(" result = {r}\n") + print(" done with line instrumentation\n") + + delete_debug_agent_context("line_inst") +} + +// ============================================================ +// Section 2: Function-level instrumentation +// ============================================================ +// This agent is notified on every function enter and exit. +// Each function gets a unique userData (an index assigned at +// instrumentation time). This enables: +// - Call graph construction +// - Function-level profiling (measure enter-to-exit time) +// - Call counting + +class FunctionProfileAgent : DapiDebugAgent { + indent : int = 0 + call_counts : array + + def override onInstrumentFunction(var ctx : Context; fun : SimFunction?; + entering : bool; userData : uint64) : void { + let idx = int(userData) + + // Grow the counts array if needed + while (length(call_counts) <= idx) { + call_counts |> push(0) + } + + if (entering) { + call_counts[idx]++ + let pad = build_string() $(var writer) { + for (_ in range(indent)) { + write(writer, " ") + } + } + print(" {pad}-> {fun.mangledName} (call #{call_counts[idx]})\n") + indent++ + } else { + indent = max(0, indent - 1) + let pad = build_string() $(var writer) { + for (_ in range(indent)) { + write(writer, " ") + } + } + print(" {pad}<- {fun.mangledName}\n") + } + } +} + +[export] +def install_func_agent(ctx : Context) { + install_new_debug_agent(new FunctionProfileAgent(), "func_prof") +} + +// Application functions to instrument + +def compute_sum(n : int) : int { + var s = 0 + for (i in range(n)) { + s += i + } + return s +} + +def compute_product(a, b : int) : int { + return a * b +} + +def do_work() { + let s = compute_sum(10) + let p = compute_product(s, 2) + print(" work result = {p}\n") +} + +def demo_function_instrumentation() { + print("\n=== function-level instrumentation ===\n") + + // Instrument all functions BEFORE forking the agent, so + // the agent receives onInstrumentFunction callbacks. + var func_index = 0 + instrument_all_functions(this_context()) <| $(fn, sfn) { + let idx = func_index + func_index++ + return uint64(idx) + } + print(" instrumented {func_index} functions\n") + + fork_debug_agent_context(@@install_func_agent) + + do_work() + do_work() + + delete_debug_agent_context("func_prof") +} + +// ============================================================ +// Main +// ============================================================ + +[export] +def main() { + demo_line_instrumentation() + demo_function_instrumentation() +} diff --git a/examples/debugapi/stack_walker.das b/examples/debugapi/stack_walker.das new file mode 100644 index 0000000000..a5e15862b4 --- /dev/null +++ b/examples/debugapi/stack_walker.das @@ -0,0 +1,247 @@ +// Stack Walking — Inspecting the Call Stack at Runtime +// +// Demonstrates `DapiStackWalker` — a debug API class that walks +// the call stack at any point during execution, visiting each +// stack frame and its arguments and local variables. +// +// This is the companion to `DapiDataWalker` (Tutorial 47). +// While DapiDataWalker inspects data values, DapiStackWalker +// inspects the execution context: call frames, arguments, locals. +// +// DapiStackWalker callbacks: +// onCallAt(pp, info, at) — stack frame with source location +// onCall(pp, info) — stack frame without source info +// onCallAOT(pp, fileName) — AOT-compiled frame +// onCallJIT(pp, fileName) — JIT-compiled frame +// onArgument(info, index, vinfo, arg) — function argument +// onVariable(info, vinfo, arg, inScope) — local variable +// +// To walk the stack you need a `StackWalker` adapter: +// 1. Create your DapiStackWalker subclass +// 2. Wrap it: `adapter <- make_stack_walker(walker)` +// 3. Call: `walk_stack(adapter, ctx, at)` +// +// Combining with DapiDataWalker: +// Embed a DapiDataWalker inside the stack walker to print +// variable values in a custom format. The `onArgument` and +// `onVariable` callbacks provide type info and data pointers +// that can be passed to `walk_data` or `sprint_data`. +// +// Run: daslang.exe examples/debugapi/stack_walker.das + +options gen2 +options debugger = true +options persistent_heap = true + +require rtti +require debugapi +require strings + +// ============================================================ +// Section 1: Basic stack walker +// ============================================================ +// Prints each call frame and its arguments/variables. + +class BasicStackWalker : DapiStackWalker { + frame_depth : int = 0 + + def make_indent() : string { + return repeat(" ", frame_depth) + } + + def override onCallAt(pp : Prologue; info : FuncInfo; at : LineInfo) : void { + let indent = make_indent() + print(" {indent}[frame {frame_depth}] {info.name} at line {int(at.line)}\n") + frame_depth++ + } + + def override onCall(pp : Prologue; info : FuncInfo) : void { + let indent = make_indent() + print(" {indent}[frame {frame_depth}] {info.name} (no source info)\n") + frame_depth++ + } + + def override onArgument(info : FuncInfo; index : int; vinfo : VarInfo; + arg : float4) : void { + let indent = make_indent() + let value = sprint_data(arg, type_info(vinfo), print_flags.singleLine) + print(" {indent} arg[{index}] {vinfo.name} = {value}\n") + } + + def override onVariable(inf : FuncInfo; vinfo : LocalVariableInfo; + arg : void?; inScope : bool) : void { + let indent = make_indent() + if (inScope) { + if (arg != null) { + let value = sprint_data(arg, type_info(vinfo), print_flags.singleLine) + print(" {indent} var {vinfo.name} = {value}\n") + } else { + print(" {indent} var {vinfo.name} (optimized out)\n") + } + } else { + print(" {indent} var {vinfo.name} (out of scope)\n") + } + } +} + +// ============================================================ +// Agent that walks the stack on breakpoint +// ============================================================ + +class StackWalkAgent : DapiDebugAgent { + walker_adapter : smart_ptr + walker : BasicStackWalker? + + def StackWalkAgent() { + walker = new BasicStackWalker() + unsafe { + walker_adapter <- make_stack_walker(walker) + } + } + + def operator delete() { + unsafe { + delete walker_adapter + delete walker + } + } + + def override onBreakpoint(var ctx : Context; at : LineInfo; + reason, text : string) : void { + print(" --- stack walk at line {int(at.line)} ---\n") + walker.frame_depth = 0 + walk_stack(walker_adapter, ctx, at) + print(" --- end stack walk ---\n") + } +} + +[export] +def install_stack_agent(ctx : Context) { + assert(this_context().category.debug_context) + install_new_debug_agent(new StackWalkAgent(), "stack_agent") +} + +// ============================================================ +// Application code with nested calls +// ============================================================ + +def inner_function(x : int; y : float) : float { + var result = float(x) + y + breakpoint() // stack walker triggers here + return result +} + +def middle_function(n : int) : float { + var sum = 0.0 + for (i in range(n)) { + sum += inner_function(i, 0.5) + } + return sum +} + +def demo_basic_stack_walk() { + print("=== basic stack walking ===\n") + + fork_debug_agent_context(@@install_stack_agent) + + let result = middle_function(1) + print(" result = {result}\n\n") + + delete_debug_agent_context("stack_agent") +} + +// ============================================================ +// Section 2: State collection with stack walking +// ============================================================ +// Combines `onCollect` (state collection) with stack walking. +// The agent collects custom diagnostic data AND walks the stack +// in a single breakpoint/collection event. +// +// `collect_debug_agent_state` triggers `onCollect` on all agents. +// Inside `onCollect`, the agent can: +// - Walk the stack to see caller info +// - Report custom variables via `report_context_state` +// - Build diagnostic objects from runtime state + +class DiagnosticAgent : DapiDebugAgent { + walker_adapter : smart_ptr + walker : BasicStackWalker? + collection_count : int = 0 + + def DiagnosticAgent() { + walker = new BasicStackWalker() + unsafe { + walker_adapter <- make_stack_walker(walker) + } + } + + def operator delete() { + unsafe { + delete walker_adapter + delete walker + } + } + + def override onCollect(var ctx : Context; at : LineInfo) : void { + collection_count++ + print(" --- diagnostic collection #{collection_count} ---\n") + + // Report custom variables to any listening debug tools + let depth = stack_depth(ctx) + unsafe { + let tinfo = typeinfo rtti_typeinfo(depth) + report_context_state(ctx, "Diagnostics", "stack_depth", + unsafe(addr(tinfo)), unsafe(addr(depth))) + let tinfo2 = typeinfo rtti_typeinfo(collection_count) + report_context_state(ctx, "Diagnostics", "collection_count", + unsafe(addr(tinfo2)), unsafe(addr(collection_count))) + } + + // Walk the stack for a full picture + walker.frame_depth = 0 + walk_stack(walker_adapter, ctx, at) + print(" --- end collection ---\n") + } + + def override onVariable(var ctx : Context; category, name : string; + info : TypeInfo; data : void?) : void { + unsafe { + let value = sprint_data(data, addr(info), print_flags.singleLine) + print(" reported {category}: {name} = {value}\n") + } + } +} + +[export] +def install_diagnostic_agent(ctx : Context) { + install_new_debug_agent(new DiagnosticAgent(), "diagnostics") +} + +def some_nested_work(depth : int) { + if (depth <= 0) { + // Trigger state collection at the deepest point + collect_debug_agent_state(this_context(), get_line_info(1)) + return + } + some_nested_work(depth - 1) +} + +def demo_diagnostic_collection() { + print("=== diagnostic collection with stack walking ===\n") + + fork_debug_agent_context(@@install_diagnostic_agent) + + some_nested_work(3) + + delete_debug_agent_context("diagnostics") +} + +// ============================================================ +// Main +// ============================================================ + +[export] +def main() { + demo_basic_stack_walk() + demo_diagnostic_collection() +} diff --git a/examples/hello_world.das b/examples/hello_world.das new file mode 100644 index 0000000000..57233d3d92 --- /dev/null +++ b/examples/hello_world.das @@ -0,0 +1,10 @@ +// Hello World -- your first daslang program +// +// Run: daslang.exe examples/hello_world.das + +options gen2 + +[export] +def main() { + print("hello, world!\n") +} diff --git a/examples/lint/example_scope_lint.das b/examples/lint/example_scope_lint.das deleted file mode 100644 index fe8f2da090..0000000000 --- a/examples/lint/example_scope_lint.das +++ /dev/null @@ -1,11 +0,0 @@ -options gen2 -require scope_lint - -[export] -def main { - var a : array // this one not fine, needs inscope - var inscope b : table // this one fine - var c : int - c ++ - print("hello world {a} {b} {c}\n") -} diff --git a/examples/lint/scope_lint.das b/examples/lint/scope_lint.das deleted file mode 100644 index 50eda13b93..0000000000 --- a/examples/lint/scope_lint.das +++ /dev/null @@ -1,100 +0,0 @@ -options gen2 -options indenting = 4 -options no_unused_block_arguments = false -options no_unused_function_arguments = false - -module scope_lint shared private - -require daslib/strings_boost -require daslib/ast_boost -require daslib/strings_boost - -[lint_macro] -class ScopeLint : AstPassMacro { - def override apply(prog : ProgramPtr; mod : Module?) : bool { - paranoid(prog, true) - return true - } -} - -class LintVisitor : AstVisitor { - compile_time_errors : bool - noLint : bool = false - def LintVisitor() { - pass - } - def lint_error(text : string; at : LineInfo) : void { - if (noLint) { - return - } - if (compile_time_errors) { - compiling_program() |> macro_error(at, text) - } else { - error("{text} at {describe(at)}\n") - } - } - def override preVisitFunction(fun : FunctionPtr) : void { - noLint = false - for (ann in fun.annotations) { - if (ann.annotation.name == "no_lint") { - noLint = true - break - } - } - } - def override visitFunction(var fun : FunctionPtr) : FunctionPtr { - noLint = false - return <- fun - } - def override preVisitExprLet(expr : smart_ptr) : void { - print("let {describe(expr)}\n") - for (v in expr.variables) { - if (!v.flags.inScope && v._type |> aggresiveInScope) { - lint_error("variable {v.name} is not in scope", v.at) - } - } - } -} - -[macro_function] -def paranoid(prog : ProgramPtr; compile_time_errors : bool) { - var astVisitor = new LintVisitor(compile_time_errors = compile_time_errors) - var inscope astVisitorAdapter <- make_visitor(*astVisitor) - visit(prog, astVisitorAdapter) - astVisitorAdapter := null - unsafe { - delete astVisitor - } -} - -def aggresiveInScope(t : TypeDeclPtr; var dep : table) : bool { - if (t.baseType == Type.tStructure) { - if (dep |> key_exists(t.structType)) { - return false - } - dep |> insert(t.structType) - for (fld in t.structType.fields) { - if (fld._type |> aggresiveInScope(dep)) { - return true - } - } - } elif (t.baseType == Type.tTuple || t.baseType == Type.tVariant || t.baseType == Type.option) { - for (arg in t.argTypes) { - if (arg |> aggresiveInScope(dep)) { - return true - } - } - } elif (t.baseType == Type.tArray || t.baseType == Type.tTable) { - return true // any array or table needs to be in scope - } elif (t.baseType == Type.tHandle) { - return false // TOOD: expose "needInScope" field of the type, and use that - } elif (t.baseType == Type.tPointer) { - return t.flags.smartPtr - } - return false -} - -def aggresiveInScope(t : TypeDeclPtr) { - var inscope dep : table - return t |> aggresiveInScope(dep) -} diff --git a/examples/pathTracer/CMakeLists.txt b/examples/pathTracer/CMakeLists.txt index 448b1ab760..f627533c70 100644 --- a/examples/pathTracer/CMakeLists.txt +++ b/examples/pathTracer/CMakeLists.txt @@ -20,14 +20,6 @@ TARGET_LINK_LIBRARIES(path_tracer libDaScriptAot ${DAS_MODULES_LIBS}) ADD_DEPENDENCIES(path_tracer libDaScriptAot pathtracer_dasAotStub) SETUP_CPP11(path_tracer) -IF(NOT ${DAS_BGFX_DISABLED}) - install(FILES - ${PROJECT_SOURCE_DIR}/examples/pathTracer/toy_path_tracer_bgfx.das - ${PROJECT_SOURCE_DIR}/examples/pathTracer/toy_path_tracer_bgfx_hdr.das - DESTINATION ${DAS_INSTALL_EXAMPLESDIR}/pathTracer - ) -ENDIF() - install(FILES ${PROJECT_SOURCE_DIR}/examples/pathTracer/path_tracer.das ${PROJECT_SOURCE_DIR}/examples/pathTracer/toy_path_tracer.das diff --git a/examples/pathTracer/path_tracer.png b/examples/pathTracer/path_tracer.png deleted file mode 100644 index 9c7c839746..0000000000 Binary files a/examples/pathTracer/path_tracer.png and /dev/null differ diff --git a/examples/pathTracer/runme.bat b/examples/pathTracer/runme.bat deleted file mode 100644 index ba72f6c3ad..0000000000 --- a/examples/pathTracer/runme.bat +++ /dev/null @@ -1 +0,0 @@ -"..\..\bin\daScript.exe" toy_path_tracer.das diff --git a/examples/pathTracer/runme_linux.sh b/examples/pathTracer/runme_linux.sh deleted file mode 100644 index 8609f5e3eb..0000000000 --- a/examples/pathTracer/runme_linux.sh +++ /dev/null @@ -1,2 +0,0 @@ -./../../bin/daScript toy_path_tracer.das - diff --git a/examples/pathTracer/runme_msvc.bat b/examples/pathTracer/runme_msvc.bat deleted file mode 100644 index 58efafcfee..0000000000 --- a/examples/pathTracer/runme_msvc.bat +++ /dev/null @@ -1 +0,0 @@ -"..\..\bin\Release\daScript.exe" toy_path_tracer.das diff --git a/examples/pathTracer/toy_path_tracer_bgfx.das b/examples/pathTracer/toy_path_tracer_bgfx.das deleted file mode 100644 index 383fb67fbc..0000000000 --- a/examples/pathTracer/toy_path_tracer_bgfx.das +++ /dev/null @@ -1,134 +0,0 @@ -options gen2 -require glfw/glfw_boost -require dasbgfx/bgfx_boost -require daslib/defer -require daslib/math_boost -require daslib/safe_addr -require daslib/random - -require path_tracer - -let TRACE_WIDTH = 1024 -let TRACE_HEIGHT = 1024 - -var @in a_position : float2 -var @in a_texcoord0 : float2 -var @inout v_texcoord0 : float2 -var @uniform@stage = 0 f_tex : sampler2D -var @uniform@format = rgba32f@stage = 0@readwrite c_destTex : image2D -var @uniform c_frame : float4 - -[bgfx_vertex_program] -def vs_effect { - v_texcoord0 = a_texcoord0 - gl_Position = float4(a_position, 0.0, 1.0) -} - -def linear_to_RGB(color : float3) { - let x = float4(max(color, float3(0)), 1.0) - return max(1.055 * pow(x, float4(0.416666667)) - float4(0.055), float4(0)) -} - -[bgfx_fragment_program] -def fs_effect { - gl_FragColor = linear_to_RGB(texture2D(f_tex, v_texcoord0).xyz).zyxx -} - -[bgfx_compute_program(local_size_x=16, local_size_y=16)] -def compute_effect { - if (gl_LocalInvocationIndex == 0u) { - init_path_tracer() - } - memoryBarrierShared() - let cframe = float_bits_to_int(c_frame.y) - let storePos = int2(gl_GlobalInvocationID.xy) - random_seed2D(RAND_SEED, storePos, cframe) - random_float4(RAND_SEED) - var rgb = draw_ray(storePos.x, TRACE_HEIGHT - storePos.y, TRACE_WIDTH, TRACE_HEIGHT) - if (true) { - var nrgb = rgb.zyxx - if (cframe != 0) { - let orgb = imageLoad(c_destTex, storePos) - let wf = float(cframe) - nrgb = (orgb * wf + nrgb) / (wf + 1.) - } - imageStore(c_destTex, storePos, nrgb) - } else { - imageStore(c_destTex, storePos, rgb.zyxx) - } -} - -[bgfx_vertex_buffer] -struct EffectVertex { - position : float2 - texcoord0 : float2 -} - -let effect_vertices = fixed_array(EffectVertex( - position = float2(-1.0, 1.0), texcoord0 = float2(0.0, 0.0)), EffectVertex( - position = float2(1.0, 1.0), texcoord0 = float2(1.0, 0.0)), EffectVertex( - position = float2(1.0, -1.0), texcoord0 = float2(1.0, 1.0)), EffectVertex( - position = float2(-1.0, -1.0), texcoord0 = float2(0.0, 1.0) -)) - -let effect_indices = fixed_array(0, 2, 1, 2, 0, 3) - -[export] -def main { - if (glfwInit() == 0) { - panic("can't init glfw") - } - defer <| $() { - glfwTerminate() - } - var window = glfwCreateWindow(TRACE_WIDTH, TRACE_HEIGHT, "BGFX Path tracer", null, null) - if (window == null) { - panic("can't create window") - } - defer <| $() { - glfwDestroyWindow(window) - } - glfwSetWindowSize(window, TRACE_WIDTH, TRACE_HEIGHT) - var pd : bgfx_platform_data_s - pd.nwh = glfwGetNativeWindow(window) - bgfx_set_platform_data(safe_addr(pd)) - // bgfx_init(TRACE_WIDTH,TRACE_WIDTH,bgfx_renderer_type OPENGL) - // bgfx_init(TRACE_WIDTH,TRACE_WIDTH,bgfx_renderer_type DIRECT3D12) - bgfx_init(TRACE_WIDTH, TRACE_WIDTH) - glfwSetWindowTitle(window, "BGFX Path tracer - {bgfx_get_renderer_type()}") - var compute_program = bgfx_create_compute_shader_program(@@compute_effect) - var display_program = bgfx_create_shader_program(@@vs_effect, @@fs_effect) - var pcvl_decl = bgfx_create_vertex_layout(type) - var vbh = bgfx_create_vertex_buffer(bgfx_make_ref(effect_vertices), safe_addr(pcvl_decl), BGFX_BUFFER_NONE) - var ibh = bgfx_create_index_buffer(bgfx_make_ref(effect_indices), BGFX_BUFFER_INDEX32) - var texture = bgfx_create_texture_2d(uint(TRACE_WIDTH), uint(TRACE_HEIGHT), false, 1u, - bgfx_texture_format.RGBA32F, BGFX_TEXTURE_COMPUTE_WRITE, null) - if (texture.idx == uint16(0xffff)) { - panic("can't create texture") - } - let v_ortho = bgfx_mat_ortho(-1., 1., -1., 1., -100., 100., 0., bgfx_get_caps().homogeneousDepth, false) - bgfx_set_view_clear(0u, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, RGBA_TO_BGFX_UCOLOR(0.2, 0.2, 0.2, 1.0), 1.0f, 0u) - var cframe = 0 - while (glfwWindowShouldClose(window) == 0) { - glfwPollEvents() - var display_w, display_h : int - glfwGetWindowSize(window, safe_addr(display_w), safe_addr(display_h)) - bgfx_reset(uint(display_w), uint(display_h), BGFX_RESET_VSYNC, bgfx_texture_format.COUNT) - bgfx_set_view_rect(0u, 0u, 0u, uint(display_w), uint(display_h)) - c_frame.x = float(cframe) - c_frame.y = int_bits_to_float(cframe) - cframe ++ - c_destTex := texture - compute_effect_bind_uniform() - bgfx_dispatch(0u, compute_program, uint(TRACE_WIDTH / 16), uint(TRACE_HEIGHT / 16), 1u, 0u) - bgfx_set_vertex_buffer(0u, vbh) - bgfx_set_index_buffer(ibh) - f_tex := texture - vs_effect_bind_uniform() - fs_effect_bind_uniform() - bgfx_set_state(BGFX_STATE_DEFAULT, 0u) - bgfx_submit(0u, display_program, 1u, BGFX_DISCARD_NONE) - bgfx_frame(true) - } - bgfx_shutdown() -} \ No newline at end of file diff --git a/examples/pathTracer/toy_path_tracer_bgfx_hdr.das b/examples/pathTracer/toy_path_tracer_bgfx_hdr.das deleted file mode 100644 index b7ed4a8b86..0000000000 --- a/examples/pathTracer/toy_path_tracer_bgfx_hdr.das +++ /dev/null @@ -1,248 +0,0 @@ -options gen2 -require glfw/glfw_boost -require dasbgfx/bgfx_boost -require daslib/defer -require daslib/math_boost -require daslib/safe_addr -require daslib/random -require daslib/unroll - -require path_tracer - -let TRACE_WIDTH = 1024 -let TRACE_HEIGHT = 1024 -let BLOOM_SCALE = 4 - -var @in a_position : float2 -var @in a_texcoord0 : float2 -var @inout v_texcoord0 : float2 -var @uniform@stage = 0 f_tex : sampler2D -var @uniform@stage = 1 f_bloom : sampler2D -var @uniform@format = rgba32f@stage = 0 c_destTex : image2D -var @uniform c_frame : float4 - -[bgfx_vertex_program] -def vs_effect { - v_texcoord0 = a_texcoord0 - gl_Position = float4(a_position, 0.0, 1.0) -} - -def linear_to_RGB(color : float3) { - let x = float4(max(color, float3(0)), 1.0) - return max(1.055 * pow(x, float4(0.416666667)) - float4(0.055), float4(0)) -} - -[bgfx_fragment_program] -def fs_effect { - let color = texture2D(f_tex, v_texcoord0) - let bloom = texture2D(f_bloom, v_texcoord0) - let res = bloom + color - gl_FragColor = linear_to_RGB(res.xyz).zyxx -} - -[bgfx_compute_program(local_size_x=16, local_size_y=16)] -def compute_effect { - if (gl_LocalInvocationIndex == 0u) { - init_path_tracer() - } - memoryBarrierShared() - let cframe = float_bits_to_int(c_frame.y) - let storePos = int2(gl_GlobalInvocationID.xy) - random_seed2D(RAND_SEED, storePos, cframe) - random_float4(RAND_SEED) - var rgb = draw_ray(storePos.x, TRACE_HEIGHT - storePos.y, TRACE_WIDTH, TRACE_HEIGHT) - if (true) { - var nrgb = rgb.zyxx - if (cframe != 0) { - let orgb = imageLoad(c_destTex, storePos) - let wf = float(cframe) - nrgb = (orgb * wf + nrgb) / (wf + 1.) - } - imageStore(c_destTex, storePos, nrgb) - } else { - imageStore(c_destTex, storePos, rgb.zyxx) - } -} - -var @uniform@format = rgba32f@stage = 0 c_bloom_source : image2D -var @uniform@format = rgba32f@stage = 1 c_bloom_vtex : image2D -var @uniform@format = rgba32f@stage = 2 c_bloom_htex : image2D -var @uniform@need_init = false c_bloom_weights : float4[9] -var @uniform c_bloom_iweights_summ : float4 - -def gaussian(x, sigma : float) { - return (1. / (sqrt(2. * PI) * sigma)) * exp(-(x * x) / (2. * sigma * sigma)) -} - -[bgfx_compute_program(version=430, local_size_x=16, local_size_y=16)] -def bloom_effect_copy { - let xy = int2(gl_GlobalInvocationID.xy) - // copy - let XY = xy * int2(BLOOM_SCALE) - var orgb : float4 - unroll <| $() { - for (by in range(BLOOM_SCALE)) { - unroll <| $() { - for (bx in range(BLOOM_SCALE)) { - orgb = max(orgb, imageLoad(c_bloom_source, XY + int2(bx, by))) - } - } - } - } - orgb = pow(orgb, float4(3.)) - orgb = saturate(orgb) - imageStore(c_bloom_vtex, xy, orgb) -} - -[bgfx_compute_program(local_size_x=16, local_size_y=16)] -def bloom_effect_v { - let xy = int2(gl_GlobalInvocationID.xy) - // blur v - var n : float4[9] - unroll <| $() { - for (i in range(9)) { - n[i] = imageLoad(c_bloom_vtex, xy + int2(i - 4, 0)) - } - } - var hrgb : float4 - for (a, w in n, c_bloom_weights) { - hrgb += a * w - } - hrgb *= c_bloom_iweights_summ - imageStore(c_bloom_htex, xy, hrgb) -} - -[bgfx_compute_program(local_size_x=16, local_size_y=16)] -def bloom_effect_h { - let xy = int2(gl_GlobalInvocationID.xy) - // blur h - var n : float4[9] - unroll <| $() { - for (i in range(9)) { - n[i] = imageLoad(c_bloom_htex, xy + int2(0, i - 4)) - } - } - var vrgb : float4 - for (a, w in n, c_bloom_weights) { - vrgb += a * w - } - vrgb *= c_bloom_iweights_summ - imageStore(c_bloom_vtex, xy, vrgb) -} - -[bgfx_vertex_buffer] -struct EffectVertex { - position : float2 - texcoord0 : float2 -} - -let effect_vertices = fixed_array(EffectVertex( - position = float2(-1.0, 1.0), texcoord0 = float2(0.0, 0.0)), EffectVertex( - position = float2(1.0, 1.0), texcoord0 = float2(1.0, 0.0)), EffectVertex( - position = float2(1.0, -1.0), texcoord0 = float2(1.0, 1.0)), EffectVertex( - position = float2(-1.0, -1.0), texcoord0 = float2(0.0, 1.0) -)) - -let effect_indices = fixed_array(0, 2, 1, 2, 0, 3) - -[export] -def main { - if (glfwInit() == 0) { - panic("can't init glfw") - } - defer <| $() { - glfwTerminate() - } - var window = glfwCreateWindow(TRACE_WIDTH, TRACE_HEIGHT, "BGFX Path tracer with bloom", null, null) - if (window == null) { - panic("can't create window") - } - defer <| $() { - glfwDestroyWindow(window) - } - glfwSetWindowSize(window, TRACE_WIDTH, TRACE_HEIGHT) - var pd : bgfx_platform_data_s - pd.nwh = glfwGetNativeWindow(window) - bgfx_set_platform_data(safe_addr(pd)) - // bgfx_init(TRACE_WIDTH,TRACE_WIDTH,bgfx_renderer_type OPENGL) - // bgfx_init(TRACE_WIDTH,TRACE_WIDTH,bgfx_renderer_type DIRECT3D12) - bgfx_init(TRACE_WIDTH, TRACE_WIDTH) - glfwSetWindowTitle(window, "BGFX Path tracer with bloom - {bgfx_get_renderer_type()}") - var compute_program = bgfx_create_compute_shader_program(@@compute_effect) - var display_program = bgfx_create_shader_program(@@vs_effect, @@fs_effect) - var pcvl_decl = bgfx_create_vertex_layout(type) - var vbh = bgfx_create_vertex_buffer(bgfx_make_ref(effect_vertices), safe_addr(pcvl_decl), BGFX_BUFFER_NONE) - var ibh = bgfx_create_index_buffer(bgfx_make_ref(effect_indices), BGFX_BUFFER_INDEX32) - var texture = bgfx_create_texture_2d(uint(TRACE_WIDTH), uint(TRACE_HEIGHT), false, 1u, - bgfx_texture_format.RGBA32F, BGFX_TEXTURE_COMPUTE_WRITE, null) - if (texture.idx == uint16(0xffff)) { - panic("can't create texture") - } - var bloom_program_copy = bgfx_create_compute_shader_program(@@bloom_effect_copy) - var bloom_program_h = bgfx_create_compute_shader_program(@@bloom_effect_h) - var bloom_program_v = bgfx_create_compute_shader_program(@@bloom_effect_v) - var bloom_texture : bgfx_texture_handle_s[2] - for (b in bloom_texture) { - b = bgfx_create_texture_2d(uint(TRACE_WIDTH / BLOOM_SCALE), uint(TRACE_HEIGHT / BLOOM_SCALE), false, 1u, - bgfx_texture_format.RGBA32F, BGFX_TEXTURE_COMPUTE_WRITE, null) - if (b.idx == uint16(0xffff)) { - panic("can't create texture") - } - } - let v_ortho = bgfx_mat_ortho(-1., 1., -1., 1., -100., 100., 0., bgfx_get_caps().homogeneousDepth, false) - bgfx_set_view_clear(0u, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, RGBA_TO_BGFX_UCOLOR(0.2, 0.2, 0.2, 1.0), 1.0f, 0u) - var cframe = 0 - while (glfwWindowShouldClose(window) == 0) { - glfwPollEvents() - var display_w, display_h : int - glfwGetWindowSize(window, safe_addr(display_w), safe_addr(display_h)) - bgfx_reset(uint(display_w), uint(display_h), BGFX_RESET_VSYNC, bgfx_texture_format.COUNT) - bgfx_set_view_rect(0u, 0u, 0u, uint(display_w), uint(display_h)) - // copmute next iteration of tracing - c_frame.x = float(cframe) - c_frame.y = int_bits_to_float(cframe) - cframe ++ - c_destTex := texture - compute_effect_bind_uniform() - bgfx_dispatch(0u, compute_program, uint(TRACE_WIDTH / 16), uint(TRACE_HEIGHT / 16), 1u, 0u) - // bloom weights - let sigma = 4.0 - for (t in range(9)) { - c_bloom_weights[t] = float4(gaussian(float(t - 4), sigma)) - } - c_bloom_iweights_summ = float4(0.) - for (w in c_bloom_weights) { - c_bloom_iweights_summ += w - } - c_bloom_iweights_summ = 1.0 / c_bloom_iweights_summ - // bloom copy - c_bloom_source := texture - c_bloom_vtex := bloom_texture[0] - c_bloom_htex := bloom_texture[1] - bloom_effect_copy_bind_uniform() - bgfx_dispatch(0u, bloom_program_copy, uint(TRACE_WIDTH / 16 / BLOOM_SCALE), uint(TRACE_HEIGHT / 16 / BLOOM_SCALE), 1u, 0u) - // bloom v - c_bloom_source := texture - c_bloom_vtex := bloom_texture[0] - c_bloom_htex := bloom_texture[1] - bloom_effect_v_bind_uniform() - bgfx_dispatch(0u, bloom_program_v, uint(TRACE_WIDTH / 16 / BLOOM_SCALE), uint(TRACE_HEIGHT / 16 / BLOOM_SCALE), 1u, 0u) - // bloom h - c_bloom_source := texture - c_bloom_vtex := bloom_texture[0] - c_bloom_htex := bloom_texture[1] - bloom_effect_h_bind_uniform() - bgfx_dispatch(0u, bloom_program_h, uint(TRACE_WIDTH / 16 / BLOOM_SCALE), uint(TRACE_HEIGHT / 16 / BLOOM_SCALE), 1u, 0u) - // display it - bgfx_set_vertex_buffer(0u, vbh) - bgfx_set_index_buffer(ibh) - f_tex := texture - f_bloom := c_bloom_vtex - vs_effect_bind_uniform() - fs_effect_bind_uniform() - bgfx_set_state(BGFX_STATE_DEFAULT, 0u) - bgfx_submit(0u, display_program, 1u, BGFX_DISCARD_NONE) - bgfx_frame(true) - } - bgfx_shutdown() -} diff --git a/examples/test/misc/a.das b/examples/test/misc/a.das deleted file mode 100644 index 9069aa8904..0000000000 --- a/examples/test/misc/a.das +++ /dev/null @@ -1,16 +0,0 @@ -options gen2 - -require m -require b - -[unique_transaction, export] -def testA() { - print("{p}") - makeDeltaTransaction(p) -} - -[export] -def test { - testA() - return true -} \ No newline at end of file diff --git a/examples/test/misc/agent_fork_sample.das b/examples/test/misc/agent_fork_sample.das deleted file mode 100644 index 8531005537..0000000000 --- a/examples/test/misc/agent_fork_sample.das +++ /dev/null @@ -1,54 +0,0 @@ -options gen2 -require rtti -require debugapi -require jobque - -// debug server - -[export] -def debug_agent(ctx : Context) { - print("from debugger\n") - install_new_debug_agent(new DapiDebugAgent(), "sample") // note - no install = no category -} - -[export, pinvoke] -def debug_agent_fn(ctx : Context; fun : function) { - print("debug agent call {fun} from context {ctx}\n") - unsafe { - ctx |> invoke_in_context(fun, "now") - } -} - -// client - -var { - wait_for_it = true -} - -[export, pinvoke] -def stop_waiting(msg : string#) { - print("we stop waiting {msg}\n") - wait_for_it = false -} - -def has_agent { - return has_debug_agent_context("sample") -} - -[export] -def main { - print("forking\n") - print("has agent? {has_agent()}\n") - fork_debug_agent_context(@@debug_agent) - print("forked\n") - print("has agent? {has_agent()}\n") - unsafe { - get_debug_agent_context("sample") |> invoke_in_context("debug_agent_fn", this_context(), @@stop_waiting) - } - while (wait_for_it) { - print("waiting\n") - } - while (true) { - pass - } -} diff --git a/examples/test/misc/all_sorts_of_prop.das b/examples/test/misc/all_sorts_of_prop.das deleted file mode 100644 index 1aa915f430..0000000000 --- a/examples/test/misc/all_sorts_of_prop.das +++ /dev/null @@ -1,56 +0,0 @@ -options gen2 -def get(cb : block<(a : string#) : void>) { - unsafe { - cb |> invoke(reinterpret "foo") - } -} - -struct Foo { - resz : string -} - -def operator . res :=(var f : Foo; st : string#) { - f.resz := st -} - -[export] -def main() { - if (true) { - var res : string - get() <| $(name) { - res := name - } - debug(res) - } - if (true) { - var f : Foo - get() <| $(name) { - f.resz := name - } - debug(f) - } - if (true) { - var f : Foo - get() <| $(name) { - f.res := name - } - debug(f) - } -} - -class sealed UIFrame { - def const operator . sizezz() : float2 { - print("get value") - return float2(1, 2) - } - def operator . sizezz :=(value : float2) { - print("set {value}\n") - } -} - -[export] -def apply_canvas_anchoring(var frame : UIFrame?; parentSize : float2) { - frame.sizezz := parentSize -} - -options log diff --git a/examples/test/misc/allocation_callbacks_in_debug_agent.das b/examples/test/misc/allocation_callbacks_in_debug_agent.das deleted file mode 100644 index 66bc4ceacc..0000000000 --- a/examples/test/misc/allocation_callbacks_in_debug_agent.das +++ /dev/null @@ -1,67 +0,0 @@ -options gen2 -options persistent_heap = true -options debugger = true - -require rtti -require debugapi -require strings - -// sample of debug agent - -class SampleDebugAgent : DapiDebugAgent { - def SampleDebugAgent { - pass - } - def override onAllocate(var ctx : Context; data : void?; size : uint64; at : LineInfo) : void { - print("{ctx} {ctx.name} : allocate {size} bytes at {describe(at)}\n") - } - def override onReallocate(var ctx : Context; data : void?; size : uint64; newData : void?; newSize : uint64; at : LineInfo) : void { - print("{ctx} {ctx.name} : reallocate {size} bytes to {newSize} bytes at {describe(at)}\n") - } - def override onFree(var ctx : Context; data : void?; at : LineInfo) : void { - print("{ctx} {ctx.name} : free at {describe(at)}\n") - } - def override onAllocateString(var ctx : Context; data : void?; size : uint64; tempString : bool, at : LineInfo) : void { - let str = escape(unsafe(reinterpret data)) - print("{ctx} {ctx.name} : allocate string (temp:{tempString}) {intptr(data)} '{str}' of length {size} bytes at {describe(at)}\n") - } - def override onFreeString(var ctx : Context; data : void?; tempString : bool, at : LineInfo) : void { - let str = escape(unsafe(reinterpret data)) - print("{ctx} {ctx.name} : free string (temp:{tempString}) {intptr(data)} `{str}` at {describe(at)}\n") - } -} - -[export] -def debug_agent(ctx : Context) { - assert(this_context().category.debug_context) - install_new_thread_local_debug_agent(new SampleDebugAgent()) -} - -struct Foo { - a : int -} - -[export] -def main { - fork_debug_agent_context(@@debug_agent) - instrument_context_allocations(this_context(), true) - var i = 0 - i ++ - var a = "hello {i} world" - print("a = {a}\n") - i ++ - var b = "hello {i} world N2" - print("b = {b}\n") - var arr : array - for (j in range(100)) { - arr |> push(j) - } - delete arr - var p = new Foo(uninitialized) - unsafe { - delete p - } -} - - - diff --git a/examples/test/misc/any_alg.das b/examples/test/misc/any_alg.das deleted file mode 100644 index b2ffcea6e6..0000000000 --- a/examples/test/misc/any_alg.das +++ /dev/null @@ -1,20 +0,0 @@ -options gen2 -require daslib/algorithm - -[export] -def main { - var a <- [for (x in range(10)); x] - var b : int[10] - for (A, B in a, b) { - B = A - } - print("a={a} b={b}\n") - - let lba = lower_bound(a, 5) - let lbb = lower_bound(b, 5) - - print("lba(5)={lba} lbb(5)={lbb}\n") - - let lba2 = lower_bound(b, 5) <| $(x, y : int) { return x < y; } - print("lba2(5)={lba2}\n") -} diff --git a/examples/test/misc/aot_dummy.das b/examples/test/misc/aot_dummy.das deleted file mode 100644 index bf76e2a7d8..0000000000 --- a/examples/test/misc/aot_dummy.das +++ /dev/null @@ -1,6 +0,0 @@ -options gen2 -[export] -def test { - return true -} - diff --git a/examples/test/misc/apply_in_context_example.das b/examples/test/misc/apply_in_context_example.das deleted file mode 100644 index 7d23944b31..0000000000 --- a/examples/test/misc/apply_in_context_example.das +++ /dev/null @@ -1,30 +0,0 @@ -options gen2 -require daslib/apply_in_context - -require debugapi - -def debug_agent(ctx : Context) { - install_new_debug_agent(new DapiDebugAgent(), "sample") -} - -var num = 13 - -[apply_in_context(sample)] -def get_num(var n : int& implicit) { - debug(n) - n = ++num -} - -[apply_in_context(sample)] -def get_other_num { - return ++num -} - -[export] -def main { - fork_debug_agent_context(@@debug_agent) - var inum = 0 - get_num(inum) - print("num = {num} inum = {inum} other_num = {get_other_num()}\n") -} - diff --git a/examples/test/misc/ast_print.das b/examples/test/misc/ast_print.das deleted file mode 100644 index 2e8e162795..0000000000 --- a/examples/test/misc/ast_print.das +++ /dev/null @@ -1,1087 +0,0 @@ -options gen2 -options rtti = true -// options log_infer_passes = true -options strict_smart_pointers = false -// options log = true - -require ast -require rtti -require daslib/ast_boost -require daslib/strings_boost - -////////// -// example - -let { - function_annotation_flags = ( - (FunctionFlags.fastCall) | - (FunctionFlags.exports) | - (FunctionFlags.privateFunction) | - (FunctionFlags.unsafeDeref) | - (FunctionFlags.unsafeOperation) | - (FunctionFlags._generator)) -} - -// TODO: fixme -def noBracket(expr) { - return false -} - -class PrintVisitor : AstVisitor { - extraTypeInfo : bool = true - printCStyle : bool = true - tab : int = 0 - // TODO: fixme - def newLine() { - print("\n") - } -// program - def override preVisitProgram(prog : ProgramPtr) { - print("// program\n") - } - def override visitProgram(prog : ProgramPtr) { - print("// end program\n") - } - def override preVisitProgramBody(prog : ProgramPtr, mod : Module?) { - print("// program body\n") - } -// type - ET : bool = false - def override preVisitTypeDecl(typ : TypeDeclPtr) { - ET = typ.isExprType - if (ET) { - print("/*[") - } - } - def override visitTypeDecl(typ : TypeDeclPtr) { - if (ET) { - print("]*/") - } - return typ - } -// alias - def override preVisitAlias(typ : TypeDeclPtr, name : das_string) { - print("typedef\n\t{name} = {describe([decl=typ,extra=extraTypeInfo])}\n\n") - } -// enumeration - def override preVisitEnumeration(enu : EnumerationPtr) { - print("enum {enu.name} : {das_to_string(enu.baseType)}\n") - } - def override preVisitEnumerationValue(enu : EnumerationPtr, name : das_string, value : ExpressionPtr, last : bool) { - print("\t{name} =") - } - def override visitEnumerationValue(enu : EnumerationPtr, name : das_string, value : ExpressionPtr, last : bool) { - print("\n") - return value - } - def override visitEnumeration(enu : EnumerationPtr) { - print("\n") - return enu - } -// structure - def override preVisitStructure(str : StructurePtr) { - if (str.annotations |> length != 0) { - print("[{describe(str.annotations)}]\n") - } - print("{str.flags.isClass ? "class" : "struct"} {str.name}\n") - } - def override preVisitStructureField(str : StructurePtr, decl : FieldDeclaration, last : bool) { - print("\t") - if (decl.annotation |> length != 0) { - print("[{describe(decl.annotation)}] ") - } - print("{decl.name} : {describe([decl=decl._type,extra=extraTypeInfo])}") - if (decl.flags.parentType) { - print(" /* from {str.parent.name} */") - } - if (decl.init != null) { - print("{decl.flags.moveSemantics ? " <- " : " = "}") - } - } - def override visitStructureField(str : StructurePtr, decl : FieldDeclaration, last : bool) { - print("\n") - } - def override visitStructure(var str : StructurePtr) : StructurePtr { - print("\n") - return <- str - } -// function - def override preVisitFunction(fun : FunctionPtr) { - if (fun.flags.knownSideEffects) { - if (fun.sideEffectFlags == bitfield(0)) { - print("// [nosideeffects]\n") - } else { - print("// {describe_bitfield(fun.sideEffectFlags)}\n") - } - } - let bfa : FunctionFlags = fun.flags & function_annotation_flags - print("{describe_bitfield(bfa,"\n")}") - if (fun.annotations |> length != 0) { - print("[{describe(fun.annotations)}]\n") - } - print("def {fun.name}") - if (fun.arguments |> length != 0) { - print(" ( ") - } - } - def override preVisitFunctionBody(fun : FunctionPtr, expr : ExpressionPtr) { - if (fun.arguments |> length != 0) { - print(" ) ") - } - if (fun.result != null && !fun.result.isVoid) { - print(" : {describe([decl=fun.result,extra=extraTypeInfo])}") - } - print("\n") - } - def override visitFunction(var fun : FunctionPtr) : FunctionPtr { - print("\n") - return <- fun - } - def override preVisitFunctionArgument(fun : FunctionPtr, arg : VariablePtr, last : bool) { - if (arg.annotation |> length != 0) { - print("[{describe(arg.annotation)}] ") - } - if (!arg._type.flags.constant) { - print("var ") - } - if (arg.isAccessUnused) { - print(" /*unsued*/ ") - } - print("{arg.name} : {describe([decl=arg._type,extra=extraTypeInfo])}") - } - def override visitFunctionArgument(fun : FunctionPtr, arg : VariablePtr, last : bool) { - if (!last) { - print(" ") - } - return arg - } - def override preVisitFunctionArgumentInit(fun : FunctionPtr, arg : VariablePtr, value : ExpressionPtr) { - print(" = ") - } -// block - def override preVisitExprBlock(blk : smart_ptr) { - if (blk.blockFlags.isClosure) { - if (blk.returnType != null || blk.arguments |> length != 0) { - print("$(") - for (arg, argIndex in blk.arguments, range(blk.arguments |> length)) { - if (arg.annotation |> length != 0) { - print("[{describe(arg.annotation)}] ") - } - if (arg._type.flags.constant) { - print("var ") - } - print("{arg.name} : {describe([decl=arg._type,extra=extraTypeInfo])}") - if (argIndex != blk.arguments |> length - 1) { - print(" ") - } - } - print(")") - if (blk.returnType != null) { - print(":{describe([decl=blk.returnType,extra=extraTypeInfo])}") - } - print("\n") - } - } - if (printCStyle || blk.blockFlags.isClosure) { - print("{repeat("\t",tab)}\{\n") - } - tab ++ - } - def override visitExprBlock(var blk : smart_ptr) : ExpressionPtr { - tab -- - if (printCStyle || blk.blockFlags.isClosure) { - print("{repeat("\t",tab)}\}\n") - } - return <- blk - } - def override preVisitExprBlockExpression(blk : smart_ptr, expr : ExpressionPtr) { - print("{repeat("\t",tab)}") - } - def override visitExprBlockExpression(blk : smart_ptr, expr : ExpressionPtr) { - if (printCStyle || blk.blockFlags.isClosure) { - print("") - } - self->newLine() - return expr - } - def override visitExprBlockFinal(blk : smart_ptr) { - if (printCStyle || blk.blockFlags.isClosure) { - print("{repeat("\t",tab-1)}\} finally \{\n") - } else { - print("{repeat("\t",tab-1)}finally\n") - } - } - def override preVisitExprBlockFinalExpression(blk : smart_ptr, expr : ExpressionPtr) { - print("{repeat("\t",tab)}") - } - def override visitExprBlockFinalExpression(blk : smart_ptr, expr : ExpressionPtr) { - if (printCStyle || blk.blockFlags.isClosure) { - print("") - } - self->newLine() - return expr - } -// let - def override preVisitExprLet(expr : smart_ptr) { - var isLet = true - for (pv in expr.variables) { - if (pv._type != null && pv._type.flags.constant) { - isLet = false - break - } - } - print("{isLet ? "let" : "var"} ") - } - def override preVisitExprLetVariable(expr : smart_ptr, arg : VariablePtr, lastArg : bool) { - if (arg.isAccessUnused) { - print(" /*unused*/ ") - } - print("{arg.name} : {describe([decl=arg._type,extra=extraTypeInfo])}") - } - def override visitExprLetVariable(expr : smart_ptr, arg : VariablePtr, lastArg : bool) { - if (!lastArg) { - print("") - } - return arg - } - def override preVisitExprLetVariableInit(blk : smart_ptr, arg : VariablePtr, expr : ExpressionPtr) { - if (arg.flags.init_via_move) { - print(" <- ") - } elif (arg.flags.init_via_clone) { - print(" := ") - } else { - print(" = ") - } - } -// global let - def override preVisitGlobalLetVariable(arg : VariablePtr, lastArg : bool) { - print("{arg._type.flags.constant ? "let" : "var"}{arg.flags.global_shared ? " shared" : ""}\n\t") - if (arg.isAccessUnused) { - print(" /*unused*/ ") - } - print("{arg.name} : {describe([decl=arg._type,extra=extraTypeInfo])}") - } - def override visitGlobalLetVariable(arg : VariablePtr, lastArg : bool) { - print("\n\n") - return arg - } - def override preVisitGlobalLetVariableInit(arg : VariablePtr, expr : ExpressionPtr) { - if (arg.flags.init_via_move) { - print(" <- ") - } elif (arg.flags.init_via_clone) { - print(" := ") - } else { - print(" = ") - } - } -// string builder - def override preVisitExprStringBuilder(expr : smart_ptr) { - print("string_builder(") - } - def override visitExprStringBuilder(var expr : smart_ptr) : ExpressionPtr { - print(")") - return <- expr - } - def override visitExprStringBuilderElement(expr : smart_ptr, elem : ExpressionPtr, last : bool) { - if (!last) { - print(",") - } - return elem - } -// new - def override preVisitExprNew(expr : smart_ptr) { - print("new {describe(expr.typeexpr)}") - if (expr.initializer) { - print("(") - } - } - def override visitExprNew(var expr : smart_ptr) : ExpressionPtr { - if (expr.initializer) { - print(")") - } - return <- expr - } - def override visitExprNewArgument(expr : smart_ptr, arg : ExpressionPtr, last : bool) { - if (!last) { - print(",") - } - return arg - } -// named call - def override preVisitExprNamedCall(expr : smart_ptr) { - print("{expr.name}([") - } - def override visitExprNamedCall(var expr : smart_ptr) : ExpressionPtr { - print("])") - return <- expr - } - def override preVisitExprNamedCallArgument(expr : smart_ptr, arg : MakeFieldDeclPtr, last : bool) { - print("{arg.name}{arg.flags.moveSemantics ? "<-" : "="}") - } - def override visitExprNamedCallArgument(expr : smart_ptr, arg : MakeFieldDeclPtr, last : bool) { - if (!last) { - print(",") - } - return arg - } -// looks like call (debug,assert,verify,erase,find,key_exists,keys,values,invoke,memzero etc) - def override preVisitExprLooksLikeCall(expr : smart_ptr) { - print("{expr.name}(") - } - def override visitExprLooksLikeCall(var expr : smart_ptr) : ExpressionPtr { - print(")") - return <- expr - } - def override visitExprLooksLikeCallArgument(expr : smart_ptr, arg : ExpressionPtr, last : bool) { - if (!last) { - print(",") - } - return arg - } -// call - def override preVisitExprCall(expr : smart_ptr) { - print("{expr.name}(") - } - def override visitExprCall(var expr : smart_ptr) : ExpressionPtr { - print(")") - return <- expr - } - def override visitExprCallArgument(expr : smart_ptr, arg : ExpressionPtr, last : bool) { - if (!last) { - print(",") - } - return arg - } -// null coaelescing - def override preVisitExprNullCoalescingDefault(expr : smart_ptr, defval : ExpressionPtr) { - print(" ?? ") - } -// at - def override visitExprAt(var expr : smart_ptr) : ExpressionPtr { - print("]") - return <- expr - } - def override preVisitExprAtIndex(expr : smart_ptr, index : ExpressionPtr) { - print("[") - } -// safe at - def override visitExprSafeAt(var expr : smart_ptr) : ExpressionPtr { - print("]") - return <- expr - } - def override preVisitExprSafeAtIndex(expr : smart_ptr, index : ExpressionPtr) { - print("?[") - } -// is - def override preVisitExprIsType(expr : smart_ptr, typeDecl : TypeDeclPtr) { - print("is type<{describe([decl=typeDecl,extra=false,contracts=true])}>") - } -// op2 - def override preVisitExprOp2(expr : smart_ptr) { - if (!noBracket(expr)) { - print("(") - } - } - def override visitExprOp2(var expr : smart_ptr) : ExpressionPtr { - if (!noBracket(expr)) { - print(")") - } - return <- expr - } - def override preVisitExprOp2Right(expr : smart_ptr, right : ExpressionPtr) { - print(" {expr.op} ") - } -// op3 - def override preVisitExprOp3(expr : smart_ptr) { - if (!noBracket(expr)) { - print("(") - } - } - def override visitExprOp3(var expr : smart_ptr) : ExpressionPtr { - if (!noBracket(expr)) { - print(")") - } - return <- expr - } - def override preVisitExprOp3Left(expr : smart_ptr, left : ExpressionPtr) { - print(" ? ") - } - def override preVisitExprOp3Right(expr : smart_ptr, right : ExpressionPtr) { - print(" : ") - } -// copy - def override preVisitExprCopyRight(expr : smart_ptr, right : ExpressionPtr) { - print(" = ") - } -// move - def override preVisitExprMoveRight(expr : smart_ptr, right : ExpressionPtr) { - print(" <- ") - } -// clone - def override preVisitExprCloneRight(expr : smart_ptr, right : ExpressionPtr) { - print(" := ") - } -// with - def override preVisitExprWith(expr : smart_ptr) { - print("with ") - } - def override preVisitExprWithBody(expr : smart_ptr, right : ExpressionPtr) { - print("\n") - } -// while - def override preVisitExprWhile(expr : smart_ptr) { - print("while ") - } - def override preVisitExprWhileBody(expr : smart_ptr, right : ExpressionPtr) { - print("\n") - } -// try-catch - def override preVisitExprTryCatch(expr : smart_ptr) { - print("try\n") - } - def override preVisitExprTryCatchCatch(expr : smart_ptr, right : ExpressionPtr) { - print("{repeat("\t",tab)}recover\n") - } -// if-then-else - def override preVisitExprIfThenElse(expr : smart_ptr) { - print("if ") - } - def override preVisitExprIfThenElseIfBlock(expr : smart_ptr, ifBlock : ExpressionPtr) { - print("\n") - } - def override preVisitExprIfThenElseElseBlock(expr : smart_ptr, elseBlock : ExpressionPtr) { - print("{repeat("\t",tab)}") - if (elseBlock.__rtti == "ExprIfThenElse") { - print("else ") - } else { - print("else\n") - } - } -// for - def override preVisitExprFor(expr : smart_ptr) { - print("for ") - } - def override preVisitExprForVariable(expr : smart_ptr, svar : VariablePtr, last : bool) { - print("{svar.name}{last ? " in " : ","}") - } - def override visitExprForSource(var expr : smart_ptr, var source : ExpressionPtr, last : bool) : ExpressionPtr { - if (!last) { - print(",") - } - return <- source - } - def override preVisitExprForBody(expr : smart_ptr) { - print("\n") - } -// make variant - def override preVisitExprMakeVariant(expr : smart_ptr) { - print("[[") - if (expr._type != null) { - print("{describe(expr._type)} ") - } - } - def override visitExprMakeVariant(var expr : smart_ptr) : ExpressionPtr { - print("]]") - return <- expr - } - def override preVisitExprMakeVariantField(expr : smart_ptr, index : int, decl : MakeFieldDeclPtr, last : bool) { - print("{decl.name} {decl.flags.moveSemantics ? "<-" : "=" } ") - } - def override visitExprMakeVariantField(expr : smart_ptr, index : int, decl : MakeFieldDeclPtr, last : bool) { - if (!last) { - print(" ") - } - return decl - } -// make structure - def override preVisitExprMakeStruct(expr : smart_ptr) { - print("[[") - if (expr._type != null) { - print("{describe(expr._type)}{expr.makeStructFlags.useInitializer ? "()" : ""} ") - } - } - def override visitExprMakeStruct(var expr : smart_ptr) : ExpressionPtr { - print("]]") - return <- expr - } - def override visitExprMakeStructIndex(expr : smart_ptr, index : int, last : bool) { - if (!last) { - print(" ") - } - } - def override preVisitExprMakeStructField(expr : smart_ptr, index : int, decl : MakeFieldDeclPtr, last : bool) { - print("{decl.name} {decl.flags.moveSemantics ? "<-" : "=" } ") - } - def override visitExprMakeStructField(expr : smart_ptr, index : int, decl : MakeFieldDeclPtr, last : bool) { - if (!last) { - print(", ") - } - return decl - } -// make array - def override preVisitExprMakeArray(expr : smart_ptr) { - print("[[") - if (expr._type != null) { - print("{describe(expr._type)} ") - } - } - def override visitExprMakeArray(var expr : smart_ptr) : ExpressionPtr { - print("]]") - return <- expr - } - def override visitExprMakeArrayIndex(expr : smart_ptr, index : int, var init : ExpressionPtr, last : bool) : ExpressionPtr { - if (!last) { - print(" ") - } - return <- init - } -// make tuple - def override preVisitExprMakeTuple(expr : smart_ptr) { - print("[[") - if (expr._type != null) { - print("{describe(expr._type)} ") - } - } - def override visitExprMakeTuple(var expr : smart_ptr) : ExpressionPtr { - print("]]") - return <- expr - } - def override visitExprMakeTupleIndex(expr : smart_ptr, index : int, var init : ExpressionPtr, last : bool) : ExpressionPtr { - if (!last) { - print(", ") - } - return <- init - } -// array comprehension - def override preVisitExprArrayComprehension(expr : smart_ptr) { - print("{expr.generatorSyntax ? "[[" : "[\{"}") - } - def override visitExprArrayComprehension(var expr : smart_ptr) : ExpressionPtr { - print("{expr.generatorSyntax ? "]]" : "\}]"}") - return <- expr - } - def override preVisitExprArrayComprehensionSubexpr(expr : smart_ptr, subexrp : ExpressionPtr) { - print(" ") - } - def override preVisitExprArrayComprehensionWhere(expr : smart_ptr, filter : ExpressionPtr) { - print(" where ") - } -// type info - def override preVisitExprTypeInfo(expr : smart_ptr) { - print("typeinfo({expr.trait}") - if (!empty(expr.subtrait)) { - print("<{expr.subtrait}") - if (!empty(expr.extratrait)) { - print("{expr.extratrait}") - } - } - print(">") - if (expr.subexpr == null) { - print("type<{describe(expr.typeexpr)}>") - } - } - def override visitExprTypeInfo(var expr : smart_ptr) : ExpressionPtr { - print(")") - return <- expr - } -// ptr to ref - def override preVisitExprPtr2Ref(expr : smart_ptr) { - print("deref(") - } - def override visitExprPtr2Ref(var expr : smart_ptr) : ExpressionPtr { - print(")") - return <- expr - } -// label - def override preVisitExprLabel(expr : smart_ptr) { - print("label {expr.labelName}:") - if (!empty(expr.comment)) { - print("/*{expr.comment}*/") - } - } -// goto - def override preVisitExprGoto(expr : smart_ptr) { - print("goto ") - if (expr.subexpr == null) { - print("label {expr.labelName}") - } - } -// ref to value - def override preVisitExprRef2Value(expr : smart_ptr) { - print("/*r2v*/ (") - } - def override visitExprRef2Value(var expr : smart_ptr) : ExpressionPtr { - print(")") - return <- expr - } -// ref 2 ptr - def override preVisitExprRef2Ptr(expr : smart_ptr) { - print("addr(") - } - def override visitExprRef2Ptr(var expr : smart_ptr) : ExpressionPtr { - print(")") - return <- expr - } -// @@ - def override preVisitExprAddr(expr : smart_ptr) { - print("@@") - if (expr.funcType != null) { - print("<{describe(expr.funcType)}>") - } - print("{expr.target}") - } -// ascend - def override preVisitExprAscend(expr : smart_ptr) { - if (expr.ascType != null) { - print("new<{describe(expr.ascType)}> ") - } else { - print("new ") - } - } -// cast - def override preVisitExprCast(expr : smart_ptr) { - if (expr.castFlags.reinterpretCast) { - print("reinterpret") - } elif (expr.castFlags.upcastCast) { - print("upcast") - } else { - print("cast") - } - print("<{describe(expr.castType)}> ") - } -// delete - def override preVisitExprDelete(expr : smart_ptr) { - print("delete ") - if (expr.native) { - print("/*native*/ ") - } - } -// var - def override preVisitExprVar(expr : smart_ptr) { - print("{expr.name}") - } -// field - def override visitExprField(var expr : smart_ptr) : ExpressionPtr { - print(".{expr.name}") - return <- expr - } -// safe field - def override visitExprSafeField(var expr : smart_ptr) : ExpressionPtr { - print("?.{expr.name}") - return <- expr - } -// swizzle - def override visitExprSwizzle(var expr : smart_ptr) : ExpressionPtr { - print(".") - let f2name = fixed_array("x", "y", "z", "w") - for (fch in expr.fields) { - let f = int(fch) - print("{f>=0 && f<=3 ? f2name[f] : "?"}") - } - return <- expr - } -// is variant - def override visitExprIsVariant(var expr : smart_ptr) : ExpressionPtr { - print(" is {expr.name}") - return <- expr - } -// as variant - def override visitExprAsVariant(var expr : smart_ptr) : ExpressionPtr { - print(" as {expr.name}") - return <- expr - } -// safe as variant - def override visitExprSafeAsVariant(var expr : smart_ptr) : ExpressionPtr { - print(" ?as {expr.name}") - return <- expr - } -// op1 - def override preVisitExprOp1(expr : smart_ptr) : void { - let op = "{expr.op}" - if (op != "+++" && op != "---") { - print(op) - } - if (!noBracket(expr)) { - print("(") - } - } - def override visitExprOp1(var expr : smart_ptr) : ExpressionPtr { - let op = "{expr.op}" - if (!noBracket(expr)) { - print(")") - } - if (op == "+++" || op == "---") { - print("{slice(op,0,-1)}") - } - return <- expr - } -// return - def override preVisitExprReturn(expr : smart_ptr) : void { - print("return ") - if (expr.returnFlags.fromYield) { - print("/* from yield */ ") - } - if (expr.returnFlags.moveSemantics) { - print("<- ") - } - } -// yield - def override preVisitExprYield(expr : smart_ptr) : void { - print("yield ") - if (expr.returnFlags.moveSemantics) { - print("<- ") - } - } -// break - def override preVisitExprBreak(expr : smart_ptr) : void { - print("break") - } -// continue - def override preVisitExprContinue(expr : smart_ptr) : void { - print("continue") - } -// const ptr - def override preVisitExprConstPtr(expr : smart_ptr) : void { - print("{expr.value}") - } -// const int 8 - def override preVisitExprConstInt8(expr : smart_ptr) : void { - print("{expr.value}") - } -// const int 16 - def override preVisitExprConstInt16(expr : smart_ptr) : void { - print("{expr.value}") - } -// const int 64 - def override preVisitExprConstInt64(expr : smart_ptr) : void { - print("{expr.value}") - } -// const int - def override preVisitExprConstInt(expr : smart_ptr) : void { - print("{expr.value}") - } -// const int2 - def override preVisitExprConstInt2(expr : smart_ptr) : void { - print("int2({expr.value})") - } -// const int3 - def override preVisitExprConstInt3(expr : smart_ptr) : void { - print("int3({expr.value})") - } -// const int4 - def override preVisitExprConstInt4(expr : smart_ptr) : void { - print("int4({expr.value})") - } -// const uint 8 - def override preVisitExprConstUInt8(expr : smart_ptr) : void { - print("{expr.value}") - } -// const uint 16 - def override preVisitExprConstUInt16(expr : smart_ptr) : void { - print("{expr.value}") - } -// const uint 64 - def override preVisitExprConstUInt64(expr : smart_ptr) : void { - print("{expr.value}") - } -// const uint - def override preVisitExprConstUInt(expr : smart_ptr) : void { - print("{expr.value}") - } -// const uint2 - def override preVisitExprConstUInt2(expr : smart_ptr) : void { - print("uint2({expr.value})") - } -// const uint3 - def override preVisitExprConstUInt3(expr : smart_ptr) : void { - print("uint3({expr.value})") - } -// const uint4 - def override preVisitExprConstUInt4(expr : smart_ptr) : void { - print("uint4({expr.value})") - } -// const range - def override preVisitExprConstRange(expr : smart_ptr) : void { - print("range({expr.value})") - } -// const urnage - def override preVisitExprConstURange(expr : smart_ptr) : void { - print("urange({expr.value})") - } -// const range - def override preVisitExprConstRange64(expr : smart_ptr) : void { - print("range64({expr.value})") - } -// const urnage - def override preVisitExprConstURange64(expr : smart_ptr) : void { - print("urange64({expr.value})") - } -// const bool - def override preVisitExprConstBool(expr : smart_ptr) : void { - print("{expr.value}") - } -// const float - def override preVisitExprConstFloat(expr : smart_ptr) : void { - print("{expr.value}") - } -// const float2 - def override preVisitExprConstFloat2(expr : smart_ptr) : void { - print("float2({expr.value})") - } -// const float3 - def override preVisitExprConstFloat3(expr : smart_ptr) : void { - print("float3({expr.value})") - } -// const float4 - def override preVisitExprConstFloat4(expr : smart_ptr) : void { - print("float4({expr.value})") - } -// const double - def override preVisitExprConstDouble(expr : smart_ptr) : void { - print("{expr.value}lf") - } -// fake context - def override preVisitExprFakeContext(expr : smart_ptr) : void { - print("__context__") - } -// fake line info - def override preVisitExprFakeLineInfo(expr : smart_ptr) : void { - print("__lineinfo__") - } -// string - def override preVisitExprConstString(expr : smart_ptr) : void { - peek(expr.value) <| $(str) { - print("\"{escape(str)}\"") - } - } -// const enumeraiton - def override preVisitExprConstEnumeration(expr : smart_ptr) : void { - let enumModule = expr.enumType._module - if (enumModule != null && !empty(enumModule.name)) { - print("{enumModule.name}::") - } - print("{expr.enumType.name} {expr.value}") - } -// const bitfield - def override preVisitExprConstBitfield(expr : smart_ptr) : void { - var name : string - if (expr.bitfieldType != null && !empty(expr.bitfieldType.alias)) { - name = find_bitfield_name(expr.bitfieldType, expr.value) - } - if (!empty(name)) { - print("{expr.bitfieldType.alias} {name}") - } else { - print("bitfield({expr.value})") - } - } -} - -typedef Integer = int -typedef IorF = variant - - -enum FooBar { - Foo - Bar = 13 -} - - -[comment(x=5, msg="haha")] -struct Foo { - @do_not_delete@temp = 13 a : int = 11 - b : array -} - -def Foo(x : int) { - return <- Foo(a = x) -} - -def Foo(x, y : int) { - return <- Foo(a = x + y) -} - -var { - add_extra = 13 -} - -[sideeffects] -def add(a, b : int) { - print("a={a} b={b}") - return a + b + add_extra -} - -[sideeffects, export] -def allExpr(arg : int) { - // ExprStringBuilder - var sb = "arg = {arg}\n" - sb = "" - // ExprNamedCall - add([a=1, b=2]) - add(3, 4, [a=1, b=2]) - // ExprNew - var pFoo1 = new Foo - var pFoo2 = new Foo(1) - var pFoo3 = new Foo(1, 2) - // ExprCall - add(1, 2) - // ExprNullCoalescing - var exprAt <- pFoo1 ?? Foo(a = 1) - exprAt <- Foo(a = 2) - // ExprAt - pFoo1.b[0] = pFoo2 - // ExprSafeAt - var exprSafeAt = pFoo1.b?[0] ?? pFoo2 - exprSafeAt = pFoo2 - // ExprIs - if (exprAt is type) { - print("nada\n") - } - // ExprOp2 - var aa = 1 - aa = 3 - var bb = 2 - bb = 4 - var cc = aa + bb - // ExprOp3 - cc = aa == bb ? aa : bb - // ExprWith - with (exprAt) { - aa = 3 - } - // ExprWhile - while (aa != 100) { - aa++ - } - // ExprTryRecover - try { - aa = 2 - } recover { - aa = 3 - } - // ExprIfThenElse - if (aa == 2) { - aa = 2 - } - if (aa == 2) { - aa = 2 - } else { - aa = 3 - } - if (aa == 2) { - aa = 2 - } elif (aa == 3) { - aa = 3 - } else { - aa = 4 - } - // ExprMakeVariant - var mkv = IorF(i = 5) - mkv = IorF(f = 1.0) - // ExprMakeStruct - var mks <- [Foo(a=5, b <- array(null)), Foo(a = 6)] - mks[1] <- Foo(a = 5) - // ExprMakeArray - var mka = fixed_array(1, 2, 3, 4) - mka = fixed_array(5, 6, 7, 8) - // ExprMakeTuple - var mkt = (1, 2.0, "three") - mkt = (2, 3.0, "four") - // ExprArrayCompehension - var acomp <- [for (x in range(3)); x * x; where x != 1] - var gcomp <- [iterator for(x in range(3)); x * x; where x != 1] - for (ta, tg in acomp, gcomp) { - verify(ta == tg) - } - // ExprTypeInfo - var tinfo = typeinfo rtti_typeinfo(type).basicType - print("{tinfo}\n") - // ExprPtr2Ref - print("{*pFoo1}") - // ExprLabel, ExprGoto - goto label 1 - print("nop") - label 1: - // ExprRef2Ptr - unsafe { - let aacomp = addr(acomp) - print("{aacomp}") - } - // ExprAddr - let eaddr = @@add - print("{eaddr}") - // ExprAssert, ExprStaticAssert - assert(aa == 4, "assert here") - verify(aa == 4, "verify here") - static_assert(true, "static assert here") - concept_assert(true, "concept assert here") - // ExprDebug - debug(aa) - // ExprInvoke - let atadd = @@add - invoke(atadd, 1, 2) - // ExprErase - var tab <- { 1 => "one", 2 => "two" } - erase(tab, 1) - // ExprFind - get(tab, 2) <| $(argX) { - print("{argX}") - } - // ExprKeyExists - assert(key_exists(tab, 2)) - // ExprAscend - let easc = new fixed_array(1, 2, 3, 4) - print("{easc}") - // ExprCast - unsafe { - let aaf = reinterpret aa - print("{aaf}") - } - // ExprDelete - unsafe { - delete pFoo1 - } - // ExprSwizzle - var fsw = float4(1, 2, 3, 4) - fsw = fsw.yyzx - // ExprOp1 - var eop1 = 1 - eop1 ++ - -- eop1 - // ExprMemZero - memzero(eop1) - // ExprConstString - var cstr = "hello\nworld\n" - cstr += "\{..\}" - // ExprConstEnumeration - var enc = Type.none - enc = Type.tInt - // ExprConstBitfield - var bfc = ExprPrintFlags.topLevel - bfc = ExprPrintFlags.argLevel -} - -[export] -def test { - var astVisitor = new PrintVisitor() - var astVisitorAdapter <- make_visitor(*astVisitor) - visit(this_program(), astVisitorAdapter) - -/* - // ast_typedecl - add_extra = 14 - let td <- typeinfo(ast_typedecl type) - print("td = {describe(td)}\n") - // ast_expression - var x = 1 - var y = 2 - x = 3 - y = 4 - let ed <- quote(x+y) - print("ed = {describe(ed)}\n") - // ast_function - let fd <- typeinfo(ast_function @@add) - print("fd = {describe(fd)}\n") -*/ - - return true -} diff --git a/examples/test/misc/ast_print_named_call.das b/examples/test/misc/ast_print_named_call.das deleted file mode 100644 index a44ce5127b..0000000000 --- a/examples/test/misc/ast_print_named_call.das +++ /dev/null @@ -1,13 +0,0 @@ -options gen2 -options log = true, log_infer_passes = true -require daslib/contracts - -def test(a : int = 1; b : int) { - print("{a},{b}\n") -} - -[export] -def main { - test([a=1, b=2]) - test(3, 4, [a=1, b=2]) -} diff --git a/examples/test/misc/b.das b/examples/test/misc/b.das deleted file mode 100644 index 504329a04a..0000000000 --- a/examples/test/misc/b.das +++ /dev/null @@ -1,15 +0,0 @@ -options gen2 -module b - -struct Foo { - t : table -} - -struct P { - iV : int - t : table -} - -var { - p : P -} \ No newline at end of file diff --git a/examples/test/misc/check_type_info.das b/examples/test/misc/check_type_info.das deleted file mode 100644 index a404afa099..0000000000 --- a/examples/test/misc/check_type_info.das +++ /dev/null @@ -1,29 +0,0 @@ -options gen2 -require UnitTest - -require rtti -require ast - -def log_type(t : auto(TT)?) { - print(" - {typeinfo typename(type)}: - isLocal = {typeinfo is_local(type)} - canBePlacedInContainer = {typeinfo can_be_placed_in_container(type)} - canCopy = {typeinfo can_copy(type)} - canMove = {typeinfo can_move(type)} - canClone = {typeinfo can_clone(type)} - canDelete = {typeinfo can_delete(type)} - canNew = {typeinfo can_new(type)} - canDeletePtr = {typeinfo can_delete_ptr(type)} - hasNonTrivialCtor = {typeinfo has_nontrivial_ctor(type)} - hasNonTrivialDtor = {typeinfo has_nontrivial_dtor(type)} - hasNonTrivialCopy = {typeinfo has_nontrivial_copy(type)} - ") -} - -[export] -def test { - var m : FileAccess? - log_type(m) - return true -} diff --git a/examples/test/misc/clone_to_field_set.das b/examples/test/misc/clone_to_field_set.das deleted file mode 100644 index 94d579267a..0000000000 --- a/examples/test/misc/clone_to_field_set.das +++ /dev/null @@ -1,30 +0,0 @@ -options gen2 -struct Box { - min, max : float2 -} - -def operator . center(var self : Box) { - return (self.min + self.max) * 0.5 -} - -def operator . size(var self : Box) { - return self.max - self.min -} - -def operator . center :=(var self : Box; at : float2) { - var size = self.size - self.min = at - size * 0.5 - self.max = at + size * 0.5 -} - -[export] -def main { - var box = Box(min = float2(-1, -1), max = float2(1, 1)) - print("box = {box}\n") - print("box.center = {box.center}\n") - box.center := float2(2, 2) - print("box = {box}\n") - print("box.center = {box.center}\n") -} - - diff --git a/examples/test/misc/clone_value_type.das b/examples/test/misc/clone_value_type.das deleted file mode 100644 index b3395c8ef7..0000000000 --- a/examples/test/misc/clone_value_type.das +++ /dev/null @@ -1,21 +0,0 @@ -options gen2 -require UnitTest - -def create_scene_node() : SceneNodeId { - return __create_scene_node() -} - -[export] -def main { - print("hello world\n") - var node := create_scene_node() - print("node = {node}\n") - node = create_scene_node() - print("node = {node}\n") - node := create_scene_node() - print("node = {node}\n") -} - - -options log_nodes - diff --git a/examples/test/misc/const_ptr_checks.das b/examples/test/misc/const_ptr_checks.das deleted file mode 100644 index 30f3c66a75..0000000000 --- a/examples/test/misc/const_ptr_checks.das +++ /dev/null @@ -1,64 +0,0 @@ -options relaxed_pointer_const = false - -struct Foo - a : int - -struct Bar - a : Foo? - -struct Boo - a : Far? - b : array - -variant Far - a : Foo? - -tuple Tup - a : Foo ? - -[export] -def test_copy_and_clone - var a : Bar? - let b : Bar? - a := b - a = b - var c = b - debug(c) - -def new_const_foo : Foo ? const - return new Foo() - -struct Goo - a : Foo? = new_const_foo() - -var A : Foo? = new_const_foo() - -def get_foo : Foo ? - let a = new Foo() - return a - -[export] -def test_make_variant - var t = Far(a = new_const_foo()) - -[export] -def test_make_struct - var t = Bar(a = new_const_foo()) - -[export] -def test_make_tuple - var t = Tup(a = new_const_foo()) - -[export] -def test_complex_types - var a : Bar - let b : Bar - a = b - a := b - -[export] -def test_clone_complex_types - var a : Bar - let b : Bar - a := b - diff --git a/examples/test/misc/constexpr_example.das b/examples/test/misc/constexpr_example.das deleted file mode 100644 index 5a598cc241..0000000000 --- a/examples/test/misc/constexpr_example.das +++ /dev/null @@ -1,17 +0,0 @@ -options gen2 -options log - -require daslib/constant_expression - -[constexpr(a)] -def foo(t : string; a : int) { - print("{t} = {a}\n") -} - -var BOO = 13 - -[export] -def main { - foo("blah", 1) - foo("ouch", BOO) -} diff --git a/examples/test/misc/context_state_example.das b/examples/test/misc/context_state_example.das deleted file mode 100644 index 69dfd6ed41..0000000000 --- a/examples/test/misc/context_state_example.das +++ /dev/null @@ -1,134 +0,0 @@ -options gen2 -options debugger = true - -require rtti -require debugapi - -// sample of debug agent - -class SampleStackWalker : DapiStackWalker { - def override onCallAOT(pp : Prologue; fileName : string#) : void { - print("AOT {fileName}\n") - } - def override onCallJIT(pp : Prologue; fileName : string#) : void { - print("JIT {fileName}\n") - } - def override onCallAt(pp : Prologue; info : FuncInfo; at : LineInfo) : void { - print("{info.name} at {at}\n") - } - def override onCall(pp : Prologue; info : FuncInfo) : void { - print("{info.name}\n") - } - def override onArgument(info : FuncInfo; index : int; vinfo : VarInfo; arg : float4) : void { - print("\targ {vinfo.name} ") - print(sprint_data(arg, type_info(vinfo), print_flags.singleLine)) - print("\n") - } - def override onVariable(inf : FuncInfo; vinfo : LocalVariableInfo; arg : void?; inScope : bool) : void { - print("\tvar {vinfo.name} ") - if (inScope) { - if (arg != null) { - print(sprint_data(arg, type_info(vinfo), print_flags.singleLine)) - } else { - print("optimized out") - } - } else { - print("out of scope") - } - print("\n") - } -} - -class SampleDebugAgent : DapiDebugAgent { - walker_adapter : smart_ptr - walker : SampleStackWalker? - def SampleDebugAgent { - walker = new SampleStackWalker() - unsafe { - walker_adapter <- make_stack_walker(walker) - } - } - def operator delete { - unsafe { - delete walker_adapter - delete walker - } - } - def override onBreakpoint(var ctx : Context; at : LineInfo; reason, text : string) : void { - print("{ctx} {ctx.name} : breakpoint at line {int(at.line)}, {reason}, {text}\n") - collect_debug_agent_state(ctx, at) - set_single_step(ctx, true) - } - def override onSingleStep(var ctx : Context; at : LineInfo) : void { - print("{ctx} {ctx.name} : step at {int(at.line)}\n") - collect_debug_agent_state(ctx, at) - walk_stack(walker_adapter, ctx, at) - } - def override onVariable(var ctx : Context; category, name : string; info : TypeInfo; data : void?) : void { - unsafe { - let value = sprint_data(data, addr(info), print_flags.singleLine) - print("reported {category}:{name} = {value}\n") - } - } -} - -[export] -def debug_agent(ctx : Context) { - assert(this_context().category.debug_context) - install_new_debug_agent(new SampleDebugAgent(), "debug") -} - -def report_to_debugger(var ctx : Context; category, name : string; value : auto(TT)) { - unsafe { - let tinfo = typeinfo rtti_typeinfo(value) - let pdata = addr(value) - print("send {category} {name}\n") - debug(tinfo) - report_context_state(ctx, category, name, addr(tinfo), pdata) - } -} - -class ContextStateAgent : DapiDebugAgent { - def override onCollect(var ctx : Context, at : LineInfo) : void { - let sdepth = stack_depth(ctx) - print("onCollect, sending depth {sdepth}\n") - report_to_debugger(ctx, "Context info", "Stack depth", sdepth) - var foo : array - for (x in range(5)) { - foo |> push((x & 1) != 0) - } - report_to_debugger(ctx, "Context info", "Random foo", foo) - var bar : bool[4] - report_to_debugger(ctx, "Context info", "Random bar", bar) - } -} - -[export] -def context_state_agent(ctx : Context) { - print("insall debug agent - context goo\n") - assert(this_context().category.debug_context) - install_new_debug_agent(new ContextStateAgent(), "context_state") -} - -def foo(var x : int&) { - x ++ - x ++ -} - -[export] -def main { - this_context().name := "stackwalk main context" - fork_debug_agent_context(@@debug_agent) - fork_debug_agent_context(@@context_state_agent) - var x = 5 - breakpoint() - x = 6 - for (t in range(10)) { - print("x={x} t={t}\n") - x ++ - foo(x) - } - var z = 13 - z ++ -} - diff --git a/examples/test/misc/contracts_example.das b/examples/test/misc/contracts_example.das deleted file mode 100644 index 8aea223089..0000000000 --- a/examples/test/misc/contracts_example.das +++ /dev/null @@ -1,77 +0,0 @@ -options gen2 - -require daslib/contracts -require daslib/safe_addr - -require UnitTest - -[expect_any_vector(blah)] // dasvector`.... or similar C++ types -def print_vec(blah) { - for (i in range(length(blah))) { - print("{blah[i]}\n") - } -} - -[expect_any_vector(blah)] -def print_vec_length(blah : auto(DummyName)) {// note, dummy name here so that we can differentiate from another print_vec_length - print("length(blah) is {length(blah)}\n") -} - -def print_vec_length(blah) { - print("blah is not a vector\n") -} - -[expect_any_array(blah)] // array, [], or dasvector`.... or similar -def print_arr(blah) { - for (i in range(length(blah))) { - print("{blah[i]}\n") - } -} - -[!expect_ref(arg)] -def test_accept_ref(var arg : int) { - print("{typeinfo typename(arg)}\n") -} - -[expect_ref(arg)] -def test_accept_ref(var arg : int&) { - print("{typeinfo typename(arg)}\n") -} - -[expect_pointer(arg)] -def test_accept_pointer(var arg : int?) { - print("{typeinfo typename(arg)}\n") -} - -[export] -def main { - testPoint3Array() <| $(arr) { - print_vec(arr) - print_vec_length(arr) - print_arr(arr) - } - // print_vec(13) - // 30304: no matching functions or generics print_vec ( int const ) - // candidate function: - // print_vec ( blah : auto const ) : auto at hello_world.das:6:4 - // argument blah is expected to be a vector template - var i : int[3] // this one ok, because i is 'any_array' - print_arr(i) - print_vec_length(13) // this one ok, because there is print_vec_length unspecialized - - var a : int - test_accept_ref(a) - test_accept_ref(1) - - var a_ptr : int? = safe_addr(a) - test_accept_pointer(a_ptr) - // test_accept_pointer(1) - // 30304: no matching functions or generics test_accept_pointer ( int const ) - // candidate function: - // test_accept_pointer ( arg : int? -const ) : void at generics.das:13:4 - // invalid argument arg (0). expecting int? -const, passing int const - // pointer types can only add constness - // argument arg is not a pointer, it is int const - - return true -} diff --git a/examples/test/misc/copy_ptr_ctor.das b/examples/test/misc/copy_ptr_ctor.das deleted file mode 100644 index c7a178783f..0000000000 --- a/examples/test/misc/copy_ptr_ctor.das +++ /dev/null @@ -1,17 +0,0 @@ -options gen2 -struct Foo { - a : int - b : float -} - -def Foo(p : Foo?) { - var self := *p - return <- self -} - -[export] -def main { - let a = new Foo(a = 1, b = 2.) - let b = new Foo(a) - print("a={a}\nb={b}\n") -} diff --git a/examples/test/misc/coroutines_example.das b/examples/test/misc/coroutines_example.das deleted file mode 100644 index 7a6df8cc9c..0000000000 --- a/examples/test/misc/coroutines_example.das +++ /dev/null @@ -1,37 +0,0 @@ -options gen2 -require daslib/coroutines - -[coroutine] -def subcr(name : string) { - print("{name} sub 1\n") - co_continue() - print("{name} sub 2\n") - co_continue() - print("{name} sub 3\n") -} - -[coroutine] -def coroutine_example(name : string; count : int) { - print("{name} step 1\n") - co_continue() - print("{name} step 2\n") - co_continue() - co_await <| subcr(name) - co_continue() - print("{name} step 3\n") - for (i in range(3, 3 + count)) { - print("{name} step {i}\n") - co_continue() - } -} - -[export] -def main { - var crs <- [ - coroutine_example("co1", 1), - coroutine_example("co2", 2) - ] - cr_run_all(crs) -} - - diff --git a/examples/test/misc/coroutines_example_2.das b/examples/test/misc/coroutines_example_2.das deleted file mode 100644 index a2af413603..0000000000 --- a/examples/test/misc/coroutines_example_2.das +++ /dev/null @@ -1,52 +0,0 @@ -options gen2 -require daslib/coroutines - -struct Tree { - data : int - left, right : Tree? -} - -let tree = new Tree(data = 5, - left = new Tree(uninitialized data = 1), - right = new Tree(uninitialized data = 7, - right = new Tree(uninitialized data = 10) - ) -); - -[coroutine] -def each_async(tree : Tree?) : int { - if (tree.left != null) { - co_await <| each_async(tree.left) - } - yield tree.data - if (tree.right != null) { - co_await <| each_async(tree.right) - } -} - -def each_async_generator(tree : Tree?) { - return <- generator() <| $() { - if (tree.left != null) { - yeild_from <| each_async_generator(tree.left) - } - yield tree.data - if (tree.right != null) { - yeild_from <| each_async_generator(tree.right) - } - return false - } -} - -[export] -def main { - for (t in each_async_generator(tree)) { - print("{t}\n") - } - - for (t in each_async(tree)) { - print("{t}\n") - } -} - - - diff --git a/examples/test/misc/cpp_gen_2.das b/examples/test/misc/cpp_gen_2.das deleted file mode 100644 index dd5706b3d8..0000000000 --- a/examples/test/misc/cpp_gen_2.das +++ /dev/null @@ -1,134 +0,0 @@ -options gen2 -require fio -require daslib/strings_boost -require daslib/regex_boost - -struct Node { - name : string - text : string - subnodes : array -} - -var ast_verbose = false -var ast_process_verbose = false -var ast_line = 0 -var ast_depth = 0 - -def parse_node(f : FILE const?; header : string; offset : int) { - ast_depth ++ - var node = new Node(uninitialized - text = slice(header, offset) - ) - for (ch, sp in node.text, count()) { - if (ch == ' ' || ch == '\n' || ch == '\r') { - node.name = slice(node.text, 0, sp) - break - } - } - if (node.name == "") { - print("expecting node name at line {ast_line}\n") - panic("expecting node name") - } - if (ast_verbose) { - print("{repeat(" ",ast_depth)} {ast_line} {node.name}\n") - } - while (true) { - let tpos = ftell(f) - let tline = ast_line - let subtext = fgets(f) - ast_line ++ - if (length(subtext) <= offset) { - fseek(f, tpos, seek_set) - ast_line = tline - break - } - let CH = character_at(subtext, offset) - if (CH == '|') {// expecting |- next node - if (character_at(subtext, offset + 1) != '-') { - if (ast_verbose) { - print("expecting - at line {ast_line}\n") - } - panic("expecting -") - } - node.subnodes |> push <| parse_node(f, subtext, offset + 2) - } elif (CH == '`') {// expecting `- next node and done - if (character_at(subtext, offset + 1) != '-') { - if (ast_verbose) { - print("expecting - at line {ast_line}\n") - } - panic("expecting -") - } - node.subnodes |> push <| parse_node(f, subtext, offset + 2) - break - } else { - fseek(f, tpos, seek_set) - ast_line = tline - break - } - } - ast_depth -- - return node -} - -def parse_ast_file(fname : string) { - var offset = 0 - var node : Node? - fopen(fname, "rb") <| $(f) { - if (f != null) { - ast_line = 1 - node = parse_node(f, fgets(f), 0) - } - } - return node -} - -def process_typedef(node : Node?) { - pass -} - -/* -| | |-CXXMethodDecl 0x17612fe54c0 col:6 vprorvd 'void (const Xbyak::Xmm &, const Xbyak::Xmm &, const Xbyak::Operand &)' -| | | |-ParmVarDecl 0x17612fe5330 col:25 used x1 'const Xbyak::Xmm &' -| | | |-ParmVarDecl 0x17612fe53a8 col:40 used x2 'const Xbyak::Xmm &' -| | | |-ParmVarDecl 0x17612fe5420 col:59 used op 'const Xbyak::Operand &' -*/ - -var reg_method_decl <- %regex~CXXMethodDecl 0x[0-9a-z]+\s*\scol:\d+\s(used\s)?(\w+)\s+'(.*)'%% - -def process_method_decl(node : Node?) { - assert(node.name == "CXXMethodDecl") - if (regex_match(reg_method_decl, node.text) != -1) { - - let method = regex_group(reg_method_decl, 1, node.text) - let method_decl = regex_group(reg_method_decl, 3, node.text) - print("method {method} as {method_decl}\n") - } else { - print("UNMATCHED {node.text}") - } -} - -def process_ast(node : Node?) { - ast_depth ++ - if (ast_process_verbose) { - print("{repeat(" ",ast_depth)} {ast_line} {node.name}\n") - } - if (node.name == "TypedefDecl") { - process_typedef(node) - } elif (node.name == "CXXMethodDecl") { - process_method_decl(node) - } else { - for (sn in node.subnodes) { - process_ast(sn) - } - } - ast_depth -- -} - -[export] -def main { - let xbfile = "{get_das_root()}/modules/dasXbyak/src/xbyak.h.ast" - var node = parse_ast_file(xbfile) - print("\n\nAND DONE PARSING\n\n") - process_ast(node) - print("\n\nAND DONE PROCESSING\n\n") -} diff --git a/examples/test/misc/debug_expression_example.das b/examples/test/misc/debug_expression_example.das deleted file mode 100644 index 3af6c6db71..0000000000 --- a/examples/test/misc/debug_expression_example.das +++ /dev/null @@ -1,22 +0,0 @@ -options gen2 -require daslib/ast_boost -require daslib/templates_boost - -[export] -def main { - var inscope q <- qmacro_block <| $() { - let x = 10 - print("x = {x+1}") - if (x != 10) { - assert(x == 10) - } else { - pass - } - return @(a, b : int) { - return a + b - } - } - print(debug_expression(q)) -} - - diff --git a/examples/test/misc/debugger.das b/examples/test/misc/debugger.das deleted file mode 100644 index e2417d464a..0000000000 --- a/examples/test/misc/debugger.das +++ /dev/null @@ -1,60 +0,0 @@ -options gen2 -options debugger = true - -// options log_stack = true - -require strings - -require UnitTest - -// options log = true - -def funC(y : string) { - var j = 13 - j ++ - for (i in range(10)) { - if (i == 3) { - var t = float3(1, 2, 3) - t.y = 11.1 - debug(unsafe(addr(t))) - var tt : float3& = t - tt.x = 1.1 - stackwalk() - } - } - var q = y - q += " before {j}" - // stackwalk() - q += " after" -} - -def invBlock(z, blk) { - invoke(blk, z) -} - -def funB(x : string) { - if (length(x) > 13) { - var brr <- array(1, 2, 3, 4) - push(brr, 13) - return <- brr - } else { - var arr <- array(1, 2, 3, 4) - push(arr, length(x)) - invBlock(x) <| $(copyX : string) { - var letter = 'c' - letter = 12345 - funC("from B {copyX}") - } - return <- arr - } -} - -def funA(a : int; b : string) { - funB("{a} is {b}") -} - -[export] -def test { - funA(1, "one") - return true -} diff --git a/examples/test/misc/dict_pg.das b/examples/test/misc/dict_pg.das deleted file mode 100644 index d654ac62a2..0000000000 --- a/examples/test/misc/dict_pg.das +++ /dev/null @@ -1,52 +0,0 @@ -options gen2 -require fio -require strings - -[export] -def test { - profile(1, "freq dictionary PG") <| $() { - let fname = get_das_root() + "/../pg/pg.txt" - fopen(fname, "rb") <| $(f) { - if (f != null) { - var dict : table - fread(f) <| $(data) { - var offset, length = 0 - for (ch, index in data, count()) { - if (is_alpha(ch)) { - if (length == 0) { - offset = index - } - length ++ - } elif (length != 0) { - unsafe { - var token = chop(data, offset, length) |> to_lower_in_place()// unsafe - dict[token]++ - } - length = 0 - } - } - } - var arr : array> - reserve(arr, length(dict)) - for (k, v in keys(dict), values(dict)) { - push(arr, (k, v)) - } - sort(arr) <| $(a, b) { - return a._1 != b._1 ? a._1 > b._1 : a._0 < b._0 - } - fopen(get_das_root() + "/../pg/das.freq", "wb") <| $(fw) { - if (fw != null) { - for (t in arr) { - var ts = "{t._1} {t._0}\n" - fwrite(fw, ts) - } - } - } - } else { - print("cant open {fname}\n") - } - } - } - return true -} - diff --git a/examples/test/misc/dump_fields.das b/examples/test/misc/dump_fields.das deleted file mode 100644 index d31d9ab42d..0000000000 --- a/examples/test/misc/dump_fields.das +++ /dev/null @@ -1,25 +0,0 @@ -options gen2 -module dump_fields - -require ast -require daslib/ast_boost -require fio - -[structure_macro(name=dump_fields)] -class DumpFields : AstStructureAnnotation { - def override finish(var st : StructurePtr; var group : ModuleGroup; args : AnnotationArgumentList; var errors : das_string) : bool { - print("struct {st.name} \{\n") - for (field in st.fields) { - print("\t{describe_cpp(field._type)} {field.name}") - if (field.init != null) { - print(" = {describe(field.init)}") - } - print(";\n") - } - print("\}\n\n") - fflush(fstdout()) - return true - } -} - - diff --git a/examples/test/misc/dump_fields_example.das b/examples/test/misc/dump_fields_example.das deleted file mode 100644 index 91a7f799a3..0000000000 --- a/examples/test/misc/dump_fields_example.das +++ /dev/null @@ -1,15 +0,0 @@ -options gen2 -require dump_fields - -[dump_fields] -struct Foo { - position : float3 - velocity : float3 - color : float4 - foo : float = 13. -} - -[export] -def main { - print("// at this point compilation is done\n") -} diff --git a/examples/test/misc/emplace_push_and_push_clone_dim.das b/examples/test/misc/emplace_push_and_push_clone_dim.das deleted file mode 100644 index d9096ac827..0000000000 --- a/examples/test/misc/emplace_push_and_push_clone_dim.das +++ /dev/null @@ -1,12 +0,0 @@ -options gen2 -var a : array - -[export] -def main() { - var toCopy = fixed_array(42) - a |> push_clone <| toCopy - a |> push <| toCopy - a |> emplace <| toCopy -} - -options log diff --git a/examples/test/misc/enum_trait_example.das b/examples/test/misc/enum_trait_example.das deleted file mode 100644 index 4c53155814..0000000000 --- a/examples/test/misc/enum_trait_example.das +++ /dev/null @@ -1,18 +0,0 @@ -options gen2 -require daslib/enum_trait - -enum Foo { - a - b -} - -enum Bar { - a - b - c -} - -[export] -def main { - print("foo = {typeinfo enum_length(type)}\nbar = {typeinfo enum_length(type)}\n") -} diff --git a/examples/test/misc/eval_in_context.das b/examples/test/misc/eval_in_context.das deleted file mode 100644 index e15fccadfc..0000000000 --- a/examples/test/misc/eval_in_context.das +++ /dev/null @@ -1,257 +0,0 @@ -options gen2 -options debugger - -require rtti -require fio -require debugapi -require daslib/strings_boost -require daslib/algorithm -require daslib/ast - -class EvalDataWalker : DapiStackWalker { - W : StringBuilderWriter? - def EvalDataWalker(var wr : StringBuilderWriter) { - W = unsafe(addr(wr)) - } - def override onCallAOT(pp : Prologue; fileName : string#) : void { - *W |> write("// AOT {fileName}\n") - } - def override onCallJIT(pp : Prologue; fileName : string#) : void { - *W |> write("// JIT {fileName}\n") - } - def override onCallAt(pp : Prologue; info : FuncInfo; at : LineInfo) : void { - *W |> write("// {info.name} at {describe(at)}\n") - } - def override onCall(pp : Prologue; info : FuncInfo) : void { - *W |> write("// {info.name}\n") - } - def override onArgument(info : FuncInfo; index : int; vinfo : VarInfo; arg : float4) : void { - if (vinfo.flags.refType) { - let parg = unsafe(reinterpret arg) - *W |> write("\t\tlet {vinfo.name} : {describe(type_info(vinfo))} & = * reinterpret<{describe(type_info(vinfo))}?> {parg}ul // ref argument\n") - } elif (vinfo.dimSize > 0u) { - let parg = unsafe(reinterpret arg) - *W |> write("\t\tlet {vinfo.name} : {describe(type_info(vinfo))} = * reinterpret<{describe(type_info(vinfo))}?> {parg}ul // ref argument\n") - } else { - *W |> write("\t\tlet {vinfo.name} : {describe(type_info(vinfo))} = ") - if (vinfo.basicType == Type.tString) { - *W |> write("\"") - *W |> write(sprint_data(arg, type_info(vinfo), print_flags.singleLine)) - *W |> write("\"") - } else { - *W |> write(sprint_data(arg, type_info(vinfo), print_flags.singleLine)) - } - *W |> write("\n") - } - } - def override onVariable(inf : FuncInfo; vinfo : LocalVariableInfo; arg : void?; inScope : bool) : void { - if (inScope) { - if (arg != null) { - if (vinfo.flags.ref) { - unsafe { - let pref = unsafe(reinterpret arg) - var cvinfo = vinfo - cvinfo.flags &= ~TypeInfoFlags.ref - *W |> write("\t\tlet {vinfo.name} : {describe(type_info(vinfo))} = * reinterpret<{describe(type_info(cvinfo))}?> {*pref}ul // already ref\n") - } - } elif (vinfo.dimSize > 0u) { - *W |> write("\t\tlet {vinfo.name} : {describe(type_info(vinfo))} = * reinterpret<{describe(type_info(vinfo))}?> {arg}ul\n") - } else { - *W |> write("\t\tlet {vinfo.name} : {describe(type_info(vinfo))} & = * reinterpret<{describe(type_info(vinfo))}?> {arg}ul\n") - } - } - } - } -} - -def getStackVariableDefinitions(var ctx : Context; at : LineInfo) { - let text = build_string <| $(st) { - var walker = new EvalDataWalker(st) - var inscope walker_adapter <- make_stack_walker(walker) - walk_stack(walker_adapter, ctx, at) - walker_adapter := null - unsafe { - delete walker - } - } - var lines <- split(text, "\n") - lines |> pop - reverse(lines) - let res = join(lines, "\n") - delete lines - return res -} - -def getGlobalVariableDefinitions(var ctx : Context) { - let text = build_string <| $(st) { - let tot = get_total_variables(ctx) - for (vi in range(tot)) { - let vinfo = unsafe(addr(get_variable_info(ctx, vi))) - if (vinfo.name |> starts_with("__")) { - continue - } - var arg = unsafe(get_context_global_variable(ctx, vinfo.name)) - if (arg != null) { - if (vinfo.flags.ref) { - unsafe { - let pref = unsafe(reinterpret arg) - var cvinfo := vinfo - // cvinfo.flags &= ~ TypeInfoFlags ref - st |> write("\t\tlet {vinfo.name} : {describe(type_info(*vinfo))} = * reinterpret<{describe(type_info(*cvinfo))}?> {*pref}ul // already ref\n") - } - } elif (vinfo.dimSize > 0u) { - st |> write("\t\tlet {vinfo.name} : {describe(type_info(*vinfo))} = * reinterpret<{describe(type_info(*vinfo))}?> {arg}ul\n") - } else { - st |> write("\t\tlet {vinfo.name} : {describe(type_info(*vinfo))} & = * reinterpret<{describe(type_info(*vinfo))}?> {arg}ul\n") - } - } - } - } - return text -} - -def getRequire(var ctx : Context; var self_text : string&) { - let prr = unsafe(get_context_global_variable(ctx, "__rtti_require")) - if (prr != null) { - let arq = *unsafe(reinterpret prr) - var mrq <- split(arq, " ") - self_text := mrq[length(mrq) - 1] - mrq |> pop - let text = build_string <| $(st) { - for (q in mrq) { - st |> write("require {q}\n") - } - } - return text - } else { - return "// __rtti_require is missing. module needs to be compiled with `options debugger`\n" - } -} - -def eval(expr : string) : tuple { - let vars = getStackVariableDefinitions(this_context(), get_line_info()) - let gvars = getGlobalVariableDefinitions(this_context()) - var self_text : string - let greq = getRequire(this_context(), self_text) - let text = build_string <| $(st) { - st |> write("require rtti\n") // TODO: list of 'require' for this eval - st |> write("require strings\n") - st |> write("require __current\n") - st |> write(greq) - st |> write("\n") - st |> write("var G_EVAL_RESULT : string\n") - st |> write("[export]\n") - st |> write("def eval``call_eval\n") - st |> write("\tunsafe\n") - st |> write("// globals:\n") - st |> write(gvars) - st |> write("// locals:\n") - st |> write(vars) - st |> write("// EVAL:\n") - st |> write("\t\tlet EVAL = {expr}\n") - st |> write("\t\tG_EVAL_RESULT = \"\{EVAL\}\" // todo: JSON?\n") - st |> write("\n") - } - return compileAndRun(text, self_text) -} - -def compileAndRun(text, self_text : string) : tuple { - var failed = true - var result = "" - var inscope access := make_file_access("") - access |> set_file_source("__project", text) - fopen(self_text, "rb") <| $(fr) { - if (fr != null) { - fmap(fr) <| $(data) { - access |> set_file_source("__current.das", string(data)) - } - } else { - print("failed to open `{self_text}`\n") - } - } - using <| $(var mg : ModuleGroup) { - using <| $(var cop : CodeOfPolicies) { - cop.allow_local_variable_shadowing = true - compile_file("__project", access, unsafe(addr(mg)), cop) <| $(ok, program, errors) { - if (ok) { - simulate(program) <| $(sok; context; serrors) { - if (sok) { - failed = false - try { - unsafe { - context |> invoke_in_context("eval``call_eval") - } - } recover { - print("exception during eval\n{text}\n{context.last_exception}\n{describe(context.exceptionAt)}\n") - failed = true - } - if (!failed) { - let prr = unsafe(get_context_global_variable(context, "G_EVAL_RESULT")) - if (prr != null) { - result = clone_string(*unsafe(reinterpret prr)) - } - } - } else { - print("failed to simulate\n{text}\n{serrors}\n") - } - } - } else { - print("failed to compile\n{text}\n{errors}\n") - } - } - } - } - return (!failed, result) -} - -var GLOB = 13 - -struct AAA { - b : int -} - -var ccc : AAA[10] - -[export] -def main { - unsafe { - var bbb : AAA[10] - bbb[0].b = 1 - - ccc[1].b = 2 - - var LOC = 13 - LOC ++ - var GLOC & = LOC - print("testing {GLOB}+{LOC}={GLOB+LOC} // {GLOC}\n") - let res = eval("GLOB + LOC") - if (res.ok) { - print("eval = {res.result}\n") - } else { - print("eval failed\n") - } - - var a = AAA(b = 13) - a.b ++ - let res2 = eval("a") - if (res2.ok) { - print("eval = {res2.result}\n") - } else { - print("eval failed\n") - } - - let res3 = eval("bbb") - if (res3.ok) { - print("eval = {res3.result}\n") - } else { - print("eval failed\n") - } - - let res4 = eval("ccc") - if (res4.ok) { - print("eval = {res4.result}\n") - } else { - print("eval failed\n") - } - } -} diff --git a/examples/test/misc/export_constructor_example.das b/examples/test/misc/export_constructor_example.das deleted file mode 100644 index 01c0f59518..0000000000 --- a/examples/test/misc/export_constructor_example.das +++ /dev/null @@ -1,20 +0,0 @@ -options gen2 -require daslib/export_constructor - -[export_constructor] -class FooBar { - i : int = 10 - def FooBar { - print("c-tor {i}\n") - } -} - - -[export] -def main { - print("hello, world\n") - var fb = make`FooBar() - print("fb = {fb}\n") -} - -options log diff --git a/examples/test/misc/extra_ann.das b/examples/test/misc/extra_ann.das deleted file mode 100644 index 6c641543aa..0000000000 --- a/examples/test/misc/extra_ann.das +++ /dev/null @@ -1,23 +0,0 @@ -options gen2 -options indenting = 4 -options no_aot = true - -module extra_ann shared - -require ast -require rtti -require daslib/ast_boost - -[function_macro(name="test_extra")] -class TestExtraAnnotation : AstFunctionAnnotation { - def override apply(var func : FunctionPtr; var group : ModuleGroup; args : AnnotationArgumentList; var errors : das_string) : bool { - let foo = ("foo", RttiValue(tBool = true)) - let bar = ("bar", RttiValue(tInt = 13)) - let pi = ("pi", RttiValue(tFloat = 3.14)) - let test = ("test", RttiValue(tString = "hello,world")) - append_annotation(func, "$", "marker", [ - foo, bar, pi, test - ]) - return true - } -} diff --git a/examples/test/misc/faker_example.das b/examples/test/misc/faker_example.das deleted file mode 100644 index de1028ae84..0000000000 --- a/examples/test/misc/faker_example.das +++ /dev/null @@ -1,29 +0,0 @@ -options gen2 -require daslib/faker -require daslib/fuzzer - -require daslib/regex_boost -require daslib/random - -[export] -def main { - var fake <- Faker() // note - we can specify different RNG source - fuzz(10) <| $() { - print("number {fake |> number}\n") - } - fuzz(10) <| $() { - print("month {fake |> month}\n") - } - fuzz(10) <| $() { - print("day {fake |> day}\n") - } - fuzz(10) <| $() { - print("date {fake |> date}\n") - } - fuzz(10) <| $() { - print("positive int {fake |> positive_int}\n") - } - fuzz(10) <| $() { - print("int {fake |> any_int}\n") - } -} diff --git a/examples/test/misc/function_annotation_example.das b/examples/test/misc/function_annotation_example.das deleted file mode 100644 index df288632a6..0000000000 --- a/examples/test/misc/function_annotation_example.das +++ /dev/null @@ -1,14 +0,0 @@ -options gen2 -require function_annotation_macro - -[unique_transaction] -def add(a, b : int) { - print("a={a}, b={b}\n") - return a + b -} - -[export] -def test { - add(1, 2) - return true -} diff --git a/examples/test/misc/function_annotation_macro.das b/examples/test/misc/function_annotation_macro.das deleted file mode 100644 index 80ef9fa2b0..0000000000 --- a/examples/test/misc/function_annotation_macro.das +++ /dev/null @@ -1,15 +0,0 @@ -options gen2 -module function_annotation_macro - -require ast -require daslib/ast_boost - -[function_macro(name="unique_transaction")] -class UniqueTransaction : AstFunctionAnnotation { - def override transform(var call : smart_ptr; var errors : das_string) : ExpressionPtr { - print("we call {call.name}\n") - return <- default - } -} - - diff --git a/examples/test/misc/gen_fields.das b/examples/test/misc/gen_fields.das deleted file mode 100644 index 137dd34145..0000000000 --- a/examples/test/misc/gen_fields.das +++ /dev/null @@ -1,149 +0,0 @@ -options gen2 -module gen_fields - -require UnitTest - -require daslib/strings_boost -require daslib/templates -require daslib/templates_boost -require daslib/ast_boost - -def public create_component(name : string; blk : block<(cmp : int) : void>) { - print("create_component\n") - invoke(blk, 13) -} - -def public set_component(cmp : int; name : string; value : int) { - print("\tset {cmp}.{name} = {value}\n") -} - -def public set_component(cmp : int; name : string; value : float) { - print("\tset {cmp}.{name} = {value}\n") -} - -def public set_component(cmp : int; name : string; value : EntityId) { - print("\tset {cmp}.{name} = {value}\n") -} - -[sideeffects] -def public set_component(cmp : int; name : string; value) { - concept_assert(false, "unsupported component type {typeinfo typename(value)}") -} - -[structure_macro(name=dump)] -class DumpFields : AstStructureAnnotation { - def override apply(var st : StructurePtr; var group : ModuleGroup; args : AnnotationArgumentList; var errors : das_string) : bool { - let fnname = "create`ecs`template`{st.name}" - var inscope fn <- new Function(at = st.at, atDecl = st.at, name := fnname) - fn.flags |= FunctionFlags.generated - fn.flags |= FunctionFlags.privateFunction - fn.flags |= FunctionFlags.init - move_new(fn.result, new TypeDecl(baseType = Type.tVoid, at = st.at)) - var inscope blk <- new ExprBlock(at = st.at) - var inscope inner_block <- new ExprBlock(at = st.at) - inner_block.blockFlags |= ExprBlockFlags.isClosure - inner_block.arguments |> emplace_new <| new Variable(at = st.at, _type <- new TypeDecl(baseType = Type.tInt), name := "cmp") - move_new(inner_block.returnType, new TypeDecl(baseType = Type.tVoid)) - for (field in st.fields) { - if (true) { - var inscope setComp <- new ExprCall(at = field.at, name := "set_component") - setComp.arguments |> emplace_new <| new ExprVar(at = field.at, name := "cmp") - setComp.arguments |> emplace_new <| new ExprConstString(at = field.at, value := field.name) - if (field.init != null) { - setComp.arguments |> emplace_new <| clone_expression(field.init) - } else { - setComp.arguments |> emplace_new <| new ExprMakeStruct(at = field.at, makeType <- clone_type(field._type)) - } - inner_block.list |> emplace(setComp) - } - } - var inscope createComp <- new ExprCall(at = st.at, name := "create_component") - createComp.arguments |> emplace_new <| new ExprConstString(at = st.at, value := st.name) - createComp.arguments |> emplace_new <| new ExprMakeBlock(_block <- inner_block) - blk.list |> emplace(createComp) - move_new(fn.body, blk) - compiling_module() |> add_function(fn) - return true - } -} - -def follow_the_yellow_brick_road(var expr : ExpressionPtr) : ExpressionPtr { - if (expr is ExprRef2Value) { - return <- (expr as ExprRef2Value).subexpr |> follow_the_yellow_brick_road - } elif (expr is ExprVar) { - var ev = expr as ExprVar - if (!ev.varFlags.local && !ev.varFlags.argument && !ev.varFlags._block) { - if (ev.variable._type.flags.constant && ev.variable.init != null) { - return <- ev.variable.init |> follow_the_yellow_brick_road - } - } - } - return <- expr -} - -[template(result)] -def get_eval_any(econst : ExpressionPtr; result : auto(TT); var errors : das_string; var any_errors : bool&) : TT { - if (econst is ExprCall) { - if (econst.flags.noSideEffects) { - var ok = true - var res : variant - unsafe { - res.dummy = eval_single_expression(econst, ok) - } - if (!ok) { - errors := "{errors}\nexpression failed to evaluate {describe(econst)}" - any_errors = true - } - unsafe { - return res.id - } - } - } - errors := "{errors}\nunsupported initializer {describe(econst)}" - any_errors = true - return TT() -} - -def get_const_expr(var expr : ExpressionPtr) : ExpressionPtr { - if (expr == null) { - return <- default - } - var inscope econst <- expr |> follow_the_yellow_brick_road - return <- econst |> is_expr_const ? econst : default -} - -def get_entity_id_const(var expr : ExpressionPtr; var errors : das_string; var any_errors : bool&) { - if (expr == null) { - return make_invalid_id() - } - var inscope econst <- expr |> follow_the_yellow_brick_road - return econst |> get_eval_any(type, errors, any_errors) -} - -[structure_macro(name=dump2)] -class Dump2Fields : AstStructureAnnotation { - def override finish(var st : StructurePtr; var group : ModuleGroup; args : AnnotationArgumentList; var errors : das_string) : bool { - var any_errors = false - create_component(string(st.name)) <| $(cmp) { - for (field in st.fields) { - if (length(field._type.dim) == 0) { - var inscope econst <- field.init |> get_const_expr - if (field._type.baseType == Type.tInt) { - set_component(cmp, string(field.name), (econst ?as ExprConstInt)?.value ?? 0) - } elif (field._type.baseType == Type.tFloat) { - set_component(cmp, string(field.name), (econst ?as ExprConstFloat)?.value ?? 0.) - } elif (field._type.baseType == Type.tHandle) { - if (field._type.annotation.name == "EntityId") { - set_component(cmp, string(field.name), get_entity_id_const(field.init, errors, any_errors)) - } - } - } - } - } - return !any_errors - } -} - - - - diff --git a/examples/test/misc/hash_map_dict.das b/examples/test/misc/hash_map_dict.das deleted file mode 100644 index 09a41f7ee7..0000000000 --- a/examples/test/misc/hash_map_dict.das +++ /dev/null @@ -1,43 +0,0 @@ -options gen2 -require math - -require daslib/flat_hash_table - -typedef FlatHashMap_string_to_int = $TFlatHashTable < string, int > - -def makeRandomSequence(var src : array) { - let n = 500000 - let mod = uint(n) - resize(src, n) - for (i in range(n)) { - let num = (271828183u ^ uint(i * 119)) % mod - src[i] = "{num}" - } -} - -def dict(var tab : auto; src : array) { - tab.clear() - var maxOcc = 0 - for (s in src) { - maxOcc = max(++tab[s], maxOcc) - } - return maxOcc -} - -[export] -def main { - var src : array - makeRandomSequence(src) - if (true) { - var tab : table - profile(20, "dictionary") <| $() { - dict(tab, src) - } - } - if (true) { - var tab <- FlatHashMap_string_to_int() - profile(20, "flat hash map") <| $() { - dict(tab, src) - } - } -} diff --git a/examples/test/misc/hash_map_example.das b/examples/test/misc/hash_map_example.das deleted file mode 100644 index 11cf5cb077..0000000000 --- a/examples/test/misc/hash_map_example.das +++ /dev/null @@ -1,86 +0,0 @@ -options gen2 -require daslib/flat_hash_table - -struct ComplexKey { - key : int - key2 : int - nocopy : array -} - -def ComplexKey(k1, k2 : int) { - return <- ComplexKey(key = k1, key2 = k2) -} - -def operator ==(a, b : ComplexKey) { - return a.key == b.key && a.key2 == b.key2 -} - -struct SomeValue { - value : int - value2 : int - nocopy : array -} - -def SomeValue(v1, v2 : int) { - return <- SomeValue(value = v1, value2 = v2) -} - -typedef ExampleHashMap = $TFlatHashTable < ComplexKey, SomeValue > - -def hash0(k : ComplexKey) { - return uint64(k.key) | (uint64(k.key2) << 32ul) -} - -[export] -def main { - var hm <- ExampleHashMap() - hm[ComplexKey(1, 2)] <- SomeValue(3, 4) - hm[ComplexKey(2, 3)] <- SomeValue(4, 5) - hm[ComplexKey(3, 4)] <- SomeValue(5, 6) - hm[ComplexKey(4, 5)] <- SomeValue(6, 7) - - print("foreach:\n") - hm.foreach() <| $(k, v) { - print("{k} -> {v}\n") - } - print("keys,values:\n") - for (k, v in hm.keys(), hm.values()) { - print("{k} -> {v}\n") - } - - hm.erase(ComplexKey(2, 3)) - print("after erase:\n") - for (k, v in hm.keys(), hm.values()) { - print("{k} -> {v}\n") - } - - let found = hm.get(ComplexKey(3, 4)) <| $(v) { - print("found: {v}\n") - } - print("found: {found}\n") - - let notfound = hm.get(ComplexKey(2, 3)) <| $(v) { - print("notfound: {v}\n") - } - print("notfound: {notfound}\n") - - let exists = hm.key_exists(ComplexKey(3, 4)) - print("exists: {exists}\n") - - let notexists = hm.key_exists(ComplexKey(2, 3)) - print("notexists: {notexists}\n") - - hm[ComplexKey(3, 4)] <- SomeValue(7, 8) - print("after update:\n") - for (k, v in hm.keys(), hm.values()) { - print("{k} -> {v}\n") - } - - let safe_at_found <- hm?[ComplexKey(3, 4)] ?? SomeValue(0, 0) - print("safe_at_found: {safe_at_found}\n") - - let safe_at_notfound <- hm?[ComplexKey(2, 3)] ?? SomeValue(0, 0) - print("safe_at_notfound: {safe_at_notfound}\n") -} - - diff --git a/examples/test/misc/heartbeat_example.das b/examples/test/misc/heartbeat_example.das deleted file mode 100644 index 157a707815..0000000000 --- a/examples/test/misc/heartbeat_example.das +++ /dev/null @@ -1,32 +0,0 @@ -options gen2 -require daslib/heartbeat - - -def foo { - print("hello\n") - for (i in range(3)) { - print("step {i}\n") - } - var q = 1 - while (q < 3) { - print("q = {q}\n") - q ++ - } - while (true) { - print(".\n") - } -} - -[export] -def main { - var count = 0 - set_heartbeat <| @ { - count ++ - if (count == 1000) { - breakpoint() - } - } - foo() -} - -options log diff --git a/examples/test/misc/hello_new_syntax.das b/examples/test/misc/hello_new_syntax.das deleted file mode 100644 index 587f248bae..0000000000 --- a/examples/test/misc/hello_new_syntax.das +++ /dev/null @@ -1,705 +0,0 @@ -options gen2; - -// NOTE - this is WIP example of every single feature new syntax has to offer -// new syntax no longer supports significant whitespace, oxoford commas, etc - -// NOTE - in every case where type is specified for let or var, it is optional, and can be inferred -// its there for the documentation purposes - - -///////////////////// -// module declaration - -// note - this works, but commented out for now, becasue of WARNING: program is setup as both module, and endpoint -// module hello_world; // module name - -//////////////////// -// alias declaration - -typedef IntArray = array // alias for array of integers - -////////////////////////////// -// global variable declaration - -let G_A = 5 - -///////////////////// -// struct declaration - -struct EmptyStructure; - -struct Foo { - a : int = 5 - b : int -} - -struct FooWhitespace - -{ - - a : int = 5 - b : int - -} - -struct Bar : Foo { // structure with inheritance - c : float -} - -[safe_when_uninitialized] // structure annotation -struct Baz : Bar { // structure with methods - def Baz { - c = 3.14 - } - def add(value : int) { - a += value - } -} - -[safe_when_uninitialized] // structure annotation - -struct BazWhitespace : Bar - -{ - - def Baz - { - c = 3.14 - } - - def add(value : int) - { - a += value - } - -} - -class Cls { // class with methods - @big // with metadata - @min = 13 - @max = 42 - private foobar : int - static foobars : float - def public foo { - debug("foo") - } - def private private_method(m : int) { // todo: make it `private def static_method` - debug(m) - } - def static static_method { - debug("static_method") - } - def abstract abstract_method(a : int) : float - [unsafe_deref] // note function annotation - def base_method { - } - -} - -class private DerivedClass : Cls { // class with inheritance - def override base_method { - debug("bar") - } - def override abstract_method(a : int) : float { - return float(a) - } -} - -/////////////////// -// enum declaration - -enum EmptyEnum { -} - -enum MyEnum { - ONE - TWO - THREE -} - -enum EnumWithTrailingComma { - ONE - TWO -} - -enum Enum8u : uint8 { - ONE - TWO - THREE = 16u8 // TODO: 16i8 causes 2x smart_ptr_leak, note - it causes 1x smart_ptr_leak with old parser -} - -enum private Enum64 : uint64 { // 64 bit enum, private - ONE - TWO - THREE = 16ul -} - -enum WhiteSpaceEnum - -{ - - ONE - TWO,,,,,, - - THREE - - FOUR = 4 - , - -} - -// TODO: add example of enum with annotation. for now we don't have a builtin enum one - -[export] -def enum_use_example { - let bf : MyEnum = MyEnum.ONE -} - -/////////// -// bitfield - - -bitfield EmptyBitfield { -} - -bitfield MyBitfield { - ONE - TWO - THREE -} - -bitfield WhiteSpaceBitfield - -{ - - ONE - TWO,,,,,, - - THREE - - FOUR - , - -} - -[export] -def bitfield_use_example { - let bf : MyBitfield = MyBitfield.ONE -} - -//////////////////// -// making structures - -struct Mks { - a : int = 1 - b : float = 2.0 - def Mks(t : int) { - a = t - b = float(t) - } - def Mks(one, two, three : int) { - a = one + two - b = float(two + three) - } -} - -[export] -def test_make_struct { - let a : Mks = Mks() // with default values - let A : Mks = default // with default values, same as Mks() - let b : Mks = Mks(a = 2, b = 3.0)// with values overwritten - let c : Mks = Mks(a = 4) // with some values overwritten - let C : Mks = Mks(5) // with constructor - let CC : Mks = Mks(1, 2, 3) // with complex constructor - let d : Mks = struct(a = 2, b = 3.0) // with values overwritten - let e : Mks[3] = struct((a = 1, b = 1.0), (a = 2, b = 2.0), (a = 3, b = 3.0))// this is array of structures // TODO: do we need better syntax_error - unsafe { - let h : Mks = default uninitialized // uninitialized, a=0, b=0.0 - let i : Mks = struct(uninitialized a = 1) // uninitialized, a=1, b=0.0 - } -} - -[export] -def test_new_struct { - let a : Mks? = new Mks() // Mks*, on heap - default values - let A : Mks? = new default // Mks*, on heap - default values - let b : Mks? = new Mks(5) // Mks*, on heap - with constructor - let c : Mks? = new(a = 1, b = 2.0)// Mks*, on heap - with values overwritten - let d : Mks? [10] = new() // fixed_array of 10 elements - unsafe { - let j : Mks? = new(uninitialized b = 2.0) // Mks* - on heap, uninitialized, a=0, b=2.0 - let h : Mks? = new default uninitialized // Mks* - on heap, uninitialized, a=0, b=0.0 - } -} - -///////// -// tuples - -tuple Tup { - a : int - b : float - c : string -} - -tuple WhiteSpaceTuple - -{ - - a : int - b : float;;;;;;;;;;;; - - c : string - - d : int - ; - -} - -[export] -def test_tuples { - let a : tuple = (1, 2., "3"); debug(a) - let b : tuple = tuple(1, 2., "3"); debug(b) - let c : tuple = Tup(1, 2., "3"); debug(c) - let d : tuple = Tup(a = 1, b = 2., c = "3"); debug(d) - let e : tuple = tuple(a = 1, b = 2., c = "3"); debug(e) - let f : tuple = tuple(uninitialized a = 1); debug(f)// a=1,b=0.0,c="" - let g : tuple? = new tuple(1, 2., "3"); debug(g)// on heap -} - -/////////// -// variants - -variant Varr { - a : int - b : float - c : string -} - -variant WhiteSpaceVariant - -{ - - a : int - b : float;;;;;;;;;;;; - - c : string - - d : int - ; - -} - -[export] -def test_variants { - // NOTE - variant can't be uninitialized (it just makes no sense) - let a : variant = Varr(a = 1) - let b : variant = variant(a = 1) -} - -///////// -// arrays - -[export] -def test_arrays { - let a : array <- [1, 2, 3, 4, 5]// array of integers - let c : array <- array(1, 2, 3, 4, 5)// array of integers - let d : array <- array(1, 2, 3, 4, 5)// array of integers - let b : int[5] = fixed_array(1, 2, 3, 4, 5)// fixed size array of integers - let e : int[5] = fixed_array(1, 2, 3, 4, 5)// fixed size array of integers - let g : array <- [ Mks(1), Mks(2, 3, 4) ] // array of structures - let f : Mks[2] <- struct((a = 1, b = 2.0), (a = 3, b = 4.0)) - let G : array <- array struct((a = 1, b = 2.0), (a = 3, b = 4.0))// array of structures - let h : Tup[2] <- tuple((a = 1, b = 2., c = "3"), (a = 4, b = 5., c = "6")) - let H : array <- array tuple((a = 1, b = 2., c = "3"), (a = 4, b = 5., c = "6"))// array of tuples - let v : Varr[6] <- variant(a = 1, b = 2., c = "3", a = 4, b = 5., c = "6") - let V : array <- array variant(a = 1, b = 2., c = "3", a = 4, b = 5., c = "6")// array of variants -} - -//////// -// table - -def test_tables() { - let a : table <- { 1, 2, 3, 4, 5 } // table of integers, keys only - let b : table <- table(1, 2, 3, 4, 5)// table of integers, keys only - let B : table <- table(1, 2, 3, 4, 5)// table of integers, keys only - let c : table <- { 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5 }// table of integers, key-value pairs - let d : table <- table(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5)// table of integers, key-value pairs - let D : table <- table(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5)// table of integers, key-value pairs -} - -///////////////// -// comprehensions - -[export] -def test_comprehensions { - let arr_comp : array <- [for (x in range(1, 100)); x * x; where x % 2 == 0]// array comprehension - let iter_comp : iterator <- [iterator for(x in range(1, 100)); x * x; where x % 2 == 0]// iterator comprehension - let set_comp : table <- {for (x in range(1, 100)); x * x; where x % 2 == 0}// set comprehension - let table_comp : table <- {for (x in range(1, 10)); x => "{x*x}"; where x % 2 == 0}// table comprehension -} - -//////////////////// -// return expression - -[export] -def test_regular_return(a, b : int) : int { - return a + b -} - -[export] -def test_return_with_move_syntax(var a : array) { - return <- a -} - -[export] -def test_return_lambda(a : int) : lambda<(arg : int) : void> { - return <- @(b : int) { - debug(a + b) - } -} - -[export] -def test_cond_return(cond : bool) { - return 13 if (cond) - return 42 - if (cond) return 13 -} - -/////////////// -// if-then-else - -[export] -def test_if_then_else(cond1, cond2 : bool) { - if (cond1) { - debug(cond1) - } - if (cond1) { - debug(cond1) - } else { - debug(cond2) - } - if (cond1) { - debug(cond1) - } elif (cond2) { - debug(cond2) - } - if (cond1) debug(cond1) - while (true) { - if (cond1) break - if (cond2) continue - } - // whitespace - if (cond1) - { - debug(cond1) - } - if (cond1) - { - debug(cond1) - } - else - { - debug(cond2) - } - if (cond1) - { - debug(cond1) - } - elif (cond2) - { - debug(cond2) - } - else - { - debug("else") - } - if (cond1) - debug(cond1) - while (true) - { - if (cond1) - break - if (cond2) - - continue - } -} - -/////////// -// for loop - -[export] -def test_for(i : int) { - for (x in range(1, i)) { - debug(x) - } - for (x, y in range(1, i), count()) { - debug(x) - debug(y) - } - for (x in range(1, i)) - { - debug(x) - } -} - -///////////// -// while loop - -[export] -def test_while(cond : bool) { - while (cond) { - debug(cond) - } - while (cond) - { - debug(cond) - } -} - -/////// -// with - -[export] -def test_with(var a : Mks) { - with (a) { - b = 13.0 - } - with (a) - { - b = 13.0 - } -} - -///////// -// unsafe - -def test_unsafe { - unsafe { - debug("unsafe") - } - unsafe - { - debug("unsafe") - } -} - -///////// -// piping - -def take_mks(a : Mks) { - debug(a) -} - -def take_mks_and_int(a : Mks; b : int) { - debug(a) - debug(b) -} - -def take_anything(a) { - debug(a) -} - -def take_any_two(a, b) { - debug(a) - debug(b) -} - -[export] -def test_pipes() { - take_anything() <| 13 // lpipe - 13.1 |> take_anything() // rpipe - take_anything() $ { - print("this is block;") // piping block - } - take_anything() $(a : int) { - print("this is block which takes argument {a};") // piping block - } - take_anything() { // naked block - print("this is block;") - } - take_any_two(13) { // argument and naked block - print("this is block;") - } - 13 |> take_any_two() { // lpipe and naked block - print("this is block;") - } - take_anything() @(a, b : int) { - print("this is lambda which takes 2 arguments") - return 13 // and returns value - } - // whitespace - take_anything() $(a : int) - { - print("this is block which takes argument {a};") // piping block - } -} - -[export] -def test_method_like_call_syntax() { - var mks = Mks() - mks.take_mks() // method-like call syntax - mks.take_mks_and_int(13) // method-like call syntax -} - -/////////// -// typeinfo - -[comment(i=1, f=2.0, s="three", b=false)] -struct Event { - i : int -} - -[export] -def test_typeinfo(arg : int) { - let a = typeinfo sizeof(arg) - debug(a) - let b = typeinfo has_field(type) - debug(b) - let c = typeinfo struct_get_annotation_argument(type) - debug(c) -} - -///////////////// -// string builder - -[export] -def test_string_builder(arg, arg2 : int) { - let a = "" - debug(a) - let b = "hello, world!" - debug(b) - let c = "arg={arg}\n" - debug(c) - let d = "{arg} + {arg2} = {arg+arg2}" - debug(d) -} - -///////////////////////// -// lambda capture example - -[export] -def test_lambda_capture(a : int) { - var b = 13 - return @ capture(= a, := b) (c : int) { - debug(a) - debug(b) - debug(c) - } - // whitespace (note, only before the block) - return @ capture(= a, := b) (c : int) - { - debug(a) - debug(b) - debug(c) - } -} - -//////////// -// generator - -[export] -def test_generator(a : int) { - // passing block as argument - var g1 <- generator(${ - for (x in range(1, a)) { - yield x - } - return false - }) - var G1 <- generator capture(= a) (${ - for (x in range(1, a)) { - yield x - } - return false - }) - // simplified syntax - var g2 <- generator { - for (x in range(1, a)) { - yield x - } - return false - } - var G2 <- generator capture(= a) { - for (x in range(1, a)) { - yield x - } - return false - } - // via pipe - var g3 <- generator() <| ${ - for (x in range(1, a)) { - yield x - } - return false - } - var G3 <- generator capture(= a) () <| ${ - for (x in range(1, a)) { - yield x - } - return false - } - // whitespace - var g22 <- generator - { - for (x in range(1, a)) { - yield x - } - return false - } - var G22 <- generator capture(= a) - { - for (x in range(1, a)) { - yield x - } - return false - } - var g33 <- generator() <| $ - { - for (x in range(1, a)) { - yield x - } - return false - } - var G33 <- generator capture(= a) () <| $ - { - for (x in range(1, a)) { - yield x - } - return false - } -} - -///////////// -// whitespace - -def test_whitespace { - // within parenthesis, there is no ; generated - let a = (1 - + 2) - // within square bracers, there is no ; generated - let b = [1, - 2, 3] -} - -[export] - -def test_more_whitespace() - -{ - pass -} - -/////// -// main - -[export] -def main { - // var f <- {1=>"a", 2=>"b", 3=>"c", 4=>"d"}; - // debug(f); - - print("foo\n") if (3 <= 4) -} - -options log - diff --git a/examples/test/misc/hello_world.das b/examples/test/misc/hello_world.das deleted file mode 100644 index b02ce1db26..0000000000 --- a/examples/test/misc/hello_world.das +++ /dev/null @@ -1,72 +0,0 @@ -require daslib/flat_hash_table -require math - -typedef FlatHashMap_int_Foo = TFlatHashTable < int; FooType > -typedef FlatHashMap_string_int = TFlatHashTable < string; int > - -struct Foo { - a : int -} - -typedef FooType = Foo - -[sideeffects] -def take_any_hash_table(a : TFlatHashTable < auto(TT); auto(QQ) >) { - return "any" -} - -[sideeffects] -def take_any_hash_map(a : TFlatHashTable < string; auto(QQ) >) { - return "string;any" -} - -typedef DictMap = TFlatHashTable < string; int >(@@hash_string) // vs @@hash - -def hash_string(s : string) : uint64 { - var h : uint64 = 14695981039346656037ul - for (c in s) { - h = h ^ uint64(c) - h = h * 1099511628211ul - } - return h -} - -def makeRandomSequence(var src : array) { - let n = 500000 - let mod = uint(n) - resize(src, n) - for (i in range(n)) { - let num = (271828183u ^ uint(i * 119)) % mod - src[i] = "{num}" - } -} - -def dict(var tab : auto; src : array) { - tab.clear() - var maxOcc = 0 - for (s in src) { - maxOcc = max(++tab[s], maxOcc) - } - return maxOcc -} - -[export] -def main { - - if (true) { - var map1 <- FlatHashMap_int_Foo() - var map2 <- FlatHashMap_string_int() - verify("any" == take_any_hash_table(map1)) - verify("string;any" == take_any_hash_map(map2)) - print("hash table specialization tests passed\n") - } - - var src : array - makeRandomSequence(src) - if (true) { - var tab <- DictMap() - profile(1, "flat hash map") <| $() { - dict(tab, src) - } - } -} diff --git a/examples/test/misc/highlights.das b/examples/test/misc/highlights.das deleted file mode 100644 index f2c0314bd2..0000000000 --- a/examples/test/misc/highlights.das +++ /dev/null @@ -1,31 +0,0 @@ -options gen2 -def main() { - foobar - foobar() - /* - here? - */ - let dummy = "1" + 2 - let x : int = "foo" + "bar" - let x = foobar() - let y = foobar() - let z = foobar() - let w = foobar() - let there = " - multi line string - " - for (t in range("a")) { - let a = foobar() - let b = foobar() - let c = foobar() - let d = foobar() - } - // let t <- {{ "one" => 1 }} - // find(t,"one") <| $ ( __a ) - // pass -} -// . . . . . . . . . . - - - - diff --git a/examples/test/misc/hw_breakpoint.das b/examples/test/misc/hw_breakpoint.das deleted file mode 100644 index a4e5ec36ed..0000000000 --- a/examples/test/misc/hw_breakpoint.das +++ /dev/null @@ -1,29 +0,0 @@ -options gen2 -options debugger -require daslib/debug - -require rtti -require debugapi - -[export] -def main { - var i = 5 - var bp = 0 - unsafe {// set breakpoint when data of 4 bytes is modified - bp = set_hw_breakpoint(this_context(), addr(i), 4, true) - } - print("before i = {i}\n") - i = 6 // this would trigger breakpoint - print("after i = {i}\n") // debugger will stop right here - i = 8 // this would trigger breakpoint - print("after i = {i}\n") // debugger will stop right here again - print("and we are done\n") - unsafe {// clear breakpoint - clear_hw_breakpoint(bp) - } - print("after clear") - i = 7 // this wont trigger breakpoint - print("finished\n") - print("!\n") -} - diff --git a/examples/test/misc/instrument.das b/examples/test/misc/instrument.das deleted file mode 100644 index 6ee1aa8d21..0000000000 --- a/examples/test/misc/instrument.das +++ /dev/null @@ -1,60 +0,0 @@ -options gen2 -options debugger = true - -require rtti -require debugapi - -// sample of debug agent - -class SampleDebugAgent : DapiDebugAgent { - def SampleDebugAgent { - pass - } - def override onBreakpoint(var ctx : Context; at : LineInfo; reason, text : string) : void { - print("{ctx} {ctx.name} : breakpoint at line {int(at.line)}, {reason}, {text}\n") - instrument_node(ctx, true) <| $(ati) { - if (ati.fileInfo == at.fileInfo) { - if (ati.line == at.line + 2u) { - return true - } - } - return false - } - } - def override onSingleStep(var ctx : Context; at : LineInfo) : void { - print("{ctx} {ctx.name} : step at {int(at.line)}\n") - } - def override onInstrument(var ctx : Context; at : LineInfo) : void { - print("{ctx} {ctx.name} : instrument at {int(at.line)}\n") - set_single_step(ctx, true) - } -} - -[export] -def debug_agent(ctx : Context) { - assert(this_context().category.debug_context) - install_new_debug_agent(new SampleDebugAgent(), "debug") -} - -def foo(var x : int&) { - x ++ - x ++ -} - -[export] -def main { - this_context().name := "stackwalk main context" - fork_debug_agent_context(@@debug_agent) - var x = 5 - breakpoint() - print("before x=6\n") - x = 6 - for (t in range(10)) { - print("x={x} t={t}\n") - x ++ - foo(x) - } - var z = 13 - z ++ -} - diff --git a/examples/test/misc/insturment_function.das b/examples/test/misc/insturment_function.das deleted file mode 100644 index 79e912510d..0000000000 --- a/examples/test/misc/insturment_function.das +++ /dev/null @@ -1,78 +0,0 @@ -options gen2 -options debugger = true - -require rtti -require debugapi - -class SampleDebugAgent : DapiDebugAgent { - def override onInstrumentFunction(var ctx : Context; fun : SimFunction?; entering : bool; userData : uint64) : void { - print("{entering} {fun.mangledName} - {userData}\n") - } -} - -[export] -def debug_agent(ctx : Context) { - assert(this_context().category.debug_context) - install_new_debug_agent(new SampleDebugAgent(), "debug") -} - -// walker - -struct Bar { - i = 1 - b = true -} - -struct Foo { - a : int - arr = fixed_array(true, false) - arr2 = fixed_array(Bar(), Bar()) - ref : Foo? -} - -def operator delete(var a : Foo&) { - print("destroy Foo[{a.a}]\n") -} - -[export] -def main() { - this_context().name := "stackwalk main context" - var count = 0 - instrument_all_functions(this_context()) <| $(fn, sfn) { - let info = get_function_info(this_context(), fn) - print("instrumenting {sfn.mangledName}\n") - return uint64(count++) - } - fork_debug_agent_context(@@debug_agent) - - var a = Foo(a = 0) - unsafe { - a.ref = addr(a) - } - delete a - // breakpoint() - - var arr <- [ Foo(a=1), Foo(a=2) ] - print("arr len = {length(arr)}\n") - - let dim = fixed_array(Foo(a = 100), Foo(a = 200)) - print("{dim}\n") - - breakpoint() - - var j : int[3] - for (q in j) { - q++ - } - - for (i in range(length(arr))) { - arr[i].a = i + 2 - } - - delete arr // <-- падает тут если пойти step-in - var arr2 <- [ Foo(a=3) ] - arr <- arr2 - // while true - // pass - delete arr -} diff --git a/examples/test/misc/interface_example.das b/examples/test/misc/interface_example.das deleted file mode 100644 index 3502e16465..0000000000 --- a/examples/test/misc/interface_example.das +++ /dev/null @@ -1,70 +0,0 @@ -options gen2 - -require daslib/interfaces - -[interface] -class ITick { - def abstract beforeTick : bool - def abstract tick(dt : float) : void - def abstract afterTick : void -} - -[interface] -class ILogger { - def abstract log(message : string) : void -} - -[implements(ITick), implements(ILogger)] -class Foo { - def Foo() { - pass - } - def ITick`tick(dt : float) { - print("tick {dt}\n") - } - def ITick`beforeTick() { - print("beforeTick\n") - return true - } - def ITick`afterTick() { - print("afterTick\n") - } - def ILogger`log(message : string) { - print("log {message}\n") - } -} - -[export] -def main() { - var f = new Foo() - - // direct getter calls (original pattern) - f->get`ITick()->beforeTick() - f->get`ITick()->tick(1.0) - f->get`ITick()->afterTick() - f->get`ILogger()->log("hello") - - // is — compile-time interface check - print("f is ITick = {f is ITick}\n") // true - print("f is ILogger = {f is ILogger}\n") // true - - // as — get the interface proxy - var tick = f as ITick - tick->tick(2.0) - - // ?as — safe interface access (null if pointer is null) - var logger = f ?as ILogger - if (logger != null) { - logger->log("safe access") - } - - // ?as on null pointer - var nothing : Foo? - var maybe_tick = nothing ?as ITick - print("null ?as ITick = {maybe_tick}\n") // null - - unsafe { - delete f - } -} - diff --git a/examples/test/misc/interface_prototype.das b/examples/test/misc/interface_prototype.das deleted file mode 100644 index aa5a521684..0000000000 --- a/examples/test/misc/interface_prototype.das +++ /dev/null @@ -1,86 +0,0 @@ -options gen2 -class ITick { - def abstract beforeTick : void - def abstract tick(dt : float) : void - def abstract afterTick : void -} - -class ILogger { - def abstract log(message : string) : void -} - -class Foo { - _i_tick : ITick? - _i_logger : ILogger? - def Foo { - pass - } - def get_ITick : ITick ? { - if (_i_tick == null) { - _i_tick = new implementation_Foo_ITick(self) - } - return _i_tick - } - def get_ILogger : ILogger ? { - if (_i_logger == null) { - _i_logger = new implementation_Foo_ILogger(self) - } - return _i_logger - } - def ITick`tick(dt : float) { - print("tick {dt}\n") - } - def ITick`beforeTick { - print("beforeTick\n") - } - def ITick`afterTick { - print("afterTick\n") - } - def ILogger`log(message : string) { - print("log {message}\n") - } -} - -class implementation_Foo_ITick : ITick { - @do_not_delete _self : Foo? - def implementation_Foo_ITick(var that : Foo) { - _self = unsafe(addr(that)) - } - def override beforeTick : void { - _self->ITick`beforeTick() - } - def override afterTick : void { - _self->ITick`afterTick() - } - def override tick(dt : float) : void { - _self->ITick`tick(dt) - } -} - -class implementation_Foo_ILogger : ILogger { - @do_not_delete _self : Foo? - def implementation_Foo_ILogger(var that : Foo) { - _self = unsafe(addr(that)) - } - def override log(message : string) : void { - _self->ILogger`log(message) - } -} - - -[export] -def main { - print("hello, world\n") - var f = new Foo() - - f->get_ITick()->beforeTick() - f->get_ITick()->tick(1.0) - f->get_ITick()->afterTick() - f->get_ILogger()->log("hello") - - unsafe { - delete f - } -} - -options log diff --git a/examples/test/misc/invoke_debug_agent_function.das b/examples/test/misc/invoke_debug_agent_function.das deleted file mode 100644 index 812d91561a..0000000000 --- a/examples/test/misc/invoke_debug_agent_function.das +++ /dev/null @@ -1,35 +0,0 @@ -options gen2 -require debugapi - -class MyDebugAgent : DapiDebugAgent { - def add_ii(var res : int&; a, b : int) { - print("add method {a} {b}\n") - res = a + b - } - def add(a, b : int) : int { - return a + b - } -} - -def debug_agent(ctx : Context) { - install_new_debug_agent(new MyDebugAgent(), "sample") -} - -[export] -def add(var self : MyDebugAgent; var res : int&; a, b : int) { - print("add function {a} {b}\n") - res = self->add(a, b) -} - -[export] -def main { - fork_debug_agent_context(@@debug_agent) - var t_m, t_f : int - unsafe { - invoke_debug_agent_method("sample", "add_ii", addr(t_m), 1, 2) - invoke_debug_agent_function("sample", "add", addr(t_f), 3, 4) - } - print("t_m = {t_m}\n") - print("t_f = {t_f}\n") -} - diff --git a/examples/test/misc/json_example.das b/examples/test/misc/json_example.das deleted file mode 100644 index be8f9506c6..0000000000 --- a/examples/test/misc/json_example.das +++ /dev/null @@ -1,95 +0,0 @@ -options gen2 -// options debugger=true -// options log = true - -options persistent_heap -options gc - -require fio -require daslib/json -require daslib/json_boost - -[export] -def test_reader { - var error = "" - var jsv = %json~ - {"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } - }} - %% - print("{write_json(jsv)}\n") - unsafe { - delete jsv - } -} - -[export] -def test { - test_reader() - for (jidx in range(1, 9)) { - let fname = "D:/Work/daScript/examples/test/json/{jidx}.json" - // let fname = "/Users/borisbatkin/Work/yzg/examples/test/json/{jidx}.json" - fopen(fname, "rb") <| $(f) { - fread(f) <| $(data) { - print("\n{fname}\n") - // print("before read {int(heap_bytes_allocated())} {int(string_heap_bytes_allocated())}\n") - var error = "" - var json = read_json(data, error) - if (json == null) { - panic("failed to parse, {error}\n") - } else { - // macro test - if (json is _object) { - print("object {int(heap_bytes_allocated())}\n") - (json as _object).insert("foo", JV("bar")) - } - print("{write_json(json)}\n") - print("before delete {int(heap_bytes_allocated())} {int(string_heap_bytes_allocated())}\n") - unsafe { - delete json - } - print("before collect {int(heap_bytes_allocated())} {int(string_heap_bytes_allocated())}\n") - heap_report() - unsafe { - heap_collect(true) - } - print("after collect {int(heap_bytes_allocated())} {int(string_heap_bytes_allocated())}\n") - } - } - } - } - print("allocated {int(heap_bytes_allocated())} {int(string_heap_bytes_allocated())}\n") - unsafe { - heap_collect(true) - } - print("after collect {int(heap_bytes_allocated())} {int(string_heap_bytes_allocated())}\n") - return true -} - -[export] -def main { - test() -} diff --git a/examples/test/misc/json_serialize.das b/examples/test/misc/json_serialize.das deleted file mode 100644 index 3c110ccb1f..0000000000 --- a/examples/test/misc/json_serialize.das +++ /dev/null @@ -1,24 +0,0 @@ -options gen2 -require daslib/json_boost - -struct Bar { - x, y : int -} - -struct Foo { - i : int - s : string - q : double[3] - b : Bar -} - -[export] -def main { - let foo = Foo(i = 1, s = "hello", q = fixed_array(1lf, 2lf, 3lf), b = Bar(x = 13, y = 14)) - - var js_foo = JV(foo) - print("{write_json(js_foo)}\n") - - var bar <- from_JV(js_foo, type) - print("bar = {bar}\n") -} diff --git a/examples/test/misc/local_temp_ref.das b/examples/test/misc/local_temp_ref.das deleted file mode 100644 index e3940e6173..0000000000 --- a/examples/test/misc/local_temp_ref.das +++ /dev/null @@ -1,33 +0,0 @@ -options gen2 -struct Foo { - a : int -} - -var foo : Foo - -def getFoo : Foo & { - unsafe { - return foo - } -} - -def getFooT : Foo & # { - unsafe { - return reinterpret foo - } -} - -[export] -def main { - var v1 & = getFooT() // NOT UNSAFE ANYMORE, v1 is Foo#& - v1.a = 13 - print("v1.a = {v1.a}\n") - unsafe { - var v2 & = getFoo() - print("v2.a = {v2.a}\n") - v2.a = 14 - print("v1.a = {v1.a}\n") - } -} - -options log diff --git a/examples/test/misc/logger_and_logger_agent.das b/examples/test/misc/logger_and_logger_agent.das deleted file mode 100644 index 9e5b3bc4b0..0000000000 --- a/examples/test/misc/logger_and_logger_agent.das +++ /dev/null @@ -1,32 +0,0 @@ -options gen2 -require debugapi - -class LogAgent : DapiDebugAgent { - def override onLog(context : Context?; at : LineInfo const?; level : int; text : string#) : bool { - print("onLog - {level} - '{text}'\n'{context}' <{at}>\n") - return true // false for not consuming - } -} - -[export] -def logger_agent(ctx : Context) { - install_new_debug_agent(new LogAgent(), "log_example") -} - -[export] -def main { - to_log(LOG_TRACE, "trace") - to_log(LOG_DEBUG, "debug") - to_log(LOG_INFO, "info") - to_log(LOG_WARNING, "warning") - to_log(LOG_ERROR, "error") - - fork_debug_agent_context(@@logger_agent) - - to_log(LOG_TRACE, "one more time, trace") - to_log(LOG_DEBUG, "one more time, debug") - to_log(LOG_INFO, "one more time, info") - to_log(LOG_WARNING, "one more time, warning") - to_log(LOG_ERROR, "one more time, error") -} - diff --git a/examples/test/misc/look_ahead_buffer.das b/examples/test/misc/look_ahead_buffer.das deleted file mode 100644 index b70eedb44f..0000000000 --- a/examples/test/misc/look_ahead_buffer.das +++ /dev/null @@ -1,126 +0,0 @@ -options gen2 -require daslib/strings_boost - -struct LookAheadBuffer { - src : iterator - que : array -} - -def look_ahead(src : string; blk : block<(var buf : LookAheadBuffer) : void>) { - unsafe { - var la <- LookAheadBuffer(uninitialized src <- each(src)) // unsafe due to 'each' on string - invoke(blk, la) - delete la - } -} - -def empty(var buf : LookAheadBuffer) : bool { - if (length(buf.que) > 0) { - return false - } - return buf.src |> empty() -} - -def next(var buf : LookAheadBuffer; var value : int&) : bool { - if (length(buf.que) > 0) { - value = buf.que[0] - buf.que |> erase(0) - return true - } - return buf.src |> next(value) -} - -def skip(var buf : LookAheadBuffer; var total : int = 1) { - let lbq = length(buf.que) - if (total <= lbq) { - total -= lbq - buf.que |> clear() - } - var Ch = 0 - while (total > 0) { - buf |> next(Ch) - total -- - } -} - -def ahead(var buf : LookAheadBuffer; var value : int&; offset : int = 0) : bool { - while (length(buf.que) <= offset) { - var Ch = 0 - if (buf.src |> next(Ch)) { - buf.que |> push(Ch) - } else { - return false - } - } - if (length(buf.que) > offset) { - value = buf.que[offset] - return true - } - return false -} - -def accept(var buf : LookAheadBuffer; st : string) : bool { - let slen = length(st) - var Ch = 0 - for (sc, i in st, range(slen)) { - if (buf |> ahead(Ch, i)) { - if (Ch != sc) { - return false - } - } else { - return false - } - } - buf |> skip(slen) - return true -} - - -let tokens <- array( - "<<", ">>" -); - -def tokenize(inp : string) { // TODO: turn into generator - look_ahead(inp) <| $(var tin) { - var Ch = 0 - while (!empty(tin)) { - while (ahead(tin, Ch) && is_white_space(Ch)) { - tin |> next(Ch) - } - var found = false - for (tok in tokens) { - if (tin |> accept(tok)) { - print("token `{tok}`") // TODO: yield - found = true - break - } - } - if (found) { - continue - } - tin |> ahead(Ch) - if (is_alpha(Ch)) { - var arr : array - while (tin |> ahead(Ch) && is_alpha(Ch)) { - tin |> next(Ch) - arr |> push(uint8(Ch)) - } - var tok = string(arr) - print("text `{tok}`\n") - unsafe { - delete_string(tok) // note: this is here for memory efficiency only - } - delete arr - } else { - tin |> skip() - print("`{to_char(Ch)}` -> {Ch}\n") // TODO: yield - } - } - } -} - -[export] -def main { - let test_str = "foo + b * ( c << 2 ) << 3" - tokenize(test_str) -} diff --git a/examples/test/misc/m.das b/examples/test/misc/m.das deleted file mode 100644 index 043b896f89..0000000000 --- a/examples/test/misc/m.das +++ /dev/null @@ -1,48 +0,0 @@ -options gen2 -module m - -require daslib.apply -require macros -require strings -require b -require daslib.ast_boost -require rtti - -def handleDuplicateTransaction() { - var i = 0 - apply(p) <| $(name : string; field) { - if (typeinfo is_table(field)) { - for (key in keys(field)) { - print("{key}") - i = i + length(key) - } - } - } - return i > 5 -} - - -def crashThere(field : auto(T)) { - var c : T - for (k, v in keys(field), values(field)) { - c[k] := v - } - print("{c}") -} - - -def makeDeltaTransaction(profile) { - var i = 0 - apply(profile) <| $(name : string; field) { - static_if (typeinfo is_table(field)) { - crashThere(field) - } - } -} - -[function_macro(name="unique_transaction")] -class UniqueTransaction : AppendCondAnnotation { - def override getCondName() : string { - return "handleDuplicateTransaction" - } -} diff --git a/examples/test/misc/macros.das b/examples/test/misc/macros.das deleted file mode 100644 index c167581751..0000000000 --- a/examples/test/misc/macros.das +++ /dev/null @@ -1,27 +0,0 @@ -options gen2 -module macros - -require rtti -require ast public -require daslib/ast_boost public - -def private prepend_cond(var fn : FunctionPtr; cond : string) { - var inscope iblk <- fn.body - var inscope blk <- new ExprBlock(at = fn.at) - var inscope ifm <- new ExprCall(at = fn.at, name := cond) - var inscope ife <- new ExprIfThenElse(at = fn.at, cond <- ifm, if_true := iblk) - emplace(blk.list, ife) - unsafe { - fn.body <- blk - } -} - - -class AppendCondAnnotation : AstFunctionAnnotation { - def abstract getCondName() : string - - def override apply(var func : FunctionPtr; var group : ModuleGroup; args : AnnotationArgumentList; var errors : das_string) : bool { - prepend_cond(func, self->getCondName()) - return true - } -} \ No newline at end of file diff --git a/examples/test/misc/mangled_name.das b/examples/test/misc/mangled_name.das deleted file mode 100644 index 2af8c44022..0000000000 --- a/examples/test/misc/mangled_name.das +++ /dev/null @@ -1,16 +0,0 @@ -options gen2 -require ast -require rtti -require daslib/ast_boost - -[export] -def main { - using() <| $(var lib : ModuleGroup) { - var inscope p <- parse_mangled_name("CN<;f>0U", lib, null) - debug(p) - print("{describe(p)}\n") - p := null - } -} - - diff --git a/examples/test/misc/move_return.das b/examples/test/misc/move_return.das deleted file mode 100644 index 7d55238a49..0000000000 --- a/examples/test/misc/move_return.das +++ /dev/null @@ -1,24 +0,0 @@ -options gen2 -def iliketomoveitmoveit(var a) { - return <- a // TODO: should kaboom here -} - -def takeit(var a) { - print("takit it {a} LC = {lock_count(a)}\n") -} - -[export] -def main { - var a : array> - var b : array> - resize(a, 10) - a[0] |> push(1) - for (t in a[0]) { - takeit(iliketomoveitmoveit(a)) - } - // b <- a - print("a = {a} LC = {lock_count(a)}\n") -} - - -options log diff --git a/examples/test/misc/out_of_heap.das b/examples/test/misc/out_of_heap.das deleted file mode 100644 index a96ec80283..0000000000 --- a/examples/test/misc/out_of_heap.das +++ /dev/null @@ -1,15 +0,0 @@ -options gen2 -options heap_size_limit = 8192 - -struct Foo { - data : uint8[1024] -} - -[export] -def main { - for (i in range(1024)) { - print("allocating Foo N{i}..\n") - var pfoo = new Foo() - pfoo.data[0] = uint8(i) - } -} diff --git a/examples/test/misc/padd.das b/examples/test/misc/padd.das deleted file mode 100644 index 45204008c5..0000000000 --- a/examples/test/misc/padd.das +++ /dev/null @@ -1,36 +0,0 @@ -options gen2 -module padd - -require daslib/ast_boost -require daslib/macro_boost -require daslib/templates_boost - -[type_macro(name="padd_dim")] -class PaddDimMacro : AstTypeMacro { - def override visit(prog : ProgramPtr; mod : Module?; td : TypeDeclPtr; passT : TypeDeclPtr) : TypeDeclPtr { - if (length(td.dimExpr) != 3) { - macro_error(compiling_program(), td.at, "expecting 2 arguments") - return <- TypeDeclPtr() - } - if (!(td.dimExpr[2] is ExprConstInt)) { - macro_error(compiling_program(), td.at, "expecting constant integer (size)") - return <- TypeDeclPtr() - } - let count = (td.dimExpr[2] as ExprConstInt).value - if (td.dimExpr[1]._type == null) { - // type is not inferred, which means we are inferring generic type - var inscope auto_type : TypeDeclPtr - if (td.dimExpr[1] is ExprTypeDecl) { - auto_type |> move_new <| clone_type((td.dimExpr[1] as ExprTypeDecl).typeexpr) - } else { - auto_type |> move_new <| new TypeDecl(baseType = Type.autoinfer) - } - auto_type.dim |> push(count) - return <- auto_type - } - var inscope final_type <- clone_type(td.dimExpr[1]._type) - final_type.dim |> push(count) - return <- final_type - } -} - diff --git a/examples/test/misc/padd_example.das b/examples/test/misc/padd_example.das deleted file mode 100644 index aa6b4dab45..0000000000 --- a/examples/test/misc/padd_example.das +++ /dev/null @@ -1,14 +0,0 @@ -options gen2 -require padd - -def take_foo(foo : $padd_dim(type, 14)) : TT { - debug(foo) - return default -} - -[export] -def main { - var foo : $padd_dim(type, 14) - print("foo = {foo}\n") - take_foo(foo) -} diff --git a/examples/test/misc/padd_function.das b/examples/test/misc/padd_function.das deleted file mode 100644 index 3e84bf1666..0000000000 --- a/examples/test/misc/padd_function.das +++ /dev/null @@ -1,119 +0,0 @@ -options gen2 -module padd_function - - -require daslib/typemacro_boost -require daslib/templates_boost - -struct public PaddStructureBase {} - -[type_macro(name="padd_structure")] -class PaddDimMacro : AstTypeMacro { - def override visit(prog : ProgramPtr; mod : Module?; td, passT : TypeDeclPtr) : TypeDeclPtr { - if (length(td.dimExpr) != 3) { - macro_error(compiling_program(), td.at, "expecting 2 arguments") - return <- TypeDeclPtr() - } - var count = -1 - if (td.dimExpr[2] is ExprConstInt) { - count = (td.dimExpr[2] as ExprConstInt).value - } elif (td.dimExpr[2] is ExprConstPtr) { - count = -1 - } else { - macro_error(compiling_program(), td.at, "expecting integer argument or null") - return <- TypeDeclPtr() - } - if (!(td.dimExpr[1] is ExprTypeDecl)) { - macro_error(compiling_program(), td.at, "expecting type argument") - return <- TypeDeclPtr() - } - var pbase = compiling_program() |> find_unique_structure("padd_function::PaddStructureBase") - if (td.dimExpr[1]._type == null) { - // we are inferring generic here - if (passT == null) { - macro_error(compiling_program(), td.at, "expecting argument type to infer") - return <- TypeDeclPtr() - } - // so we return whatever was passed, assuming its a PaddStructure - if (passT.baseType == Type.tStructure && passT.structType.parent == pbase) { - let field = passT.structType |> find_structure_field("data") - // we need to check if size matches - if (field == null || field._type == null) { - return <- TypeDeclPtr() - } - if (length(field._type.dim) != 1) { - return <- TypeDeclPtr() - } - if (count != -1 && count != field._type.dim[0]) { - return <- TypeDeclPtr() - } - // we need to check if type matches - var inscope argT <- clone_type((td.dimExpr[1] as ExprTypeDecl).typeexpr) - if (argT == null) { - return <- TypeDeclPtr() - } - if (argT.isAutoOrAlias) { - var inscope fieldT <- clone_type(field._type) - var inscope resT <- infer_generic_type(argT, fieldT, true, true) - if (resT == null) { - macro_error(compiling_program(), td.at, "type mismatch, expecting {describe(argT)} got {describe(fieldT)}") - return <- TypeDeclPtr() - } - if (!fieldT |> is_same_type(resT, RefMatters.no, ConstMatters.no, TemporaryMatters.yes)) { - macro_error(compiling_program(), td.at, "type mismatch, expecting {describe(argT)} got {describe(fieldT)}") - return <- TypeDeclPtr() - } - compiling_program() |> update_alias_map(argT, resT) - } else { - // do we need to check if passT is auto and do 2-sided infer? - var inscope fieldT <- clone_type(field._type) - fieldT.dim |> pop - if (!fieldT |> is_same_type(argT, RefMatters.no, ConstMatters.no, TemporaryMatters.yes)) { - macro_error(compiling_program(), td.at, "type mismatch, expecting {describe(argT)} got {describe(fieldT)}") - return <- TypeDeclPtr() - } - } - return <- clone_type(passT) - } - return <- TypeDeclPtr() - } else { - if (td.dimExpr[1]._type.isAutoOrAlias) { - return <- TypeDeclPtr() - } - var inscope elemType <- clone_type(td.dimExpr[1]._type) - elemType.flags &= ~TypeDeclFlags.ref - let hash = elemType |> get_mangled_name() - let structName = "PaddStructure`{count}`{hash}" - var st_ptr = compiling_program() |> find_unique_structure(structName) - if (st_ptr == null) { - var inscope st <- new Structure(at = td.at, name := structName) - st.flags |= StructureFlags.privateStructure | StructureFlags.generated - st.parent = pbase - elemType.dim |> push(count) - st |> add_structure_field("data", clone_type(elemType), default) - st_ptr = get_ptr(st) - compiling_module() |> add_structure(st) - } - return <- new TypeDecl(at = td.at, baseType = Type.tStructure, structType = st_ptr) - } - } -} - -/* -[typemacro_function] -def padd_structure ( macroArgument:TypeDeclPtr; elemType:TypeDeclPtr; count:int ) - if elemType==null - return <- new [[TypeDecl() at=macroArgument.at, baseType=Type autoinfer]] - let structName = "PaddStructure`{count}`{macroArgument.at.line}`{macroArgument.at.column}" - var st_ptr = compiling_program() |> find_unique_structure(structName) - if st_ptr == null - var inscope st <- new [[Structure() at=macroArgument.at, name := "PaddStructure_{count}_{macroArgument.at.line}_{macroArgument.at.column}"]] - st.flags |= StructureFlags privateStructure | StructureFlags generated - var inscope st_type <- clone_type(elemType) - st_type.dim |> push(count) - st |> add_structure_field ( "data", clone_type(st_type), [[ExpressionPtr]]) - st_ptr = get_ptr(st) - compiling_module() |> add_structure(st) - return <- new [[TypeDecl() at=macroArgument.at, baseType=Type tStructure, structType=st_ptr]] -*/ - diff --git a/examples/test/misc/padd_function_example.das b/examples/test/misc/padd_function_example.das deleted file mode 100644 index 166931f81c..0000000000 --- a/examples/test/misc/padd_function_example.das +++ /dev/null @@ -1,10 +0,0 @@ -options gen2 -require padd_function - -[export] -def main { - var foo : $padd_structure(type, 13 + 1) - print("foo = {foo}\n") -} - -options log diff --git a/examples/test/misc/producer-consumer.das b/examples/test/misc/producer-consumer.das deleted file mode 100644 index 3f32a4184e..0000000000 --- a/examples/test/misc/producer-consumer.das +++ /dev/null @@ -1,43 +0,0 @@ -options gen2 -require daslib/jobque_boost - -struct OneJob { - name : string -} - -[export] -def main { - let some_job_list <- [for (x in range(10)); "job_{x}"] - let total_jobs = length(some_job_list) - let total_threads = 3 // get_total_hw_threads() - 2 - with_channel(total_jobs) <| $(channel) { - with_job_status(total_threads) <| $(completion) { - // create threads - for (t in range(total_threads)) { - new_thread <| @ { - print("in thread {t}\n") - for_each_clone(channel) <| $(j : OneJob#) { - // each thread reads from channel, until its empty - print("in thread {t} job {j.name}\n") - } - channel |> release - // once done, notifies for the job completion - completion |> notify_and_release - print("done thread {t}\n") - } - } - // this could be anywhere - print("pushing jobs\n") - for (jb in some_job_list) { - channel |> push_clone(OneJob(name = jb)) - channel |> notify - } - print("done pushing jobs\n") - // wait for threads to finish - completion |> join // if we comment out this line, we get `job status beeing deleted while being used` exception - } - print("done\n") - } -} - - diff --git a/examples/test/misc/qfn.das b/examples/test/misc/qfn.das deleted file mode 100644 index 02e765fe18..0000000000 --- a/examples/test/misc/qfn.das +++ /dev/null @@ -1,23 +0,0 @@ -options gen2 -module qfn public - -require ast -require daslib/ast_boost -require daslib/templates_boost - -struct CommandBuffer { - cmd : int -} - -[structure_macro(name=qfn)] -class QfnFields : AstStructureAnnotation { - def override apply(var st : StructurePtr; var group : ModuleGroup; args : AnnotationArgumentList; var errors : das_string) : bool { - var inscope sendFn <- qmacro_function("send") <| $(var cb : CommandBuffer&; cmd : $t(st)) : bool { - print("send({cb},{cmd})\n") - return true - } - sendFn.flags |= FunctionFlags.exports - compiling_module() |> add_function(sendFn) - return true - } -} diff --git a/examples/test/misc/qfn_test.das b/examples/test/misc/qfn_test.das deleted file mode 100644 index a56c081c8f..0000000000 --- a/examples/test/misc/qfn_test.das +++ /dev/null @@ -1,16 +0,0 @@ -options gen2 -require qfn - -[qfn] -struct FooBar { - a : int -} - -[export] -def main { - var buf = CommandBuffer() - var foo = FooBar(a = 1) - send(buf, foo) -} - - diff --git a/examples/test/misc/regex_lite.das b/examples/test/misc/regex_lite.das deleted file mode 100644 index 6fcfb9dd95..0000000000 --- a/examples/test/misc/regex_lite.das +++ /dev/null @@ -1,143 +0,0 @@ -options gen2 -// options log = true -// options log_aot = true - -require daslib/regex -require daslib/regex_boost -require strings -require fio - -let { - test_and_log = true - only_find_one_result = true -} - -[export] -def test { - static_if (test_and_log) { - test_regex() - } - - var r1 <- %regex~[\w\.+-]+@[\w\.-]+\.[\w\.-]+%% - static_if (test_and_log) { - regex_debug(r1) - } - - let test = "first.last@learnxinyminutes.com" - let res = regex_match(r1, test) - assert(res != -1) - - let test2 = "first" - let res2 = regex_match(r1, test2) - assert(res2 == -1) - - // regex_debug(r1) - let root = get_das_root() - let input = root + "/../REGEX/input-text.txt" - fopen(input, "rb") <| $(f) { - if (f != null) { - var dict : table - let data = fread(f) - profile(5, "regex email") <| $() { - regex_foreach(r1, data) <| $(r) { - static_if (test_and_log) { - print("match {slice(data,r.x,r.y)}\n") - } - return !only_find_one_result - } - } - } else { - print("can't open ") - } - } - return true -} - -def test_re(var regex : Regex; matches : array; nonmatches : array) { - print("re is:\n") - regex_debug(regex) - var failed = false - for (m in matches) { - let ma = regex_match(regex, m) - print("matching `{m}` -> {ma} {ma==-1 ? "failed" : "ok"}\n") - failed ||= ma == -1 - } - for (m in nonmatches) { - let ma = regex_match(regex, m) - print("^matching `{m}` -> {ma} {ma!=-1 ? "failed" : "ok"}\n") - failed ||= ma != -1 - } - print("{failed ? "failed" : "ok"}\n\n") - assert(!failed) - delete regex -} - -def test_group(var regex : Regex; match : string; groups : array) { - print("re is:\n") - regex_debug(regex) - if (length(regex.groups) == 0) { - print("has no groups\n") - assert(false) - } - let ma = regex_match(regex, match) - assert(ma != -1, "failed to match\n") - let tot = length(regex.groups) - 1 - assert(tot == length(groups), "group count mismatch") - var failed = false - for (x in range(tot)) { - let grp = regex_group(regex, x + 1, match) - let cgrp = groups[x] - if (grp != cgrp) { - print("failed, expecting {x}={cgrp}, got {grp}") - failed = true - } - } - assert(!failed) - delete regex -} - -def test_replace(var regex : Regex; input : string; expected : string) { - let res = regex_replace(regex, input, $(a) => "") - print("replacing `{input}` -> `{res}`\n") - print("expected `{expected}`\n") - assert(res == expected) - delete regex -} - -def test_regex { - // character - test_re(%regex~a%%, [ "a"], array("", "b", "ba")) - // union - test_re(%regex~cat|dog%%, array("cat", "dog", "cats"), array("at", " cat", "doog")) - test_re(%regex~cat|dog|bat%%, array("cat", "dog", "cats", "bats"), array("at", " cat", "doog", "at")) - // set & negatvie set - test_re(%regex~[0-9a-zA-Z_]%%, array("0", "3", "9", "a", "e", "z", "A", "Q", "Z", "_"), array("#", "*")) - test_re(%regex~[\w]%%, array("0", "3", "9", "a", "e", "z", "A", "Q", "Z", "_"), array("#", "*")) - test_re(%regex~\w%%, array("0", "3", "9", "a", "e", "z", "A", "Q", "Z", "_"), array("#", "*")) - test_re(%regex~[^0-9a-zA-Z_]%%, array("#", "*"), array("0", "3", "9", "a", "e", "z", "A", "Q", "Z", "_")) - // any, concat - test_re(%regex~cat.%%, array("catt", "cats"), array("cat", " cat")) - test_re(%regex~(cat)(dog)(bat)%%, [ "catdogbat"], array("cat", " cat", "catdog", "dogbat")) - // eos - test_re(%regex~cat$%%, [ "cat"], array("cattt", " cat")) - // + - test_re(%regex~ab+%%, array("ab", "abb", "abbbc"), array("a", " ab", "bbb")) - test_re(%regex~(cat)+%%, array("cat", "catcat"), array("dog", "caat")) - // * - test_re(%regex~ab*%%, array("a", "ab", "abb", "abbbc"), array(" ab", "bbb")) - test_re(%regex~a(cat)*%%, array("a", "acat", "acatcat"), array("dog", "caat", "cat")) - test_re(%regex~a*(cat)%%, array("cat", "acat", "aaacat"), array("dog", "caat")) - // ? - test_re(%regex~ab?%%, array("a", "ab", "abb"), array("b", " ab", "bbb")) - test_re(%regex~(cat)?x%%, array("catx", "x"), array("dog", "caat")) - // match2 - test_re(%regex~[a-z.]+.com%%, [ "abra.com"], array("1", "2")) - - // gropus - test_group( %regex~i have a (cat|dog)%%, "i have a cat.", [ "cat"]) - test_group( %regex~(this|that) is a (book|table|car)%%, "that is a table", array("that", "table")) - - // replace - test_replace( %regex~[^a-z]*%%, "ch!ar#l@y123be&%rt!", "charlybert") -} - diff --git a/examples/test/misc/reification.das b/examples/test/misc/reification.das deleted file mode 100644 index fe3bb3b087..0000000000 --- a/examples/test/misc/reification.das +++ /dev/null @@ -1,132 +0,0 @@ -options gen2 -options rtti - -require daslib/templates_boost -require daslib/ast_boost -require daslib/strings -require daslib/defer - -def test_block_to_array { - var inscope blk_array <- qmacro_block_to_array <| $() { - a <- 1 - b <- 2 - c <- 3 - } - for (a in blk_array) { - print("{describe(a)}\n") - } - delete blk_array -} - -def test_addr { - let foobar = "FOO_BAR" - var inscope aaddr <- qmacro(@@ $i(foobar)) - print("\nADDR IS:\n{describe(aaddr)}\n") -} - -def test_fun_arg { - var inscope foo <- array( - new Variable(name := "v1", _type <- qmacro_type(type)), - new Variable(name := "v2", _type <- qmacro_type(type), init <- qmacro(1.2)) - ) - var inscope fun <- qmacro_function("add") <| $(a : int; $a(foo); b : int) { - return a + b - } - print("\nFUNCTION ARGUMENTS ARE:\n{describe(fun)}\n") - delete fun -} - -def test_var { - var inscope tt <- typeinfo ast_typedecl(type) - var inscope vvar <- qmacro_variable("foo", type<$t(tt)?>) - print("\nVARIABLE IS:\n{describe(vvar)}\n") -} - -def test_type { - var inscope argT <- typeinfo ast_typedecl(type) - var inscope resT <- qmacro_type(type<$t(argT) ???>) - print("\nTYPE IS:\n{describe(resT)}\n") -} - -def test_fun { - var inscope argT <- typeinfo ast_typedecl(type) - var inscope fun <- qmacro_function("add") <| $(a : $t(argT); b : float) { - return $i("a") + b - } - print("\nFUNCTION REIFICATION IS:\n{describe(fun)}\n") - delete fun -} - -def test_for { - var bus = "BUS" - var inscope blk <- qmacro_block <| $() { - for ($i(bus) in foobar) { - print("{$i(bus)}\n") - } - } - print("\nFOR REIFICATION IS:\n{describe(blk)}\n") - delete blk -} - -def test_regular { - let bus = "bus_variable_name" - let car = "car_variable_name" - let cll = "call_me_maybe" - let bar = "barbar" - var a1 = 1 - var a2 = a1 + 1 - var a3 = a1 + 13 - var inscope expr <- quote(length(bus)) - var inscope qqblk : array - for (i in range(3)) { - qqblk |> emplace_new <| qmacro(print("{$v(i)}\n")) - } - var inscope arguments <- array(quote(a1), quote(a2)) - var inscope aargs <- array(quote(a1), quote(a2), quote(a3)) - var inscope subtype <- typeinfo ast_typedecl(type) - var inscope blk <- qmacro <| $() { - let t = $i(bus) - let q = $v((a1, car)) - let lb = $e(expr) - print("{q}{t}{lb}\n") - $b(qqblk) - somefunnycall(1, $a(arguments), 2) - var aaa <- $a(aargs) - var a : $t(subtype) - $c(cll)(1, 2, $a(arguments), 3) - foo.$f(bar) = 13 - foo?.$f("{bar}`bar") = 14 - foo.$f(bar).$f(bar) = 15 - foo as $f(bar) = 13 - if (foo is $f(bar)) { - print("hello!\n") - } - let qq = @@$c(cll) - let $i(bus) = "busbus" - invoke <| $($i(bus) : bool) { - pass - } - } - print(describe(blk)) - delete blk -} - -def test_make_struct { - let foobar = "FOO_BAR" - var inscope mks <- qmacro(Foo($f(foobar) = 13)) - print("\nADDR IS:\n{describe(mks)}\n") -} - -[export] -def main { - test_make_struct() - test_block_to_array() - test_addr() - test_regular() - test_fun() - test_type() - test_var() - test_fun_arg() - test_for() -} - diff --git a/examples/test/misc/rst_comment_test.das b/examples/test/misc/rst_comment_test.das deleted file mode 100644 index 8d7c326aab..0000000000 --- a/examples/test/misc/rst_comment_test.das +++ /dev/null @@ -1,49 +0,0 @@ -options gen2 -require daslib/rst_comment - -struct Foo { - /* this is a C comment in structure */ - a : int // this is a C++ comment in the field a - no_comment : float - b, c : int// this is a C++ comment for the fields b, c -} - -struct Bar { - // this is a C++ comment in structure - a : int -} - -let some_const = 1234 // this is a C++ comment for a constant - -[export] -def foo(a, b : int) { - // this is a C++ comment - pass -} - -[export] -def bar(a, b : int) { - /* this is a C comment */ - pass -} - -class MyClass { - /* this is a C comment in class */ - a : int // this is a C++ comment in the class field a - no_comment : float - b, c : int// this is a C++ comment for the class fields b, c - def abstract abstract_method(t : int) : void // this is comment for an abstract method - def no_comment_method { - pass - } - def foo(t : int) : int /* this is comment for the method foo */ { - // this is a C++ comment, for the method foo - return 1 - } -} - -[export] -def main { - let c = new MyClass() - print("hello, world!\n") -} diff --git a/examples/test/misc/shutdown_finalize.das b/examples/test/misc/shutdown_finalize.das deleted file mode 100644 index ead1ad56b5..0000000000 --- a/examples/test/misc/shutdown_finalize.das +++ /dev/null @@ -1,35 +0,0 @@ -options gen2 -options log - -require daslib/static_let - -struct Foo { - a : int -} - -def Foo() { - print("in foo c-tor\n") - var f : Foo - f.a = 5 - return f -} - -def operator delete(var f : Foo) { - print("killing foo\n") -} - -[finalize] -def byebye() { - print("bytebye, world\n") -} - -[export] -def main() { - static_let_finalize <| $() { - var x = new Foo() - } - print("hello, world\n") - print("x = {x}\n") -} - -options log diff --git a/examples/test/misc/simple_interpreter.das b/examples/test/misc/simple_interpreter.das deleted file mode 100644 index 1038c1b1aa..0000000000 --- a/examples/test/misc/simple_interpreter.das +++ /dev/null @@ -1,26 +0,0 @@ -options gen2 -class Node { - def eval(i : int) { - pass - } -} - -// TODO: early out of empty array causes lock underflow -// need to go to appropriate source out, not just endloop - -[jit] -def eval(var a : array) { - for (n, i in a, count()) { - (*n)->eval(i) - } -} - -[export] -def main { - var A <- array(1, 2, 3, 4, 5, 6, 7, 8, 9) - for (a, c in A, count(0, 2)) { - print("a = {a} c = {c}\n") - } -} - -// options log_cpp diff --git a/examples/test/misc/stackwalk.das b/examples/test/misc/stackwalk.das deleted file mode 100644 index 2eaec668f0..0000000000 --- a/examples/test/misc/stackwalk.das +++ /dev/null @@ -1,117 +0,0 @@ -options gen2 -options debugger = true - -require rtti -require debugapi - -// sample of debug agent - -class SampleDataWalker : DapiDataWalker { - def override Float(var value : float&) : void { - print("[float] {value}") - } - def override Int(var value : int&) : void { - print("[int] {value}") - } -} - -class SampleStackWalker : DapiStackWalker { - data_walker_adapter : smart_ptr - data_walker : SampleDataWalker? - def SampleStackWalker { - data_walker = new SampleDataWalker() - unsafe { - data_walker_adapter <- make_data_walker(data_walker) - } - } - def operator delete { - unsafe { - delete data_walker_adapter - delete data_walker - } - } - def override onCallAOT(pp : Prologue; fileName : string#) : void { - print("AOT {fileName}\n") - } - def override onCallJIT(pp : Prologue; fileName : string#) : void { - print("JIT {fileName}\n") - } - def override onCallAt(pp : Prologue; info : FuncInfo; at : LineInfo) : void { - print("{info.name} at {at}\n") - } - def override onCall(pp : Prologue; info : FuncInfo) : void { - print("{info.name}\n") - } - def override onArgument(info : FuncInfo; index : int; vinfo : VarInfo; arg : float4) : void { - print("\targ {vinfo.name} ") - print(sprint_data(arg, type_info(vinfo), print_flags.singleLine)) - print("\n") - } - def override onVariable(inf : FuncInfo; vinfo : LocalVariableInfo; arg : void?; inScope : bool) : void { - print("\tvar {vinfo.name} ") - if (inScope) { - if (arg != null) { - // walk_data(data_walker_adapter,arg,*type_info(vinfo)) - print(sprint_data(arg, type_info(vinfo), print_flags.singleLine)) - } else { - print("optimized out") - } - } else { - print("out of scope") - } - print("\n") - } -} - -class SampleDebugAgent : DapiDebugAgent { - walker_adapter : smart_ptr - walker : SampleStackWalker? - def SampleDebugAgent { - walker = new SampleStackWalker() - unsafe { - walker_adapter <- make_stack_walker(walker) - } - } - def operator delete { - unsafe { - delete walker_adapter - delete walker - } - } - def override onBreakpoint(var ctx : Context; at : LineInfo; reason, text : string) : void { - print("{ctx} {ctx.name} : breakpoint at line {int(at.line)}, {reason}, {text}\n") - set_single_step(ctx, true) - } - def override onSingleStep(var ctx : Context; at : LineInfo) : void { - print("{ctx} {ctx.name} : step at {int(at.line)}\n") - walk_stack(walker_adapter, ctx, at) - } -} - -[export] -def debug_agent(ctx : Context) { - assert(this_context().category.debug_context) - install_new_debug_agent(new SampleDebugAgent(), "debug") -} - -def foo(var x : int&) { - x ++ - x ++ -} - -[export] -def main { - this_context().name := "stackwalk main context" - fork_debug_agent_context(@@debug_agent) - var x = 5 - breakpoint() - x = 6 - for (t in range(10)) { - print("x={x} t={t}\n") - x ++ - foo(x) - } - var z = 13 - z ++ -} - diff --git a/examples/test/misc/t_counter.das b/examples/test/misc/t_counter.das deleted file mode 100644 index 5cd8b49b0f..0000000000 --- a/examples/test/misc/t_counter.das +++ /dev/null @@ -1,54 +0,0 @@ -options gen2 - -module t_counter public - -require daslib/ast_boost -require daslib/templates_boost -require daslib/typemacro_boost - -struct template TemplateCounter { - counter : CounterType // we add this one in a typemacro (or we can use $t(counter_type)) - def TemplateCounter { - counter = CounterType($v(initialValue)) - } - def next { - counter ++ - } - def value { - return counter - } -} - -def template print_counter(c : $t(resType)) { - print("Counter value: {c.value()}\n") -} - -[typemacro_function] -def counter(macroArgument, passArgument : TypeDeclPtr; counter_type : TypeDeclPtr; initialValue : int = 123) : TypeDeclPtr { - var inscope template_type <- typeinfo ast_typedecl(type) - var inscope template_arguments <- [ - TypeMacroTemplateArgument(name="CounterType", argument_type <- clone_type(counter_type)) - ] - var extra_template_arguments <- [ - ("initialValue", "{initialValue}") - ] - // code bellow can be auto-generated - if (passArgument != null) { - return <- TypeDeclPtr() if (!is_typemacro_template_instance(passArgument, template_type, extra_template_arguments)) - return <- TypeDeclPtr() if (!infer_struct_aliases(passArgument.structType, template_arguments)) - return <- infer_template_types(passArgument, template_arguments) - } else { - return <- TypeDeclPtr() if (!verify_arguments(template_arguments)) - var struct_name = template_structure_name(template_type.structType, template_arguments, extra_template_arguments) - var existing_struct = compiling_program().find_unique_structure(struct_name) - return <- new TypeDecl(baseType = Type.tStructure, structType = existing_struct, at = template_type.at) if (existing_struct != null) - var inscope resType <- qmacro_template_class(struct_name, type) - make_typemacro_template_instance(resType.structType, template_type.structType, extra_template_arguments) - add_structure_aliases(resType.structType, template_arguments) - // for demo purposes, we can add a print_counter function here - var inscope print_fn <- qmacro_template_function(@@print_counter) - add_function(compiling_module(), print_fn) - return <- resType - } -} - diff --git a/examples/test/misc/t_counter_example.das b/examples/test/misc/t_counter_example.das deleted file mode 100644 index 20a8751f3d..0000000000 --- a/examples/test/misc/t_counter_example.das +++ /dev/null @@ -1,10 +0,0 @@ -require t_counter - -typedef CounterInt32 = $counter(type) - -[export] -def main { - var counter = CounterInt32() - counter.next() - print_counter(counter) -} diff --git a/examples/test/misc/template_example.das b/examples/test/misc/template_example.das deleted file mode 100644 index 44cadf3d7b..0000000000 --- a/examples/test/misc/template_example.das +++ /dev/null @@ -1,27 +0,0 @@ -options gen2 -options log = true - -require ast -require daslib/ast_boost -require daslib/templates_boost - -[export] -def test { - - var inscope expr <- quote() <| $() { - x ++ - print("{x}\n") - } - - print(describe(expr)) - - var inscope rules : Template - rules |> replaceVariable("x") <| new ExprVar(name := "y") - rules |> renameVariable("x", "y") - - apply_template(rules, expr.at, expr) - - print(describe(expr)) - - return true -} diff --git a/examples/test/misc/test_constant_expression.das b/examples/test/misc/test_constant_expression.das deleted file mode 100644 index fbac088c6f..0000000000 --- a/examples/test/misc/test_constant_expression.das +++ /dev/null @@ -1,17 +0,0 @@ -options gen2 -require daslib/constant_expression - -[constant_expression(constString)] -def take_const_arg(boo : bool; constString : string) { - print("constant string is = {constString}\n") -} - -[export] -def main { - take_const_arg(true, "hello world") - take_const_arg(true, "goodbye world") -} - -options log - - diff --git a/examples/test/misc/test_debug_eval.das b/examples/test/misc/test_debug_eval.das deleted file mode 100644 index 76ba5ce94f..0000000000 --- a/examples/test/misc/test_debug_eval.das +++ /dev/null @@ -1,135 +0,0 @@ -options gen2 -require daslib/debug_eval -require UnitTest - -def print(result : Result) { - if (!empty(result.error)) { - print("error: {result.error}\n") - } - unsafe { - var text : string - if (result.data != null) { - text = sprint_data(result.data, addr(result.tinfo), print_flags_debug) - } else { - text = sprint_data(result.value, addr(result.tinfo), print_flags_debug) - } - print("{text}\n") - } -} - -let print_flags_debug = ( - print_flags.escapeString - | print_flags.namesAndDimensions - | print_flags.singleLine - // | print_flags humanReadable - // | print_flags typeQualifiers - // | print_flags refAddresses - ) - -def eval_test(context : table; expr : string) : string { - var result = debug_eval(context, expr) - if (!empty(result.error)) { - return result.error - } - if (result.data != null) { - return sprint_data(result.data, unsafe(addr(result.tinfo)), print_flags_debug) - } else { - return sprint_data(result.value, unsafe(addr(result.tinfo)), print_flags_debug) - } -} - -struct Foo { - a : int - b : float -} - -[export] -def main { - var context : table - - var temp_int : int = 13 - var temp_str = "hello, world" - var temp_dim_int = fixed_array(1, 2, 3, 4, 5, 6) - var temp_arr_string <- [ "a", "b", "c", "d", "e"] - var temp_struct = Foo(a = 1, b = 2.23f) - var temp_float4 = float4(1, 2, 3, 4) - var temp_tuple = (3, 0.14f) - var temp_tab <- {1 => "one", 2 => "two", 3 => "three"} - var temp_foo = TestObjectFoo(fooData = 13) - unsafe { - context["temp_int"] = Result(data = addr(temp_int), tinfo = typeinfo rtti_typeinfo(temp_int)) - context["temp_str"] = Result(data = addr(temp_str), tinfo = typeinfo rtti_typeinfo(temp_str)) - context["temp_dim_int"] = Result(data = addr(temp_dim_int), tinfo = typeinfo rtti_typeinfo(temp_dim_int)) - context["temp_arr_string"] = Result(data = addr(temp_arr_string), tinfo = typeinfo rtti_typeinfo(temp_arr_string)) - context["temp_struct"] = Result(data = addr(temp_struct), tinfo = typeinfo rtti_typeinfo(temp_struct)) - context["temp_float4"] = Result(data = addr(temp_float4), tinfo = typeinfo rtti_typeinfo(temp_float4)) - context["temp_tuple"] = Result(data = addr(temp_tuple), tinfo = typeinfo rtti_typeinfo(temp_tuple)) - context["temp_tab"] = Result(data = addr(temp_tab), tinfo = typeinfo rtti_typeinfo(temp_tab)) - context["temp_foo"] = Result(data = addr(temp_foo), tinfo = typeinfo rtti_typeinfo(temp_foo)) - } - - context |> debug_eval("temp_foo.fooData") |> print - context |> debug_eval("temp_tab") |> print - context |> debug_eval("temp_tab[1]") |> print - context |> debug_eval("temp_tab[2]") |> print - context |> debug_eval("temp_tab[-1]") |> print - - context |> debug_eval("temp_tuple") |> print - context |> debug_eval("temp_tuple._0") |> print - context |> debug_eval("temp_tuple._1") |> print - - context |> debug_eval("temp_float4") |> print - context |> debug_eval("temp_float4.x") |> print - context |> debug_eval("temp_float4.y") |> print - context |> debug_eval("temp_float4.z") |> print - context |> debug_eval("temp_float4.w") |> print - - context |> debug_eval("temp_int+3") |> print - context |> debug_eval("temp_str") |> print - context |> debug_eval("temp_str[2]") |> print - context |> debug_eval("temp_dim_int") |> print - context |> debug_eval("temp_dim_int[2]") |> print - context |> debug_eval("temp_arr_string") |> print - context |> debug_eval("temp_arr_string[1]") |> print - context |> debug_eval("temp_arr_string[1][0]") |> print - context |> debug_eval("temp_struct") |> print - context |> debug_eval("temp_struct.a") |> print - context |> debug_eval("temp_struct.b") |> print - - context |> debug_eval("length(temp_str)") |> print - - verify("true" == context |> eval_test("true")) - verify("false" == context |> eval_test("false")) - verify("false" == context |> eval_test("1==2")) - verify("true" == context |> eval_test("1==2-1")) - verify("true" == context |> eval_test("!(1+1!=2)")) - verify("true" == context |> eval_test("1<=2")) - verify("true" == context |> eval_test("1!=2")) - verify("false" == context |> eval_test("1>=2")) - verify("false" == context |> eval_test("1>2")) - verify("true" == context |> eval_test("1<2")) - - verify(context |> eval_test("-2+2") == "0") - verify(context |> eval_test("-2*2") == "-4") - verify(context |> eval_test("1+2+3") == "6") - verify(context |> eval_test("1*2*3") == "6") - verify(context |> eval_test("2+3*4") == "14") - verify(context |> eval_test("4*3+2") == "14") - verify(context |> eval_test("2+2") == "4") - verify(context |> eval_test("(2+3)*4") == "20") - verify(context |> eval_test("+2") == "2") - verify(context |> eval_test("-2") == "-2") - verify(context |> eval_test("-(2+3)*4") == "-20") - verify(context |> eval_test("-") == "unexpected end of stream") - verify(context |> eval_test("2+") == "unexpected end of stream") - verify(context |> eval_test("2/0") == "runtime error, division by 0") - verify(context |> eval_test("2+()") == "unexpected character ), expecting number or (") - verify(context |> eval_test("1+#") == "invalid token invalid character #, expecting number or (") - verify(context |> eval_test("123)))") == "unexpected token 41") - verify(context |> eval_test("foo+1") == "unknown variable foo") - verify(context |> eval_test("0x12+0x1f") == "49") - verify(context |> eval_test("temp_foo.fooData+1") == "14") -} - - - diff --git a/examples/test/misc/test_option_type.das b/examples/test/misc/test_option_type.das deleted file mode 100644 index 5157db9836..0000000000 --- a/examples/test/misc/test_option_type.das +++ /dev/null @@ -1,53 +0,0 @@ -options gen2 -require daslib/templates - -let FAIL_TO_COMPILE = false - -def take_int_or_float(a : int | float) { - print("int_or_float : {typeinfo typename(a)} = {a}\n") -} - -def take_array_of_int_or_float(a : array) { - print("array_of_int_or_float : {typeinfo typename(a)} = {a}\n") -} - - -def take_partial_0(var a : array | table) { - var t : TT -# := a[0] - print("partial = {t}\n") - return t -} - -struct Foo { - a : int -} - -def take_temp_or_not(a : Foo# | Foo) { - print("temp_or_not : {typeinfo typename(a)} = {a}\n") -} - -[export] -def main { - // basic - take_int_or_float(1) - take_int_or_float(2.) - static_if (FAIL_TO_COMPILE) { - take_int_or_float("3") // does not compile - } - // nested - take_array_of_int_or_float([ 1, 2, 3]) - take_array_of_int_or_float([ 1., 2., 3.]) - static_if (FAIL_TO_COMPILE) { - take_array_of_int_or_float([ "1", "2", "3"])// does not compile - } - // partial - take_partial_0([ 1, 2, 3]) - take_partial_0({0 => 1, 1 => 2, 2 => 3, 3 => 4}) - static_if (FAIL_TO_COMPILE) { - take_partial_0({"0" => 1, "1" => 2, "2" => 3, "3" => 4}) - } - // temp or not - take_temp_or_not(Foo(a = 1)) - var t : Foo# - take_temp_or_not(t) -} diff --git a/examples/test/misc/test_reader.das b/examples/test/misc/test_reader.das deleted file mode 100644 index 487bb21908..0000000000 --- a/examples/test/misc/test_reader.das +++ /dev/null @@ -1,30 +0,0 @@ -options gen2 -options no_unused_block_arguments = false -options no_unused_function_arguments = false -options indenting = 4 -options strict_smart_pointers = true - -module test_reader shared public - -require strings -require daslib/ast_boost - -[reader_macro(name="suffix")] -class private SuffixReader : AstReaderMacro { - def override accept(prog : ProgramPtr; mod : Module?; expr : ExprReader?; ch : int; info : LineInfo) : bool { - append(expr.sequence, ch) - if (ends_with(expr.sequence, "%%")) { - let len = length(expr.sequence) - resize(expr.sequence, len - 2) - return false - } else { - return true - } - } - def override suffix(prog : ProgramPtr; mod : Module?; var expr : ExprReader?; info : LineInfo) : string { - return string(expr.sequence) - } - def override visit(prog : ProgramPtr; mod : Module?; expr : smart_ptr) : ExpressionPtr { - return <- new ExprConstString(at = expr.at, value := expr.sequence) - } -} diff --git a/examples/test/misc/test_shader_like.das b/examples/test/misc/test_shader_like.das deleted file mode 100644 index fba123026d..0000000000 --- a/examples/test/misc/test_shader_like.das +++ /dev/null @@ -1,35 +0,0 @@ -options gen2 -require daslib/validate_code -require daslib/lpipe - -options shader_like - -// this fails -var arr : array // 40104: global variable arr requires heap - -def add(a, b) { - return a + b -} - -struct Foo { - a : int = 13 -} - -[export] -def main { - var i = add(1) - lpipe(2) - print("i = {i}\n") - - print("arr = {arr}\n") - - // this fails - var lmb <- @ {// 40104: not shader-like, type requires heap lambda - print("hello\n") // 40104: can't ascend in shader-like code (new [[...]]) - } - invoke(lmb) - - // this fails - var f = new Foo() // 40104: can't new in shader-like code (new ...) -} - diff --git a/examples/test/misc/test_shared_addr.das b/examples/test/misc/test_shared_addr.das deleted file mode 100644 index 4fbba5c892..0000000000 --- a/examples/test/misc/test_shared_addr.das +++ /dev/null @@ -1,18 +0,0 @@ -options gen2 -require daslib/safe_addr - -let shared num2name <- { - 1 => ["one", "один"], - 2 => ["two", "два"] - } - -[export] -def main() { - let t = shared_addr(num2name, 1) - print("t = {t}\n") - for (k, v in keys(num2name), values(num2name)) { - let pA = shared_addr(v) - print("k = {k}, v = {v}, pA = {pA}\n") - } -} - diff --git a/examples/test/misc/test_stages_extra.das b/examples/test/misc/test_stages_extra.das deleted file mode 100644 index 77441b36a0..0000000000 --- a/examples/test/misc/test_stages_extra.das +++ /dev/null @@ -1,18 +0,0 @@ -options gen2 -options persistent_heap = true -options gc - -module test_stages_extra public - -require daslib/decs_boost -require dastest/testing_boost public - -[decs(stage="make_invisible")] -def make_invisible(var visible : bool) { - visible = false -} - -[decs(stage="check_visible")] -def check_visible(visible : bool) { - assert(visible) -} diff --git a/examples/test/misc/trivial_value.das b/examples/test/misc/trivial_value.das deleted file mode 100644 index 566d945863..0000000000 --- a/examples/test/misc/trivial_value.das +++ /dev/null @@ -1,30 +0,0 @@ -options gen2 -options indenting = 4 -options no_aot = true - -module trivial_value - -require ast -require rtti -require daslib/ast_boost -require daslib/templates_boost -require daslib/macro_boost - -// macro, which replaces trivial_value(VAL) -// with: -// @@ (effects : int) // effects : ArmyEffects -// return <- [{ auto[] val => 1.0 }] -[call_macro(name="trivial_value")] -class TrivialValueMacro : AstCallMacro { - def override visit(prog : ProgramPtr; mod : Module?; var call : smart_ptr) : ExpressionPtr { - // check if we get correct number of arguments - macro_verify(call.arguments |> length == 1, prog, call.at, "expecting trivalValue(constant_value)") - // check if argument is constant value (not expression). i.e. "blah" or 1234 - macro_verify((call.arguments[0] is ExprConstString) || (call.arguments[0] is ExprConstInt), - prog, call.at, "expecting constant value, got {call.arguments[0].__rtti}") - // build a block which we are planning to return - return <- qmacro() <| @@(effects : int) { // effects : ArmyEffects - return <- [($e(call.arguments[0]), 1.0)] - } - } -} diff --git a/examples/test/misc/trivial_value_example.das b/examples/test/misc/trivial_value_example.das deleted file mode 100644 index 800745829a..0000000000 --- a/examples/test/misc/trivial_value_example.das +++ /dev/null @@ -1,14 +0,0 @@ -options gen2 - -require trivial_value - -[export] -def test { - let i_val = trivial_value(1) - let i <- invoke(i_val, 13) - print("i = {i}\n") - let s_val = trivial_value("foo") - let s <- invoke(s_val, 13) - print("s = {s}\n") - return true -} diff --git a/examples/test/misc/unroll_example.das b/examples/test/misc/unroll_example.das deleted file mode 100644 index 14b97fbcbf..0000000000 --- a/examples/test/misc/unroll_example.das +++ /dev/null @@ -1,13 +0,0 @@ -options gen2 -require daslib/unroll - -options log - -[export] -def main { - unroll <| $() { - for (i in range(5)) { - print("i = {i}\n") - } - } -} diff --git a/examples/test/misc/uri.das b/examples/test/misc/uri.das deleted file mode 100644 index 737c964128..0000000000 --- a/examples/test/misc/uri.das +++ /dev/null @@ -1,13 +0,0 @@ -options gen2 -require uriparser - -[export] -def test { - let uri = "file:///d%3A/dev/cpp/daScript/cmake_temp/Debug/mod.das" - let path = uri_to_file_name(uri) - let buri = file_name_to_uri(path) - let eburi = escape_uri(buri, true, true) - let ueburi = unescape_uri(eburi) - print("\nuri\t\t{uri}\npath\t\t{path}\nb-uri\t\t{buri}\ne-b-uri\t\t{eburi}\nu-e-b-uri\t{ueburi}\n") - return true -} \ No newline at end of file diff --git a/examples/test/misc/verify_completion_test.das b/examples/test/misc/verify_completion_test.das deleted file mode 100644 index ca5c43e54c..0000000000 --- a/examples/test/misc/verify_completion_test.das +++ /dev/null @@ -1,52 +0,0 @@ -options gen2 -require daslib/validate_code - - -[export, verify_completion] -def bad_loop(var all : iterator; cond_const : bool) { - for (t in all) {// 40104: we don't know if this loop ever finishes. add explicit range - print("t = {t}\n") - } - for (t, r in all, range(100500)) {// this one ok - print("t = {t}\n") - } - var cond = true - while (cond) {// 40104: we can't tell if this `while` loop ever finishes - print("nop\n") - cond = false - } - var tab <- {1 => 1, 2 => 2, 3 => 3} - for (x in tab |> keys()) {// this one ok - we know keys and values are finite - print("x = {x}\n") - } -} - -[export, verify_completion] -def simple_recursive { - print("simple\n") - simple_recursive() // 40104: recursive calls are not allowed -} - -def rec_a { - print("a\n") - rec_b() // 40104: recursive calls are not allowed -> rec_b -> rec_a -> rec_b -} - -def rec_b { - print("b\n") - rec_a() // 40104: recursive calls are not allowed -> rec_a -> rec_b -> rec_a -} - -def rec_c { - rec_a() -} - -[export, verify_completion] -def rec_d { - rec_c() // 40104: recursive calls are not allowed -> rec_c -> rec_a -> rec_b -> rec_a -} - -[export] -def main { - pass -} diff --git a/examples/test/misc/yield_from.das b/examples/test/misc/yield_from.das deleted file mode 100644 index 13f2d14d41..0000000000 --- a/examples/test/misc/yield_from.das +++ /dev/null @@ -1,43 +0,0 @@ -options gen2 -require daslib/coroutines - -struct Tree { - data : int - left, right : Tree? -} - -let tree = new Tree( - data = 5, - left = new Tree(uninitialized - data = 1 - ), - right = new Tree(uninitialized - data = 7, - right = new Tree(uninitialized - data = 10 - ) - ) -); - -def each_async(tree : Tree?) : iterator { - return <- generator() <| $() { - if (tree.left != null) { - yeild_from <| each_async(tree.left) - } - yield tree.data - if (tree.right != null) { - yeild_from <| each_async(tree.right) - } - return false - } -} - -[export] -def main { - for (t in each_async(tree)) { - print("{t}\n") - } -} - - - diff --git a/examples/typeMacro/example1.das b/examples/typeMacro/example1.das deleted file mode 100644 index 1d7b799d23..0000000000 --- a/examples/typeMacro/example1.das +++ /dev/null @@ -1,15 +0,0 @@ -require macro1 - -def print_counter(c : $TemplateCounter < auto(CType) >) { - print("Counter value: {c.value()}\n") -} - -[export] -def main { - var ct = default < $TemplateCounter < int > > - ct.next() - print_counter(ct) - print("Counter value: {ct.value()}\n") -} - -options log diff --git a/examples/typeMacro/example2.das b/examples/typeMacro/example2.das deleted file mode 100644 index b7444982f2..0000000000 --- a/examples/typeMacro/example2.das +++ /dev/null @@ -1,9 +0,0 @@ -require macro2 - -[export] -def main { - var ct = default < $TemplateCounter > - ct.next() - print_counter(ct) - print("Counter value: {ct.value()}\n") -} diff --git a/examples/typeMacro/example3.das b/examples/typeMacro/example3.das deleted file mode 100644 index d5eff6758e..0000000000 --- a/examples/typeMacro/example3.das +++ /dev/null @@ -1,9 +0,0 @@ -require macro3 - -[export] -def main { - var ct = default < $TemplateCounter > - ct.next() - print_counter(ct) - print("Counter value: {ct.value()}\n") -} diff --git a/examples/typeMacro/macro1.das b/examples/typeMacro/macro1.das deleted file mode 100644 index 901926bb64..0000000000 --- a/examples/typeMacro/macro1.das +++ /dev/null @@ -1,18 +0,0 @@ -module macro1 public - -require daslib/typemacro_boost - -[template_structure(CounterType, initialValue=1)] -struct template TemplateCounter { - private counter : CounterType - def TemplateCounter { - counter = CounterType($v(initialValue)) - } - def next { - counter ++ - } - def const value { - return counter - } -} - diff --git a/examples/typeMacro/macro2.das b/examples/typeMacro/macro2.das deleted file mode 100644 index f53ec1ff0c..0000000000 --- a/examples/typeMacro/macro2.das +++ /dev/null @@ -1,49 +0,0 @@ -module macro2 public - -require daslib/typemacro_boost - -struct template TemplateCounter { - counter : CounterType - def TemplateCounter { - counter = CounterType($v(initialValue)) - } - def next { - counter ++ - } - def value { - return counter - } -} - -def template print_counter(c : $t(resType)) { - print("Counter value: {c.value()}\n") -} - -[typemacro_function] -def TemplateCounter(macroArgument, passArgument : TypeDeclPtr; counter_type : TypeDeclPtr; initialValue : int = 123) : TypeDeclPtr { - var inscope template_type <- typeinfo ast_typedecl(type) - var inscope template_arguments <- [ - TypeMacroTemplateArgument(name="CounterType", argument_type <- clone_type(counter_type)) - ] - var extra_template_arguments <- [ - ("initialValue", "{initialValue}") - ] - if (passArgument != null) { - return <- TypeDeclPtr() if (!is_typemacro_template_instance(passArgument, template_type, extra_template_arguments)) - return <- TypeDeclPtr() if (!infer_struct_aliases(passArgument.structType, template_arguments)) - return <- infer_template_types(passArgument, template_arguments) - } else { - return <- TypeDeclPtr() if (!verify_arguments(template_arguments)) - var struct_name = template_structure_name(template_type.structType, template_arguments, extra_template_arguments) - var existing_struct = compiling_program().find_unique_structure(struct_name) - return <- new TypeDecl(baseType = Type.tStructure, structType = existing_struct, at = template_type.at) if (existing_struct != null) - var inscope resType <- qmacro_template_class(struct_name, type) - make_typemacro_template_instance(resType.structType, template_type.structType, extra_template_arguments) - add_structure_aliases(resType.structType, template_arguments) - // for demo purposes, we can add a print_counter function here - var inscope print_fn <- qmacro_template_function(@@print_counter) - add_function(compiling_module(), print_fn) - return <- resType - } -} - diff --git a/examples/typeMacro/macro3.das b/examples/typeMacro/macro3.das deleted file mode 100644 index 111c7a3552..0000000000 --- a/examples/typeMacro/macro3.das +++ /dev/null @@ -1,39 +0,0 @@ -module macro3 public - -require daslib/typemacro_boost - -struct template TemplateCounter { - counter : CounterType - def TemplateCounter { - counter = CounterType($v(initialValue)) - } - def next { - counter ++ - } - def value { - return counter - } -} - -def template print_counter(c : $t(resType)) { - print("Counter value: {c.value()}\n") -} - -[typemacro_template_function(TemplateCounter)] -def makeTemplateCounter(macroArgument, passArgument : TypeDeclPtr; CounterType : TypeDeclPtr; initialValue : int = 123) : TypeDeclPtr { - return <- default -} - -[typemacro_function] -def TemplateCounter(macroArgument, passArgument : TypeDeclPtr; CounterType : TypeDeclPtr; initialValue : int = 123) : TypeDeclPtr { - var inscope resType <- makeTemplateCounter(macroArgument, passArgument, CounterType, initialValue) - if (resType != null && passArgument == null) { - if (!is_custom_work_done(resType.structType)) { - mark_custom_work_done(resType.structType) - var inscope print_fn <- qmacro_template_function(@@print_counter) - add_function(compiling_module(), print_fn) - } - } - return <- resType -} - diff --git a/examples/test/misc/base64.das b/examples/uncategorized/base64_generators.das similarity index 58% rename from examples/test/misc/base64.das rename to examples/uncategorized/base64_generators.das index 9fd43dc61b..7f0b469da1 100644 --- a/examples/test/misc/base64.das +++ b/examples/uncategorized/base64_generators.das @@ -1,10 +1,30 @@ +// Base64 Encoder -- Generator Chain Example +// +// Encodes a string to Base64 by piping data through a chain of +// composable generators, each performing one step of the transform: +// +// from_sv -- iterates characters of the input string +// chunk6 -- groups 8-bit bytes into 6-bit values +// xlat -- maps 6-bit values to the Base64 alphabet +// pad4 -- pads output to a multiple of 4 characters +// linebreak -- inserts newlines every N characters +// +// The full pipeline: +// input |> from_sv() |> chunk6() |> xlat() |> pad4() |> linebreak() +// +// NOTE: This is deliberately slow -- each generator yield crosses +// a coroutine boundary, so there's significant overhead per byte. +// This is a demonstration of generator composition, not a fast +// Base64 implementation. For production use, process data in +// blocks with bit manipulation directly. +// +// Run: daslang.exe examples/uncategorized/base64_generators.das + options gen2 require strings -// note: this is equivalent to -// unsafe -// return <- each(input) -// unsafe is required due to lifetime of inp. version bellow will keep string alive +// Iterate characters of a string as ints. +// Uses a generator to keep the string alive across yields. def from_sv(inp : string) { return <- generator() <| $() { for (x in inp) { @@ -14,6 +34,8 @@ def from_sv(inp : string) { } } +// Group 8-bit input bytes into 6-bit output values. +// Every 3 input bytes produce 4 output values (with padding handled later). def chunk6(var inp : iterator) { return <- generator capture(<- inp) () <| $() { var b0 = 0 @@ -34,14 +56,12 @@ def chunk6(var inp : iterator) { } } +// Base64 alphabet lookup table (A-Z, a-z, 0-9, +, /) let { xlattable64 <- [for (t in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); t] } -// note: this is equivalent to -// unsafe -// return <- [[ for i in inp; yield xlattable64[i] ]] -// unsafe is required due to implicit capture of inp +// Map each 6-bit index to the corresponding Base64 character. def xlat(var inp : iterator) { return <- generator capture(<- inp) () <| $() { for (i in inp) { @@ -51,12 +71,13 @@ def xlat(var inp : iterator) { } } +// Pad output with '=' to make the total length a multiple of 4. def pad4(var inp : iterator) { return <- generator capture(<- inp) () <| $() { var len = 0 for (c in inp) { yield c - ++ len + ++len } while ((len++ % 4) != 0) { yield '=' @@ -65,6 +86,7 @@ def pad4(var inp : iterator) { } } +// Insert a newline every `linewidth` characters. def linebreak(var inp : iterator; linewidth = 76) { return <- generator capture(<- inp) () <| $() { for (c, len in inp, range(1, INT_MAX)) { @@ -77,6 +99,7 @@ def linebreak(var inp : iterator; linewidth = 76) { } } +// Full Base64 pipeline: compose all generator stages. def base64(inp : string; linewidth = 76) { return <- generator() <| $() { var lb <- inp |> from_sv() |> chunk6() |> xlat() |> pad4() |> linebreak(linewidth) @@ -87,6 +110,8 @@ def base64(inp : string; linewidth = 76) { } } +// --- Demo --- + let { sample = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable @@ -94,11 +119,10 @@ generation of knowledge, exceeds the short vehemence of any carnal pleasure." } [export] -def test { - print("\n\n{sample}\n\n") +def main() { + print("input:\n{sample}\n\nbase64:\n") for (ch in base64(sample)) { print(to_char(ch)) } - return true + print("\n") } - diff --git a/examples/uncategorized/shader_like_validation.das b/examples/uncategorized/shader_like_validation.das new file mode 100644 index 0000000000..b59e6d4855 --- /dev/null +++ b/examples/uncategorized/shader_like_validation.das @@ -0,0 +1,44 @@ +options gen2 + +// Shader-like mode demo — rejects heap-allocating constructs at simulation time. +// +// `options shader_like` (from daslib/validate_code) enforces a restricted subset +// of daScript: no global arrays (heap), no lambdas (heap), no `new` (heap). +// Errors are reported via simulate_macro, so they appear at simulation time, +// not compilation time. Run standalone to see the expected errors: +// +// daslang.exe shader_like_validation.das +// +// Expected output: 6x error 40104 (global requires heap, lambda requires heap, +// can't ascend, new requires heap, can't new). + +require daslib/validate_code + +options shader_like + +// global array requires heap → error 40104 +var arr : array + +def add(a, b) { + return a + b +} + +struct Foo { + a : int = 13 +} + +[export] +def main() { + var i = add(1, 2) + print("i = {i}\n") + print("arr = {arr}\n") + + // lambda requires heap → 2x error 40104 + var lmb <- @ { + print("hello\n") + } + invoke(lmb) + + // new requires heap → 2x error 40104 + var f = new Foo() +} diff --git a/examples/w3dold/Texture.png b/examples/w3dold/Texture.png deleted file mode 100644 index fbfe83a7b8..0000000000 Binary files a/examples/w3dold/Texture.png and /dev/null differ diff --git a/examples/w3dold/app_opengl_glfw.das b/examples/w3dold/app_opengl_glfw.das deleted file mode 100644 index 7f4953ade6..0000000000 --- a/examples/w3dold/app_opengl_glfw.das +++ /dev/null @@ -1,198 +0,0 @@ -options gen2 -options persistent_heap -options gc -module app_opengl_glfw private - -require rast2d public - -require glfw/glfw_boost -require opengl/opengl_boost -require glsl/glsl_opengl -require daslib/defer -require daslib/safe_addr -require math - -var @in @location v_position : float2 -var @in @location v_texcoord : float2 -var @inout f_texcoord : float2 -var @uniform f_tex : sampler2D -var @out f_FragColor : float4 - -[vertex_program] -def vs_main { - f_texcoord = v_texcoord - gl_Position = float4(v_position, 0.0, 1.0) -} - -[fragment_program] -def fs_main { - f_FragColor = texture(f_tex, f_texcoord) -} - -var program : uint -var vao : uint -var vbo : uint -var ebo : uint -var texture : uint - -[vertex_buffer] -struct Vertex { - xy : float2 - rgb : float3 - uv : float2 -} - -let vertices = [Vertex( - xy=float2(-1.0, 1.0), uv=float2(0.0, 0.0)), Vertex( - xy=float2(1.0, 1.0), uv=float2(1.0, 0.0)), Vertex( - xy=float2(1.0, -1.0), uv=float2(1.0, 1.0)), Vertex( - xy=float2(-1.0, -1.0), uv=float2(0.0, 1.0) -)]; - -let indices = fixed_array(0, 1, 2, 2, 3, 0) - -var bb_width = 0 -var bb_height = 0 -var bb_data : array - -def public get_screen_size { - return int2(bb_width, bb_height) -} - -def update_bb(var w, h : int) { - w = (w + 3) & ~3 - h = (h + 3) & ~3 - if (w == bb_width && h == bb_height) { - return false - } - bb_width = w - bb_height = h - bb_data |> clear() - bb_data |> resize(w * h) - return true -} - -def create_gl_objects(w, h : int) { - program = create_shader_program(@@vs_main, @@fs_main) - // vao - glGenVertexArrays(1, safe_addr(vao)) - glBindVertexArray(vao) - // vbo - glGenBuffers(1, safe_addr(vbo)) - glBindBuffer(GL_ARRAY_BUFFER, vbo) - glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW) - bind_vertex_buffer(null, type) - // ebo - glGenBuffers(1, safe_addr(ebo)) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo) - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW) - // texture - update_bb(w, h) -} - -var window : GLFWwindow? - -let public VK_LSHIFT = GLFW_KEY_LEFT_SHIFT -let public VK_RSHIFT = GLFW_KEY_RIGHT_SHIFT -let public VK_LALT = GLFW_KEY_LEFT_ALT -let public VK_RALT = GLFW_KEY_RIGHT_ALT -let public VK_LCONTROL = GLFW_KEY_LEFT_CONTROL -let public VK_RCONTROL = GLFW_KEY_RIGHT_CONTROL -let public VK_LEFT = GLFW_KEY_LEFT -let public VK_RIGHT = GLFW_KEY_RIGHT -let public VK_UP = GLFW_KEY_UP -let public VK_DOWN = GLFW_KEY_DOWN -let public VK_1 = GLFW_KEY_1 -let public VK_2 = GLFW_KEY_2 -let public VK_3 = GLFW_KEY_3 -let public VK_4 = GLFW_KEY_4 -let public VK_5 = GLFW_KEY_5 -let public VK_6 = GLFW_KEY_6 -let public VK_7 = GLFW_KEY_7 -let public VK_8 = GLFW_KEY_8 -let public VK_9 = GLFW_KEY_9 -let public VK_0 = GLFW_KEY_0 -let public VK_SPACE = GLFW_KEY_SPACE -let public VK_A = GLFW_KEY_A -let public VK_D = GLFW_KEY_D - -def public is_key_pressed(key : int) { - return glfwGetKey(window, key) != 0 -} - -var dt_sec = 0.0lf - -def public get_delta_time_sec { - return float(dt_sec) -} - -def public raster_app_main(blk : block<(var back_buffer : Bitmap) : void>) { - if (glfwInit() == 0) { - panic("can't init glfw") - } - defer <| $() { - glfwTerminate() - } - glfwInitOpenGL(3, 3) - window = glfwCreateWindow(1920, 1080, "RASTER2D", null, null) - if (window == null) { - panic("can't create window") - } - defer <| $() { - glfwDestroyWindow(window) - } - glfwMakeContextCurrent(window) - var display_w, display_h : int - glfwGetFramebufferSize(window, display_w, display_h) - create_gl_objects(display_w, display_h) - var tframe = ref_time_ticks() - var prev_sec = glfwGetTime() - var msecs = 12. - while (glfwWindowShouldClose(window) == 0) { - var tsec = glfwGetTime() - dt_sec = tsec - prev_sec - prev_sec = tsec - var dt_frame = get_time_usec(tframe) - tframe = ref_time_ticks() - unsafe { - heap_collect(true, true) - } - glfwPollEvents() - glfwGetFramebufferSize(window, display_w, display_h) - update_bb(display_w, display_h) - // callbakc - var bmp = Bitmap(size = int2(bb_width, bb_height), data = unsafe(addr(bb_data[0]))) - let t0 = ref_time_ticks() - invoke(blk, bmp) - let dt = get_time_usec(t0) - msecs = msecs * 0.95 + float(dt / 100) * 0.05 - let it = int(msecs) - glfwSetWindowTitle(window, "RASTER2D {bb_width}x{bb_height} frame:{dt_frame/1000}ms rast:{it/10}.{it%10}ms") - // make a texture - glGenTextures(1, safe_addr(texture)) - glBindTexture(GL_TEXTURE_2D, texture) - glTexImage2D(GL_TEXTURE_2D, 0, int(GL_RGBA), bb_width, bb_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, unsafe(addr(bb_data[0]))) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) - glBindTexture(GL_TEXTURE_2D, GL_INVALID_VALUE) - // render - glViewport(0, 0, display_w, display_h) - glDisable(GL_DEPTH_TEST) - glDepthMask(false) - glUseProgram(program) - f_tex := texture // bind texture - vs_main_bind_uniform(program) - fs_main_bind_uniform(program) - glBindVertexArray(vao) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo) - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, null) - glBindTexture(GL_TEXTURE_2D, GL_INVALID_VALUE) - // kill texture - glDeleteTextures(1, safe_addr(texture)) - // swap buffersa - glfwMakeContextCurrent(window) - glfwSwapBuffers(window) - } -} diff --git a/examples/w3dold/rast2d.das b/examples/w3dold/rast2d.das deleted file mode 100644 index 427f382762..0000000000 --- a/examples/w3dold/rast2d.das +++ /dev/null @@ -1,185 +0,0 @@ -options gen2 -module rast2d private - -require math -require raster - -struct public Texture { - //! texture surface - size : int2 - @do_not_delete pixels : uint? -} - -struct public Bitmap { - //! single surface - size : int2 - @do_not_delete data : uint? -} - -def public clear(var bmp : Bitmap; color : uint) { - //! clear surface with solid color - unsafe { - memset32(bmp.data, color, bmp.size.x * bmp.size.y) - } -} - -[jit, hint(unsafe_range_check, noalias=bmp, hot)] -def public fill_rect(var bmp : Bitmap; var xmin, ymin, dx, dy : int; color : uint) { - //! rectangle by x,y,width,height - fill_rect_p2(bmp, xmin, ymin, xmin + dx, ymin + dy, color) -} - -[jit, hint(unsafe_range_check, noalias=bmp, hot)] -def public fill_rect_p2(var bmp : Bitmap; var xmin, ymin, xmax, ymax : int; color : uint) { - //! fill rectangle with solid color, clip to surface - unsafe { - xmin = max(xmin, 0) - xmax = min(xmax, bmp.size.x) - ymin = max(ymin, 0) - ymax = min(ymax, bmp.size.y) - if (xmin >= xmax || ymin >= ymax) { - return - } - var pitch = bmp.size.x - var span = xmax - xmin - var pixels = bmp.data + (pitch * ymin + xmin) - if (false) {// span == pitch - memset32(pixels, color, span * (ymax - ymin)) - } else { - for (y in ymin..ymax) { - memset32(pixels, color, span) - pixels += pitch - } - } - } -} - -[jit, hint(unsafe_range_check, noalias=bmp, noalias=texture, hot, alwaysinline), unsafe_deref] -def public draw_vspan(var bmp : Bitmap; texture : Texture; x, y : int; uv : float4; h : int) { - //! draw vertical span of texture - if (texture.size == int2()) { - return - } - if (x < 0 || x >= bmp.size.x) { - return - } - let yMin = max(y, 0) - let yMax = min(y + h, bmp.size.y) - if (yMin >= yMax) { - return - } - let iTexSizeX = int(texture.size.x) - let i4TexSizeX = int4(iTexSizeX) - let bmpSizeX = bmp.size.x - let bmpSizeX4 = bmpSizeX * 4 - let bmpIdxs = int4(0, 1, 2, 3) * bmpSizeX - var bmpData = unsafe(addr(unsafe(bmp.data[yMin * bmp.size.x + x]))) - var pixelData = unsafe(addr(unsafe(texture.pixels[int(uv.x)]))) - let dh = rcp(float(h)) - var uvY = uv.y + uv.w * (float(yMin - y) * dh) - let dUVY = uv.w * dh - let count = yMax - yMin - var count4 = count >> 2 - let count16 = count4 >> 2 - count4 &= 3 - let tail4 = count & 3 - var uv4 = float4(uvY) + float4(dUVY) * float4(1., 2., 3., 4.) - let duv4 = float4(dUVY) * 4. - unsafe { - for (_ in range(count16)) { - gather_store_stride(bmpData, bmpSizeX, pixelData, int4(uv4) * i4TexSizeX) - bmpData += bmpSizeX4 - uv4 += duv4 - gather_store_stride(bmpData, bmpSizeX, pixelData, int4(uv4) * i4TexSizeX) - bmpData += bmpSizeX4 - uv4 += duv4 - gather_store_stride(bmpData, bmpSizeX, pixelData, int4(uv4) * i4TexSizeX) - bmpData += bmpSizeX4 - uv4 += duv4 - gather_store_stride(bmpData, bmpSizeX, pixelData, int4(uv4) * i4TexSizeX) - bmpData += bmpSizeX4 - uv4 += duv4 - } - for (_ in range(count4)) { - gather_store_stride(bmpData, bmpSizeX, pixelData, int4(uv4) * i4TexSizeX) - bmpData += bmpSizeX4 - uv4 += duv4 - } - uvY = uv4.x - for (_ in range(tail4)) { - *bmpData = pixelData[int(uvY) * iTexSizeX] - bmpData += bmpSizeX - uvY += dUVY - } - } -} - -[jit, hint(unsafe_range_check, noalias=bmp, noalias=texture, hot, alwaysinline), unsafe_deref] -def public draw_image_region_masked(var bmp : Bitmap; texture : Texture; x, y : int; uv : float4; size : int2; mask_color : uint) { - //! draw image region with mask color - if (texture.size == int2()) { - return - } - let w = size.x - let h = size.y - let yMin = max(y, 0) - let yMax = min(y + h, bmp.size.y) - let xMin = max(x, 0) - let xMax = min(x + w, bmp.size.x) - if (xMin >= xMax || yMin >= yMax) { - return - } - var bmpData = unsafe(addr(unsafe(bmp.data[yMin * bmp.size.x + xMin]))) - var pixelData = unsafe(addr(unsafe(texture.pixels[0]))) - let dwh = rcp(float2(w, h)) - let uvUV = uv.xy + uv.zw * float2(xMin - x, yMin - y) * dwh - let duvUV = uv.zw * dwh - let count = xMax - xMin - var count4 = count >> 2 - let tail4 = count & 3 - let count16 = count4 >> 2 - count4 &= 3 - let u4 = float4(uvUV.x) + duvUV.x * float4(1., 2., 3., 4.) - let du4 = float4(duvUV.x * 4.) - let bmpSizeX = bmp.size.x - let mask_color_4 = uint4(mask_color) - let texSizeX = texture.size.x - unsafe { - var v = uvUV.y - for (_ in range(yMin, yMax)) { - let pixelPart = pixelData + (int(v) * texSizeX) - var bmpSpan = reinterpret bmpData - var u = u4 - for (_1 in range(count16)) { - gather_store_neq_mask(bmpSpan, pixelPart, int4(u), mask_color_4) - bmpSpan ++ - u += du4 - gather_store_neq_mask(bmpSpan, pixelPart, int4(u), mask_color_4) - bmpSpan ++ - u += du4 - gather_store_neq_mask(bmpSpan, pixelPart, int4(u), mask_color_4) - bmpSpan ++ - u += du4 - gather_store_neq_mask(bmpSpan, pixelPart, int4(u), mask_color_4) - bmpSpan ++ - u += du4 - } - for (_2 in range(count4)) { - gather_store_neq_mask(bmpSpan, pixelPart, int4(u), mask_color_4) - bmpSpan ++ - u += du4 - } - var u1 = u.x - var tailSpan = reinterpret bmpSpan - for (xx in range(tail4)) { - let pixel = pixelPart[int(u1)] - if (pixel != mask_color) { - tailSpan[xx] = pixel - } - u1 += duvUV.x - } - bmpData += bmpSizeX - v += duvUV.y - } - } -} diff --git a/examples/w3dold/w3d.das b/examples/w3dold/w3d.das deleted file mode 100644 index 9426058b1e..0000000000 --- a/examples/w3dold/w3d.das +++ /dev/null @@ -1,2025 +0,0 @@ -options gen2 -require app_opengl_glfw -require rast2d - -require daslib/match -require daslib/safe_addr - -require math -require raster -require fio -require stbimage -require strings - -def set_debug_status_string(str) { - print("status: {str}\n") -} - -var MapSize = 1723 -var @transient MapData = fixed_array( - 412, 1, 15, 12, 49, 1, 3, 12, -1, 10, 5, 12, -1, 10, 5, 12, 49, 1, -2, 12, 142, 9, 0, -1, 142, 6, 12, 24, 1, 2, 156, 2, 159, 9, 1, 2, 2, -1, 1, 2, 2, -5, 3, 1, 2, 1, 10, 2, 0, -4, 132, 0, 178, 132, 2, 0, -1, 132, 2, 0, -1, 10, 5, 12, 24, 1, 2, 156, -2, 161, - 159, 7, 1, -1, 2, 10, 0, -1, 12, 11, 0, -1, 12, 2, 159, -1, 160, 2, 12, 24, 1, 2, 156, 2, 161, -1, 0, 7, 1, -2, 0, 144, 4, 0, -1, 144, 3, 0, -1, 90, 5, 0, -1, 134, 4, 0, -7, 178, 90, 0, 180, 159, 10, 12, 24, 1, 2, 156, -1, 161, 2, 0, 6, 1, -1, 2, 10, 0, -1, - 12, 11, 0, -1, 12, 3, 160, 2, 12, 24, 1, -8, 2, 6, 1, 2, 4, 2, 1, 6, 4, 1, 3, 0, 3, 1, -1, 3, 2, 1, -2, 2, 11, 11, 0, -1, 11, 5, 12, 23, 1, -8, 2, 0, 159, 160, 138, 0, 138, 160, 2, 0, -1, 2, 2, 1, 3, 0, 7, 1, -1, 12, 11, 0, 6, 12, 23, 1, -3, 3, 0, 133, 3, - 0, -7, 159, 0, 133, 178, 3, 1, 2, 3, 0, -2, 1, 2, 5, 1, 3, 12, -1, 10, 2, 12, -1, 91, 2, 12, -1, 10, 4, 12, 28, 1, 2, 0, -1, 184, 6, 0, -1, 2, 3, 0, -1, 182, 3, 0, 5, 1, 5, 12, 3, 0, 6, 12, 27, 1, -2, 2, 169, 3, 0, -3, 132, 0, 178, 2, 0, -1, 90, 3, 0, -1, - 144, 3, 0, 7, 1, 3, 12, -3, 0, 178, 0, 6, 12, 22, 1, 4, 2, 2, 1, 9, 0, -1, 1, 5, 0, -2, 182, 0, 7, 1, 2, 12, -6, 11, 0, 144, 0, 11, 12, 27, 1, -8, 2, 1, 2, 1, 3, 161, 133, 184, 4, 0, -9, 133, 0, 3, 1, 2, 1, 6, 1, 2, 2, 1, -1, 2, 5, 1, 3, 12, 3, 0, 2, 12, - 26, 1, -4, 2, 0, 155, 165, 2, 1, 2, 161, 6, 0, -1, 182, 11, 1, 7, 12, 3, 0, 4, 12, 25, 1, -7, 0, 144, 0, 2, 1, 2, 6, 2, 1, -1, 91, 2, 1, -2, 6, 2, 11, 1, 7, 12, 3, 0, 4, 12, 25, 1, 3, 0, 5, 1, 3, 0, -1, 2, 13, 1, 2, 12, 2, 0, -2, 10, 184, 2, 0, -1, 144, 2, - 0, -1, 146, 2, 12, 24, 1, -3, 2, 1, 91, 5, 1, -5, 3, 0, 144, 0, 3, 13, 1, 2, 12, -2, 156, 0, 3, 12, 3, 0, 4, 12, 25, 1, 3, 0, 2, 1, -1, 2, 2, 1, 3, 0, -1, 2, 13, 1, 2, 12, -2, 156, 155, 3, 12, 3, 0, 4, 12, 25, 1, -4, 0, 144, 0, 2, 2, 0, -2, 154, 1, 3, 0, - 14, 1, 2, 12, -2, 157, 155, 3, 12, 3, 0, 4, 12, 25, 1, 5, 0, -7, 144, 180, 3, 0, 144, 0, 3, 13, 1, 6, 12, -6, 10, 0, 144, 0, 10, 12, 27, 1, 3, 0, -1, 1, 2, 0, -5, 160, 2, 0, 182, 0, 14, 1, 7, 12, 3, 0, 2, 12, 14, 1, 12, 9, -1, 2, 3, 0, -4, 1, 2, 1, 2, 2, 1, - -1, 91, 2, 1, -1, 2, 18, 1, -5, 12, 10, 91, 10, 12, 7, 2, 8, 1, -1, 9, 2, 8, -1, 9, 3, 8, 3, 9, -9, 8, 9, 3, 0, 144, 0, 3, 1, 184, 8, 0, 11, 1, -7, 2, 1, 2, 1, 3, 2, 141, 3, 0, -5, 141, 1, 3, 1, 2, 2, 1, -1, 2, 8, 1, -3, 9, 8, 154, 3, 0, -1, 130, 3, 165, - -3, 8, 9, 2, 3, 0, -4, 1, 2, 0, 141, 5, 0, -3, 141, 0, 3, 11, 1, -3, 141, 0, 178, 11, 0, -1, 141, 2, 2, 9, 9, -1, 8, 7, 0, -1, 165, 2, 9, -1, 1, 3, 0, -2, 1, 2, 2, 0, -1, 144, 3, 0, -1, 144, 2, 0, 11, 1, -1, 6, 15, 0, -2, 6, 9, 3, 8, -1, 9, 3, 8, 2, 9, -1, - 8, 5, 0, -1, 180, 2, 0, -3, 8, 9, 1, 4, 0, -1, 1, 9, 0, -1, 2, 11, 1, 16, 0, -1, 9, 9, 0, -1, 8, 8, 0, 2, 9, -1, 1, 4, 0, -3, 90, 0, 180, 7, 0, -1, 3, 10, 1, -1, 2, 2, 0, -1, 134, 4, 0, -1, 134, 3, 0, -2, 180, 134, 3, 0, -1, 90, 9, 0, -1, 90, 8, 0, -3, 5, - 9, 1, 4, 0, -1, 1, 9, 0, 11, 1, -1, 2, 16, 0, -3, 8, 0, 229, 7, 0, -1, 9, 8, 0, 2, 9, -1, 1, 3, 0, 2, 1, 2, 0, -1, 144, 3, 0, -1, 144, 2, 0, 2, 2, 9, 1, -1, 6, 15, 0, -1, 6, 3, 8, 4, 0, 2, 9, 2, 8, -11, 227, 0, 143, 154, 0, 143, 0, 180, 8, 9, 2, 3, 0, 2, 1, - -2, 0, 141, 5, 0, -3, 141, 0, 3, 10, 1, -2, 2, 141, 13, 0, -1, 141, 3, 2, 2, 8, 2, 0, 4, 8, -1, 9, 8, 0, 2, 9, -1, 1, 3, 0, 2, 1, 7, 0, -2, 182, 0, 13, 1, -4, 4, 1, 2, 1, 5, 0, -10, 1, 2, 4, 1, 2, 1, 2, 1, 8, 9, 2, 0, -1, 9, 2, 8, -2, 9, 8, 6, 0, -11, 154, - 0, 8, 9, 4, 0, 144, 0, 4, 1, 2, 2, 1, -2, 2, 91, 2, 1, 2, 2, 17, 1, 2, 8, -2, 91, 9, 2, 8, 6, 2, -3, 1, 8, 9, 2, 0, 2, 8, 4, 9, -7, 8, 166, 9, 8, 167, 9, 8, 2, 9, -1, 1, 3, 0, -1, 2, 4, 1, 3, 0, 19, 1, 2, 8, 3, 0, -2, 9, 8, 7, 1, 2, 8, 2, 0, -2, 9, 8, 3, 9, - -1, 8, 9, 9, -1, 1, 3, 0, 4, 1, -1, 2, 3, 0, -1, 2, 18, 1, -7, 8, 9, 0, 144, 0, 9, 8, 7, 1, -2, 8, 9, 2, 0, 2, 8, 13, 9, -1, 2, 3, 0, -5, 1, 178, 0, 131, 1, 3, 0, 19, 1, 2, 8, 3, 0, -2, 9, 8, 7, 1, 2, 8, -3, 0, 182, 9, 12, 8, 3, 1, 5, 0, -7, 144, 0, 3, 0, - 144, 0, 3, 18, 1, -2, 8, 9, 3, 0, 2, 8, 7, 1, -2, 8, 9, 2, 0, 2, 8, -11, 9, 0, 8, 0, 9, 0, 9, 136, 8, 9, 8, 2, 1, -1, 2, 3, 0, -2, 2, 154, 2, 0, -1, 2, 3, 0, -1, 2, 18, 1, -2, 8, 9, 3, 0, -2, 9, 8, 7, 1, 2, 8, 3, 0, -1, 8, 5, 0, -1, 229, 3, 0, 2, 8, 2, 1, - -4, 2, 0, 144, 0, 2, 1, -1, 2, 2, 1, 3, 0, -1, 2, 4, 1, -1, 2, 13, 1, 2, 8, -3, 0, 144, 0, 2, 8, 7, 1, 2, 8, 3, 0, -1, 90, 8, 0, -3, 229, 5, 8, 3, 1, -14, 0, 178, 0, 2, 1, 2, 1, 2, 0, 182, 0, 1, 2, 1, 2, 2, -8, 3, 1, 2, 1, 6, 2, 1, 2, 6, 1, -7, 8, 9, 0, - 178, 0, 8, 9, 7, 1, -6, 8, 9, 0, 182, 0, 8, 3, 0, -1, 233, 4, 0, -1, 153, 2, 8, 2, 1, -1, 2, 16, 0, -1, 2, 5, 0, -3, 180, 3, 21, 5, 1, 2, 8, 3, 0, -2, 9, 8, 7, 1, 2, 8, -1, 9, 3, 8, -11, 9, 0, 8, 0, 8, 0, 8, 0, 8, 9, 8, 2, 1, -1, 2, 5, 0, -1, 144, 7, 0, -1, - 144, 2, 0, -1, 90, 3, 0, -1, 180, 2, 0, -3, 100, 0, 21, 4, 1, -2, 8, 9, 3, 0, -2, 9, 8, 7, 1, 17, 8, 3, 1, 16, 0, -1, 1, 5, 0, -3, 180, 3, 21, 5, 1, -5, 8, 9, 0, 144, 0, 2, 8, 27, 1, 2, 2, -1, 1, 2, 2, -1, 1, 2, 2, -2, 1, 4, 3, 1, -1, 2, 4, 1, -5, 2, 1, 6, - 1, 2, 2, 1, -2, 2, 1, 5, 8, 3, 0, -1, 9, 6, 8, 31, 1, -2, 21, 3, 2, 0, -1, 1, 2, 0, -3, 1, 0, 155, 7, 1, 2, 8, -3, 9, 8, 9, 2, 8, -1, 91, 5, 8, -1, 9, 2, 8, 30, 1, -3, 21, 0, 100, 2, 0, -1, 1, 2, 0, -3, 1, 0, 2, 6, 1, -4, 8, 9, 149, 154, 2, 0, -1, 8, 3, 0, - -1, 8, 4, 0, -2, 9, 8, 31, 1, -2, 21, 3, 5, 0, 9, 1, 2, 8, 4, 0, -7, 90, 0, 144, 0, 90, 0, 139, 2, 0, -2, 9, 8, 47, 1, 2, 8, 4, 0, -1, 8, 3, 0, -1, 8, 4, 0, -2, 9, 8, 34, 1, 2, 0, 11, 1, -2, 8, 9, 4, 0, -1, 9, 3, 0, -1, 9, 4, 0, -2, 9, 8, 34, 1, -2, 0, 163, - 11, 1, 3, 8, -1, 9, 2, 8, -1, 9, 3, 0, 7, 8, 47, 1, 2, 8, 4, 0, -1, 8, 3, 0, -1, 8, 4, 0, 2, 8, 47, 1, -2, 8, 9, 3, 0, -7, 223, 90, 0, 144, 0, 90, 154, 2, 0, -3, 149, 9, 8, 47, 1, 2, 8, 4, 0, -1, 8, 3, 0, -1, 8, 4, 0, 2, 8, 47, 1, 2, 8, 2, 9, 2, 8, -1, 9, - 3, 0, -1, 9, 2, 8, -1, 9, 3, 8, 47, 1, 2, 8, 13, 0, 2, 8, 47, 1, -2, 8, 9, 2, 0, -1, 144, 3, 0, -1, 144, 3, 0, -3, 144, 180, 156, 2, 8, 47, 1, 2, 8, -1, 184, 5, 0, -1, 154, 6, 0, 2, 8, 47, 1, 2, 8, -13, 5, 9, 8, 5, 8, 9, 7, 8, 9, 5, 9, 8, 5, 2, 8, 21, 1) - -var @transient Obstacles = fixed_array(0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0) - -var @transient NextFrames = fixed_array( - 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 8, 9, 10, 11, 12, 13, 14, 15, 41, 42, 43, 45, 0, 45, - 47, 48, 46, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 49, 50, 51, 52, 53, - 54, 55, 56, 49, 83, 84, 84, 86, 87, 85, 88, 89, 90, 91, 92, 93, 94, 95, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 96, 97, 98, 99, 100, 101, 102, 103, 129, 130, 131, 133, 88, 133, 135, 136, 135, 137, 138, 139, 140, 141, - 142, 143, 144, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 145, 146, 147, 148, 149, - 150, 151, 152, 178, 179, 180, 182, 137, 183, 183, 185, 186, 187, 184, 188, 189, 190, 191, 192, 193, 194, 195, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 196, 197, 198, 199, 200, 201, 202, 203, 229, 230, 231, 233, 188, 234, 234, 236, 237, 235, - 239, 238, 241, 240, 243, 242, 245, 244, 247, 248, 249, 246, 251, 252, 251, 253, 255, 256, 253, 258, 259, 260, 257, 262, 261, 264, 265, 266, 266, 268, 269, 270, - 267, 272, 273, 274, 271, 275, 277, 276, 279, 280, 281, 282, 283, 283, 285, 286, 287, 284, 289, 290, 289, 291, 293, 294, 295, 296, 297, 298, 295, 300, 301, 300, - 302, 304, 305, 306, 307, 308, 309, 302, 311, 312, 313, 310, 315, 314, 317, 318, 319, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, 336, 337, 338, 335, 340, 341, 340, 342, 344, 345, 342, 347, 348, 349, 346, 351, 352, 353, 350, 355, 356, 357, 357, 359, 360, 361, 362, 363, 364, 365, 365) - -struct STile { - ID : int - Visible : bool - DoorState : int - DoorSlide : float -} - -var MapWidth = 64 -var MapHeight = 64 -var @transient Map : array - -var @transient DepthBuffer : array - -var @transient Texture : Texture - -let MASK_COLOR = 0xFF980088 - -struct SPlayer { - Position : float2 - Direction : float - Size : float - Health : float -} - -var Player : SPlayer - -struct SWeapon { - Type : int - Shoot : bool - Animation : float -} - -var Weapon : SWeapon - -struct SObject { - ID : int - Position : float2 - Animation : float - Enemy : int -} - -var @transient Objects : array - -enum EEnemyType { - Invalid - - Guard - Dog - SS - Mutant - Officer - - Blinky - Pinky - Clyde - Inky - - Boss - Schabbs - FakeHitler - MechaHitler - Hitler - Gift - Gretel - Fat -} - -struct SEnemy { - Object : int - Type : EEnemyType - Health : float -} - -var @transient Enemies : array - -var DoorUse = false - -var FlashState = false -var FlashPhase = 0.0 -var FlashColor = 0x000000 - -def UncompressMap() { - clear(Map) - - var Tile : STile - Tile.ID = 0 - Tile.Visible = false - Tile.DoorState = 0 - Tile.DoorSlide = 0.0f - -/* - let level = 0 - for y in 0..64 - for x in 0..64 - Tile.ID = int(Levels[level].plane0[x + y*64]) - if Tile.ID >= 106 && Tile.ID <= 143 - Tile.ID = 0 - push(Map, Tile) -*/ - - var X = 0 - var Y = 0 - var Index = 0 - - while (Index < MapSize) { - var Count = MapData[Index] - Index = Index + 1 - - var Step = -1 - if (Count < 0) { - Step = 1 - } - - if (Count > 0) { - Tile.ID = MapData[Index] - Index = Index + 1 - } - - while (Count != 0) { - if (Count < 0) { - Tile.ID = MapData[Index] - Index = Index + 1 - } - - push(Map, Tile) - - X = X + 1 - if (X == MapWidth) { - X = 0 - Y = Y + 1 - } - - Count = Count + Step - } - } -} - -def InitPlayer() { - Player.Position = float2(29.5f, 57.5f) - Player.Direction = 0.0f - Player.Size = 0.2f - Player.Health = 100.0f -} - -def InitWeapon() { - Weapon.Type = 1 - Weapon.Shoot = false - Weapon.Animation = 0.0f -} - -/* -000 - 063 Walls -090 - 091 Regular unlocked door (oriented) -092 - 093 Gold-locked door (oriented) -094 - 095 Silver-locked door (oriented) -100 - 101 Elevator door (oriented) -106 - 143 Walkable tile (room) -*/ - -def InitObjects() { - clear(Objects) - clear(Enemies) - - var Index = 0 - for (Y in range(0, MapHeight)) { - for (X in range(0, MapWidth)) { - var Object : SObject - Object.ID = 0 - Object.Position = float2(float(X) + 0.5f, float(Y) + 0.5f) - Object.Animation = 0.0f - - var ID = Map[Y * MapWidth + X].ID - if (ID >= 128) { - Map[Y * MapWidth + X].ID = 0 - Object.ID = ID - } - - /* - var ID = int(Levels[0].plane1[Y*64+X]) - if ID == 0 - ID = int(Levels[0].plane1[Y*64+X]) - if ID >= 106 && ID <= 143 - pass - else - ID = 0 - */ - - if (ID >= 178 && ID <= 543) { - var Enemy : SEnemy - Enemy.Object = Y * MapWidth + X - Enemy.Type = EEnemyType.Invalid - Enemy.Health = 100.0f - - if (ID >= 178 && ID <= 226) { - Enemy.Type = EEnemyType.Guard - } - if (ID >= 227 && ID <= 265) { - Enemy.Type = EEnemyType.Dog - } - if (ID >= 266 && ID <= 314) { - Enemy.Type = EEnemyType.SS - } - if (ID >= 315 && ID <= 365) { - Enemy.Type = EEnemyType.Mutant - } - if (ID >= 366 && ID <= 415) { - Enemy.Type = EEnemyType.Officer - } - - if (ID >= 416 && ID <= 417) { - Enemy.Type = EEnemyType.Blinky - } - if (ID >= 418 && ID <= 419) { - Enemy.Type = EEnemyType.Pinky - } - if (ID >= 420 && ID <= 421) { - Enemy.Type = EEnemyType.Clyde - } - if (ID >= 422 && ID <= 423) { - Enemy.Type = EEnemyType.Inky - } - - if (ID >= 424 && ID <= 434) { - Enemy.Type = EEnemyType.Boss - } - if (ID >= 435 && ID <= 444) { - Enemy.Type = EEnemyType.Schabbs - } - if (ID >= 449 && ID <= 461) { - Enemy.Type = EEnemyType.FakeHitler - } - if (ID >= 462 && ID <= 472) { - Enemy.Type = EEnemyType.MechaHitler - } - if (ID >= 473 && ID <= 487) { - Enemy.Type = EEnemyType.Hitler - } - if (ID >= 488 && ID <= 497) { - Enemy.Type = EEnemyType.Gift - } - if (ID >= 513 && ID <= 523) { - Enemy.Type = EEnemyType.Gretel - } - if (ID >= 524 && ID <= 535) { - Enemy.Type = EEnemyType.Fat - } - - if (Enemy.Type != EEnemyType.Invalid) { - Object.Enemy = Index - Index = Index + 1 - - push(Enemies, Enemy) - } - } - - push(Objects, Object) - } - } -} - -def GetIdleFrame(Enemy : SEnemy) : int { - if (Enemy.Type == EEnemyType.Invalid) { - return -1 - } - - var Object = Objects[Enemy.Object] - var ID = Object.ID - - if (Enemy.Type == EEnemyType.Guard) { - return 178 - } - if (Enemy.Type == EEnemyType.Dog) { - return 227 - } - if (Enemy.Type == EEnemyType.SS) { - return 266 - } - if (Enemy.Type == EEnemyType.Mutant) { - return 315 - } - if (Enemy.Type == EEnemyType.Officer) { - return 366 - } - - if (Enemy.Type == EEnemyType.Boss) { - return 424 - } - if (Enemy.Type == EEnemyType.Schabbs) { - return 435 - } - if (Enemy.Type == EEnemyType.FakeHitler) { - return 449 - } - if (Enemy.Type == EEnemyType.MechaHitler) { - return 462 - } - if (Enemy.Type == EEnemyType.Hitler) { - return 473 - } - if (Enemy.Type == EEnemyType.Gift) { - return 488 - } - if (Enemy.Type == EEnemyType.Gretel) { - return 513 - } - if (Enemy.Type == EEnemyType.Fat) { - return 524 - } - - return ID -} - -def GetAttackDistance(Enemy : SEnemy) : float { - if (Enemy.Type == EEnemyType.Invalid) { - return -1.0f - } - - var Object = Objects[Enemy.Object] - var ID = Object.ID - - if (Enemy.Type == EEnemyType.Guard) { - return 5.0f - } - if (Enemy.Type == EEnemyType.Dog) { - return 1.0f - } - if (Enemy.Type == EEnemyType.SS) { - return 8.0f - } - if (Enemy.Type == EEnemyType.Mutant) { - return 4.0f - } - if (Enemy.Type == EEnemyType.Officer) { - return 6.0f - } - - if (Enemy.Type == EEnemyType.Boss) { - return 10.0f - } - if (Enemy.Type == EEnemyType.Schabbs) { - return 10.0f - } - if (Enemy.Type == EEnemyType.FakeHitler) { - return 10.0f - } - if (Enemy.Type == EEnemyType.MechaHitler) { - return 10.0f - } - if (Enemy.Type == EEnemyType.Hitler) { - return 10.0f - } - if (Enemy.Type == EEnemyType.Gift) { - return 10.0f - } - if (Enemy.Type == EEnemyType.Gretel) { - return 10.0f - } - if (Enemy.Type == EEnemyType.Fat) { - return 10.0f - } - - return -1.0f -} - -def GetAttackFrame(Enemy : SEnemy) : int { - if (Enemy.Type == EEnemyType.Invalid) { - return -1 - } - - var Object = Objects[Enemy.Object] - var ID = Object.ID - - if (Enemy.Type == EEnemyType.Guard) { - return 224 - } - if (Enemy.Type == EEnemyType.Dog) { - return 263 - } - if (Enemy.Type == EEnemyType.SS) { - return 312 - } - if (Enemy.Type == EEnemyType.Mutant) { - return 362 - } - if (Enemy.Type == EEnemyType.Officer) { - return 413 - } - - if (Enemy.Type == EEnemyType.Boss) { - return 428 - } - if (Enemy.Type == EEnemyType.Schabbs) { - return 439 - } - if (Enemy.Type == EEnemyType.FakeHitler) { - return 458 - } - if (Enemy.Type == EEnemyType.MechaHitler) { - return 466 - } - if (Enemy.Type == EEnemyType.Hitler) { - return 477 - } - if (Enemy.Type == EEnemyType.Gift) { - return 492 - } - if (Enemy.Type == EEnemyType.Gretel) { - return 517 - } - if (Enemy.Type == EEnemyType.Fat) { - return 528 - } - - return ID -} - -def IsAttack(Enemy : SEnemy) : bool { - if (Enemy.Type == EEnemyType.Invalid) { - return false - } - - var Object = Objects[Enemy.Object] - var ID = Object.ID - - if (Enemy.Type == EEnemyType.Guard && ID >= 224 && ID <= 226) { - return true - } - if (Enemy.Type == EEnemyType.Dog && ID >= 263 && ID <= 265) { - return true - } - if (Enemy.Type == EEnemyType.SS && ID >= 312 && ID <= 314) { - return true - } - if (Enemy.Type == EEnemyType.Mutant && ID >= 362 && ID <= 365) { - return true - } - if (Enemy.Type == EEnemyType.Officer && ID >= 413 && ID <= 415) { - return true - } - - if (Enemy.Type == EEnemyType.Boss && ID >= 428 && ID <= 430) { - return true - } - if (Enemy.Type == EEnemyType.Schabbs && ID >= 439 && ID <= 440) { - return true - } - if (Enemy.Type == EEnemyType.FakeHitler && ID >= 458 && ID <= 458) { - return true - } - if (Enemy.Type == EEnemyType.MechaHitler && ID >= 466 && ID <= 468) { - return true - } - if (Enemy.Type == EEnemyType.Hitler && ID >= 477 && ID <= 479) { - return true - } - if (Enemy.Type == EEnemyType.Gift && ID >= 492 && ID <= 493) { - return true - } - if (Enemy.Type == EEnemyType.Gretel && ID >= 517 && ID <= 519) { - return true - } - if (Enemy.Type == EEnemyType.Fat && ID >= 528 && ID <= 531) { - return true - } - - return false -} - -def GetDamageFrame(Enemy : SEnemy) : int { - if (Enemy.Type == EEnemyType.Invalid) { - return -1 - } - - var Object = Objects[Enemy.Object] - var ID = Object.ID - - if (Enemy.Type == EEnemyType.Guard) { - return 222 - } - if (Enemy.Type == EEnemyType.Dog) { - return 259 - } - if (Enemy.Type == EEnemyType.SS) { - return 310 - } - if (Enemy.Type == EEnemyType.Mutant) { - return 359 - } - if (Enemy.Type == EEnemyType.Officer) { - return 410 - } - - return ID -} - -def GetDyingFrame(Enemy : SEnemy) : int { - if (Enemy.Type == EEnemyType.Invalid) { - return -1 - } - - var Object = Objects[Enemy.Object] - var ID = Object.ID - - if (Enemy.Type == EEnemyType.Guard) { - return 218 - } - if (Enemy.Type == EEnemyType.Dog) { - return 260 - } - if (Enemy.Type == EEnemyType.SS) { - return 306 - } - if (Enemy.Type == EEnemyType.Mutant) { - return 355 - } - if (Enemy.Type == EEnemyType.Officer) { - return 406 - } - - if (Enemy.Type == EEnemyType.Boss) { - return 431 - } - if (Enemy.Type == EEnemyType.Schabbs) { - return 441 - } - if (Enemy.Type == EEnemyType.FakeHitler) { - return 456 - } - if (Enemy.Type == EEnemyType.MechaHitler) { - return 469 - } - if (Enemy.Type == EEnemyType.Hitler) { - return 480 - } - if (Enemy.Type == EEnemyType.Gift) { - return 494 - } - if (Enemy.Type == EEnemyType.Gretel) { - return 520 - } - if (Enemy.Type == EEnemyType.Fat) { - return 532 - } - - return ID -} - -def IsDying(Enemy : SEnemy) : bool { - if (Enemy.Type == EEnemyType.Invalid) { - return false - } - - var Object = Objects[Enemy.Object] - var ID = Object.ID - - if (Enemy.Type == EEnemyType.Guard && ID >= 218 && ID <= 223) { - return true - } - if (Enemy.Type == EEnemyType.Dog && ID >= 259 && ID <= 262) { - return true - } - if (Enemy.Type == EEnemyType.SS && ID >= 306 && ID <= 311) { - return true - } - if (Enemy.Type == EEnemyType.Mutant && ID >= 355 && ID <= 361) { - return true - } - if (Enemy.Type == EEnemyType.Officer && ID >= 406 && ID <= 412) { - return true - } - - if (Enemy.Type == EEnemyType.Boss && ID >= 431 && ID <= 434) { - return true - } - if (Enemy.Type == EEnemyType.Schabbs && ID >= 441 && ID <= 444) { - return true - } - if (Enemy.Type == EEnemyType.FakeHitler && ID >= 456 && ID <= 461) { - return true - } - if (Enemy.Type == EEnemyType.MechaHitler && ID >= 469 && ID <= 472) { - return true - } - if (Enemy.Type == EEnemyType.Hitler && ID >= 480 && ID <= 487) { - return true - } - if (Enemy.Type == EEnemyType.Gift && ID >= 494 && ID <= 497) { - return true - } - if (Enemy.Type == EEnemyType.Gretel && ID >= 520 && ID <= 523) { - return true - } - if (Enemy.Type == EEnemyType.Fat && ID >= 532 && ID <= 535) { - return true - } - - return false -} - -def GetFirstDirection(ID : int) : int { - if (ID >= 178 && ID <= 217) { - return 178 - } - if (ID >= 227 && ID <= 258) { - return 227 - } - if (ID >= 266 && ID <= 305) { - return 266 - } - if (ID >= 315 && ID <= 354) { - return 315 - } - if (ID >= 366 && ID <= 405) { - return 366 - } - - return -1 -} - -def IsBlock(X : int; Y : int) : bool { - if (X < 0 || Y < 0 || X >= MapWidth || Y >= MapHeight) { - return false - } - - var Tile = Map[Y * MapWidth + X] - var ID = Tile.ID - if (ID == 0) { - ID = Objects[Y * MapWidth + X].ID - if (ID == 0) { - return false - } - } - - if (ID >= 90 && ID <= 101) { - if (Tile.DoorSlide >= 1.0f) { - return false - } - } - - if (ID >= 128) { - if (ID <= 177) { - if (Obstacles[ID - 128] != 0) { - return true - } else { - return false - } - } else { - if (ID == 223 || ID == 262 || ID == 311 || ID == 361 || ID == 412) { - return false - } elif (ID == 431 || ID == 444 || ID == 461 || ID == 469 || ID == 480 || ID == 487 || ID == 497 || ID == 520 || ID == 535) { - return false - } else { - return true - } - } - } - - return true -} - -def IsDoor(X : int; Y : int) : bool { - if (X < 0 || Y < 0 || X >= MapWidth || Y >= MapHeight) { - return false - } - - var ID = Map[Y * MapWidth + X].ID - if (ID >= 90 && ID <= 101) { - return true - } - - return false -} - -def GetNextFrame(ID : int) : int { - if (ID >= 178 && ID <= 543) { - return NextFrames[ID - 178] + 178 - } - return ID -} - -def IsVisible(PositionA : float2; PositionB : float2) : bool { - var Ray = PositionB - PositionA - - var MapX = int(PositionA.x) - var MapY = int(PositionA.y) - - var StepX : int - if (Ray.x > 0.0f) { - StepX = 1 - } elif (Ray.x < 0.0f) { - StepX = -1 - } else { - StepX = 0 - } - - var StepY : int - if (Ray.y > 0.0f) { - StepY = 1 - } elif (Ray.y < 0.0f) { - StepY = -1 - } else { - StepY = 0 - } - - var Fraction = float2(PositionA.x - float(MapX), PositionA.y - float(MapY)) - - var Distance : float2 - if (Ray.x > 0.0f) { - Distance.x = 1.0f - Fraction.x - } elif (Ray.x < 0.0f) { - Distance.x = Fraction.x - } else { - Distance.x = 0.0f - } - - if (Ray.y > 0.0f) { - Distance.y = 1.0f - Fraction.y - } elif (Ray.y < 0.0f) { - Distance.y = Fraction.y - } else { - Distance.y = 0.0f - } - - var Sign = float2(StepX, StepY) - var Abs = Sign * Ray - - var Ratio = float2(0.0f, 0.0f) - if (Abs.x != 0.0f) { - Ratio.x = Abs.y / Abs.x - } - if (Abs.y != 0.0f) { - Ratio.y = Abs.x / Abs.y - } - - var Axis = float2(1.0f, 1.0f) - if (Abs.x >= Abs.y) { - Axis.y = Ratio.y - } else { - Axis.x = Ratio.x - } - - var Next = float2(Distance.x * Axis.x, Distance.y * Axis.y) - - if (Abs.x == 0.0f) { - Next = float2(1.0f, 0.0f) - Axis = float2(0.0f, 0.0f) - } - - if (Abs.y == 0.0f) { - Next = float2(0.0f, 1.0f) - Axis = float2(0.0f, 0.0f) - } - - Distance = Distance - float2(1.0f, 1.0f) - - var Side : int - var Empty : bool - - Empty = true - while (Empty) { - if (Next.x < Next.y) { - Next.x = Next.x + Axis.x - Distance.x = Distance.x + 1.0f - if (Distance.x > Abs.x) { - return true - } - MapX = MapX + StepX - Side = 0 - } else { - Next.y = Next.y + Axis.y - Distance.y = Distance.y + 1.0f - if (Distance.y > Abs.y) { - return true - } - MapY = MapY + StepY - Side = 1 - } - - var ID = Map[MapY * MapWidth + MapX].ID - Empty = ID == 0 || ID >= 128 - - if (ID >= 90 && ID <= 101) { - var Slide = Map[MapY * MapWidth + MapX].DoorSlide - var Vec = float2(MapX, MapY) - PositionA - if (Side == 0) { - Vec.x = (Vec.x + 0.5f) * Sign.x - var Open = Vec.x * Ratio.x * Sign.y - Vec.y - if (Open >= Slide && Open <= 1.0f) { - Distance.x = Vec.x - } else { - Empty = true - } - } else { - Vec.y = (Vec.y + 0.5f) * Sign.y - var Open = Vec.y * Ratio.y * Sign.x - Vec.x - if (Open >= Slide && Open <= 1.0f) { - Distance.y = Vec.y - } else { - Empty = true - } - } - } - } - - if (Side == 0) { - if (Distance.x <= Abs.x) { - return false - } - } else { - if (Distance.y <= Abs.y) { - return false - } - } - - return true -} - -def GetPlayerAngle(Position : float2) : int { - var Direction = Position - Player.Position - var PlayerAngle = floori((8.0f * atan2(Direction.y, Direction.x) / (2.0f * PI)) + 0.5f) - if (PlayerAngle < 0) { - PlayerAngle = 8 - ((-PlayerAngle) % 8) - } - PlayerAngle = PlayerAngle % 8 - return PlayerAngle -} - -def UpdatePlayer(Time : float) { - if (Player.Health <= 0.0f) { - return - } - - var TurnSpeed = Time * 2.0f - var MoveSpeed = Time * 5.0f - - var Direction = float2(cos(Player.Direction), sin(Player.Direction)) - var Forward = float2(Direction.x, Direction.y) - var Leftward = float2(Direction.y, -Direction.x) - - var Velocity = float2(0.0f, 0.0f) - - var Run = false - if (is_key_pressed(VK_LSHIFT) || is_key_pressed(VK_RSHIFT)) { - Run = true - } - - if (Run) { - MoveSpeed = MoveSpeed * 2.0f - TurnSpeed = TurnSpeed * 2.0f - } - - var Strafe = false - if (is_key_pressed(VK_LALT) || is_key_pressed(VK_RALT)) { - Strafe = true - } - - if (Strafe) { - if (is_key_pressed(VK_LEFT)) { - Velocity = Velocity + Leftward * MoveSpeed - } - if (is_key_pressed(VK_RIGHT)) { - Velocity = Velocity - Leftward * MoveSpeed - } - } else { - if (is_key_pressed(VK_LEFT)) { - Player.Direction = Player.Direction - TurnSpeed - } - if (is_key_pressed(VK_RIGHT)) { - Player.Direction = Player.Direction + TurnSpeed - } - } - - if (is_key_pressed(VK_UP)) { - Velocity = Velocity + Forward * MoveSpeed - } - if (is_key_pressed(VK_DOWN)) { - Velocity = Velocity - Forward * MoveSpeed - } - - var Position = Player.Position - var Size = float2(Player.Size, Player.Size) - - var Min = Position - Size - var Max = Position + Size - - var X1 = floori(Min.x) - var Y1 = floori(Min.y) - var X2 = ceili(Max.x) - var Y2 = ceili(Max.y) - - var FlagX = false - var FlagY = false - - for (Y in range(Y1, Y2)) { - for (X in range(X1, X2)) { - if (!IsBlock(X, Y)) { - continue - } - - var Block = float2(X, Y) - if (Block.x >= Position.x + Size.x || Block.y >= Position.y + Size.y || Block.x + 1.0f <= Position.x - Size.x || Block.y + 1.0f <= Position.y - Size.y) { - continue - } - - var Stop : float2 - if (Block.x + 0.5f > Position.x) { - Stop.x = Block.x - Size.x - } else { - Stop.x = Block.x + 1.0f + Size.x - } - if (Block.y + 0.5f > Position.y) { - Stop.y = Block.y - Size.y - } else { - Stop.y = Block.y + 1.0f + Size.y - } - - if (abs(Stop.x - Position.x) <= abs(Stop.y - Position.y)) { - if (!IsBlock(int(Stop.x), Y)) { - FlagX = true - } elif (!IsBlock(X, int(Stop.y))) { - FlagY = true - } elif (!IsBlock(int(Stop.x), int(Stop.y))) { - FlagX = true - FlagY = true - } - } else { - if (!IsBlock(X, int(Stop.y))) { - FlagY = true - } elif (!IsBlock(int(Stop.x), Y)) { - FlagX = true - } elif (!IsBlock(int(Stop.x), int(Stop.y))) { - FlagX = true - FlagY = true - } - } - - - if (FlagX) { - if (Position.x > Stop.x == Velocity.x > 0.0f) { - Velocity.x = 0.0f - } - Position.x = Stop.x - } - - if (FlagY) { - if (Position.y > Stop.y == Velocity.y > 0.0f) { - Velocity.y = 0.0f - } - Position.y = Stop.y - } - - if (FlagX || FlagY) { - break - } - } - - if (FlagX || FlagY) { - break - } - } - - for (Step in range(0, 2)) { - if (Velocity.x == 0.0f && Velocity.y == 0.0f) { - break - } - - var Stop = float2(0.0f, 0.0f) - var Move = 1.0f - var Side = 0 - - Min = Position - Size - Max = Position + Size - - if (Velocity.x < 0.0f) { - Min.x = Min.x + Velocity.x - } else { - Max.x = Max.x + Velocity.x - } - - if (Velocity.y < 0.0f) { - Min.y = Min.y + Velocity.y - } else { - Max.y = Max.y + Velocity.y - } - - X1 = floori(Min.x) - Y1 = floori(Min.y) - X2 = ceili(Max.x) - Y2 = ceili(Max.y) - - if (X1 < 0) { - X1 = 0 - } - if (Y1 < 0) { - Y1 = 0 - } - if (X2 > MapWidth) { - X2 = MapWidth - } - if (Y2 > MapHeight) { - Y2 = MapHeight - } - - var ClipLines : array - push(ClipLines, float3(1.0f, 0.0f, -Min.x)) - push(ClipLines, float3(0.0f, 1.0f, -Min.y)) - push(ClipLines, float3(-1.0f, 0.0f, Max.x)) - push(ClipLines, float3(0.0f, -1.0f, Max.y)) - - if (Velocity.x != 0.0f && Velocity.y != 0.0f) { - var Extent : float2 - if (Velocity.y > 0.0f) { - Extent.x = Size.x - } else { - Extent.x = -Size.x - } - if (Velocity.x > 0.0f) { - Extent.y = Size.y - } else { - Extent.y = -Size.y - } - - var Center = Velocity.x * Position.y - Velocity.y * Position.x - var Corner = Velocity.x * Extent.y + Velocity.y * Extent.x - - push(ClipLines, float3(Velocity.y, -Velocity.x, Corner + Center)) - push(ClipLines, float3(-Velocity.y, Velocity.x, Corner - Center)) - } - - for (Line in ClipLines) { - Line.z = (Line.x + abs(Line.x)) * 0.5f + (Line.y + abs(Line.y)) * 0.5f + Line.z - } - - for (Y in range(Y1, Y2)) { - for (X in range(X1, X2)) { - if (!IsBlock(X, Y)) { - continue - } - - var Block = float2(X, Y) - - var Inside = true - for (Line in ClipLines) { - if (Line.x * Block.x + Line.y * Block.y + Line.z <= 0.0f) { - Inside = false - break - } - } - - if (Inside) { - if (Velocity.x != 0.0f) { - if (Velocity.x > 0.0f) { - Stop.x = Block.x - Size.x - } else { - Stop.x = Block.x + 1.0f + Size.x - } - Stop.x = (Stop.x - Position.x) / Velocity.x - } - - if (Velocity.y != 0.0f) { - if (Velocity.y > 0.0f) { - Stop.y = Block.y - Size.y - } else { - Stop.y = Block.y + 1.0f + Size.y - } - Stop.y = (Stop.y - Position.y) / Velocity.y - } - - if (Stop.y <= Stop.x && 0.0f <= Stop.x && Move >= Stop.x) { - Move = Stop.x - Side = 1 - } - if (Stop.x <= Stop.y && 0.0f <= Stop.y && Move >= Stop.y) { - Move = Stop.y - Side = 2 - } - } - } - } - - Position = Position + Velocity * Move - - if (Side == 1) { - Velocity.y = Velocity.y * (1.0f - Move) - Velocity.x = 0.0f - } - if (Side == 2) { - Velocity.x = Velocity.x * (1.0f - Move) - Velocity.y = 0.0f - } - - if (Move == 1.0f) { - break - } - } - - Player.Position = Position -} - -def GetWeaponRange() : float { - if (Weapon.Type == 0) { - return 0.2f - } - if (Weapon.Type == 1) { - return 0.3f - } - if (Weapon.Type == 2) { - return 0.5f - } - if (Weapon.Type == 3) { - return 1.0f - } - - return 0.0f -} - -def GetWeaponDamage() : float { - if (Weapon.Type == 0) { - return 100.0f - } - if (Weapon.Type == 1) { - return 200.0f - } - if (Weapon.Type == 2) { - return 300.0f - } - if (Weapon.Type == 3) { - return 500.0f - } - - return 0.0f -} - -def UpdateWeapon(Time : float) { - if (is_key_pressed(VK_1)) { - Weapon.Type = 0 - } - if (is_key_pressed(VK_2)) { - Weapon.Type = 1 - } - if (is_key_pressed(VK_3)) { - Weapon.Type = 2 - } - if (is_key_pressed(VK_4)) { - Weapon.Type = 3 - } - - var Shoot = false - if (is_key_pressed(VK_LCONTROL) || is_key_pressed(VK_RCONTROL)) { - Shoot = true - } - - var ShootSpeed = Time * 10.0f - if (Weapon.Shoot) { - Weapon.Animation = Weapon.Animation + ShootSpeed - if (Weapon.Type >= 2 && Shoot) { - if (Weapon.Animation >= 4.0f) { - Weapon.Animation = 2.0f - Weapon.Shoot = false - } - } else { - if (Weapon.Animation >= 5.0f) { - Weapon.Animation = 0.0f - Weapon.Shoot = false - } - } - } elif (Shoot) { - Weapon.Shoot = true - - var WeaponRange = GetWeaponRange() - var WeaponDamage = GetWeaponDamage() - - var Direction = float2(cos(Player.Direction), sin(Player.Direction)) - - var NearestEnemy = -1 - var NearestDistance = 0.0f - - var Index = 0 - for (Enemy in Enemies) { - var Object = Objects[Enemy.Object] - var X = int(Object.Position.x) - var Y = int(Object.Position.y) - if (X >= 0 && Y >= 0 && X < MapWidth && Y < MapHeight) { - if (Map[Y * MapWidth + X].Visible && IsBlock(X, Y)) { - var Distance = Object.Position - Player.Position - var DistanceC = Distance.x * Distance.x + Distance.y * Distance.y - if (Weapon.Type >= 1 || DistanceC <= 2.0f) { - var DistanceA = Distance.x * Direction.x + Distance.y * Direction.y - var DistanceB = DistanceC - DistanceA * DistanceA - if (DistanceB <= WeaponRange * WeaponRange) { - if (NearestDistance > DistanceC || NearestEnemy == -1) { - NearestDistance = DistanceC - NearestEnemy = Index - } - } - } - } - } - Index = Index + 1 - } - - if (NearestEnemy != -1) { - assume Enemy = Enemies[NearestEnemy] - if (!IsDying(Enemy)) { - assume Object = Objects[Enemy.Object] - - var Damage = 1.0f - if (NearestDistance >= 1.0f) { - Damage = 1.0f / sqrt(NearestDistance) - } - - Enemy.Health = Enemy.Health - Damage * WeaponDamage - - if (Enemy.Health <= 0.0f) { - Enemy.Health = 0.0f - Object.ID = GetDyingFrame(Enemy) - } else { - Object.ID = GetDamageFrame(Enemy) - } - - Object.Animation = 0.0f - } - } - } elif (Weapon.Animation > 0.0f) { - Weapon.Animation = Weapon.Animation + ShootSpeed - if (Weapon.Animation >= 5.0f) { - Weapon.Animation = 0.0f - } - } -} - -def UpdateObjects(Time : float) { - for (Object in Objects) { - if (Object.ID != 0) { - Object.Animation = Object.Animation + Time - if (Object.Animation >= 0.2f) { - Object.Animation = Object.Animation - 0.2f - if (Object.Enemy != -1) { - var Enemy = Enemies[Object.Enemy] - if (Object.ID == GetDamageFrame(Enemy)) { - Object.ID = GetIdleFrame(Enemy) + GetPlayerAngle(Object.Position) - } - } - Object.ID = GetNextFrame(Object.ID) - } - - var ID = Object.ID - if (ID == 136 || ID == 150 || ID == 151 || (ID >= 154 && ID <= 163)) { - var Distance = Object.Position - Player.Position - var DistanceC = Distance.x * Distance.x + Distance.y * Distance.y - if (DistanceC <= 0.25f) { - Object.ID = 0 - - if (ID == 136) { - Player.Health = Player.Health + 4.0f - } - if (ID == 154) { - Player.Health = Player.Health + 10.0f - } - if (ID == 155) { - Player.Health = Player.Health + 25.0f - } - if (ID == 163) { - Player.Health = Player.Health + 100.0f - } - - if (Player.Health > 100.0f) { - Player.Health = 100.0f - } - - FlashState = true - FlashPhase = 0.0f - FlashColor = 0xffff00 - } - } - } - } -} - -def UpdateEnemies(Time : float) { - var Shoot = Weapon.Shoot && Weapon.Type >= 1 - if (!Shoot) { - for (Enemy in Enemies) { - if (IsAttack(Enemy)) { - Shoot = true - break - } - } - } - - for (Enemy in Enemies) { - var AttackDistance = GetAttackDistance(Enemy) - var HearDistance = 1.2f - - assume Object = Objects[Enemy.Object] - var Distance = Object.Position - Player.Position - var DistanceA = Distance.x * Distance.x + Distance.y * Distance.y - - var DistanceB = 1.0f - if (!Shoot) { - var FirstDirection = GetFirstDirection(Object.ID) - if (FirstDirection != -1) { - var Index = Object.ID - FirstDirection - var Angle = 2.0f * PI * float(Index % 8) / 8.0f - var Direction = float2(cos(Angle), sin(Angle)) - DistanceB = Distance.x * Direction.x + Distance.y * Direction.y - } - } - - var SightRange = DistanceA <= AttackDistance * AttackDistance - var ViewRange = DistanceA <= HearDistance * HearDistance || DistanceB >= 0.0f - if (ViewRange) { - ViewRange = IsVisible(Object.Position, Player.Position) - } - - var Attack = SightRange && ViewRange - - if (IsAttack(Enemy)) { - if (Attack) { - var Damage = Time * 10.0f - Player.Health = Player.Health - Damage - if (Player.Health < 0.0f) { - Player.Health = 0.0f - } - - if (!FlashState && Object.ID == GetAttackFrame(Enemy)) { - FlashState = true - FlashPhase = 0.0f - FlashColor = 0xff0000 - } - } else { - Object.ID = GetIdleFrame(Enemy) + GetPlayerAngle(Object.Position) - Object.Animation = 0.0f - } - } elif (!IsDying(Enemy)) { - if (Attack) { - Object.ID = GetAttackFrame(Enemy) - Object.Animation = 0.0f - } elif (ViewRange) { - Object.ID = GetIdleFrame(Enemy) + GetPlayerAngle(Object.Position) - Object.Animation = 0.0f - } - } - } -} - -def UpdateDoors(Time : float) { - var Direction = float2(cos(Player.Direction), sin(Player.Direction)) - - if (is_key_pressed(VK_SPACE)) { - if (!DoorUse) { - var X = int(Player.Position.x + Direction.x) - var Y = int(Player.Position.y + Direction.y) - if (X >= 0 && Y >= 0 && X < MapWidth && Y < MapHeight) { - if (IsDoor(X, Y)) { - DoorUse = true - assume Tile = Map[Y * MapWidth + X] - if (Tile.DoorState == 0) { - Tile.DoorState = 1 - } - } - } - } - } else { - DoorUse = false - } - - var DoorSpeed = Time * 1.0f - for (Y in range(0, MapHeight)) { - for (X in range(0, MapWidth)) { - if (!IsDoor(X, Y)) { - continue - } - - assume Tile = Map[Y * MapWidth + X] - - if (Tile.DoorState == 1) { - Tile.DoorSlide = Tile.DoorSlide + DoorSpeed - if (Tile.DoorSlide > 4.0f) { - Tile.DoorSlide = 4.0f - Tile.DoorState = 2 - } - } elif (Tile.DoorState == 2) { - Tile.DoorSlide = Tile.DoorSlide - DoorSpeed - if (Tile.DoorSlide < 0.0f) { - Tile.DoorSlide = 0.0f - Tile.DoorState = 0 - } - } - - var Block = float2(X, Y) - if (Player.Position.x + Player.Size >= Block.x && Player.Position.y + Player.Size >= Block.y && Player.Position.x - Player.Size <= Block.x + 1.0f && Player.Position.y - Player.Size <= Block.y + 1.0f) { - if (Tile.DoorState == 2 && Tile.DoorSlide >= 1.0f) { - Tile.DoorSlide = 4.0f - } - } - } - } -} - - -def UpdateFlash(Time : float) { - var FlashSpeed = Time * 10.0f - if (Player.Health <= 0.0f && FlashState && FlashColor == 0x7f0000) { - FlashPhase = FlashPhase + FlashSpeed * 0.1f - if (FlashPhase >= 1.0f) { - FlashPhase = 1.0f - - if (is_key_pressed(VK_SPACE)) { - UncompressMap() - InitPlayer() - InitWeapon() - InitObjects() - ClearVisibility() - } - } - } else { - if (FlashState) { - FlashPhase = FlashPhase + FlashSpeed - if (FlashPhase >= 1.0f) { - FlashPhase = 0.0f - FlashState = false - FlashColor = 0x000000 - } - } elif (Player.Health <= 0.0f) { - FlashState = true - FlashPhase = 0.0f - FlashColor = 0x7f0000 - } - } -} - -def ClearVisibility() { - for (Y in range(0, MapHeight)) { - for (X in range(0, MapWidth)) { - Map[Y * MapWidth + X].Visible = false - } - } -} - -def DrawBackground(var bmp : Bitmap) { - var ScreenWidth = bmp.size.x - var ScreenHeight = bmp.size.y - var CenterX = ScreenWidth / 2 - var CenterY = ScreenHeight / 2 - - fill_rect(bmp, 0, 0, ScreenWidth, CenterY, 0xff383838) - fill_rect(bmp, 0, CenterY, ScreenWidth, ScreenHeight - CenterY, 0xff707070) -} - -[unsafe_deref, jit, hint(unsafe_range_check, noalias=bmp, hot)] -def DrawWalls(var bmp : Bitmap) { - var ScreenWidth = bmp.size.x - var ScreenHeight = bmp.size.y - var CenterX = ScreenWidth / 2 - var CenterY = ScreenHeight / 2 - - clear(DepthBuffer) - DepthBuffer |> resize(bmp.size.x) - - var Position = Player.Position - var Direction = float2(cos(Player.Direction), sin(Player.Direction)) - - var MapPtr = unsafe(addr(Map[0])) - - for (X in range(0, ScreenWidth)) { - var View = float2(CenterX, X - CenterX) - var Ray = float2(View.x * Direction.x - View.y * Direction.y, View.x * Direction.y + View.y * Direction.x) - - var MapX = int(Position.x) - var MapY = int(Position.y) - - var StepX : int - if (Ray.x > 0.0f) { - StepX = 1 - } elif (Ray.x < 0.0f) { - StepX = -1 - } else { - StepX = 0 - } - - var StepY : int - if (Ray.y > 0.0f) { - StepY = 1 - } elif (Ray.y < 0.0f) { - StepY = -1 - } else { - StepY = 0 - } - - var Fraction = float2(Position.x - float(MapX), Position.y - float(MapY)) - - var Distance : float2 - if (Ray.x > 0.0f) { - Distance.x = 1.0f - Fraction.x - } elif (Ray.x < 0.0f) { - Distance.x = Fraction.x - } else { - Distance.x = 0.0f - } - - if (Ray.y > 0.0f) { - Distance.y = 1.0f - Fraction.y - } elif (Ray.y < 0.0f) { - Distance.y = Fraction.y - } else { - Distance.y = 0.0f - } - - var Sign = float2(StepX, StepY) - var Abs = Sign * Ray - - var Ratio = float2(0.0f, 0.0f) - if (Abs.x != 0.0f) { - Ratio.x = Abs.y / Abs.x - } - if (Abs.y != 0.0f) { - Ratio.y = Abs.x / Abs.y - } - - var Axis = float2(1.0f, 1.0f) - if (Abs.x >= Abs.y) { - Axis.y = Ratio.y - } else { - Axis.x = Ratio.x - } - - var Next = float2(Distance.x * Axis.x, Distance.y * Axis.y) - - if (Abs.x == 0.0f) { - Next = float2(1.0f, 0.0f) - Axis = float2(0.0f, 0.0f) - } - - if (Abs.y == 0.0f) { - Next = float2(0.0f, 1.0f) - Axis = float2(0.0f, 0.0f) - } - - Distance = Distance - float2(1.0f, 1.0f) - - var ID : int - var Side : int - var Door : bool - var Slide : float - var Empty : bool - - Door = IsDoor(MapX, MapY) - - Empty = true - while (Empty) { - unsafe { - MapPtr[MapY * MapWidth + MapX].Visible = true - } - - if (Next.x < Next.y) { - Next.x = Next.x + Axis.x - Distance.x = Distance.x + 1.0f - MapX = MapX + StepX - Side = 0 - } else { - Next.y = Next.y + Axis.y - Distance.y = Distance.y + 1.0f - MapY = MapY + StepY - Side = 1 - } - - unsafe { - ID = MapPtr[MapY * MapWidth + MapX].ID - } - Empty = ID == 0 || ID >= 128 - if (Door && Empty) { - Door = false - } - - if (ID >= 90 && ID <= 101) { - unsafe { - Slide = MapPtr[MapY * MapWidth + MapX].DoorSlide - } - var Vec = float2(MapX, MapY) - Position - if (Side == 0) { - Vec.x = (Vec.x + 0.5f) * Sign.x - var Open = Vec.x * Ratio.x * Sign.y - Vec.y - if (Open >= Slide && Open <= 1.0f) { - Distance.x = Vec.x - } else { - Empty = true - Door = true - Slide = 0.0f - } - } else { - Vec.y = (Vec.y + 0.5f) * Sign.y - var Open = Vec.y * Ratio.y * Sign.x - Vec.x - if (Open >= Slide && Open <= 1.0f) { - Distance.y = Vec.y - } else { - Empty = true - Door = true - Slide = 0.0f - } - } - } - } - - if (ID >= 90 && ID <= 91) { - ID = 50 - } - if (ID >= 92 && ID <= 99) { - ID = 53 - } - if (ID >= 100 && ID <= 101) { - ID = 52 - } - - if (Door) { - ID = 51 - } - - if (Side == 0) { - Distance.y = Distance.x * Ratio.x - } else { - Distance.x = Distance.y * Ratio.y - } - - Distance = Distance * Sign - - var Size = CenterY - var Depth = Distance.x * Direction.x + Distance.y * Direction.y - if (Depth != 0.0f) { - Size = int((float(CenterX)) / Depth) - } - var Y = CenterY - Size / 2 - - var T : float - if (Side == 0) { - T = Position.y + Distance.y - } else { - T = Position.x + Distance.x - } - - T = T - floor(T) - - if (ID == 50 || ID == 52 || ID == 53) { - T = T - Slide - } else { - if (Side == 0) { - if (StepX < 0) { - T = 1.0f - T - } - } else { - if (StepY > 0) { - T = 1.0f - T - } - } - } - - if (T > 63.0f / 64.0f) { - T = 63.0f / 64.0f - } - - var Sprite = (ID - 1) * 2 + 1 - Side - - var U = float(Sprite & 31) + T - var V = float(Sprite >> 5) - - - draw_vspan(bmp, Texture, X, Y, float4(U * 64.0f, V * 64.0f, 1.0f, 64.0f), Size) - - DepthBuffer[X] = Depth - } -} - -[jit, hint(unsafe_range_check, noalias=bmp, hot)] -def DrawObjects(var bmp : Bitmap) { - var Direction = float2(cos(Player.Direction), sin(Player.Direction)) - - var ScreenWidth = bmp.size.x - var ScreenHeight = bmp.size.y - var CenterX = ScreenWidth / 2 - var CenterY = ScreenHeight / 2 - - var MinX = 0 - var MinY = 0 - var MaxX = ScreenWidth - 1 - var MaxY = ScreenHeight - 1 - - var M11 = 0 - var M21 = 0 - var M12 = 0 - var M22 = 0 - var M31 = 0 - var M32 = 0 - - if (abs(Direction.x) >= abs(Direction.y)) { - if (Direction.X > 0.0f) { - M21 = -1 - } else { - M21 = 1 - } - - if (Direction.Y > 0.0f) { - M12 = -1 - } else { - M12 = 1 - } - } else { - if (Direction.X > 0.0f) { - M11 = -1 - } else { - M11 = 1 - } - - if (Direction.Y > 0.0f) { - M22 = -1 - } else { - M22 = 1 - } - } - - if (M11 < 0 || M21 < 0) { - M31 = MapWidth - 1 - } - if (M12 < 0 || M22 < 0) { - M32 = MapHeight - 1 - } - - var Width = MapWidth - var Height = MapHeight - if (M12 == 0) { - Width = MapHeight - } - if (M21 == 0) { - Height = MapWidth - } - - for (Y in range(0, Height)) { - for (X in range(0, Width)) { - var MapX = X * M11 + Y * M21 + M31 - var MapY = X * M12 + Y * M22 + M32 - - if (!Map[MapY * MapWidth + MapX].Visible) { - continue - } - - var Object = Objects[MapY * MapWidth + MapX] - var ID = Object.ID - if (ID < 128) { - continue - } - - var Distance = Object.Position - Player.Position - - var Center = float(CenterX) - var Size = float(CenterX) - - var Position = Distance.y * Direction.x - Distance.x * Direction.y - var Depth = Distance.x * Direction.x + Distance.y * Direction.y - if (Depth != 0.0f) { - Center = Center * Position / Depth - Size = float(CenterY) / Depth - } - - var X1 = CenterX - int(Size) + int(Center) - var Y1 = CenterY - int(Size) - var X2 = CenterX + int(Size) + int(Center) - var Y2 = CenterY + int(Size) - - var OriginX = float(X1) - var OriginY = float(Y1) - var SizeX = float(X2 - X1) - var SizeY = float(Y2 - Y1) - - if (X1 > MaxX || Y1 > MaxY || X2 < MinX || Y2 < MinY) { - continue - } - - if (X1 < MinX) { - X1 = MinX - } - if (Y1 < MinY) { - Y1 = MinY - } - if (X2 > MaxX) { - X2 = MaxX - } - if (Y2 > MaxY) { - Y2 = MaxY - } - - while (X1 <= X2 && DepthBuffer[X1] < Depth) { - X1 = X1 + 1 - } - while (X1 <= X2 && DepthBuffer[X2] < Depth) { - X2 = X2 - 1 - } - - if (X1 > X2) { - continue - } - - var FirstDirection = GetFirstDirection(ID) - if (FirstDirection != -1) { - var PlayerAngle = GetPlayerAngle(Object.Position) - var Index = ID - FirstDirection - var Angle = Index % 8 - var Phase = Index / 8 - Angle = (Angle + 8 - PlayerAngle) % 8 - ID = Phase * 8 + Angle + FirstDirection - } - - var U = float(ID % 32) - var V = float(ID / 32) - - var U1 = U + (float(X1) - OriginX) / SizeX - var V1 = V + (float(Y1) - OriginY) / SizeY - var U2 = U + (float(X2) - OriginX) / SizeX - var V2 = V + (float(Y2) - OriginY) / SizeY - - draw_image_region_masked(bmp, Texture, X1, Y1, float4(U1 * 64.0f, V1 * 64.0f, (U2 - U1) * 64.0f, (V2 - V1) * 64.0f), int2(X2 - X1, Y2 - Y1), MASK_COLOR) - } - } -} - -def DrawMap(var bmp : Bitmap) { - ClearVisibility() - DrawWalls(bmp) - DrawObjects(bmp) -} - -def DrawWeapon(var bmp : Bitmap) { - var ScreenWidth = bmp.size.x - var ScreenHeight = bmp.size.y - var CenterX = ScreenWidth / 2 - var CenterY = ScreenHeight / 2 - - var Size = ScreenHeight - - var X = CenterX - Size / 2 - var Y = ScreenHeight - Size - - var U = float(Weapon.Type * 5) + floor(Weapon.Animation) - var V = 17.0f - - draw_image_region_masked(bmp, Texture, X, Y, float4(U * 64.0f, V * 64.0f, 64.0f, 64.0f), int2(Size, Size), MASK_COLOR) -} - -def DrawHealth(var bmp : Bitmap) { - var ScreenWidth = bmp.size.x - var ScreenHeight = bmp.size.y - - var BarWidth = ScreenHeight / 3 - var BarHeight = ScreenHeight / 30 - - var Border = ScreenHeight / 20 - - var Alpha = Player.Health / 100.0f - if (Alpha < 0.0f) { - Alpha = 0.0f - } - if (Alpha > 1.0f) { - Alpha = 1.0f - } - - var Value = uint(float(255.0f * Alpha)) - var Color = 0xff000000 | ((uint(255) - Value) << uint(16)) | (Value << uint(8)) - - var X = Border - var Y = ScreenHeight - Border - BarHeight - - var Width = int(float(BarWidth) * Alpha) - var Height = BarHeight - - fill_rect(bmp, X, Y, Width, Height, Color) - fill_rect(bmp, X + Width, Y, BarWidth - Width, Height, 0x7f7f7f7f) -} - -def DrawFlash(var bmp : Bitmap) { - if (!FlashState) { - return - } - - var ScreenWidth = bmp.size.x - var ScreenHeight = bmp.size.y - - var Alpha = FlashPhase - if (FlashColor != 0x7f0000) { - Alpha = Alpha * 2.0f - if (Alpha > 1.0f) { - Alpha = 2.0f - Alpha - } - Alpha = Alpha * 0.5f - } - - if (Alpha < 0.0f) { - Alpha = 0.0f - } - if (Alpha > 1.0f) { - Alpha = 1.0f - } - - var Color = (uint(Alpha * 255.0f) << uint(24)) | FlashColor - fill_rect(bmp, 0, 0, ScreenWidth, ScreenHeight, Color) -} - -def LoadTexture { - var x, y : int - var comp : int - let name = "{get_das_root()}/examples/w3dold/Texture.png" - let data = stbi_load(name, safe_addr(x), safe_addr(y), safe_addr(comp), 4) - if (data == null) { - panic("no texture {name}\n") - } - Texture.size = int2(x, y) - Texture.pixels = unsafe(reinterpret data) - for (i in range(Texture.size.x * Texture.size.y)) { - var pixel = unsafe(Texture.pixels[i]) - pixel = (pixel & 0xff00ff00) | ((pixel & 0xff) << 16u) | ((pixel & 0xff0000) >> 16u) - unsafe(Texture.pixels[i]) = pixel - } -} - -[export] -def on_initialize() { - set_debug_status_string("arrows - move, ctrl - attack, space - action, alt - strafe, 1,2,3,4 - select weapon") - LoadTexture() - UncompressMap() - InitPlayer() - InitWeapon() - InitObjects() - ClearVisibility() -} - -var time = 12lf - -[export] -def on_update(var bmp : Bitmap) { - - let begin = ref_time_ticks() - - let Time = get_delta_time_sec() - UpdatePlayer(Time) - UpdateWeapon(Time) - UpdateObjects(Time) - UpdateEnemies(Time) - UpdateDoors(Time) - UpdateFlash(Time) - - DrawBackground(bmp) - DrawMap(bmp) - DrawWeapon(bmp) - DrawHealth(bmp) - DrawFlash(bmp) - - time = time * 0.95lf + double(get_time_usec(begin) / 1000) * 0.05lf -} - - // set_debug_status_string("update time: {get_time_usec(begin)/1000}ms avg: {time}ms") - -[export] -def main { - on_initialize() - raster_app_main <| $(backbuffer) { - on_update(backbuffer) - } -} - diff --git a/generate_xcode_min.sh b/generate_xcode_min.sh index 33f04f0149..62e19e56a6 100755 --- a/generate_xcode_min.sh +++ b/generate_xcode_min.sh @@ -9,8 +9,6 @@ time { CC=clang CXX=clang++ cmake -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" \ -DDAS_GLFW_DISABLED:BOOL=TRUE \ -DDAS_IMGUI_DISABLED:BOOL=TRUE \ - -DDAS_BGFX_DISABLED:BOOL=TRUE \ - -DDAS_XBYAK_DISABLED:BOOL=TRUE \ -DDAS_CLANG_BIND_DISABLED:BOOL=TRUE \ -DDAS_LLVM_DISABLED:BOOL=TRUE \ -DDAS_MINFFT_DISABLED:BOOL=TRUE \ diff --git a/modules.py b/modules.py index c7eacde3c0..8550b169fa 100644 --- a/modules.py +++ b/modules.py @@ -6,7 +6,6 @@ options_table = { - "dasBGFX": "DAS_BGFX_DISABLED", "dasClangBind": "DAS_CLANG_BIND_DISABLED", "dasGlfw": "DAS_GLFW_DISABLED", "dasGlsl": "", @@ -16,12 +15,10 @@ "dasMinfft": "DAS_MINFFT_DISABLED", "dasOpenGL": "", "dasQuirrel": "DAS_QUIRREL_DISABLED", - "dasSFML": "DAS_SFML_DISABLED", "dasAudio": "DAS_AUDIO_DISABLED", "dasStbImage": "DAS_STBIMAGE_DISABLED", "dasStbTrueType": "DAS_STBTRUETYPE_DISABLED", - "dasStdDlg": "DAS_STDDLG_DISABLED", - "dasXbyak": "DAS_XBYAK_DISABLED" + "dasStdDlg": "DAS_STDDLG_DISABLED" } cmake_options_cache: Dict[str, str] = {} diff --git a/modules/dasBGFX b/modules/dasBGFX deleted file mode 160000 index a569838d35..0000000000 --- a/modules/dasBGFX +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a569838d35a2a584946e784d5e013fb2f08ec4c1 diff --git a/modules/dasSFML b/modules/dasSFML deleted file mode 160000 index 8ea230433c..0000000000 --- a/modules/dasSFML +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8ea230433c8c9e6e49a91b2d5a70a54dc7b4f789 diff --git a/modules/dasStbImage/CMakeLists.txt b/modules/dasStbImage/CMakeLists.txt index 433aa1faf4..7da85af27b 100644 --- a/modules/dasStbImage/CMakeLists.txt +++ b/modules/dasStbImage/CMakeLists.txt @@ -22,11 +22,5 @@ IF ((NOT DAS_STBIMAGE_INCLUDED) AND (NOT ${DAS_STBIMAGE_DISABLED})) # ADD_DEPENDENCIES(libDasModuleStbImage) TARGET_INCLUDE_DIRECTORIES(libDasModuleStbImage PUBLIC ${STBIMAGE_INCLUDE_DIR}) - IF(NOT APPLE) - IF((NOT ${DAS_SFML_DISABLED}) OR (NOT DEFINED DAS_SFML_DISABLED)) - TARGET_COMPILE_DEFINITIONS(libDasModuleStbImage PUBLIC -DSTB_IMPLEMENTATION_ALREADY_LINKED) - ENDIF() - ENDIF() - SETUP_CPP11(libDasModuleStbImage) ENDIF() diff --git a/modules/dasStbTrueType/CMakeLists.txt b/modules/dasStbTrueType/CMakeLists.txt index f43987d2ff..2172283526 100644 --- a/modules/dasStbTrueType/CMakeLists.txt +++ b/modules/dasStbTrueType/CMakeLists.txt @@ -29,9 +29,4 @@ IF ((NOT DAS_STBTRUETYPE_INCLUDED) AND ((NOT ${DAS_STBTRUETYPE_DISABLED}) OR (NO PATTERN "*.das" ) - IF ((NOT ${DAS_BGFX_DISABLED}) OR (NOT DEFINED DAS_BGFX_DISABLED)) - install(FILES ${PROJECT_SOURCE_DIR}/modules/dasBGFX/bgfx/bgfx/examples/runtime/font/droidsansmono.ttf - DESTINATION ${DAS_INSTALL_EXAMPLESDIR}/media - ) - ENDIF() ENDIF() diff --git a/modules/dasXbyak b/modules/dasXbyak deleted file mode 160000 index aa6d14baa4..0000000000 --- a/modules/dasXbyak +++ /dev/null @@ -1 +0,0 @@ -Subproject commit aa6d14baa467fb433a6492e76700daee3b3756ef diff --git a/tests/constexpr/test_constexpr_fail.das b/tests/constexpr/test_constexpr_fail.das new file mode 100644 index 0000000000..37d842f25d --- /dev/null +++ b/tests/constexpr/test_constexpr_fail.das @@ -0,0 +1,21 @@ +options gen2 +expect 40102:1 + +// Verify that [constexpr] annotation rejects non-constant arguments. +// The call `foo("ouch", BOO)` must fail because BOO is a global variable, +// not a compile-time constant. + +require daslib/constant_expression + +[constexpr(a)] +def foo(t : string; a : int) { + print("{t} = {a}\n") +} + +var BOO = 13 + +[export] +def main() { + foo("blah", 1) // ok — literal 1 is constexpr + foo("ouch", BOO) // 40102: a is not constexpr +} diff --git a/tests/data_walker/dw_common.das b/tests/data_walker/dw_common.das new file mode 100644 index 0000000000..8181f70b34 --- /dev/null +++ b/tests/data_walker/dw_common.das @@ -0,0 +1,288 @@ +// Shared helpers and data types for DapiDataWalker tests. +// +// Convention: test files `require dw_common` to access LogWalker, +// walk_and_log, and all shared struct / enum / class definitions. + +options gen2 +options indenting = 4 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +module dw_common shared public + +require dastest/testing_boost public +require rtti public +require debugapi public +require strings public + + +// ============================================================ +// LogWalker — logs callback invocations as "NAME:value\n" +// ============================================================ + +class LogWalker : DapiDataWalker { + log : string + + // --- scalars --- + def override Bool(var value : bool&) : void { + log += "Bool:{value}\n" + } + def override Int8(var value : int8&) : void { + log += "Int8:{int(value)}\n" + } + def override UInt8(var value : uint8&) : void { + log += "UInt8:{int(value)}\n" + } + def override Int16(var value : int16&) : void { + log += "Int16:{int(value)}\n" + } + def override UInt16(var value : uint16&) : void { + log += "UInt16:{int(value)}\n" + } + def override Int(var value : int&) : void { + log += "Int:{value}\n" + } + def override UInt(var value : uint&) : void { + log += "UInt:{value}\n" + } + def override Int64(var value : int64&) : void { + log += "Int64:{value}\n" + } + def override UInt64(var value : uint64&) : void { + log += "UInt64:{value}\n" + } + def override Float(var value : float&) : void { + log += "Float:{value}\n" + } + def override Double(var value : double&) : void { + log += "Double:{value}\n" + } + def override String(var value : string&) : void { + log += "String:{value}\n" + } + + // --- vectors --- + def override Int2(var value : int2&) : void { + log += "Int2:{value}\n" + } + def override Int3(var value : int3&) : void { + log += "Int3:{value}\n" + } + def override Int4(var value : int4&) : void { + log += "Int4:{value}\n" + } + def override UInt2(var value : uint2&) : void { + log += "UInt2:{value}\n" + } + def override UInt3(var value : uint3&) : void { + log += "UInt3:{value}\n" + } + def override UInt4(var value : uint4&) : void { + log += "UInt4:{value}\n" + } + def override Float2(var value : float2&) : void { + log += "Float2:{value}\n" + } + def override Float3(var value : float3&) : void { + log += "Float3:{value}\n" + } + def override Float4(var value : float4&) : void { + log += "Float4:{value}\n" + } + + // --- ranges --- + def override Range(var value : range&) : void { + log += "Range:{value}\n" + } + def override URange(var value : urange&) : void { + log += "URange:{value}\n" + } + def override Range64(var value : range64&) : void { + log += "Range64:{value}\n" + } + def override URange64(var value : urange64&) : void { + log += "URange64:{value}\n" + } + + // --- enum/bitfield --- + def override WalkEnumeration(var value : int&; ei : EnumInfo) : void { + log += "Enum:{ei.name}:{value}\n" + } + def override Bitfield(var value : uint&; ti : TypeInfo) : void { + log += "Bitfield:{value}\n" + } + + // --- structure --- + def override beforeStructure(ps : void?; si : StructInfo) : void { + log += "beforeStruct:{si.name}\n" + } + def override afterStructure(ps : void?; si : StructInfo) : void { + log += "afterStruct:{si.name}\n" + } + def override beforeStructureField(ps : void?; si : StructInfo; pv : void?; vi : VarInfo; last : bool) : void { + log += "beforeField:{vi.name}:{last}\n" + } + def override afterStructureField(ps : void?; si : StructInfo; pv : void?; vi : VarInfo; last : bool) : void { + log += "afterField:{vi.name}:{last}\n" + } + + // --- dim (fixed array) --- + def override beforeDim(ps : void?; ti : TypeInfo) : void { + log += "beforeDim\n" + } + def override afterDim(ps : void?; ti : TypeInfo) : void { + log += "afterDim\n" + } + + // --- dynamic array --- + def override beforeArray(pa : DapiArray; ti : TypeInfo) : void { + log += "beforeArray\n" + } + def override afterArray(pa : DapiArray; ti : TypeInfo) : void { + log += "afterArray\n" + } + def override beforeArrayData(ps : void?; stride : uint; count : uint; ti : TypeInfo) : void { + log += "beforeArrayData:{int(count)}\n" + } + def override afterArrayData(ps : void?; stride : uint; count : uint; ti : TypeInfo) : void { + log += "afterArrayData:{int(count)}\n" + } + def override beforeArrayElement(ps : void?; ti : TypeInfo; pe : void?; index : uint; last : bool) : void { + log += "beforeElem:{int(index)}:{last}\n" + } + def override afterArrayElement(ps : void?; ti : TypeInfo; pe : void?; index : uint; last : bool) : void { + log += "afterElem:{int(index)}:{last}\n" + } + + // --- table --- + def override beforeTable(pa : DapiTable; ti : TypeInfo) : void { + log += "beforeTable\n" + } + def override afterTable(pa : DapiTable; ti : TypeInfo) : void { + log += "afterTable\n" + } + def override beforeTableKey(pa : DapiTable; ti : TypeInfo; pk : void?; ki : TypeInfo; index : uint; last : bool) : void { + log += "beforeKey:{int(index)}:{last}\n" + } + def override afterTableKey(pa : DapiTable; ti : TypeInfo; pk : void?; ki : TypeInfo; index : uint; last : bool) : void { + log += "afterKey:{int(index)}:{last}\n" + } + def override beforeTableValue(pa : DapiTable; ti : TypeInfo; pv : void?; kv : TypeInfo; index : uint; last : bool) : void { + log += "beforeVal:{int(index)}:{last}\n" + } + def override afterTableValue(pa : DapiTable; ti : TypeInfo; pv : void?; kv : TypeInfo; index : uint; last : bool) : void { + log += "afterVal:{int(index)}:{last}\n" + } + + // --- tuple --- + def override beforeTuple(ps : void?; ti : TypeInfo) : void { + log += "beforeTuple\n" + } + def override afterTuple(ps : void?; ti : TypeInfo) : void { + log += "afterTuple\n" + } + def override beforeTupleEntry(ps : void?; ti : TypeInfo; pv : void?; idx : int; last : bool) : void { + log += "beforeTupleEntry:{idx}:{last}\n" + } + def override afterTupleEntry(ps : void?; ti : TypeInfo; pv : void?; idx : int; last : bool) : void { + log += "afterTupleEntry:{idx}:{last}\n" + } + + // --- variant --- + def override beforeVariant(ps : void?; ti : TypeInfo) : void { + log += "beforeVariant\n" + } + def override afterVariant(ps : void?; ti : TypeInfo) : void { + log += "afterVariant\n" + } + + // --- pointer --- + def override beforePtr(ps : void?; ti : TypeInfo) : void { + log += "beforePtr\n" + } + def override afterPtr(ps : void?; ti : TypeInfo) : void { + log += "afterPtr\n" + } + def override Null(ti : TypeInfo) : void { + log += "Null\n" + } + + // --- lambda --- + def override beforeLambda(var value : DapiLambda; ti : TypeInfo) : void { + log += "beforeLambda\n" + } + def override afterLambda(var value : DapiLambda; ti : TypeInfo) : void { + log += "afterLambda\n" + } +} + + +// ============================================================ +// Shared data types +// ============================================================ + +struct SimpleStruct { + x : int = 0 + y : float = 0.0 +} + +struct NestedStruct { + inner : SimpleStruct = SimpleStruct() + tag : string = "" +} + +struct ManyFields { + a : int = 0 + b : int = 0 + c : int = 0 + d : int = 0 +} + +enum Color { + Red + Green + Blue +} + +bitfield Permissions { + read + write + execute +} + +typedef MyVariant = variant + +class Animal { + name : string = "" +} + +class Dog : Animal { + breed : string = "" +} + +struct AllScalars { + b : bool = false + i : int = 0 + u : uint = 0u + f : float = 0.0 + d : double = 0.0lf + s : string = "" + i8 : int8 = int8(0) + u8 : uint8 = uint8(0) + i16 : int16 = int16(0) + u16 : uint16 = uint16(0) + i64 : int64 = 0l + u64 : uint64 = 0ul +} + +struct VectorRangeStruct { + v2 : float2 = float2(0.0, 0.0) + v3 : float3 = float3(0.0, 0.0, 0.0) + v4 : float4 = float4(0.0, 0.0, 0.0, 0.0) + r : range = range(0, 0) +} + +struct TreeNode { + value : int = 0 + children : array +} diff --git a/tests/data_walker/test_walk_containers.das b/tests/data_walker/test_walk_containers.das new file mode 100644 index 0000000000..24a104efe0 --- /dev/null +++ b/tests/data_walker/test_walk_containers.das @@ -0,0 +1,224 @@ +// Tests for DapiDataWalker — containers (arrays, dim, tables) +// +// Covers: dynamic array, fixed array (dim), tables (string keys, int keys), +// empty containers, single-element, array of structs, array of strings, +// array of tuples, table with multiple entries, key-value ordering + +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dw_common + + +// ============================================================ +// Dynamic arrays +// ============================================================ + +[test] +def test_walk_array(t : T?) { + t |> run("array of ints") @(t : T?) { + var walker = new LogWalker() + var arr = [10, 20, 30] + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + var expected = "beforeArray\n" + expected += "beforeArrayData:3\n" + expected += "beforeElem:0:false\n" + expected += "Int:10\n" + expected += "afterElem:0:false\n" + expected += "beforeElem:1:false\n" + expected += "Int:20\n" + expected += "afterElem:1:false\n" + expected += "beforeElem:2:true\n" + expected += "Int:30\n" + expected += "afterElem:2:true\n" + expected += "afterArrayData:3\n" + expected += "afterArray\n" + t |> equal(walker.log, expected) + unsafe { delete walker; } + } + t |> run("empty array") @(t : T?) { + var walker = new LogWalker() + var arr : array + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + var expected = "beforeArray\n" + expected += "beforeArrayData:0\n" + expected += "afterArrayData:0\n" + expected += "afterArray\n" + t |> equal(walker.log, expected) + unsafe { delete walker; } + } + t |> run("single element array") @(t : T?) { + var walker = new LogWalker() + var arr = [42] + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + // Single element: index=0, last=true + t |> equal(find(walker.log, "beforeElem:0:true") != -1, true) + t |> equal(find(walker.log, "Int:42") != -1, true) + unsafe { delete walker; } + } + t |> run("array of structs") @(t : T?) { + var walker = new LogWalker() + var arr : array + arr |> push(SimpleStruct(x = 1, y = 1.0)) + arr |> push(SimpleStruct(x = 2, y = 2.0)) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + t |> equal(find(walker.log, "beforeArray") != -1, true) + t |> equal(find(walker.log, "beforeStruct:SimpleStruct") != -1, true) + t |> equal(find(walker.log, "Int:1") != -1, true) + t |> equal(find(walker.log, "Int:2") != -1, true) + unsafe { delete walker; } + } + t |> run("array of strings") @(t : T?) { + var walker = new LogWalker() + var arr = ["foo", "bar", "baz"] + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + t |> equal(find(walker.log, "String:foo") != -1, true) + t |> equal(find(walker.log, "String:bar") != -1, true) + t |> equal(find(walker.log, "String:baz") != -1, true) + unsafe { delete walker; } + } + t |> run("array of tuples") @(t : T?) { + var walker = new LogWalker() + var arr : array> + arr |> push((1, "one")) + arr |> push((2, "two")) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + t |> equal(find(walker.log, "beforeArray") != -1, true) + t |> equal(find(walker.log, "beforeTuple") != -1, true) + t |> equal(find(walker.log, "Int:1") != -1, true) + t |> equal(find(walker.log, "String:one") != -1, true) + t |> equal(find(walker.log, "Int:2") != -1, true) + t |> equal(find(walker.log, "String:two") != -1, true) + unsafe { delete walker; } + } +} + + +// ============================================================ +// Fixed-size arrays (dim) +// ============================================================ + +[test] +def test_walk_dim(t : T?) { + t |> run("int dim") @(t : T?) { + var walker = new LogWalker() + var arr : int[3] + arr[0] = 100 + arr[1] = 200 + arr[2] = 300 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + t |> equal(find(walker.log, "beforeDim") != -1, true) + t |> equal(find(walker.log, "Int:100") != -1, true) + t |> equal(find(walker.log, "Int:200") != -1, true) + t |> equal(find(walker.log, "Int:300") != -1, true) + t |> equal(find(walker.log, "afterDim") != -1, true) + unsafe { delete walker; } + } +} + + +// ============================================================ +// Tables +// ============================================================ + +[test] +def test_walk_table(t : T?) { + t |> run("table string to int") @(t : T?) { + var walker = new LogWalker() + var tab : table + tab |> insert("alpha", 1) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(tab), typeinfo rtti_typeinfo(tab)) + } + t |> equal(find(walker.log, "beforeTable") != -1, true) + t |> equal(find(walker.log, "String:alpha") != -1, true) + t |> equal(find(walker.log, "Int:1") != -1, true) + t |> equal(find(walker.log, "afterTable") != -1, true) + unsafe { delete walker; } + } + t |> run("empty table") @(t : T?) { + var walker = new LogWalker() + var tab : table + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(tab), typeinfo rtti_typeinfo(tab)) + } + var expected = "beforeTable\n" + expected += "afterTable\n" + t |> equal(walker.log, expected) + unsafe { delete walker; } + } + t |> run("table key-value order") @(t : T?) { + // Each entry: beforeKey → key value → afterKey → beforeVal → val value → afterVal + var walker = new LogWalker() + var tab : table + tab |> insert("x", 42) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(tab), typeinfo rtti_typeinfo(tab)) + } + var key_pos = find(walker.log, "beforeKey") + var key_after_pos = find(walker.log, "afterKey") + var val_pos = find(walker.log, "beforeVal") + var val_after_pos = find(walker.log, "afterVal") + // Key should come before value + t |> equal(key_pos < key_after_pos, true) + t |> equal(key_after_pos < val_pos, true) + t |> equal(val_pos < val_after_pos, true) + unsafe { delete walker; } + } + t |> run("table int to string") @(t : T?) { + var walker = new LogWalker() + var tab : table + tab |> insert(42, "answer") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(tab), typeinfo rtti_typeinfo(tab)) + } + t |> equal(find(walker.log, "Int:42") != -1, true) + t |> equal(find(walker.log, "String:answer") != -1, true) + unsafe { delete walker; } + } + t |> run("table with 3 entries") @(t : T?) { + var walker = new LogWalker() + var tab : table + tab |> insert("a", 1) + tab |> insert("b", 2) + tab |> insert("c", 3) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(tab), typeinfo rtti_typeinfo(tab)) + } + // All 3 keys and values should appear (order may vary due to hash table) + t |> equal(find(walker.log, "String:a") != -1, true) + t |> equal(find(walker.log, "String:b") != -1, true) + t |> equal(find(walker.log, "String:c") != -1, true) + t |> equal(find(walker.log, "Int:1") != -1, true) + t |> equal(find(walker.log, "Int:2") != -1, true) + t |> equal(find(walker.log, "Int:3") != -1, true) + unsafe { delete walker; } + } +} diff --git a/tests/data_walker/test_walk_edge_cases.das b/tests/data_walker/test_walk_edge_cases.das new file mode 100644 index 0000000000..b87955d2d9 --- /dev/null +++ b/tests/data_walker/test_walk_edge_cases.das @@ -0,0 +1,242 @@ +// Tests for DapiDataWalker — edge cases and miscellaneous +// +// Covers: null/non-null pointers, lambdas, edge values (zero, negative, +// min/max int), deeply nested data, adapter reuse, scalar counting + +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dw_common + + +// ============================================================ +// Local walker class +// ============================================================ + +// Counts all scalar visits +class CountWalker : DapiDataWalker { + count : int = 0 + def override Bool(var value : bool&) : void { count++; } + def override Int(var value : int&) : void { count++; } + def override UInt(var value : uint&) : void { count++; } + def override Float(var value : float&) : void { count++; } + def override Double(var value : double&) : void { count++; } + def override String(var value : string&) : void { count++; } + def override Int64(var value : int64&) : void { count++; } + def override UInt64(var value : uint64&) : void { count++; } + def override Int8(var value : int8&) : void { count++; } + def override UInt8(var value : uint8&) : void { count++; } + def override Int16(var value : int16&) : void { count++; } + def override UInt16(var value : uint16&) : void { count++; } +} + + +// ============================================================ +// Pointers +// ============================================================ + +[test] +def test_walk_null_pointer(t : T?) { + t |> run("null pointer") @(t : T?) { + var walker = new LogWalker() + var p : SimpleStruct? + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(p), typeinfo rtti_typeinfo(p)) + } + // Null pointer: beforePtr → Null → afterPtr (walker still brackets with ptr callbacks) + var expected = "beforePtr\n" + expected += "Null\n" + expected += "afterPtr\n" + t |> equal(walker.log, expected) + unsafe { delete walker; } + } + t |> run("non-null pointer") @(t : T?) { + var walker = new LogWalker() + var s = SimpleStruct(x = 7, y = 1.5) + var p : SimpleStruct? = unsafe(addr(s)) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(p), typeinfo rtti_typeinfo(p)) + } + t |> equal(find(walker.log, "beforePtr") != -1, true) + t |> equal(find(walker.log, "beforeStruct:SimpleStruct") != -1, true) + t |> equal(find(walker.log, "Int:7") != -1, true) + t |> equal(find(walker.log, "afterPtr") != -1, true) + unsafe { delete walker; } + } +} + + +// ============================================================ +// Lambdas +// ============================================================ + +[test] +def test_walk_lambda(t : T?) { + t |> run("lambda with capture") @(t : T?) { + var walker = new LogWalker() + var captured_value = 99 + var lam <- @ { + return captured_value + } + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(lam), typeinfo rtti_typeinfo(lam)) + } + t |> equal(find(walker.log, "beforeLambda") != -1, true) + t |> equal(find(walker.log, "afterLambda") != -1, true) + unsafe { delete walker; } + } +} + + +// ============================================================ +// Edge values +// ============================================================ + +[test] +def test_walk_edge_values(t : T?) { + t |> run("zero int") @(t : T?) { + var walker = new LogWalker() + var x = 0 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int:0\n") + unsafe { delete walker; } + } + t |> run("negative int") @(t : T?) { + var walker = new LogWalker() + var x = -42 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int:-42\n") + unsafe { delete walker; } + } + t |> run("negative float") @(t : T?) { + var walker = new LogWalker() + var x = -1.5 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Float:-1.5\n") + unsafe { delete walker; } + } + t |> run("max int") @(t : T?) { + var walker = new LogWalker() + var x = 2147483647 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int:2147483647\n") + unsafe { delete walker; } + } + t |> run("min int") @(t : T?) { + var walker = new LogWalker() + var x = -2147483647 - 1 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int:-2147483648\n") + unsafe { delete walker; } + } +} + + +// ============================================================ +// Deeply nested data +// ============================================================ + +[test] +def test_deeply_nested(t : T?) { + t |> run("nested struct in array") @(t : T?) { + var walker = new LogWalker() + var root = TreeNode(value = 1) + root.children |> emplace(TreeNode(value = 2)) + root.children |> emplace(TreeNode(value = 3)) + root.children[0].children |> emplace(TreeNode(value = 4)) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(root), typeinfo rtti_typeinfo(root)) + } + // All 4 values should be visited + t |> equal(find(walker.log, "Int:1") != -1, true) + t |> equal(find(walker.log, "Int:2") != -1, true) + t |> equal(find(walker.log, "Int:3") != -1, true) + t |> equal(find(walker.log, "Int:4") != -1, true) + unsafe { delete walker; } + } +} + + +// ============================================================ +// Adapter reuse +// ============================================================ + +[test] +def test_reuse_adapter(t : T?) { + t |> run("walk twice with same adapter") @(t : T?) { + var walker = new LogWalker() + var inscope adapter <- make_data_walker(walker) + var x = 10 + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int:10\n") + // Reset log and walk again + walker.log = "" + var y = 20 + unsafe { + adapter |> walk_data(addr(y), typeinfo rtti_typeinfo(y)) + } + t |> equal(walker.log, "Int:20\n") + unsafe { delete walker; } + } +} + + +// ============================================================ +// Scalar counting +// ============================================================ + +[test] +def test_count_scalars(t : T?) { + t |> run("count in struct") @(t : T?) { + var walker = new CountWalker() + var s = SimpleStruct(x = 1, y = 2.0) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + t |> equal(walker.count, 2) // x(int) + y(float) + unsafe { delete walker; } + } + t |> run("count in nested struct") @(t : T?) { + var walker = new CountWalker() + var s = NestedStruct(inner = SimpleStruct(x = 1, y = 2.0), tag = "test") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + t |> equal(walker.count, 3) // inner.x(int) + inner.y(float) + tag(string) + unsafe { delete walker; } + } + t |> run("count in array") @(t : T?) { + var walker = new CountWalker() + var arr = [1, 2, 3, 4, 5] + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + t |> equal(walker.count, 5) + unsafe { delete walker; } + } +} diff --git a/tests/data_walker/test_walk_filtering.das b/tests/data_walker/test_walk_filtering.das new file mode 100644 index 0000000000..98f594bfe7 --- /dev/null +++ b/tests/data_walker/test_walk_filtering.das @@ -0,0 +1,243 @@ +// Tests for DapiDataWalker — canVisit* filtering +// +// Covers: canVisitStructure, canVisitArray, canVisitArrayData, +// canVisitTableData, canVisitPointer, selective struct walking + +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dw_common + + +// ============================================================ +// Local walker classes for filtering tests +// ============================================================ + +// A walker that skips structures entirely +class SkipStructWalker : DapiDataWalker { + log : string + def override canVisitStructure(ps : void?; si : StructInfo) : bool { + log += "canVisitStructure:false\n" + return false + } + def override Int(var value : int&) : void { + log += "Int:{value}\n" + } + def override Float(var value : float&) : void { + log += "Float:{value}\n" + } + def override beforeStructure(ps : void?; si : StructInfo) : void { + log += "beforeStruct\n" + } + def override afterStructure(ps : void?; si : StructInfo) : void { + log += "afterStruct\n" + } +} + +// A walker that skips arrays +class SkipArrayWalker : DapiDataWalker { + log : string + def override canVisitArray(pa : void?; ti : TypeInfo) : bool { + return false + } + def override Int(var value : int&) : void { + log += "Int:{value}\n" + } + def override beforeArray(pa : DapiArray; ti : TypeInfo) : void { + log += "beforeArray\n" + } +} + +// A walker that skips array data but still gets before/afterArray +class SkipArrayDataWalker : DapiDataWalker { + log : string + def override canVisitArrayData(ti : TypeInfo; count : uint) : bool { + log += "canVisitArrayData:{int(count)}\n" + return false + } + def override beforeArray(pa : DapiArray; ti : TypeInfo) : void { + log += "beforeArray\n" + } + def override afterArray(pa : DapiArray; ti : TypeInfo) : void { + log += "afterArray\n" + } + def override Int(var value : int&) : void { + log += "Int:{value}\n" + } +} + +// A walker that skips table data +class SkipTableDataWalker : DapiDataWalker { + log : string + def override canVisitTableData(ti : TypeInfo) : bool { + return false + } + def override beforeTable(pa : DapiTable; ti : TypeInfo) : void { + log += "beforeTable\n" + } + def override afterTable(pa : DapiTable; ti : TypeInfo) : void { + log += "afterTable\n" + } + def override String(var value : string&) : void { + log += "String:{value}\n" + } + def override Int(var value : int&) : void { + log += "Int:{value}\n" + } +} + +// A walker that skips pointer dereference +class SkipPointerWalker : DapiDataWalker { + log : string + def override canVisitPointer(ti : TypeInfo) : bool { + return false + } + def override beforePtr(ps : void?; ti : TypeInfo) : void { + log += "beforePtr\n" + } + def override Int(var value : int&) : void { + log += "Int:{value}\n" + } + def override beforeStructure(ps : void?; si : StructInfo) : void { + log += "beforeStruct\n" + } +} + +// A walker that selectively skips a named struct +class SelectiveStructWalker : DapiDataWalker { + log : string + skip_name : string + def override canVisitStructure(ps : void?; si : StructInfo) : bool { + if (si.name == skip_name) { + return false + } + return true + } + def override beforeStructure(ps : void?; si : StructInfo) : void { + log += "visit:{si.name}\n" + } + def override Int(var value : int&) : void { + log += "Int:{value}\n" + } + def override Float(var value : float&) : void { + log += "Float:{value}\n" + } + def override String(var value : string&) : void { + log += "String:{value}\n" + } +} + + +// ============================================================ +// Tests +// ============================================================ + +[test] +def test_can_visit_filtering(t : T?) { + t |> run("skip structures") @(t : T?) { + var walker = new SkipStructWalker() + var s = SimpleStruct(x = 10, y = 2.5) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + // Should see canVisitStructure but NOT beforeStruct/afterStruct or field values + t |> equal(find(walker.log, "canVisitStructure:false") != -1, true) + t |> equal(find(walker.log, "beforeStruct") == -1, true) + t |> equal(find(walker.log, "Int:") == -1, true) + t |> equal(find(walker.log, "Float:") == -1, true) + unsafe { delete walker; } + } + t |> run("skip arrays") @(t : T?) { + var walker = new SkipArrayWalker() + var arr = [1, 2, 3] + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + // Should NOT see any Int callbacks or beforeArray + t |> equal(walker.log, "") + unsafe { delete walker; } + } +} + + +[test] +def test_can_visit_array_data(t : T?) { + t |> run("skip array data but still get before/after array") @(t : T?) { + var walker = new SkipArrayDataWalker() + var arr = [1, 2, 3] + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + // Should see beforeArray/afterArray but no element callbacks + t |> equal(find(walker.log, "beforeArray") != -1, true) + t |> equal(find(walker.log, "afterArray") != -1, true) + t |> equal(find(walker.log, "canVisitArrayData:3") != -1, true) + t |> equal(find(walker.log, "Int:") == -1, true) + unsafe { delete walker; } + } +} + + +[test] +def test_can_visit_table_data(t : T?) { + t |> run("skip table data entries") @(t : T?) { + var walker = new SkipTableDataWalker() + var tab : table + tab |> insert("a", 1) + tab |> insert("b", 2) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(tab), typeinfo rtti_typeinfo(tab)) + } + t |> equal(find(walker.log, "beforeTable") != -1, true) + t |> equal(find(walker.log, "afterTable") != -1, true) + // No keys or values should be walked + t |> equal(find(walker.log, "String:") == -1, true) + t |> equal(find(walker.log, "Int:") == -1, true) + unsafe { delete walker; } + } +} + + +[test] +def test_can_visit_pointer(t : T?) { + t |> run("skip pointer dereference") @(t : T?) { + var walker = new SkipPointerWalker() + var s = SimpleStruct(x = 99, y = 1.0) + var p : SimpleStruct? = unsafe(addr(s)) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(p), typeinfo rtti_typeinfo(p)) + } + // Should NOT walk through the pointer + t |> equal(walker.log, "") + unsafe { delete walker; } + } +} + + +[test] +def test_selective_struct_visit(t : T?) { + t |> run("skip inner struct only") @(t : T?) { + var walker = new SelectiveStructWalker() + walker.skip_name = "SimpleStruct" + var s = NestedStruct(inner = SimpleStruct(x = 1, y = 2.0), tag = "outer") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + // Should visit NestedStruct but skip SimpleStruct + t |> equal(find(walker.log, "visit:NestedStruct") != -1, true) + t |> equal(find(walker.log, "visit:SimpleStruct") == -1, true) + // tag field (string) should still be walked since it belongs to NestedStruct + t |> equal(find(walker.log, "String:outer") != -1, true) + // inner struct's fields should NOT appear + t |> equal(find(walker.log, "Int:1") == -1, true) + t |> equal(find(walker.log, "Float:2") == -1, true) + unsafe { delete walker; } + } +} diff --git a/tests/data_walker/test_walk_mutation.das b/tests/data_walker/test_walk_mutation.das new file mode 100644 index 0000000000..016cd2dd22 --- /dev/null +++ b/tests/data_walker/test_walk_mutation.das @@ -0,0 +1,100 @@ +// Tests for DapiDataWalker — in-place mutation via walker callbacks +// +// Covers: mutate scalars, mutate struct fields, mutate array elements, +// mutate strings in nested structs and arrays + +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dw_common + + +// ============================================================ +// Local walker classes for mutation tests +// ============================================================ + +// Doubles every int and float encountered +class Doubler : DapiDataWalker { + def override Int(var value : int&) : void { + value *= 2 + } + def override Float(var value : float&) : void { + value *= 2.0 + } +} + +// Converts all strings to upper case +class StringUpperWalker : DapiDataWalker { + def override String(var value : string&) : void { + value = to_upper(value) + } +} + + +// ============================================================ +// Tests +// ============================================================ + +[test] +def test_mutation(t : T?) { + t |> run("mutate scalar int") @(t : T?) { + var walker = new Doubler() + var x = 21 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(x, 42) + unsafe { delete walker; } + } + t |> run("mutate struct fields") @(t : T?) { + var walker = new Doubler() + var s = SimpleStruct(x = 5, y = 1.5) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + t |> equal(s.x, 10) + t |> equal(s.y, 3.0) + unsafe { delete walker; } + } + t |> run("mutate array elements") @(t : T?) { + var walker = new Doubler() + var arr = [1, 2, 3] + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + t |> equal(arr[0], 2) + t |> equal(arr[1], 4) + t |> equal(arr[2], 6) + unsafe { delete walker; } + } +} + + +[test] +def test_mutate_nested(t : T?) { + t |> run("mutate strings in struct") @(t : T?) { + var walker = new StringUpperWalker() + var s = NestedStruct(inner = SimpleStruct(x = 1, y = 2.0), tag = "hello") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + t |> equal(s.tag, "HELLO") + unsafe { delete walker; } + } + t |> run("mutate strings in array") @(t : T?) { + var walker = new StringUpperWalker() + var arr = ["abc", "def"] + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(arr), typeinfo rtti_typeinfo(arr)) + } + t |> equal(arr[0], "ABC") + t |> equal(arr[1], "DEF") + unsafe { delete walker; } + } +} diff --git a/tests/data_walker/test_walk_scalars.das b/tests/data_walker/test_walk_scalars.das new file mode 100644 index 0000000000..de4430df98 --- /dev/null +++ b/tests/data_walker/test_walk_scalars.das @@ -0,0 +1,216 @@ +// Tests for DapiDataWalker — scalar types +// +// Covers: int, uint, int64, uint64, int8, uint8, int16, uint16, +// float, double, bool, string, enum, bitfield + +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dw_common + + +[test] +def test_walk_int(t : T?) { + t |> run("int") @(t : T?) { + var walker = new LogWalker() + var x = 42 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int:42\n") + unsafe { delete walker; } + } + t |> run("uint") @(t : T?) { + var walker = new LogWalker() + var x = 0xFF_u + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "UInt:0xff\n") + unsafe { delete walker; } + } + t |> run("int64") @(t : T?) { + var walker = new LogWalker() + var x = 100_000_000_000l + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int64:100000000000\n") + unsafe { delete walker; } + } + t |> run("uint64") @(t : T?) { + var walker = new LogWalker() + var x = 99ul + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "UInt64:0x63\n") + unsafe { delete walker; } + } + t |> run("int8") @(t : T?) { + var walker = new LogWalker() + var x = int8(127) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int8:127\n") + unsafe { delete walker; } + } + t |> run("uint8") @(t : T?) { + var walker = new LogWalker() + var x = uint8(200) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "UInt8:200\n") + unsafe { delete walker; } + } + t |> run("int16") @(t : T?) { + var walker = new LogWalker() + var x = int16(-1000) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Int16:-1000\n") + unsafe { delete walker; } + } + t |> run("uint16") @(t : T?) { + var walker = new LogWalker() + var x = uint16(60000) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "UInt16:60000\n") + unsafe { delete walker; } + } +} + + +[test] +def test_walk_float_double(t : T?) { + t |> run("float") @(t : T?) { + var walker = new LogWalker() + var x = 3.14 + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Float:3.14\n") + unsafe { delete walker; } + } + t |> run("double") @(t : T?) { + var walker = new LogWalker() + var x = 2.718281828lf + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Double:2.718281828\n") + unsafe { delete walker; } + } +} + + +[test] +def test_walk_bool_string(t : T?) { + t |> run("bool true") @(t : T?) { + var walker = new LogWalker() + var x = true + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Bool:true\n") + unsafe { delete walker; } + } + t |> run("bool false") @(t : T?) { + var walker = new LogWalker() + var x = false + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "Bool:false\n") + unsafe { delete walker; } + } + t |> run("string") @(t : T?) { + var walker = new LogWalker() + var x = "hello world" + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "String:hello world\n") + unsafe { delete walker; } + } + t |> run("empty string") @(t : T?) { + var walker = new LogWalker() + var x = "" + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + t |> equal(walker.log, "String:\n") + unsafe { delete walker; } + } +} + + +[test] +def test_walk_enum(t : T?) { + t |> run("enum value") @(t : T?) { + var walker = new LogWalker() + var c : Color = Color.Green + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(c), typeinfo rtti_typeinfo(c)) + } + t |> equal(walker.log, "Enum:Color:1\n") + unsafe { delete walker; } + } + t |> run("first enum value") @(t : T?) { + var walker = new LogWalker() + var c : Color = Color.Red + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(c), typeinfo rtti_typeinfo(c)) + } + t |> equal(walker.log, "Enum:Color:0\n") + unsafe { delete walker; } + } +} + + +[test] +def test_walk_bitfield(t : T?) { + t |> run("bitfield with flags set") @(t : T?) { + var walker = new LogWalker() + var p : Permissions = Permissions.read | Permissions.execute + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(p), typeinfo rtti_typeinfo(p)) + } + // read=bit0 (1), execute=bit2 (4) → 5 = 0x5 + t |> equal(walker.log, "Bitfield:0x5\n") + unsafe { delete walker; } + } + t |> run("empty bitfield") @(t : T?) { + var walker = new LogWalker() + var p : Permissions + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(p), typeinfo rtti_typeinfo(p)) + } + t |> equal(walker.log, "Bitfield:0x0\n") + unsafe { delete walker; } + } +} diff --git a/tests/data_walker/test_walk_structs.das b/tests/data_walker/test_walk_structs.das new file mode 100644 index 0000000000..6fd2579cb9 --- /dev/null +++ b/tests/data_walker/test_walk_structs.das @@ -0,0 +1,155 @@ +// Tests for DapiDataWalker — structures and classes +// +// Covers: simple struct, nested struct, field last flags, class/derived class, +// struct with all scalar types, struct with vectors and ranges + +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dw_common + + +[test] +def test_walk_struct(t : T?) { + t |> run("simple struct") @(t : T?) { + var walker = new LogWalker() + var s = SimpleStruct(x = 10, y = 2.5) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + var expected = "beforeStruct:SimpleStruct\n" + expected += "beforeField:x:false\n" + expected += "Int:10\n" + expected += "afterField:x:false\n" + expected += "beforeField:y:true\n" + expected += "Float:2.5\n" + expected += "afterField:y:true\n" + expected += "afterStruct:SimpleStruct\n" + t |> equal(walker.log, expected) + unsafe { delete walker; } + } + t |> run("nested struct") @(t : T?) { + var walker = new LogWalker() + var s = NestedStruct(inner = SimpleStruct(x = 1, y = 2.0), tag = "test") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + // Should see: NestedStruct → inner(SimpleStruct → x, y) → tag + t |> equal(find(walker.log, "beforeStruct:NestedStruct") != -1, true) + t |> equal(find(walker.log, "beforeStruct:SimpleStruct") != -1, true) + t |> equal(find(walker.log, "Int:1") != -1, true) + t |> equal(find(walker.log, "Float:2") != -1, true) + t |> equal(find(walker.log, "String:test") != -1, true) + unsafe { delete walker; } + } + t |> run("field last flags") @(t : T?) { + // ManyFields has 4 fields — only the last should have last=true + var walker = new LogWalker() + var s = ManyFields(a = 1, b = 2, c = 3, d = 4) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + t |> equal(find(walker.log, "beforeField:a:false") != -1, true) + t |> equal(find(walker.log, "beforeField:b:false") != -1, true) + t |> equal(find(walker.log, "beforeField:c:false") != -1, true) + t |> equal(find(walker.log, "beforeField:d:true") != -1, true) + unsafe { delete walker; } + } +} + + +[test] +def test_walk_class(t : T?) { + t |> run("base class") @(t : T?) { + var walker = new LogWalker() + var a = new Animal(name = "cat") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(a), typeinfo rtti_typeinfo(a)) + } + // Walking a class pointer: beforePtr → beforeStruct:Animal → field:name → afterStruct → afterPtr + t |> equal(find(walker.log, "beforeStruct:Animal") != -1, true) + t |> equal(find(walker.log, "String:cat") != -1, true) + unsafe { delete a; delete walker; } + } + t |> run("derived class") @(t : T?) { + var walker = new LogWalker() + var d = new Dog(name = "Rex", breed = "Shepherd") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(d), typeinfo rtti_typeinfo(d)) + } + // Derived class should walk Dog fields including breed + t |> equal(find(walker.log, "beforeStruct:Dog") != -1, true) + t |> equal(find(walker.log, "String:Rex") != -1, true) + t |> equal(find(walker.log, "String:Shepherd") != -1, true) + unsafe { delete d; delete walker; } + } +} + + +[test] +def test_walk_all_scalars_in_struct(t : T?) { + t |> run("struct with all scalar types") @(t : T?) { + var walker = new LogWalker() + var s = AllScalars( + b = true, + i = 42, + u = 0xFFu, + f = 3.14, + d = 2.718lf, + s = "test", + i8 = int8(8), + u8 = uint8(16), + i16 = int16(256), + u16 = uint16(512), + i64 = 100l, + u64 = 200ul + ) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + // Verify all scalar callbacks fired + t |> equal(find(walker.log, "Bool:true") != -1, true) + t |> equal(find(walker.log, "Int:42") != -1, true) + t |> equal(find(walker.log, "UInt:0xff") != -1, true) + t |> equal(find(walker.log, "Float:3.14") != -1, true) + t |> equal(find(walker.log, "Double:2.718") != -1, true) + t |> equal(find(walker.log, "String:test") != -1, true) + t |> equal(find(walker.log, "Int8:8") != -1, true) + t |> equal(find(walker.log, "UInt8:16") != -1, true) + t |> equal(find(walker.log, "Int16:256") != -1, true) + t |> equal(find(walker.log, "UInt16:512") != -1, true) + t |> equal(find(walker.log, "Int64:100") != -1, true) + t |> equal(find(walker.log, "UInt64:") != -1, true) + unsafe { delete walker; } + } +} + + +[test] +def test_walk_vectors_in_struct(t : T?) { + t |> run("struct with vectors and range") @(t : T?) { + var walker = new LogWalker() + var s = VectorRangeStruct( + v2 = float2(1.0, 2.0), + v3 = float3(3.0, 4.0, 5.0), + v4 = float4(6.0, 7.0, 8.0, 9.0), + r = range(10, 20) + ) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + t |> equal(find(walker.log, "Float2:") != -1, true) + t |> equal(find(walker.log, "Float3:") != -1, true) + t |> equal(find(walker.log, "Float4:") != -1, true) + t |> equal(find(walker.log, "Range:") != -1, true) + unsafe { delete walker; } + } +} diff --git a/tests/data_walker/test_walk_tuples_variants.das b/tests/data_walker/test_walk_tuples_variants.das new file mode 100644 index 0000000000..a6dbe8e5f7 --- /dev/null +++ b/tests/data_walker/test_walk_tuples_variants.das @@ -0,0 +1,88 @@ +// Tests for DapiDataWalker — tuples and variants +// +// Covers: tuple (2-element, 3-element), variant (int/string/float alternatives) + +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dw_common + + +[test] +def test_walk_tuple(t : T?) { + t |> run("int-string tuple") @(t : T?) { + var walker = new LogWalker() + var tup : tuple = (42, "hello") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(tup), typeinfo rtti_typeinfo(tup)) + } + var expected = "beforeTuple\n" + expected += "beforeTupleEntry:0:false\n" + expected += "Int:42\n" + expected += "afterTupleEntry:0:false\n" + expected += "beforeTupleEntry:1:true\n" + expected += "String:hello\n" + expected += "afterTupleEntry:1:true\n" + expected += "afterTuple\n" + t |> equal(walker.log, expected) + unsafe { delete walker; } + } + t |> run("3-element tuple") @(t : T?) { + var walker = new LogWalker() + var tup : tuple = (1, 2.0, true) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(tup), typeinfo rtti_typeinfo(tup)) + } + // Middle element should not be last + t |> equal(find(walker.log, "beforeTupleEntry:1:false") != -1, true) + // Last element should be last + t |> equal(find(walker.log, "beforeTupleEntry:2:true") != -1, true) + unsafe { delete walker; } + } +} + + +[test] +def test_walk_variant(t : T?) { + t |> run("variant int alternative") @(t : T?) { + var walker = new LogWalker() + var v : MyVariant = MyVariant(i = 42) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(find(walker.log, "beforeVariant") != -1, true) + t |> equal(find(walker.log, "Int:42") != -1, true) + t |> equal(find(walker.log, "afterVariant") != -1, true) + // Should NOT contain String or Float callbacks + t |> equal(find(walker.log, "String:") == -1, true) + t |> equal(find(walker.log, "Float:") == -1, true) + unsafe { delete walker; } + } + t |> run("variant string alternative") @(t : T?) { + var walker = new LogWalker() + var v : MyVariant = MyVariant(s = "hello") + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(find(walker.log, "beforeVariant") != -1, true) + t |> equal(find(walker.log, "String:hello") != -1, true) + t |> equal(find(walker.log, "afterVariant") != -1, true) + t |> equal(find(walker.log, "Int:") == -1, true) + unsafe { delete walker; } + } + t |> run("variant float alternative") @(t : T?) { + var walker = new LogWalker() + var v : MyVariant = MyVariant(f = 9.5) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(find(walker.log, "Float:9.5") != -1, true) + unsafe { delete walker; } + } +} diff --git a/tests/data_walker/test_walk_vectors_ranges.das b/tests/data_walker/test_walk_vectors_ranges.das new file mode 100644 index 0000000000..563f5b876a --- /dev/null +++ b/tests/data_walker/test_walk_vectors_ranges.das @@ -0,0 +1,149 @@ +// Tests for DapiDataWalker — vector and range types +// +// Covers: int2/3/4, uint2/3/4, float2/3/4, range, urange, range64, urange64 + +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dw_common + + +[test] +def test_walk_vectors(t : T?) { + t |> run("int2") @(t : T?) { + var walker = new LogWalker() + var v = int2(10, 20) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "Int2:{v}\n") + unsafe { delete walker; } + } + t |> run("int3") @(t : T?) { + var walker = new LogWalker() + var v = int3(1, 2, 3) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "Int3:{v}\n") + unsafe { delete walker; } + } + t |> run("int4") @(t : T?) { + var walker = new LogWalker() + var v = int4(1, 2, 3, 4) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "Int4:{v}\n") + unsafe { delete walker; } + } + t |> run("float2") @(t : T?) { + var walker = new LogWalker() + var v = float2(1.5, 2.5) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "Float2:{v}\n") + unsafe { delete walker; } + } + t |> run("float3") @(t : T?) { + var walker = new LogWalker() + var v = float3(1.0, 2.0, 3.0) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "Float3:{v}\n") + unsafe { delete walker; } + } + t |> run("float4") @(t : T?) { + var walker = new LogWalker() + var v = float4(1.0, 2.0, 3.0, 4.0) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "Float4:{v}\n") + unsafe { delete walker; } + } + t |> run("uint2") @(t : T?) { + var walker = new LogWalker() + var v = uint2(1u, 2u) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "UInt2:{v}\n") + unsafe { delete walker; } + } + t |> run("uint3") @(t : T?) { + var walker = new LogWalker() + var v = uint3(1u, 2u, 3u) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "UInt3:{v}\n") + unsafe { delete walker; } + } + t |> run("uint4") @(t : T?) { + var walker = new LogWalker() + var v = uint4(1u, 2u, 3u, 4u) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(v), typeinfo rtti_typeinfo(v)) + } + t |> equal(walker.log, "UInt4:{v}\n") + unsafe { delete walker; } + } +} + + +[test] +def test_walk_ranges(t : T?) { + t |> run("range") @(t : T?) { + var walker = new LogWalker() + var r = range(0, 10) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(r), typeinfo rtti_typeinfo(r)) + } + t |> equal(walker.log, "Range:{r}\n") + unsafe { delete walker; } + } + t |> run("urange") @(t : T?) { + var walker = new LogWalker() + var r = urange(5u, 15u) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(r), typeinfo rtti_typeinfo(r)) + } + t |> equal(walker.log, "URange:{r}\n") + unsafe { delete walker; } + } + t |> run("range64") @(t : T?) { + var walker = new LogWalker() + var r = range64(0l, 100l) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(r), typeinfo rtti_typeinfo(r)) + } + t |> equal(walker.log, "Range64:{r}\n") + unsafe { delete walker; } + } + t |> run("urange64") @(t : T?) { + var walker = new LogWalker() + var r = urange64(10ul, 20ul) + var inscope adapter <- make_data_walker(walker) + unsafe { + adapter |> walk_data(addr(r), typeinfo rtti_typeinfo(r)) + } + t |> equal(walker.log, "URange64:{r}\n") + unsafe { delete walker; } + } +} diff --git a/tests/language/properties.das b/tests/language/properties.das new file mode 100644 index 0000000000..cd6ecc6b64 --- /dev/null +++ b/tests/language/properties.das @@ -0,0 +1,73 @@ +options gen2 +options no_unused_function_arguments = false +require dastest/testing_boost public + +// Custom property operator: `.res :=` dispatches to a setter +struct Foo { + resz : string +} + +def operator . res :=(var f : Foo; st : string#) { + f.resz := st +} + +// Class with getter/setter property pair +class sealed UIFrame { + _size : float2 + def const operator . sizezz() : float2 { + return _size + } + def operator . sizezz :=(value : float2) { + _size = value + } +} + +[test] +def test_property_clone_assign(t : T?) { + t |> run("clone-assign string via block") @(t : T?) { + var res : string + unsafe { + res := reinterpret "foo" + } + t |> equal(res, "foo") + } + t |> run("clone-assign to struct field directly") @(t : T?) { + var f : Foo + unsafe { + f.resz := reinterpret "bar" + } + t |> equal(f.resz, "bar") + } + t |> run("clone-assign via property operator") @(t : T?) { + var f : Foo + unsafe { + f.res := reinterpret "baz" + } + t |> equal(f.resz, "baz") + } +} + +[test] +def test_class_property_operators(t : T?) { + t |> run("setter assigns value") @(t : T?) { + var frame = new UIFrame() + frame.sizezz := float2(100.0, 200.0) + t |> equal(frame.sizezz, float2(100.0, 200.0)) + unsafe { delete frame; } + } + t |> run("getter returns current value") @(t : T?) { + var frame = new UIFrame() + frame.sizezz := float2(3.0, 4.0) + let sz = frame.sizezz + t |> equal(sz.x, 3.0) + t |> equal(sz.y, 4.0) + unsafe { delete frame; } + } + t |> run("multiple assignments overwrite") @(t : T?) { + var frame = new UIFrame() + frame.sizezz := float2(1.0, 1.0) + frame.sizezz := float2(5.0, 6.0) + t |> equal(frame.sizezz, float2(5.0, 6.0)) + unsafe { delete frame; } + } +} diff --git a/tests/language/typeinfo_traits.das b/tests/language/typeinfo_traits.das new file mode 100644 index 0000000000..6f29f54594 --- /dev/null +++ b/tests/language/typeinfo_traits.das @@ -0,0 +1,93 @@ +options gen2 +options no_unused_function_arguments = false +require dastest/testing_boost public +require rtti +require ast + +// Test typeinfo trait queries on various types + +struct SimpleStruct { + x : int + y : float +} + +class SimpleClass { + value : int +} + +[test] +def test_typeinfo_traits_value_types(t : T?) { + t |> run("int is local") @(t : T?) { + t |> equal(typeinfo is_local(type), true) + } + t |> run("int can copy") @(t : T?) { + t |> equal(typeinfo can_copy(type), true) + } + t |> run("int can be placed in container") @(t : T?) { + t |> equal(typeinfo can_be_placed_in_container(type), true) + } + t |> run("float3 is local") @(t : T?) { + t |> equal(typeinfo is_local(type), true) + } + t |> run("string can copy") @(t : T?) { + t |> equal(typeinfo can_copy(type), true) + } + t |> run("string can clone") @(t : T?) { + t |> equal(typeinfo can_clone(type), true) + } +} + +[test] +def test_typeinfo_traits_structs(t : T?) { + t |> run("struct is local") @(t : T?) { + t |> equal(typeinfo is_local(type), true) + } + t |> run("struct can copy") @(t : T?) { + t |> equal(typeinfo can_copy(type), true) + } + t |> run("struct can move") @(t : T?) { + t |> equal(typeinfo can_move(type), true) + } + t |> run("struct can new") @(t : T?) { + t |> equal(typeinfo can_new(type), true) + } + t |> run("struct has no nontrivial ctor") @(t : T?) { + t |> equal(typeinfo has_nontrivial_ctor(type), false) + } + t |> run("struct has no nontrivial dtor") @(t : T?) { + t |> equal(typeinfo has_nontrivial_dtor(type), false) + } +} + +[test] +def test_typeinfo_traits_handled_types(t : T?) { + // FileAccess is a C++ handled type from the ast module + t |> run("FileAccess? is local") @(t : T?) { + t |> equal(typeinfo is_local(type), true) + } + t |> run("FileAccess? can copy") @(t : T?) { + t |> equal(typeinfo can_copy(type), true) + } + t |> run("FileAccess? can move") @(t : T?) { + t |> equal(typeinfo can_move(type), true) + } + t |> run("FileAccess? cannot delete ptr") @(t : T?) { + t |> equal(typeinfo can_delete_ptr(type), false) + } +} + +[test] +def test_typeinfo_traits_containers(t : T?) { + t |> run("array is local") @(t : T?) { + t |> equal(typeinfo is_local(type>), true) + } + t |> run("array can move") @(t : T?) { + t |> equal(typeinfo can_move(type>), true) + } + t |> run("array can clone") @(t : T?) { + t |> equal(typeinfo can_clone(type>), true) + } + t |> run("table can move") @(t : T?) { + t |> equal(typeinfo can_move(type>), true) + } +} diff --git a/tests/safe_addr/test_shared_addr.das b/tests/safe_addr/test_shared_addr.das new file mode 100644 index 0000000000..8d19934a47 --- /dev/null +++ b/tests/safe_addr/test_shared_addr.das @@ -0,0 +1,39 @@ +options gen2 +options no_unused_function_arguments = false +options no_unused_block_arguments = false + +require dastest/testing_boost public +require daslib/safe_addr + +// shared global scalar +let shared MAGIC = 42 + +// shared global array +let shared NAMES <- ["alpha", "beta", "gamma"] + +[test] +def test_shared_addr_scalar(t : T?) { + t |> run("address of shared int") @(tt : T?) { + let p = shared_addr(MAGIC) + tt |> equal(*p, 42) + } +} + +[test] +def test_shared_addr_array(t : T?) { + t |> run("address of shared array") @(tt : T?) { + let p = shared_addr(NAMES) + tt |> equal((*p)[0], "alpha") + tt |> equal((*p)[1], "beta") + tt |> equal((*p)[2], "gamma") + } + t |> run("iterate shared values") @(tt : T?) { + var count = 0 + for (name in NAMES) { + let pn = shared_addr(name) + tt |> equal(empty(*pn), false) + count++ + } + tt |> equal(count, 3) + } +} diff --git a/tests/verify/test_verify_completion.das b/tests/verify/test_verify_completion.das new file mode 100644 index 0000000000..6e8816be4b --- /dev/null +++ b/tests/verify/test_verify_completion.das @@ -0,0 +1,55 @@ +options gen2 +expect 40104:8 + +// Verify that [verify_completion] rejects unbounded loops and recursive calls. + +require daslib/validate_code + +[export, verify_completion] +def bad_loop(var all : iterator; cond_const : bool) { + for (t in all) { // 40104: unbounded iterator loop + print("t = {t}\n") + } + for (t, r in all, range(100500)) { // ok — has explicit range + print("t = {t}\n") + } + var cond = true + while (cond) { // 40104: unbounded while loop + print("nop\n") + cond = false + } + var tab <- {1 => 1, 2 => 2, 3 => 3} + for (x in tab |> keys()) { // 40104: keys() is unbounded + print("x = {x}\n") + } +} + +[export, verify_completion] +def simple_recursive() { + print("simple\n") + simple_recursive() // 40104: direct recursion +} + +def rec_a() { + print("a\n") + rec_b() // 40104: mutual recursion a->b->a +} + +def rec_b() { + print("b\n") + rec_a() // 40104: mutual recursion b->a->b +} + +def rec_c() { + rec_a() // 40104: transitive recursion +} + +[export, verify_completion] +def rec_d() { + rec_c() // 40104: transitive recursion c->a->b->a +} + +[export] +def main() { + pass +} diff --git a/tutorials/language/47_data_walker.das b/tutorials/language/47_data_walker.das new file mode 100644 index 0000000000..126fc372f0 --- /dev/null +++ b/tutorials/language/47_data_walker.das @@ -0,0 +1,817 @@ +// Tutorial 47: Data Walking with DapiDataWalker +// +// This tutorial covers: +// - Subclassing DapiDataWalker to inspect daScript values at runtime +// - Walking scalar types (int, float, string, bool) +// - Walking structures with field names via StructInfo/VarInfo +// - Walking arrays, tables, tuples, and variants +// - Walking enumerations and bitfields +// - Building a JSON serializer as a practical example +// - Filtering traversal with canVisit methods +// - Mutating data in-place through walker callbacks +// +// Prerequisites: None (basic daScript knowledge only) +// +// Key concepts: +// - DapiDataWalker is a visitor pattern for daScript data at runtime +// - Override scalar callbacks (Int, Float, String, ...) to handle values +// - Override before/after callbacks for containers (structures, arrays, etc.) +// - All canVisit methods default to true — override to prune traversal +// - Scalar callbacks receive mutable references — values can be modified +// - walk_data takes a smart_ptr adapter, a data pointer, and TypeInfo +// +// Run: daslang.exe tutorials/language/47_data_walker.das + +options gen2 +options rtti + +require rtti +require debugapi +require daslib/strings_boost + + +// ============================================================ +// Section 1: Minimal walker — scalar types +// ============================================================ +// +// A DapiDataWalker subclass overrides only the callbacks you care +// about. All methods default to no-op, so a minimal walker that +// just prints integers and floats is very small. + +class ScalarPrinter : DapiDataWalker { + def override Int(var value : int&) : void { + print(" int: {value}\n") + } + def override Float(var value : float&) : void { + print(" float: {value}\n") + } + def override String(var value : string&) : void { + print(" string: \"{value}\"\n") + } + def override Bool(var value : bool&) : void { + print(" bool: {value}\n") + } +} + +def demo_scalar_types() { + print("\n=== Section 1: Scalar types ===\n") + + // Step 1: create the walker and its adapter + var walker = new ScalarPrinter() + var inscope adapter <- make_data_walker(walker) + + // Step 2: walk various scalar values + // typeinfo rtti_typeinfo(var) returns the TypeInfo for any variable + var x = 42 + print("Walking int 42:\n") + unsafe { + adapter |> walk_data(addr(x), typeinfo rtti_typeinfo(x)) + } + + var f = 3.14 + print("Walking float 3.14:\n") + unsafe { + adapter |> walk_data(addr(f), typeinfo rtti_typeinfo(f)) + } + + var s = "hello" + print("Walking string \"hello\":\n") + unsafe { + adapter |> walk_data(addr(s), typeinfo rtti_typeinfo(s)) + } + + var b = true + print("Walking bool true:\n") + unsafe { + adapter |> walk_data(addr(b), typeinfo rtti_typeinfo(b)) + } + + unsafe { + delete walker + } +} + + +// ============================================================ +// Section 2: Structures +// ============================================================ +// +// The walker calls beforeStructure/afterStructure around the whole +// struct, and beforeStructureField/afterStructureField around each +// field. StructInfo.name gives the struct type name, VarInfo.name +// gives the field name. + +struct Vec3 { + x : float + y : float + z : float +} + +struct Player { + name : string + health : int + pos : Vec3 +} + +class StructPrinter : DapiDataWalker { + indent : int = 0 + + def pad() { + for (_ in range(indent)) { + print(" ") + } + } + + def override beforeStructure(ps : void?; si : StructInfo) : void { + print("{si.name} \{\n") + indent++ + } + + def override afterStructure(ps : void?; si : StructInfo) : void { + indent-- + self->pad() + print("\}\n") + } + + def override beforeStructureField(ps : void?; si : StructInfo; pv : void?; vi : VarInfo; last : bool) : void { + self->pad() + print("{vi.name} = ") + } + + def override afterStructureField(ps : void?; si : StructInfo; pv : void?; vi : VarInfo; last : bool) : void { + pass + } + + def override Int(var value : int&) : void { + print("{value}\n") + } + + def override Float(var value : float&) : void { + print("{value}\n") + } + + def override String(var value : string&) : void { + print("\"{value}\"\n") + } +} + +def demo_structures() { + print("\n=== Section 2: Structures ===\n") + + var walker = new StructPrinter() + var inscope adapter <- make_data_walker(walker) + + var player = Player(name = "Alice", health = 100, pos = Vec3(x = 1.0, y = 2.5, z = -3.0)) + print("Walking Player:\n") + unsafe { + adapter |> walk_data(addr(player), typeinfo rtti_typeinfo(player)) + } + + unsafe { + delete walker + } +} + + +// ============================================================ +// Section 3: Arrays and tables +// ============================================================ +// +// Dynamic arrays trigger beforeArray/afterArray plus the element +// callbacks. Fixed-size arrays (dim) trigger beforeDim/afterDim. +// Tables trigger beforeTable/afterTable with key/value pairs. + +class ContainerPrinter : DapiDataWalker { + indent : int = 0 + + def pad() { + for (_ in range(indent)) { + print(" ") + } + } + + // --- arrays --- + def override beforeArrayData(ps : void?; stride : uint; count : uint; ti : TypeInfo) : void { + self->pad() + print("array[{int(count)}] = [\n") + indent++ + } + + def override afterArrayData(ps : void?; stride : uint; count : uint; ti : TypeInfo) : void { + indent-- + self->pad() + print("]\n") + } + + def override beforeArrayElement(ps : void?; ti : TypeInfo; pe : void?; index : uint; last : bool) : void { + self->pad() + print("[{int(index)}] = ") + } + + def override afterArrayElement(ps : void?; ti : TypeInfo; pe : void?; index : uint; last : bool) : void { + print("\n") + } + + // --- tables --- + def override beforeTable(pa : DapiTable; ti : TypeInfo) : void { + self->pad() + print("table[{int(pa.size)}] = \{\n") + indent++ + } + + def override afterTable(pa : DapiTable; ti : TypeInfo) : void { + indent-- + self->pad() + print("\}\n") + } + + def override beforeTableKey(pa : DapiTable; ti : TypeInfo; pk : void?; ki : TypeInfo; index : uint; last : bool) : void { + self->pad() + } + + def override afterTableKey(pa : DapiTable; ti : TypeInfo; pk : void?; ki : TypeInfo; index : uint; last : bool) : void { + print(" => ") + } + + def override afterTableValue(pa : DapiTable; ti : TypeInfo; pv : void?; kv : TypeInfo; index : uint; last : bool) : void { + print("\n") + } + + // --- scalars --- + def override Int(var value : int&) : void { + print("{value}") + } + + def override Float(var value : float&) : void { + print("{value}") + } + + def override String(var value : string&) : void { + print("\"{value}\"") + } +} + +def demo_arrays_and_tables() { + print("\n=== Section 3: Arrays and tables ===\n") + + var walker = new ContainerPrinter() + var inscope adapter <- make_data_walker(walker) + + var nums = [10, 20, 30, 40, 50] + print("Walking array:\n") + unsafe { + adapter |> walk_data(addr(nums), typeinfo rtti_typeinfo(nums)) + } + + var scores : table + scores |> insert("Alice", 95) + scores |> insert("Bob", 87) + scores |> insert("Charlie", 72) + print("\nWalking table:\n") + unsafe { + adapter |> walk_data(addr(scores), typeinfo rtti_typeinfo(scores)) + } + + unsafe { + delete walker + } +} + + +// ============================================================ +// Section 4: Tuples and variants +// ============================================================ +// +// Tuples walk each element by index. Variants walk only the +// active alternative — you see which variant is active from te +// TypeInfo passed to beforeVariant/afterVariant. + +typedef Result = variant + +class TupleVariantPrinter : DapiDataWalker { + indent : int = 0 + + def pad() { + for (_ in range(indent)) { + print(" ") + } + } + + def override beforeTuple(ps : void?; ti : TypeInfo) : void { + self->pad() + print("tuple(\n") + indent++ + } + + def override afterTuple(ps : void?; ti : TypeInfo) : void { + indent-- + self->pad() + print(")\n") + } + + def override beforeTupleEntry(ps : void?; ti : TypeInfo; pv : void?; idx : int; last : bool) : void { + self->pad() + print("_{idx} = ") + } + + def override afterTupleEntry(ps : void?; ti : TypeInfo; pv : void?; idx : int; last : bool) : void { + print("\n") + } + + def override beforeVariant(ps : void?; ti : TypeInfo) : void { + self->pad() + print("variant = ") + } + + def override afterVariant(ps : void?; ti : TypeInfo) : void { + print("\n") + } + + def override Int(var value : int&) : void { + print("{value}") + } + + def override Float(var value : float&) : void { + print("{value}") + } + + def override String(var value : string&) : void { + print("\"{value}\"") + } +} + +def demo_tuples_and_variants() { + print("\n=== Section 4: Tuples and variants ===\n") + + var walker = new TupleVariantPrinter() + var inscope adapter <- make_data_walker(walker) + + var t = ("hello", 42, 3.14) + print("Walking tuple:\n") + unsafe { + adapter |> walk_data(addr(t), typeinfo rtti_typeinfo(t)) + } + + var ok_result = Result(ok = 42) + print("\nWalking variant (ok=42):\n") + unsafe { + adapter |> walk_data(addr(ok_result), typeinfo rtti_typeinfo(ok_result)) + } + + var err_result = Result(err = "not found") + print("\nWalking variant (err=\"not found\"):\n") + unsafe { + adapter |> walk_data(addr(err_result), typeinfo rtti_typeinfo(err_result)) + } + + unsafe { + delete walker + } +} + + +// ============================================================ +// Section 5: Enumerations and bitfields +// ============================================================ +// +// Enumerations trigger WalkEnumeration with an EnumInfo that +// contains value names. Bitfields trigger the Bitfield callback +// with a TypeInfo that contains field names. + +enum Color { + Red + Green + Blue +} + +bitfield Permissions { + readable + writable + executable +} + +class EnumBitfieldPrinter : DapiDataWalker { + def override WalkEnumeration(var value : int&; ei : EnumInfo) : void { + // EnumInfo contains the enum name and value names + for (i in range(ei.count)) { + unsafe { + if (int(ei.fields[i].value) == value) { + print(" enum {ei.name}.{ei.fields[i].name} ({value})\n") + return + } + } + } + print(" enum {ei.name} = {value}\n") + } + + def override Bitfield(var value : uint&; ti : TypeInfo) : void { + // TypeInfo.argNames contains the bit field names + print(" bitfield = {value} [") + var first = true + for (i in range(ti.argCount)) { + if ((value & (1u << uint(i))) != 0u) { + if (!first) { + print(", ") + } + first = false + unsafe { + print("{ti.argNames[i]}") + } + } + } + print("]\n") + } +} + +def demo_enums_and_bitfields() { + print("\n=== Section 5: Enumerations and bitfields ===\n") + + var walker = new EnumBitfieldPrinter() + var inscope adapter <- make_data_walker(walker) + + var color = Color.Green + print("Walking enum Color.Green:\n") + unsafe { + adapter |> walk_data(addr(color), typeinfo rtti_typeinfo(color)) + } + + var perms : Permissions = Permissions.readable | Permissions.executable + print("Walking bitfield (readable | executable):\n") + unsafe { + adapter |> walk_data(addr(perms), typeinfo rtti_typeinfo(perms)) + } + + unsafe { + delete walker + } +} + + +// ============================================================ +// Section 6: JSON serializer — putting it all together +// ============================================================ +// +// A practical DapiDataWalker that serializes any daScript value +// to a JSON string. This demonstrates combining all of the +// structure, array, table, tuple, and scalar callbacks into one +// coherent walker. + +struct Item { + name : string + weight : float +} + +struct Inventory { + owner : string + gold : int + items : array + flags : table +} + +class JsonWalker : DapiDataWalker { + // The walker writes directly to a StringBuilderWriter for efficiency. + // The writer is set externally by to_json() via build_string(). + @do_not_delete writer : StringBuilderWriter? + indent : int = 0 + needComma : array + + def comma() { + if (length(needComma) > 0 && needComma[length(needComma) - 1]) { + *writer |> write(",") + } + } + + def nl() { + *writer |> write("\n") + for (_ in range(indent)) { + *writer |> write(" ") + } + } + + def pushComma() { + needComma |> push(false) + } + + def popComma() { + needComma |> pop() + } + + def markComma() { + if (length(needComma) > 0) { + needComma[length(needComma) - 1] = true + } + } + + // --- structures --- + def override beforeStructure(ps : void?; si : StructInfo) : void { + *writer |> write("\{") + indent++ + pushComma() + } + + def override afterStructure(ps : void?; si : StructInfo) : void { + popComma() + indent-- + nl() + *writer |> write("\}") + markComma() + } + + def override beforeStructureField(ps : void?; si : StructInfo; pv : void?; vi : VarInfo; last : bool) : void { + comma() + nl() + *writer |> write("\"") + *writer |> write(vi.name) + *writer |> write("\": ") + } + + def override afterStructureField(ps : void?; si : StructInfo; pv : void?; vi : VarInfo; last : bool) : void { + markComma() + } + + // --- arrays --- + def override beforeArrayData(ps : void?; stride : uint; count : uint; ti : TypeInfo) : void { + *writer |> write("[") + indent++ + pushComma() + } + + def override afterArrayData(ps : void?; stride : uint; count : uint; ti : TypeInfo) : void { + popComma() + indent-- + nl() + *writer |> write("]") + markComma() + } + + def override beforeArrayElement(ps : void?; ti : TypeInfo; pe : void?; index : uint; last : bool) : void { + comma() + nl() + } + + def override afterArrayElement(ps : void?; ti : TypeInfo; pe : void?; index : uint; last : bool) : void { + markComma() + } + + // --- tables --- + def override beforeTable(pa : DapiTable; ti : TypeInfo) : void { + *writer |> write("\{") + indent++ + pushComma() + } + + def override afterTable(pa : DapiTable; ti : TypeInfo) : void { + popComma() + indent-- + nl() + *writer |> write("\}") + markComma() + } + + def override beforeTableKey(pa : DapiTable; ti : TypeInfo; pk : void?; ki : TypeInfo; index : uint; last : bool) : void { + comma() + nl() + } + + def override afterTableKey(pa : DapiTable; ti : TypeInfo; pk : void?; ki : TypeInfo; index : uint; last : bool) : void { + *writer |> write(": ") + } + + def override afterTableValue(pa : DapiTable; ti : TypeInfo; pv : void?; kv : TypeInfo; index : uint; last : bool) : void { + markComma() + } + + // --- tuples --- + def override beforeTuple(ps : void?; ti : TypeInfo) : void { + *writer |> write("[") + indent++ + pushComma() + } + + def override afterTuple(ps : void?; ti : TypeInfo) : void { + popComma() + indent-- + nl() + *writer |> write("]") + markComma() + } + + def override beforeTupleEntry(ps : void?; ti : TypeInfo; pv : void?; idx : int; last : bool) : void { + comma() + nl() + } + + def override afterTupleEntry(ps : void?; ti : TypeInfo; pv : void?; idx : int; last : bool) : void { + markComma() + } + + // --- scalars --- + def override Int(var value : int&) : void { + *writer |> write(value) + } + + def override Float(var value : float&) : void { + *writer |> write(value) + } + + def override String(var value : string&) : void { + *writer |> write("\"") + *writer |> write(value) + *writer |> write("\"") + } + + def override Bool(var value : bool&) : void { + *writer |> write(value ? "true" : "false") + } + + def override Null(ti : TypeInfo) : void { + *writer |> write("null") + } +} + +def to_json(var value; tinfo : TypeInfo) : string { + var walker = new JsonWalker() + var inscope adapter <- make_data_walker(walker) + let res = build_string() $(var writer) { + unsafe { + walker.writer = addr(writer) + adapter |> walk_data(addr(value), tinfo) + walker.writer = null + } + } + unsafe { + delete walker + } + return res +} + +def demo_json_serializer() { + print("\n=== Section 6: JSON serializer ===\n") + + var inv = Inventory( + owner = "Alice", + gold = 250, + items <- [Item(name = "Sword", weight = 3.5), Item(name = "Shield", weight = 5.2), Item(name = "Potion", weight = 0.5)], + flags <- { "is_merchant" => true, "is_hostile" => false } + ) + + let json = to_json(inv, typeinfo rtti_typeinfo(inv)) + print("{json}\n") +} + + +// ============================================================ +// Section 7: Filtering with canVisit +// ============================================================ +// +// All canVisit methods return true by default. Override them to +// return false and the walker skips that subtree entirely. + +struct Secret { + classified : string + code : int +} + +struct PublicRecord { + title : string + secret : Secret + score : int +} + +class FilteringWalker : DapiDataWalker { + indent : int = 0 + skipStructName : string + + def pad() { + for (_ in range(indent)) { + print(" ") + } + } + + def override canVisitStructure(ps : void?; si : StructInfo) : bool { + // Skip structs matching the filter name + if (si.name == skipStructName) { + print("\n") + return false + } + return true + } + + def override beforeStructure(ps : void?; si : StructInfo) : void { + print("{si.name} \{\n") + indent++ + } + + def override afterStructure(ps : void?; si : StructInfo) : void { + indent-- + self->pad() + print("\}\n") + } + + def override beforeStructureField(ps : void?; si : StructInfo; pv : void?; vi : VarInfo; last : bool) : void { + self->pad() + print("{vi.name} = ") + } + + def override afterStructureField(ps : void?; si : StructInfo; pv : void?; vi : VarInfo; last : bool) : void { + pass + } + + def override Int(var value : int&) : void { + print("{value}\n") + } + + def override String(var value : string&) : void { + print("\"{value}\"\n") + } +} + +def demo_filtering() { + print("\n=== Section 7: Filtering with canVisit ===\n") + + var walker = new FilteringWalker() + walker.skipStructName = "Secret" + var inscope adapter <- make_data_walker(walker) + + var record = PublicRecord( + title = "Performance Review", + secret = Secret(classified = "top-secret", code = 42), + score = 95 + ) + + print("Walking PublicRecord (Secret fields skipped):\n") + unsafe { + adapter |> walk_data(addr(record), typeinfo rtti_typeinfo(record)) + } + + unsafe { + delete walker + } +} + + +// ============================================================ +// Section 8: Mutating data in-place +// ============================================================ +// +// Scalar callbacks receive `var value : T&` — a mutable reference. +// This means the walker can modify data during traversal. Here we +// build a "clamper" that restricts all float values to [0..1]. + +struct Particle { + x : float + y : float + z : float + alpha : float +} + +class FloatClamper : DapiDataWalker { + lo : float = 0.0 + hi : float = 1.0 + + def override Float(var value : float&) : void { + if (value < lo) { + value = lo + } + if (value > hi) { + value = hi + } + } +} + +def demo_mutation() { + print("\n=== Section 8: Mutating data in-place ===\n") + + var particle = Particle(x = -0.5, y = 0.3, z = 1.7, alpha = 0.8) + print("Before clamping: x={particle.x} y={particle.y} z={particle.z} alpha={particle.alpha}\n") + + var walker = new FloatClamper() + var inscope adapter <- make_data_walker(walker) + + unsafe { + adapter |> walk_data(addr(particle), typeinfo rtti_typeinfo(particle)) + } + + print("After clamping: x={particle.x} y={particle.y} z={particle.z} alpha={particle.alpha}\n") + + unsafe { + delete walker + } +} + + +// ============================================================ +// Main +// ============================================================ + +[export] +def main() { + demo_scalar_types() + demo_structures() + demo_arrays_and_tables() + demo_tuples_and_variants() + demo_enums_and_bitfields() + demo_json_serializer() + demo_filtering() + demo_mutation() +} diff --git a/web/CMakeLists.txt b/web/CMakeLists.txt index ef7fe9f1b6..925e86d46a 100644 --- a/web/CMakeLists.txt +++ b/web/CMakeLists.txt @@ -11,14 +11,11 @@ option(DAS_QUIRREL_DISABLED "Disable dasQuirrel (quirrel bindings)" ON) option(DAS_HV_DISABLED "Disable dasHV (websokets,http server and client)" ON) option(DAS_GLFW_DISABLED "Disable dasGLFW (GLFW window for graphics apps)" ON) option(DAS_IMGUI_DISABLED "Disable dasIMGUI (IMGUI, IMNODES, IMGUI-NODE-EDITOR gui libraries)" ON) -option(DAS_BGFX_DISABLED "Disable dasBGFX (BGFX graphics API)" ON) -option(DAS_XBYAK_DISABLED "Disable dasXbyak (XBYAK and ZYDIS, x86 assembly, jit)" ON) option(DAS_MINFFT_DISABLED "Disable dasMinfft (Minimal FFT library)" ON) option(DAS_AUDIO_DISABLED "Disable dasAudio (Miniaudio sound library)" ON) option(DAS_STDDLG_DISABLED "Disable dasStdDlg (File new,open,save etc dialogs)" ON) option(DAS_STBIMAGE_DISABLED "Disable dasStbImage (StbImage bindings, image loading and saving)" ON) option(DAS_STBTRUETYPE_DISABLED "Disable dasStbTrueType (StbTrueType bindings, ttf rasterization)" ON) -option(DAS_SFML_DISABLED "Disable dasSFML (SFML multimedia library)" ON) option(DAS_PUGIXML_DISABLED "Disable dasPUGIXML (xml parsing library)" ON) option(DAS_SQLITE_DISABLED "Disable dasSQLITE (sqlite3 library)" ON)