diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f924aed --- /dev/null +++ b/.clang-format @@ -0,0 +1,321 @@ +--- +Language: Cpp +AlignAfterOpenBracket: true +AccessModifierOffset: -2 +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: true + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseArrows: false + AlignCaseColons: false +AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenCondOperatorColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenDefinitionColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + AlignPPAndNotPP: true + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowBreakBeforeQtProperty: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseExpressionOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AllowShortNamespacesOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AttributeMacros: + - __capability +BinPackArguments: true +BinPackLongBracedList: true +BinPackParameters: BinPack +BitFieldColonSpacing: Both +BracedInitializerIndentWidth: -1 +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakAfterOpenBracketBracedList: false +BreakAfterOpenBracketFunction: false +BreakAfterOpenBracketIf: false +BreakAfterOpenBracketLoop: false +BreakAfterOpenBracketSwitch: false +BreakAfterReturnType: None +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeCloseBracketBracedList: false +BreakBeforeCloseBracketFunction: false +BreakBeforeCloseBracketIf: false +BreakBeforeCloseBracketLoop: false +BreakBeforeCloseBracketSwitch: false +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTemplateCloser: false +BreakBeforeTernaryOperators: true +BreakBinaryOperations: Never +BreakConstructorInitializers: BeforeColon +BreakFunctionDefinitionParameters: false +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +BreakTemplateDeclarations: MultiLine +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: AlignFirstComment +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +EnumTrailingComma: Leave +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExportBlock: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigitsInsert: 0 + BinaryMaxDigitsRemove: 0 + Decimal: 0 + DecimalMinDigitsInsert: 0 + DecimalMaxDigitsRemove: 0 + Hex: 0 + HexMinDigitsInsert: 0 + HexMaxDigitsRemove: 0 + BinaryMinDigits: 0 + DecimalMinDigits: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: true + AtStartOfFile: true +KeepFormFeed: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MainIncludeChar: Quote +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +NumericLiteralCase: + ExponentLetter: Leave + HexDigit: Leave + Prefix: Leave + Suffix: Leave +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +OneLineFormatOffRegex: '' +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakBeforeMemberAccess: 150 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: Always +RemoveBracesLLVM: false +RemoveEmptyLinesInUnwrappedLines: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: + Enabled: true + IgnoreCase: false + IgnoreExtension: false +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterOperatorKeyword: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterNot: false + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBraces: Never +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + ExceptDoubleParentheses: false + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TableGenBreakInsideDAGArg: DontBreak +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +WrapNamespaceBodyWithEmptyLines: Leave +... + diff --git a/.gitea/workflows/tag.yaml b/.gitea/workflows/tag.yaml index 6843311..f0e30fc 100644 --- a/.gitea/workflows/tag.yaml +++ b/.gitea/workflows/tag.yaml @@ -29,7 +29,6 @@ jobs: - run: chown build:build /home/build/PKGBUILD - run: chown build:build /home/build/build-arch.sh - run: su build -c /home/build/build-arch.sh - - run: env -C Packaging/Slim bash build.sh - uses: akkuman/gitea-release-action@v1 env: NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18 @@ -39,9 +38,20 @@ jobs: artifacts/** update-tap: - runs-on: ubuntu-latest + runs-on: global-container-mingw steps: - uses: actions/checkout@v4 + - run: | + mkdir -p artifacts + env -C Packaging/Windows bash build.sh + - uses: akkuman/gitea-release-action@v1 + env: + NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18 + with: + prerelease: true + files: |- + artifacts/** + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to registry diff --git a/.vscode/settings.json b/.vscode/settings.json index 471378b..8a02237 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -88,7 +88,8 @@ "clangd.fallbackFlags": [ "-I${workspaceFolder}/include", "-I/home/mike/tmp-crosslang/usr/local/include/" - ] + ], + "editor.formatOnSave": true } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 81f1d19..16db340 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,188 +1,34 @@ cmake_minimum_required(VERSION 3.16) include(cmake/version.cmake) -include(cmake/options.cmake) - project(TessesCrossLang VERSION ${CROSSLANG_MAJOR_VERSION}.${CROSSLANG_MINOR_VERSION}.${CROSSLANG_PATCH_VERSION}) set(CMAKE_CXX_STANDARD 17) - - -include(CMakePackageConfigHelpers) -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) - - -if(CROSSLANG_CUSTOM_CONSOLE) -set(CROSSLANG_ENABLE_BINARIES OFF) -set(CROSSLANG_ENABLE_SHARED OFF) -endif() - - -if(CROSSLANG_FETCHCONTENT) - -set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF) -set(TESSESFRAMEWORK_ENABLE_APPS OFF) - -if(NOT TESSESFRAMEWORK_ENABLE_SHARED) -set(CROSSLANG_ENABLE_SHARED OFF) -endif() -if(NOT TESSESFRAMEWORK_ENABLE_STATIC) -set(CROSSLANG_ENABLE_STATIC OFF) -endif() -if(NOT TESSESFRAMEWORK_ENABLE_RPATH) -set(CROSSLANG_ENABLE_RPATH OFF) -endif() - -#set(CROSSLANG_ENABLE_SHARED OFF) -#set(TESSESFRAMEWORK_ENABLE_SHARED OFF) -#set(CROSSLANG_SHARED_EXECUTABLES OFF) +include(GNUInstallDirs) +include(CheckLibraryExists) include(FetchContent) -FetchContent_Declare( - TessesFramework - GIT_REPOSITORY https://git.tesses.org/tesses50/tessesframework.git -) -FetchContent_MakeAvailable(TessesFramework) -list(APPEND TessesCrossLangLibs ${TessesFrameworkTargets}) -else() -find_package(TessesFramework REQUIRED) -endif() - +include(cmake/sources.cmake) +include(cmake/options.cmake) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) if(CROSSLANG_ENABLE_FFI) find_package(PkgConfig) endif() -include(cmake/linkdeps.cmake) -if(CROSSLANG_ENABLE_FFI AND CROSSLANG_ENABLE_SHARED) -pkg_check_modules(LIBFFI REQUIRED IMPORTED_TARGET libffi) -endif() -configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/CrossLangVersion.h.in "${CMAKE_CURRENT_BINARY_DIR}/include/CrossLangVersion.h" -INSTALL_DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/CrossLangVersion.h) + + + +include(cmake/findtf.cmake) include(cmake/sources.cmake) - -if(CROSSLANG_OFFLINE_SHELL_PACKAGE STREQUAL "") - +include(cmake/cpack.cmake) +if(CROSSLANG_STATIC) +include(cmake/staticlib.cmake) else() -install(FILES ${CROSSLANG_OFFLINE_SHELL_PACKAGE} DESTINATION share/Tesses/CrossLang) +include(cmake/sharedlib.cmake) endif() -if(MINGW) -list(APPEND CROSSLANG_WIN32_EXE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/winicon.rc") -if(MINGW) - ENABLE_LANGUAGE(RC) -endif(MINGW) -endif() +include(cmake/install-dev.cmake) +include(cmake/app.cmake) - -include(GNUInstallDirs) - -if(CROSSLANG_ENABLE_STATIC) - -add_library(crosslang_static STATIC ${CROSSLANG_SOURCE}) -CROSSLANG_LINK_DEPS(crosslang_static) -if(CROSSLANG_FETCHCONTENT) - -target_link_libraries(crosslang_static PUBLIC tessesframework) -else() -target_link_libraries(crosslang_static PUBLIC TessesFramework::tessesframework) -endif() - -list(APPEND TessesCrossLangLibs crosslang_static) -endif() - - -if(CROSSLANG_ENABLE_SHARED) -add_library(crosslang_shared SHARED ${CROSSLANG_SOURCE}) -CROSSLANG_LINK_DEPS(crosslang_shared) -if(CROSSLANG_FETCHCONTENT) -target_link_libraries(crosslang_shared PUBLIC tessesframework_shared) -else() -target_link_libraries(crosslang_shared PUBLIC TessesFramework::tessesframework_shared) -endif() -list(APPEND TessesCrossLangLibs crosslang_shared) -endif() - - -if(CROSSLANG_ENABLE_SUPERSLIM) -include(cmake/slim.cmake) -else() -include(cmake/shared.cmake) - - - -if(CROSSLANG_ENABLE_BINARIES) -if(CROSSLANG_ENABLE_SHARED AND CROSSLANG_SHARED_EXECUTABLES) -include(cmake/shared_exec.cmake) -elseif(CROSSLANG_ENABLE_STATIC) -include(cmake/static_exec.cmake) -else() -include(cmake/exec.cmake) -endif() - -install(TARGETS crossc DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crossvm DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crossint DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crossdump DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crosslang DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crossarchiveextract DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crossarchivecreate DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crossasm DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crossdisasm DESTINATION "${CMAKE_INSTALL_BINDIR}") -install(TARGETS crossmerge DESTINATION "${CMAKE_INSTALL_BINDIR}") -if(NOT WIN32) -install(TARGETS crossthumbnailer DESTINATION "${CMAKE_INSTALL_BINDIR}") - -configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/crossvm-binfmt.conf.in "${CMAKE_CURRENT_BINARY_DIR}/crossvm-binfmt.conf" -INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/binfmt.d) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crossvm-binfmt.conf" -DESTINATION ${CMAKE_INSTALL_LIBDIR}/binfmt.d) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/crosslang.xml" -DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/crosslang.png" -DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/crosslang.thumbnailer" -DESTINATION ${CMAKE_INSTALL_PREFIX}/share/thumbnailers) -endif() -endif() -endif() -include(InstallRequiredSystemLibraries) -set(CPACK_PACKAGE_CONTACT "Mike Nolan ") -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md") -set(CPACK_PACKAGE_VERSION_MAJOR "${TessesCrossLang_VERSION_MAJOR}") -set(CPACK_PACKAGE_VERSION_MINOR "${TessesCrossLang_VERSION_MINOR}") - -set(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS -"!include \\\"FileFunc.nsh\\\"\n!include \\\"${CMAKE_CURRENT_SOURCE_DIR}/FileAssociation.nsh\\\"") - - -# Create association on install -set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS - "\\\${RegisterExtension} '$INSTDIR\\\\bin\\\\crossvm.exe' '.crvm' 'CrossLang Executable'\n\ - \\\${RefreshShellIcons}") - -# Remove association on uninstall - - - set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS - "\\\${RegisterExtension} '$INSTDIR\\\\bin\\\\crossint.exe' '.tcross' 'CrossLang Script'\n\ - \\\${RefreshShellIcons}\n\ - \\\${UnRegisterExtension} '.crvm' 'CrossLang Executable'\n\ - \\\${RefreshShellIcons}") - -# Remove association on uninstall -set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS - "\\\${UnRegisterExtension} '.tcross' 'CrossLang Script'\n\ - \\\${RefreshShellIcons}\n\ - \\\${UnRegisterExtension} '.crvm' 'CrossLang Executable'\n\ - \\\${RefreshShellIcons}") - - set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/winicon.ico") -set(CPACK_NSIS_MODIFY_PATH ON) -set(CPACK_PACKAGE_VENDOR "Tesses") -set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$DESKTOP\\\\CrossLang Interperter.lnk' '$INSTDIR\\\\bin\\\\crossint.exe'") -set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\CrossLang Interperter.lnk' '$INSTDIR\\\\bin\\\\crossint.exe'") - - -include(CPack) if(CROSSLANG_INSTALL_DEVELOPMENT) add_subdirectory(pkgconfig) -endif() +endif() \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 8530286..a5a743a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ RUN apk add --no-cache cmake g++ make git COPY ./ /src -RUN cd /src && mkdir build && cd build && cmake -S .. -B . -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_APPS=ON -DCMAKE_BUILD_TYPE=Release ; make -j`nproc` && make install DESTDIR=/out +RUN cd /src && mkdir build && cd build && cmake -S .. -B . -DTESSESFRAMEWORK_STATIC=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_APPS=ON -DCMAKE_BUILD_TYPE=Release ; make -j`nproc` && make install DESTDIR=/out FROM alpine:latest RUN apk update @@ -14,4 +14,4 @@ RUN apk add --no-cache libstdc++ COPY --from=build /out/usr /usr ENV CROSSLANG_CONTAINER=1 -ENTRYPOINT ["/usr/local/bin/crossint"] +ENTRYPOINT ["/usr/local/bin/crosslang","int"] diff --git a/Packaging/Linux/PKGBUILD b/Packaging/Linux/PKGBUILD index 5996d69..d78cc38 100644 --- a/Packaging/Linux/PKGBUILD +++ b/Packaging/Linux/PKGBUILD @@ -1,13 +1,13 @@ # Maintainer: Mike Nolan pkgname=crosslang # '-bzr', '-git', '-hg' or '-svn' -pkgver=0.0.5 +pkgver=0.0.6 pkgrel=1 pkgdesc="" arch=('x86_64' 'powerpc') url="https://git.tesses.org/tesses50/crosslang" license=('GPLv3') groups=() -depends=('mbedtls' 'tessesframework=0.0.3') +depends=('mbedtls' 'tessesframework=0.0.4') makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion' install= source=('crosslang::git+https://git.tesses.org/tesses50/crosslang') diff --git a/Packaging/Slim/build.sh b/Packaging/Slim/build.sh index 38e5afa..09baa3f 100644 --- a/Packaging/Slim/build.sh +++ b/Packaging/Slim/build.sh @@ -7,7 +7,7 @@ git clone --depth 1 https://git.tesses.org/tesses50/zig-cross builds/zig-cross for tripple in x86_64-linux-musl x86-linux-musl aarch64-linux-musl arm-linux-musleabi riscv64-linux-musl powerpc-linux-musleabihf; do export BUILDDIR=builds/$tripple mkdir -p $BUILDDIR - cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DCROSSLANG_ENABLE_SUPERSLIM=ON -DCMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++ -static -Wl,--strip-all" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -GNinja + cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -D -DTESSESFRAMEWORK_STATIC=ON -DCROSSLANG_ENABLE_SUPERSLIM=ON -DCMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++ -static -Wl,--strip-all" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -GNinja cmake --build $BUILDDIR || exit 1 cmake --install $BUILDDIR --prefix $BUILDDIR/out mv $BUILDDIR/out/bin/crosslang ../../artifacts/crosslang-slim-$tripple @@ -16,7 +16,7 @@ done for tripple in x86_64-windows-gnu x86-windows-gnu aarch64-windows-gnu; do export BUILDDIR=builds/$tripple mkdir -p $BUILDDIR - cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DCMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++ -static -Wl,--strip-all" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCROSSLANG_ENABLE_SUPERSLIM=ON -GNinja + cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -D -DTESSESFRAMEWORK_STATIC=ON -DCMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++ -static -Wl,--strip-all" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCROSSLANG_ENABLE_SUPERSLIM=ON -GNinja cmake --build $BUILDDIR || exit 1 cmake --install $BUILDDIR --prefix $BUILDDIR/out @@ -26,7 +26,7 @@ done for tripple in x86_64-macos-none aarch64-macos-none; do export BUILDDIR=builds/$tripple mkdir -p $BUILDDIR - cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCROSSLANG_ENABLE_SUPERSLIM=ON -GNinja -DCMAKE_EXE_LINKER_FLAGS="-Wl,--strip-all" + cmake -S ../.. -B $BUILDDIR --toolchain $PWD/builds/zig-cross/$tripple\.cmake -DCMAKE_BUILD_TYPE=Release -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -D -DTESSESFRAMEWORK_STATIC=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCROSSLANG_ENABLE_SUPERSLIM=ON -GNinja -DCMAKE_EXE_LINKER_FLAGS="-Wl,--strip-all" cmake --build $BUILDDIR || exit 1 cmake --install $BUILDDIR --prefix $BUILDDIR/out diff --git a/Packaging/Windows/build.sh b/Packaging/Windows/build.sh index a58929f..a18174d 100644 --- a/Packaging/Windows/build.sh +++ b/Packaging/Windows/build.sh @@ -1,16 +1,15 @@ #!/bin/bash -cmake -S ../.. -B build-x86 -DCMAKE_TOOLCHAIN_FILE=`pwd`/WindowsToolchains/x86.cmake -DTESSESFRAMEWORK_FETCHCONTENT=ON -DTESSESFRAMEWORK_ENABLE_APPS=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DCMAKE_INSTALL_PREFIX=tmp-x86 -DCMAKE_BUILD_TYPE=Release +mkdir -p ../../artifacts +cmake -S ../.. -B build-x86 -DCMAKE_TOOLCHAIN_FILE=`pwd`/WindowsToolchains/x86.cmake -DTESSESFRAMEWORK_FETCHCONTENT=ON -DTESSESFRAMEWORK_ENABLE_APPS=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_STATIC=ON -DCMAKE_INSTALL_PREFIX=tmp-x86 -DCMAKE_BUILD_TYPE=Release cd build-x86 make -j`nproc` cpack -G NSIS -cpack -G ZIP -mv TessesCrossLang-*-win32.exe ../../../artifacts/crosslang-win32.exe -mv TessesCrossLang-*-win32.zip ../../../artifacts/crosslang-win32.zip +mv TessesCrossLang-*-win32.exe ../../../artifacts/crosslang-win32-setup.exe +mv crosslang.exe ../../../artifacts/crosslang-win32-portable.exe cd .. -cmake -S ../.. -B build-x64 -DCMAKE_TOOLCHAIN_FILE=`pwd`/WindowsToolchains/x64.cmake -DTESSESFRAMEWORK_FETCHCONTENT=ON -DTESSESFRAMEWORK_ENABLE_APPS=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DCMAKE_INSTALL_PREFIX=tmp-x64 -DCMAKE_BUILD_TYPE=Release +cmake -S ../.. -B build-x64 -DCMAKE_TOOLCHAIN_FILE=`pwd`/WindowsToolchains/x64.cmake -DTESSESFRAMEWORK_FETCHCONTENT=ON -DTESSESFRAMEWORK_ENABLE_APPS=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_STATIC=ON -DCMAKE_INSTALL_PREFIX=tmp-x64 -DCMAKE_BUILD_TYPE=Release cd build-x64 make -j`nproc` cpack -G NSIS -cpack -G ZIP -mv TessesCrossLang-*-win64.exe ../../../artifacts/crosslang-win64.exe -mv TessesCrossLang-*-win64.zip ../../../artifacts/crosslang-win64.zip \ No newline at end of file +mv TessesCrossLang-*-win64.exe ../../../artifacts/crosslang-win64-setup.exe +mv crosslang.exe ../../../artifacts/crosslang-win64-portable.exe diff --git a/README.md b/README.md index 72a4a3e..d112165 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ sudo make install ## Build with shared libs only (self contained dependencies) ```bash -cmake -S ../.. -B . -DTESSESFRAMEWORK_ENABLE_STATIC=OFF -DTESSESFRAMEWORK_ENABLE_SHARED=ON +cmake -S ../.. -B . make -j`nproc` sudo make install ``` diff --git a/build-dvd.tcross b/build-dvd.tcross deleted file mode 100644 index 2824bf4..0000000 --- a/build-dvd.tcross +++ /dev/null @@ -1,280 +0,0 @@ -var cpus = [ - { - uname = "ppc", - name = "powerpc", - compiler = "powerpc-linux-musl-cross", - cc = "powerpc-linux-musl-gcc", - cxx = "powerpc-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "ppc64", - name = "powerpc64", - compiler = "powerpc64-linux-musl-cross", - cc = "powerpc64-linux-musl-gcc", - cxx = "powerpc64-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "x86_64", - name = "x86_64", - compiler = "x86_64-linux-musl-cross", - cc = "x86_64-linux-musl-gcc", - cxx = "x86_64-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname="i686", - name = "i686", - compiler = "i686-linux-musl-cross", - cc = "i686-linux-musl-gcc", - cxx = "i686-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "aarch64", - name = "aarch64", - compiler = "aarch64-linux-musl-cross", - cc = "aarch64-linux-musl-gcc", - cxx = "aarch64-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "arm", - name = "arm", - compiler = "arm-linux-musleabi-cross", - cc = "arm-linux-musleabi-gcc", - cxx = "arm-linux-musleabi-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "armv7l", - name = "armv7l", - compiler = "arm-linux-musleabihf-cross", - cc = "arm-linux-musleabihf-gcc", - cxx = "arm-linux-musleabihf-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "mips", - name = "mips", - compiler = "mips-linux-musl-cross", - cc = "mips-linux-musl-gcc", - cxx = "mips-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "mips64", - name = "mips64", - compiler = "mips64-linux-musl-cross", - cc = "mips64-linux-musl-gcc", - cxx = "mips64-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "riscv32", - name = "riscv32", - compiler = "riscv32-linux-musl-cross", - cc = "riscv32-linux-musl-gcc", - cxx = "riscv32-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - }, - { - uname = "riscv64", - name = "riscv64", - compiler = "riscv64-linux-musl-cross", - cc = "riscv64-linux-musl-gcc", - cxx = "riscv64-linux-musl-g++", - flags = "-static-libgcc -static-libstdc++ -static" - } -]; - - -var mbedversion="mbedtls-2.28.9"; -func main(args) -{ - var working = FS.CurrentPath / "Working"; - - - FS.Local.CreateDirectory(working / "Toolchains"); - FS.Local.CreateDirectory(working / "CMakeToolchains"); - FS.Local.CreateDirectory(working / "Source"); - FS.Local.CreateDirectory(working / "DvdFiles" / "Linux"); - FS.Local.CreateDirectory(working / "DvdFiles" / "Common"); - FS.Local.CreateDirectory(working / "Output"); -var install = "#!/bin/bash -export CPU=`uname -m` - -"; -var file = $"cd {working / \"Source\"} -if [ ! -d \"{mbedversion}\" ]; then -wget -O ../DvdFiles/crosslang-license.txt https://downloads.tesses.net/gpl-3.0.txt -cp ../DvdFiles/crosslang-license.txt ../Output/crosslang-license.txt -wget -O {mbedversion}.tar.bz2 https://downloads.tesses.net/cache/libraries/source/{mbedversion}.tar.bz2 -tar xf {mbedversion}.tar.bz2 -rm {mbedversion}.tar.bz2 -fi -git clone --depth=1 https://git.tesses.org/tesses50/tessesframework -git clone --depth=1 https://git.tesses.org/tesses50/crosslang -zip -r \"{working / \"DvdFiles\" / \"crosslang-source.zip\"}\" ./* -cp ../DvdFiles/crosslang-source.zip ../Output/crosslang-source.zip -wget -O \"{working / \"DvdFiles\" / \"Common\" / \"ShellPackage.crvm\"}\" https://redirect.tesses.net/crosslang-shell -"; - var w32_toolchain = $" - set(CMAKE_C_COMPILER \"/usr/bin/i686-w64-mingw32-gcc\") - set(CMAKE_CXX_COMPILER \"/usr/bin/i686-w64-mingw32-g++\") - set(CMAKE_C_FLAGS \"-static-libgcc -static-libstdc++ -static\") - set(CMAKE_CXX_FLAGS \"-static-libgcc -static-libstdc++ -static\") - set(CMAKE_EXE_LINKER_FLAGS \"-static-libgcc -static-libstdc++ -static\") - - set(CMAKE_SYSROOT \"{working}/Sysroot/windows\") - - set(CMAKE_SYSTEM_NAME Windows) - set(CMAKE_SYSTEM_PROCESSOR i686) - "; - FS.Local.CreateDirectory(working / "Build" / "windows"); - FS.Local.CreateDirectory(working / "Sysroot" / "windows"); - FS.WriteAllText(FS.Local,working / "CMakeToolchains" / "windows.cmake", w32_toolchain); - file += $"#windows - cd \"{working / \"Build\" / \"windows\"}\" -mkdir -p mbedtls -cd mbedtls -cmake -S \"{working / \"Source\" / mbedversion}\" -B . -DCMAKE_TOOLCHAIN_FILE=\"{working / \"CMakeToolchains\" / \"windows\"}.cmake\" -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -make -j16 -make install DESTDIR=\"{working / \"Sysroot\" / \"windows\"}\" -cd .. -mkdir -p tesses-framework -cd tesses-framework -cmake -S \"{working / \"Source\" / \"tesses-framework\"}\" -DMBEDTLS_DIR=\"{working / \"Sysroot\" / \"windows\"/\"usr\"/\"local\"}\" -B . -DCMAKE_TOOLCHAIN_FILE=\"{working / \"CMakeToolchains\" / \"windows\"}.cmake\" -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_APPS=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -make -j16 -make install DESTDIR=\"{working / \"Sysroot\" / \"windows\"}\" -cd .. -mkdir -p crosslang -cd crosslang -cmake -S \"{working / \"Source\" / \"crosslang\"}\" -B . -DCMAKE_TOOLCHAIN_FILE=\"{working / \"CMakeToolchains\" / \"windows\"}.cmake\" -DCROSSLANG_ENABLE_SHARED=OFF -DCROSSLANG_FETCHCONTENT=OFF -DCROSSLANG_SHARED_EXECUTABLES=OFF -make -j16 -cpack -G NSIS -cpack -G ZIP -cp TessesCrossLang-*-win32.exe \"{working/\"DvdFiles\"/\"setup.exe\"}\" -cp TessesCrossLang-*-win32.zip \"{working/\"DvdFiles\"/\"crosslang-win32.zip\"}\" -cp TessesCrossLang-*-win32.exe \"{working/\"Output\"/\"crosslang-win32.exe\"}\" -cp TessesCrossLang-*-win32.zip \"{working/\"Output\"/\"crosslang-win32.zip\"}\" - "; - each(var item : cpus) - { - FS.Local.CreateDirectory(working / "Build" / item.name); - FS.Local.CreateDirectory(working / "Sysroot" / item.name); - - var toolchain = $" - set(CMAKE_C_COMPILER \"{working}/Toolchains/{item.compiler}/bin/{item.cc}\") - set(CMAKE_CXX_COMPILER \"{working}/Toolchains/{item.compiler}/bin/{item.cxx}\") - set(CMAKE_C_FLAGS \"{item.flags}\") - set(CMAKE_CXX_FLAGS \"{item.flags}\") - set(CMAKE_EXE_LINKER_FLAGS \"{item.flags}\") - - set(CMAKE_SYSROOT \"{working}/Sysroot/{item.name}\") - - set(CMAKE_SYSTEM_NAME Linux) - set(CMAKE_SYSTEM_PROCESSOR powerpc) - "; - if(item.name == "riscv32" || item.name == "riscv64") - { - toolchain += "set(CMAKE_POSITION_INDEPENDENT_CODE ON)\n"; - } - FS.WriteAllText(FS.Local,working / "CMakeToolchains" / $"{item.name}.cmake", toolchain); - var tar = working / "Output" / $"crosslang-{item.name}.tar.gz"; - var dvdDir = working / "DvdFiles" / "Linux" / item.name; -file += $"#{item.name} -cd \"{working / \"Toolchains\"}\" -if [ ! -d \"{item.compiler}\" ]; then - -wget -O {item.compiler}.tgz https://downloads.tesses.net/cache/compilers/{item.compiler}.tgz -tar xzf {item.compiler}.tgz -rm {item.compiler}.tgz -fi -cd \"{working / \"Build\" / item.name}\" -mkdir -p mbedtls -cd mbedtls -cmake -S \"{working / \"Source\" / mbedversion}\" -B . -DCMAKE_TOOLCHAIN_FILE=\"{working / \"CMakeToolchains\" / item.name}.cmake\" -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -make -j16 -make install DESTDIR=\"{working / \"Sysroot\" / item.name}\" -cd .. -mkdir -p tesses-framework -cd tesses-framework -cmake -S \"{working / \"Source\" / \"tesses-framework\"}\" -DMBEDTLS_DIR=\"{working / \"Sysroot\" / item.name/\"usr\"/\"local\"}\" -B . -DCMAKE_TOOLCHAIN_FILE=\"{working / \"CMakeToolchains\" / item.name}.cmake\" -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_APPS=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -make -j16 -make install DESTDIR=\"{working / \"Sysroot\" / item.name}\" -cd .. -mkdir -p crosslang -cd crosslang -cmake -S \"{working / \"Source\" / \"crosslang\"}\" -B . -DCMAKE_TOOLCHAIN_FILE=\"{working / \"CMakeToolchains\" / item.name}.cmake\" -DCROSSLANG_ENABLE_SHARED=OFF -DCROSSLANG_FETCHCONTENT=OFF -DCROSSLANG_SHARED_EXECUTABLES=OFF -make -j16 -make install DESTDIR=\"{working / \"Sysroot\" / item.name}\" -cd \"{working/\"Sysroot\"/item.name/\"usr\"/\"local\"}\" -tar czf \"{tar}\" bin share lib/binfmt.d -mv bin \"{dvdDir}\" -"; - install += $" -if [[ \"$CPU\" == \"{item.uname}\" ]]; then - install -D -m 755 -o root ./Linux/{item.name}/crossarchivecreate /usr/local/bin/crossarchivecreate - install -D -m 755 -o root ./Linux/{item.name}/crossarchiveextract /usr/local/bin/crossarchiveextract - install -D -m 755 -o root ./Linux/{item.name}/crossc /usr/local/bin/crossc - install -D -m 755 -o root ./Linux/{item.name}/crossdump /usr/local/bin/crossdump - install -D -m 755 -o root ./Linux/{item.name}/crossint /usr/local/bin/crossint - install -D -m 755 -o root ./Linux/{item.name}/crosslang /usr/local/bin/crosslang - install -D -m 755 -o root ./Linux/{item.name}/crossthumbnailer /usr/local/bin/crossthumbnailer - install -D -m 755 -o root ./Linux/{item.name}/crossvm /usr/local/bin/crossvm - install -D -m 644 -o root ./Linux/crosslang.thumbnailer /usr/local/share/thumbnailers/crosslang.thumbnailer - install -D -m 644 -o root ./Linux/crosslang.xml /usr/local/share/mime/crosslang.xml - install -D -m 644 -o root ./Linux/crossvm-binfmt.conf /usr/local/lib/binfmt.d/crossvm-binfmt.conf - install -D -m 644 -o root ./Linux/crosslang.png /usr/local/share/icons/crosslang.png - install -D -m 644 -o root ./Common/ShellPackage.crvm /usr/local/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm - - -fi - "; - } - - file += $" -cd \"{working.GetParent()}\" -cd \"{working}\" -chmod 755 DvdFiles/install.sh -cp Source/crosslang/crosslang.png DvdFiles/Linux/crosslang.png -cp Source/crosslang/winicon.ico DvdFiles/cross.ico -cd DvdFiles -xorriso -outdev ../Output/crosslang.iso -add * - "; - - - FS.WriteAllText(FS.Local,"script.sh", file); - FS.WriteAllText(FS.Local,./"Working"/"DvdFiles"/"install.sh", install); - FS.WriteAllText(FS.Local,./"Working"/"DvdFiles"/"Linux"/"crossvm-binfmt.conf",":CrossVM:M::TCROSSVM::/usr/local/bin/crossvm:\n"); - FS.WriteAllText(FS.Local,./"Working"/"DvdFiles"/"Linux"/"crosslang.thumbnailer","[Thumbnailer Entry] -TryExec=crossthumbnailer -Exec=crossthumbnailer %i %o -MimeType=application/crvm; -"); - FS.WriteAllText(FS.Local,"Working"/"DvdFiles"/"ReadmeWindows.txt", "When installing make sure to enable path\nRun ShellInstaller.bat from each user (if offline)"); - - FS.WriteAllText(FS.Local,"Working"/"DvdFiles"/"ShellInstaller.bat", "@echo off\r\ncrossarchiveextract Common\\ShellPackage.crvm %APPDATA%\\Tesses\\CrossLang"); - FS.WriteAllText(FS.Local,./"Working"/"DvdFiles"/"autorun.inf","[autorun]\r\nicon=cross.ico\r\nopen=setup.exe\r\nlabel=CrossLang"); - FS.WriteAllText(FS.Local,./"Working"/"DvdFiles"/"Linux"/"crosslang.xml"," - - - - CrossLang Executable - CrossLang Executable - - - - - - CrossLang Source - CrossLang Source - - - -" - ); -} - diff --git a/changelog.md b/changelog.md index 3f3a60e..fa264b6 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,8 @@ # Changelog +## 0.0.6 +Fix bug with classes, use slim exclusively, add package private data and change rehaul cmake configs + ## 0.0.5 Fix crosslang Stat, StatVFS for custom crosslang filesystems and add queryable diff --git a/cmake/app.cmake b/cmake/app.cmake new file mode 100644 index 0000000..e6b24d2 --- /dev/null +++ b/cmake/app.cmake @@ -0,0 +1,25 @@ +if(CROSSLANG_ENABLE_BINARIES) +if(MINGW) +list(APPEND CROSSLANG_WIN32_EXE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/winicon.rc") +if(MINGW) + ENABLE_LANGUAGE(RC) +endif(MINGW) +endif() +add_executable(crosslang_app src/programs/slim.cpp "${CROSSLANG_WIN32_EXE_SRC}") +target_link_libraries(crosslang_app PUBLIC crosslang) +set_target_properties(crosslang_app PROPERTIES OUTPUT_NAME crosslang) +install(TARGETS crosslang_app DESTINATION "${CMAKE_INSTALL_BINDIR}") +endif() + +if(NOT WIN32 AND NOT APPLE) +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/crossvm-binfmt.conf.in "${CMAKE_CURRENT_BINARY_DIR}/crossvm-binfmt.conf" +INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/binfmt.d) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crossvm-binfmt.conf" +DESTINATION ${CMAKE_INSTALL_LIBDIR}/binfmt.d) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/crosslang.xml" +DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/crosslang.png" +DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/crosslang.thumbnailer" +DESTINATION ${CMAKE_INSTALL_PREFIX}/share/thumbnailers) +endif() \ No newline at end of file diff --git a/cmake/cpack.cmake b/cmake/cpack.cmake new file mode 100644 index 0000000..f87deb1 --- /dev/null +++ b/cmake/cpack.cmake @@ -0,0 +1,39 @@ +include(InstallRequiredSystemLibraries) +set(CPACK_PACKAGE_CONTACT "Mike Nolan ") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md") +set(CPACK_PACKAGE_VERSION_MAJOR "${TessesCrossLang_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${TessesCrossLang_VERSION_MINOR}") + +set(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS +"!include \\\"FileFunc.nsh\\\"\n!include \\\"${CMAKE_CURRENT_SOURCE_DIR}/FileAssociation.nsh\\\"") + + +# Create association on install +set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS + "\\\${RegisterExtension} '$INSTDIR\\\\bin\\\\crossvm.exe' '.crvm' 'CrossLang Executable'\n\ + \\\${RefreshShellIcons}") + +# Remove association on uninstall + + + set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS + "\\\${RegisterExtension} '$INSTDIR\\\\bin\\\\crosslang.exe int' '.tcross' 'CrossLang Script'\n\ + \\\${RefreshShellIcons}\n\ + \\\${UnRegisterExtension} '.crvm' 'CrossLang Executable'\n\ + \\\${RefreshShellIcons}") + +# Remove association on uninstall +set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS + "\\\${UnRegisterExtension} '.tcross' 'CrossLang Script'\n\ + \\\${RefreshShellIcons}\n\ + \\\${UnRegisterExtension} '.crvm' 'CrossLang Executable'\n\ + \\\${RefreshShellIcons}") + + set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/winicon.ico") +set(CPACK_NSIS_MODIFY_PATH ON) +set(CPACK_PACKAGE_VENDOR "Tesses") +set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$DESKTOP\\\\CrossLang Interperter.lnk' '$INSTDIR\\\\bin\\\\crossint.exe'") +set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\CrossLang Interperter.lnk' '$INSTDIR\\\\bin\\\\crossint.exe'") + + +include(CPack) \ No newline at end of file diff --git a/cmake/exec.cmake b/cmake/exec.cmake deleted file mode 100644 index 51512ee..0000000 --- a/cmake/exec.cmake +++ /dev/null @@ -1,57 +0,0 @@ -add_executable(crossc src/programs/crosslangcompiler.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossvm src/programs/crosslangvm.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossint src/programs/crosslanginterperter.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossdump src/programs/crosslangdump.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crosslang src/programs/crosslang.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossarchiveextract src/programs/crossarchiveextract.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossarchivecreate src/programs/crossarchivecreate.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossasm src/crossasmcli.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossdisasm src/crossdisasmcli.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossmerge src/crossmergecli.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) - -if(NOT WIN32) -add_executable(crossthumbnailer src/crossthumbnailer.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) -endif() -CROSSLANG_LINK_DEPS(crossc) -CROSSLANG_LINK_DEPS(crossvm) -CROSSLANG_LINK_DEPS(crossint) -CROSSLANG_LINK_DEPS(crosslang) -CROSSLANG_LINK_DEPS(crossdump) -CROSSLANG_LINK_DEPS(crossarchiveextract) -CROSSLANG_LINK_DEPS(crossarchivecreate) -CROSSLANG_LINK_DEPS(crossmerge) -CROSSLANG_LINK_DEPS(crossdisasm) -CROSSLANG_LINK_DEPS(crossasm) - -if(NOT WIN32) -CROSSLANG_LINK_DEPS(crossthumbnailer) -endif() -if(CROSSLANG_FETCHCONTENT) -target_link_libraries(crossc PUBLIC tessesframework) -target_link_libraries(crossvm PUBLIC tessesframework) -target_link_libraries(crossint PUBLIC tessesframework) -target_link_libraries(crosslang PUBLIC tessesframework) -target_link_libraries(crossdump PUBLIC tessesframework) -target_link_libraries(crossarchiveextract PUBLIC tessesframework) -target_link_libraries(crossarchivecreate PUBLIC tessesframework) -target_link_libraries(crossasm PUBLIC tessesframework) -target_link_libraries(crossdisasm PUBLIC tessesframework) -target_link_libraries(crossmerge PUBLIC tessesframework) -if(NOT WIN32) -target_link_libraries(crossthumbnailer PUBLIC tessesframework) -endif() -else() -target_link_libraries(crossc PUBLIC TessesFramework::tessesframework) -target_link_libraries(crossvm PUBLIC TessesFramework::tessesframework) -target_link_libraries(crossint PUBLIC TessesFramework::tessesframework) -target_link_libraries(crosslang PUBLIC TessesFramework::tessesframework) -target_link_libraries(crossdump PUBLIC TessesFramework::tessesframework) -target_link_libraries(crossarchiveextract PUBLIC TessesFramework::tessesframework) -target_link_libraries(crossarchivecreate PUBLIC TessesFramework::tessesframework) -target_link_libraries(crossasm PUBLIC TessesFramework::tessesframework) -target_link_libraries(crossdisasm PUBLIC TessesFramework::tessesframework) -target_link_libraries(crossmerge PUBLIC TessesFramework::tessesframework) -if(NOT WIN32) -target_link_libraries(crossthumbnailer PUBLIC TessesFramework::tessesframework) -endif() -endif() diff --git a/cmake/findtf.cmake b/cmake/findtf.cmake new file mode 100644 index 0000000..e1438c4 --- /dev/null +++ b/cmake/findtf.cmake @@ -0,0 +1,14 @@ +if(CROSSLANG_FETCHCONTENT) + + +set(CROSSLANG_STATIC ${TESSESFRAMEWORK_STATIC} CACHE INTERNAL "For CrossLang" FORCE) +FetchContent_Declare( + TessesFramework + GIT_REPOSITORY https://git.tesses.org/tesses50/tessesframework.git + GIT_TAG 25d67053ccebf209f50e6928fad8827164eb4c28 +) +set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF) +FetchContent_MakeAvailable(TessesFramework) +else() +find_package(TessesFramework REQUIRED) +endif() \ No newline at end of file diff --git a/cmake/helpers.cmake b/cmake/helpers.cmake new file mode 100644 index 0000000..6f11e0a --- /dev/null +++ b/cmake/helpers.cmake @@ -0,0 +1,38 @@ +if(CROSSLANG_ENABLE_FFI) +if(NOT CROSSLANG_STATIC) +pkg_check_modules(LIBFFI REQUIRED IMPORTED_TARGET libffi) +target_compile_definitions(crosslang PUBLIC CROSSLANG_ENABLE_FFI) +target_link_libraries(crosslang PUBLIC PkgConfig::LIBFFI) + +endif() +endif() + +if(CROSSLANG_CUSTOM_CONSOLE) +target_compile_definitions(crosslang PRIVATE CROSSLANG_CUSTOM_CONSOLE) + +endif() + +if(CROSSLANG_STATIC) +target_compile_definitions(crosslang PRIVATE CROSSLANG_STATIC) + +endif() + +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/CrossLangVersion.h.in "${CMAKE_CURRENT_BINARY_DIR}/include/CrossLangVersion.h" +INSTALL_DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/CrossLangVersion.h) + +target_include_directories(crosslang + PUBLIC + "$" + "$" +) +target_include_directories(crosslang + PUBLIC + "$" + "$" +) + +if(TESSESFRAMEWORK_FETCHCONTENT) +target_link_libraries(crosslang PUBLIC tessesframework) +else() +target_link_libraries(crosslang PUBLIC TessesFramework::tessesframework) +endif() \ No newline at end of file diff --git a/cmake/shared.cmake b/cmake/install-dev.cmake similarity index 58% rename from cmake/shared.cmake rename to cmake/install-dev.cmake index 9d35304..838ee18 100644 --- a/cmake/shared.cmake +++ b/cmake/install-dev.cmake @@ -1,34 +1,28 @@ if(CROSSLANG_INSTALL_DEVELOPMENT) -install(TARGETS ${TessesCrossLangLibs} - EXPORT TessesCrossLangTargets +install(TARGETS ${CrossLangLibs} + EXPORT CrossLangTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) -install(FILES include/CrossLang.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/CrossLangVersion.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(EXPORT TessesCrossLangTargets +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/CrossLang.hpp" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/CrossLangVersion.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + +install(EXPORT CrossLangTargets FILE TessesCrossLangTargets.cmake NAMESPACE TessesCrossLang:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesCrossLang ) + +include(CMakePackageConfigHelpers) configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/TessesCrossLangConfig.cmake" INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesCrossLang) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/TessesCrossLangConfig.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesCrossLang) -else() - -if(CROSSLANG_ENABLE_SHARED) -install(TARGETS crosslang_shared - EXPORT TessesCrossLangTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) endif() -endif() diff --git a/cmake/linkdeps.cmake b/cmake/linkdeps.cmake deleted file mode 100644 index 7c284f5..0000000 --- a/cmake/linkdeps.cmake +++ /dev/null @@ -1,62 +0,0 @@ -function(CROSSLANG_LINK_DEPS CROSSLANG_TARGET_NAME) -target_include_directories(${CROSSLANG_TARGET_NAME} - PUBLIC - "$" - "$" -) -if(CROSSLANG_ENABLE_FFI AND CROSSLANG_ENABLE_SHARED) - -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_FFI) -target_link_libraries(${CROSSLANG_TARGET_NAME} PUBLIC PkgConfig::LIBFFI) - -endif() -if(CROSSLANG_ENABLE_SUPERSLIM) - -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_SUPERSLIM) -endif() -if(CROSSLANG_ENABLE_TIME) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_TIME) -endif() -if(CROSSLANG_ENABLE_CONFIG_ENVVAR) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_CONFIG_ENVVAR) -endif() -if(CROSSLANG_ENABLE_PROCESS) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_PROCESS) -endif() -if(CROSSLANG_ENABLE_THREADING) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_THREADING) -endif() -if(CROSSLANG_ENABLE_TERMIOS) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_TERMIOS) -endif() - -if(CROSSLANG_ENABLE_SQLITE) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_SQLITE) -endif() - -if(CROSSLANG_CUSTOM_CONSOLE) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_CUSTOM_CONSOLE) -endif() -if(CROSSLANG_ENABLE_PLATFORM_FOLDERS) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_PLATFORM_FOLDERS) -endif() -if(CROSSLANG_ENABLE_SHARED) -target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_SHARED) - -endif() -if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoGameCube") -target_link_libraries(${CROSSLANG_TARGET_NAME} PUBLIC fat) -endif() -if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii") -target_link_libraries(${CROSSLANG_TARGET_NAME} PUBLIC wiisocket) -endif() -if(CROSSLANG_ENABLE_SHARED AND NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")) -target_link_libraries(${CROSSLANG_TARGET_NAME} PUBLIC dl) -endif() -target_include_directories(${CROSSLANG_TARGET_NAME} - PUBLIC - "$" - "$" -) - -endfunction() diff --git a/cmake/options.cmake b/cmake/options.cmake index eec81be..b63cb86 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -1,18 +1,7 @@ -option(CROSSLANG_ENABLE_STATIC "Enable Tesses CrossLang static libraries" ON) -option(CROSSLANG_ENABLE_SHARED "Enable Tesses CrossLang shared libraries" ON) option(CROSSLANG_ENABLE_BINARIES "Enable Tesses CrossLang binaries" ON) option(CROSSLANG_INSTALL_DEVELOPMENT "Enable Tesses CrossLang development files" ON) -option(CROSSLANG_ENABLE_THREADING "Enable Tesses CrossLang threading" ON) -option(CROSSLANG_ENABLE_TERMIOS "Enable termios (For changing terminal options)" ON) -option(CROSSLANG_SHARED_EXECUTABLES "Link with libcrosslang_shared" ON) option(CROSSLANG_FETCHCONTENT "Use fetchcontent" ON) -option(CROSSLANG_ENABLE_CONFIG_ENVVAR "Allow setting config directory via the environment variable CROSSLANG_CONFIG" ON) option(CROSSLANG_ENABLE_FFI "Enable libffi" OFF) option(CROSSLANG_ENABLE_RPATH "Enable RPATH" ON) -option(CROSSLANG_ENABLE_SUPERSLIM "Enable crosslang superslim, one binary" OFF) - option(CROSSLANG_CUSTOM_CONSOLE "Enable custom Console" OFF) - - - -set(CROSSLANG_OFFLINE_SHELL_PACKAGE "" CACHE FILEPATH "Path to the shell package generated from https://git.tesses.org/crosslangextras") +option(CROSSLANG_STATIC "Build with static libraries instead of shared" OFF) diff --git a/cmake/shared_exec.cmake b/cmake/shared_exec.cmake deleted file mode 100644 index 1897a8a..0000000 --- a/cmake/shared_exec.cmake +++ /dev/null @@ -1,37 +0,0 @@ -if(CROSSLANG_ENABLE_RPATH) -set(CMAKE_MACOSX_RPATH 1) -set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE) -if (APPLE) - set(CMAKE_INSTALL_RPATH "@executable_path/../${CMAKE_INSTALL_LIBDIR}") -else() - set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") -endif() -endif() -add_executable(crossmerge src/crossmergecli.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossasm src/crossasmcli.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossdisasm src/crossdisasmcli.cpp ${CROSSLANG_WIN32_EXE_SRC}) - -add_executable(crossc src/programs/crosslangcompiler.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossvm src/programs/crosslangvm.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossint src/programs/crosslanginterperter.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossdump src/programs/crosslangdump.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crosslang src/programs/crosslang.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossarchiveextract src/programs/crossarchiveextract.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossarchivecreate src/programs/crossarchivecreate.cpp ${CROSSLANG_WIN32_EXE_SRC}) -if(NOT WIN32) -add_executable(crossthumbnailer src/crossthumbnailer.cpp ${CROSSLANG_WIN32_EXE_SRC}) -endif() -target_link_libraries(crossc PUBLIC crosslang_shared) -target_link_libraries(crossvm PUBLIC crosslang_shared) -target_link_libraries(crossint PUBLIC crosslang_shared) -target_link_libraries(crossdump PUBLIC crosslang_shared) -target_link_libraries(crosslang PUBLIC crosslang_shared) -target_link_libraries(crossarchiveextract PUBLIC crosslang_shared) -target_link_libraries(crossarchivecreate PUBLIC crosslang_shared) -target_link_libraries(crossasm PUBLIC crosslang_shared) -target_link_libraries(crossdisasm PUBLIC crosslang_shared) -target_link_libraries(crossmerge PUBLIC crosslang_shared) - -if(NOT WIN32) -target_link_libraries(crossthumbnailer PUBLIC crosslang_shared) -endif() diff --git a/cmake/sharedlib.cmake b/cmake/sharedlib.cmake new file mode 100644 index 0000000..4305ed5 --- /dev/null +++ b/cmake/sharedlib.cmake @@ -0,0 +1,20 @@ +if(TESSESFRAMEWORK_ENABLE_RPATH) +set(CMAKE_MACOSX_RPATH 1) +set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE) + +if (APPLE) + set(CMAKE_INSTALL_RPATH "@executable_path/../${CMAKE_INSTALL_LIBDIR}") +else() + set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") +endif() +endif() +add_library(crosslang SHARED ${CROSSLANG_SOURCE}) +set_target_properties(crosslang PROPERTIES + VERSION ${CROSSLANG_MAJOR_VERSION}.${CROSSLANG_MINOR_VERSION}.${CROSSLANG_PATCH_VERSION} + SOVERSION ${CROSSLANG_MAJOR_VERSION} +) +include(${CMAKE_CURRENT_LIST_DIR}/helpers.cmake) + + + +list(APPEND CrossLangLibs crosslang) \ No newline at end of file diff --git a/cmake/slim.cmake b/cmake/slim.cmake deleted file mode 100644 index 926c4a2..0000000 --- a/cmake/slim.cmake +++ /dev/null @@ -1,21 +0,0 @@ - -add_executable(crosslang WIN32 src/programs/slim.cpp ${CROSSLANG_WIN32_EXE_SRC}) - -if(CROSSLANG_ENABLE_STATIC) - -target_link_libraries(crosslang PUBLIC crosslang_static) -elseif(CROSSLANG_ENABLE_SHARED) -target_link_libraries(crosslang PUBLIC crosslang_shared) -endif() - -if(CROSSLANG_ENABLE_SHARED) - -install(TARGETS crosslang_shared - EXPORT TessesCrossLangTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) - -endif() - -install(TARGETS crosslang DESTINATION "${CMAKE_INSTALL_BINDIR}") diff --git a/cmake/sources.cmake b/cmake/sources.cmake index 3990624..7dc8216 100644 --- a/cmake/sources.cmake +++ b/cmake/sources.cmake @@ -9,9 +9,6 @@ src/vm/bc/invokemethod.cpp src/vm/bc/executemethod2.cpp src/vm/bc/invoketwo.cpp src/vm/bc/tobool.cpp -src/assembler/asm.cpp -src/assembler/disasm.cpp -src/assembler/merge.cpp src/compiler/codegen.cpp src/compiler/lexer.cpp src/compiler/parser.cpp diff --git a/cmake/static_exec.cmake b/cmake/static_exec.cmake deleted file mode 100644 index 1c845a3..0000000 --- a/cmake/static_exec.cmake +++ /dev/null @@ -1,28 +0,0 @@ -add_executable(crossc src/programs/crosslangcompiler.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossvm src/programs/crosslangvm.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossint src/programs/crosslanginterperter.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossdump src/programs/crosslangdump.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crosslang src/programs/crosslang.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossarchiveextract src/programs/crossarchiveextract.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossarchivecreate src/programs/crossarchivecreate.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossasm src/crossasmcli.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossdisasm src/crossdisasmcli.cpp ${CROSSLANG_WIN32_EXE_SRC}) -add_executable(crossmerge src/crossmergecli.cpp ${CROSSLANG_WIN32_EXE_SRC}) - -if(NOT WIN32) -add_executable(crossthumbnailer src/crossthumbnailer.cpp ${CROSSLANG_WIN32_EXE_SRC}) -endif() -target_link_libraries(crossc PUBLIC crosslang_static) -target_link_libraries(crossvm PUBLIC crosslang_static) -target_link_libraries(crossint PUBLIC crosslang_static) -target_link_libraries(crossdump PUBLIC crosslang_static) -target_link_libraries(crosslang PUBLIC crosslang_static) -target_link_libraries(crossarchiveextract PUBLIC crosslang_static) -target_link_libraries(crossarchivecreate PUBLIC crosslang_static) -target_link_libraries(crossmerge PUBLIC crosslang_static) -target_link_libraries(crossasm PUBLIC crosslang_static) -target_link_libraries(crossdisasm PUBLIC crosslang_static) - -if(NOT WIN32) -target_link_libraries(crossthumbnailer PUBLIC crosslang_static) -endif() diff --git a/cmake/staticlib.cmake b/cmake/staticlib.cmake new file mode 100644 index 0000000..9f72d8f --- /dev/null +++ b/cmake/staticlib.cmake @@ -0,0 +1,6 @@ + +add_library(crosslang STATIC ${CROSSLANG_SOURCE}) + +include(${CMAKE_CURRENT_LIST_DIR}/helpers.cmake) + +list(APPEND CrossLangLibs crosslang) \ No newline at end of file diff --git a/cmake/version.cmake b/cmake/version.cmake index 3a74251..c00b2bd 100644 --- a/cmake/version.cmake +++ b/cmake/version.cmake @@ -1,3 +1,3 @@ set(CROSSLANG_MAJOR_VERSION 0) set(CROSSLANG_MINOR_VERSION 0) -set(CROSSLANG_PATCH_VERSION 5) +set(CROSSLANG_PATCH_VERSION 6) diff --git a/crosslang.thumbnailer b/crosslang.thumbnailer index 24d27e3..92253a5 100644 --- a/crosslang.thumbnailer +++ b/crosslang.thumbnailer @@ -1,4 +1,4 @@ [Thumbnailer Entry] -TryExec=crossthumbnailer -Exec=crossthumbnailer %i %o +TryExec=crosslang +Exec=crosslang thumbnailer %i %o MimeType=application/crvm; \ No newline at end of file diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index 956e892..722e04f 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -1,23 +1,21 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "CrossLangVersion.h" #include "TessesFramework/Streams/ByteReader.hpp" @@ -25,7 +23,7 @@ #define CROSSLANG_BYTECODE_MAJOR 1 #define CROSSLANG_BYTECODE_MINOR 0 #define CROSSLANG_BYTECODE_PATCH 0 -#define CROSSLANG_BYTECODE_BUILD 0 //SHOULD ALWAYS BE 0 +#define CROSSLANG_BYTECODE_BUILD 0 // SHOULD ALWAYS BE 0 #define CROSSLANG_BYTECODE_VERSIONSTAGE DevVersion #if defined(_WIN32) @@ -37,544 +35,498 @@ * */ namespace Tesses::CrossLang { - using BitConverter = Tesses::Framework::Serialization::BitConverter; - constexpr std::string_view VMName = "CrossLangVM"; - constexpr std::string_view VMHowToGet = "https://crosslang.tesseslanguage.com/"; +using BitConverter = Tesses::Framework::Serialization::BitConverter; +constexpr std::string_view VMName = "CrossLangVM"; +constexpr std::string_view VMHowToGet = "https://crosslang.tesseslanguage.com/"; - +/** + * @brief Escape a crosslang string (for generating source code) + * + * @param text text to escape + * @param quote whether to surround with double quotes + * @return std::string the escaped string + */ +std::string EscapeString(std::string text, bool quote); + +/** + * @brief Get the config folder used by crosslang + * + * @return Tesses::Framework::Filesystem::VFSPath the config folder for + * crosslang + */ +Tesses::Framework::Filesystem::VFSPath GetCrossLangConfigDir(); + +/** + * @brief Version stage + * + */ +enum TVMVersionStage : uint8_t { + DevVersion = 0, + AlphaVersion = 1, + BetaVersion = 2, + ProductionVersion = 3 +}; +/** + * @brief CrossLang version + * + */ +class TVMVersion { + uint8_t major; + uint8_t minor; + uint8_t patch; + uint16_t build; + + public: /** - * @brief Escape a crosslang string (for generating source code) + * @brief Major * - * @param text text to escape - * @param quote whether to surround with double quotes - * @return std::string the escaped string + * @return uint8_t The major */ - std::string EscapeString(std::string text,bool quote); - + uint8_t Major() { return major; } /** - * @brief Get the config folder used by crosslang + * @brief Minor * - * @return Tesses::Framework::Filesystem::VFSPath the config folder for crosslang + * @return uint8_t The minor */ - Tesses::Framework::Filesystem::VFSPath GetCrossLangConfigDir(); - - - + uint8_t Minor() { return minor; } /** - * @brief Version stage + * @brief Patch + * + * @return uint8_t The patch + */ + uint8_t Patch() { return patch; } + /** + * @brief Build + * + * @return uint16_t The build + */ + uint16_t Build() { return build >> 2; } + /** + * @brief Stage (dev, alpha, beta or prod) + * + * @return TVMVersionStage The stage + */ + TVMVersionStage VersionStage() { return (TVMVersionStage)(build & 3); } + /** + * @brief Set the Major + * + * @param major The major + */ + void SetMajor(uint8_t major) { this->major = major; } + /** + * @brief Set the Minor + * + * @param minor The minor + */ + void SetMinor(uint8_t minor) { this->minor = minor; } + /** + * @brief Set the Patch + * + * @param patch The patch + */ + void SetPatch(uint8_t patch) { this->patch = patch; } + /** + * @brief Set the Build + * + * @param build The build << 2 | (stage & 3) + */ + void SetBuild(uint16_t build) { this->build = build; } + /** + * @brief Set the Build (and stage) + * + * @param build + * @param version + */ + void SetBuild(uint16_t build, TVMVersionStage version) { + this->build = (build << 2) | version; + } + /** + * @brief Set the Version + * + * @param major The major + * @param minor The minor + * @param patch The patch + * @param build The build + * @param ver The stage + */ + void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build, + TVMVersionStage ver) { + this->SetMajor(major); + this->SetMinor(minor); + this->SetPatch(patch); + this->SetBuild(build, ver); + } + /** + * @brief Set the Version + * + * @param major The major + * @param minor The minor + * @param patch The patch + * @param build The build << 2 | (stage & 3) + */ + void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, + uint16_t build) { + this->SetMajor(major); + this->SetMinor(minor); + this->SetPatch(patch); + this->SetBuild(build); + } + /** + * @brief Set the Version + * + * @param major The major + * @param minor The minor + * @param patch The patch + * @param buildHigh The build (high 8 bits) + * @param buildLow The build (low 6 bits) << 2 | (stage & 3) + */ + void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, + uint8_t buildHigh, uint8_t buildLow) { + this->SetVersion(major, minor, patch, buildHigh << 8 | buildLow); + } + /** + * @brief Set the Version + * + * @param versionData same order as SetVersion(uint8_t major, uint8_t minor, + * uint8_t patch, uint8_t buildHigh, uint8_t buildLow) but is a pointer to + * uint8_t version[5] + */ + void SetVersion(uint8_t *versionData) { + this->SetVersion(versionData[0], versionData[1], versionData[2], + versionData[3], versionData[4]); + } + /** + * @brief Set the version from long + * + * @param v version serialized as long + */ + void SetFromLong(uint64_t v) { + + this->major = (uint8_t)((v >> 32) & 0xFF); + this->minor = (uint8_t)(v >> 24) & 0xFF; + this->patch = (uint8_t)(v >> 16) & 0xFF; + this->build = (uint16_t)(v & 0xFFFF); + } + /** + * @brief Encodes the version to bytes to be decoded by SetVersion(uint8_t*) + * or the constructor + * + * @param versionData an array that is 5 bytes long + */ + void ToArray(uint8_t *versionData) { + versionData[0] = major; + versionData[1] = minor; + versionData[2] = patch; + versionData[3] = build >> 8; + versionData[4] = build & 0xFF; + } + /** + * @brief Construct a new Version object + * + * @param major Major + * @param minor Minor + * @param patch Patch + * @param build Build + * @param version Stage (dev, alpha, beta, prod) see TVMVersionStage for + * actual names + */ + TVMVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build, + TVMVersionStage version) { + this->SetVersion(major, minor, patch, build, version); + } + /** + * @brief Construct a new Version object + * + * @param versionData same order as SetVersion(uint8_t major, uint8_t minor, + * uint8_t patch, uint8_t buildHigh, uint8_t buildLow) but is a pointer to + * uint8_t version[5] + */ + TVMVersion(uint8_t *versionData) { this->SetVersion(versionData); } + /** + * @brief Construct a new 1.0.0.0-dev Version object * */ - enum TVMVersionStage : uint8_t - { - DevVersion=0, - AlphaVersion=1, - BetaVersion=2, - ProductionVersion=3 - }; + TVMVersion() { + this->major = 1; + this->minor = 0; + this->patch = 0; + this->SetBuild(0, TVMVersionStage::DevVersion); + } /** - * @brief CrossLang version + * @brief Construct a new Version object from a long * + * @param v version serialized as long */ - class TVMVersion - { - uint8_t major; - uint8_t minor; - uint8_t patch; - uint16_t build; - public: - /** - * @brief Major - * - * @return uint8_t The major - */ - uint8_t Major() - { - return major; - } - /** - * @brief Minor - * - * @return uint8_t The minor - */ - uint8_t Minor() - { - return minor; - } - /** - * @brief Patch - * - * @return uint8_t The patch - */ - uint8_t Patch() - { - return patch; - } - /** - * @brief Build - * - * @return uint16_t The build - */ - uint16_t Build() - { - return build >> 2; - } - /** - * @brief Stage (dev, alpha, beta or prod) - * - * @return TVMVersionStage The stage - */ - TVMVersionStage VersionStage() - { - return (TVMVersionStage)(build & 3); - } - /** - * @brief Set the Major - * - * @param major The major - */ - void SetMajor(uint8_t major) - { - this->major=major; - } - /** - * @brief Set the Minor - * - * @param minor The minor - */ - void SetMinor(uint8_t minor) - { - this->minor=minor; - } - /** - * @brief Set the Patch - * - * @param patch The patch - */ - void SetPatch(uint8_t patch) - { - this->patch=patch; - } - /** - * @brief Set the Build - * - * @param build The build << 2 | (stage & 3) - */ - void SetBuild(uint16_t build) - { - this->build = build; - } - /** - * @brief Set the Build (and stage) - * - * @param build - * @param version - */ - void SetBuild(uint16_t build,TVMVersionStage version) - { - this->build = (build << 2) | version; - } - /** - * @brief Set the Version - * - * @param major The major - * @param minor The minor - * @param patch The patch - * @param build The build - * @param ver The stage - */ - void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build, TVMVersionStage ver) - { - this->SetMajor(major); - this->SetMinor(minor); - this->SetPatch(patch); - this->SetBuild(build,ver); - } - /** - * @brief Set the Version - * - * @param major The major - * @param minor The minor - * @param patch The patch - * @param build The build << 2 | (stage & 3) - */ - void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build) - { - this->SetMajor(major); - this->SetMinor(minor); - this->SetPatch(patch); - this->SetBuild(build); - } - /** - * @brief Set the Version - * - * @param major The major - * @param minor The minor - * @param patch The patch - * @param buildHigh The build (high 8 bits) - * @param buildLow The build (low 6 bits) << 2 | (stage & 3) - */ - void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint8_t buildHigh, uint8_t buildLow) - { - this->SetVersion(major, minor, patch, buildHigh << 8 | buildLow); - } - /** - * @brief Set the Version - * - * @param versionData same order as SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint8_t buildHigh, uint8_t buildLow) but is a pointer to uint8_t version[5] - */ - void SetVersion(uint8_t* versionData) - { - this->SetVersion(versionData[0],versionData[1],versionData[2],versionData[3],versionData[4]); - } - /** - * @brief Set the version from long - * - * @param v version serialized as long - */ - void SetFromLong(uint64_t v) - { - - this->major = (uint8_t)((v >> 32) & 0xFF); - this->minor = (uint8_t)(v >> 24) & 0xFF; - this->patch = (uint8_t)(v >> 16) & 0xFF; - this->build = (uint16_t)(v & 0xFFFF); - } - /** - * @brief Encodes the version to bytes to be decoded by SetVersion(uint8_t*) or the constructor - * - * @param versionData an array that is 5 bytes long - */ - void ToArray(uint8_t* versionData) - { - versionData[0] = major; - versionData[1] = minor; - versionData[2] = patch; - versionData[3] = build >> 8; - versionData[4] = build & 0xFF; - } - /** - * @brief Construct a new Version object - * - * @param major Major - * @param minor Minor - * @param patch Patch - * @param build Build - * @param version Stage (dev, alpha, beta, prod) see TVMVersionStage for actual names - */ - TVMVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build, TVMVersionStage version) - { - this->SetVersion(major,minor,patch,build,version); - } - /** - * @brief Construct a new Version object - * - * @param versionData same order as SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint8_t buildHigh, uint8_t buildLow) but is a pointer to uint8_t version[5] - */ - TVMVersion(uint8_t* versionData) - { - this->SetVersion(versionData); - } - /** - * @brief Construct a new 1.0.0.0-dev Version object - * - */ - TVMVersion() - { - this->major=1; - this->minor=0; - this->patch=0; - this->SetBuild(0, TVMVersionStage::DevVersion); - } - /** - * @brief Construct a new Version object from a long - * - * @param v version serialized as long - */ - TVMVersion(uint64_t v) - { - this->SetFromLong(v); - } - /** - * @brief Compares to another version - * - * @param version another version object - * @return int returns 1 if this is newer than other version, 0 if same, -1 if this is older than other version - */ - int CompareTo(TVMVersion& version) - { - if(this->major > version.major) return 1; - if(this->major < version.major) return -1; - if(this->minor > version.minor) return 1; - if(this->minor < version.minor) return -1; - if(this->patch > version.patch) return 1; - if(this->patch < version.patch) return -1; - if(this->build > version.build) return 1; - if(this->build < version.build) return -1; - return 0; - } - /** - * @brief Serializes to a long - * - * @return uint64_t serialized as a long - */ - uint64_t AsLong() - { - uint64_t v = (uint64_t)major << 32; - v |= (uint64_t)minor << 24; - v |= (uint64_t)patch << 16; - v |= (uint64_t)build; - return v; - } - /** - * @brief Compares this to the runtime version (for Bytecode) - * - * @return int CompareTo(RuntimeVersion) where RuntimeVersion is the runtime version - */ - int CompareToRuntime() - { - TVMVersion version(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE); - return CompareTo(version); - } - /** - * @brief Try to parse the version from a string - * - * @param versionStr the version string like 1.0.0.0-prod (or dev, alpha, beta) - * @param version a reference to a version - * @return true the parsing succeeded - * @return false the parsing failed - */ - static bool TryParse(std::string versionStr, TVMVersion& version) - { - if(versionStr.empty()) return false; - size_t sep=versionStr.find_last_of('-'); - - std::string left = versionStr; - std::string right = "prod"; - - if(sep != std::string::npos) - { - left = versionStr.substr(0, sep); - right = versionStr.substr(sep+1); - } - - if(left.empty()) return false; - - - - TVMVersionStage stage; - if(right == "dev") - stage = TVMVersionStage::DevVersion; - else if(right == "alpha") - stage = TVMVersionStage::AlphaVersion; - else if(right == "beta") - stage = TVMVersionStage::BetaVersion; - else if(right == "prod") - stage = TVMVersionStage::ProductionVersion; - else - return false; - - - //1 0.0.0 - sep=left.find_first_of('.'); - - if(sep != std::string::npos) - { - auto lStr = left.substr(0, sep); - - right = left.substr(sep+1); - left = lStr; - } - else - { - version.SetMajor((uint8_t)std::stoul(left)); - version.SetBuild(0,stage); - return true; - } - version.SetMajor((uint8_t)std::stoul(left)); - left = right; - sep=left.find_first_of('.'); - - if(sep != std::string::npos) - { - auto lStr = left.substr(0, sep); - - right = left.substr(sep+1); - left = lStr; - } - else - { - version.SetMinor((uint8_t)std::stoul(left)); - version.SetBuild(0,stage); - return true; - } - version.SetMinor((uint8_t)std::stoul(left)); - left = right; - sep=left.find_first_of('.'); - - if(sep != std::string::npos) - { - auto lStr = left.substr(0, sep); - - right = left.substr(sep+1); - left = lStr; - } - else - { - version.SetPatch((uint8_t)std::stoul(left)); - version.SetBuild(0,stage); - return true; - } - version.SetPatch((uint8_t)std::stoul(left)); - - version.SetBuild((uint16_t)std::stoul(right),stage); - return true; - - } - /** - * @brief Converts version to string - * - * @return std::string the version string like 1.0.0.0-prod (or dev, alpha, beta) - */ - std::string ToString() - { - std::string str={}; - str.append(std::to_string((int)this->Major())); - str.push_back('.'); - str.append(std::to_string((int)this->Minor())); - str.push_back('.'); - str.append(std::to_string((int)this->Patch())); - str.push_back('.'); - str.append(std::to_string((int)this->Build())); - if(this->VersionStage() == TVMVersionStage::DevVersion) - { - str.append("-dev"); - } - else if(this->VersionStage() == TVMVersionStage::AlphaVersion) - { - str.append("-alpha"); - } - else if(this->VersionStage() == TVMVersionStage::BetaVersion) - { - str.append("-beta"); - } - else if(this->VersionStage() == TVMVersionStage::ProductionVersion) - { - str.append("-prod"); - } - return str; - } - }; - + TVMVersion(uint64_t v) { this->SetFromLong(v); } /** - * @brief Create a crvm archive file + * @brief Compares to another version * - * @param vfs the filesystem used as root of the archive - * @param strm the output stream - * @param name the crvm name - * @param version the crvm version - * @param info the crvm info - * @param icon the crvm icon + * @param version another version object + * @return int returns 1 if this is newer than other version, 0 if same, -1 + * if this is older than other version */ - void CrossArchiveCreate(std::shared_ptr vfs,std::shared_ptr strm,std::string name,TVMVersion version,std::string info, std::string icon=""); + int CompareTo(TVMVersion &version) { + if (this->major > version.major) + return 1; + if (this->major < version.major) + return -1; + if (this->minor > version.minor) + return 1; + if (this->minor < version.minor) + return -1; + if (this->patch > version.patch) + return 1; + if (this->patch < version.patch) + return -1; + if (this->build > version.build) + return 1; + if (this->build < version.build) + return -1; + return 0; + } /** - * @brief + * @brief Serializes to a long * - * @param strm the input stream - * @param vfs vfs to extract to (as root) - * @return std::pair,std::string> ((name, version),info) + * @return uint64_t serialized as a long */ - std::pair,std::string> CrossArchiveExtract(std::shared_ptr strm,std::shared_ptr vfs); + uint64_t AsLong() { + uint64_t v = (uint64_t)major << 32; + v |= (uint64_t)minor << 24; + v |= (uint64_t)patch << 16; + v |= (uint64_t)build; + return v; + } + /** + * @brief Compares this to the runtime version (for Bytecode) + * + * @return int CompareTo(RuntimeVersion) where RuntimeVersion is the runtime + * version + */ + int CompareToRuntime() { + TVMVersion version(CROSSLANG_BYTECODE_MAJOR, CROSSLANG_BYTECODE_MINOR, + CROSSLANG_BYTECODE_PATCH, CROSSLANG_BYTECODE_BUILD, + CROSSLANG_BYTECODE_VERSIONSTAGE); + return CompareTo(version); + } + /** + * @brief Try to parse the version from a string + * + * @param versionStr the version string like 1.0.0.0-prod (or dev, alpha, + * beta) + * @param version a reference to a version + * @return true the parsing succeeded + * @return false the parsing failed + */ + static bool TryParse(std::string versionStr, TVMVersion &version) { + if (versionStr.empty()) + return false; + size_t sep = versionStr.find_last_of('-'); + std::string left = versionStr; + std::string right = "prod"; + if (sep != std::string::npos) { + left = versionStr.substr(0, sep); + right = versionStr.substr(sep + 1); + } + + if (left.empty()) + return false; + + TVMVersionStage stage; + if (right == "dev") + stage = TVMVersionStage::DevVersion; + else if (right == "alpha") + stage = TVMVersionStage::AlphaVersion; + else if (right == "beta") + stage = TVMVersionStage::BetaVersion; + else if (right == "prod") + stage = TVMVersionStage::ProductionVersion; + else + return false; + + // 1 0.0.0 + sep = left.find_first_of('.'); + + if (sep != std::string::npos) { + auto lStr = left.substr(0, sep); + + right = left.substr(sep + 1); + left = lStr; + } else { + version.SetMajor((uint8_t)std::stoul(left)); + version.SetBuild(0, stage); + return true; + } + version.SetMajor((uint8_t)std::stoul(left)); + left = right; + sep = left.find_first_of('.'); + + if (sep != std::string::npos) { + auto lStr = left.substr(0, sep); + + right = left.substr(sep + 1); + left = lStr; + } else { + version.SetMinor((uint8_t)std::stoul(left)); + version.SetBuild(0, stage); + return true; + } + version.SetMinor((uint8_t)std::stoul(left)); + left = right; + sep = left.find_first_of('.'); + + if (sep != std::string::npos) { + auto lStr = left.substr(0, sep); + + right = left.substr(sep + 1); + left = lStr; + } else { + version.SetPatch((uint8_t)std::stoul(left)); + version.SetBuild(0, stage); + return true; + } + version.SetPatch((uint8_t)std::stoul(left)); + + version.SetBuild((uint16_t)std::stoul(right), stage); + return true; + } + /** + * @brief Converts version to string + * + * @return std::string the version string like 1.0.0.0-prod (or dev, alpha, + * beta) + */ + std::string ToString() { + std::string str = {}; + str.append(std::to_string((int)this->Major())); + str.push_back('.'); + str.append(std::to_string((int)this->Minor())); + str.push_back('.'); + str.append(std::to_string((int)this->Patch())); + str.push_back('.'); + str.append(std::to_string((int)this->Build())); + if (this->VersionStage() == TVMVersionStage::DevVersion) { + str.append("-dev"); + } else if (this->VersionStage() == TVMVersionStage::AlphaVersion) { + str.append("-alpha"); + } else if (this->VersionStage() == TVMVersionStage::BetaVersion) { + str.append("-beta"); + } else if (this->VersionStage() == TVMVersionStage::ProductionVersion) { + str.append("-prod"); + } + return str; + } +}; + +/** + * @brief Create a crvm archive file + * + * @param vfs the filesystem used as root of the archive + * @param strm the output stream + * @param name the crvm name + * @param version the crvm version + * @param info the crvm info + * @param icon the crvm icon + */ +void CrossArchiveCreate( + std::shared_ptr vfs, + std::shared_ptr strm, std::string name, + TVMVersion version, std::string info, std::string icon = ""); +/** + * @brief + * + * @param strm the input stream + * @param vfs vfs to extract to (as root) + * @return std::pair,std::string> ((name, + * version),info) + */ +std::pair, std::string> +CrossArchiveExtract(std::shared_ptr strm, + std::shared_ptr vfs); /** * @brief The token type for lexer * */ -typedef enum { - Identifier, - Symbol, - String, - Char, - Documentation -} LexTokenType; +typedef enum { Identifier, Symbol, String, Char, Documentation } LexTokenType; +/** + * @brief The line info for lextoken + * + */ +class LexTokenLineInfo { + public: /** - * @brief The line info for lextoken + * @brief line number * */ - class LexTokenLineInfo - { - public: - /** - * @brief line number - * - */ - int line; - /** - * @brief column number - * - */ - int column; - /** - * @brief byte offset in file - * - */ - int offset; - /** - * @brief filename - * - */ - std::string filename; - /** - * @brief Add a char - * - * @param c a char to add to line, column, offset - */ - void Add(int c); - /** - * @brief Subtract from column and offset - * - * @param c the number of chars - */ - void Subtract(size_t c); - }; + int line; + /** + * @brief column number + * + */ + int column; + /** + * @brief byte offset in file + * + */ + int offset; + /** + * @brief filename + * + */ + std::string filename; + /** + * @brief Add a char + * + * @param c a char to add to line, column, offset + */ + void Add(int c); + /** + * @brief Subtract from column and offset + * + * @param c the number of chars + */ + void Subtract(size_t c); +}; +/** + * @brief The lextoken for lexer + * + */ +class LexToken { + public: /** - * @brief The lextoken for lexer + * @brief line information * */ - class LexToken { - public: - /** - * @brief line information - * - */ - LexTokenLineInfo lineInfo; - /** - * @brief the token type - * - */ - LexTokenType type; - /** - * @brief the token text - * - */ - std::string text; - /** - * @brief any white space characters before this token - * - */ - std::string whiteSpaceCharsBefore; - }; + LexTokenLineInfo lineInfo; /** - * @brief Start lexing the file + * @brief the token type * - * @param filename the filename used for exception purposes - * @param strm the character stream - * @param tokens the tokens - * @return int 0 on success, line number on failure */ - int Lex(std::string filename, std::istream& strm, std::vector& tokens); + LexTokenType type; + /** + * @brief the token text + * + */ + std::string text; + /** + * @brief any white space characters before this token + * + */ + std::string whiteSpaceCharsBefore; +}; +/** + * @brief Start lexing the file + * + * @param filename the filename used for exception purposes + * @param strm the character stream + * @param tokens the tokens + * @return int 0 on success, line number on failure + */ +int Lex(std::string filename, std::istream &strm, + std::vector &tokens); using Undefined = std::monostate; class AdvancedSyntaxNode; @@ -649,150 +601,152 @@ typedef enum { DECLARECONSTVARIABLE, LINEINFO, PUSHRESOURCESTREAM, - PUSHRESOUURCEDIR + PUSHRESOUURCEDIR, + PUSHPRIVATEXPRESSION } Instruction; /** * @brief Base type for bytecode instruction * */ class ByteCodeInstruction { - public: - /** - * @brief Size of instruction - * - * @return size_t the length of the instruction - */ - virtual size_t Size()=0; - /** - * @brief Write the instruction to vector - * - * @param data the vector of uint8_t - */ - virtual void Write(std::vector& data)=0; - virtual ~ByteCodeInstruction() - {} + public: + /** + * @brief Size of instruction + * + * @return size_t the length of the instruction + */ + virtual size_t Size() = 0; + /** + * @brief Write the instruction to vector + * + * @param data the vector of uint8_t + */ + virtual void Write(std::vector &data) = 0; + virtual ~ByteCodeInstruction() {} }; /** * @brief Basic bytecode instruction * */ class SimpleInstruction : public ByteCodeInstruction { - public: - /** - * @brief The instruction - * - */ - Instruction instruction; - /** - * @brief Construct a new Simple Instruction object - * - * @param instr the instruction - */ - SimpleInstruction(Instruction instr); - /** - * @brief Size of instruction - * - * @return size_t 1, because simple instructions are just an instruction - */ - size_t Size(); - /** - * @brief Write the opcode to the vector - * - * @param data the vector of uint8_t - */ - void Write(std::vector& data); + public: + /** + * @brief The instruction + * + */ + Instruction instruction; + /** + * @brief Construct a new Simple Instruction object + * + * @param instr the instruction + */ + SimpleInstruction(Instruction instr); + /** + * @brief Size of instruction + * + * @return size_t 1, because simple instructions are just an instruction + */ + size_t Size(); + /** + * @brief Write the opcode to the vector + * + * @param data the vector of uint8_t + */ + void Write(std::vector &data); }; class StringInstruction : public ByteCodeInstruction { - public: - uint32_t n; - StringInstruction(uint32_t n); - size_t Size(); - void Write(std::vector& data); + public: + uint32_t n; + StringInstruction(uint32_t n); + size_t Size(); + void Write(std::vector &data); }; class ScopeEndTimesInstruction : public ByteCodeInstruction { - public: - uint32_t n; - ScopeEndTimesInstruction(uint32_t n); - size_t Size(); - void Write(std::vector& data); + public: + uint32_t n; + ScopeEndTimesInstruction(uint32_t n); + size_t Size(); + void Write(std::vector &data); }; class LabelInstruction : public ByteCodeInstruction { - public: - std::string label; - LabelInstruction(std::string lbl); - size_t Size(); - void Write(std::vector& data); + public: + std::string label; + LabelInstruction(std::string lbl); + size_t Size(); + void Write(std::vector &data); }; class LabelableInstruction : public ByteCodeInstruction { - public: - uint32_t n; - std::string label; - virtual size_t Size(); - virtual void Write(std::vector& data); + public: + uint32_t n; + std::string label; + virtual size_t Size(); + virtual void Write(std::vector &data); }; class JumpStyleInstruction : public LabelableInstruction { - public: - Instruction type; + public: + Instruction type; - JumpStyleInstruction(Instruction conditional,std::string label); - size_t Size(); - void Write(std::vector& data); + JumpStyleInstruction(Instruction conditional, std::string label); + size_t Size(); + void Write(std::vector &data); }; class EmbedInstruction : public ByteCodeInstruction { - public: - uint32_t n; - EmbedInstruction(uint32_t n); - size_t Size(); - void Write(std::vector& data); + public: + uint32_t n; + EmbedInstruction(uint32_t n); + size_t Size(); + void Write(std::vector &data); }; class EmbedStreamInstruction : public ByteCodeInstruction { - public: - uint32_t n; - EmbedStreamInstruction(uint32_t n); - size_t Size(); - void Write(std::vector& data); + public: + uint32_t n; + EmbedStreamInstruction(uint32_t n); + size_t Size(); + void Write(std::vector &data); }; class ClosureInstruction : public ByteCodeInstruction { - public: - bool hasScope; - uint32_t n; - ClosureInstruction(uint32_t n,bool hasScope=true); - size_t Size(); - void Write(std::vector& data); + public: + bool hasScope; + uint32_t n; + ClosureInstruction(uint32_t n, bool hasScope = true); + size_t Size(); + void Write(std::vector &data); }; class DoubleInstruction : public ByteCodeInstruction { - public: - double n; - DoubleInstruction(double n); - size_t Size(); - void Write(std::vector& data); + public: + double n; + DoubleInstruction(double n); + size_t Size(); + void Write(std::vector &data); }; class LongInstruction : public ByteCodeInstruction { - public: - int64_t n; - LongInstruction(int64_t n); - size_t Size(); - void Write(std::vector& data); + public: + int64_t n; + LongInstruction(int64_t n); + size_t Size(); + void Write(std::vector &data); }; class CharInstruction : public ByteCodeInstruction { - public: - char n; - CharInstruction(char n); - size_t Size(); - void Write(std::vector& data); + public: + char n; + CharInstruction(char n); + size_t Size(); + void Write(std::vector &data); }; -using SyntaxNode = std::variant, AdvancedSyntaxNode,std::shared_ptr,std::shared_ptr>; - - +using SyntaxNode = + std::variant, AdvancedSyntaxNode, + std::shared_ptr, + std::shared_ptr>; struct CodeGenClassEntry { uint8_t type; @@ -810,42 +764,44 @@ struct CodeGenClass { }; class ResourceBase { - public: - virtual uint32_t GetLength(std::shared_ptr embedFS)=0; - virtual void Write(std::shared_ptr output)=0; - virtual ~ResourceBase(); - virtual bool IsEqual(ResourceBase* base); + public: + virtual uint32_t + GetLength(std::shared_ptr embedFS) = 0; + virtual void + Write(std::shared_ptr output) = 0; + virtual ~ResourceBase(); + virtual bool IsEqual(ResourceBase *base); }; -class ResourceFile : public ResourceBase -{ - std::shared_ptr strm=nullptr; - public: - ResourceFile(); - ResourceFile(std::string file); - std::string file; - uint32_t GetLength(std::shared_ptr embedFS); - void Write(std::shared_ptr output); - bool IsEqual(ResourceBase* base); - ~ResourceFile(); +class ResourceFile : public ResourceBase { + std::shared_ptr strm = nullptr; + + public: + ResourceFile(); + ResourceFile(std::string file); + std::string file; + uint32_t + GetLength(std::shared_ptr embedFS); + void Write(std::shared_ptr output); + bool IsEqual(ResourceBase *base); + ~ResourceFile(); }; -class ResourceByteArray : public ResourceBase -{ - public: - std::vector data; - uint32_t GetLength(std::shared_ptr embedFS); - void Write(std::shared_ptr output); +class ResourceByteArray : public ResourceBase { + public: + std::vector data; + uint32_t + GetLength(std::shared_ptr embedFS); + void Write(std::shared_ptr output); }; - class CodeGen { uint32_t id; uint32_t NewId(); - void GetFunctionArgs(std::vector& args,SyntaxNode n); - void GetFunctionName(std::vector& name,SyntaxNode n); - void GetFunctionArgs(std::vector& args,SyntaxNode n); + void GetFunctionArgs(std::vector &args, SyntaxNode n); + void GetFunctionName(std::vector &name, SyntaxNode n); + void GetFunctionArgs(std::vector &args, SyntaxNode n); SyntaxNode StringifyListOfVars(SyntaxNode n); uint32_t GetString(std::string str); @@ -853,26 +809,31 @@ class CodeGen { std::vector strs; std::vector> res; - std::vector, std::vector>> chunks; - std::vector,uint32_t>> funcs; + std::vector< + std::pair, std::vector>> + chunks; + std::vector, uint32_t>> funcs; std::vector classes; std::vector> meta; SyntaxNode OptimizeNode(SyntaxNode n); - void WriteMetadataObject(std::vector& bytes, SyntaxNode n); - void GenNode(std::vector& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI); - void GenPop(std::vector& instrs,SyntaxNode n); - public: - std::shared_ptr embedFS; - std::vector> dependencies; - std::vector> tools; - TVMVersion version; - std::string name; - std::string info; - std::string icon; - void GenRoot(SyntaxNode n); - void Save(std::shared_ptr output); - ~CodeGen(); + void WriteMetadataObject(std::vector &bytes, SyntaxNode n); + void GenNode(std::vector &instructions, SyntaxNode n, + int32_t scope, int32_t contscope, int32_t brkscope, + int32_t contI, int32_t brkI); + void GenPop(std::vector &instrs, SyntaxNode n); + + public: + std::shared_ptr embedFS; + std::vector> dependencies; + std::vector> tools; + TVMVersion version; + std::string name; + std::string info; + std::string icon; + void GenRoot(SyntaxNode n); + void Save(std::shared_ptr output); + ~CodeGen(); }; /** * @brief A html expression @@ -880,20 +841,24 @@ class CodeGen { */ constexpr std::string_view HtmlRootExpression = "htmlRootExpression"; /** - * @brief an intrinsic function that embeds a resource from the filename based on the constant string argument + * @brief an intrinsic function that embeds a resource from the filename based + * on the constant string argument * */ constexpr std::string_view EmbedExpression = "embedExpression"; /** - * @brief an intrinsic function that embeds a resource as a stream from the filename based on the constant string argument + * @brief an intrinsic function that embeds a resource as a stream from the + * filename based on the constant string argument * */ constexpr std::string_view EmbedStreamExpression = "embedStreamExpression"; /** - * @brief an intrinsic function that embeds a resource directory from the directory name based on the constant string argument + * @brief an intrinsic function that embeds a resource directory from the + * directory name based on the constant string argument * */ -constexpr std::string_view EmbedDirectoryExpression = "embedDirectoryExpression"; +constexpr std::string_view EmbedDirectoryExpression = + "embedDirectoryExpression"; /** * @brief Negative operator -EXPR * @@ -913,34 +878,40 @@ constexpr std::string_view BitwiseNotExpression = "bitwiseNotExpression"; * @brief ++i * */ -constexpr std::string_view PrefixIncrementExpression = "prefixIncrementExpression"; +constexpr std::string_view PrefixIncrementExpression = + "prefixIncrementExpression"; /** * @brief --i * */ -constexpr std::string_view PrefixDecrementExpression = "prefixDecrementExpression"; +constexpr std::string_view PrefixDecrementExpression = + "prefixDecrementExpression"; /** * @brief i++ * */ -constexpr std::string_view PostfixIncrementExpression = "postfixIncrementExpression"; +constexpr std::string_view PostfixIncrementExpression = + "postfixIncrementExpression"; /** * @brief i-- * */ -constexpr std::string_view PostfixDecrementExpression = "postfixDecrementExpression"; +constexpr std::string_view PostfixDecrementExpression = + "postfixDecrementExpression"; /** * @brief Gets variable value * */ constexpr std::string_view GetVariableExpression = "getVariableExpression"; /** - * @brief Get field or get property (EXPR.getNAME()) (unless it is wrapped in AssignExpression) which then it sets the field or calls EXPR.setNAME(VALUE) + * @brief Get field or get property (EXPR.getNAME()) (unless it is wrapped in + * AssignExpression) which then it sets the field or calls EXPR.setNAME(VALUE) * */ constexpr std::string_view GetFieldExpression = "getFieldExpression"; /** - * @brief Syntax sugar for EXPR.GetAt(index) (unless it is wrapped in AssignExpresion) which then it is EXPR.SetAt(index, VALUE) + * @brief Syntax sugar for EXPR.GetAt(index) (unless it is wrapped in + * AssignExpresion) which then it is EXPR.SetAt(index, VALUE) * */ constexpr std::string_view GetArrayExpression = "getArrayExpression"; @@ -953,7 +924,8 @@ constexpr std::string_view FunctionCallExpression = "functionCallExpression"; * @brief Used for compound assignment like VAR += EXPR * */ -constexpr std::string_view CompoundAssignExpression = "compoundAssignExpression"; +constexpr std::string_view CompoundAssignExpression = + "compoundAssignExpression"; /** * @brief Assign something using = * @@ -1009,7 +981,8 @@ constexpr std::string_view ClosureExpression = "closureExpression"; * @brief Just like normal closures but doesn't create its own scope * */ -constexpr std::string_view ScopelessClosureExpression = "scopelessClosureExpression"; +constexpr std::string_view ScopelessClosureExpression = + "scopelessClosureExpression"; /** * @brief Ternary operator COND ? EXPR : EXPR * @@ -1159,12 +1132,14 @@ constexpr std::string_view GreaterThanExpression = "greaterThanExpression"; * @brief The less than equals expression EXPR <= EXPR * */ -constexpr std::string_view LessThanEqualsExpression = "lessThanEqualsExpression"; +constexpr std::string_view LessThanEqualsExpression = + "lessThanEqualsExpression"; /** * @brief The greater than equals expression EXPR >= EXPR * */ -constexpr std::string_view GreaterThanEqualsExpression = "greaterThanEqualsExpression"; +constexpr std::string_view GreaterThanEqualsExpression = + "greaterThanEqualsExpression"; /** * @brief The parentheses expression (expression) * @@ -1240,7 +1215,8 @@ constexpr std::string_view FieldStatement = "fieldStatement"; */ constexpr std::string_view RootPathExpression = "rootPathExpression"; /** - * @brief The relative path expression ./ "path" / "to" / "subdir" (fullfills the ./) + * @brief The relative path expression ./ "path" / "to" / "subdir" (fullfills + * the ./) * */ constexpr std::string_view RelativePathExpression = "relativePathExpression"; @@ -1251,50 +1227,54 @@ constexpr std::string_view AwaitExpression = "awaitExpression"; /** * @brief ?? operator */ -constexpr std::string_view NullCoalescingExpression = "nullCoalescingExpression"; +constexpr std::string_view NullCoalescingExpression = + "nullCoalescingExpression"; /** * @brief For debugging (store line info and filename) */ -constexpr std::string_view LineNode="lineNode"; +constexpr std::string_view LineNode = "lineNode"; /** * @brief For storing generic metadata */ constexpr std::string_view MetadataStatement = "MetadataStatement"; - +/** + * @brief For storing private data (isolated to specific crvm file) + */ +constexpr std::string_view GetPrivateExpression = "getPrivateExpression"; /** * @brief Advanced AST node * */ class AdvancedSyntaxNode { - public: - /** - * @brief The name of the advanced AST node - * - */ - std::string nodeName; - /** - * @brief The advanced syntax node is an expression - * - */ - bool isExpression; - /** - * @brief The subnodes of the abstract syntax node - * - */ - std::vector nodes; - /** - * @brief Create abstract syntax node - * - * @param nodeName The name of the advanced AST node - * @param isExpression The advanced syntax node is an expression - * @param n The subnodes of the abstract syntax node - * @return AdvancedSyntaxNode The AST node - */ - static AdvancedSyntaxNode Create(std::string_view nodeName,bool isExpression, std::vector n); + public: + /** + * @brief The name of the advanced AST node + * + */ + std::string nodeName; + /** + * @brief The advanced syntax node is an expression + * + */ + bool isExpression; + /** + * @brief The subnodes of the abstract syntax node + * + */ + std::vector nodes; + /** + * @brief Create abstract syntax node + * + * @param nodeName The name of the advanced AST node + * @param isExpression The advanced syntax node is an expression + * @param n The subnodes of the abstract syntax node + * @return AdvancedSyntaxNode The AST node + */ + static AdvancedSyntaxNode Create(std::string_view nodeName, + bool isExpression, + std::vector n); }; - - SyntaxNode Deserialize(std::string astData); std::string Serialize(SyntaxNode node); @@ -1312,14 +1292,16 @@ class Parser { LexToken tkn; void EnsureSymbol(std::string txt); - bool IsIdentifier(std::string txt,bool pop=true); - bool IsAnyIdentifier(std::initializer_list idents, bool pop=true); - bool IsSymbol(std::string txt,bool pop=true); - bool IsAnySymbol(std::initializer_list idents, bool pop=true); + bool IsIdentifier(std::string txt, bool pop = true); + bool IsAnyIdentifier(std::initializer_list idents, + bool pop = true); + bool IsSymbol(std::string txt, bool pop = true); + bool IsAnySymbol(std::initializer_list idents, + bool pop = true); SyntaxNode ParseExpression(); SyntaxNode ParseTernary(); - SyntaxNode ParseNode(bool isRoot=false); + SyntaxNode ParseNode(bool isRoot = false); SyntaxNode ParseAssignment(); SyntaxNode ParseXOr(); SyntaxNode ParseBOr(); @@ -1334,1335 +1316,1329 @@ class Parser { SyntaxNode ParseValue(); SyntaxNode ParseUnary(); SyntaxNode ParseNullCoalescing(); - void ParseHtml(std::vector& nodes,std::string var); + void ParseHtml(std::vector &nodes, std::string var); std::shared_ptr gc; - TRootEnvironment* env; - int lastLine=-1; - std::string lastFile=""; - bool CanEmit(LexTokenLineInfo& token); - public: - bool debug=true; - /** - * @brief Construct a new Parser object - * - * @param tokens the tokens from lexer - */ - Parser(std::vector tokens); - Parser(std::vector tokens, std::shared_ptr gc, TRootEnvironment* env); - /** - * @brief Turn tokens into abstract syntax tree - * - * @return SyntaxNode the abstract syntax tree - */ - SyntaxNode ParseRoot() - { - return ParseNode(true); - } -}; - class THeapObject; - class CallStackEntry; - class InterperterThread; - class THeapObject { - public: - bool marked; - virtual void Mark() - { - marked = true; - } + TRootEnvironment *env; + int lastLine = -1; + std::string lastFile = ""; + bool CanEmit(LexTokenLineInfo &token); - virtual ~THeapObject() - { - - } - - - }; - - - class THeapObjectHolder - { - public: - THeapObject* obj; - THeapObjectHolder(THeapObject* obj) - { - this->obj = obj; - } - THeapObjectHolder() - { - - } - }; - - - - //this is a dummy type with - class MethodInvoker { - - }; - - -class TBreak { - -}; -class TContinue { - -}; + public: + bool debug = true; /** - * @brief A script object + * @brief Construct a new Parser object * + * @param tokens the tokens from lexer */ + Parser(std::vector tokens); + Parser(std::vector tokens, std::shared_ptr gc, + TRootEnvironment *env); + /** + * @brief Turn tokens into abstract syntax tree + * + * @return SyntaxNode the abstract syntax tree + */ + SyntaxNode ParseRoot() { return ParseNode(true); } +}; +class THeapObject; +class CallStackEntry; +class InterperterThread; +class THeapObject { + public: + bool marked; + virtual void Mark() { marked = true; } -using TObject = std::variant,std::shared_ptr,TBreak,TContinue,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr, std::shared_ptr, Tesses::Framework::Uuid>; + virtual ~THeapObject() {} +}; + +class THeapObjectHolder { + public: + THeapObject *obj; + THeapObjectHolder(THeapObject *obj) { this->obj = obj; } + THeapObjectHolder() {} +}; + +// this is a dummy type with +class MethodInvoker {}; + +class TBreak {}; +class TContinue {}; +/** + * @brief A script object + * + */ + +using TObject = + std::variant, + std::shared_ptr, TBreak, + TContinue, std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + Tesses::Framework::Uuid>; class TRootEnvironment; class GC : public std::enable_shared_from_this { - Tesses::Framework::Threading::Thread* thrd; - Tesses::Framework::Threading::Mutex* mtx; + Tesses::Framework::Threading::Thread *thrd; + Tesses::Framework::Threading::Mutex *mtx; volatile std::atomic running; - std::vector roots; - std::vector objects; + std::vector roots; + std::vector objects; - Tesses::Framework::Lazy* tpool; - std::vector gc, TRootEnvironment* env)>> register_everything; - public: - Tesses::Framework::Threading::ThreadPool* GetPool(); - bool UsingNullThreads(); - GC(); - void Start(); - bool IsRunning(); - void BarrierBegin(); - void BarrierEnd(); - void Collect(); - void Watch(TObject obj); - void Unwatch(TObject obj); - void SetRoot(TObject obj); - void UnsetRoot(TObject obj); - static void Mark(TObject obj); - void RegisterEverythingCallback(std::function gc, TRootEnvironment* env)> cb); - void RegisterEverything(TRootEnvironment* env); - ~GC(); + Tesses::Framework::Lazy *tpool; + std::vector< + std::function gc, TRootEnvironment *env)>> + register_everything; + + public: + Tesses::Framework::Threading::ThreadPool *GetPool(); + bool UsingNullThreads(); + GC(); + void Start(); + bool IsRunning(); + void BarrierBegin(); + void BarrierEnd(); + void Collect(); + void Watch(TObject obj); + void Unwatch(TObject obj); + void SetRoot(TObject obj); + void UnsetRoot(TObject obj); + static void Mark(TObject obj); + void RegisterEverythingCallback( + std::function gc, TRootEnvironment *env)> cb); + void RegisterEverything(TRootEnvironment *env); + ~GC(); }; - std::string GetObjectTypeString(TObject obj); - std::string ToString(std::shared_ptr gc, TObject obj); +std::string GetObjectTypeString(TObject obj); +std::string ToString(std::shared_ptr gc, TObject obj); - class GCList : public THeapObject - { - std::vector items; +class GCList : public THeapObject { + std::vector items; - std::shared_ptr gc; - public: - GCList(std::shared_ptr gc); - std::shared_ptr GetGC(); - void Add(TObject v); - void Remove(TObject v); - void Mark(); + std::shared_ptr gc; + public: + GCList(std::shared_ptr gc); + std::shared_ptr GetGC(); + void Add(TObject v); + void Remove(TObject v); + void Mark(); - - ~GCList(); - friend class GC; - }; - - - - - - class TFile; - - class TFileChunk : public THeapObject - { - public: - static TFileChunk* Create(GCList* gc); - static TFileChunk* Create(GCList& gc); - TFile* file; - std::vector code; - std::vector args; - std::optional name; - void Mark(); - }; - - - - - class TByteArray : public THeapObject - { - public: - std::vector data; - static TByteArray* Create(GCList* gc); - static TByteArray* Create(GCList& gc); - }; - enum class TClassModifier { - Private, - Protected, - Public, - Static - }; - class TClassEntry { - public: - - TClassModifier modifier; - bool isFunction; - bool isAbstract; - std::vector args; - std::string documentation; - std::string name; - - uint32_t chunkId; - }; - class TClass { - public: - std::string documentation; - std::vector name; - std::vector inherits; - std::vector entry; - - }; - class TClassObjectEntry { - public: - TClassModifier modifier; - bool canSet; - std::string name; - std::string owner; - TObject value; - - }; - class TDictionary; - class TFile : public THeapObject - { - public: - - static TFile* Create(GCList* gc); - static TFile* Create(GCList& gc); - std::vector chunks; - - std::vector strings; - std::vector> vms; - std::vector, uint32_t>> functions; - std::vector> dependencies; - std::vector> tools; - std::vector>> sections; - std::vector>> metadata; - std::vector> resources; - std::vector classes; - std::string name; - TVMVersion version; - std::string info; - int32_t icon; - - void Load(std::shared_ptr gc, std::shared_ptr strm); - void Skip(std::shared_ptr strm,size_t len); - void Ensure(std::shared_ptr strm,uint8_t* buffer, size_t len); - uint32_t EnsureInt(std::shared_ptr strm); - std::string EnsureString(std::shared_ptr strm); - - std::string GetString(std::shared_ptr strm); - void Mark(); - - void EnsureCanRunInCrossLang(); - - TDictionary* MetadataDecode(GCList& ls, size_t index); - }; - class TAssociativeArray : public THeapObject - { - public: - std::vector> items; - static TAssociativeArray* Create(GCList& ls); - static TAssociativeArray* Create(GCList* ls); - void Set(std::shared_ptr gc, TObject key, TObject value); - TObject Get(std::shared_ptr gc, TObject key); - TObject GetKey(int64_t index); - TObject GetValue(int64_t index); - void SetKey(int64_t index, TObject key); - void SetValue(int64_t index,TObject value); - int64_t Count(); - void Mark(); - }; - - - class TList : public THeapObject - { - public: - std::vector items; - static TList* Create(GCList* gc); - static TList* Create(GCList& gc); - template - static TList* Create(GCList* gc, Itterator begin, Itterator end) - { - auto list = Create(gc); - gc->GetGC()->BarrierBegin(); - for(Itterator i = begin; i != end; ++i) - { - TObject item = *i; - list->Add(item); - } - gc->GetGC()->BarrierEnd(); - return list; - } - template - static TList* Create(GCList& gc, Itterator begin, Itterator end) - { - return Create(&gc,begin,end); - } - static TList* Create(GCList* gc, std::initializer_list il) - { - return Create(gc,il.begin(),il.end()); - } - static TList* Create(GCList& gc, std::initializer_list il) - { - return Create(gc,il.begin(),il.end()); - } - virtual int64_t Count(); - virtual TObject Get(int64_t index); - virtual void Set(int64_t index, TObject value); - virtual void Insert(int64_t index,TObject value); - virtual void Add(TObject value); - virtual void RemoveAt(int64_t index); - virtual void Clear(); - virtual void Mark(); - - }; - using TDItem = std::pair; - class TDictionary : public THeapObject - { - public: - std::map items; - static TDictionary* Create(GCList* gc); - static TDictionary* Create(GCList& gc); - template - static TDictionary* Create(GCList* gc, Itterator begin, Itterator end) - { - auto dict = Create(gc); - gc->GetGC()->BarrierBegin(); - for(Itterator i = begin; i != end; ++i) - { - TDItem item = *i; - dict->SetValue(item.first, item.second); - } - gc->GetGC()->BarrierEnd(); - return dict; - } - template - static TDictionary* Create(GCList& gc, Itterator begin, Itterator end) - { - return Create(&gc,begin,end); - } - - static TDictionary* Create(GCList* gc, std::initializer_list il) - { - return Create(gc,il.begin(),il.end()); - } - static TDictionary* Create(GCList& gc, std::initializer_list il) - { - return Create(gc, il.begin(),il.end()); - } - - - - virtual bool HasValue(std::string key); - virtual bool MethodExists(GCList& ls,std::string key); - virtual TObject GetValue(std::string key); - virtual void SetValue(std::string key, TObject value); - virtual void Mark(); - void DeclareFunction(std::shared_ptr gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb); - void DeclareFunction(std::shared_ptr gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb,std::function destroy); - TObject CallMethod(GCList& ls, std::string key, std::vector args); - TObject CallMethodWithFatalError(GCList& ls, std::string key, std::vector args); - }; - - - - class TRootEnvironment; - class TSubEnvironment; - - class TCallable : public THeapObject - { - public: - TObject tag; - std::string documentation; - virtual TObject Call(GCList& ls,std::vector args)=0; - TObject CallWithFatalError(GCList& ls, std::vector args); - virtual void Mark(); - - Tesses::Framework::Http::ServerRequestHandler ToRouteServerRequestHandler(std::shared_ptr gc); - }; - - void ThrowFatalError(std::exception& ex); - - void ThrowConstError(std::string key); - - class TEnvironment : public THeapObject { - std::vector consts; - public: - std::vector defers; - TObject LoadFile(std::shared_ptr gc, TFile* f); - TObject Eval(GCList& ls,std::string code); - virtual bool HasVariable(std::string key)=0; - virtual bool HasVariableRecurse(std::string key)=0; - - - virtual bool HasVariableOrFieldRecurse(std::string key,bool setting=false)=0; - virtual TObject GetVariable(std::string key)=0; - - virtual TObject GetVariable(GCList& ls, std::string key)=0; - virtual TObject SetVariable(GCList& ls, std::string key, TObject v)=0; - - virtual void SetVariable(std::string key, TObject value)=0; - TDictionary* EnsureDictionary(std::shared_ptr gc, std::string key); - virtual void DeclareVariable(std::string key, TObject value)=0; - void DeclareConstVariable(std::string key, TObject value); - bool HasConstForDeclare(std::string key); - virtual bool HasConstForSet(std::string key); - void DeclareVariable(std::shared_ptr gc,std::vector key, TObject value); - virtual TRootEnvironment* GetRootEnvironment()=0; - virtual TEnvironment* GetParentEnvironment()=0; - virtual TSubEnvironment* GetSubEnvironment(TDictionary* dict); - TSubEnvironment* GetSubEnvironment(GCList* gc); - TSubEnvironment* GetSubEnvironment(GCList& gc); - - void DeclareFunction(std::shared_ptr gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb); - void DeclareFunction(std::shared_ptr gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb,std::function destroy); - TObject CallFunction(GCList& ls, std::string key, std::vector args); - TObject CallFunctionWithFatalError(GCList& ls, std::string key, std::vector args); - }; - class TClassEnvironment; - class TClassObject : public THeapObject - { - TClassObjectEntry* GetEntry(std::string classN, std::string key); - public: - TFile* file; - uint32_t classIndex; - TEnvironment* ogEnv; - TClassEnvironment* env; - std::string name; - std::vector inherit_tree; - std::vector entries; - - static TClassObject* Create(GCList& ls, TFile* f, uint32_t classIndex, TEnvironment* env, std::vector args); - static TClassObject* Create(GCList* ls, TFile* f, uint32_t classIndex, TEnvironment* env, std::vector args); - - TObject GetValue(std::string className, std::string name); - void SetValue(std::string className, std::string name,TObject value); - bool HasValue(std::string className,std::string name); - bool HasField(std::string className,std::string name); - bool HasMethod(std::string className,std::string name); - TObject CallMethod(GCList& ls, std::string className, std::string name,std::vector args); - std::string TypeName(); - void Mark(); - }; - class TClassEnvironment : public TEnvironment - { - TEnvironment* env; - TClassObject* clsObj; - public: - static TClassEnvironment* Create(GCList* gc,TEnvironment* env,TClassObject* obj); - static TClassEnvironment* Create(GCList& gc,TEnvironment* env,TClassObject* obj); - TClassEnvironment(TEnvironment* env,TClassObject* obj); - bool HasVariable(std::string key); - bool HasVariableRecurse(std::string key); - bool HasVariableOrFieldRecurse(std::string key, bool setting=false); - - TObject GetVariable(std::string key); - void SetVariable(std::string key, TObject value); - TObject GetVariable(GCList& ls, std::string key); - TObject SetVariable(GCList& ls, std::string key, TObject v); - - void DeclareVariable(std::string key, TObject value); - bool HasConstForSet(std::string key); - - TRootEnvironment* GetRootEnvironment(); - TEnvironment* GetParentEnvironment(); - - void Mark(); - }; - - - class EnvironmentPermissions { - public: - EnvironmentPermissions(); - Tesses::Framework::Filesystem::VFSPath sqliteOffsetPath; - std::shared_ptr localfs; - bool canRegisterEverything; - bool canRegisterConsole; - bool canRegisterIO; - bool canRegisterNet; - bool canRegisterSqlite; - bool canRegisterVM; - bool canRegisterDictionary; - bool canRegisterJSON; - bool canRegisterCrypto; - bool canRegisterRoot; - bool canRegisterProcess; - bool canRegisterPath; - bool canRegisterOGC; - bool canRegisterEnv; - bool canRegisterClass; - bool sqlite3Scoped; - bool locked; - TDictionary* customConsole =nullptr; - }; - - class TRootEnvironment : public TEnvironment - { - TDictionary* dict; - TCallable* error=nullptr; - - void LoadDependency(std::shared_ptr gc,std::shared_ptr vfs, std::pair dep); - public: - EnvironmentPermissions permissions; - - std::vector> dependencies; - std::vector> classes; - - bool TryFindClass(std::vector& name, size_t& index); - - void LoadFileWithDependencies(std::shared_ptr gc,std::shared_ptr vfs, TFile* f); - void LoadFileWithDependencies(std::shared_ptr gc,std::shared_ptr vfs, Tesses::Framework::Filesystem::VFSPath path); - - TDictionary* GetDictionary(); - static TRootEnvironment* Create(GCList* gc,TDictionary* dict); - static TRootEnvironment* Create(GCList& gc,TDictionary* dict); - TRootEnvironment(TDictionary* dict); - bool HasVariable(std::string key); - bool HasVariableRecurse(std::string key); - bool HasVariableOrFieldRecurse(std::string key,bool setting=false); - - TObject GetVariable(std::string key); - void SetVariable(std::string key, TObject value); - - TObject GetVariable(GCList& ls, std::string key); - TObject SetVariable(GCList& ls, std::string key, TObject v); - void DeclareVariable(std::string key, TObject value); - TRootEnvironment* GetRootEnvironment(); - TEnvironment* GetParentEnvironment(); - void RegisterOnError(TCallable* callable); - bool HandleException(std::shared_ptr gc,TEnvironment* env, TObject err); - bool HandleBreakpoint(std::shared_ptr gc,TEnvironment* env, TObject err); - void Mark(); - }; - class TStd { - private: - static void RegisterHelpers(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterUuid(std::shared_ptr gc, TRootEnvironment* env); - public: - static void RegisterStd(std::shared_ptr gc, TRootEnvironment* env, std::shared_ptr localfs); - static void RegisterStd(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterConsole(std::shared_ptr gc,TRootEnvironment* env); - static void RegisterIO(std::shared_ptr gc,TRootEnvironment* env, std::shared_ptr local); - static void RegisterIO(std::shared_ptr gc,TRootEnvironment* env, bool enableLocalFS=true); - static void RegisterNet(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterSqlite(std::shared_ptr gc,TRootEnvironment* env); - static void RegisterVM(std::shared_ptr gc,TRootEnvironment* env); - static void RegisterDictionary(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterJson(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterCrypto(std::shared_ptr gc,TRootEnvironment* env); - static void RegisterRoot(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterPath(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterOGC(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterEnv(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterProcess(std::shared_ptr gc, TRootEnvironment* env); - static void RegisterClass(std::shared_ptr gc, TRootEnvironment* env); - - }; - - class TSubEnvironment : public TEnvironment - { - TEnvironment* env; - TDictionary* dict; - public: - static TSubEnvironment* Create(GCList* gc,TEnvironment* env,TDictionary* dict); - static TSubEnvironment* Create(GCList& gc,TEnvironment* env,TDictionary* dict); - TSubEnvironment(TEnvironment* env,TDictionary* dict); - bool HasVariable(std::string key); - bool HasVariableRecurse(std::string key); - bool HasVariableOrFieldRecurse(std::string key, bool setting=false); - bool HasConstForSet(std::string key); - - TObject GetVariable(std::string key); - void SetVariable(std::string key, TObject value); - TObject GetVariable(GCList& ls, std::string key); - TObject SetVariable(GCList& ls, std::string key, TObject v); - - void DeclareVariable(std::string key, TObject value); - TRootEnvironment* GetRootEnvironment(); - TEnvironment* GetParentEnvironment(); - TDictionary* GetDictionary(); - void Mark(); - }; - - - TDictionary* CreateThread(GCList& ls, TCallable* callable,bool detached); - - class TArgWrapper : public TCallable - { - public: - TCallable* callable; - static TArgWrapper* Create(GCList& ls, TCallable* callable); - static TArgWrapper* Create(GCList* ls, TCallable* callable); - TObject Call(GCList& ls,std::vector args); - void Mark(); - }; - - class TExternalMethod : public TCallable - { - std::function args)> cb; - std::function destroy; - - public: - std::vector args; - std::vector watch; - TExternalMethod(std::function args)> cb,std::string documentation, std::vector argNames,std::function destroy); - static TExternalMethod* Create(GCList& ls,std::string documentation, std::vector argNames,std::function args)> cb,std::function destroy); - static TExternalMethod* Create(GCList* ls,std::string documentation, std::vector argNames,std::function args)> cb,std::function destroy); - - static TExternalMethod* Create(GCList& ls,std::string documentation, std::vector argNames,std::function args)> cb); - static TExternalMethod* Create(GCList* ls,std::string documentation, std::vector argNames,std::function args)> cb); - TObject Call(GCList& ls, std::vector args); - - ~TExternalMethod(); - void Mark() - { - if(this->marked) return; - this->marked=true; - for(auto item : watch) - GC::Mark(item); - GC::Mark(this->tag); - } - - }; - - class TEnumerator : public THeapObject - { - public: - virtual bool MoveNext(std::shared_ptr ls)=0; - virtual TObject GetCurrent(GCList& ls)=0; - static TEnumerator* CreateFromObject(GCList& ls, TObject obj); - }; - class TAssociativeArrayEnumerator : public TEnumerator - { - int64_t index; - TAssociativeArray* ls; - public: - static TAssociativeArrayEnumerator* Create(GCList& ls, TAssociativeArray* list); - static TAssociativeArrayEnumerator* Create(GCList* ls, TAssociativeArray* list); - bool MoveNext(std::shared_ptr ls); - TObject GetCurrent(GCList& ls); - void Mark(); - }; - - class TCustomEnumerator : public TEnumerator { - public: - TDictionary* dict; - bool MoveNext(std::shared_ptr ls); - TObject GetCurrent(GCList& ls); - void Mark(); - static TCustomEnumerator* Create(GCList& ls,TDictionary* dict); - static TCustomEnumerator* Create(GCList* ls,TDictionary* dict); - - }; - - class TYieldEnumerator : public TEnumerator - { - bool hasStarted; - TObject enumerator; - TObject current; - public: - bool MoveNext(std::shared_ptr ls); - TObject GetCurrent(GCList& ls); - void Mark(); - static TYieldEnumerator* Create(GCList& ls,TObject v); - static TYieldEnumerator* Create(GCList* ls,TObject v); - - }; - - class TStringEnumerator : public TEnumerator - { - bool hasStarted; - size_t index; - std::string str; - public: - static TStringEnumerator* Create(GCList& ls,std::string str); - static TStringEnumerator* Create(GCList* ls,std::string str); - bool MoveNext(std::shared_ptr ls); - TObject GetCurrent(GCList& ls); - }; - - class TListEnumerator : public TEnumerator - { - int64_t index; - TList* ls; - public: - static TListEnumerator* Create(GCList& ls, TList* list); - static TListEnumerator* Create(GCList* ls, TList* list); - bool MoveNext(std::shared_ptr ls); - TObject GetCurrent(GCList& ls); - void Mark(); - }; - class TDynamicList; - class TDynamicDictionary; - class TDynamicListEnumerator : public TEnumerator - { - int64_t index; - TDynamicList* ls; - public: - static TDynamicListEnumerator* Create(GCList& ls, TDynamicList* list); - static TDynamicListEnumerator* Create(GCList* ls, TDynamicList* list); - bool MoveNext(std::shared_ptr ls); - TObject GetCurrent(GCList& ls); - void Mark(); - }; - class TVFSPathEnumerator : public TEnumerator - { - Tesses::Framework::Filesystem::VFSPathEnumerator enumerator; - public: - static TVFSPathEnumerator* Create(GCList& ls, Tesses::Framework::Filesystem::VFSPathEnumerator list); - static TVFSPathEnumerator* Create(GCList* ls, Tesses::Framework::Filesystem::VFSPathEnumerator list); - bool MoveNext(std::shared_ptr ls); - TObject GetCurrent(GCList& ls); - - }; - - - - class TObjectVFS : public Tesses::Framework::Filesystem::VFS - { - public: - TObject obj; - GCList* ls; - TObjectVFS(std::shared_ptr gc, TObject obj); - std::shared_ptr OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode); - Tesses::Framework::Filesystem::FIFOCreationResult CreateFIFO(Tesses::Framework::Filesystem::VFSPath path); - void CreateDirectory(Tesses::Framework::Filesystem::VFSPath path); - void DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path); - void CreateSymlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath symlinkFile); - void CreateHardlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath newName); - void DeleteFile(Tesses::Framework::Filesystem::VFSPath path); - void Lock(Tesses::Framework::Filesystem::VFSPath path); - void Unlock(Tesses::Framework::Filesystem::VFSPath path); - - void DeleteDirectoryRecurse(Tesses::Framework::Filesystem::VFSPath path); - Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path); - void MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest); - void MoveDirectory(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest); - Tesses::Framework::Filesystem::VFSPath ReadLink(Tesses::Framework::Filesystem::VFSPath path); - std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path); - Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path); - void SetDate(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Date::DateTime lastWrite, Tesses::Framework::Date::DateTime lastAccess); - void Chmod(Tesses::Framework::Filesystem::VFSPath path, uint32_t mode); - void Chown(Tesses::Framework::Filesystem::VFSPath path, uint32_t uid, uint32_t gid); - - bool StatVFS(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Filesystem::StatVFSData& data); - - bool Stat(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Filesystem::StatData& data); - void Close(); - ~TObjectVFS(); - }; - - class TObjectStream : public Tesses::Framework::Streams::Stream - { - int64_t _GetPosInternal(); - public: - TObject obj; - GCList* ls; - TObjectStream(std::shared_ptr gc, TObject obj); - bool EndOfStream(); - size_t Read(uint8_t* buff, size_t sz); - size_t Write(const uint8_t* buff, size_t sz); - bool CanRead(); - bool CanWrite(); - bool CanSeek(); - int64_t GetPosition(); - int64_t GetLength(); - void Flush(); - void Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence); - void Close(); - ~TObjectStream(); - }; - - - - class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer - { - public: - TObject obj; - GCList* ls; - TObjectHttpServer(std::shared_ptr gc,TObject obj); - bool Handle(Tesses::Framework::Http::ServerContext& ctx); - ~TObjectHttpServer(); - }; - - - class TDictionaryEnumerator : public TEnumerator - { - bool hasStarted; - std::map::iterator ittr; - TDictionary* dict; - public: - static TDictionaryEnumerator* Create(GCList& ls, TDictionary* dict); - static TDictionaryEnumerator* Create(GCList* ls, TDictionary* dict); - bool MoveNext(std::shared_ptr ls); - TObject GetCurrent(GCList& ls); - void Mark(); - }; - - class TClosure : public TCallable - { - public: - static TClosure* Create(GCList& ls,TEnvironment* env,TFile* file,uint32_t chunkId,bool ownScope=true); - static TClosure* Create(GCList* ls,TEnvironment* env,TFile* file,uint32_t chunkId,bool ownScope=true); - bool ownScope; - TFileChunk* closure; - TFile* file; - uint32_t chunkId; - TEnvironment* env; - std::string className; - TObject Call(GCList& ls,std::vector args); - void Mark(); - }; - class TDynamicList : public THeapObject - { - public: - TCallable* cb; - static TDynamicList* Create(GCList& ls,TCallable* callable); - static TDynamicList* Create(GCList* ls,TCallable* callable); - - void Mark(); - - int64_t Count(GCList& ls); - - TObject GetAt(GCList& ls, int64_t index); - - TObject SetAt(GCList& ls, int64_t index, TObject val); - - TObject Add(GCList& ls, TObject v); - TObject Insert(GCList& ls, int64_t index, TObject v); - TObject RemoveAllEqual(GCList& ls, TObject v); - TObject Remove(GCList& ls, TObject v); - TObject RemoveAt(GCList& ls, int64_t v); - TObject Clear(GCList& ls); - TObject ToString(GCList& ls); - - ~TDynamicList(); - }; - class TDynamicDictionary : public THeapObject - { - public: - TCallable* cb; - - static TDynamicDictionary* Create(GCList& ls,TCallable* callable); - static TDynamicDictionary* Create(GCList* ls,TCallable* callable); - - void Mark(); - - TObject GetField(GCList& ls, std::string key); - - TObject SetField(GCList& ls, std::string key, TObject value); - - TObject CallMethod(GCList& ls, std::string name, std::vector args); - - bool MethodExists(GCList& ls, std::string name); - - TEnumerator* GetEnumerator(GCList& ls); - - - ~TDynamicDictionary(); - }; - class InterperterThread; - - class CallStackEntry : public THeapObject - { - public: - static CallStackEntry* Create(GCList* ls); - static CallStackEntry* Create(GCList& ls); - InterperterThread* thread; - std::vector stack; - TEnvironment* env; - TClosure* callable; - uint32_t ip; - uint32_t scopes; - int64_t srcline; - std::string srcfile; - bool mustReturn; - - void Mark(); - void Push(std::shared_ptr gc,TObject v); - TObject Pop(GCList& gcl); - - TObject Resume(GCList& ls); - }; - class TTask : public THeapObject - { - TCallable* cont=nullptr; - std::exception_ptr ex=nullptr; - std::shared_ptr gc; - TObject obj=Undefined(); - bool isCompleted=false; - TTask(std::shared_ptr gc); - public: - static TTask* Create(GCList& ls); - bool IsCompleted(); - - void ContinueWith(TCallable* callable); - TTask* ContinueWith(GCList& ls,TCallable* callable); - - - void SetFailed(std::exception_ptr ex); - void SetSucceeded(TObject v); - - TObject Wait(); - void Mark(); - - static TTask* FromClosure(GCList& ls, TClosure* closure); - - static TTask* FromCallStackEntry(GCList& ls, CallStackEntry* ent); - - static TTask* Run(GCList& ls, TCallable* callable); - - static TTask* FromResult(GCList& ls, TObject v); - }; - extern thread_local CallStackEntry* current_function; - - class InterperterThread : public THeapObject - { - private: - bool InvokeTwo(GCList& ls,TObject fn, TObject left, TObject right); - bool InvokeOne(GCList& ls,TObject fn, TObject arg); - bool InvokeMethod(GCList& ls, TObject fn, TObject instance, std::vector args); - bool ExecuteMethod2(std::shared_ptr gc, TObject instance, std::string key, std::vector args); - protected: - static void* ThreadCallback(void* ptr); - bool JumpIfDefined(std::shared_ptr gc); - bool Add(std::shared_ptr gc); - bool Sub(std::shared_ptr gc); - bool Times(std::shared_ptr gc); - bool Divide(std::shared_ptr gc); - bool Mod(std::shared_ptr gc); - bool Neg(std::shared_ptr gc); - bool Lt(std::shared_ptr gc); - bool Gt(std::shared_ptr gc); - bool Lte(std::shared_ptr gc); - bool Gte(std::shared_ptr gc); - bool Eq(std::shared_ptr gc); - bool NEq(std::shared_ptr gc); - bool LShift(std::shared_ptr gc); - bool RShift(std::shared_ptr gc); - bool BOr(std::shared_ptr gc); - bool XOr(std::shared_ptr gc); - bool LNot(std::shared_ptr gc); - bool BNot(std::shared_ptr gc); - bool BAnd(std::shared_ptr gc); - bool ExecuteFunction(std::shared_ptr gc); - bool ExecuteMethod(std::shared_ptr gc); - bool GetVariable(std::shared_ptr gc); - bool SetVariable(std::shared_ptr gc); - bool GetField(std::shared_ptr gc); - bool SetField(std::shared_ptr gc); - bool GetArray(std::shared_ptr gc); - bool SetArray(std::shared_ptr gc); - bool DeclareVariable(std::shared_ptr gc); - bool DeclareConstVariable(std::shared_ptr gc); - bool PushLong(std::shared_ptr gc); - bool PushDouble(std::shared_ptr gc); - bool PushChar(std::shared_ptr gc); - bool PushString(std::shared_ptr gc); - bool PushClosure(std::shared_ptr gc); - bool PushScopelessClosure(std::shared_ptr gc); - bool PushResource(std::shared_ptr gc); - bool Illegal(std::shared_ptr gc); - bool Throw(std::shared_ptr gc); - bool Yield(std::shared_ptr gc); - bool Jump(std::shared_ptr gc); - bool JumpConditional(std::shared_ptr gc); - bool JumpUndefined(std::shared_ptr gc); - bool Defer(std::shared_ptr gc); - bool TryCatch(std::shared_ptr gc); - bool Return(std::shared_ptr gc); - bool ScopeBegin(std::shared_ptr gc); - bool ScopeEnd(std::shared_ptr gc); - bool ScopeEndTimes(std::shared_ptr gc); - bool PushTrue(std::shared_ptr gc); - bool PushFalse(std::shared_ptr gc); - bool PushNull(std::shared_ptr gc); - bool PushUndefined(std::shared_ptr gc); - bool CreateDictionary(std::shared_ptr gc); - bool CreateArray(std::shared_ptr gc); - bool AppendList(std::shared_ptr gc); - bool AppendDictionary(std::shared_ptr gc); - bool PushRootPath(std::shared_ptr gc); - bool PushRelativePath(std::shared_ptr gc); - bool Pop(std::shared_ptr gc); - bool Dup(std::shared_ptr gc); - bool Nop(std::shared_ptr gc); - bool Breakpoint(std::shared_ptr gc); - bool PushBreak(std::shared_ptr gc); - bool PushContinue(std::shared_ptr gc); - bool JumpIfBreak(std::shared_ptr gc); - bool JumpIfContinue(std::shared_ptr gc); - bool LineInfo(std::shared_ptr gc); - bool PushResourceStream(std::shared_ptr gc); - bool PushResourceDirectory(std::shared_ptr gc); - public: - static InterperterThread* Create(GCList* ls); - static InterperterThread* Create(GCList& ls); - std::vector call_stack_entries; - virtual void Execute(std::shared_ptr gc); - void AddCallStackEntry(GCList& ls,TClosure* closure, std::vector args); - void Mark(); - }; - - - - - class VMException : public std::exception { - - std::string error_message; - public: - - VMException(std::string ex) - { - error_message = "VMException: "; - error_message.append(ex); - } - - - - const char * what() const noexcept override - { - return error_message.c_str(); - } - }; - class TAny : public THeapObject { - public: - std::any any; - TObject other; - - static TAny* Create(GCList& ls); - static TAny* Create(GCList* ls); - void Mark(); - }; - class TNativeObject : public THeapObject - { - public: - template - static T* Create(GCList& ls,TArgs... args) - { - T* obj = new T(args...); - std::shared_ptr gc = ls.GetGC(); - ls.Add(obj); - gc->Watch(obj); - return obj; - } - template - static T* Create(GCList* ls,TArgs... args) - { - T* obj = new T(args...); - std::shared_ptr gc = ls->GetGC(); - ls->Add(obj); - gc->Watch(obj); - return obj; - } - - virtual TObject CallMethod(GCList& ls,std::string name, std::vector args)=0; - virtual std::string TypeName()=0; - virtual bool ToBool(); - virtual bool Equals(std::shared_ptr gc, TObject right); - virtual ~TNativeObject(); - }; - class TRandom : public TNativeObject - { - public: - Tesses::Framework::Random random; - TRandom(); - TRandom(uint64_t seed); - std::string TypeName(); - TObject CallMethod(GCList& ls,std::string name, std::vector args); - - }; - class TNative : public THeapObject - { - std::atomic destroyed; - void* ptr; - std::function destroy; - public: - TObject other; - TNative(void* ptr,std::function destroy); - bool GetDestroyed(); - void* GetPointer(); - void Destroy(); - void Mark(); - static TNative* Create(GCList& ls, void* ptr,std::function destroy); - static TNative* Create(GCList* ls, void* ptr,std::function destroy); - ~TNative(); - }; - - - - class ThreadHandle : public THeapObject { - public: - Tesses::Framework::Threading::Thread* thrd; - std::atomic hasInit; - std::atomic hasReturned; - std::atomic detached; - TCallable* callable; - TObject returnValue; - std::shared_ptr gc; - - - void Mark() - { - if(this->marked) return; - this->marked = true; - callable->Mark(); - GC::Mark(returnValue); - } - ~ThreadHandle() - { - if(this->detached) - { - this->thrd->Join(); - delete this->thrd; - } - - } - }; - - - TObject ExecuteFunction(GCList& ls,TCallable* callable,std::vector args); - class VMByteCodeException : public std::exception - { - std::string lastErrorText; - std::shared_ptr gcList; - - public: - - TObject exception; - std::vector stack_trace; - - - VMByteCodeException() - { - } - - VMByteCodeException(std::shared_ptr gc,TObject obj, CallStackEntry* ent) - { - gcList = std::make_shared(gc); - gcList->Add(obj); - if(ent != nullptr && ent->thread != nullptr) - { - this->stack_trace = ent->thread->call_stack_entries; - for(auto item : this->stack_trace) - gcList->Add(item); - } - this->exception = obj; - UpdateError(); - } - - void UpdateError() - { - lastErrorText = ToString(gcList->GetGC(),exception); - - } - - const char * what() const noexcept override - { - return lastErrorText.c_str(); - } - std::shared_ptr GetGCList() { - return this->gcList; - } - - }; - - class SyntaxException : public std::exception - { - std::string msg={}; - LexTokenLineInfo line; - std::string message; - public: - SyntaxException(LexTokenLineInfo lineInfo, std::string message) : line(lineInfo), message(message) - { - msg.append("in file: "); - msg.append(lineInfo.filename); - msg.append(":"); - msg.append(std::to_string(lineInfo.line)); - msg.append(":"); - msg.append(std::to_string(lineInfo.column)); - msg.append(":"); - msg.append(std::to_string(lineInfo.offset)); - msg.append(": "); - msg.append(message); - } - const char * what() const noexcept override - { - return msg.c_str(); - } - - std::string Message() { return message;} - LexTokenLineInfo LineInfo() { return line;} - }; - - - template - bool GetObject(TObject& obj, T& res) - { - if(!std::holds_alternative(obj)) return false; - res = std::get(obj); - return true; - } - template - bool GetArgument(std::vector& args, size_t index, T& obj) - { - if( index >= args.size()) return false; - return GetObject(args[index], obj); - } - - template - bool GetObjectHeap(TObject& obj, T& res) - { - THeapObjectHolder h; - if(!GetObject(obj,h)) return false; - auto v = dynamic_cast(h.obj); - if(v == nullptr) return false; - res = v; - return true; - } - - template - bool GetArgumentHeap(std::vector& args, size_t index, T& obj) - { - if( index >= args.size()) return false; - return GetObjectHeap(args[index], obj); - } - bool GetObjectAsPath(TObject& obj, Tesses::Framework::Filesystem::VFSPath& path, bool allowString=true); - bool GetArgumentAsPath(std::vector& args, size_t index, Tesses::Framework::Filesystem::VFSPath& path,bool allowString=true); - bool ToBool(TObject obj); - bool Equals(std::shared_ptr gc, TObject left, TObject right); - typedef void (*PluginFunction)(std::shared_ptr gc,TRootEnvironment* env); - #if !defined(_WIN32) - #define DLLEXPORT - #else - #define DLLEXPORT __declspec(dllexport) - #endif - #define CROSSLANG_PLUGIN(plugin) DLLEXPORT extern "C" void CrossLangPluginInit(std::shared_ptr gc, TRootEnvironment* env) { plugin(gc,env); } - - void LoadPlugin(std::shared_ptr gc, TRootEnvironment* env, Tesses::Framework::Filesystem::VFSPath sharedObjectPath); - std::string Json_Encode(TObject o,bool indent=false); - TObject Json_Decode(GCList ls,std::string str); - std::string Json_DocEncode(TObject o,bool indent); - TObject Json_DocDecode(GCList ls,std::string str); - //DO NOT USE DIRECTLY - class SharedPtrTObject { - GCList* ls; - TObject o; - public: - SharedPtrTObject(std::shared_ptr gc, TObject o); - TObject& GetObject(); - std::shared_ptr GetGC(); - ~SharedPtrTObject(); - }; - using MarkedTObject = std::shared_ptr; - - MarkedTObject CreateMarkedTObject(std::shared_ptr gc, TObject o); - MarkedTObject CreateMarkedTObject(GCList* gc, TObject o); - MarkedTObject CreateMarkedTObject(GCList& gc, TObject o); - std::string JoinPeriod(std::vector& p); - TObject GetClassInfo(GCList& ls,TFile* f, uint32_t index); - - extern Tesses::Framework::Filesystem::VFSPath CrossLangConfigPath; - - Tesses::Framework::Filesystem::VFSPath Assemble(std::shared_ptr vfs); - void Disassemble(std::shared_ptr src,std::shared_ptr vfs, bool generateJSON=true,bool extractResources=true); - Tesses::Framework::Filesystem::VFSPath Merge(std::shared_ptr srcFS, Tesses::Framework::Filesystem::VFSPath sourcePath, std::shared_ptr destFS); - - - std::shared_ptr ToHttpServer(std::shared_ptr gc,TObject obj); - - class EmbedStream : public Tesses::Framework::Streams::Stream - { - size_t offset; - MarkedTObject file; - uint32_t resource; - - public: - EmbedStream(std::shared_ptr gc, TFile* file, uint32_t resource); - bool CanRead(); - bool CanSeek(); - bool EndOfStream(); - size_t Read(uint8_t* buff, size_t len); - int64_t GetPosition(); - int64_t GetLength(); - void Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence); - }; - - class EmbedDirectory : public Tesses::Framework::Filesystem::VFS - { - MarkedTObject dir; - TObject getEntry(Tesses::Framework::Filesystem::VFSPath path); - public: - EmbedDirectory(std::shared_ptr gc, TDictionary* dict); - std::shared_ptr OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode); - - Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path); - std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path); - Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path); - - bool Stat(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Filesystem::StatData& data); - }; - - - namespace Programs { - int64_t CrossArchiveCreate(std::vector& argv); - int64_t CrossArchiveExtract(std::vector& argv); - TObject CrossLangInterperter(GCList& ls,TRootEnvironment* env,std::vector& argv); - TObject CrossLangShell(GCList& ls, std::vector& argv); - - TObject CrossLangVM(GCList& ls,TRootEnvironment* env, std::vector& argv); - - void CrossLangDump(std::shared_ptr strm); - void CrossLangCompiler(std::vector& argv); - } - - enum class TQueryableMode { - Passthrough, - Skip, - SkipWhile, - Take, - TakeWhile, - Select, - Where - }; - - class TQueryable : public THeapObject { - - - TObject parent; - TQueryableMode mode; - std::vector args; - TQueryable(TObject parent); - TQueryable(TObject parent, TQueryableMode mode, std::vector args); - - public: - - static TQueryable* Create(GCList& ls, TObject parent); - static TQueryable* Create(GCList& ls, TObject parent, TQueryableMode mode, std::vector args); - - TQueryable* Skip(GCList& ls,int64_t no); - TQueryable* SkipWhile(GCList& ls, TCallable* call); - TQueryable* Take(GCList& ls, int64_t no); - TQueryable* TakeWhile(GCList& ls, TCallable* call); - TQueryable* Select(GCList& ls, TCallable* call); - TQueryable* Where(GCList& ls, TCallable* call); - void ForEach(std::shared_ptr gc, TCallable* call); - int64_t Count(std::shared_ptr gc, TCallable* call); - int64_t Count(std::shared_ptr gc); - bool Contains(std::shared_ptr, TObject value); - bool Any(std::shared_ptr gc, TCallable* call); - bool All(std::shared_ptr gc, TCallable* call); - - TList* ToList(GCList& ls); - TEnumerator* GetEnumerator(GCList& ls); - - void Mark(); - }; + ~GCList(); + friend class GC; }; + +class TFile; + +class TFileChunk : public THeapObject { + public: + static TFileChunk *Create(GCList *gc); + static TFileChunk *Create(GCList &gc); + TFile *file; + std::vector code; + std::vector args; + std::optional name; + void Mark(); +}; + +class TByteArray : public THeapObject { + public: + std::vector data; + static TByteArray *Create(GCList *gc); + static TByteArray *Create(GCList &gc); +}; +enum class TClassModifier { Private, Protected, Public, Static }; +class TClassEntry { + public: + TClassModifier modifier; + bool isFunction; + bool isAbstract; + std::vector args; + std::string documentation; + std::string name; + + uint32_t chunkId; +}; +class TClass { + public: + std::string documentation; + std::vector name; + std::vector inherits; + std::vector entry; +}; +class TClassObjectEntry { + public: + TClassModifier modifier; + bool canSet; + std::string name; + std::string owner; + TObject value; +}; +class TDictionary; +class TFile : public THeapObject { + public: + static TFile *Create(GCList *gc); + static TFile *Create(GCList &gc); + std::vector chunks; + + std::vector strings; + std::vector> vms; + std::vector, uint32_t>> functions; + std::vector> dependencies; + std::vector> tools; + std::vector>> sections; + std::vector>> metadata; + std::vector> resources; + std::vector classes; + std::string name; + TVMVersion version; + std::string info; + int32_t icon; + + void Load(std::shared_ptr gc, + std::shared_ptr strm); + void Skip(std::shared_ptr strm, + size_t len); + void Ensure(std::shared_ptr strm, + uint8_t *buffer, size_t len); + uint32_t + EnsureInt(std::shared_ptr strm); + std::string + EnsureString(std::shared_ptr strm); + + std::string + GetString(std::shared_ptr strm); + void Mark(); + + void EnsureCanRunInCrossLang(); + + TDictionary *MetadataDecode(GCList &ls, size_t index); +}; +class TAssociativeArray : public THeapObject { + public: + std::vector> items; + static TAssociativeArray *Create(GCList &ls); + static TAssociativeArray *Create(GCList *ls); + void Set(std::shared_ptr gc, TObject key, TObject value); + TObject Get(std::shared_ptr gc, TObject key); + TObject GetKey(int64_t index); + TObject GetValue(int64_t index); + void SetKey(int64_t index, TObject key); + void SetValue(int64_t index, TObject value); + int64_t Count(); + void Mark(); +}; + +class TList : public THeapObject { + public: + std::vector items; + static TList *Create(GCList *gc); + static TList *Create(GCList &gc); + template + static TList *Create(GCList *gc, Itterator begin, Itterator end) { + auto list = Create(gc); + gc->GetGC()->BarrierBegin(); + for (Itterator i = begin; i != end; ++i) { + TObject item = *i; + list->Add(item); + } + gc->GetGC()->BarrierEnd(); + return list; + } + template + static TList *Create(GCList &gc, Itterator begin, Itterator end) { + return Create(&gc, begin, end); + } + static TList *Create(GCList *gc, std::initializer_list il) { + return Create(gc, il.begin(), il.end()); + } + static TList *Create(GCList &gc, std::initializer_list il) { + return Create(gc, il.begin(), il.end()); + } + virtual int64_t Count(); + virtual TObject Get(int64_t index); + virtual void Set(int64_t index, TObject value); + virtual void Insert(int64_t index, TObject value); + virtual void Add(TObject value); + virtual void RemoveAt(int64_t index); + virtual void Clear(); + virtual void Mark(); +}; +using TDItem = std::pair; +class TDictionary : public THeapObject { + public: + std::map items; + static TDictionary *Create(GCList *gc); + static TDictionary *Create(GCList &gc); + template + static TDictionary *Create(GCList *gc, Itterator begin, Itterator end) { + auto dict = Create(gc); + gc->GetGC()->BarrierBegin(); + for (Itterator i = begin; i != end; ++i) { + TDItem item = *i; + dict->SetValue(item.first, item.second); + } + gc->GetGC()->BarrierEnd(); + return dict; + } + template + static TDictionary *Create(GCList &gc, Itterator begin, Itterator end) { + return Create(&gc, begin, end); + } + + static TDictionary *Create(GCList *gc, std::initializer_list il) { + return Create(gc, il.begin(), il.end()); + } + static TDictionary *Create(GCList &gc, std::initializer_list il) { + return Create(gc, il.begin(), il.end()); + } + + virtual bool HasValue(std::string key); + virtual bool MethodExists(GCList &ls, std::string key); + virtual TObject GetValue(std::string key); + virtual void SetValue(std::string key, TObject value); + virtual void Mark(); + void DeclareFunction( + std::shared_ptr gc, std::string key, std::string documentation, + std::vector argNames, + std::function args)> cb); + void DeclareFunction( + std::shared_ptr gc, std::string key, std::string documentation, + std::vector argNames, + std::function args)> cb, + std::function destroy); + TObject CallMethod(GCList &ls, std::string key, std::vector args); + TObject CallMethodWithFatalError(GCList &ls, std::string key, + std::vector args); +}; + +class TRootEnvironment; +class TSubEnvironment; + +class TCallable : public THeapObject { + public: + TObject tag; + std::string documentation; + virtual TObject Call(GCList &ls, std::vector args) = 0; + TObject CallWithFatalError(GCList &ls, std::vector args); + virtual void Mark(); + + Tesses::Framework::Http::ServerRequestHandler + ToRouteServerRequestHandler(std::shared_ptr gc); +}; + +void ThrowFatalError(std::exception &ex); + +void ThrowConstError(std::string key); + +class TEnvironment : public THeapObject { + std::vector consts; + + public: + std::vector defers; + TObject LoadFile(std::shared_ptr gc, TFile *f); + TObject Eval(GCList &ls, std::string code); + virtual bool HasVariable(std::string key) = 0; + virtual bool HasVariableRecurse(std::string key) = 0; + + virtual bool HasVariableOrFieldRecurse(std::string key, + bool setting = false) = 0; + virtual TObject GetVariable(std::string key) = 0; + + virtual TObject GetVariable(GCList &ls, std::string key) = 0; + virtual TObject SetVariable(GCList &ls, std::string key, TObject v) = 0; + + virtual void SetVariable(std::string key, TObject value) = 0; + TDictionary *EnsureDictionary(std::shared_ptr gc, std::string key); + virtual void DeclareVariable(std::string key, TObject value) = 0; + void DeclareConstVariable(std::string key, TObject value); + bool HasConstForDeclare(std::string key); + virtual bool HasConstForSet(std::string key); + void DeclareVariable(std::shared_ptr gc, std::vector key, + TObject value); + virtual TRootEnvironment *GetRootEnvironment() = 0; + virtual TEnvironment *GetParentEnvironment() = 0; + virtual TSubEnvironment *GetSubEnvironment(TDictionary *dict); + TSubEnvironment *GetSubEnvironment(GCList *gc); + TSubEnvironment *GetSubEnvironment(GCList &gc); + + void DeclareFunction( + std::shared_ptr gc, std::string key, std::string documentation, + std::vector argNames, + std::function args)> cb); + void DeclareFunction( + std::shared_ptr gc, std::string key, std::string documentation, + std::vector argNames, + std::function args)> cb, + std::function destroy); + TObject CallFunction(GCList &ls, std::string key, + std::vector args); + TObject CallFunctionWithFatalError(GCList &ls, std::string key, + std::vector args); +}; +class TClassEnvironment; +class TClassObject : public THeapObject { + TClassObjectEntry *GetEntry(std::string classN, std::string key); + + public: + TFile *file; + uint32_t classIndex; + TEnvironment *ogEnv; + TClassEnvironment *env; + std::string name; + std::vector inherit_tree; + std::vector entries; + + static TClassObject *Create(GCList &ls, TFile *f, uint32_t classIndex, + TEnvironment *env, std::vector args); + static TClassObject *Create(GCList *ls, TFile *f, uint32_t classIndex, + TEnvironment *env, std::vector args); + + TObject GetValue(std::string className, std::string name); + void SetValue(std::string className, std::string name, TObject value); + bool HasValue(std::string className, std::string name); + bool HasField(std::string className, std::string name); + bool HasMethod(std::string className, std::string name); + TObject CallMethod(GCList &ls, std::string className, std::string name, + std::vector args); + std::string TypeName(); + void Mark(); +}; +class TClassEnvironment : public TEnvironment { + TEnvironment *env; + TClassObject *clsObj; + + public: + static TClassEnvironment *Create(GCList *gc, TEnvironment *env, + TClassObject *obj); + static TClassEnvironment *Create(GCList &gc, TEnvironment *env, + TClassObject *obj); + TClassEnvironment(TEnvironment *env, TClassObject *obj); + bool HasVariable(std::string key); + bool HasVariableRecurse(std::string key); + bool HasVariableOrFieldRecurse(std::string key, bool setting = false); + + TObject GetVariable(std::string key); + void SetVariable(std::string key, TObject value); + TObject GetVariable(GCList &ls, std::string key); + TObject SetVariable(GCList &ls, std::string key, TObject v); + + void DeclareVariable(std::string key, TObject value); + bool HasConstForSet(std::string key); + + TRootEnvironment *GetRootEnvironment(); + TEnvironment *GetParentEnvironment(); + + void Mark(); +}; + +class EnvironmentPermissions { + public: + EnvironmentPermissions(); + Tesses::Framework::Filesystem::VFSPath sqliteOffsetPath; + std::shared_ptr localfs; + bool canRegisterEverything; + bool canRegisterConsole; + bool canRegisterIO; + bool canRegisterNet; + bool canRegisterSqlite; + bool canRegisterVM; + bool canRegisterDictionary; + bool canRegisterJSON; + bool canRegisterCrypto; + bool canRegisterRoot; + bool canRegisterProcess; + bool canRegisterPath; + bool canRegisterOGC; + bool canRegisterEnv; + bool canRegisterClass; + bool sqlite3Scoped; + bool locked; + TDictionary *customConsole = nullptr; +}; + +class TRootEnvironment : public TEnvironment { + TDictionary *dict; + TCallable *error = nullptr; + std::map private_file_data; + + void LoadDependency(std::shared_ptr gc, + std::shared_ptr vfs, + std::pair dep); + + public: + EnvironmentPermissions permissions; + + std::vector> dependencies; + std::vector> classes; + + TDictionary *GetPrivateFromFile(std::shared_ptr gc, TFile *file); + + bool TryFindClass(std::vector &name, size_t &index); + + void LoadFileWithDependencies( + std::shared_ptr gc, + std::shared_ptr vfs, TFile *f); + void LoadFileWithDependencies( + std::shared_ptr gc, + std::shared_ptr vfs, + Tesses::Framework::Filesystem::VFSPath path); + + TDictionary *GetDictionary(); + static TRootEnvironment *Create(GCList *gc, TDictionary *dict); + static TRootEnvironment *Create(GCList &gc, TDictionary *dict); + TRootEnvironment(TDictionary *dict); + bool HasVariable(std::string key); + bool HasVariableRecurse(std::string key); + bool HasVariableOrFieldRecurse(std::string key, bool setting = false); + + TObject GetVariable(std::string key); + void SetVariable(std::string key, TObject value); + + TObject GetVariable(GCList &ls, std::string key); + TObject SetVariable(GCList &ls, std::string key, TObject v); + void DeclareVariable(std::string key, TObject value); + TRootEnvironment *GetRootEnvironment(); + TEnvironment *GetParentEnvironment(); + void RegisterOnError(TCallable *callable); + bool HandleException(std::shared_ptr gc, TEnvironment *env, + TObject err); + bool HandleBreakpoint(std::shared_ptr gc, TEnvironment *env, + TObject err); + void Mark(); +}; +class TStd { + private: + static void RegisterHelpers(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterUuid(std::shared_ptr gc, TRootEnvironment *env); + + public: + static void RegisterStd( + std::shared_ptr gc, TRootEnvironment *env, + std::shared_ptr + localfs); + static void RegisterStd(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterConsole(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterIO( + std::shared_ptr gc, TRootEnvironment *env, + std::shared_ptr + local); + static void RegisterIO(std::shared_ptr gc, TRootEnvironment *env, + bool enableLocalFS = true); + static void RegisterNet(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterSqlite(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterVM(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterDictionary(std::shared_ptr gc, + TRootEnvironment *env); + static void RegisterJson(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterCrypto(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterRoot(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterPath(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterOGC(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterEnv(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterProcess(std::shared_ptr gc, TRootEnvironment *env); + static void RegisterClass(std::shared_ptr gc, TRootEnvironment *env); +}; + +class TSubEnvironment : public TEnvironment { + TEnvironment *env; + TDictionary *dict; + + public: + static TSubEnvironment *Create(GCList *gc, TEnvironment *env, + TDictionary *dict); + static TSubEnvironment *Create(GCList &gc, TEnvironment *env, + TDictionary *dict); + TSubEnvironment(TEnvironment *env, TDictionary *dict); + bool HasVariable(std::string key); + bool HasVariableRecurse(std::string key); + bool HasVariableOrFieldRecurse(std::string key, bool setting = false); + bool HasConstForSet(std::string key); + + TObject GetVariable(std::string key); + void SetVariable(std::string key, TObject value); + TObject GetVariable(GCList &ls, std::string key); + TObject SetVariable(GCList &ls, std::string key, TObject v); + + void DeclareVariable(std::string key, TObject value); + TRootEnvironment *GetRootEnvironment(); + TEnvironment *GetParentEnvironment(); + TDictionary *GetDictionary(); + void Mark(); +}; + +TDictionary *CreateThread(GCList &ls, TCallable *callable, bool detached); + +class TArgWrapper : public TCallable { + public: + TCallable *callable; + static TArgWrapper *Create(GCList &ls, TCallable *callable); + static TArgWrapper *Create(GCList *ls, TCallable *callable); + TObject Call(GCList &ls, std::vector args); + void Mark(); +}; + +class TExternalMethod : public TCallable { + std::function args)> cb; + std::function destroy; + + public: + std::vector args; + std::vector watch; + TExternalMethod( + std::function args)> cb, + std::string documentation, std::vector argNames, + std::function destroy); + static TExternalMethod * + Create(GCList &ls, std::string documentation, + std::vector argNames, + std::function args)> cb, + std::function destroy); + static TExternalMethod * + Create(GCList *ls, std::string documentation, + std::vector argNames, + std::function args)> cb, + std::function destroy); + + static TExternalMethod * + Create(GCList &ls, std::string documentation, + std::vector argNames, + std::function args)> cb); + static TExternalMethod * + Create(GCList *ls, std::string documentation, + std::vector argNames, + std::function args)> cb); + TObject Call(GCList &ls, std::vector args); + + ~TExternalMethod(); + void Mark() { + if (this->marked) + return; + this->marked = true; + for (auto item : watch) + GC::Mark(item); + GC::Mark(this->tag); + } +}; + +class TEnumerator : public THeapObject { + public: + virtual bool MoveNext(std::shared_ptr ls) = 0; + virtual TObject GetCurrent(GCList &ls) = 0; + static TEnumerator *CreateFromObject(GCList &ls, TObject obj); +}; +class TAssociativeArrayEnumerator : public TEnumerator { + int64_t index; + TAssociativeArray *ls; + + public: + static TAssociativeArrayEnumerator *Create(GCList &ls, + TAssociativeArray *list); + static TAssociativeArrayEnumerator *Create(GCList *ls, + TAssociativeArray *list); + bool MoveNext(std::shared_ptr ls); + TObject GetCurrent(GCList &ls); + void Mark(); +}; + +class TCustomEnumerator : public TEnumerator { + public: + TDictionary *dict; + bool MoveNext(std::shared_ptr ls); + TObject GetCurrent(GCList &ls); + void Mark(); + static TCustomEnumerator *Create(GCList &ls, TDictionary *dict); + static TCustomEnumerator *Create(GCList *ls, TDictionary *dict); +}; + +class TYieldEnumerator : public TEnumerator { + bool hasStarted; + TObject enumerator; + TObject current; + + public: + bool MoveNext(std::shared_ptr ls); + TObject GetCurrent(GCList &ls); + void Mark(); + static TYieldEnumerator *Create(GCList &ls, TObject v); + static TYieldEnumerator *Create(GCList *ls, TObject v); +}; + +class TStringEnumerator : public TEnumerator { + bool hasStarted; + size_t index; + std::string str; + + public: + static TStringEnumerator *Create(GCList &ls, std::string str); + static TStringEnumerator *Create(GCList *ls, std::string str); + bool MoveNext(std::shared_ptr ls); + TObject GetCurrent(GCList &ls); +}; + +class TListEnumerator : public TEnumerator { + int64_t index; + TList *ls; + + public: + static TListEnumerator *Create(GCList &ls, TList *list); + static TListEnumerator *Create(GCList *ls, TList *list); + bool MoveNext(std::shared_ptr ls); + TObject GetCurrent(GCList &ls); + void Mark(); +}; +class TDynamicList; +class TDynamicDictionary; +class TDynamicListEnumerator : public TEnumerator { + int64_t index; + TDynamicList *ls; + + public: + static TDynamicListEnumerator *Create(GCList &ls, TDynamicList *list); + static TDynamicListEnumerator *Create(GCList *ls, TDynamicList *list); + bool MoveNext(std::shared_ptr ls); + TObject GetCurrent(GCList &ls); + void Mark(); +}; +class TVFSPathEnumerator : public TEnumerator { + Tesses::Framework::Filesystem::VFSPathEnumerator enumerator; + + public: + static TVFSPathEnumerator * + Create(GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator list); + static TVFSPathEnumerator * + Create(GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator list); + bool MoveNext(std::shared_ptr ls); + TObject GetCurrent(GCList &ls); +}; + +class TObjectVFS : public Tesses::Framework::Filesystem::VFS { + public: + TObject obj; + GCList *ls; + TObjectVFS(std::shared_ptr gc, TObject obj); + std::shared_ptr + OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode); + Tesses::Framework::Filesystem::FIFOCreationResult + CreateFIFO(Tesses::Framework::Filesystem::VFSPath path); + void CreateDirectory(Tesses::Framework::Filesystem::VFSPath path); + void DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path); + void CreateSymlink(Tesses::Framework::Filesystem::VFSPath existingFile, + Tesses::Framework::Filesystem::VFSPath symlinkFile); + void CreateHardlink(Tesses::Framework::Filesystem::VFSPath existingFile, + Tesses::Framework::Filesystem::VFSPath newName); + void DeleteFile(Tesses::Framework::Filesystem::VFSPath path); + void Lock(Tesses::Framework::Filesystem::VFSPath path); + void Unlock(Tesses::Framework::Filesystem::VFSPath path); + + void DeleteDirectoryRecurse(Tesses::Framework::Filesystem::VFSPath path); + Tesses::Framework::Filesystem::VFSPathEnumerator + EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path); + void MoveFile(Tesses::Framework::Filesystem::VFSPath src, + Tesses::Framework::Filesystem::VFSPath dest); + void MoveDirectory(Tesses::Framework::Filesystem::VFSPath src, + Tesses::Framework::Filesystem::VFSPath dest); + Tesses::Framework::Filesystem::VFSPath + ReadLink(Tesses::Framework::Filesystem::VFSPath path); + std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path); + Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path); + void SetDate(Tesses::Framework::Filesystem::VFSPath path, + Tesses::Framework::Date::DateTime lastWrite, + Tesses::Framework::Date::DateTime lastAccess); + void Chmod(Tesses::Framework::Filesystem::VFSPath path, uint32_t mode); + void Chown(Tesses::Framework::Filesystem::VFSPath path, uint32_t uid, + uint32_t gid); + + bool StatVFS(Tesses::Framework::Filesystem::VFSPath path, + Tesses::Framework::Filesystem::StatVFSData &data); + + bool Stat(Tesses::Framework::Filesystem::VFSPath path, + Tesses::Framework::Filesystem::StatData &data); + void Close(); + ~TObjectVFS(); +}; + +class TObjectStream : public Tesses::Framework::Streams::Stream { + int64_t _GetPosInternal(); + + public: + TObject obj; + GCList *ls; + TObjectStream(std::shared_ptr gc, TObject obj); + bool EndOfStream(); + size_t Read(uint8_t *buff, size_t sz); + size_t Write(const uint8_t *buff, size_t sz); + bool CanRead(); + bool CanWrite(); + bool CanSeek(); + int64_t GetPosition(); + int64_t GetLength(); + void Flush(); + void Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence); + void Close(); + ~TObjectStream(); +}; + +class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer { + public: + TObject obj; + GCList *ls; + TObjectHttpServer(std::shared_ptr gc, TObject obj); + bool Handle(Tesses::Framework::Http::ServerContext &ctx); + ~TObjectHttpServer(); +}; + +class TDictionaryEnumerator : public TEnumerator { + bool hasStarted; + std::map::iterator ittr; + TDictionary *dict; + + public: + static TDictionaryEnumerator *Create(GCList &ls, TDictionary *dict); + static TDictionaryEnumerator *Create(GCList *ls, TDictionary *dict); + bool MoveNext(std::shared_ptr ls); + TObject GetCurrent(GCList &ls); + void Mark(); +}; + +class TClosure : public TCallable { + public: + static TClosure *Create(GCList &ls, TEnvironment *env, TFile *file, + uint32_t chunkId, bool ownScope = true); + static TClosure *Create(GCList *ls, TEnvironment *env, TFile *file, + uint32_t chunkId, bool ownScope = true); + bool ownScope; + TFileChunk *closure; + TFile *file; + uint32_t chunkId; + TEnvironment *env; + std::string className; + TObject Call(GCList &ls, std::vector args); + void Mark(); +}; +class TDynamicList : public THeapObject { + public: + TCallable *cb; + static TDynamicList *Create(GCList &ls, TCallable *callable); + static TDynamicList *Create(GCList *ls, TCallable *callable); + + void Mark(); + + int64_t Count(GCList &ls); + + TObject GetAt(GCList &ls, int64_t index); + + TObject SetAt(GCList &ls, int64_t index, TObject val); + + TObject Add(GCList &ls, TObject v); + TObject Insert(GCList &ls, int64_t index, TObject v); + TObject RemoveAllEqual(GCList &ls, TObject v); + TObject Remove(GCList &ls, TObject v); + TObject RemoveAt(GCList &ls, int64_t v); + TObject Clear(GCList &ls); + TObject ToString(GCList &ls); + + ~TDynamicList(); +}; +class TDynamicDictionary : public THeapObject { + public: + TCallable *cb; + + static TDynamicDictionary *Create(GCList &ls, TCallable *callable); + static TDynamicDictionary *Create(GCList *ls, TCallable *callable); + + void Mark(); + + TObject GetField(GCList &ls, std::string key); + + TObject SetField(GCList &ls, std::string key, TObject value); + + TObject CallMethod(GCList &ls, std::string name, std::vector args); + + bool MethodExists(GCList &ls, std::string name); + + TEnumerator *GetEnumerator(GCList &ls); + + ~TDynamicDictionary(); +}; +class InterperterThread; + +class CallStackEntry : public THeapObject { + public: + static CallStackEntry *Create(GCList *ls); + static CallStackEntry *Create(GCList &ls); + InterperterThread *thread; + std::vector stack; + TEnvironment *env; + TClosure *callable; + uint32_t ip; + uint32_t scopes; + int64_t srcline; + std::string srcfile; + bool mustReturn; + + void Mark(); + void Push(std::shared_ptr gc, TObject v); + TObject Pop(GCList &gcl); + + TObject Resume(GCList &ls); +}; +class TTask : public THeapObject { + TCallable *cont = nullptr; + std::exception_ptr ex = nullptr; + std::shared_ptr gc; + TObject obj = Undefined(); + bool isCompleted = false; + TTask(std::shared_ptr gc); + + public: + static TTask *Create(GCList &ls); + bool IsCompleted(); + + void ContinueWith(TCallable *callable); + TTask *ContinueWith(GCList &ls, TCallable *callable); + + void SetFailed(std::exception_ptr ex); + void SetSucceeded(TObject v); + + TObject Wait(); + void Mark(); + + static TTask *FromClosure(GCList &ls, TClosure *closure); + + static TTask *FromCallStackEntry(GCList &ls, CallStackEntry *ent); + + static TTask *Run(GCList &ls, TCallable *callable); + + static TTask *FromResult(GCList &ls, TObject v); +}; +extern thread_local CallStackEntry *current_function; + +class InterperterThread : public THeapObject { + private: + bool InvokeTwo(GCList &ls, TObject fn, TObject left, TObject right); + bool InvokeOne(GCList &ls, TObject fn, TObject arg); + bool InvokeMethod(GCList &ls, TObject fn, TObject instance, + std::vector args); + bool ExecuteMethod2(std::shared_ptr gc, TObject instance, + std::string key, std::vector args); + + protected: + static void *ThreadCallback(void *ptr); + bool JumpIfDefined(std::shared_ptr gc); + bool Add(std::shared_ptr gc); + bool Sub(std::shared_ptr gc); + bool Times(std::shared_ptr gc); + bool Divide(std::shared_ptr gc); + bool Mod(std::shared_ptr gc); + bool Neg(std::shared_ptr gc); + bool Lt(std::shared_ptr gc); + bool Gt(std::shared_ptr gc); + bool Lte(std::shared_ptr gc); + bool Gte(std::shared_ptr gc); + bool Eq(std::shared_ptr gc); + bool NEq(std::shared_ptr gc); + bool LShift(std::shared_ptr gc); + bool RShift(std::shared_ptr gc); + bool BOr(std::shared_ptr gc); + bool XOr(std::shared_ptr gc); + bool LNot(std::shared_ptr gc); + bool BNot(std::shared_ptr gc); + bool BAnd(std::shared_ptr gc); + bool ExecuteFunction(std::shared_ptr gc); + bool ExecuteMethod(std::shared_ptr gc); + bool GetVariable(std::shared_ptr gc); + bool SetVariable(std::shared_ptr gc); + bool GetField(std::shared_ptr gc); + bool SetField(std::shared_ptr gc); + bool GetArray(std::shared_ptr gc); + bool SetArray(std::shared_ptr gc); + bool DeclareVariable(std::shared_ptr gc); + bool DeclareConstVariable(std::shared_ptr gc); + bool PushLong(std::shared_ptr gc); + bool PushDouble(std::shared_ptr gc); + bool PushChar(std::shared_ptr gc); + bool PushString(std::shared_ptr gc); + bool PushClosure(std::shared_ptr gc); + bool PushScopelessClosure(std::shared_ptr gc); + bool PushResource(std::shared_ptr gc); + bool Illegal(std::shared_ptr gc); + bool Throw(std::shared_ptr gc); + bool Yield(std::shared_ptr gc); + bool Jump(std::shared_ptr gc); + bool JumpConditional(std::shared_ptr gc); + bool JumpUndefined(std::shared_ptr gc); + bool Defer(std::shared_ptr gc); + bool TryCatch(std::shared_ptr gc); + bool Return(std::shared_ptr gc); + bool ScopeBegin(std::shared_ptr gc); + bool ScopeEnd(std::shared_ptr gc); + bool ScopeEndTimes(std::shared_ptr gc); + bool PushTrue(std::shared_ptr gc); + bool PushFalse(std::shared_ptr gc); + bool PushNull(std::shared_ptr gc); + bool PushUndefined(std::shared_ptr gc); + bool CreateDictionary(std::shared_ptr gc); + bool CreateArray(std::shared_ptr gc); + bool AppendList(std::shared_ptr gc); + bool AppendDictionary(std::shared_ptr gc); + bool PushRootPath(std::shared_ptr gc); + bool PushRelativePath(std::shared_ptr gc); + bool Pop(std::shared_ptr gc); + bool Dup(std::shared_ptr gc); + bool Nop(std::shared_ptr gc); + bool Breakpoint(std::shared_ptr gc); + bool PushBreak(std::shared_ptr gc); + bool PushContinue(std::shared_ptr gc); + bool JumpIfBreak(std::shared_ptr gc); + bool JumpIfContinue(std::shared_ptr gc); + bool LineInfo(std::shared_ptr gc); + bool PushResourceStream(std::shared_ptr gc); + bool PushResourceDirectory(std::shared_ptr gc); + bool PushPrivateExpression(std::shared_ptr gc); + + public: + static InterperterThread *Create(GCList *ls); + static InterperterThread *Create(GCList &ls); + std::vector call_stack_entries; + virtual void Execute(std::shared_ptr gc); + void AddCallStackEntry(GCList &ls, TClosure *closure, + std::vector args); + void Mark(); +}; + +class VMException : public std::exception { + + std::string error_message; + + public: + VMException(std::string ex) { + error_message = "VMException: "; + error_message.append(ex); + } + + const char *what() const noexcept override { return error_message.c_str(); } +}; +class TAny : public THeapObject { + public: + std::any any; + TObject other; + + static TAny *Create(GCList &ls); + static TAny *Create(GCList *ls); + void Mark(); +}; +class TNativeObject : public THeapObject { + public: + template + static T *Create(GCList &ls, TArgs... args) { + T *obj = new T(args...); + std::shared_ptr gc = ls.GetGC(); + ls.Add(obj); + gc->Watch(obj); + return obj; + } + template + static T *Create(GCList *ls, TArgs... args) { + T *obj = new T(args...); + std::shared_ptr gc = ls->GetGC(); + ls->Add(obj); + gc->Watch(obj); + return obj; + } + + virtual TObject CallMethod(GCList &ls, std::string name, + std::vector args) = 0; + virtual std::string TypeName() = 0; + virtual bool ToBool(); + virtual bool Equals(std::shared_ptr gc, TObject right); + virtual ~TNativeObject(); +}; +class TRandom : public TNativeObject { + public: + Tesses::Framework::Random random; + TRandom(); + TRandom(uint64_t seed); + std::string TypeName(); + TObject CallMethod(GCList &ls, std::string name, std::vector args); +}; +class TNative : public THeapObject { + std::atomic destroyed; + void *ptr; + std::function destroy; + + public: + TObject other; + TNative(void *ptr, std::function destroy); + bool GetDestroyed(); + void *GetPointer(); + void Destroy(); + void Mark(); + static TNative *Create(GCList &ls, void *ptr, + std::function destroy); + static TNative *Create(GCList *ls, void *ptr, + std::function destroy); + ~TNative(); +}; + +class ThreadHandle : public THeapObject { + public: + Tesses::Framework::Threading::Thread *thrd; + std::atomic hasInit; + std::atomic hasReturned; + std::atomic detached; + TCallable *callable; + TObject returnValue; + std::shared_ptr gc; + + void Mark() { + if (this->marked) + return; + this->marked = true; + callable->Mark(); + GC::Mark(returnValue); + } + ~ThreadHandle() { + if (this->detached) { + this->thrd->Join(); + delete this->thrd; + } + } +}; + +TObject ExecuteFunction(GCList &ls, TCallable *callable, + std::vector args); +class VMByteCodeException : public std::exception { + std::string lastErrorText; + std::shared_ptr gcList; + + public: + TObject exception; + std::vector stack_trace; + + VMByteCodeException() {} + + VMByteCodeException(std::shared_ptr gc, TObject obj, + CallStackEntry *ent) { + gcList = std::make_shared(gc); + gcList->Add(obj); + if (ent != nullptr && ent->thread != nullptr) { + this->stack_trace = ent->thread->call_stack_entries; + for (auto item : this->stack_trace) + gcList->Add(item); + } + this->exception = obj; + UpdateError(); + } + + void UpdateError() { lastErrorText = ToString(gcList->GetGC(), exception); } + + const char *what() const noexcept override { return lastErrorText.c_str(); } + std::shared_ptr GetGCList() { return this->gcList; } +}; + +class SyntaxException : public std::exception { + std::string msg = {}; + LexTokenLineInfo line; + std::string message; + + public: + SyntaxException(LexTokenLineInfo lineInfo, std::string message) + : line(lineInfo), message(message) { + msg.append("in file: "); + msg.append(lineInfo.filename); + msg.append(":"); + msg.append(std::to_string(lineInfo.line)); + msg.append(":"); + msg.append(std::to_string(lineInfo.column)); + msg.append(":"); + msg.append(std::to_string(lineInfo.offset)); + msg.append(": "); + msg.append(message); + } + const char *what() const noexcept override { return msg.c_str(); } + + std::string Message() { return message; } + LexTokenLineInfo LineInfo() { return line; } +}; + +template bool GetObject(TObject &obj, T &res) { + if (!std::holds_alternative(obj)) + return false; + res = std::get(obj); + return true; +} +template +bool GetArgument(std::vector &args, size_t index, T &obj) { + if (index >= args.size()) + return false; + return GetObject(args[index], obj); +} + +template bool GetObjectHeap(TObject &obj, T &res) { + THeapObjectHolder h; + if (!GetObject(obj, h)) + return false; + auto v = dynamic_cast(h.obj); + if (v == nullptr) + return false; + res = v; + return true; +} + +template +bool GetArgumentHeap(std::vector &args, size_t index, T &obj) { + if (index >= args.size()) + return false; + return GetObjectHeap(args[index], obj); +} +bool GetObjectAsPath(TObject &obj, Tesses::Framework::Filesystem::VFSPath &path, + bool allowString = true); +bool GetArgumentAsPath(std::vector &args, size_t index, + Tesses::Framework::Filesystem::VFSPath &path, + bool allowString = true); +bool ToBool(TObject obj); +bool Equals(std::shared_ptr gc, TObject left, TObject right); +typedef void (*PluginFunction)(std::shared_ptr gc, TRootEnvironment *env); +#if !defined(_WIN32) +#define DLLEXPORT +#else +#define DLLEXPORT __declspec(dllexport) +#endif +#define CROSSLANG_PLUGIN(plugin) \ + DLLEXPORT extern "C" void CrossLangPluginInit(std::shared_ptr gc, \ + TRootEnvironment *env) { \ + plugin(gc, env); \ + } + +void LoadPlugin(std::shared_ptr gc, TRootEnvironment *env, + Tesses::Framework::Filesystem::VFSPath sharedObjectPath); +std::string Json_Encode(TObject o, bool indent = false); +TObject Json_Decode(GCList ls, std::string str); +std::string Json_DocEncode(TObject o, bool indent); +TObject Json_DocDecode(GCList ls, std::string str); +// DO NOT USE DIRECTLY +class SharedPtrTObject { + GCList *ls; + TObject o; + + public: + SharedPtrTObject(std::shared_ptr gc, TObject o); + TObject &GetObject(); + std::shared_ptr GetGC(); + ~SharedPtrTObject(); +}; +using MarkedTObject = std::shared_ptr; + +MarkedTObject CreateMarkedTObject(std::shared_ptr gc, TObject o); +MarkedTObject CreateMarkedTObject(GCList *gc, TObject o); +MarkedTObject CreateMarkedTObject(GCList &gc, TObject o); +std::string JoinPeriod(std::vector &p); +TObject GetClassInfo(GCList &ls, TFile *f, uint32_t index); + +extern Tesses::Framework::Filesystem::VFSPath CrossLangConfigPath; + +std::shared_ptr +ToHttpServer(std::shared_ptr gc, TObject obj); + +class EmbedStream : public Tesses::Framework::Streams::Stream { + size_t offset; + MarkedTObject file; + uint32_t resource; + + public: + EmbedStream(std::shared_ptr gc, TFile *file, uint32_t resource); + bool CanRead(); + bool CanSeek(); + bool EndOfStream(); + size_t Read(uint8_t *buff, size_t len); + int64_t GetPosition(); + int64_t GetLength(); + void Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence); +}; + +class EmbedDirectory : public Tesses::Framework::Filesystem::VFS { + MarkedTObject dir; + TObject getEntry(Tesses::Framework::Filesystem::VFSPath path); + + public: + EmbedDirectory(std::shared_ptr gc, TDictionary *dict); + std::shared_ptr + OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode); + + Tesses::Framework::Filesystem::VFSPathEnumerator + EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path); + std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path); + Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path); + + bool Stat(Tesses::Framework::Filesystem::VFSPath path, + Tesses::Framework::Filesystem::StatData &data); +}; + +namespace Programs { +int64_t CrossArchiveCreate(std::vector &argv); +int64_t CrossArchiveExtract(std::vector &argv); +TObject CrossLangInterperter(GCList &ls, TRootEnvironment *env, + std::vector &argv); +TObject CrossLangShell(GCList &ls, std::vector &argv); + +TObject CrossLangVM(GCList &ls, TRootEnvironment *env, + std::vector &argv); + +void CrossLangDump(std::shared_ptr strm); +void CrossLangCompiler(std::vector &argv); +} // namespace Programs + +enum class TQueryableMode { + Passthrough, + Skip, + SkipWhile, + Take, + TakeWhile, + Select, + Where +}; + +class TQueryable : public THeapObject { + + TObject parent; + TQueryableMode mode; + std::vector args; + TQueryable(TObject parent); + TQueryable(TObject parent, TQueryableMode mode, std::vector args); + + public: + static TQueryable *Create(GCList &ls, TObject parent); + static TQueryable *Create(GCList &ls, TObject parent, TQueryableMode mode, + std::vector args); + + TQueryable *Skip(GCList &ls, int64_t no); + TQueryable *SkipWhile(GCList &ls, TCallable *call); + TQueryable *Take(GCList &ls, int64_t no); + TQueryable *TakeWhile(GCList &ls, TCallable *call); + TQueryable *Select(GCList &ls, TCallable *call); + TQueryable *Where(GCList &ls, TCallable *call); + void ForEach(std::shared_ptr gc, TCallable *call); + int64_t Count(std::shared_ptr gc, TCallable *call); + int64_t Count(std::shared_ptr gc); + bool Contains(std::shared_ptr, TObject value); + bool Any(std::shared_ptr gc, TCallable *call); + bool All(std::shared_ptr gc, TCallable *call); + + TList *ToList(GCList &ls); + TEnumerator *GetEnumerator(GCList &ls); + + void Mark(); +}; +}; // namespace Tesses::CrossLang diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt index d298b71..47259a6 100644 --- a/pkgconfig/CMakeLists.txt +++ b/pkgconfig/CMakeLists.txt @@ -10,16 +10,8 @@ else() set(PKGCONFIG_DEPS "") endif() -if(CROSSLANG_ENABLE_STATIC) -configure_file(crosslang_static.pc.in crosslang_static.pc @ONLY) -install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/crosslang_static.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -endif() -if(CROSSLANG_ENABLE_SHARED) configure_file(crosslang.pc.in crosslang.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/crosslang.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -endif() \ No newline at end of file diff --git a/pkgconfig/crosslang.pc.in b/pkgconfig/crosslang.pc.in index e83680b..e19827c 100644 --- a/pkgconfig/crosslang.pc.in +++ b/pkgconfig/crosslang.pc.in @@ -11,4 +11,4 @@ Version: @PROJECT_VERSION@ Requires: tessesframework Cflags: -I"${includedir}" -Libs: -L"${libdir}" -lcrosslang_shared \ No newline at end of file +Libs: -L"${libdir}" -lcrosslang \ No newline at end of file diff --git a/pkgconfig/crosslang_static.pc.in b/pkgconfig/crosslang_static.pc.in deleted file mode 100644 index 94765a2..0000000 --- a/pkgconfig/crosslang_static.pc.in +++ /dev/null @@ -1,14 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -includedir=@PKGCONFIG_INCLUDEDIR@ -libdir=@PKGCONFIG_LIBDIR@ - -Name: @PROJECT_NAME@ -Description: @PKGCONFIG_PROJECT_DESCRIPTION@ -URL: @PKGCONFIG_PROJECT_HOMEPAGE_URL@ -Version: @PROJECT_VERSION@ - -@PKGCONFIG_DEPS@ -Requires: tessesframework_static - -Cflags: -I"${includedir}" -Libs: -L"${libdir}" -lcrosslang_static \ No newline at end of file diff --git a/src/archive.cpp b/src/archive.cpp index 5f70e4e..97e6e4c 100644 --- a/src/archive.cpp +++ b/src/archive.cpp @@ -1,324 +1,306 @@ #include "CrossLang.hpp" #include -namespace Tesses::CrossLang -{ - - void CrossArchiveCreate(std::shared_ptr vfs,std::shared_ptr strm,std::string name, TVMVersion version, std::string info, std::string icon) - { - std::vector ignored_files; - std::string file = "/.crossarchiveignore"; - if(vfs->FileExists(file)) - { - auto strm = vfs->OpenFile(file,"rb"); - if(strm != nullptr) - { - Tesses::Framework::TextStreams::StreamReader reader(strm); - std::string ignores; - while(reader.ReadLine(ignores)) - { - if(!ignores.empty() && ignores[0] != '#') - { - ignored_files.push_back(ignores); - } - ignores.clear(); +namespace Tesses::CrossLang { + +void CrossArchiveCreate( + std::shared_ptr vfs, + std::shared_ptr strm, std::string name, + TVMVersion version, std::string info, std::string icon) { + std::vector ignored_files; + std::string file = "/.crossarchiveignore"; + if (vfs->FileExists(file)) { + auto strm = vfs->OpenFile(file, "rb"); + if (strm != nullptr) { + Tesses::Framework::TextStreams::StreamReader reader(strm); + std::string ignores; + while (reader.ReadLine(ignores)) { + if (!ignores.empty() && ignores[0] != '#') { + ignored_files.push_back(ignores); } + ignores.clear(); } } - static std::vector error_message_byte_code = { - PUSHSTRING, - 0, - 0, - 0, - 2, - GETVARIABLE, - PUSHSTRING, - 0, - 0, - 0, - 3, - PUSHSTRING, - 0, - 0, - 0, - 4, - PUSHLONG, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - CALLMETHOD, - RET - }; - auto writeInt = [](std::shared_ptr strm,uint32_t number)->void{ - uint8_t buff[4]; - BitConverter::FromUint32BE(buff[0],number); - strm->WriteBlock(buff,4); - }; - auto writeStr = [&writeInt](std::shared_ptr strm,std::string text)->void { - writeInt(strm,(uint32_t)text.size()); - strm->WriteBlock((const uint8_t*)text.c_str(),text.size()); - }; - - std::vector strs; - strs.push_back(name); - strs.push_back(info); - strs.push_back("Console"); - strs.push_back("WriteLine"); - strs.push_back("You are trying to run a crvm archive, stop it you won't get anywhere!\nUse crossarchiveextract instead."); - - std::vector resources; - - auto ensureResource = [&resources](std::string path)->uint32_t { - for(uint32_t i = 0; i < (uint32_t)resources.size(); i++) - { - if(resources[i] == path) return i; - } - uint32_t index = (uint32_t)resources.size(); - resources.push_back(path); - return index; - }; - auto ensureString = [&strs](std::string str)->uint32_t { - for(uint32_t i = 0; i < (uint32_t)strs.size(); i++) - { - if(strs[i] == str) return i; - } - uint32_t index = (uint32_t)strs.size(); - strs.push_back(str); - return index; - }; - auto ms = std::make_shared(true); - - std::function walkFS = [&ignored_files,vfs,&ensureString,&ensureResource,&ms,&walkFS,&writeInt](Tesses::Framework::Filesystem::VFSPath path)->void { - - if(vfs->DirectoryExists(path)) - { - - ms->WriteByte(1); - std::vector paths; - for(auto item : vfs->EnumeratePaths(path)) - { - if(!item.relative && item.path.size() == 1 && item.path[0] == "__resdir_tmp") continue; - if(!item.relative && item.path.size() == 1 && item.path[0] == ".crossarchiveignore") continue; - std::string filename = item.GetFileName(); - bool shallIgnore=false; - for(auto ign : ignored_files) if(ign == filename) {shallIgnore=true; break;} - if(shallIgnore) continue; - if(vfs->DirectoryExists(item) || vfs->RegularFileExists(item)) - paths.push_back(item.GetFileName()); - } - writeInt(ms,(uint32_t)paths.size()); - for(auto item : paths) - { - writeInt(ms,ensureString(item)); - walkFS(path / item); - } - } - else if(vfs->RegularFileExists(path)) - { - ms->WriteByte(0); - writeInt(ms,ensureResource(path.ToString())); - } - }; - - walkFS(std::string("/")); - if(!icon.empty()) - ensureResource(icon); - - uint8_t main_header[18]; - memcpy(main_header,"TCROSSVM",8); - TVMVersion rtVersion(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE); - rtVersion.ToArray(main_header+8); - version.ToArray(main_header+13); - strm->WriteBlock(main_header,sizeof(main_header)); - writeInt(strm,(uint32_t)((icon.empty() ? 5 : 6)+resources.size())); - strm->WriteBlock((const uint8_t*)"STRS",4); - uint32_t sz=4; - for(auto str : strs) - sz += (uint32_t)(4 + str.size()); - writeInt(strm,sz); - writeInt(strm,(uint32_t)strs.size()); - for(auto str : strs) - { - writeStr(strm,str); - } - strm->WriteBlock((const uint8_t*)"NAME",4); - writeInt(strm,4); - writeInt(strm,0); - strm->WriteBlock((const uint8_t*)"INFO",4); - writeInt(strm,4); - writeInt(strm,1); - if(!icon.empty()) - { - strm->WriteBlock((const uint8_t*)"ICON",4); - writeInt(strm,4); - writeInt(strm,ensureResource(icon)); - } - strm->WriteBlock((const uint8_t*)"CHKS",4); - writeInt(strm,(uint32_t)(12+error_message_byte_code.size())); - writeInt(strm,1); - writeInt(strm,0); - writeInt(strm,(uint32_t)error_message_byte_code.size()); - strm->WriteBlock(error_message_byte_code.data(),error_message_byte_code.size()); - - - - for(auto res : resources) - { - strm->WriteBlock((const uint8_t*)"RESO",4); - auto strm2 = vfs->OpenFile(res,"rb"); - writeInt(strm,(uint32_t)strm2->GetLength()); - strm2->CopyTo(strm); - - } - strm->WriteBlock((const uint8_t*)"ARCV",4); - writeInt(strm,(uint32_t)ms->GetLength()); - ms->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin); - ms->CopyTo(strm); } - std::pair,std::string> CrossArchiveExtract(std::shared_ptr strm,std::shared_ptr vfs) - { - auto ensure = [strm](uint8_t* buffer,size_t count)->void{ + static std::vector error_message_byte_code = { + PUSHSTRING, 0, 0, 0, 2, GETVARIABLE, PUSHSTRING, 0, 0, 0, + 3, PUSHSTRING, 0, 0, 0, 4, PUSHLONG, 0, 0, 0, + 0, 0, 0, 0, 1, CALLMETHOD, RET}; + auto writeInt = [](std::shared_ptr strm, + uint32_t number) -> void { + uint8_t buff[4]; + BitConverter::FromUint32BE(buff[0], number); + strm->WriteBlock(buff, 4); + }; + auto writeStr = + [&writeInt](std::shared_ptr strm, + std::string text) -> void { + writeInt(strm, (uint32_t)text.size()); + strm->WriteBlock((const uint8_t *)text.c_str(), text.size()); + }; - size_t read = strm->ReadBlock(buffer, count); - if(read < count) throw VMException("End of file, could not read " + std::to_string((int64_t)count) + " byte(s)., offset=" + std::to_string(strm->GetLength())); - }; - auto ensureInt = [&ensure]()->uint32_t { - uint8_t buffer[4]; - ensure(buffer,4); - return BitConverter::ToUint32BE(buffer[0]); - }; - auto ensureStr = [&ensure,&ensureInt]()-> std::string { - auto len = ensureInt(); - if(len == 0) return {}; - std::string str={}; - str.resize((size_t)len); - ensure((uint8_t*)str.data(),str.size()); - return str; - }; - std::vector strs; - auto getStr = [&ensure,&ensureInt,&strs]()-> std::string { - auto index = ensureInt(); - if(index > strs.size()) throw VMException("String does not exist in TCrossVM file, expected string index: " + std::to_string(index) + ", total strings: " + std::to_string(strs.size())); - return strs[index]; - }; - uint8_t main_header[18]; - ensure(main_header,sizeof(main_header)); - if(strncmp((const char*)main_header,"TCROSSVM",8) != 0) throw VMException("Invalid TCrossVM image."); - TVMVersion version(main_header+8); - if(version.CompareToRuntime() == 1) - { - throw VMException("Runtime is too old."); + std::vector strs; + strs.push_back(name); + strs.push_back(info); + strs.push_back("Console"); + strs.push_back("WriteLine"); + strs.push_back("You are trying to run a crvm archive, stop it you won't " + "get anywhere!\nUse crossarchiveextract instead."); + + std::vector resources; + + auto ensureResource = [&resources](std::string path) -> uint32_t { + for (uint32_t i = 0; i < (uint32_t)resources.size(); i++) { + if (resources[i] == path) + return i; } - TVMVersion v2(main_header+13); - std::string name; - std::string info; - + uint32_t index = (uint32_t)resources.size(); + resources.push_back(path); + return index; + }; + auto ensureString = [&strs](std::string str) -> uint32_t { + for (uint32_t i = 0; i < (uint32_t)strs.size(); i++) { + if (strs[i] == str) + return i; + } + uint32_t index = (uint32_t)strs.size(); + strs.push_back(str); + return index; + }; + auto ms = std::make_shared(true); - size_t _len = (size_t)ensureInt(); + std::function walkFS = + [&ignored_files, vfs, &ensureString, &ensureResource, &ms, &walkFS, + &writeInt](Tesses::Framework::Filesystem::VFSPath path) -> void { + if (vfs->DirectoryExists(path)) { - char table_name[4]; - - uint32_t resource_id = 0; - - Tesses::Framework::Filesystem::VFSPath tmpDir("/__resdir_tmp"); - - vfs->CreateDirectory(tmpDir); - for(size_t i = 0;i < _len; i++) - { - ensure((uint8_t*)table_name,sizeof(table_name)); - size_t tableLen = (size_t)ensureInt(); - if(strncmp(table_name,"NAME",4) == 0) - { - name = getStr(); - } - else if(strncmp(table_name,"INFO",4) == 0) - { - info = getStr(); - - } - - else if(strncmp(table_name,"RESO",4) == 0) //resources (using embed) - { - - auto path = tmpDir /std::to_string(resource_id); - - auto strm2 = vfs->OpenFile(path,"wb"); - size_t read = 0; - size_t offset = 0; - uint8_t buff[1024]; - do { - - read = std::min(std::min(tableLen-offset,tableLen), sizeof(buff)); - read = strm->Read(buff,read); - if(read > 0) - strm2->WriteBlock(buff,read); - offset+=read; - } while(read > 0); - - resource_id++; - } - - else if(strncmp(table_name,"STRS",4) == 0) //strings - { - size_t strsLen = (size_t)ensureInt(); - for(size_t j = 0;j < strsLen;j++) - { - strs.push_back(ensureStr()); - } - } - else if(strncmp(table_name,"ARCV",4) == 0) - { - size_t offset = 0; - - std::function walkEntry = [strm,vfs,&getStr,&ensureInt,&tmpDir,&tableLen,&offset,&walkEntry](Tesses::Framework::Filesystem::VFSPath path)->void { - if(offset + 1 > tableLen) return; - uint8_t type = strm->ReadByte(); - offset++; - if(type == 1) - { - //ISDIR - vfs->CreateDirectory(path); - if(offset + 4 > tableLen) return; - uint32_t count = ensureInt(); - offset +=4; - for(uint32_t i = 0; i < count; i++) - { - if(offset + 4 > tableLen) return; - std::string name = getStr(); - offset +=4; - walkEntry(path / name); - } - } - else if(type == 0) - { - if(offset + 4 > tableLen) return; - uint32_t index = ensureInt(); - auto fSrc = tmpDir /std::to_string(index); - vfs->MoveFile(fSrc, path); + ms->WriteByte(1); + std::vector paths; + for (auto item : vfs->EnumeratePaths(path)) { + if (!item.relative && item.path.size() == 1 && + item.path[0] == "__resdir_tmp") + continue; + if (!item.relative && item.path.size() == 1 && + item.path[0] == ".crossarchiveignore") + continue; + std::string filename = item.GetFileName(); + bool shallIgnore = false; + for (auto ign : ignored_files) + if (ign == filename) { + shallIgnore = true; + break; } - }; - - walkEntry(std::string("/")); + if (shallIgnore) + continue; + if (vfs->DirectoryExists(item) || vfs->RegularFileExists(item)) + paths.push_back(item.GetFileName()); } - else - { - if(strm->CanSeek()) - { - strm->Seek((int64_t)tableLen,Tesses::Framework::Streams::SeekOrigin::Current); - } - else{ - uint8_t* buffer=new uint8_t[tableLen]; - ensure(buffer,tableLen); - delete[] buffer; - } + writeInt(ms, (uint32_t)paths.size()); + for (auto item : paths) { + writeInt(ms, ensureString(item)); + walkFS(path / item); } + } else if (vfs->RegularFileExists(path)) { + ms->WriteByte(0); + writeInt(ms, ensureResource(path.ToString())); } - vfs->DeleteDirectoryRecurse(tmpDir); - - return std::pair,std::string>(std::pair(name,v2),info); + }; + + walkFS(std::string("/")); + if (!icon.empty()) + ensureResource(icon); + + uint8_t main_header[18]; + memcpy(main_header, "TCROSSVM", 8); + TVMVersion rtVersion(CROSSLANG_BYTECODE_MAJOR, CROSSLANG_BYTECODE_MINOR, + CROSSLANG_BYTECODE_PATCH, CROSSLANG_BYTECODE_BUILD, + CROSSLANG_BYTECODE_VERSIONSTAGE); + rtVersion.ToArray(main_header + 8); + version.ToArray(main_header + 13); + strm->WriteBlock(main_header, sizeof(main_header)); + writeInt(strm, (uint32_t)((icon.empty() ? 5 : 6) + resources.size())); + strm->WriteBlock((const uint8_t *)"STRS", 4); + uint32_t sz = 4; + for (auto str : strs) + sz += (uint32_t)(4 + str.size()); + writeInt(strm, sz); + writeInt(strm, (uint32_t)strs.size()); + for (auto str : strs) { + writeStr(strm, str); } + strm->WriteBlock((const uint8_t *)"NAME", 4); + writeInt(strm, 4); + writeInt(strm, 0); + strm->WriteBlock((const uint8_t *)"INFO", 4); + writeInt(strm, 4); + writeInt(strm, 1); + if (!icon.empty()) { + strm->WriteBlock((const uint8_t *)"ICON", 4); + writeInt(strm, 4); + writeInt(strm, ensureResource(icon)); + } + strm->WriteBlock((const uint8_t *)"CHKS", 4); + writeInt(strm, (uint32_t)(12 + error_message_byte_code.size())); + writeInt(strm, 1); + writeInt(strm, 0); + writeInt(strm, (uint32_t)error_message_byte_code.size()); + strm->WriteBlock(error_message_byte_code.data(), + error_message_byte_code.size()); + + for (auto res : resources) { + strm->WriteBlock((const uint8_t *)"RESO", 4); + auto strm2 = vfs->OpenFile(res, "rb"); + writeInt(strm, (uint32_t)strm2->GetLength()); + strm2->CopyTo(strm); + } + strm->WriteBlock((const uint8_t *)"ARCV", 4); + writeInt(strm, (uint32_t)ms->GetLength()); + ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin); + ms->CopyTo(strm); } +std::pair, std::string> +CrossArchiveExtract(std::shared_ptr strm, + std::shared_ptr vfs) { + auto ensure = [strm](uint8_t *buffer, size_t count) -> void { + size_t read = strm->ReadBlock(buffer, count); + if (read < count) + throw VMException( + "End of file, could not read " + + std::to_string((int64_t)count) + + " byte(s)., offset=" + std::to_string(strm->GetLength())); + }; + auto ensureInt = [&ensure]() -> uint32_t { + uint8_t buffer[4]; + ensure(buffer, 4); + return BitConverter::ToUint32BE(buffer[0]); + }; + auto ensureStr = [&ensure, &ensureInt]() -> std::string { + auto len = ensureInt(); + if (len == 0) + return {}; + std::string str = {}; + str.resize((size_t)len); + ensure((uint8_t *)str.data(), str.size()); + return str; + }; + std::vector strs; + auto getStr = [&ensure, &ensureInt, &strs]() -> std::string { + auto index = ensureInt(); + if (index > strs.size()) + throw VMException("String does not exist in TCrossVM file, " + "expected string index: " + + std::to_string(index) + ", total strings: " + + std::to_string(strs.size())); + return strs[index]; + }; + uint8_t main_header[18]; + ensure(main_header, sizeof(main_header)); + if (strncmp((const char *)main_header, "TCROSSVM", 8) != 0) + throw VMException("Invalid TCrossVM image."); + TVMVersion version(main_header + 8); + if (version.CompareToRuntime() == 1) { + throw VMException("Runtime is too old."); + } + TVMVersion v2(main_header + 13); + std::string name; + std::string info; + + size_t _len = (size_t)ensureInt(); + + char table_name[4]; + + uint32_t resource_id = 0; + + Tesses::Framework::Filesystem::VFSPath tmpDir("/__resdir_tmp"); + + vfs->CreateDirectory(tmpDir); + for (size_t i = 0; i < _len; i++) { + ensure((uint8_t *)table_name, sizeof(table_name)); + size_t tableLen = (size_t)ensureInt(); + if (strncmp(table_name, "NAME", 4) == 0) { + name = getStr(); + } else if (strncmp(table_name, "INFO", 4) == 0) { + info = getStr(); + + } + + else if (strncmp(table_name, "RESO", 4) == 0) // resources (using embed) + { + + auto path = tmpDir / std::to_string(resource_id); + + auto strm2 = vfs->OpenFile(path, "wb"); + size_t read = 0; + size_t offset = 0; + uint8_t buff[1024]; + do { + + read = std::min(std::min(tableLen - offset, tableLen), + sizeof(buff)); + read = strm->Read(buff, read); + if (read > 0) + strm2->WriteBlock(buff, read); + offset += read; + } while (read > 0); + + resource_id++; + } + + else if (strncmp(table_name, "STRS", 4) == 0) // strings + { + size_t strsLen = (size_t)ensureInt(); + for (size_t j = 0; j < strsLen; j++) { + strs.push_back(ensureStr()); + } + } else if (strncmp(table_name, "ARCV", 4) == 0) { + size_t offset = 0; + + std::function + walkEntry = + [strm, vfs, &getStr, &ensureInt, &tmpDir, &tableLen, + &offset, &walkEntry]( + Tesses::Framework::Filesystem::VFSPath path) -> void { + if (offset + 1 > tableLen) + return; + uint8_t type = strm->ReadByte(); + offset++; + if (type == 1) { + // ISDIR + vfs->CreateDirectory(path); + if (offset + 4 > tableLen) + return; + uint32_t count = ensureInt(); + offset += 4; + for (uint32_t i = 0; i < count; i++) { + if (offset + 4 > tableLen) + return; + std::string name = getStr(); + offset += 4; + walkEntry(path / name); + } + } else if (type == 0) { + if (offset + 4 > tableLen) + return; + uint32_t index = ensureInt(); + auto fSrc = tmpDir / std::to_string(index); + vfs->MoveFile(fSrc, path); + } + }; + + walkEntry(std::string("/")); + } else { + if (strm->CanSeek()) { + strm->Seek((int64_t)tableLen, + Tesses::Framework::Streams::SeekOrigin::Current); + } else { + uint8_t *buffer = new uint8_t[tableLen]; + ensure(buffer, tableLen); + delete[] buffer; + } + } + } + vfs->DeleteDirectoryRecurse(tmpDir); + + return std::pair, std::string>( + std::pair(name, v2), info); +} +} // namespace Tesses::CrossLang diff --git a/src/assembler/asm.cpp b/src/assembler/asm.cpp deleted file mode 100644 index 1c58fd0..0000000 --- a/src/assembler/asm.cpp +++ /dev/null @@ -1,1323 +0,0 @@ -#include "CrossLang.hpp" -using namespace Tesses::Framework::Serialization::Json; - -namespace Tesses::CrossLang { - - class ChunkInstruction { - - public: - virtual ~ChunkInstruction() {} - virtual size_t Size()=0; - }; - - class SimpleChunkInstruction : public ChunkInstruction - { - public: - SimpleChunkInstruction(Instruction instr) : instruction(instr) - { - - } - Instruction instruction; - size_t Size() - { - return 1; - } - - }; - - class PushLongChunkInstruction : public ChunkInstruction { - public: - PushLongChunkInstruction(int64_t v) : value(v) - {} - int64_t value; - - size_t Size() - { - return 9; - } - }; - class PushDoubleChunkInstruction : public ChunkInstruction { - public: - PushDoubleChunkInstruction(double v) : value(v) - {} - double value; - - size_t Size() - { - return 9; - } - }; - - - class PushStringChunkInstruction : public ChunkInstruction { - public: - PushStringChunkInstruction(std::string v) : value(v) - {} - std::string value; - - size_t Size() - { - return 5; - } - }; - - class PushCharChunkInstruction : public ChunkInstruction { - public: - PushCharChunkInstruction(char v) : value(v) - {} - char value; - size_t Size() - { - return 2; - } - }; - - class PushResourceChunkInstruction : public ChunkInstruction { - public: - PushResourceChunkInstruction(std::string v) : value(v) - {} - std::string value; - size_t Size() - { - return 5; - } - }; - - - class PushResourceStreamChunkInstruction : public ChunkInstruction { - public: - PushResourceStreamChunkInstruction(std::string v) : value(v) - {} - std::string value; - size_t Size() - { - return 5; - } - }; - - class LabelChunkInstruction : public ChunkInstruction { - public: - LabelChunkInstruction(std::string lbl) : lbl(lbl) - {} - std::string lbl; - size_t Size() - { - return 0; - } - }; - class JumpStyleChunkInstruction : public ChunkInstruction { - public: - JumpStyleChunkInstruction(Instruction instr,std::string lbl) : instr(instr), lbl(lbl) - { - - } - Instruction instr; - std::string lbl; - size_t Size() - { - return 5; - } - }; - - class ScopeEndTimesChunkInstruction : public ChunkInstruction { - public: - ScopeEndTimesChunkInstruction(uint32_t times) : times(times) - {} - uint32_t times; - size_t Size() - { - return 5; - } - }; - - class ChunkData { - public: - std::vector args; - std::vector> instructions; - - }; - class ClosureChunkInstruction : public ChunkInstruction { - public: - ClosureChunkInstruction(bool scoped) : scoped(scoped) - { - - } - ChunkData data; - bool scoped; - size_t Size() - { - return 5; - } - }; - - - class FunctionData { - public: - std::vector name; - ChunkData chunk; - - }; - class ClassDataEntry { - public: - ChunkData data; - std::string documentation; - std::string name; - TClassModifier modifier; - bool isFunction; - bool isAbstract; - }; - class ClassData { - public: - std::string documentation; - std::vector name; - std::vector inherits; - std::vector entries; - }; - class AssemblerParser { - std::vector& tokens; - size_t i=0; - std::string ReadIdent() - { - if(i >= tokens.size()) throw std::out_of_range("End of file"); - if(tokens[i].type != LexTokenType::Identifier) throw std::runtime_error("Expected an identifier"); - return tokens[i++].text; - } - bool IsIdent(std::string val,bool pop=true) - { - if(i >= tokens.size()) return false; - if(tokens[i].type != LexTokenType::Identifier) return false; - if(tokens[i].text != val) return false; - if(pop) i++; - return true; - } - bool IsSym(std::string val,bool pop=true) - { - if(i >= tokens.size()) return false; - if(tokens[i].type != LexTokenType::Symbol) return false; - if(tokens[i].text != val) return false; - if(pop) i++; - return true; - } - - void ParseClosureInstructions(std::vector>& instrs, std::string lbl_prefix) - { - while(!IsSym("}",false)) - { - auto name = ReadIdent(); - - if(name == "add") - { - instrs.push_back(std::make_shared(ADD)); - } - else if(name == "sub") - { - instrs.push_back(std::make_shared(SUB)); - } - else if(name == "mul") - { - instrs.push_back(std::make_shared(TIMES)); - } - else if(name == "div") - { - instrs.push_back(std::make_shared(DIVIDE)); - } - else if(name == "mod") - { - instrs.push_back(std::make_shared(MODULO)); - } - else if(name == "lsh") - { - instrs.push_back(std::make_shared(LEFTSHIFT)); - } - else if(name == "rsh") - { - instrs.push_back(std::make_shared(RIGHTSHIFT)); - } - else if(name == "bor") - { - instrs.push_back(std::make_shared(BITWISEOR)); - } - else if(name == "band") - { - instrs.push_back(std::make_shared(BITWISEAND)); - } - else if(name == "bnot") - { - instrs.push_back(std::make_shared(BITWISENOT)); - } - else if(name == "lt") - { - instrs.push_back(std::make_shared(LESSTHAN)); - } - else if(name == "gt") - { - instrs.push_back(std::make_shared(GREATERTHAN)); - } - else if(name == "lte") - { - instrs.push_back(std::make_shared(LESSTHANEQ)); - } - else if(name == "gte") - { - instrs.push_back(std::make_shared(GREATERTHANEQ)); - } - else if(name == "eq") - { - instrs.push_back(std::make_shared(EQ)); - } - else if(name == "neq") - { - instrs.push_back(std::make_shared(NEQ)); - } - else if(name == "not") - { - instrs.push_back(std::make_shared(NOT)); - } - else if(name == "neg") - { - instrs.push_back(std::make_shared(NEGATIVE)); - } - else if(name == "xor") - { - instrs.push_back(std::make_shared(XOR)); - } - else if(name == "pop") - { - instrs.push_back(std::make_shared(POP)); - } - else if(name == "dup") - { - instrs.push_back(std::make_shared(DUP)); - } - else if(name == "nop") - { - instrs.push_back(std::make_shared(NOP)); - } - else if(name == "lineinfo") - { - instrs.push_back(std::make_shared(LINEINFO)); - } - else if(name == "embeddir") - { - instrs.push_back(std::make_shared(PUSHRESOUURCEDIR)); - } - else if(name == "pushclosure") - { - auto closure = std::make_shared(true); - EnsureSymbol("("); - while(!IsSym(")",false) && i < tokens.size()) - { - closure->data.args.push_back(ReadIdent()); - IsSym(","); - } - EnsureSymbol(")"); - EnsureSymbol("{"); - ParseClosureInstructions(closure->data.instructions,"closure"); - EnsureSymbol("}"); - instrs.push_back(closure); - //instrs.push_back(std::make_shared(JMPC,lblName)); - } - else if(name == "createdict") - { - instrs.push_back(std::make_shared(CREATEDICTIONARY)); - } - else if(name == "createarray") - { - instrs.push_back(std::make_shared(CREATEARRAY)); - } - else if(name == "appendlist") - { - instrs.push_back(std::make_shared(APPENDLIST)); - } - else if(name == "appenddict") - { - instrs.push_back(std::make_shared(APPENDDICT)); - } - else if(name == "embed") - { - if(i < tokens.size() && tokens[i].type == LexTokenType::String) - { - std::string str = tokens[i++].text; - instrs.push_back(std::make_shared(str)); - } - } - else if(name == "embedstrm") - { - if(i < tokens.size() && tokens[i].type == LexTokenType::String) - { - std::string str = tokens[i++].text; - instrs.push_back(std::make_shared(str)); - } - } - else if(name == "push") - { - if(IsSym(".")) - { - instrs.push_back(std::make_shared(PUSHRELATIVEPATH)); - } - else if(IsSym("/")) - { - instrs.push_back(std::make_shared(PUSHROOTPATH)); - } - else if(IsSym("}",false)) - { - throw std::runtime_error("Push needs an argument"); - } - else if(i < tokens.size() && tokens[i].type == LexTokenType::Identifier) - { - - std::string token = tokens[i].text; - - i++; - - bool hasNumber=true; - int64_t lngNum = 0; - - if(token.size() == 1 && token[0] == '0') - { - lngNum = 0; - } - else if(token.size() > 0 && token[0] == '0') - { - if(token.size() > 1 && token[1] == 'x') - { - lngNum = std::stoll(token.substr(2),nullptr,16); - } - else if(token.size() > 1 && token[1] == 'b') - { - lngNum = std::stoll(token.substr(2),nullptr,2); - } - else - { - lngNum = std::stoll(token.substr(1),nullptr,8); - } - - } - else if(token.size() > 0 && token[0] >= '0' && token[0] <= '9') - { - lngNum=std::stoll(token,nullptr,10); - } - else - { - hasNumber = false; - } - - if(hasNumber && this->IsSym(".",false) && i+1 < tokens.size() && tokens[i+1].type == LexTokenType::Identifier) - { - std::string myToken = tokens[i+1].text; - if(myToken.size() > 0 && myToken[0] >= '0' && myToken[0] <= '9') - { - i+=2; - std::string myN = std::to_string(lngNum) + "." + myToken; - - double v = std::stod(myN,nullptr); - - - instrs.push_back(std::make_shared(v)); - } - else - { - - instrs.push_back(std::make_shared(lngNum)); - } - } - else if(hasNumber) - { - - instrs.push_back(std::make_shared(lngNum)); - } - - if(!hasNumber) - { - if(token == "true") - instrs.push_back(std::make_shared(PUSHTRUE)); - if(token == "false") - instrs.push_back(std::make_shared(PUSHFALSE)); - if(token == "null") - instrs.push_back(std::make_shared(PUSHNULL)); - if(token == "undefined") - instrs.push_back(std::make_shared(PUSHUNDEFINED)); - if(token == "break") - instrs.push_back(std::make_shared(PUSHBREAK)); - - if(token == "continue") - instrs.push_back(std::make_shared(PUSHCONTINUE)); - } - } - else if(i < tokens.size() && tokens[i].type == LexTokenType::String) - { - instrs.push_back(std::make_shared(tokens[i++].text)); - - } - else if(i < tokens.size() && tokens[i].type == LexTokenType::Char) - { - instrs.push_back(std::make_shared(tokens[i++].text[0])); - } - } - else if(name == "scopebegin") - { - instrs.push_back(std::make_shared(SCOPEBEGIN)); - } - else if(name == "scopeend") - { - instrs.push_back(std::make_shared(SCOPEEND)); - } - else if(name == "scopeendtimes") - { - if(tokens[i].type == LexTokenType::Identifier) - instrs.push_back(std::make_shared((uint32_t)std::stoul(tokens[i++].text))); - } - else if(name == "setvariable") - { - instrs.push_back(std::make_shared(SETVARIABLE)); - } - else if(name == "getvariable") - { - instrs.push_back(std::make_shared(GETVARIABLE)); - } - else if(name == "declarevariable") - { - instrs.push_back(std::make_shared(DECLAREVARIABLE)); - } - else if(name == "declareconstvariable") - { - instrs.push_back(std::make_shared(DECLARECONSTVARIABLE)); - } - else if(name == "setfield") - { - instrs.push_back(std::make_shared(SETFIELD)); - } - else if(name == "getfield") - { - instrs.push_back(std::make_shared(GETFIELD)); - } - else if(name == "callfunction") - { - instrs.push_back(std::make_shared(CALLFUNCTION)); - } - else if(name == "callmethod") - { - instrs.push_back(std::make_shared(CALLMETHOD)); - } - else if(name == "ret") - { - instrs.push_back(std::make_shared(RET)); - } - else if(name == "jmpc") - { - auto lblName = lbl_prefix + "_" + ReadIdent(); - instrs.push_back(std::make_shared(JMPC,lblName)); - } - else if(name == "jmp") - { - auto lblName = lbl_prefix + "_" + ReadIdent(); - instrs.push_back(std::make_shared(JMP,lblName)); - } - else if(name == "jmpundefined") - { - auto lblName = lbl_prefix + "_" + ReadIdent(); - instrs.push_back(std::make_shared(JMPUNDEFINED,lblName)); - } - else if(name == "defer") - { - instrs.push_back(std::make_shared(DEFER)); - } - else if(name == "trycatch") - { - instrs.push_back(std::make_shared(TRYCATCH)); - } - else if(name == "throw") - { - instrs.push_back(std::make_shared(THROW)); - } - else if(name == "pushscopelessclosure") - { - auto closure = std::make_shared(false); - EnsureSymbol("("); - while(!IsSym(")",false) && i < tokens.size()) - { - closure->data.args.push_back(ReadIdent()); - IsSym(","); - } - EnsureSymbol(")"); - EnsureSymbol("{"); - ParseClosureInstructions(closure->data.instructions,"closure"); - EnsureSymbol("}"); - instrs.push_back(closure); - //instrs.push_back(std::make_shared(JMPC,lblName)); - } - else if(name == "yield") - { - instrs.push_back(std::make_shared(YIELD)); - } - else if(name == "breakpoint") - { - instrs.push_back(std::make_shared(BREAKPOINT)); - } - else if(name == "jmpifbreak") - { - auto lblName = lbl_prefix + "_" + ReadIdent(); - instrs.push_back(std::make_shared(JMPIFBREAK,lblName)); - } - else if(name == "jmpifcontinue") - { - auto lblName = lbl_prefix + "_" + ReadIdent(); - instrs.push_back(std::make_shared(JMPIFCONTINUE,lblName)); - } - else if(name == "jmpifdefined") - { - auto lblName = lbl_prefix + "_" + ReadIdent(); - instrs.push_back(std::make_shared(JMPIFDEFINED,lblName)); - } - else if(name == "lbl") - { - auto lblName = lbl_prefix + "_" + ReadIdent(); - instrs.push_back(std::make_shared(lblName)); - } - else { - throw std::runtime_error("NOT IMPLEMENTED: " + name); - } - } - } - void EnsureSymbol(std::string txt) - { - if(i < tokens.size()) - { - if(tokens[i].type != LexTokenType::Symbol) - { - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but did not get a symbol at all."); - } - if(tokens[i].text != txt) - { - - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + "\""); - } - i++; - return; - } - throw std::out_of_range("End of file"); - } - std::string ParseDocumentation() - { - if(i >= tokens.size()) return {}; - if(tokens[i].type != LexTokenType::Documentation) return {}; - return tokens[i++].text; - } - public: - AssemblerParser(std::vector& tokens) : tokens(tokens) - { - size_t root=0; - - while(i < tokens.size()) - { - auto doc = ParseDocumentation(); - - if(IsIdent("root")) { - EnsureSymbol("{"); - ParseClosureInstructions(this->root.instructions, "root_" + std::to_string(root)); - EnsureSymbol("}"); - root++; - } - else if(IsIdent("func")) { - FunctionData fdata; - fdata.name.push_back(doc); - fdata.name.push_back(ReadIdent()); - while(IsSym(".")) - { - fdata.name.push_back(ReadIdent()); - } - EnsureSymbol("("); - while(!IsSym(")",false) && i < tokens.size()) - { - fdata.chunk.args.push_back(ReadIdent()); - IsSym(","); - } - EnsureSymbol(")"); - - EnsureSymbol("{"); - ParseClosureInstructions(fdata.chunk.instructions, "func_" + std::to_string(root)); - EnsureSymbol("}"); - this->functions.push_back(fdata); - } - else if(IsIdent("class")) - { - ClassData cdata; - cdata.documentation = doc; - cdata.name.push_back(ReadIdent()); - while(IsSym(".")) - { - cdata.name.push_back(ReadIdent()); - } - if(IsSym(":")) - { - cdata.inherits.push_back(ReadIdent()); - while(IsSym(".")) - { - cdata.inherits.push_back(ReadIdent()); - } - } - else { - cdata.inherits.push_back("ClassObject"); - } - - EnsureSymbol("{"); - - while(i < tokens.size() && !IsSym("}",false)) - { - - ClassDataEntry ent; - ent.documentation = ParseDocumentation(); - - - if(IsIdent("public")) - { - ent.modifier = TClassModifier::Public; - } - else if(IsIdent("protected")) - { - ent.modifier = TClassModifier::Protected; - } - else if(IsIdent("private")) - { - ent.modifier = TClassModifier::Private; - } - else if(IsIdent("static")) - { - ent.modifier = TClassModifier::Static; - } - else throw std::runtime_error("Invalid modifier on class entry"); - - if(IsIdent("abstract")) - { - ent.name = ReadIdent(); - ent.isAbstract = true; - ent.isFunction=true; - - - EnsureSymbol("("); - while(!IsSym(")",false) && i < tokens.size()) - { - ent.data.args.push_back(ReadIdent()); - IsSym(","); - } - EnsureSymbol(")"); - EnsureSymbol(";"); - } - else { - ent.name = ReadIdent(); - if(IsSym("(")) - { - ent.isFunction=true; - ent.isAbstract=false; - while(!IsSym(")",false) && i < tokens.size()) - { - ent.data.args.push_back(ReadIdent()); - IsSym(","); - } - EnsureSymbol(")"); - EnsureSymbol("{"); - ParseClosureInstructions(ent.data.instructions,"cls_fn"); - EnsureSymbol("}"); - } - else if(IsSym(";")) - { - - ent.isFunction=false; - ent.isAbstract=true; - } - else if(IsSym("{")) - { - - ent.isFunction=false; - ent.isAbstract=false; - EnsureSymbol("{"); - ParseClosureInstructions(ent.data.instructions,"cls_field"); - EnsureSymbol("}"); - - } - } - cdata.entries.push_back(ent); - } - - EnsureSymbol("}"); - - this->classes.push_back(cdata); - } - } - } - - ChunkData root; - std::vector functions; - std::vector classes; - - - }; - - class CodeGen2 { - public: - void Write(std::shared_ptr strm, uint8_t* buffer, size_t len) - { - strm->WriteBlock(buffer,len); - } - void WriteInt(std::shared_ptr strm,uint32_t v) - { - uint8_t buffer[4]; - BitConverter::FromUint32BE(buffer[0],v); - Write(strm,buffer,4); - } - void WriteString(std::shared_ptr strm,std::string v) - { - WriteInt(strm,(uint32_t)v.size()); - Write(strm,(uint8_t*)v.data(),v.size()); - } - void Save(std::shared_ptr vfs, std::shared_ptr stream) - { - - TVMVersion runtime_version(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE); - uint8_t buffer[18]; - memcpy(buffer,"TCROSSVM",8); - runtime_version.ToArray(buffer+8); - version.ToArray(buffer+13); - Write(stream,buffer,18); - uint32_t sections=5; - uint32_t name = GetString(this->name); - uint32_t info = GetString(this->info); - - for(auto& dep : this->dependencies) - { - GetString(dep.first); - sections++; - } - for(auto& tool : this->tools) - { - GetString(tool.first); - sections++; - } - if(!this->icon.empty()) - { - this->GetResource(this->icon); - - } - for(auto& sec : this->sections) - sections++; - for(auto& vm : this->vms) - { - this->GetString(vm.first); - this->GetString(vm.second); - sections++; - } - - for(auto& res : this->res) - sections++; - - if(!this->icon.empty()) - sections++; - if(!this->classes.empty()) - sections++; - - - WriteInt(stream,sections); - uint32_t strSz=4; - for(auto& s : this->strs) - { - strSz += (uint32_t)s.size() + 4; - } - memcpy(buffer,"STRS",4); - Write(stream,buffer,4); - WriteInt(stream,strSz); //even though its ignored - WriteInt(stream,this->strs.size()); - for(auto& str : this->strs) - WriteString(stream,str); - memcpy(buffer,"NAME",4); - Write(stream,buffer,4); - WriteInt(stream,4); - WriteInt(stream,name); - memcpy(buffer,"INFO",4); - Write(stream,buffer,4); - WriteInt(stream,4); - WriteInt(stream,info); - - for(auto& dep : this->dependencies) - { - memcpy(buffer,"DEPS",4); - Write(stream,buffer,4); - WriteInt(stream,9); //even though its ignored - WriteInt(stream,GetString(dep.first)); - dep.second.ToArray(buffer); - Write(stream,buffer,5); - } - for(auto& tool : this->tools) - { - memcpy(buffer,"TOOL",4); - Write(stream,buffer,4); - WriteInt(stream,9); //even though its ignored - WriteInt(stream,GetString(tool.first)); - tool.second.ToArray(buffer); - Write(stream,buffer,5); - } - - for(auto& vm : this->vms) - { - memcpy(buffer,"MACH",4); - Write(stream,buffer,4); - WriteInt(stream,8); //even though its ignored - WriteInt(stream,GetString(vm.first)); - WriteInt(stream,GetString(vm.second)); - - } - - uint32_t fnLen=4; - - for(auto& fn : this->funcs) - { - fnLen += (fn.first.size() + 2) * 4; - } - - memcpy(buffer,"FUNS",4); - Write(stream,buffer,4); - WriteInt(stream,fnLen); - WriteInt(stream,(uint32_t)this->funcs.size()); - for(auto& fn : this->funcs) - { - WriteInt(stream,(uint32_t)fn.first.size()); - for(auto namePart : fn.first) - { - WriteInt(stream,namePart); - } - WriteInt(stream,fn.second); - } - - uint32_t clength = 4; - - memcpy(buffer,"CHKS",4); - Write(stream,buffer,4); - WriteInt(stream,clength); - WriteInt(stream,(uint32_t)this->chunks.size()); - for(auto& chunk : this->chunks) - { - std::vector buffer; - WriteInt(stream,(uint32_t)chunk.first.size()); - for(auto arg : chunk.first) - { - WriteInt(stream,arg); - } - for(auto instr : chunk.second) - { - instr->Write(buffer); - } - WriteInt(stream,(uint32_t)buffer.size()); - Write(stream,buffer.data(),buffer.size()); - } - - if(!classes.empty()) - { - uint32_t len = 4; - for(auto& cls : classes) - { - len += 8; - len += cls.name.size() * 4; - len += 4; - len += cls.inherits.size() * 4; - len += 4; - for(auto& clsEnt : cls.entries) - { - len += 17; - for(auto& arg : clsEnt.arguments) len+=4; - } - } - - memcpy(buffer,"CLSS",4); - Write(stream,buffer,4); - WriteInt(stream,len); - WriteInt(stream,(uint32_t)classes.size()); - for(auto& cls : classes) - { - WriteInt(stream,cls.documentation); - WriteInt(stream,(uint32_t)cls.name.size()); - for(auto namePart : cls.name) WriteInt(stream,namePart); - - WriteInt(stream,(uint32_t)cls.inherits.size()); - for(auto inhPart : cls.inherits) WriteInt(stream,inhPart); - - WriteInt(stream,(uint32_t)cls.entries.size()); - - for(auto& ent : cls.entries) - { - buffer[0] = ent.type; - Write(stream,buffer,1); - WriteInt(stream,ent.documentation); - WriteInt(stream,ent.name); - WriteInt(stream,(uint32_t)ent.arguments.size()); - for(auto ar : ent.arguments) - { - WriteInt(stream,ar); - } - WriteInt(stream,ent.closure); - } - } - } - - for(auto& reso : res) - { - memcpy(buffer,"RESO",4); - Write(stream,buffer,4); - - auto strm = vfs->OpenFile(reso,"rb"); - if(strm->EndOfStream()) - { - WriteInt(stream,0); - - } - else { - WriteInt(stream, (uint32_t)strm->GetLength()); - strm->CopyTo(stream); - } - - } - if(!this->icon.empty()) - { - memcpy(buffer,"ICON",4); - Write(stream,buffer,4); - WriteInt(stream,4); - WriteInt(stream,this->GetResource(this->icon)); - - } - for(auto& sect : this->sections) - { - memcpy(buffer,sect.first.data(),4); - Write(stream,buffer,4); - WriteInt(stream,(uint32_t)sect.second.size()); - Write(stream,sect.second.data(),sect.second.size()); - } - } - - - uint32_t GetResource(std::string resource) - { - for(uint32_t i = 0; i < (uint32_t)this->res.size();i++) - { - if(this->res[i] == resource) return i; - } - uint32_t resI = (uint32_t)this->res.size(); - this->res.push_back(resource); - return resI; - } - uint32_t GetString(std::string str) - { - for(uint32_t i = 0; i < (uint32_t)this->strs.size();i++) - { - if(this->strs[i] == str) return i; - } - uint32_t strI = (uint32_t)this->strs.size(); - this->strs.push_back(str); - return strI; - } - - std::vector strs; - std::vector res; - std::vector,uint32_t>> funcs; - std::vector classes; - std::vector, std::vector>>> chunks; - - std::vector> dependencies; - std::vector> tools; - std::vector>> sections; - std::vector> vms; - TVMVersion version; - std::string name; - std::string info; - std::string icon; - - uint32_t PushChunk(ChunkData& data) - { - uint32_t chunkId = chunks.size(); - - chunks.push_back(std::pair,std::vector>>()); - chunks[chunkId].first.resize(data.args.size()); - for(size_t i = 0; i < data.args.size(); i++) - { - chunks[chunkId].first[i] = GetString(data.args[i]); - } - - std::map labels; - - uint32_t offset=0; - - for(auto item : data.instructions) - { - offset += item->Size(); - - auto lbl = std::dynamic_pointer_cast(item); - auto simp = std::dynamic_pointer_cast(item); - auto lng = std::dynamic_pointer_cast(item); - auto dbl = std::dynamic_pointer_cast(item); - auto str = std::dynamic_pointer_cast(item); - auto chr = std::dynamic_pointer_cast(item); - auto chk = std::dynamic_pointer_cast(item); - auto reso = std::dynamic_pointer_cast(item); - auto resos = std::dynamic_pointer_cast(item); - auto jmp = std::dynamic_pointer_cast(item); - auto scopeend = std::dynamic_pointer_cast(item); - if(lbl) - { - labels[lbl->lbl] = offset; - } - if(simp) - { - chunks[chunkId].second.push_back(std::make_shared(simp->instruction)); - } - if(lng) - { - chunks[chunkId].second.push_back(std::make_shared(lng->value)); - } - if(dbl) - { - chunks[chunkId].second.push_back(std::make_shared(dbl->value)); - } - if(str) - { - chunks[chunkId].second.push_back(std::make_shared(GetString(str->value))); - } - if(chr) - { - chunks[chunkId].second.push_back(std::make_shared(chr->value)); - } - if(chk) - { - auto item = std::make_shared(PushChunk(chk->data),chk->scoped); - chunks[chunkId].second.push_back(item); - } - if(reso) - { - chunks[chunkId].second.push_back(std::make_shared(GetResource(reso->value))); - } - if(resos) - { - chunks[chunkId].second.push_back(std::make_shared(GetResource(reso->value))); - } - if(jmp) - { - chunks[chunkId].second.push_back(std::make_shared(jmp->instr,jmp->lbl)); - } - if(scopeend) - { - chunks[chunkId].second.push_back(std::make_shared(scopeend->times)); - } - } - - for(auto& item : chunks[chunkId].second) - { - auto jmp = std::dynamic_pointer_cast(item); - if(jmp) - { - jmp->n = labels[jmp->label]; - } - } - return chunkId; - } - }; - - - - - - Tesses::Framework::Filesystem::VFSPath Assemble(std::shared_ptr vfs) - { - using namespace Tesses::Framework::Filesystem; - using namespace Tesses::Framework::TextStreams; - std::function getSrc; - - std::vector tokens; - - getSrc = [&](VFSPath path)->void { - if(vfs->DirectoryExists(path)) - for(auto item : vfs->EnumeratePaths(path)) - { - if(vfs->DirectoryExists(item)) - { - getSrc(item); - } - else { - if(item.GetExtension() == ".tcasm") - { - StreamReader reader(vfs->OpenFile(item,"rb")); - - std::stringstream strm(reader.ReadToEnd(),std::ios_base::binary | std::ios_base::in); - Lex(item.ToString(), strm, tokens); - } - } - } - }; - - getSrc(VFSPath() / "src"); - - AssemblerParser parser(tokens); - CodeGen2 cg2; - cg2.name = "out"; - cg2.version = TVMVersion(1,0,0,0,TVMVersionStage::ProductionVersion); - - - auto confFile = VFSPath() / "crossapp.json"; - if(vfs->FileExists(confFile)) - { - Tesses::Framework::TextStreams::StreamReader reader(vfs->OpenFile(confFile,"rb")); - auto jobj = Json::Decode(reader.ReadToEnd()); - JObject main; - if(TryGetJToken(jobj,main)) - { - TVMVersion version; - std::string str0; - std::string str1; - JObject dict0; - JArray array0; - - main.TryGetValueAsType("name",cg2.name); - if(main.TryGetValueAsType("version",str0)) - TVMVersion::TryParse(str0, cg2.version); - - if(main.TryGetValueAsType("info",dict0)) - cg2.info = Json::Encode(dict0,false); - - main.TryGetValueAsType("icon", cg2.icon); - - if(main.TryGetValueAsType("dependencies",array0)) - { - for(auto item : array0) - { - if(TryGetJToken(item,dict0)) - { - if(dict0.TryGetValueAsType("version", str1) && TVMVersion::TryParse(str1,version) && dict0.TryGetValueAsType("name",str0)) - { - cg2.dependencies.emplace_back(str0, version); - } - - } - } - } - if(main.TryGetValueAsType("tools",array0)) - { - for(auto item : array0) - { - if(TryGetJToken(item,dict0)) - { - if(dict0.TryGetValueAsType("version", str1) && TVMVersion::TryParse(str1,version) && dict0.TryGetValueAsType("name",str0)) - { - cg2.tools.emplace_back(str0, version); - } - - } - } - } - if(main.TryGetValueAsType("vms",array0)) - { - for(auto item : array0) - { - if(TryGetJToken(item,dict0)) - { - if(dict0.TryGetValueAsType("name", str0) && dict0.TryGetValueAsType("how_to_get",str1)) - { - cg2.vms.emplace_back(str0, str1); - } - - } - } - } - - } - } - - cg2.PushChunk(parser.root); - for(auto& fn : parser.functions) - { - std::vector nameParts; - nameParts.resize(fn.name.size()); - for(size_t i = 0; i < fn.name.size(); i++) - { - nameParts[i] = cg2.GetString(fn.name[i]); - } - - auto chunk = cg2.PushChunk(fn.chunk); - cg2.funcs.push_back(std::pair,uint32_t>(nameParts,chunk)); - } - for(auto& cls : parser.classes) - { - CodeGenClass cls2; - cls2.name.resize(cls.name.size()); - for(size_t i = 0; i < cls.name.size(); i++) - { - cls2.name[i] = cg2.GetString(cls.name[i]); - } - - cls2.inherits.resize(cls.inherits.size()); - for(size_t i = 0; i < cls.inherits.size(); i++) - { - cls2.inherits[i] = cg2.GetString(cls.inherits[i]); - } - - cls2.documentation = cg2.GetString(cls.documentation); - - for(auto clsItem : cls.entries) - { - CodeGenClassEntry ent; - ent.type = 0; - ent.type = (uint8_t)clsItem.modifier & 3; - if(clsItem.isAbstract) ent.type |= 0b00001000; - if(!clsItem.isFunction) ent.type |= 0b00000100; - ent.documentation = cg2.GetString(clsItem.documentation); - ent.name = cg2.GetString(clsItem.name); - ent.closure = 0; - ent.arguments.resize(clsItem.data.args.size()); - for(size_t i = 0; i < clsItem.data.args.size(); i++) - { - ent.arguments[i] = cg2.GetString(clsItem.data.args[i]); - } - if(!clsItem.isAbstract) - { - ent.closure = cg2.PushChunk(clsItem.data); - - } - - cls2.entries.push_back(ent); - } - cg2.classes.push_back(cls2); - } - vfs->CreateDirectory(VFSPath() / "res"); - vfs->CreateDirectory(VFSPath() / "bin"); - vfs->CreateDirectory(VFSPath() / "sections"); - - auto sectionsdir = std::make_shared(vfs,VFSPath() / "sections"); - auto resdir = std::make_shared(vfs,VFSPath() / "res"); - - for(auto file : sectionsdir->EnumeratePaths(VFSPath())) - { - if(file.GetExtension() == ".tsec" && sectionsdir->FileExists(file)) - { - auto strm0 = sectionsdir->OpenFile(file,"rb"); - int64_t len = strm0->GetLength(); - if(len > 4) - { - std::string name(4,' '); - strm0->ReadBlock((uint8_t*)name.data(),4); - - size_t off = cg2.sections.size(); - cg2.sections.push_back(std::pair>(name,{})); - cg2.sections[off].second.resize((size_t)len-4); - strm0->ReadBlock(cg2.sections[off].second.data(), cg2.sections[off].second.size()); - } - - - } - } - - - - auto strm = vfs->OpenFile(VFSPath() / "bin" / cg2.name + "-" + cg2.version.ToString() + ".crvm","wb"); - cg2.Save(resdir, strm); - - - - return VFSPath() / "bin" / cg2.name + "-" + cg2.version.ToString() + ".crvm"; - - } - -} diff --git a/src/assembler/disasm.cpp b/src/assembler/disasm.cpp deleted file mode 100644 index ff6d249..0000000 --- a/src/assembler/disasm.cpp +++ /dev/null @@ -1,917 +0,0 @@ -#include "CrossLang.hpp" - -namespace Tesses::CrossLang { - class CrossLangFileReader { - std::shared_ptr strm; - - void Ensure(uint8_t* buffer, size_t len) - { - auto read = this->strm->ReadBlock(buffer, len); - if(read < len) throw VMException("End of file, could not read " + std::to_string((int64_t)len) + " byte(s)., offset=" + std::to_string(strm->GetLength())); - } - - uint32_t ReadInt() - { - uint8_t buffer[4]; - Ensure(buffer,4); - return BitConverter::ToUint32BE(buffer[0]); - } - std::string ReadString() - { - auto len = ReadInt(); - if(len == 0) return {}; - std::string str={}; - str.resize((size_t)len); - Ensure((uint8_t*)str.data(),str.size()); - return str; - } - - std::string GetString() - { - uint32_t index=ReadInt(); - if(index >= this->strings.size()) throw VMException("String does not exist in TCrossVM file, expected string index: " + std::to_string(index) + ", total strings: " + std::to_string(this->strings.size())); - return this->strings[index]; - } - - public: - CrossLangFileReader(std::shared_ptr strm) - { - this->strm = strm; - - - - uint8_t main_header[18]; - Ensure(main_header,sizeof(main_header)); - if(strncmp((const char*)main_header,"TCROSSVM",8) != 0) throw VMException("Invalid TCrossVM image."); - TVMVersion version(main_header+8); - if(version.CompareToRuntime() == 1) - { - throw VMException("Runtime is too old."); - } - TVMVersion v2(main_header+13); - this->version = v2; - - size_t _len = (size_t)ReadInt(); - - char table_name[4]; - - for(size_t i = 0;i < _len; i++) - { - Ensure((uint8_t*)table_name,sizeof(table_name)); - size_t tableLen = (size_t)ReadInt(); - if(strncmp(table_name,"NAME",4) == 0) - { - this->name = GetString(); - } - else if(strncmp(table_name,"INFO",4) == 0) - { - this->info = GetString(); - } - else if(strncmp(table_name,"DEPS",4) == 0) //dependencies - { - std::string name = GetString(); - uint8_t version_bytes[5]; - Ensure(version_bytes,sizeof(version_bytes)); - TVMVersion depVersion(version_bytes); - this->dependencies.push_back(std::pair(name, depVersion)); - } - else if(strncmp(table_name,"TOOL",4) == 0) //compile tools (for package manager) - { - std::string name = GetString(); - uint8_t version_bytes[5]; - Ensure(version_bytes,sizeof(version_bytes)); - TVMVersion depVersion(version_bytes); - this->tools.push_back(std::pair(name, depVersion)); - } - else if(strncmp(table_name,"RESO",4) == 0) //resources (using embed) - { - std::vector data; - data.resize(tableLen); - Ensure(data.data(), tableLen); - this->resources.push_back(data); - } - else if(strncmp(table_name,"CHKS",4) == 0) //chunks - { - size_t chunkCount = (size_t)ReadInt(); - for(size_t j = 0; j < chunkCount; j++) - { - std::vector args; - - - size_t argCount = (size_t)ReadInt(); - for(size_t k = 0; k < argCount; k++) - { - args.push_back(GetString()); - } - std::vector code; - size_t len = (size_t)ReadInt(); - code.resize(len); - Ensure(code.data(),len); - //reader.ReadIntoBuffer(chunk->code); - - this->chunks.emplace(this->chunks.end(),args,code); - } - - } - else if(strncmp(table_name,"FUNS",4) == 0) //functions - { - size_t funLength = (size_t)ReadInt(); - - for(size_t j = 0; j < funLength;j++) - { - std::vector fnParts; - uint32_t fnPartsC = ReadInt(); - for(uint32_t k = 0; k < fnPartsC; k++) - { - fnParts.push_back(GetString()); - } - - uint32_t fnNumber = ReadInt(); - this->functions.push_back(std::pair,uint32_t>(fnParts,fnNumber)); - - } - - } - else if(strncmp(table_name,"STRS",4) == 0) //strings - { - size_t strsLen = (size_t)ReadInt(); - for(size_t j = 0;j < strsLen;j++) - { - this->strings.push_back(ReadString()); - } - } - else if(strncmp(table_name,"ICON",4) == 0) //icon - { - this->icon = (int32_t)ReadInt(); - } - else if(strncmp(table_name,"MACH",4) == 0) //machine - { - std::string name = GetString(); - std::string howToGet = GetString(); - this->vms.push_back(std::pair(name,howToGet)); - } - else if(strncmp(table_name,"CLSS",4) == 0) //classes - { - uint32_t clsCnt = ReadInt(); - for(uint32_t j = 0; j < clsCnt; j++) - { - TClass cls; - cls.documentation= GetString(); - uint32_t name_cnt = ReadInt(); - for(uint32_t k = 0; k < name_cnt; k++) - { - cls.name.push_back(GetString()); - } - name_cnt = ReadInt(); - for(uint32_t k = 0; k < name_cnt; k++) - { - cls.inherits.push_back(GetString()); - } - name_cnt = ReadInt(); - for(uint32_t k = 0; k < name_cnt; k++) - { - TClassEntry ent; - Ensure(main_header,1); - uint8_t sig = main_header[0]; - ent.isAbstract = (sig & 0b00001000) != 0; - ent.isFunction = (sig & 0b00000100) == 0; - ent.modifier = (TClassModifier)(sig & 3); - ent.documentation = GetString(); - ent.name = GetString(); - uint32_t arglen = ReadInt(); - for(uint32_t l = 0; l < arglen; l++) - ent.args.push_back(GetString()); - ent.chunkId = ReadInt(); - cls.entry.push_back(ent); - } - this->classes.push_back(cls); - } - } - else - { - std::vector data; - data.resize(tableLen); - Ensure(data.data(), tableLen); - std::string key(std::string(table_name), 4); - this->sections.push_back(std::pair>(key,data)); - } - } - } - std::vector strings; - std::vector,std::vector>> chunks; - std::vector> vms; - std::vector, uint32_t>> functions; - std::vector> dependencies; - std::vector> tools; - std::vector>> sections; - std::vector> resources; - std::vector classes; - std::string name; - TVMVersion version; - std::string info; - int32_t icon; - - std::string Chunk2String(size_t chunkId,size_t tab) - { - if(chunkId >= this->chunks.size()) return {}; - auto& code = this->chunks[chunkId].second; - - std::string buffer = {}; - std::vector labels; - size_t i = 0; - while(i < code.size()) - { - switch(code[i++]) - { - case PUSHRESOURCESTREAM: - case PUSHRESOURCE: - case PUSHSTRING: - case SCOPEENDTIMES: - case PUSHCLOSURE: - case PUSHSCOPELESSCLOSURE: - i+=4; - break; - case PUSHLONG: - case PUSHDOUBLE: - i+=8; - break; - case PUSHCHAR: - i+=1; - break; - case JMP: - case JMPC: - case JMPIFBREAK: - case JMPIFCONTINUE: - case JMPIFDEFINED: - case JMPUNDEFINED: - { - bool already = false; - for(auto item : labels) - { - if(item == i) { - already=true; - break; - } - } - if(!already) - labels.push_back(BitConverter::ToUint32BE(code[i])); - i+=4; - } - break; - - default: - break; - } - } - i=0; - - while(i < code.size()) - { - for(size_t j = 0; j < labels.size(); j++) - { - if(labels[j] == i) - { - buffer.append(tab,'\t'); - buffer.append("lbl l" + std::to_string((uint32_t)j) + "\n"); - break; - } - } - - buffer.append(tab,'\t'); - - - switch(code[i++]) - { - case ADD: - buffer.append("add"); - break; - case SUB: - buffer.append("sub"); - break; - case TIMES: - buffer.append("mul"); - break; - case DIVIDE: - buffer.append("div"); - break; - case MODULO: - buffer.append("mod"); - break; - case LEFTSHIFT: - buffer.append("lsh"); - break; - case RIGHTSHIFT: - buffer.append("rsh"); - break; - case BITWISEOR: - buffer.append("bor"); - break; - case BITWISEAND: - buffer.append("band"); - break; - case BITWISENOT: - buffer.append("bnot"); - break; - case LESSTHAN: - buffer.append("lt"); - break; - case GREATERTHAN: - buffer.append("gt"); - break; - case LESSTHANEQ: - buffer.append("lte"); - break; - case GREATERTHANEQ: - buffer.append("gte"); - break; - case EQ: - buffer.append("eq"); - break; - case NEQ: - buffer.append("neq"); - break; - case NOT: - buffer.append("not"); - break; - case NEGATIVE: - buffer.append("neg"); - break; - case XOR: - buffer.append("xor"); - break; - case POP: - buffer.append("pop"); - break; - case DUP: - buffer.append("dup"); - break; - case PUSHCLOSURE: - { - uint32_t clId = (uint32_t)code[i++] << 24; - clId |= (uint32_t)code[i++] << 16; - clId |= (uint32_t)code[i++] << 8; - clId |= (uint32_t)code[i++]; - buffer.append("pushclosure ("); - bool first=true; - - for(auto item : this->chunks.at(clId).first) - { - if(!first) - buffer.append(", "); - buffer.append(item); - first=false; - } - - - - buffer.append(") {\n"); - buffer.append(Chunk2String((size_t)clId,tab+1)); - buffer.append(tab,'\t'); - buffer.append("}"); - } - break; - case CREATEDICTIONARY: - buffer.append("createdict"); - break; - case CREATEARRAY: - buffer.append("createarray"); - break; - case APPENDLIST: - buffer.append("appendlist"); - break; - case APPENDDICT: - buffer.append("appenddict"); - break; - case PUSHRESOUURCEDIR: - buffer.append("embeddir"); - break; - case PUSHRESOURCE: - { - uint32_t clId = (uint32_t)code[i++] << 24; - clId |= (uint32_t)code[i++] << 16; - clId |= (uint32_t)code[i++] << 8; - clId |= (uint32_t)code[i++]; - buffer.append("embed "); - buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true)); - } - break; - case PUSHRESOURCESTREAM: - { - uint32_t clId = (uint32_t)code[i++] << 24; - clId |= (uint32_t)code[i++] << 16; - clId |= (uint32_t)code[i++] << 8; - clId |= (uint32_t)code[i++]; - buffer.append("embedstrm "); - buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true)); - } - break; - case PUSHLONG: - { - uint64_t number = (uint64_t)code[i++] << 56; - number |= (uint64_t)code[i++] << 48; - number |= (uint64_t)code[i++] << 40; - number |= (uint64_t)code[i++] << 32; - number |= (uint64_t)code[i++] << 24; - number |= (uint64_t)code[i++] << 16; - number |= (uint64_t)code[i++] << 8; - number |= (uint64_t)code[i++]; - buffer.append("push " + std::to_string(number)); - - } - break; - case PUSHCHAR: - { - buffer.append("push '" + EscapeString(std::string({(char)code[i++]}),false) + "'"); - } - break; - case PUSHDOUBLE: - { - - auto res = BitConverter::ToDoubleBE(code[i]); - i+=8; - buffer.append("push " + std::to_string(res)); - } - break; - case PUSHSTRING: - { - auto res = BitConverter::ToUint32BE(code[i]); - i+=4; - buffer.append("push " + EscapeString(strings[res],true)); - } - break; - case PUSHNULL: - buffer.append("push null"); - break; - case PUSHUNDEFINED: - buffer.append("push undefined"); - break; - case SCOPEBEGIN: - buffer.append("scopebegin"); - break; - case SCOPEEND: - buffer.append("scopeend"); - break; - case SCOPEENDTIMES: - { - auto res = BitConverter::ToUint32BE(code[i]); - i+=4; - buffer.append("scopeendtimes " + std::to_string(res)); - } - break; - case PUSHFALSE: - buffer.append("push false"); - break; - case PUSHTRUE: - buffer.append("push true"); - break; - case SETVARIABLE: - buffer.append("setvariable"); - break; - case GETVARIABLE: - buffer.append("getvariable"); - break; - case DECLAREVARIABLE: - buffer.append("declarevariable"); - break; - case DECLARECONSTVARIABLE: - buffer.append("declareconstvariable"); - break; - case SETFIELD: - buffer.append("setfield"); - break; - case GETFIELD: - buffer.append("getfield"); - break; - case CALLFUNCTION: - buffer.append("callfunction"); - break; - case CALLMETHOD: - buffer.append("callmethod"); - break; - case RET: - buffer.append("ret"); - break; - case JMPC: - { - auto res = BitConverter::ToUint32BE(code[i]); - i+=4; - buffer.append("jmpc l"); - for(size_t j = 0; j < labels.size(); j++) - { - if(labels[j] == res) - { - buffer.append(std::to_string((uint32_t)j)); - break; - } - } - - } - break; - case JMP: - { - auto res = BitConverter::ToUint32BE(code[i]); - i+=4; - buffer.append("jmp l"); - for(size_t j = 0; j < labels.size(); j++) - { - if(labels[j] == res) - { - buffer.append(std::to_string((uint32_t)j)); - break; - } - } - - } - break; - case JMPUNDEFINED: - { - auto res = BitConverter::ToUint32BE(code[i]); - i+=4; - buffer.append("jmpundefined l"); - for(size_t j = 0; j < labels.size(); j++) - { - if(labels[j] == res) - { - buffer.append(std::to_string((uint32_t)j)); - break; - } - } - - } - break; - case DEFER: - buffer.append("defer"); - break; - case TRYCATCH: - buffer.append("trycatch"); - break; - case THROW: - buffer.append("throw"); - break; - case PUSHSCOPELESSCLOSURE: - { - uint32_t clId = (uint32_t)code[i++] << 24; - clId |= (uint32_t)code[i++] << 16; - clId |= (uint32_t)code[i++] << 8; - clId |= (uint32_t)code[i++]; - buffer.append("pushscopelessclosure ("); - bool first=true; - - for(auto item : this->chunks.at(clId).first) - { - if(!first) - buffer.append(", "); - buffer.append(item); - first=false; - } - - - - buffer.append(") {\n"); - buffer.append(Chunk2String((size_t)clId,tab+1)); - buffer.append(tab,'\t'); - buffer.append("}"); - } - break; - case YIELD: - buffer.append("yield"); - break; - case PUSHROOTPATH: - buffer.append("push /"); - break; - case PUSHRELATIVEPATH: - buffer.append("push ."); - break; - case BREAKPOINT: - buffer.append("breakpoint"); - break; - case LINEINFO: - buffer.append("lineinfo"); - break; - case PUSHBREAK: - buffer.append("push break"); - break; - case PUSHCONTINUE: - buffer.append("push continue"); - break; - case JMPIFBREAK: - { - auto res = BitConverter::ToUint32BE(code[i]); - i+=4; - buffer.append("jmpifbreak l"); - for(size_t j = 0; j < labels.size(); j++) - { - if(labels[j] == res) - { - buffer.append(std::to_string((uint32_t)j)); - break; - } - } - - } - break; - case JMPIFCONTINUE: - { - auto res = BitConverter::ToUint32BE(code[i]); - i+=4; - buffer.append("jmpifcontinue l"); - for(size_t j = 0; j < labels.size(); j++) - { - if(labels[j] == res) - { - buffer.append(std::to_string((uint32_t)j)); - break; - } - } - - } - break; - case JMPIFDEFINED: - { - auto res = BitConverter::ToUint32BE(code[i]); - i+=4; - buffer.append("jmpifdefined l"); - for(size_t j = 0; j < labels.size(); j++) - { - if(labels[j] == res) - { - buffer.append(std::to_string((uint32_t)j)); - break; - } - } - - } - break; - default: - printf("ILL: %i\n", (int)code[i-1]); - break; - } - - buffer.push_back('\n'); - } - - if(code.empty()) buffer.push_back('\n'); - - return buffer; - } - }; - - - - - void Disassemble(std::shared_ptr src,std::shared_ptr vfs, bool generateJSON,bool extractResources) - { - using namespace Tesses::Framework::Filesystem; - CrossLangFileReader file(src); - if(extractResources) - { - std::string resdir = "res"; - VFSPath path=resdir; - vfs->CreateDirectory(path); - for(size_t i = 0; i < file.resources.size(); i++) - { - auto path2 = path / file.name + "-" + file.version.ToString()+"_"+ std::to_string((uint32_t)i) + ".bin"; - auto strm = vfs->OpenFile(path2,"wb"); - strm->WriteBlock(file.resources[i].data(),file.resources[i].size()); - - } - - std::string secdir = "sections"; - VFSPath secpath=secdir; - vfs->CreateDirectory(secpath); - - for(size_t i = 0; i < file.sections.size(); i++) - { - auto path2 = secpath / file.name + "-" + file.version.ToString()+"_"+ std::to_string((uint32_t)i) + ".tsec"; - - if(file.sections[i].first.size() != 4) { - throw std::runtime_error("Chunk name is not 4 bytes"); - } - auto strm = vfs->OpenFile(path2,"wb"); - strm->WriteBlock((const uint8_t*)file.sections[i].first.data(), 4); - strm->WriteBlock(file.sections[i].second.data(),file.sections[i].second.size()); - - } - } - - std::string srcFile = {}; - - srcFile.append("root {\n"); - srcFile.append(file.Chunk2String(0,1)); - srcFile.append("}\n"); - - for(auto& item : file.functions) - { - if(!item.first[0].empty()) - { - srcFile.append("/^" + Tesses::Framework::Http::HttpUtils::Replace(item.first[0],"^","^^") +"^/\n"); - } - srcFile.append("func "); - for(size_t i = 1; i < item.first.size(); i++) - { - if(i > 1) - { - srcFile.push_back('.'); - } - srcFile.append(item.first[i]); - } - srcFile.append("("); - auto& chunk = file.chunks.at(item.second); - for(size_t i = 0; i < chunk.first.size(); i++) - { - if(i > 0) - { - srcFile.append(", "); - } - srcFile.append(chunk.first[i]); - } - srcFile.append(") {\n"); - srcFile.append(file.Chunk2String((size_t)item.second,1)); - srcFile.append("}\n"); - } - for(auto& cls : file.classes) - { - if(!cls.documentation.empty()) - { - srcFile.append("/^" + Tesses::Framework::Http::HttpUtils::Replace(cls.documentation,"^","^^") +"^/\n"); - } - srcFile.append("class "); - for(size_t i = 0; i < cls.name.size(); i++) - { - if(i > 0) - { - srcFile.push_back('.'); - } - srcFile.append(cls.name[i]); - } - - if(!(cls.inherits.size() == 1 && cls.inherits[0] == "ClassObject")) - { - srcFile.append(" : "); - for(size_t i = 0; i < cls.inherits.size(); i++) - { - if(i > 0) - { - srcFile.push_back('.'); - } - srcFile.append(cls.inherits[i]); - } - } - srcFile.append(" {\n"); - for(auto& item : cls.entry) - { - if(!item.documentation.empty()) - srcFile.append("\t/^"+Tesses::Framework::Http::HttpUtils::Replace(item.documentation,"^","^^")+"^/\n"); - - switch(item.modifier) - { - case TClassModifier::Private: - srcFile.append("\tprivate "); - break; - case TClassModifier::Protected: - srcFile.append("\tprotected "); - break; - case TClassModifier::Public: - srcFile.append("\tpublic "); - break; - case TClassModifier::Static: - srcFile.append("\tstatic "); - default: - break; - } - - if(item.isFunction) - { - - if(item.isAbstract) - { - srcFile.append("abstract " + item.name); - srcFile.append("("); - for(size_t i = 0; i < item.args.size(); i++) - { - if(i > 0) - { - srcFile.append(", "); - } - srcFile.append(item.args[i]); - } - srcFile.append(");\n"); - } - else { - srcFile.append(item.name); - srcFile.append("("); - for(size_t i = 0; i < item.args.size(); i++) - { - if(i > 0) - { - srcFile.append(", "); - } - srcFile.append(item.args[i]); - } - srcFile.append(") {\n"); - srcFile.append(file.Chunk2String(item.chunkId,2)); - srcFile.append("\t}\n"); - } - } - else { - srcFile.append(item.name); - if(item.isAbstract) - { - - srcFile.append(";\n"); - } - else { - srcFile.append(" {\n"); - srcFile.append(file.Chunk2String(item.chunkId,2)); - srcFile.append("\t}\n"); - } - } - } - srcFile.append("}\n"); - } - std::string srcdirs = "src"; - VFSPath srcdir=srcdirs; - vfs->CreateDirectory(srcdir); - Tesses::Framework::TextStreams::StreamWriter writer(vfs->OpenFile(srcdir / file.name + "-" + file.version.ToString() + ".tcasm","wb")); - writer.Write(srcFile); - - if(generateJSON) - { - using namespace Tesses::Framework::Serialization::Json; - - JObject json_data { - JOItem{"name", file.name}, - JOItem{"version",file.version.ToString()} - }; - if(!file.info.empty()) - { - json_data.SetValue("info",Json::Decode(file.info)); - - } - - if(file.icon > -1 && file.icon < file.resources.size()) - { - json_data.SetValue("icon",file.name + "-" + file.version.ToString()+"_"+ std::to_string(file.icon) + ".bin"); - } - if(!file.dependencies.empty()) - { - JArray array; - for(auto& item : file.dependencies) - { - array.Add(JObject { - JOItem { - "name", - item.first - }, - JOItem { - "version", - item.second.ToString() - } - }); - } - json_data.SetValue("dependencies", array); - } - if(!file.tools.empty()) - { - JArray array; - for(auto& item : file.tools) - { - array.Add(JObject { - JOItem { - "name", - item.first - }, - JOItem { - "version", - item.second.ToString() - } - }); - } - json_data.SetValue("tools", array); - } - if(!file.vms.empty()) - { - JArray array; - for(auto& item : file.vms) - { - array.Add(JObject { - JOItem { - "name", - item.first - }, - JOItem { - "how_to_get", - item.second - } - }); - } - json_data.SetValue("vms", array); - } - - - Tesses::Framework::TextStreams::StreamWriter json_writer(vfs->OpenFile(VFSPath() / "crossapp.json","wb" )); - json_writer.WriteLine(Json::Encode(json_data,true)); - - } - } -} \ No newline at end of file diff --git a/src/assembler/merge.cpp b/src/assembler/merge.cpp deleted file mode 100644 index 62803f1..0000000 --- a/src/assembler/merge.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#include "CrossLang.hpp" -using namespace Tesses::Framework::Serialization::Json; -namespace Tesses::CrossLang { - static void LoadDependency(std::shared_ptr srcFS, Tesses::Framework::Filesystem::VFSPath sourceDir, std::pair dep, std::vector>& files, std::vector>& tools); - static void LoadDependencies(std::shared_ptr srcFS, Tesses::Framework::Filesystem::VFSPath sourceDir,TFile* file, std::vector>& files, std::vector>& tools); - static void LoadDependency(std::shared_ptr srcFS, Tesses::Framework::Filesystem::VFSPath sourceDir, std::pair dep, std::vector>& files, std::vector>& tools) - { - for(auto index = files.begin(); index != files.end(); index++) - { - if(index->first == dep.first) - { - if(index->second.CompareTo(dep.second) >= 0) return; - files.erase(index); - break; - } - } - std::string name = {}; - name.append(dep.first); - name.push_back('-'); - name.append(dep.second.ToString()); - name.append(".crvm"); - auto filename= sourceDir / name; - - if(srcFS->RegularFileExists(filename)) - { - auto file = srcFS->OpenFile(filename,"rb"); - - TFile f; - f.Load(nullptr, file); - - LoadDependencies(srcFS,sourceDir,&f,files,tools); - } - else throw VMException("Could not open file: \"" + name + "\"."); - - } - static void LoadDependencies(std::shared_ptr srcFS, Tesses::Framework::Filesystem::VFSPath sourceDir,TFile* file, std::vector>& files, std::vector>& tools) - { - files.push_back(std::pair(file->name,file->version)); - for(auto item : file->tools) - { - bool exists = false; - for(auto& itm2 : tools) - { - if(itm2.first == item.first) - { - exists=true; - if(itm2.second.CompareTo(item.second) < 0) { - itm2.second = item.second; - } - break; - } - } - if(!exists) - tools.push_back(item); - } - for(auto item : file->dependencies) - { - LoadDependency(srcFS,sourceDir,item,files,tools); - } - } - static void EnumerateCRVM(std::shared_ptr srcFS, Tesses::Framework::Filesystem::VFSPath sourceDir,std::string filename, std::vector>& files, std::shared_ptr destFS) - { - - - TFile file; - auto strm = srcFS->OpenFile(sourceDir / filename,"rb"); - if(strm->EndOfStream()) { - - - throw std::runtime_error("File does not exist: " + (sourceDir / filename).ToString() ); - } - file.Load(nullptr,strm); - - - - std::vector> tools; - LoadDependencies(srcFS,sourceDir,&file,files,tools); - - - - - - JObject json_data { - JOItem{"name", file.name}, - JOItem{"version",file.version.ToString()} - - }; - if(!file.info.empty()) - { - json_data.SetValue("info",Json::Decode(file.info)); - - } - - if(file.icon > -1 && file.icon < file.resources.size()) - { - json_data.SetValue("icon",file.name + "-" + file.version.ToString()+"_"+ std::to_string(file.icon) + ".bin"); - } - if(!file.tools.empty()) - { - JArray array; - for(auto& item : file.tools) - { - array.Add(JObject { - JOItem { - "name", - item.first - }, - JOItem { - "version", - item.second.ToString() - } - }); - } - json_data.SetValue("tools", array); - } - if(!file.vms.empty()) - { - JArray array; - for(auto& item : file.vms) - { - array.Add(JObject { - JOItem { - "name", - item.first - }, - JOItem { - "how_to_get", - item.second - } - }); - } - json_data.SetValue("vms", array); - } - - - Tesses::Framework::TextStreams::StreamWriter json_writer(destFS->OpenFile(Tesses::Framework::Filesystem::VFSPath() / "crossapp.json","wb" )); - json_writer.WriteLine(Json::Encode(json_data,true)); - } - Tesses::Framework::Filesystem::VFSPath Merge(std::shared_ptr srcFS, Tesses::Framework::Filesystem::VFSPath sourcePath, std::shared_ptr destFS) - { - std::vector> files; - - for(auto ent : destFS->EnumeratePaths(Tesses::Framework::Filesystem::VFSPath())) - { - if(destFS->DirectoryExists(ent)) - { - destFS->DeleteDirectoryRecurse(ent); - } - else { - destFS->DeleteFile(ent); - } - } - - - EnumerateCRVM(srcFS,sourcePath.GetParent(), sourcePath.GetFileName(),files,destFS); - - for(auto item : files) - { - auto filePath = sourcePath.GetParent() / item.first + "-" + item.second.ToString() + ".crvm"; - if(srcFS->RegularFileExists(filePath)) - { - auto strm = srcFS->OpenFile(filePath,"rb"); - Disassemble(strm,destFS,false); - } - } - - return Assemble(destFS); - } -} \ No newline at end of file diff --git a/src/compiler/ast.cpp b/src/compiler/ast.cpp index 1209236..945361f 100644 --- a/src/compiler/ast.cpp +++ b/src/compiler/ast.cpp @@ -2,10 +2,10 @@ #if defined(CROSSLANG_ENABLE_JSON) #include #endif -namespace Tesses::CrossLang -{ -AdvancedSyntaxNode AdvancedSyntaxNode::Create(std::string_view nodeName,bool isExpression, std::vector nodes) -{ +namespace Tesses::CrossLang { +AdvancedSyntaxNode AdvancedSyntaxNode::Create(std::string_view nodeName, + bool isExpression, + std::vector nodes) { AdvancedSyntaxNode asn; asn.nodeName = std::string(nodeName); asn.isExpression = isExpression; @@ -14,45 +14,43 @@ AdvancedSyntaxNode AdvancedSyntaxNode::Create(std::string_view nodeName,bool isE } #if defined(CROSSLANG_ENABLE_JSON) -static SyntaxNode Deserialize2(json_t* json) -{ - if(json_is_null(json)) return nullptr; - if(json_is_true(json)) return true; - if(json_is_false(json)) return false; - if(json_is_integer(json)) return (int64_t)json_integer_value(json); - if(json_is_real(json)) return json_real_value(json); - if(json_is_string(json)) return std::string(json_string_value(json),json_string_length(json)); - if(json_is_object(json)) - { - json_t* typ = json_object_get(json, "type"); - if(json_is_string(typ)) - { - std::string type(json_string_value(typ),json_string_length(typ)); - if(type == CharExpression) - { - json_t* chrData = json_object_get(json,"value"); - if(json_is_integer(chrData)) - { +static SyntaxNode Deserialize2(json_t *json) { + if (json_is_null(json)) + return nullptr; + if (json_is_true(json)) + return true; + if (json_is_false(json)) + return false; + if (json_is_integer(json)) + return (int64_t)json_integer_value(json); + if (json_is_real(json)) + return json_real_value(json); + if (json_is_string(json)) + return std::string(json_string_value(json), json_string_length(json)); + if (json_is_object(json)) { + json_t *typ = json_object_get(json, "type"); + if (json_is_string(typ)) { + std::string type(json_string_value(typ), json_string_length(typ)); + if (type == CharExpression) { + json_t *chrData = json_object_get(json, "value"); + if (json_is_integer(chrData)) { return (char)(uint8_t)json_integer_value(chrData); } } - if(type == UndefinedExpression) - { + if (type == UndefinedExpression) { return Undefined(); } - json_t* isExpr = json_object_get(json,"isExpression"); + json_t *isExpr = json_object_get(json, "isExpression"); bool isExprB = json_is_true(isExpr); - AdvancedSyntaxNode asn; + AdvancedSyntaxNode asn; asn.nodeName = type; asn.isExpression = isExprB; - json_t* args = json_object_get(json, "args"); - if(json_is_array(args)) - { + json_t *args = json_object_get(json, "args"); + if (json_is_array(args)) { size_t index; - json_t* value; - - json_array_foreach(args, index, value) - { + json_t *value; + + json_array_foreach(args, index, value) { asn.nodes.push_back(Deserialize2(value)); } } @@ -63,89 +61,79 @@ static SyntaxNode Deserialize2(json_t* json) } #endif - -SyntaxNode Deserialize(std::string astData) -{ - #if defined(CROSSLANG_ENABLE_JSON) - json_t* json = json_loadb(astData.c_str(),astData.size(), 0, NULL); +SyntaxNode Deserialize(std::string astData) { +#if defined(CROSSLANG_ENABLE_JSON) + json_t *json = json_loadb(astData.c_str(), astData.size(), 0, NULL); auto r = Deserialize2(json); json_decref(json); return r; - #endif +#endif return nullptr; } #if defined(CROSSLANG_ENABLE_JSON) -static json_t* Serialize2(SyntaxNode node) -{ - if(std::holds_alternative(node)) +static json_t *Serialize2(SyntaxNode node) { + if (std::holds_alternative(node)) return json_null(); - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { return json_integer(std::get(node)); } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { return json_real(std::get(node)); } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { return json_boolean(std::get(node)); } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { std::string str = std::get(node); - return json_stringn(str.c_str(),str.size()); + return json_stringn(str.c_str(), str.size()); } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { char c = std::get(node); - json_t* json = json_object(); - json_object_set_new(json,"type",json_string((const char*)CharExpression.data())); + json_t *json = json_object(); + json_object_set_new(json, "type", + json_string((const char *)CharExpression.data())); json_object_set_new(json, "value", json_integer((uint8_t)c)); return json; } - if(std::holds_alternative(node)) - { - json_t* json = json_object(); - json_object_set_new(json,"type",json_string((const char*)UndefinedExpression.data())); + if (std::holds_alternative(node)) { + json_t *json = json_object(); + json_object_set_new( + json, "type", + json_string((const char *)UndefinedExpression.data())); return json; } - - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { auto asn = std::get(node); - json_t* j = json_object(); + json_t *j = json_object(); json_object_set_new(j, "type", json_string(asn.nodeName.c_str())); - json_object_set_new(j, "isExpression",json_boolean(asn.isExpression)); - json_t* arr=json_array(); - for(auto item : asn.nodes) - { - json_array_append_new(arr,Serialize2(item)); + json_object_set_new(j, "isExpression", json_boolean(asn.isExpression)); + json_t *arr = json_array(); + for (auto item : asn.nodes) { + json_array_append_new(arr, Serialize2(item)); } json_object_set_new(j, "args", arr); return j; } - + return json_null(); } #endif -std::string Serialize(SyntaxNode node) -{ +std::string Serialize(SyntaxNode node) { #if defined(CROSSLANG_ENABLE_JSON) -json_t* json = Serialize2(node); -char* txt = json_dumps(json,0); -std::string str(txt); -free(json); -json_decref(json); -return str; + json_t *json = Serialize2(node); + char *txt = json_dumps(json, 0); + std::string str(txt); + free(json); + json_decref(json); + return str; #endif -return ""; + return ""; } -} +} // namespace Tesses::CrossLang diff --git a/src/compiler/codegen.cpp b/src/compiler/codegen.cpp index c4497a5..f9d3d6f 100644 --- a/src/compiler/codegen.cpp +++ b/src/compiler/codegen.cpp @@ -1,2353 +1,2288 @@ #include "CrossLang.hpp" -#include #include -#include #include +#include +#include #include -namespace Tesses::CrossLang -{ - void Write(std::shared_ptr strm, uint8_t* buffer, size_t len) - { - strm->WriteBlock(buffer,len); +namespace Tesses::CrossLang { +void Write(std::shared_ptr strm, + uint8_t *buffer, size_t len) { + strm->WriteBlock(buffer, len); +} +void WriteInt(std::shared_ptr strm, + uint32_t v) { + uint8_t buffer[4]; + BitConverter::FromUint32BE(buffer[0], v); + Write(strm, buffer, 4); +} +void WriteString(std::shared_ptr strm, + std::string v) { + WriteInt(strm, (uint32_t)v.size()); + Write(strm, (uint8_t *)v.data(), v.size()); +} + +CodeGen::~CodeGen() { + for (auto &item : this->chunks) { + for (auto instr : item.second) + delete instr; } - void WriteInt(std::shared_ptr strm,uint32_t v) - { - uint8_t buffer[4]; - BitConverter::FromUint32BE(buffer[0],v); - Write(strm,buffer,4); - } - void WriteString(std::shared_ptr strm,std::string v) - { - WriteInt(strm,(uint32_t)v.size()); - Write(strm,(uint8_t*)v.data(),v.size()); - } - - - CodeGen::~CodeGen() - { - for(auto& item : this->chunks) - { - for(auto instr : item.second) - delete instr; +} + +SyntaxNode CodeGen::OptimizeNode(SyntaxNode n) { + if (std::holds_alternative(n)) { + auto &asn = std::get(n); + if (asn.nodeName == AddExpression && asn.nodes.size() == 2) { + auto leftNode = OptimizeNode(asn.nodes[0]); + auto rightNode = OptimizeNode(asn.nodes[1]); + + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) + + std::get(rightNode); + } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) + std::get(rightNode); + } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return (double)std::get(leftNode) + + std::get(rightNode); + } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) + + (double)std::get(rightNode); + } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) + + std::get(rightNode); + } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) + + std::get(rightNode); + } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) + + std::get(rightNode); + } } - } + if (asn.nodeName == SubExpression && asn.nodes.size() == 2) { + auto leftNode = OptimizeNode(asn.nodes[0]); + auto rightNode = OptimizeNode(asn.nodes[1]); - SyntaxNode CodeGen::OptimizeNode(SyntaxNode n) - { - if(std::holds_alternative(n)) - { - auto& asn = std::get(n); - if(asn.nodeName == AddExpression && asn.nodes.size() == 2) - { - auto leftNode = OptimizeNode(asn.nodes[0]); - auto rightNode = OptimizeNode(asn.nodes[1]); - - - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) + std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) + std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return (double)std::get(leftNode) + std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) + (double)std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) + std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) + std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) + std::get(rightNode); - } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) - + std::get(rightNode); } - if(asn.nodeName == SubExpression && asn.nodes.size() == 2) - { - auto leftNode = OptimizeNode(asn.nodes[0]); - auto rightNode = OptimizeNode(asn.nodes[1]); - - - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) - std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) - std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return (double)std::get(leftNode) - std::get(rightNode); - } - if(std::holds_alternative(leftNode) && std::holds_alternative(rightNode)) - { - return std::get(leftNode) - (double)std::get(rightNode); - } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) - std::get(rightNode); } - if(asn.nodeName == CommaExpression && asn.nodes.size() == 2) - { - return AdvancedSyntaxNode::Create(CommaExpression,true, { - OptimizeNode(asn.nodes[0]), - OptimizeNode(asn.nodes[1]) - }); + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return (double)std::get(leftNode) - + std::get(rightNode); } - if(asn.nodeName == ScopeNode) - { - if(asn.nodes.empty()) - { - asn.nodeName = NodeList; - return asn; - } - else - { - for(auto& item : asn.nodes) - { - item = OptimizeNode(item); - } + if (std::holds_alternative(leftNode) && + std::holds_alternative(rightNode)) { + return std::get(leftNode) - + (double)std::get(rightNode); + } + } + if (asn.nodeName == CommaExpression && asn.nodes.size() == 2) { + return AdvancedSyntaxNode::Create( + CommaExpression, true, + {OptimizeNode(asn.nodes[0]), OptimizeNode(asn.nodes[1])}); + } + if (asn.nodeName == ScopeNode) { + if (asn.nodes.empty()) { + asn.nodeName = NodeList; + return asn; + } else { + for (auto &item : asn.nodes) { + item = OptimizeNode(item); } } } - return n; } + return n; +} - /* - 0: false, - 1: true, - 2: null, - 3: Long, - 4: Double, - 5: Char - 6: String, - 7: List, - 8: Dictionary, - 9: ByteArray (embed), - 10: Stream (embedstrm), - 11: VFS (embeddir), - 12: ClosureOfEmbedStream (used by embeddir) - */ +/* + 0: false, +1: true, +2: null, +3: Long, +4: Double, +5: Char +6: String, +7: List, +8: Dictionary, +9: ByteArray (embed), +10: Stream (embedstrm), +11: VFS (embeddir), +12: ClosureOfEmbedStream (used by embeddir) +*/ - void CodeGen::WriteMetadataObject(std::vector& bytes, SyntaxNode n) - { - if(std::holds_alternative(n)) - { - bytes.push_back(std::get(n) ? 1 : 0); - return; - } - if(std::holds_alternative(n)) - { - bytes.push_back(2); - return; - } - if(std::holds_alternative(n)) - { - auto num = std::get(n); - bytes.push_back(3); +void CodeGen::WriteMetadataObject(std::vector &bytes, SyntaxNode n) { + if (std::holds_alternative(n)) { + bytes.push_back(std::get(n) ? 1 : 0); + return; + } + if (std::holds_alternative(n)) { + bytes.push_back(2); + return; + } + if (std::holds_alternative(n)) { + auto num = std::get(n); + bytes.push_back(3); + size_t offset = bytes.size(); + bytes.resize(offset + 8); + BitConverter::FromUint64BE(bytes[offset], num); + return; + } + if (std::holds_alternative(n)) { + auto num = std::get(n); + bytes.push_back(4); + size_t offset = bytes.size(); + bytes.resize(offset + 8); + BitConverter::FromDoubleBE(bytes[offset], num); + return; + } + if (std::holds_alternative(n)) { + auto chr = std::get(n); + bytes.push_back(5); + bytes.push_back((uint8_t)chr); + return; + } + if (std::holds_alternative(n)) { + auto &str = std::get(n); + bytes.push_back(6); + size_t offset = bytes.size(); + bytes.resize(offset + 4); + BitConverter::FromUint32BE(bytes[offset], GetString(str)); + return; + } + if (std::holds_alternative(n)) { + auto &asn = std::get(n); + if (asn.nodeName == ArrayExpression) { + std::vector itms; + if (asn.nodes.size() > 0) + + GetFunctionArgs(itms, asn.nodes[0]); + bytes.push_back(7); size_t offset = bytes.size(); - bytes.resize(offset+8); - BitConverter::FromUint64BE(bytes[offset],num); - return; - } - if(std::holds_alternative(n)) - { - auto num = std::get(n); - bytes.push_back(4); - size_t offset = bytes.size(); - bytes.resize(offset+8); - BitConverter::FromDoubleBE(bytes[offset],num); - return; - } - if(std::holds_alternative(n)) - { - auto chr = std::get(n); - bytes.push_back(5); - bytes.push_back((uint8_t)chr); - return; - } - if(std::holds_alternative(n)) - { - auto& str = std::get(n); - bytes.push_back(6); - size_t offset = bytes.size(); - bytes.resize(offset+4); - BitConverter::FromUint32BE(bytes[offset], GetString(str)); - return; - } - if(std::holds_alternative(n)) - { - auto& asn = std::get(n); - if(asn.nodeName == ArrayExpression) - { - std::vector itms; - if(asn.nodes.size() > 0) - - GetFunctionArgs(itms,asn.nodes[0]); - bytes.push_back(7); - size_t offset = bytes.size(); - bytes.resize(offset+4); - BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size()); - for(auto& item : itms) - { - WriteMetadataObject(bytes,item); - } - return; + bytes.resize(offset + 4); + BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size()); + for (auto &item : itms) { + WriteMetadataObject(bytes, item); } - if(asn.nodeName == DictionaryExpression) - { - std::vector itms; - if(asn.nodes.size() > 0) - - GetFunctionArgs(itms,asn.nodes[0]); - bytes.push_back(8); - size_t offset = bytes.size(); - bytes.resize(offset+4); - BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size()); - for(auto& item : itms) - { - if(std::holds_alternative(item)) - { - auto tkn = std::get(item); - if(tkn.nodeName == GetVariableExpression && !tkn.nodes.empty()) - { - if(std::holds_alternative(tkn.nodes[0])) - { - size_t offset2 = bytes.size(); - bytes.resize(offset2+4); - BitConverter::FromUint32BE(bytes[offset2], GetString(std::get(tkn.nodes[0]))); - bytes.push_back(2); - - } - else - { - - size_t offset2 = bytes.size(); - bytes.resize(offset2+4); - BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown")); - bytes.push_back(2); - - } - } - else if(tkn.nodeName == AssignExpression && tkn.nodes.size()==2 && std::holds_alternative(tkn.nodes[0])) - { - auto myTn = std::get(tkn.nodes[0]); - if(myTn.nodeName == GetVariableExpression && !myTn.nodes.empty()) - { - if(std::holds_alternative(myTn.nodes[0])) - { - size_t offset2 = bytes.size(); - bytes.resize(offset2+4); - BitConverter::FromUint32BE(bytes[offset2], GetString(std::get(myTn.nodes[0]))); - WriteMetadataObject(bytes,tkn.nodes[1]); - - } - else - { - - size_t offset2 = bytes.size(); - bytes.resize(offset2+4); - BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown")); - bytes.push_back(2); - - } - } - else - { - - size_t offset2 = bytes.size(); - bytes.resize(offset2+4); - BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown")); - bytes.push_back(2); - - } - } - else - { - + return; + } + if (asn.nodeName == DictionaryExpression) { + std::vector itms; + if (asn.nodes.size() > 0) + + GetFunctionArgs(itms, asn.nodes[0]); + bytes.push_back(8); + size_t offset = bytes.size(); + bytes.resize(offset + 4); + BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size()); + for (auto &item : itms) { + if (std::holds_alternative(item)) { + auto tkn = std::get(item); + if (tkn.nodeName == GetVariableExpression && + !tkn.nodes.empty()) { + if (std::holds_alternative(tkn.nodes[0])) { size_t offset2 = bytes.size(); - bytes.resize(offset2+4); - BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown")); + bytes.resize(offset2 + 4); + BitConverter::FromUint32BE( + bytes[offset2], + GetString(std::get(tkn.nodes[0]))); + bytes.push_back(2); + + } else { + + size_t offset2 = bytes.size(); + bytes.resize(offset2 + 4); + BitConverter::FromUint32BE(bytes[offset2], + GetString("__unknown")); bytes.push_back(2); - } + } else if (tkn.nodeName == AssignExpression && + tkn.nodes.size() == 2 && + std::holds_alternative( + tkn.nodes[0])) { + auto myTn = std::get(tkn.nodes[0]); + if (myTn.nodeName == GetVariableExpression && + !myTn.nodes.empty()) { + if (std::holds_alternative( + myTn.nodes[0])) { + size_t offset2 = bytes.size(); + bytes.resize(offset2 + 4); + BitConverter::FromUint32BE( + bytes[offset2], + GetString( + std::get(myTn.nodes[0]))); + WriteMetadataObject(bytes, tkn.nodes[1]); + + } else { + + size_t offset2 = bytes.size(); + bytes.resize(offset2 + 4); + BitConverter::FromUint32BE( + bytes[offset2], GetString("__unknown")); + bytes.push_back(2); + } + } else { + + size_t offset2 = bytes.size(); + bytes.resize(offset2 + 4); + BitConverter::FromUint32BE(bytes[offset2], + GetString("__unknown")); + bytes.push_back(2); + } + } else { + + size_t offset2 = bytes.size(); + bytes.resize(offset2 + 4); + BitConverter::FromUint32BE(bytes[offset2], + GetString("__unknown")); + bytes.push_back(2); } } + } + return; + } + if (asn.nodeName == EmbedExpression) { + if (!asn.nodes.empty() && + std::holds_alternative(asn.nodes[0])) { + auto &filename = std::get(asn.nodes[0]); + bytes.push_back(9); + size_t offset = bytes.size(); + bytes.resize(offset + 4); + BitConverter::FromUint32BE( + bytes[offset], + GetResource(std::make_shared(filename))); return; } - if(asn.nodeName == EmbedExpression) - { - if(!asn.nodes.empty() && std::holds_alternative(asn.nodes[0])) - { - auto& filename = std::get(asn.nodes[0]); - bytes.push_back(9); - size_t offset = bytes.size(); - bytes.resize(offset+4); - BitConverter::FromUint32BE(bytes[offset], GetResource(std::make_shared(filename))); - return; - } + } + if (asn.nodeName == EmbedStreamExpression) { + if (!asn.nodes.empty() && + std::holds_alternative(asn.nodes[0])) { + auto &filename = std::get(asn.nodes[0]); + bytes.push_back(10); + size_t offset = bytes.size(); + bytes.resize(offset + 4); + BitConverter::FromUint32BE( + bytes[offset], + GetResource(std::make_shared(filename))); + return; } - if(asn.nodeName == EmbedStreamExpression) - { - if(!asn.nodes.empty() && std::holds_alternative(asn.nodes[0])) - { - auto& filename = std::get(asn.nodes[0]); - bytes.push_back(10); - size_t offset = bytes.size(); - bytes.resize(offset+4); - BitConverter::FromUint32BE(bytes[offset], GetResource(std::make_shared(filename))); - return; - } - } - if(asn.nodeName == EmbedDirectoryExpression) - { - if(!asn.nodes.empty() && std::holds_alternative(asn.nodes[0])) - { - auto& filename = std::get(asn.nodes[0]); - bytes.push_back(11); + } + if (asn.nodeName == EmbedDirectoryExpression) { + if (!asn.nodes.empty() && + std::holds_alternative(asn.nodes[0])) { + auto &filename = std::get(asn.nodes[0]); + bytes.push_back(11); - - std::function embedDir; - embedDir = [&](Tesses::Framework::Filesystem::VFSPath path)-> void { + std::function + embedDir; + embedDir = + [&](Tesses::Framework::Filesystem::VFSPath path) -> void { bytes.push_back(8); - std::vector> entries; - if(embedFS != nullptr && embedFS->DirectoryExists(path)) - for(auto& item : embedFS->EnumeratePaths(path)) - { - if(embedFS->DirectoryExists(item)) - entries.emplace_back(item,true); - else if(embedFS->FileExists(item)) - entries.emplace_back(item,false); - + std::vector< + std::pair> + entries; + if (embedFS != nullptr && embedFS->DirectoryExists(path)) + for (auto &item : embedFS->EnumeratePaths(path)) { + if (embedFS->DirectoryExists(item)) + entries.emplace_back(item, true); + else if (embedFS->FileExists(item)) + entries.emplace_back(item, false); - /*GenNode(instructions,item.GetFileName(),scope,contscope,brkscope,contI,brkI); - if(embedFS->DirectoryExists(item)) - { - embedDir(item); - } - else if(embedFS->RegularFileExists(item)) - { - auto ce = AdvancedSyntaxNode::Create(ClosureExpression,true,{ - AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(EmbedStreamExpression,true,{item.ToString()}) - }) - }); - GenNode(instructions,ce,scope,contscope,brkscope,contI,brkI); - } - else { - instructions.push_back(new SimpleInstruction(PUSHUNDEFINED)); - } + /*GenNode(instructions,item.GetFileName(),scope,contscope,brkscope,contI,brkI); + if(embedFS->DirectoryExists(item)) + { + embedDir(item); + } + else if(embedFS->RegularFileExists(item)) + { + auto ce = + AdvancedSyntaxNode::Create(ClosureExpression,true,{ + AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), + AdvancedSyntaxNode::Create(ReturnStatement,false,{ + AdvancedSyntaxNode::Create(EmbedStreamExpression,true,{item.ToString()}) + }) + }); + GenNode(instructions,ce,scope,contscope,brkscope,contI,brkI); + } + else { + instructions.push_back(new + SimpleInstruction(PUSHUNDEFINED)); + } - instructions.push_back(new SimpleInstruction(APPENDDICT));*/ - } + instructions.push_back(new + SimpleInstruction(APPENDDICT));*/ + } size_t offset = bytes.size(); - bytes.resize(offset+4); - BitConverter::FromUint32BE(bytes[offset], (uint32_t)entries.size()); - for(auto& item : entries) - { + bytes.resize(offset + 4); + BitConverter::FromUint32BE(bytes[offset], + (uint32_t)entries.size()); + for (auto &item : entries) { offset = bytes.size(); - bytes.resize(offset+4); - BitConverter::FromUint32BE(bytes[offset],GetString(item.first.GetFileName())); - if(item.second) + bytes.resize(offset + 4); + BitConverter::FromUint32BE( + bytes[offset], GetString(item.first.GetFileName())); + if (item.second) embedDir(item.first); else { bytes.push_back(12); offset = bytes.size(); - bytes.resize(offset+4); - bytes.resize(offset+4); - BitConverter::FromUint32BE(bytes[offset],GetResource(std::make_shared(item.first.ToString()))); + bytes.resize(offset + 4); + bytes.resize(offset + 4); + BitConverter::FromUint32BE( + bytes[offset], + GetResource(std::make_shared( + item.first.ToString()))); } } }; embedDir(filename); + return; + } + } + } + + bytes.push_back(2); +} + +void CodeGen::Save(std::shared_ptr stream) { + TVMVersion runtime_version( + CROSSLANG_BYTECODE_MAJOR, CROSSLANG_BYTECODE_MINOR, + CROSSLANG_BYTECODE_PATCH, CROSSLANG_BYTECODE_BUILD, + CROSSLANG_BYTECODE_VERSIONSTAGE); + uint8_t buffer[18]; + memcpy(buffer, "TCROSSVM", 8); + runtime_version.ToArray(buffer + 8); + version.ToArray(buffer + 13); + Write(stream, buffer, 18); + uint32_t sections = 5; + uint32_t name = GetString(this->name); + uint32_t info = GetString(this->info); + + for (auto &dep : this->dependencies) { + GetString(dep.first); + sections++; + } + for (auto &tool : this->tools) { + GetString(tool.first); + sections++; + } + for (auto &meta : this->meta) { + sections++; + } + if (!this->icon.empty()) { + this->GetResource(std::make_shared(this->icon)); + } + for (auto &res : this->res) + sections++; + + if (!this->icon.empty()) + sections++; + if (!this->classes.empty()) + sections++; + + WriteInt(stream, sections); + uint32_t strSz = 4; + for (auto &s : this->strs) { + strSz += (uint32_t)s.size() + 4; + } + memcpy(buffer, "STRS", 4); + Write(stream, buffer, 4); + WriteInt(stream, strSz); // even though its ignored + WriteInt(stream, this->strs.size()); + for (auto &str : this->strs) + WriteString(stream, str); + memcpy(buffer, "NAME", 4); + Write(stream, buffer, 4); + WriteInt(stream, 4); + WriteInt(stream, name); + memcpy(buffer, "INFO", 4); + Write(stream, buffer, 4); + WriteInt(stream, 4); + WriteInt(stream, info); + + for (auto &dep : this->dependencies) { + memcpy(buffer, "DEPS", 4); + Write(stream, buffer, 4); + WriteInt(stream, 9); // even though its ignored + WriteInt(stream, GetString(dep.first)); + dep.second.ToArray(buffer); + Write(stream, buffer, 5); + } + for (auto &tool : this->tools) { + memcpy(buffer, "TOOL", 4); + Write(stream, buffer, 4); + WriteInt(stream, 9); // even though its ignored + WriteInt(stream, GetString(tool.first)); + tool.second.ToArray(buffer); + Write(stream, buffer, 5); + } + + uint32_t fnLen = 4; + + for (auto &fn : this->funcs) { + fnLen += (fn.first.size() + 2) * 4; + } + + memcpy(buffer, "FUNS", 4); + Write(stream, buffer, 4); + WriteInt(stream, fnLen); + WriteInt(stream, (uint32_t)this->funcs.size()); + for (auto &fn : this->funcs) { + WriteInt(stream, (uint32_t)fn.first.size()); + for (auto namePart : fn.first) { + WriteInt(stream, namePart); + } + WriteInt(stream, fn.second); + } + + uint32_t clength = 4; + for (auto &chunk : this->chunks) { + clength += (2 + chunk.first.size()) * 4; + size_t offset = 0; + std::map items; + + for (auto instr : chunk.second) { + + auto lbl = dynamic_cast(instr); + if (lbl != nullptr) { + items[lbl->label] = offset; + } + + offset += instr->Size(); + } + + clength += (uint32_t)offset; + + for (auto instr : chunk.second) { + auto jmp = dynamic_cast(instr); + if (jmp != nullptr) { + jmp->n = items[jmp->label]; + } + } + } + + memcpy(buffer, "CHKS", 4); + Write(stream, buffer, 4); + WriteInt(stream, clength); + WriteInt(stream, (uint32_t)this->chunks.size()); + for (auto &chunk : this->chunks) { + std::vector buffer; + WriteInt(stream, (uint32_t)chunk.first.size()); + for (auto arg : chunk.first) { + WriteInt(stream, arg); + } + for (auto instr : chunk.second) { + instr->Write(buffer); + } + WriteInt(stream, (uint32_t)buffer.size()); + Write(stream, buffer.data(), buffer.size()); + } + + if (!classes.empty()) { + uint32_t len = 4; + for (auto &cls : classes) { + len += 8; + len += cls.name.size() * 4; + len += 4; + len += cls.inherits.size() * 4; + len += 4; + for (auto &clsEnt : cls.entries) { + len += 17; + for (auto &arg : clsEnt.arguments) + len += 4; + } + } + + memcpy(buffer, "CLSS", 4); + Write(stream, buffer, 4); + WriteInt(stream, len); + WriteInt(stream, (uint32_t)classes.size()); + for (auto &cls : classes) { + WriteInt(stream, cls.documentation); + WriteInt(stream, (uint32_t)cls.name.size()); + for (auto namePart : cls.name) + WriteInt(stream, namePart); + + WriteInt(stream, (uint32_t)cls.inherits.size()); + for (auto inhPart : cls.inherits) + WriteInt(stream, inhPart); + + WriteInt(stream, (uint32_t)cls.entries.size()); + + for (auto &ent : cls.entries) { + buffer[0] = ent.type; + Write(stream, buffer, 1); + WriteInt(stream, ent.documentation); + WriteInt(stream, ent.name); + WriteInt(stream, (uint32_t)ent.arguments.size()); + for (auto ar : ent.arguments) { + WriteInt(stream, ar); + } + WriteInt(stream, ent.closure); + } + } + } + + for (auto &reso : res) { + memcpy(buffer, "RESO", 4); + Write(stream, buffer, 4); + WriteInt(stream, reso->GetLength(embedFS)); + reso->Write(stream); + } + if (!this->icon.empty()) { + memcpy(buffer, "ICON", 4); + Write(stream, buffer, 4); + WriteInt(stream, 4); + WriteInt(stream, + this->GetResource(std::make_shared(this->icon))); + } + for (auto &meta : this->meta) { + memcpy(buffer, "META", 4); + Write(stream, buffer, 4); + WriteInt(stream, (uint32_t)meta.size()); + Write(stream, meta.data(), meta.size()); + } +} + +size_t SimpleInstruction::Size() { return 1; } +SimpleInstruction::SimpleInstruction(Instruction instr) { + this->instruction = instr; +} +void SimpleInstruction::Write(std::vector &instr) { + instr.push_back(instruction); +} + +ScopeEndTimesInstruction::ScopeEndTimesInstruction(uint32_t s) { this->n = s; } +size_t ScopeEndTimesInstruction::Size() { return 5; } +void ScopeEndTimesInstruction::Write(std::vector &instr) { + instr.push_back(SCOPEENDTIMES); + std::array buff; + BitConverter::FromUint32BE(buff[0], this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} + +LabelInstruction::LabelInstruction(std::string lbl) { this->label = lbl; } + +size_t LabelInstruction::Size() { return 0; } + +void LabelInstruction::Write(std::vector &instr) { + // label instructions do not write a thing +} + +JumpStyleInstruction::JumpStyleInstruction(Instruction instr, std::string lbl) { + this->type = instr; + this->label = lbl; + this->n = 0; +} + +size_t JumpStyleInstruction::Size() { return 5; } +void JumpStyleInstruction::Write(std::vector &instr) { + instr.push_back((uint8_t)type); + std::array buff; + BitConverter::FromUint32BE(buff[0], this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} + +size_t LabelableInstruction::Size() { return 4; } +void LabelableInstruction::Write(std::vector &instr) { + + std::array buff; + BitConverter::FromUint32BE(buff[0], this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} +StringInstruction::StringInstruction(uint32_t s) { this->n = s; } +size_t StringInstruction::Size() { return 5; } +void StringInstruction::Write(std::vector &instr) { + instr.push_back(PUSHSTRING); + std::array buff; + BitConverter::FromUint32BE(buff[0], this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} +EmbedInstruction::EmbedInstruction(uint32_t s) { this->n = s; } +size_t EmbedInstruction::Size() { return 5; } +void EmbedInstruction::Write(std::vector &instr) { + instr.push_back(PUSHRESOURCE); + std::array buff; + BitConverter::FromUint32BE(buff[0], this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} +EmbedStreamInstruction::EmbedStreamInstruction(uint32_t s) { this->n = s; } +size_t EmbedStreamInstruction::Size() { return 5; } +void EmbedStreamInstruction::Write(std::vector &instr) { + instr.push_back(PUSHRESOURCESTREAM); + std::array buff; + BitConverter::FromUint32BE(buff[0], this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} +ClosureInstruction::ClosureInstruction(uint32_t s, bool hasScope) { + this->n = s; + this->hasScope = hasScope; +} +size_t ClosureInstruction::Size() { return 5; } +void ClosureInstruction::Write(std::vector &instr) { + instr.push_back(this->hasScope ? PUSHCLOSURE : PUSHSCOPELESSCLOSURE); + std::array buff; + BitConverter::FromUint32BE(buff[0], this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} + +DoubleInstruction::DoubleInstruction(double s) { this->n = s; } +size_t DoubleInstruction::Size() { return 9; } +void DoubleInstruction::Write(std::vector &instr) { + instr.push_back(PUSHDOUBLE); + std::array buff; + BitConverter::FromDoubleBE(buff[0], this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} + +CharInstruction::CharInstruction(char s) { this->n = s; } +size_t CharInstruction::Size() { return 2; } +void CharInstruction::Write(std::vector &instr) { + instr.push_back(PUSHCHAR); + uint8_t buff[8]; + instr.push_back((uint8_t)this->n); +} +LongInstruction::LongInstruction(int64_t s) { this->n = s; } +size_t LongInstruction::Size() { return 9; } +void LongInstruction::Write(std::vector &instr) { + instr.push_back(PUSHLONG); + std::array buff; + BitConverter::FromUint64BE(buff[0], (uint64_t)this->n); + instr.insert(instr.end(), buff.begin(), buff.end()); +} +uint32_t CodeGen::GetString(std::string str) { + for (uint32_t i = 0; i < (uint32_t)this->strs.size(); i++) { + if (this->strs[i] == str) + return i; + } + uint32_t strI = (uint32_t)this->strs.size(); + this->strs.push_back(str); + return strI; +} +uint32_t CodeGen::GetResource(std::shared_ptr resource) { + for (uint32_t i = 0; i < (uint32_t)this->res.size(); i++) { + if (this->res[i]->IsEqual(resource.get())) + return i; + } + uint32_t resI = (uint32_t)this->res.size(); + this->res.push_back(resource); + return resI; +} +#define ONE_EXPR(EXPRESSION, INSTRUCTION) \ + if (adv.nodeName == EXPRESSION && adv.nodes.size() == 1) { \ + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, contI, \ + brkI); \ + instructions.push_back(new SimpleInstruction(INSTRUCTION)); \ + } +#define TWO_EXPR(EXPRESSION, INSTRUCTION) \ + if (adv.nodeName == EXPRESSION && adv.nodes.size() == 2) { \ + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, contI, \ + brkI); \ + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, contI, \ + brkI); \ + instructions.push_back(new SimpleInstruction(INSTRUCTION)); \ + } + +SyntaxNode CodeGen::StringifyListOfVars(SyntaxNode n) { + if (std::holds_alternative(n)) { + return n; + } else if (std::holds_alternative(n)) { + auto itemA = std::get(n); + if (itemA.nodeName == GetVariableExpression && + itemA.nodes.size() == 1 && + std::holds_alternative(itemA.nodes[0])) { + return std::get(itemA.nodes[0]); + } else if (itemA.nodeName == CommaExpression && + itemA.nodes.size() == 2) { + return AdvancedSyntaxNode::Create( + CommaExpression, true, + {StringifyListOfVars(itemA.nodes[0]), + StringifyListOfVars(itemA.nodes[1])}); + } + } + return nullptr; +} + +void CodeGen::GenNode(std::vector &instructions, + SyntaxNode n, int32_t scope, int32_t contscope, + int32_t brkscope, int32_t contI, int32_t brkI) { + if (std::holds_alternative(n)) { + instructions.push_back(new SimpleInstruction(PUSHNULL)); + } else if (std::holds_alternative(n)) { + instructions.push_back(new SimpleInstruction(PUSHUNDEFINED)); + } else if (std::holds_alternative(n)) { + instructions.push_back( + new SimpleInstruction(std::get(n) ? PUSHTRUE : PUSHFALSE)); + } else if (std::holds_alternative(n)) { + instructions.push_back( + new StringInstruction(GetString(std::get(n)))); + } else if (std::holds_alternative(n)) { + instructions.push_back(new CharInstruction(std::get(n))); + } else if (std::holds_alternative(n)) { + instructions.push_back(new LongInstruction(std::get(n))); + } else if (std::holds_alternative(n)) { + instructions.push_back(new DoubleInstruction(std::get(n))); + } else if (std::holds_alternative>(n)) { + ResourceByteArray ba; + ba.data = std::get>(n); + instructions.push_back(new EmbedInstruction( + GetResource(std::make_shared(ba)))); + } else if (std::holds_alternative(n)) { + auto adv = std::get(n); + ONE_EXPR(NotExpression, NOT) + ONE_EXPR(BitwiseNotExpression, BITWISENOT) + ONE_EXPR(NegativeExpression, NEGATIVE) + TWO_EXPR(AddExpression, ADD) + TWO_EXPR(SubExpression, SUB) + TWO_EXPR(TimesExpression, TIMES) + TWO_EXPR(DivideExpression, DIVIDE) + TWO_EXPR(ModExpression, MODULO) + TWO_EXPR(LeftShiftExpression, LEFTSHIFT) + TWO_EXPR(RightShiftExpression, RIGHTSHIFT) + TWO_EXPR(BitwiseOrExpression, BITWISEOR) + TWO_EXPR(BitwiseAndExpression, BITWISEAND) + TWO_EXPR(LessThanExpression, LESSTHAN) + TWO_EXPR(GreaterThanExpression, GREATERTHAN) + TWO_EXPR(LessThanEqualsExpression, LESSTHANEQ) + TWO_EXPR(GreaterThanEqualsExpression, GREATERTHANEQ) + TWO_EXPR(NotEqualsExpression, NEQ) + TWO_EXPR(EqualsExpression, EQ) + TWO_EXPR(XOrExpression, XOR) + if (adv.nodeName == GetPrivateExpression) { + instructions.push_back(new SimpleInstruction(PUSHPRIVATEXPRESSION)); + } + if (adv.nodeName == LineNode && adv.nodes.size() == 2) { + + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(LINEINFO)); + } else if (adv.nodeName == NullCoalescingExpression && + adv.nodes.size() == 2) { + uint32_t ifId = NewId(); + std::string ifIdTrue = "__compGenTrue"; + ifIdTrue.append(std::to_string(ifId)); + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back( + new JumpStyleInstruction(Instruction::JMPIFDEFINED, ifIdTrue)); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new LabelInstruction(ifIdTrue)); + + } else if (adv.nodeName == ClassStatement && adv.nodes.size() >= 3 && + std::holds_alternative(adv.nodes[0])) { + CodeGenClass cls; + cls.documentation = GetString(std::get(adv.nodes[0])); + GetFunctionName(cls.name, adv.nodes[1]); + GetFunctionName(cls.inherits, adv.nodes[2]); + for (size_t i = 3; i < adv.nodes.size(); i++) { + auto &node = adv.nodes[i]; + if (std::holds_alternative(node)) { + auto &adv2 = std::get(node); + CodeGenClassEntry ent; + ent.type = 0; + if (adv2.nodes.size() >= 2 && + std::holds_alternative(adv2.nodes[0]) && + std::holds_alternative(adv2.nodes[1])) { + ent.documentation = + GetString(std::get(adv2.nodes[0])); + std::string type = std::get(adv2.nodes[1]); + if (type == "private") + ent.type = 0; + else if (type == "protected") + ent.type = 1; + else if (type == "public") + ent.type = 2; + else if (type == "static") + ent.type = 3; + } + + if (adv2.nodeName == MethodStatement && + adv2.nodes.size() == 4 && + std::holds_alternative( + adv2.nodes[2])) { + + // documentation,myTkn.text,nameAndArgs,closureData + size_t fnindex = this->chunks.size(); + ent.closure = (uint32_t)fnindex; + this->chunks.resize(fnindex + 1); + auto &nameAndArgs = + std::get(adv2.nodes[2]); + if (nameAndArgs.nodeName == FunctionCallExpression && + !nameAndArgs.nodes.empty() && + std::holds_alternative( + nameAndArgs.nodes[0])) { + auto &getvar = std::get( + nameAndArgs.nodes[0]); + if (getvar.nodeName == GetVariableExpression && + getvar.nodes.size() == 1 && + std::holds_alternative( + getvar.nodes[0])) { + + ent.name = GetString( + std::get(getvar.nodes[0])); + if (nameAndArgs.nodes.size() > 1) { + GetFunctionArgs(ent.arguments, + nameAndArgs.nodes[1]); + } + } else + continue; + } + + std::vector fnInstructions; + + GenNode(fnInstructions, adv2.nodes[3], 0, -1, -1, -1, + -1); + + this->chunks[fnindex] = + std::pair, + std::vector>( + ent.arguments, fnInstructions); + } else if (adv2.nodeName == AbstractMethodStatement && + adv2.nodes.size() == 3 && + std::holds_alternative( + adv2.nodes[2])) { + ent.closure = 0; + ent.type |= 0b00001000; + // documentation,myTkn.text,nameAndArgs + auto &nameAndArgs = + std::get(adv2.nodes[2]); + if (nameAndArgs.nodeName == FunctionCallExpression && + !nameAndArgs.nodes.empty() && + std::holds_alternative( + nameAndArgs.nodes[0])) { + auto &getvar = std::get( + nameAndArgs.nodes[0]); + if (getvar.nodeName == GetVariableExpression && + getvar.nodes.size() == 1 && + std::holds_alternative( + getvar.nodes[0])) { + ent.name = GetString( + std::get(getvar.nodes[0])); + if (nameAndArgs.nodes.size() > 1) { + GetFunctionArgs(ent.arguments, + nameAndArgs.nodes[1]); + } + } else + continue; + } + + } else if (adv2.nodeName == FieldStatement && + adv2.nodes.size() == 3 && + std::holds_alternative( + adv2.nodes[2])) { + auto &setter = + std::get(adv2.nodes[2]); + if (setter.nodeName == GetVariableExpression && + setter.nodes.size() == 1 && + std::holds_alternative( + setter.nodes[0])) { + ent.closure = 0; + ent.type |= 0b00001100; + + ent.name = GetString( + std::get(setter.nodes[0])); + + } else if (setter.nodeName == AssignExpression && + setter.nodes.size() == 2 && + std::holds_alternative( + setter.nodes[0])) { + auto &getvar = + std::get(setter.nodes[0]); + if (getvar.nodeName == GetVariableExpression && + getvar.nodes.size() == 1 && + std::holds_alternative( + getvar.nodes[0])) { + ent.type |= 0b00000100; + ent.name = GetString( + std::get(getvar.nodes[0])); + size_t fnindex = this->chunks.size(); + ent.closure = (uint32_t)fnindex; + ent.arguments = {}; + + this->chunks.resize(fnindex + 1); + + std::vector + fnInstructions; + + GenNode(fnInstructions, + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {setter.nodes[1]}), + 0, -1, -1, -1, -1); + + this->chunks[fnindex] = std::pair< + std::vector, + std::vector>( + {}, fnInstructions); + } else + continue; + } else + continue; + } + cls.entries.push_back(ent); + } + } + classes.push_back(cls); + } else if (adv.nodeName == RelativePathExpression) { + instructions.push_back( + new SimpleInstruction(Instruction::PUSHRELATIVEPATH)); + } else if (adv.nodeName == RootPathExpression) { + instructions.push_back( + new SimpleInstruction(Instruction::PUSHROOTPATH)); + } else if (adv.nodeName == SwitchStatement && adv.nodes.size() == 2) { + // THIS CODE WORKED FIRST TRY, I DON'T SEE THAT EVERY DAY, PRAISE + // GOD!!!!!!! + auto expr = adv.nodes[0]; + + std::vector nodes_before; + + SyntaxNode currentCase = nullptr; + std::vector currentNodes; + std::string defaultJmp = {}; + + std::vector, + std::vector>> + snodes; + + if (std::holds_alternative(adv.nodes[1])) { + auto body = std::get(adv.nodes[1]); + if (body.nodeName == ScopeNode) { + for (auto item : body.nodes) { + if (std::holds_alternative(item)) { + auto no = std::get(item); + if (no.nodeName == CaseStatement || + no.nodeName == DefaultStatement) { + if (std::holds_alternative( + currentCase)) { + + uint32_t jmpId = NewId(); + std::string jmpIdStr = "__compGenJmp"; + jmpIdStr.append(std::to_string(jmpId)); + snodes.push_back( + std::pair, + std::vector>( + std::pair( + jmpIdStr, + std::get( + currentCase)), + currentNodes)); + currentNodes = {}; + } + currentCase = no; + continue; + } + } + + if (std::holds_alternative( + currentCase)) { + currentNodes.push_back(item); + } else { + nodes_before.push_back(item); + } + } + if (std::holds_alternative( + currentCase)) { + + uint32_t jmpId = NewId(); + std::string jmpIdStr = "__compGenJmp"; + jmpIdStr.append(std::to_string(jmpId)); + snodes.push_back( + std::pair< + std::pair, + std::vector>( + std::pair( + jmpIdStr, + std::get(currentCase)), + currentNodes)); + currentNodes = {}; + } + + uint32_t endId = NewId(); + std::string endIdStr = "__compGenBrk"; + endIdStr.append(std::to_string(endId)); + for (auto item : nodes_before) { + GenNode(instructions, item, scope, contscope, brkscope, + contI, brkI); + } + + for (auto item : snodes) { + if (item.first.second.nodeName == CaseStatement) { + auto eq = AdvancedSyntaxNode::Create( + EqualsExpression, true, + {item.first.second.nodes[0], adv.nodes[0]}); + GenNode(instructions, eq, scope, contscope, + brkscope, contI, brkI); + instructions.push_back(new JumpStyleInstruction( + JMPC, item.first.first)); + } + if (item.first.second.nodeName == DefaultStatement) { + if (!defaultJmp.empty()) + std::cout << "ERROR: multiple default in " + "switch statement will cause " + "undefined behaviour, this is not " + "an exception due to not allowing " + "exceptions in codegen stage (the " + "compilation shouldn't fail)" + << std::endl; + defaultJmp = item.first.first; + } + } + + if (defaultJmp.empty()) { + instructions.push_back( + new JumpStyleInstruction(JMP, endIdStr)); + } else { + instructions.push_back( + new JumpStyleInstruction(JMP, defaultJmp)); + } + + for (auto item : snodes) { + instructions.push_back( + new LabelInstruction(item.first.first)); + for (auto item2 : item.second) { + GenNode(instructions, item2, scope, contscope, + scope, contI, endId); + } + } + + instructions.push_back(new LabelInstruction(endIdStr)); + } + } + return; + } + if (adv.nodeName == TernaryExpression && adv.nodes.size() == 3) { + uint32_t ifId = NewId(); + std::string ifIdTrue = "__compGenTrue"; + ifIdTrue.append(std::to_string(ifId)); + std::string ifIdEnd = "__compGenEnd"; + ifIdEnd.append(std::to_string(ifId)); + + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new JumpStyleInstruction(JMPC, ifIdTrue)); + if (!std::holds_alternative(adv.nodes[2])) { + GenNode(instructions, adv.nodes[2], scope, contscope, brkscope, + contI, brkI); + } + instructions.push_back(new JumpStyleInstruction(JMP, ifIdEnd)); + instructions.push_back(new LabelInstruction(ifIdTrue)); + if (!std::holds_alternative(adv.nodes[1])) { + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + } + instructions.push_back(new LabelInstruction(ifIdEnd)); + + } else if (adv.nodeName == CompoundAssignExpression && + adv.nodes.size() == 1 && + std::holds_alternative(adv.nodes[0])) { + auto data = std::get(adv.nodes[0]); + if (data.nodes.size() == 2) { + auto d = AdvancedSyntaxNode::Create(AssignExpression, true, + {data.nodes[0], data}); + GenNode(instructions, d, scope, contscope, brkscope, contI, + brkI); + } + } else if (adv.nodeName == PrefixIncrementExpression && + adv.nodes.size() == 1) { + GenNode(instructions, + AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, {adv.nodes[0], (int64_t)1})}), + scope, contscope, brkscope, contI, brkI); + } else if (adv.nodeName == PrefixDecrementExpression && + adv.nodes.size() == 1) { + GenNode(instructions, + AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + SubExpression, true, {adv.nodes[0], (int64_t)1})}), + scope, contscope, brkscope, contI, brkI); + } else if (adv.nodeName == PostfixIncrementExpression && + adv.nodes.size() == 1) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + GenNode(instructions, + AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, {adv.nodes[0], (int64_t)1})}), + scope, contscope, brkscope, contI, brkI); + instructions.push_back(new SimpleInstruction(POP)); + } else if (adv.nodeName == PostfixDecrementExpression && + adv.nodes.size() == 1) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + GenNode(instructions, + AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + SubExpression, true, {adv.nodes[0], (int64_t)1})}), + scope, contscope, brkscope, contI, brkI); + instructions.push_back(new SimpleInstruction(POP)); + } else if (adv.nodeName == LogicalOrExpression && + adv.nodes.size() == 2) { + auto data = AdvancedSyntaxNode::Create( + TernaryExpression, true, + {adv.nodes[0], true, + AdvancedSyntaxNode::Create(TernaryExpression, true, + {adv.nodes[1], true, false})}); + GenNode(instructions, data, scope, contscope, brkscope, contI, + brkI); + } else if (adv.nodeName == LogicalAndExpression && + adv.nodes.size() == 2) { + auto data = AdvancedSyntaxNode::Create( + TernaryExpression, true, + {adv.nodes[0], + AdvancedSyntaxNode::Create(TernaryExpression, true, + {adv.nodes[1], true, false}), + false}); + GenNode(instructions, data, scope, contscope, brkscope, contI, + brkI); + } else if (adv.nodeName == EachStatement && adv.nodes.size() == 3) { + auto item = adv.nodes[0]; + auto list = adv.nodes[1]; + auto body = adv.nodes[2]; + + uint32_t compGenId = NewId(); + std::string compGenIttr = "__compGenIttr"; + compGenIttr.append(std::to_string(compGenId)); + + auto each = AdvancedSyntaxNode::Create( + NodeList, false, + {AdvancedSyntaxNode::Create( + AssignExpression, true, + {AdvancedSyntaxNode::Create(DeclareExpression, true, + {compGenIttr}), + AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {list, "GetEnumerator"})})}), + AdvancedSyntaxNode::Create( + DeferStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {compGenIttr}), + "Dispose"})})}), + AdvancedSyntaxNode::Create( + WhileStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + { + AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {compGenIttr}), + "MoveNext"}), + }), + AdvancedSyntaxNode::Create( + NodeList, false, + {AdvancedSyntaxNode::Create( + AssignExpression, true, + {item, AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {compGenIttr}), + "Current"})}), + body})})}); + GenNode(instructions, each, scope, contscope, brkscope, contI, + brkI); + + } else if (adv.nodeName == ArrayExpression) { + instructions.push_back(new SimpleInstruction(CREATEARRAY)); + std::vector itms; + if (adv.nodes.size() > 0) + + GetFunctionArgs(itms, adv.nodes[0]); + for (auto item : itms) { + GenNode(instructions, item, scope, contscope, brkscope, contI, + brkI); + instructions.push_back(new SimpleInstruction(APPENDLIST)); + } + } else if (adv.nodeName == DictionaryExpression) { + instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); + std::vector itms; + if (adv.nodes.size() > 0) + GetFunctionArgs(itms, adv.nodes[0]); + for (auto item : itms) { + if (std::holds_alternative(item)) { + auto tkn = std::get(item); + if (tkn.nodeName == GetVariableExpression && + !tkn.nodes.empty()) { + GenNode(instructions, tkn.nodes[0], scope, contscope, + brkscope, contI, brkI); + GenNode(instructions, item, scope, contscope, brkscope, + contI, brkI); + instructions.push_back( + new SimpleInstruction(APPENDDICT)); + } else if (tkn.nodeName == AssignExpression && + tkn.nodes.size() == 2 && + std::holds_alternative( + tkn.nodes[0])) { + auto myTn = std::get(tkn.nodes[0]); + if (myTn.nodeName == GetVariableExpression && + !myTn.nodes.empty()) { + GenNode(instructions, myTn.nodes[0], scope, + contscope, brkscope, contI, brkI); + GenNode(instructions, tkn.nodes[1], scope, + contscope, brkscope, contI, brkI); + instructions.push_back( + new SimpleInstruction(APPENDDICT)); + } + } + } + } + } else if (adv.nodeName == FunctionCallExpression && + adv.nodes.size() >= 1 && + std::holds_alternative(adv.nodes[0])) { + auto v = std::get(adv.nodes[0]); + if (v.nodeName == GetFieldExpression && v.nodes.size() == 2) { + GenNode(instructions, v.nodes[0], scope, contscope, brkscope, + contI, brkI); + GenNode(instructions, v.nodes[1], scope, contscope, brkscope, + contI, brkI); + if (adv.nodes.size() == 2) { + std::vector nodes; + GetFunctionArgs(nodes, adv.nodes[1]); + for (auto item : nodes) + GenNode(instructions, item, scope, contscope, brkscope, + contI, brkI); + instructions.push_back( + new LongInstruction((int64_t)nodes.size())); + } else { + instructions.push_back(new LongInstruction(0)); + } + instructions.push_back(new SimpleInstruction(CALLMETHOD)); + } else if (v.nodeName != GetFieldExpression) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + if (adv.nodes.size() == 2) { + std::vector nodes; + GetFunctionArgs(nodes, adv.nodes[1]); + for (auto item : nodes) + GenNode(instructions, item, scope, contscope, brkscope, + contI, brkI); + instructions.push_back( + new LongInstruction((int64_t)nodes.size())); + } else { + instructions.push_back(new LongInstruction(0)); + } + instructions.push_back(new SimpleInstruction(CALLFUNCTION)); + } + } else if (adv.nodeName == IfStatement && adv.nodes.size() == 3) { + uint32_t ifId = NewId(); + std::string ifIdTrue = "__compGenTrue"; + ifIdTrue.append(std::to_string(ifId)); + std::string ifIdEnd = "__compGenEnd"; + ifIdEnd.append(std::to_string(ifId)); + + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new JumpStyleInstruction(JMPC, ifIdTrue)); + if (!std::holds_alternative(adv.nodes[2])) { + GenNode(instructions, adv.nodes[2], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[2]); + } + instructions.push_back(new JumpStyleInstruction(JMP, ifIdEnd)); + instructions.push_back(new LabelInstruction(ifIdTrue)); + if (!std::holds_alternative(adv.nodes[1])) { + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[1]); + } + instructions.push_back(new LabelInstruction(ifIdEnd)); + + } else if (adv.nodeName == UsingStatement && adv.nodes.size() == 2) { + // using(EXPRESSION) {} + // using(EXPRESSION) STATEMENT; + + //{ __compGen = EXPRESSION; defer { __compGen.Dispose(); } + //{}(unrolled) OR STATEMENT; } + + if (std::holds_alternative(adv.nodes[1])) { + auto asn2 = std::get(adv.nodes[1]); + if (asn2.nodeName == ScopeNode) { + scope++; + instructions.push_back(new SimpleInstruction(SCOPEBEGIN)); + + uint32_t exprId = NewId(); + std::string exprStr = "__compGenUsing"; + exprStr.append(std::to_string(exprId)); + + auto _assign = AdvancedSyntaxNode::Create( + AssignExpression, true, + {AdvancedSyntaxNode::Create(DeclareExpression, true, + {exprStr}), + adv.nodes[0]}); + + GenNode(instructions, _assign, scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, _assign); + + auto _defer = AdvancedSyntaxNode::Create( + DeferStatement, false, + {AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {exprStr}), + "Dispose"})})})}); + + GenNode(instructions, _defer, scope, contscope, brkscope, + contI, brkI); + + for (size_t i = 0; i < asn2.nodes.size(); i++) { + GenNode(instructions, asn2.nodes[i], scope, contscope, + brkscope, contI, brkI); + if (!asn2.isExpression || i < asn2.nodes.size() - 1) + GenPop(instructions, asn2.nodes[i]); + } + instructions.push_back(new SimpleInstruction(SCOPEEND)); + scope--; return; } } - } - bytes.push_back(2); - } - - void CodeGen::Save(std::shared_ptr stream) - { - TVMVersion runtime_version(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE); - uint8_t buffer[18]; - memcpy(buffer,"TCROSSVM",8); - runtime_version.ToArray(buffer+8); - version.ToArray(buffer+13); - Write(stream,buffer,18); - uint32_t sections=5; - uint32_t name = GetString(this->name); - uint32_t info = GetString(this->info); - - for(auto& dep : this->dependencies) - { - GetString(dep.first); - sections++; - } - for(auto& tool : this->tools) - { - GetString(tool.first); - sections++; - } - for(auto& meta : this->meta) - { - sections++; - } - if(!this->icon.empty()) - { - this->GetResource(std::make_shared(this->icon)); - - } - for(auto& res : this->res) - sections++; - - if(!this->icon.empty()) - sections++; - if(!this->classes.empty()) - sections++; - - WriteInt(stream,sections); - uint32_t strSz=4; - for(auto& s : this->strs) - { - strSz += (uint32_t)s.size() + 4; - } - memcpy(buffer,"STRS",4); - Write(stream,buffer,4); - WriteInt(stream,strSz); //even though its ignored - WriteInt(stream,this->strs.size()); - for(auto& str : this->strs) - WriteString(stream,str); - memcpy(buffer,"NAME",4); - Write(stream,buffer,4); - WriteInt(stream,4); - WriteInt(stream,name); - memcpy(buffer,"INFO",4); - Write(stream,buffer,4); - WriteInt(stream,4); - WriteInt(stream,info); - - for(auto& dep : this->dependencies) - { - memcpy(buffer,"DEPS",4); - Write(stream,buffer,4); - WriteInt(stream,9); //even though its ignored - WriteInt(stream,GetString(dep.first)); - dep.second.ToArray(buffer); - Write(stream,buffer,5); - } - for(auto& tool : this->tools) - { - memcpy(buffer,"TOOL",4); - Write(stream,buffer,4); - WriteInt(stream,9); //even though its ignored - WriteInt(stream,GetString(tool.first)); - tool.second.ToArray(buffer); - Write(stream,buffer,5); - } - - uint32_t fnLen=4; - - for(auto& fn : this->funcs) - { - fnLen += (fn.first.size() + 2) * 4; - } - - memcpy(buffer,"FUNS",4); - Write(stream,buffer,4); - WriteInt(stream,fnLen); - WriteInt(stream,(uint32_t)this->funcs.size()); - for(auto& fn : this->funcs) - { - WriteInt(stream,(uint32_t)fn.first.size()); - for(auto namePart : fn.first) { - WriteInt(stream,namePart); + scope++; + instructions.push_back(new SimpleInstruction(SCOPEBEGIN)); + + uint32_t exprId = NewId(); + std::string exprStr = "__compGenUsing"; + exprStr.append(std::to_string(exprId)); + + auto _assign = AdvancedSyntaxNode::Create( + AssignExpression, true, + {AdvancedSyntaxNode::Create(DeclareExpression, true, + {exprStr}), + adv.nodes[0]}); + + GenNode(instructions, _assign, scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, _assign); + + auto _defer = AdvancedSyntaxNode::Create( + DeferStatement, false, + {AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, {exprStr}), + "Dispose"})})})}); + + GenNode(instructions, _defer, scope, contscope, brkscope, contI, + brkI); + + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + if (!adv.isExpression) + GenPop(instructions, adv.nodes[1]); + + instructions.push_back(new SimpleInstruction(SCOPEEND)); + scope--; } - WriteInt(stream,fn.second); - } + } else if (adv.nodeName == WhileStatement && adv.nodes.size() == 2) { + auto old_contI = contI; + auto old_brkI = brkI; + auto old_contscope = contscope; + auto old_brkscope = brkscope; - uint32_t clength = 4; - for(auto& chunk : this->chunks) - { - clength += (2 + chunk.first.size())*4; - size_t offset=0; - std::map items; - - for(auto instr : chunk.second) - { - - auto lbl = dynamic_cast(instr); - if(lbl != nullptr) - { - items[lbl->label] = offset; + contscope = scope; + brkscope = scope; + + uint32_t whileId = NewId(); + std::string whileIdCont = "__compGenCont"; + whileIdCont.append(std::to_string(whileId)); + std::string whileIdBrk = "__compGenBrk"; + whileIdBrk.append(std::to_string(whileId)); + + contI = whileId; + brkI = whileId; + + instructions.push_back(new LabelInstruction(whileIdCont)); + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(NOT)); + instructions.push_back(new JumpStyleInstruction(JMPC, whileIdBrk)); + + if (!std::holds_alternative(adv.nodes[1])) { + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[1]); + } + + instructions.push_back(new JumpStyleInstruction(JMP, whileIdCont)); + instructions.push_back(new LabelInstruction(whileIdBrk)); + + contI = old_contI; + brkI = old_brkI; + contscope = old_contscope; + brkscope = old_brkscope; + + } else if (adv.nodeName == DoStatement && adv.nodes.size() == 2) { + auto old_contI = contI; + auto old_brkI = brkI; + auto old_contscope = contscope; + auto old_brkscope = brkscope; + + contscope = scope; + brkscope = scope; + + uint32_t doId = NewId(); + std::string doIdCont = "__compGenCont"; + doIdCont.append(std::to_string(doId)); + std::string doIdBrk = "__compGenBrk"; + doIdBrk.append(std::to_string(doId)); + std::string doIdStart = "__compGenStart"; + doIdStart.append(std::to_string(doId)); + + contI = doId; + brkI = doId; + + instructions.push_back(new LabelInstruction(doIdStart)); + + if (!std::holds_alternative(adv.nodes[1])) { + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[1]); + } + instructions.push_back(new LabelInstruction(doIdCont)); + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + + instructions.push_back(new JumpStyleInstruction(JMPC, doIdStart)); + instructions.push_back(new LabelInstruction(doIdBrk)); + + contI = old_contI; + brkI = old_brkI; + contscope = old_contscope; + brkscope = old_brkscope; + + } else if (adv.nodeName == ForStatement && adv.nodes.size() == 4) { + if (!std::holds_alternative(adv.nodes[0])) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[0]); + } + auto old_contI = contI; + auto old_brkI = brkI; + auto old_contscope = contscope; + auto old_brkscope = brkscope; + + contscope = scope; + brkscope = scope; + + uint32_t doId = NewId(); + std::string doIdCont = "__compGenCont"; + doIdCont.append(std::to_string(doId)); + std::string doIdBrk = "__compGenBrk"; + doIdBrk.append(std::to_string(doId)); + std::string doIdStart = "__compGenStart"; + doIdStart.append(std::to_string(doId)); + std::string doIdStart2 = "__compGenCond"; + doIdStart2.append(std::to_string(doId)); + + contI = doId; + brkI = doId; + + instructions.push_back(new JumpStyleInstruction(JMP, doIdStart2)); + instructions.push_back(new LabelInstruction(doIdStart)); + if (!std::holds_alternative(adv.nodes[3])) { + GenNode(instructions, adv.nodes[3], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[3]); + } + + instructions.push_back(new LabelInstruction(doIdCont)); + if (!std::holds_alternative(adv.nodes[2])) { + GenNode(instructions, adv.nodes[2], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[2]); + } + instructions.push_back(new LabelInstruction(doIdStart2)); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new JumpStyleInstruction(JMPC, doIdStart)); + instructions.push_back(new LabelInstruction(doIdBrk)); + contI = old_contI; + brkI = old_brkI; + contscope = old_contscope; + brkscope = old_brkscope; + } else if (adv.nodeName == CommaExpression && adv.nodes.size() == 2) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[0]); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + + } else if (adv.nodeName == ContinueStatement) { + if (contscope == -1) { + std::cout << "WARN: continue does nothing here\n"; + } else if (contscope == -2) { + instructions.push_back(new SimpleInstruction(PUSHCONTINUE)); + instructions.push_back(new SimpleInstruction(RET)); + } else { + auto cont = scope - contscope; + if (cont > 0) + instructions.push_back( + new ScopeEndTimesInstruction((uint32_t)cont)); + + std::string myJmp = "__compGenCont"; + myJmp.append(std::to_string(contI)); + + instructions.push_back(new JumpStyleInstruction(JMP, myJmp)); + } + } else if (adv.nodeName == BreakStatement) { + if (brkscope == -1) { + std::cout << "WARN: break does nothing here\n"; + } else if (brkscope == -2) { + instructions.push_back(new SimpleInstruction(PUSHBREAK)); + instructions.push_back(new SimpleInstruction(RET)); + } else { + auto _brk = scope - brkscope; + if (_brk > 0) + instructions.push_back( + new ScopeEndTimesInstruction((uint32_t)_brk)); + + std::string myJmp = "__compGenBrk"; + myJmp.append(std::to_string(brkI)); + + instructions.push_back(new JumpStyleInstruction(JMP, myJmp)); + } + } else if (adv.nodeName == GetVariableExpression && + adv.nodes.size() == 1) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(GETVARIABLE)); + } else if (adv.nodeName == GetFieldExpression && + adv.nodes.size() == 2) { + + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + + instructions.push_back(new SimpleInstruction(GETFIELD)); + + } else if (adv.nodeName == GetArrayExpression && + adv.nodes.size() == 2) { + SyntaxNode n = AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create(GetFieldExpression, true, + {adv.nodes[0], "GetAt"}), + adv.nodes[1]}); + GenNode(instructions, n, scope, contscope, brkscope, contI, brkI); + } else if (adv.nodeName == AssignExpression && adv.nodes.size() == 2 && + std::holds_alternative(adv.nodes[0])) { + auto varNode = std::get(adv.nodes[0]); + + if (varNode.nodeName == GetVariableExpression && + varNode.nodes.size() == 1) { + GenNode(instructions, varNode.nodes[0], scope, contscope, + brkscope, contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(SETVARIABLE)); + } else if (varNode.nodeName == ArrayExpression && + varNode.nodes.size() >= 1) { + + auto vars = StringifyListOfVars(varNode.nodes[0]); + + auto nArray = + AdvancedSyntaxNode::Create(ArrayExpression, true, {vars}); + + this->GenNode(instructions, nArray, scope, contscope, brkscope, + contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(SETVARIABLE)); + } else if (varNode.nodeName == DeclareExpression && + varNode.nodes.size() == 1 && + std::holds_alternative(varNode.nodes[0])) { + GenNode(instructions, varNode.nodes[0], scope, contscope, + brkscope, contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(DECLAREVARIABLE)); + } else if (varNode.nodeName == DeclareExpression && + varNode.nodes.size() == 1 && + std::holds_alternative( + varNode.nodes[0])) { + auto adv2 = std::get(varNode.nodes[0]); + + if (adv2.nodeName == ArrayExpression && + adv2.nodes.size() == 1) { + + auto vars = StringifyListOfVars(adv2.nodes[0]); + + auto nArray = AdvancedSyntaxNode::Create(ArrayExpression, + true, {vars}); + + this->GenNode(instructions, nArray, scope, contscope, + brkscope, contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, + brkscope, contI, brkI); + instructions.push_back( + new SimpleInstruction(DECLAREVARIABLE)); } + } else if (varNode.nodeName == ConstExpression && + varNode.nodes.size() == 1 && + std::holds_alternative(varNode.nodes[0])) { + GenNode(instructions, varNode.nodes[0], scope, contscope, + brkscope, contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back( + new SimpleInstruction(DECLARECONSTVARIABLE)); + } else if (varNode.nodeName == ConstExpression && + varNode.nodes.size() == 1 && + std::holds_alternative( + varNode.nodes[0])) { + auto adv2 = std::get(varNode.nodes[0]); - offset += instr->Size(); + if (adv2.nodeName == ArrayExpression && + adv2.nodes.size() == 1) { - } - - clength += (uint32_t)offset; - - for(auto instr : chunk.second) - { - auto jmp = dynamic_cast(instr); - if(jmp != nullptr) - { - jmp->n = items[jmp->label]; + auto vars = StringifyListOfVars(adv2.nodes[0]); + + auto nArray = AdvancedSyntaxNode::Create(ArrayExpression, + true, {vars}); + + this->GenNode(instructions, nArray, scope, contscope, + brkscope, contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, + brkscope, contI, brkI); + instructions.push_back( + new SimpleInstruction(DECLARECONSTVARIABLE)); } + } else if (varNode.nodeName == GetFieldExpression && + varNode.nodes.size() == 2) { + GenNode(instructions, varNode.nodes[0], scope, contscope, + brkscope, contI, brkI); + + GenNode(instructions, varNode.nodes[1], scope, contscope, + brkscope, contI, brkI); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(SETFIELD)); + } else if (varNode.nodeName == GetArrayExpression && + varNode.nodes.size() == 2) { + SyntaxNode n = AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create(GetFieldExpression, true, + {varNode.nodes[0], "SetAt"}), + AdvancedSyntaxNode::Create( + CommaExpression, true, + {varNode.nodes[1], adv.nodes[1]})}); + GenNode(instructions, n, scope, contscope, brkscope, contI, + brkI); } - - } + } else if (adv.nodeName == BreakpointStatement && + adv.nodes.size() == 5) { + instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); + instructions.push_back(new StringInstruction(GetString("Data"))); + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back( + new StringInstruction(GetString("Filename"))); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Line"))); + GenNode(instructions, adv.nodes[2], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Column"))); + GenNode(instructions, adv.nodes[3], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Offset"))); + GenNode(instructions, adv.nodes[4], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new SimpleInstruction(BREAKPOINT)); + } else if (adv.nodeName == ThrowStatement && adv.nodes.size() == 5) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back( + new StringInstruction(GetString("Filename"))); + GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Line"))); + GenNode(instructions, adv.nodes[2], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Column"))); + GenNode(instructions, adv.nodes[3], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Offset"))); + GenNode(instructions, adv.nodes[4], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new SimpleInstruction(THROW)); + } else if (adv.nodeName == ReturnStatement && adv.nodes.size() == 1) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(RET)); + } else if (adv.nodeName == YieldStatement && adv.nodes.size() == 1) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + instructions.push_back(new SimpleInstruction(YIELD)); + } else if (adv.nodeName == ParenthesesExpression && + adv.nodes.size() == 1) { + GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, + contI, brkI); + } else if (adv.nodeName == EmbedExpression && adv.nodes.size() == 1 && + std::holds_alternative(adv.nodes[0])) { + std::string filename = std::get(adv.nodes[0]); + instructions.push_back(new EmbedInstruction( + GetResource(std::make_shared(filename)))); - memcpy(buffer,"CHKS",4); - Write(stream,buffer,4); - WriteInt(stream,clength); - WriteInt(stream,(uint32_t)this->chunks.size()); - for(auto& chunk : this->chunks) - { - std::vector buffer; - WriteInt(stream,(uint32_t)chunk.first.size()); - for(auto arg : chunk.first) - { - WriteInt(stream,arg); - } - for(auto instr : chunk.second) - { - instr->Write(buffer); - } - WriteInt(stream,(uint32_t)buffer.size()); - Write(stream,buffer.data(),buffer.size()); - } - - if(!classes.empty()) - { - uint32_t len = 4; - for(auto& cls : classes) - { - len += 8; - len += cls.name.size() * 4; - len += 4; - len += cls.inherits.size() * 4; - len += 4; - for(auto& clsEnt : cls.entries) - { - len += 17; - for(auto& arg : clsEnt.arguments) len+=4; - } - } + } else if (adv.nodeName == MetadataStatement && adv.nodes.size() == 2 && + std::holds_alternative(adv.nodes[0])) { + auto &name = std::get(adv.nodes[0]); - memcpy(buffer,"CLSS",4); - Write(stream,buffer,4); - WriteInt(stream,len); - WriteInt(stream,(uint32_t)classes.size()); - for(auto& cls : classes) - { - WriteInt(stream,cls.documentation); - WriteInt(stream,(uint32_t)cls.name.size()); - for(auto namePart : cls.name) WriteInt(stream,namePart); + auto &metabytes = this->meta.emplace_back(); + metabytes.resize(4); + BitConverter::FromUint32BE(metabytes[0], GetString(name)); - WriteInt(stream,(uint32_t)cls.inherits.size()); - for(auto inhPart : cls.inherits) WriteInt(stream,inhPart); + WriteMetadataObject(metabytes, adv.nodes[1]); + } else if (adv.nodeName == EmbedStreamExpression && + adv.nodes.size() == 1 && + std::holds_alternative(adv.nodes[0])) { + std::string filename = std::get(adv.nodes[0]); + instructions.push_back(new EmbedStreamInstruction( + GetResource(std::make_shared(filename)))); - WriteInt(stream,(uint32_t)cls.entries.size()); - - for(auto& ent : cls.entries) - { - buffer[0] = ent.type; - Write(stream,buffer,1); - WriteInt(stream,ent.documentation); - WriteInt(stream,ent.name); - WriteInt(stream,(uint32_t)ent.arguments.size()); - for(auto ar : ent.arguments) - { - WriteInt(stream,ar); - } - WriteInt(stream,ent.closure); - } - } - } - - for(auto& reso : res) - { - memcpy(buffer,"RESO",4); - Write(stream,buffer,4); - WriteInt(stream,reso->GetLength(embedFS)); - reso->Write(stream); - } - if(!this->icon.empty()) - { - memcpy(buffer,"ICON",4); - Write(stream,buffer,4); - WriteInt(stream,4); - WriteInt(stream,this->GetResource(std::make_shared(this->icon))); - - } - for(auto& meta : this->meta) - { - memcpy(buffer,"META", 4); - Write(stream,buffer,4); - WriteInt(stream,(uint32_t)meta.size()); - Write(stream,meta.data(),meta.size()); - } - } - - - size_t SimpleInstruction::Size() - { - return 1; - } - SimpleInstruction::SimpleInstruction(Instruction instr) - { - this->instruction = instr; - } - void SimpleInstruction::Write(std::vector& instr) - { - instr.push_back(instruction); - } - - - ScopeEndTimesInstruction::ScopeEndTimesInstruction(uint32_t s) - { - this->n = s; - } - size_t ScopeEndTimesInstruction::Size() - { - return 5; - } - void ScopeEndTimesInstruction::Write(std::vector& instr) - { - instr.push_back(SCOPEENDTIMES); - std::array buff; - BitConverter::FromUint32BE(buff[0],this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - - LabelInstruction::LabelInstruction(std::string lbl) - { - this->label = lbl; - } - - size_t LabelInstruction::Size() - { - return 0; - } - - void LabelInstruction::Write(std::vector& instr) - { - //label instructions do not write a thing - } - - JumpStyleInstruction::JumpStyleInstruction(Instruction instr, std::string lbl) - { - this->type = instr; - this->label = lbl; - this->n = 0; - } - - size_t JumpStyleInstruction::Size() - { - return 5; - } - void JumpStyleInstruction::Write(std::vector& instr) - { - instr.push_back((uint8_t)type); - std::array buff; - BitConverter::FromUint32BE(buff[0],this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - - size_t LabelableInstruction::Size() - { - return 4; - } - void LabelableInstruction::Write(std::vector& instr) - { - - std::array buff; - BitConverter::FromUint32BE(buff[0],this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - StringInstruction::StringInstruction(uint32_t s) - { - this->n = s; - } - size_t StringInstruction::Size() - { - return 5; - } - void StringInstruction::Write(std::vector& instr) - { - instr.push_back(PUSHSTRING); - std::array buff; - BitConverter::FromUint32BE(buff[0],this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - EmbedInstruction::EmbedInstruction(uint32_t s) - { - this->n = s; - } - size_t EmbedInstruction::Size() - { - return 5; - } - void EmbedInstruction::Write(std::vector& instr) - { - instr.push_back(PUSHRESOURCE); - std::array buff; - BitConverter::FromUint32BE(buff[0],this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - EmbedStreamInstruction::EmbedStreamInstruction(uint32_t s) - { - this->n = s; - } - size_t EmbedStreamInstruction::Size() - { - return 5; - } - void EmbedStreamInstruction::Write(std::vector& instr) - { - instr.push_back(PUSHRESOURCESTREAM); - std::array buff; - BitConverter::FromUint32BE(buff[0],this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - ClosureInstruction::ClosureInstruction(uint32_t s,bool hasScope) - { - this->n = s; - this->hasScope = hasScope; - } - size_t ClosureInstruction::Size() - { - return 5; - } - void ClosureInstruction::Write(std::vector& instr) - { - instr.push_back(this->hasScope ? PUSHCLOSURE : PUSHSCOPELESSCLOSURE); - std::array buff; - BitConverter::FromUint32BE(buff[0],this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - - DoubleInstruction::DoubleInstruction(double s) - { - this->n = s; - } - size_t DoubleInstruction::Size() - { - return 9; - } - void DoubleInstruction::Write(std::vector& instr) - { - instr.push_back(PUSHDOUBLE); - std::array buff; - BitConverter::FromDoubleBE(buff[0],this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - - CharInstruction::CharInstruction(char s) - { - this->n = s; - } - size_t CharInstruction::Size() - { - return 2; - } - void CharInstruction::Write(std::vector& instr) - { - instr.push_back(PUSHCHAR); - uint8_t buff[8]; - instr.push_back((uint8_t)this->n); - } - LongInstruction::LongInstruction(int64_t s) - { - this->n = s; - } - size_t LongInstruction::Size() - { - return 9; - } - void LongInstruction::Write(std::vector& instr) - { - instr.push_back(PUSHLONG); - std::array buff; - BitConverter::FromUint64BE(buff[0],(uint64_t)this->n); - instr.insert(instr.end(),buff.begin(),buff.end()); - } - uint32_t CodeGen::GetString(std::string str) - { - for(uint32_t i = 0; i < (uint32_t)this->strs.size();i++) - { - if(this->strs[i] == str) return i; - } - uint32_t strI = (uint32_t)this->strs.size(); - this->strs.push_back(str); - return strI; - } - uint32_t CodeGen::GetResource(std::shared_ptr resource) - { - for(uint32_t i = 0; i < (uint32_t)this->res.size();i++) - { - if(this->res[i]->IsEqual(resource.get())) return i; - } - uint32_t resI = (uint32_t)this->res.size(); - this->res.push_back(resource); - return resI; - } - #define ONE_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 1) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));} - #define TWO_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 2) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));} - - SyntaxNode CodeGen::StringifyListOfVars(SyntaxNode n) - { - if(std::holds_alternative(n)) - { - return n; - } - else if(std::holds_alternative(n)) - { - auto itemA=std::get(n); - if(itemA.nodeName == GetVariableExpression && itemA.nodes.size()==1 && std::holds_alternative(itemA.nodes[0])) - { - return std::get(itemA.nodes[0]); - } - else if(itemA.nodeName == CommaExpression && itemA.nodes.size()==2) - { - return AdvancedSyntaxNode::Create(CommaExpression,true,{StringifyListOfVars(itemA.nodes[0]),StringifyListOfVars(itemA.nodes[1])}); - } - - - - } - return nullptr; - } - - - void CodeGen::GenNode(std::vector& instructions, SyntaxNode n,int32_t scope,int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI) - { - if(std::holds_alternative(n)) - { - instructions.push_back(new SimpleInstruction(PUSHNULL)); - } - else if(std::holds_alternative(n)) - { - instructions.push_back(new SimpleInstruction(PUSHUNDEFINED)); - } - else if(std::holds_alternative(n)) - { - instructions.push_back(new SimpleInstruction(std::get(n) ? PUSHTRUE : PUSHFALSE)); - } - else if(std::holds_alternative(n)) - { - instructions.push_back(new StringInstruction(GetString(std::get(n)))); - } - else if(std::holds_alternative(n)) - { - instructions.push_back(new CharInstruction(std::get(n))); - } - else if(std::holds_alternative(n)) - { - instructions.push_back(new LongInstruction(std::get(n))); - } - else if(std::holds_alternative(n)) - { - instructions.push_back(new DoubleInstruction(std::get(n))); - } - else if(std::holds_alternative>(n)) - { - ResourceByteArray ba; - ba.data = std::get>(n); - instructions.push_back(new EmbedInstruction(GetResource(std::make_shared(ba)))); - } - else if(std::holds_alternative(n)) - { - auto adv = std::get(n); - ONE_EXPR(NotExpression, NOT) - ONE_EXPR(BitwiseNotExpression, BITWISENOT) - ONE_EXPR(NegativeExpression,NEGATIVE) - TWO_EXPR(AddExpression, ADD) - TWO_EXPR(SubExpression, SUB) - TWO_EXPR(TimesExpression, TIMES) - TWO_EXPR(DivideExpression, DIVIDE) - TWO_EXPR(ModExpression, MODULO) - TWO_EXPR(LeftShiftExpression, LEFTSHIFT) - TWO_EXPR(RightShiftExpression, RIGHTSHIFT) - TWO_EXPR(BitwiseOrExpression, BITWISEOR) - TWO_EXPR(BitwiseAndExpression, BITWISEAND) - TWO_EXPR(LessThanExpression, LESSTHAN) - TWO_EXPR(GreaterThanExpression, GREATERTHAN) - TWO_EXPR(LessThanEqualsExpression, LESSTHANEQ) - TWO_EXPR(GreaterThanEqualsExpression, GREATERTHANEQ) - TWO_EXPR(NotEqualsExpression, NEQ) - TWO_EXPR(EqualsExpression, EQ) - TWO_EXPR(XOrExpression, XOR) - if(adv.nodeName == LineNode && adv.nodes.size() == 2) - { - - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(LINEINFO)); - } - else if(adv.nodeName == NullCoalescingExpression && adv.nodes.size() == 2) - { - uint32_t ifId = NewId(); - std::string ifIdTrue = "__compGenTrue"; - ifIdTrue.append(std::to_string(ifId)); - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new JumpStyleInstruction(Instruction::JMPIFDEFINED, ifIdTrue)); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new LabelInstruction(ifIdTrue)); - - } - else if(adv.nodeName == ClassStatement && adv.nodes.size() >= 3 && std::holds_alternative(adv.nodes[0])) - { - CodeGenClass cls; - cls.documentation = GetString(std::get(adv.nodes[0])); - GetFunctionName(cls.name,adv.nodes[1]); - GetFunctionName(cls.inherits,adv.nodes[2]); - for(size_t i = 3; i < adv.nodes.size(); i++) - { - auto& node = adv.nodes[i]; - if(std::holds_alternative(node)) - { - auto& adv2 = std::get(node); - CodeGenClassEntry ent; - ent.type = 0; - if(adv2.nodes.size() >= 2 && std::holds_alternative(adv2.nodes[0]) && std::holds_alternative(adv2.nodes[1])) - { - ent.documentation=GetString(std::get(adv2.nodes[0])); - std::string type=std::get(adv2.nodes[1]); - if(type == "private") ent.type = 0; - else if(type == "protected") ent.type = 1; - else if(type == "public") ent.type = 2; - else if(type == "static") ent.type = 3; - } - - if(adv2.nodeName == MethodStatement && adv2.nodes.size() == 4 && std::holds_alternative(adv2.nodes[2]) ) - { - - - //documentation,myTkn.text,nameAndArgs,closureData - size_t fnindex=this->chunks.size(); - ent.closure=(uint32_t)fnindex; - this->chunks.resize(fnindex+1); - auto& nameAndArgs= std::get(adv2.nodes[2]); - if(nameAndArgs.nodeName == FunctionCallExpression && !nameAndArgs.nodes.empty() && std::holds_alternative(nameAndArgs.nodes[0])) - { - auto& getvar = std::get(nameAndArgs.nodes[0]); - if(getvar.nodeName == GetVariableExpression && getvar.nodes.size() == 1 && std::holds_alternative(getvar.nodes[0])) - { - - ent.name = GetString(std::get(getvar.nodes[0])); - if(nameAndArgs.nodes.size() > 1) - { - GetFunctionArgs(ent.arguments, nameAndArgs.nodes[1]); - } - } - else continue; - } - - std::vector fnInstructions; - - GenNode(fnInstructions,adv2.nodes[3],0,-1,-1,-1,-1); - - this->chunks[fnindex] = std::pair,std::vector>(ent.arguments, fnInstructions); - } - else if(adv2.nodeName == AbstractMethodStatement && adv2.nodes.size() == 3 && std::holds_alternative(adv2.nodes[2])) - { - ent.closure = 0; - ent.type |= 0b00001000; - //documentation,myTkn.text,nameAndArgs - auto& nameAndArgs= std::get(adv2.nodes[2]); - if(nameAndArgs.nodeName == FunctionCallExpression && !nameAndArgs.nodes.empty() && std::holds_alternative(nameAndArgs.nodes[0])) - { - auto& getvar = std::get(nameAndArgs.nodes[0]); - if(getvar.nodeName == GetVariableExpression && getvar.nodes.size() == 1 && std::holds_alternative(getvar.nodes[0])) - { - ent.name = GetString(std::get(getvar.nodes[0])); - if(nameAndArgs.nodes.size() > 1) - { - GetFunctionArgs(ent.arguments, nameAndArgs.nodes[1]); - } - } else continue; - - - } - - } - else if(adv2.nodeName == FieldStatement && adv2.nodes.size() == 3 && std::holds_alternative(adv2.nodes[2])) - { - auto& setter = std::get(adv2.nodes[2]); - if(setter.nodeName == GetVariableExpression && setter.nodes.size() == 1 && std::holds_alternative(setter.nodes[0])) - { - ent.closure = 0; - ent.type |= 0b00001100; - - ent.name = GetString(std::get(setter.nodes[0])); - - } - else if(setter.nodeName == AssignExpression && setter.nodes.size() == 2 && std::holds_alternative(setter.nodes[0])) - { - auto& getvar = std::get(setter.nodes[0]); - if(getvar.nodeName == GetVariableExpression && getvar.nodes.size() == 1 && std::holds_alternative(getvar.nodes[0])) - { - ent.type |= 0b00000100; - ent.name = GetString(std::get(getvar.nodes[0])); - size_t fnindex=this->chunks.size(); - ent.closure=(uint32_t)fnindex; - ent.arguments={}; - - this->chunks.resize(fnindex+1); - - std::vector fnInstructions; - - GenNode(fnInstructions,AdvancedSyntaxNode::Create(ReturnStatement,false,{setter.nodes[1]}),0,-1,-1,-1,-1); - - this->chunks[fnindex] = std::pair,std::vector>({}, fnInstructions); - } - else continue; - } - else continue; - } - cls.entries.push_back(ent); - } - } - classes.push_back(cls); - } - else if(adv.nodeName == RelativePathExpression) - { - instructions.push_back(new SimpleInstruction(Instruction::PUSHRELATIVEPATH)); - } - else if(adv.nodeName == RootPathExpression) - { - instructions.push_back(new SimpleInstruction(Instruction::PUSHROOTPATH)); - } - else if(adv.nodeName == SwitchStatement && adv.nodes.size() == 2) - { - //THIS CODE WORKED FIRST TRY, I DON'T SEE THAT EVERY DAY, PRAISE GOD!!!!!!! - auto expr = adv.nodes[0]; - - std::vector nodes_before; - - SyntaxNode currentCase = nullptr; - std::vector currentNodes; - std::string defaultJmp = {}; - - std::vector,std::vector>> snodes; - - - - if(std::holds_alternative(adv.nodes[1])) - { - auto body = std::get(adv.nodes[1]); - if(body.nodeName == ScopeNode) - { - for(auto item : body.nodes) - { - if(std::holds_alternative(item)) - { - auto no = std::get(item); - if(no.nodeName == CaseStatement || no.nodeName == DefaultStatement) - { - if(std::holds_alternative(currentCase)) - { - - uint32_t jmpId = NewId(); - std::string jmpIdStr = "__compGenJmp"; - jmpIdStr.append(std::to_string(jmpId)); - snodes.push_back(std::pair,std::vector>(std::pair(jmpIdStr,std::get(currentCase)),currentNodes)); - currentNodes={}; - } - currentCase = no; - continue; - } - - } - - if(std::holds_alternative(currentCase)) - { - currentNodes.push_back(item); - } - else - { - nodes_before.push_back(item); - } - - } - if(std::holds_alternative(currentCase)) - { - - uint32_t jmpId = NewId(); - std::string jmpIdStr = "__compGenJmp"; - jmpIdStr.append(std::to_string(jmpId)); - snodes.push_back(std::pair,std::vector>(std::pair(jmpIdStr,std::get(currentCase)),currentNodes)); - currentNodes={}; - } - - uint32_t endId = NewId(); - std::string endIdStr = "__compGenBrk"; - endIdStr.append(std::to_string(endId)); - for(auto item : nodes_before) - { - GenNode(instructions,item,scope,contscope,brkscope,contI,brkI); - } - - for(auto item : snodes) - { - if(item.first.second.nodeName == CaseStatement) - { - auto eq = AdvancedSyntaxNode::Create(EqualsExpression,true,{ - item.first.second.nodes[0], - adv.nodes[0] - }); - GenNode(instructions,eq,scope,contscope,brkscope,contI,brkI); - instructions.push_back(new JumpStyleInstruction(JMPC,item.first.first)); - } - if(item.first.second.nodeName == DefaultStatement) - { - if(!defaultJmp.empty()) std::cout << "ERROR: multiple default in switch statement will cause undefined behaviour, this is not an exception due to not allowing exceptions in codegen stage (the compilation shouldn't fail)" << std::endl; - defaultJmp = item.first.first; - } - } - - if(defaultJmp.empty()) - { - instructions.push_back(new JumpStyleInstruction(JMP,endIdStr)); - } - else - { - instructions.push_back(new JumpStyleInstruction(JMP,defaultJmp)); - } - - for(auto item : snodes) - { - instructions.push_back(new LabelInstruction(item.first.first)); - for(auto item2 : item.second) - { - GenNode(instructions,item2,scope,contscope,scope,contI,endId); - } - } - - instructions.push_back(new LabelInstruction(endIdStr)); - } - } - return; - } - if(adv.nodeName == TernaryExpression && adv.nodes.size() == 3) - { - uint32_t ifId = NewId(); - std::string ifIdTrue = "__compGenTrue"; - ifIdTrue.append(std::to_string(ifId)); - std::string ifIdEnd = "__compGenEnd"; - ifIdEnd.append(std::to_string(ifId)); - - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new JumpStyleInstruction(JMPC,ifIdTrue)); - if(!std::holds_alternative(adv.nodes[2])) - { - GenNode(instructions,adv.nodes[2],scope,contscope,brkscope,contI,brkI); - - } - instructions.push_back(new JumpStyleInstruction(JMP,ifIdEnd)); - instructions.push_back(new LabelInstruction(ifIdTrue)); - if(!std::holds_alternative(adv.nodes[1])) - { - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - - } - instructions.push_back(new LabelInstruction(ifIdEnd)); - - } - else if(adv.nodeName == CompoundAssignExpression && adv.nodes.size() == 1 && std::holds_alternative(adv.nodes[0])) - { - auto data = std::get(adv.nodes[0]); - if(data.nodes.size() == 2) - { - auto d = AdvancedSyntaxNode::Create(AssignExpression,true,{ - data.nodes[0], - data - }); - GenNode(instructions,d,scope,contscope,brkscope,contI,brkI); - } - } - else if(adv.nodeName == PrefixIncrementExpression && adv.nodes.size() == 1) - { - GenNode(instructions, - AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{ - AdvancedSyntaxNode::Create(AddExpression,true,{ - adv.nodes[0] - , - (int64_t)1 - }) - }) - ,scope,contscope,brkscope,contI,brkI); - } - else if(adv.nodeName == PrefixDecrementExpression && adv.nodes.size() == 1) - { - GenNode(instructions, - AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{ - AdvancedSyntaxNode::Create(SubExpression,true,{ - adv.nodes[0] - , - (int64_t)1 - }) - }) - ,scope,contscope,brkscope,contI,brkI); - } - else if(adv.nodeName == PostfixIncrementExpression && adv.nodes.size() == 1) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions, - AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{ - AdvancedSyntaxNode::Create(AddExpression,true,{ - adv.nodes[0] - , - (int64_t)1 - }) - }) - ,scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(POP)); - } - else if(adv.nodeName == PostfixDecrementExpression && adv.nodes.size() == 1) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions, - AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{ - AdvancedSyntaxNode::Create(SubExpression,true,{ - adv.nodes[0] - , - (int64_t)1 - }) - }) - ,scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(POP)); - } - else if(adv.nodeName == LogicalOrExpression && adv.nodes.size() == 2) - { - auto data= AdvancedSyntaxNode::Create(TernaryExpression,true,{adv.nodes[0],true, AdvancedSyntaxNode::Create(TernaryExpression,true,{adv.nodes[1],true,false}) }); - GenNode(instructions,data,scope,contscope,brkscope,contI,brkI); - } - else if(adv.nodeName == LogicalAndExpression && adv.nodes.size() == 2) - { - auto data= AdvancedSyntaxNode::Create(TernaryExpression,true,{adv.nodes[0], AdvancedSyntaxNode::Create(TernaryExpression,true,{adv.nodes[1],true,false}),false}); - GenNode(instructions,data,scope,contscope,brkscope,contI,brkI); - } - else if(adv.nodeName == EachStatement && adv.nodes.size() == 3) - { - auto item = adv.nodes[0]; - auto list = adv.nodes[1]; - auto body = adv.nodes[2]; - - uint32_t compGenId = NewId(); - std::string compGenIttr = "__compGenIttr"; - compGenIttr.append(std::to_string(compGenId)); - - auto each = AdvancedSyntaxNode::Create(NodeList,false,{ - AdvancedSyntaxNode::Create(AssignExpression,true, { - AdvancedSyntaxNode::Create(DeclareExpression,true,{compGenIttr}), - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{AdvancedSyntaxNode::Create(GetFieldExpression,true,{list,"GetEnumerator"})}) - }), - AdvancedSyntaxNode::Create(DeferStatement,false,{AdvancedSyntaxNode::Create(FunctionCallExpression,true,{AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{compGenIttr}), "Dispose"})})}), - AdvancedSyntaxNode::Create(WhileStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{compGenIttr}),"MoveNext" }),}), - AdvancedSyntaxNode::Create(NodeList,false,{ - AdvancedSyntaxNode::Create(AssignExpression,true,{ - item, - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{ - compGenIttr - }), - "Current" - }) - }), - body - }) - }) - }); - GenNode(instructions,each,scope,contscope,brkscope,contI,brkI); - - } - else if(adv.nodeName == ArrayExpression) - { - instructions.push_back(new SimpleInstruction(CREATEARRAY)); - std::vector itms; - if(adv.nodes.size() > 0) - - GetFunctionArgs(itms,adv.nodes[0]); - for(auto item : itms) - { - GenNode(instructions,item,scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(APPENDLIST)); - } - } - else if(adv.nodeName == DictionaryExpression) - { + } else if (adv.nodeName == EmbedDirectoryExpression && + adv.nodes.size() == 1 && + std::holds_alternative(adv.nodes[0])) { + std::string filename = std::get(adv.nodes[0]); + std::function + embedDir; + embedDir = + [&](Tesses::Framework::Filesystem::VFSPath path) -> void { instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); - std::vector itms; - if(adv.nodes.size() > 0) - GetFunctionArgs(itms,adv.nodes[0]); - for(auto item : itms) - { - if(std::holds_alternative(item)) - { - auto tkn = std::get(item); - if(tkn.nodeName == GetVariableExpression && !tkn.nodes.empty()) - { - GenNode(instructions,tkn.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,item,scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - } - else if(tkn.nodeName == AssignExpression && tkn.nodes.size()==2 && std::holds_alternative(tkn.nodes[0])) - { - auto myTn = std::get(tkn.nodes[0]); - if(myTn.nodeName == GetVariableExpression && !myTn.nodes.empty()) - { - GenNode(instructions,myTn.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,tkn.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - } + + if (embedFS != nullptr && embedFS->DirectoryExists(path)) + for (auto &item : embedFS->EnumeratePaths(path)) { + GenNode(instructions, item.GetFileName(), scope, + contscope, brkscope, contI, brkI); + if (embedFS->DirectoryExists(item)) { + embedDir(item); + } else if (embedFS->RegularFileExists(item)) { + auto ce = AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create( + ParenthesesExpression, true, {}), + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + EmbedStreamExpression, true, + {item.ToString()})})}); + GenNode(instructions, ce, scope, contscope, + brkscope, contI, brkI); + } else { + instructions.push_back( + new SimpleInstruction(PUSHUNDEFINED)); } + + instructions.push_back( + new SimpleInstruction(APPENDDICT)); } - } + }; + embedDir(filename); + // + // instructions.push_back(new + // EmbedStreamInstruction(GetResource(std::make_shared(filename)))); + instructions.push_back(new SimpleInstruction(PUSHRESOUURCEDIR)); + } else if (adv.nodeName == HtmlRootExpression) { + scope++; + instructions.push_back(new SimpleInstruction(SCOPEBEGIN)); + + instructions.push_back(new StringInstruction( + GetString(std::get(adv.nodes[0])))); + instructions.push_back(new StringInstruction(GetString(""))); + instructions.push_back(new SimpleInstruction(DECLAREVARIABLE)); + instructions.push_back(new SimpleInstruction(POP)); + + for (size_t i = 1; i < adv.nodes.size(); i++) { + GenNode(instructions, adv.nodes[i], scope, contscope, brkscope, + contI, brkI); + GenPop(instructions, adv.nodes[i]); } - else if(adv.nodeName == FunctionCallExpression && adv.nodes.size() >= 1 && std::holds_alternative(adv.nodes[0])) - { - auto v = std::get(adv.nodes[0]); - if(v.nodeName == GetFieldExpression && v.nodes.size() == 2) - { - GenNode(instructions,v.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,v.nodes[1],scope,contscope,brkscope,contI,brkI); - if(adv.nodes.size()==2) - { - std::vector nodes; - GetFunctionArgs(nodes,adv.nodes[1]); - for(auto item : nodes) - GenNode(instructions,item,scope,contscope,brkscope,contI,brkI); - instructions.push_back(new LongInstruction((int64_t)nodes.size())); - } - else { - instructions.push_back(new LongInstruction(0)); - } - instructions.push_back(new SimpleInstruction(CALLMETHOD)); - } - else if(v.nodeName != GetFieldExpression) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - if(adv.nodes.size()==2) - { - std::vector nodes; - GetFunctionArgs(nodes,adv.nodes[1]); - for(auto item : nodes) - GenNode(instructions,item,scope,contscope,brkscope,contI,brkI); - instructions.push_back(new LongInstruction((int64_t)nodes.size())); - } - else { - instructions.push_back(new LongInstruction(0)); - } - instructions.push_back(new SimpleInstruction(CALLFUNCTION)); - } + + instructions.push_back(new StringInstruction( + GetString(std::get(adv.nodes[0])))); + instructions.push_back(new SimpleInstruction(GETVARIABLE)); + instructions.push_back(new SimpleInstruction(SCOPEEND)); + scope--; + } else if (adv.nodeName == ScopeNode) { + + scope++; + instructions.push_back(new SimpleInstruction(SCOPEBEGIN)); + for (size_t i = 0; i < adv.nodes.size(); i++) { + GenNode(instructions, adv.nodes[i], scope, contscope, brkscope, + contI, brkI); + if (!adv.isExpression || i < adv.nodes.size() - 1) + GenPop(instructions, adv.nodes[i]); } - else if(adv.nodeName == IfStatement && adv.nodes.size() == 3) - { - uint32_t ifId = NewId(); - std::string ifIdTrue = "__compGenTrue"; - ifIdTrue.append(std::to_string(ifId)); - std::string ifIdEnd = "__compGenEnd"; - ifIdEnd.append(std::to_string(ifId)); - - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new JumpStyleInstruction(JMPC,ifIdTrue)); - if(!std::holds_alternative(adv.nodes[2])) - { - GenNode(instructions,adv.nodes[2],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[2]); - } - instructions.push_back(new JumpStyleInstruction(JMP,ifIdEnd)); - instructions.push_back(new LabelInstruction(ifIdTrue)); - if(!std::holds_alternative(adv.nodes[1])) - { - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[1]); - } - instructions.push_back(new LabelInstruction(ifIdEnd)); + instructions.push_back(new SimpleInstruction(SCOPEEND)); + scope--; + } else if (adv.nodeName == NodeList) { + for (auto item : adv.nodes) { + GenNode(instructions, item, scope, contscope, brkscope, contI, + brkI); + GenPop(instructions, item); } - else if(adv.nodeName == UsingStatement && adv.nodes.size() == 2) - { - //using(EXPRESSION) {} - //using(EXPRESSION) STATEMENT; - - //{ __compGen = EXPRESSION; defer { __compGen.Dispose(); } {}(unrolled) OR STATEMENT; } - - if(std::holds_alternative(adv.nodes[1])) - { - auto asn2 = std::get(adv.nodes[1]); - if(asn2.nodeName == ScopeNode) - { - scope++; - instructions.push_back(new SimpleInstruction(SCOPEBEGIN)); - - uint32_t exprId = NewId(); - std::string exprStr = "__compGenUsing"; - exprStr.append(std::to_string(exprId)); - - auto _assign=AdvancedSyntaxNode::Create(AssignExpression,true,{ - AdvancedSyntaxNode::Create(DeclareExpression,true,{exprStr}), - adv.nodes[0] - }); - - GenNode(instructions,_assign,scope,contscope,brkscope,contI,brkI); - GenPop(instructions,_assign); - - - auto _defer=AdvancedSyntaxNode::Create(DeferStatement,false,{ - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression, true, { - exprStr - }), - "Dispose" - }) - }) - }) - }); - - - GenNode(instructions,_defer,scope,contscope,brkscope,contI,brkI); - - for(size_t i = 0; i < asn2.nodes.size(); i++) - { - GenNode(instructions,asn2.nodes[i],scope,contscope,brkscope,contI,brkI); - if(!asn2.isExpression || i < asn2.nodes.size()-1) - GenPop(instructions,asn2.nodes[i]); - } - instructions.push_back(new SimpleInstruction(SCOPEEND)); - scope--; - return; - } - } - - { - scope++; - instructions.push_back(new SimpleInstruction(SCOPEBEGIN)); - - uint32_t exprId = NewId(); - std::string exprStr = "__compGenUsing"; - exprStr.append(std::to_string(exprId)); - - auto _assign=AdvancedSyntaxNode::Create(AssignExpression,true,{ - AdvancedSyntaxNode::Create(DeclareExpression,true,{exprStr}), - adv.nodes[0] - }); - - GenNode(instructions,_assign,scope,contscope,brkscope,contI,brkI); - GenPop(instructions,_assign); - - - auto _defer=AdvancedSyntaxNode::Create(DeferStatement,false,{ - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression, true, { - exprStr - }), - "Dispose" - }) - }) - }) - }); - - - GenNode(instructions,_defer,scope,contscope,brkscope,contI,brkI); - - - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - if(!adv.isExpression) - GenPop(instructions,adv.nodes[1]); - - instructions.push_back(new SimpleInstruction(SCOPEEND)); - scope--; - } + } else if (adv.nodeName == DeferStatement && adv.nodes.size() == 1) { + GenNode(instructions, + AdvancedSyntaxNode::Create( + ScopelessClosureExpression, true, + {AdvancedSyntaxNode::Create(ParenthesesExpression, true, + {}), + adv.nodes[0]}), + scope, contscope, brkscope, contI, brkI); + instructions.push_back(new SimpleInstruction(DEFER)); + } else if (adv.nodeName == TryStatement && adv.nodes.size() == 4) { + // AdvancedSyntaxNode::Create(TryStatement, false, + // {tryBody,catchNode,catchEx, finally}); + if (std::holds_alternative(adv.nodes[3])) { + GenNode(instructions, + AdvancedSyntaxNode::Create(DeferStatement, false, + {adv.nodes[3]}), + scope, contscope, brkscope, contI, brkI); } - else if(adv.nodeName == WhileStatement && adv.nodes.size() == 2) - { - auto old_contI = contI; - auto old_brkI = brkI; - auto old_contscope = contscope; - auto old_brkscope = brkscope; - - contscope = scope; - brkscope = scope; - - uint32_t whileId = NewId(); - std::string whileIdCont = "__compGenCont"; - whileIdCont.append(std::to_string(whileId)); - std::string whileIdBrk = "__compGenBrk"; - whileIdBrk.append(std::to_string(whileId)); - - contI = whileId; - brkI = whileId; - - instructions.push_back(new LabelInstruction(whileIdCont)); - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(NOT)); - instructions.push_back(new JumpStyleInstruction(JMPC,whileIdBrk)); - - if(!std::holds_alternative(adv.nodes[1])) - { - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[1]); + if (std::holds_alternative(adv.nodes[0]) && + std::holds_alternative(adv.nodes[1]) && + std::holds_alternative(adv.nodes[2])) { + GenNode(instructions, + AdvancedSyntaxNode::Create( + ScopelessClosureExpression, true, + {AdvancedSyntaxNode::Create(ParenthesesExpression, + true, {}), + adv.nodes[0]}), + scope, contscope == -1 ? -1 : -2, + brkscope == -1 ? -1 : -2, contI, brkI); + GenNode(instructions, + AdvancedSyntaxNode::Create( + ScopelessClosureExpression, true, + {AdvancedSyntaxNode::Create(ParenthesesExpression, + true, {adv.nodes[2]}), + adv.nodes[1]}), + scope, contscope == -1 ? -1 : -2, + brkscope == -1 ? -1 : -2, contI, brkI); + instructions.push_back(new SimpleInstruction(TRYCATCH)); + uint32_t compGenId = NewId(); + std::string compGenIttr = "__compGenRetThing"; + compGenIttr.append(std::to_string(compGenId)); + if (contscope != -1) { + instructions.push_back(new JumpStyleInstruction( + JMPIFCONTINUE, compGenIttr + "_cont")); } - - instructions.push_back(new JumpStyleInstruction(JMP,whileIdCont)); - instructions.push_back(new LabelInstruction(whileIdBrk)); - - contI = old_contI; - brkI = old_brkI; - contscope = old_contscope; - brkscope = old_brkscope; - - } - else if(adv.nodeName == DoStatement && adv.nodes.size() == 2) - { - auto old_contI = contI; - auto old_brkI = brkI; - auto old_contscope = contscope; - auto old_brkscope = brkscope; - - contscope = scope; - brkscope = scope; - - uint32_t doId = NewId(); - std::string doIdCont = "__compGenCont"; - doIdCont.append(std::to_string(doId)); - std::string doIdBrk = "__compGenBrk"; - doIdBrk.append(std::to_string(doId)); - std::string doIdStart = "__compGenStart"; - doIdStart.append(std::to_string(doId)); - - contI = doId; - brkI = doId; - - - instructions.push_back(new LabelInstruction(doIdStart)); - - if(!std::holds_alternative(adv.nodes[1])) - { - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[1]); + if (brkscope != -1) { + instructions.push_back(new JumpStyleInstruction( + JMPIFBREAK, compGenIttr + "_brk")); } - instructions.push_back(new LabelInstruction(doIdCont)); - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - - instructions.push_back(new JumpStyleInstruction(JMPC,doIdStart)); - instructions.push_back(new LabelInstruction(doIdBrk)); - - contI = old_contI; - brkI = old_brkI; - contscope = old_contscope; - brkscope = old_brkscope; - - } - else if(adv.nodeName == ForStatement && adv.nodes.size() == 4) - { - if(!std::holds_alternative(adv.nodes[0])) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[0]); - } - auto old_contI = contI; - auto old_brkI = brkI; - auto old_contscope = contscope; - auto old_brkscope = brkscope; - - contscope = scope; - brkscope = scope; - - uint32_t doId = NewId(); - std::string doIdCont = "__compGenCont"; - doIdCont.append(std::to_string(doId)); - std::string doIdBrk = "__compGenBrk"; - doIdBrk.append(std::to_string(doId)); - std::string doIdStart = "__compGenStart"; - doIdStart.append(std::to_string(doId)); - std::string doIdStart2 = "__compGenCond"; - doIdStart2.append(std::to_string(doId)); - - contI = doId; - brkI = doId; - - instructions.push_back(new JumpStyleInstruction(JMP,doIdStart2)); - instructions.push_back(new LabelInstruction(doIdStart)); - if(!std::holds_alternative(adv.nodes[3])) - { - GenNode(instructions,adv.nodes[3],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[3]); - } - - instructions.push_back(new LabelInstruction(doIdCont)); - if(!std::holds_alternative(adv.nodes[2])) - { - GenNode(instructions,adv.nodes[2],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[2]); - } - instructions.push_back(new LabelInstruction(doIdStart2)); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new JumpStyleInstruction(JMPC,doIdStart)); - instructions.push_back(new LabelInstruction(doIdBrk)); - contI = old_contI; - brkI = old_brkI; - contscope = old_contscope; - brkscope = old_brkscope; - } - else if(adv.nodeName == CommaExpression && adv.nodes.size() == 2) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[0]); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - - } - else if(adv.nodeName == ContinueStatement) - { - if( contscope == -1) - { - std::cout << "WARN: continue does nothing here\n"; - } - else if(contscope == -2) - { + instructions.push_back( + new JumpStyleInstruction(JMPUNDEFINED, compGenIttr)); + instructions.push_back(new SimpleInstruction(RET)); + if (contscope == -2) { + instructions.push_back( + new LabelInstruction(compGenIttr + "_cont")); instructions.push_back(new SimpleInstruction(PUSHCONTINUE)); instructions.push_back(new SimpleInstruction(RET)); - } - else - { - auto cont = scope-contscope; - if(cont > 0) - instructions.push_back(new ScopeEndTimesInstruction((uint32_t)cont)); - + } else if (contscope != -1) { + instructions.push_back( + new LabelInstruction(compGenIttr + "_cont")); + auto cont = scope - contscope; + if (cont > 0) + instructions.push_back( + new ScopeEndTimesInstruction((uint32_t)cont)); + std::string myJmp = "__compGenCont"; myJmp.append(std::to_string(contI)); - instructions.push_back(new JumpStyleInstruction(JMP,myJmp)); + instructions.push_back( + new JumpStyleInstruction(JMP, myJmp)); } - } - else if(adv.nodeName == BreakStatement) - { - if( brkscope == -1) - { - std::cout << "WARN: break does nothing here\n"; - } - else if(brkscope == -2) - { + if (brkscope == -2) { + instructions.push_back( + new LabelInstruction(compGenIttr + "_brk")); instructions.push_back(new SimpleInstruction(PUSHBREAK)); instructions.push_back(new SimpleInstruction(RET)); - } - else - { - auto _brk = scope-brkscope; - if(_brk > 0) - instructions.push_back(new ScopeEndTimesInstruction((uint32_t)_brk)); - + } else if (brkscope != -1) { + instructions.push_back( + new LabelInstruction(compGenIttr + "_brk")); + auto _brk = scope - brkscope; + if (_brk > 0) + instructions.push_back( + new ScopeEndTimesInstruction((uint32_t)_brk)); + std::string myJmp = "__compGenBrk"; myJmp.append(std::to_string(brkI)); - instructions.push_back(new JumpStyleInstruction(JMP,myJmp)); + instructions.push_back( + new JumpStyleInstruction(JMP, myJmp)); } - } - else if(adv.nodeName == GetVariableExpression && adv.nodes.size() == 1) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(GETVARIABLE)); - } - else if(adv.nodeName == GetFieldExpression && adv.nodes.size() == 2) - { - - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - - instructions.push_back(new SimpleInstruction(GETFIELD)); - - } - else if(adv.nodeName == GetArrayExpression && adv.nodes.size() == 2) - { - SyntaxNode n = AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{adv.nodes[0],"GetAt"}), - adv.nodes[1] - }); - GenNode(instructions,n,scope,contscope,brkscope,contI,brkI); - } - else if(adv.nodeName == AssignExpression && adv.nodes.size() == 2 && std::holds_alternative(adv.nodes[0])) - { - auto varNode = std::get(adv.nodes[0]); - if(varNode.nodeName == GetVariableExpression && varNode.nodes.size() == 1) - { - GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(SETVARIABLE)); + instructions.push_back(new LabelInstruction(compGenIttr)); + } + + } else if (adv.nodeName == ScopelessClosureExpression && + adv.nodes.size() == 2) { + //()=>{} + // Name => {} + //(a,b) => {} + // it has two args + std::vector args; + GetFunctionArgs(args, adv.nodes[0]); + + std::vector fnInstructions; + size_t fnindex = this->chunks.size(); + this->chunks.resize(fnindex + 1); + + auto body = adv.nodes[1]; + + if (std::holds_alternative(body)) { + auto res = std::get(body); + if (res.nodeName == ScopeNode) { + res.nodeName = NodeList; } - else if(varNode.nodeName == ArrayExpression && varNode.nodes.size() >= 1) - { + body = res; + } - auto vars= StringifyListOfVars(varNode.nodes[0]); + GenNode(fnInstructions, body, 0, contscope == -2 ? -2 : -1, + brkscope == -2 ? -2 : -1, -1, -1); + this->chunks[fnindex] = + std::pair, + std::vector>(args, + fnInstructions); + instructions.push_back( + new ClosureInstruction((uint32_t)fnindex, false)); + } else if (adv.nodeName == ClosureExpression && adv.nodes.size() == 2) { + //()=>{} + // Name => {} + //(a,b) => {} + // it has two args + std::vector args; + GetFunctionArgs(args, adv.nodes[0]); - auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,true,{vars}); + std::vector fnInstructions; + size_t fnindex = this->chunks.size(); + this->chunks.resize(fnindex + 1); - this->GenNode(instructions,nArray ,scope ,contscope ,brkscope ,contI , brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(SETVARIABLE)); + auto body = adv.nodes[1]; + + if (std::holds_alternative(body)) { + auto res = std::get(body); + if (res.nodeName == ScopeNode) { + res.nodeName = NodeList; } - else if(varNode.nodeName == DeclareExpression && varNode.nodes.size() == 1 && std::holds_alternative(varNode.nodes[0])) - { - GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(DECLAREVARIABLE)); + body = res; + } + + GenNode(fnInstructions, body, 0, -1, -1, -1, -1); + + this->chunks[fnindex] = + std::pair, + std::vector>(args, + fnInstructions); + instructions.push_back(new ClosureInstruction((uint32_t)fnindex)); + } else if (adv.nodeName == FunctionStatement && adv.nodes.size() == 2 && + std::holds_alternative(adv.nodes[0])) { + // func NAME(ARGS) {} + // we need to disect NAME(ARGS) and {} + // then disect NAME and (ARGS) + auto fcall = std::get(adv.nodes[0]); + if (fcall.nodeName == FunctionCallExpression && + adv.nodes.size() >= 1 && + std::holds_alternative(fcall.nodes[0])) { + SyntaxNode args = + AdvancedSyntaxNode::Create(ParenthesesExpression, true, {}); + if (fcall.nodes.size() == 2) { + args = AdvancedSyntaxNode::Create(ParenthesesExpression, + true, {fcall.nodes[1]}); } - else if(varNode.nodeName == DeclareExpression && varNode.nodes.size() == 1 && std::holds_alternative(varNode.nodes[0])) - { - auto adv2 = std::get(varNode.nodes[0]); + SyntaxNode closure = AdvancedSyntaxNode::Create( + ClosureExpression, true, {args, adv.nodes[1]}); - if(adv2.nodeName == ArrayExpression && adv2.nodes.size() == 1) - { + SyntaxNode assign = AdvancedSyntaxNode::Create( + AssignExpression, false, {fcall.nodes[0], closure}); + GenNode(instructions, assign, scope, contscope, brkscope, contI, + brkI); - auto vars= StringifyListOfVars(adv2.nodes[0]); - - auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,true,{vars}); - - this->GenNode(instructions,nArray ,scope ,contscope ,brkscope ,contI , brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(DECLAREVARIABLE)); - - } - } - else if(varNode.nodeName == ConstExpression && varNode.nodes.size() == 1 && std::holds_alternative(varNode.nodes[0])) - { - GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(DECLARECONSTVARIABLE)); - } - else if(varNode.nodeName == ConstExpression && varNode.nodes.size() == 1 && std::holds_alternative(varNode.nodes[0])) - { - auto adv2 = std::get(varNode.nodes[0]); - - if(adv2.nodeName == ArrayExpression && adv2.nodes.size() == 1) - { - - auto vars= StringifyListOfVars(adv2.nodes[0]); - - auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,true,{vars}); - - this->GenNode(instructions,nArray ,scope ,contscope ,brkscope ,contI , brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(DECLARECONSTVARIABLE)); - - } - } - else if(varNode.nodeName == GetFieldExpression && varNode.nodes.size() == 2) - { - GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI); - - GenNode(instructions,varNode.nodes[1],scope,contscope,brkscope,contI,brkI); - GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(SETFIELD)); - } - else if(varNode.nodeName == GetArrayExpression && varNode.nodes.size() == 2) - { - SyntaxNode n = AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{varNode.nodes[0],"SetAt"}), - AdvancedSyntaxNode::Create(CommaExpression,true, - { - varNode.nodes[1], - adv.nodes[1] - }) - }); - GenNode(instructions,n,scope,contscope,brkscope,contI,brkI); - } - } - else if(adv.nodeName == BreakpointStatement && adv.nodes.size() == 5) - { - instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); - instructions.push_back(new StringInstruction(GetString("Data"))); - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new StringInstruction(GetString("Filename"))); - GenNode(instructions,adv.nodes[1] ,scope,contscope ,brkscope ,contI ,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new StringInstruction(GetString("Line"))); - GenNode(instructions,adv.nodes[2] ,scope,contscope ,brkscope ,contI ,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new StringInstruction(GetString("Column"))); - GenNode(instructions,adv.nodes[3] ,scope,contscope ,brkscope ,contI ,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new StringInstruction(GetString("Offset"))); - GenNode(instructions,adv.nodes[4] ,scope,contscope ,brkscope ,contI ,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new SimpleInstruction(BREAKPOINT)); - } - else if(adv.nodeName == ThrowStatement && adv.nodes.size() == 5) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new StringInstruction(GetString("Filename"))); - GenNode(instructions,adv.nodes[1] ,scope,contscope ,brkscope ,contI ,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new StringInstruction(GetString("Line"))); - GenNode(instructions,adv.nodes[2] ,scope,contscope ,brkscope ,contI ,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new StringInstruction(GetString("Column"))); - GenNode(instructions,adv.nodes[3] ,scope,contscope ,brkscope ,contI ,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new StringInstruction(GetString("Offset"))); - GenNode(instructions,adv.nodes[4] ,scope,contscope ,brkscope ,contI ,brkI); - instructions.push_back(new SimpleInstruction(APPENDDICT)); - instructions.push_back(new SimpleInstruction(THROW)); - } - else if(adv.nodeName == ReturnStatement && adv.nodes.size() == 1) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(RET)); - } - else if(adv.nodeName == YieldStatement && adv.nodes.size() == 1) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(YIELD)); - } - else if(adv.nodeName == ParenthesesExpression && adv.nodes.size() == 1) - { - GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); - } - else if(adv.nodeName == EmbedExpression && adv.nodes.size() == 1 && std::holds_alternative(adv.nodes[0])) - { - std::string filename = std::get(adv.nodes[0]); - instructions.push_back(new EmbedInstruction(GetResource(std::make_shared(filename)))); - - } - else if(adv.nodeName == MetadataStatement && adv.nodes.size() == 2 && std::holds_alternative(adv.nodes[0])) - { - auto& name = std::get(adv.nodes[0]); - - - auto& metabytes= this->meta.emplace_back(); - metabytes.resize(4); - BitConverter::FromUint32BE(metabytes[0],GetString(name)); - - WriteMetadataObject(metabytes, adv.nodes[1]); - } - else if(adv.nodeName == EmbedStreamExpression && adv.nodes.size() == 1 && std::holds_alternative(adv.nodes[0])) - { - std::string filename = std::get(adv.nodes[0]); - instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared(filename)))); - - } - else if(adv.nodeName == EmbedDirectoryExpression && adv.nodes.size() == 1 && std::holds_alternative(adv.nodes[0])) - { - std::string filename = std::get(adv.nodes[0]); - std::function embedDir; - embedDir = [&](Tesses::Framework::Filesystem::VFSPath path)-> void { - instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); - - if(embedFS != nullptr && embedFS->DirectoryExists(path)) - for(auto& item : embedFS->EnumeratePaths(path)) - { - GenNode(instructions,item.GetFileName(),scope,contscope,brkscope,contI,brkI); - if(embedFS->DirectoryExists(item)) - { - embedDir(item); - } - else if(embedFS->RegularFileExists(item)) - { - auto ce = AdvancedSyntaxNode::Create(ClosureExpression,true,{ - AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(EmbedStreamExpression,true,{item.ToString()}) - }) - }); - GenNode(instructions,ce,scope,contscope,brkscope,contI,brkI); - } - else { - instructions.push_back(new SimpleInstruction(PUSHUNDEFINED)); - } - - instructions.push_back(new SimpleInstruction(APPENDDICT)); - } - }; - embedDir(filename); - // - //instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared(filename)))); - instructions.push_back(new SimpleInstruction(PUSHRESOUURCEDIR)); - } - else if(adv.nodeName == HtmlRootExpression) - { - scope++; - instructions.push_back(new SimpleInstruction(SCOPEBEGIN)); - - instructions.push_back(new StringInstruction(GetString(std::get(adv.nodes[0])))); - instructions.push_back(new StringInstruction(GetString(""))); - instructions.push_back(new SimpleInstruction(DECLAREVARIABLE)); instructions.push_back(new SimpleInstruction(POP)); - - for(size_t i = 1; i < adv.nodes.size(); i++) - { - GenNode(instructions,adv.nodes[i],scope,contscope,brkscope,contI,brkI); - GenPop(instructions,adv.nodes[i]); - } - - instructions.push_back(new StringInstruction(GetString(std::get(adv.nodes[0])))); - instructions.push_back(new SimpleInstruction(GETVARIABLE)); - instructions.push_back(new SimpleInstruction(SCOPEEND)); - scope--; - } - else if(adv.nodeName == ScopeNode) - { - - scope++; - instructions.push_back(new SimpleInstruction(SCOPEBEGIN)); - for(size_t i = 0; i < adv.nodes.size(); i++) - { - GenNode(instructions,adv.nodes[i],scope,contscope,brkscope,contI,brkI); - if(!adv.isExpression || i < adv.nodes.size()-1) - GenPop(instructions,adv.nodes[i]); - } - instructions.push_back(new SimpleInstruction(SCOPEEND)); - scope--; - } - else if(adv.nodeName == NodeList) - { - - for(auto item : adv.nodes) - { - GenNode(instructions,item,scope,contscope,brkscope,contI,brkI); - GenPop(instructions,item); - } - } - else if(adv.nodeName == DeferStatement && adv.nodes.size() == 1) - { - GenNode(instructions,AdvancedSyntaxNode::Create(ScopelessClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),adv.nodes[0]}),scope,contscope,brkscope,contI,brkI); - instructions.push_back(new SimpleInstruction(DEFER)); - } - else if(adv.nodeName == TryStatement && adv.nodes.size() == 4) - { - //AdvancedSyntaxNode::Create(TryStatement, false, {tryBody,catchNode,catchEx, finally}); - if(std::holds_alternative(adv.nodes[3])) - { - GenNode(instructions,AdvancedSyntaxNode::Create(DeferStatement,false, {adv.nodes[3]}),scope,contscope,brkscope,contI,brkI); - } - if(std::holds_alternative(adv.nodes[0]) && std::holds_alternative(adv.nodes[1]) && std::holds_alternative(adv.nodes[2])) - { - GenNode(instructions,AdvancedSyntaxNode::Create(ScopelessClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),adv.nodes[0]}),scope,contscope == -1 ? -1 : -2,brkscope == -1 ? -1 : -2,contI,brkI); - GenNode(instructions,AdvancedSyntaxNode::Create(ScopelessClosureExpression,true,{ - AdvancedSyntaxNode::Create(ParenthesesExpression,true,{adv.nodes[2]}), - adv.nodes[1] - }),scope,contscope == -1 ? -1 : -2,brkscope == -1 ? -1 : -2,contI,brkI); - instructions.push_back(new SimpleInstruction(TRYCATCH)); - uint32_t compGenId = NewId(); - std::string compGenIttr = "__compGenRetThing"; - compGenIttr.append(std::to_string(compGenId)); - if(contscope != -1) - { - instructions.push_back(new JumpStyleInstruction(JMPIFCONTINUE,compGenIttr+"_cont")); - } - if(brkscope != -1) - { - instructions.push_back(new JumpStyleInstruction(JMPIFBREAK,compGenIttr+"_brk")); - } - instructions.push_back(new JumpStyleInstruction(JMPUNDEFINED, compGenIttr)); - instructions.push_back(new SimpleInstruction(RET)); - if(contscope == -2) - { - instructions.push_back(new LabelInstruction(compGenIttr+"_cont")); - instructions.push_back(new SimpleInstruction(PUSHCONTINUE)); - instructions.push_back(new SimpleInstruction(RET)); - } - else if(contscope != -1) - { - instructions.push_back(new LabelInstruction(compGenIttr+"_cont")); - auto cont = scope-contscope; - if(cont > 0) - instructions.push_back(new ScopeEndTimesInstruction((uint32_t)cont)); - - std::string myJmp = "__compGenCont"; - myJmp.append(std::to_string(contI)); - - instructions.push_back(new JumpStyleInstruction(JMP,myJmp)); - } - if(brkscope == -2) - { - instructions.push_back(new LabelInstruction(compGenIttr+"_brk")); - instructions.push_back(new SimpleInstruction(PUSHBREAK)); - instructions.push_back(new SimpleInstruction(RET)); - } - else if(brkscope != -1) - { - instructions.push_back(new LabelInstruction(compGenIttr+"_brk")); - auto _brk = scope-brkscope; - if(_brk > 0) - instructions.push_back(new ScopeEndTimesInstruction((uint32_t)_brk)); - - std::string myJmp = "__compGenBrk"; - myJmp.append(std::to_string(brkI)); - - instructions.push_back(new JumpStyleInstruction(JMP,myJmp)); - - } - - instructions.push_back(new LabelInstruction(compGenIttr)); - } - - } - else if(adv.nodeName == ScopelessClosureExpression && adv.nodes.size() == 2) - { - //()=>{} - //Name => {} - //(a,b) => {} - //it has two args - std::vector args; - GetFunctionArgs(args, adv.nodes[0]); - - std::vector fnInstructions; - size_t fnindex=this->chunks.size(); - this->chunks.resize(fnindex+1); - - auto body = adv.nodes[1]; - - if(std::holds_alternative(body)) - { - auto res = std::get(body); - if(res.nodeName == ScopeNode) - { - res.nodeName = NodeList; - } - body = res; - } - - - GenNode(fnInstructions,body,0,contscope == -2 ? -2 : -1,brkscope == -2 ? -2 : -1,-1,-1); - - this->chunks[fnindex] = std::pair,std::vector>(args, fnInstructions); - instructions.push_back(new ClosureInstruction((uint32_t)fnindex,false)); - } - else if(adv.nodeName == ClosureExpression && adv.nodes.size() == 2) - { - //()=>{} - //Name => {} - //(a,b) => {} - //it has two args - std::vector args; - GetFunctionArgs(args, adv.nodes[0]); - - std::vector fnInstructions; - size_t fnindex=this->chunks.size(); - this->chunks.resize(fnindex+1); - - auto body = adv.nodes[1]; - - if(std::holds_alternative(body)) - { - auto res = std::get(body); - if(res.nodeName == ScopeNode) - { - res.nodeName = NodeList; - } - body = res; - } - - - GenNode(fnInstructions,body,0,-1,-1,-1,-1); - - this->chunks[fnindex] = std::pair,std::vector>(args, fnInstructions); - instructions.push_back(new ClosureInstruction((uint32_t)fnindex)); - } - else if(adv.nodeName == FunctionStatement && adv.nodes.size() == 2 && std::holds_alternative(adv.nodes[0])) - { - //func NAME(ARGS) {} - //we need to disect NAME(ARGS) and {} - //then disect NAME and (ARGS) - auto fcall = std::get(adv.nodes[0]); - if(fcall.nodeName == FunctionCallExpression && adv.nodes.size() >= 1 && std::holds_alternative(fcall.nodes[0])) - { - SyntaxNode args = AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}); - if(fcall.nodes.size() == 2) - { - args = AdvancedSyntaxNode::Create(ParenthesesExpression,true,{fcall.nodes[1]}); - } - SyntaxNode closure = AdvancedSyntaxNode::Create(ClosureExpression,true,{args,adv.nodes[1]}); - - SyntaxNode assign = AdvancedSyntaxNode::Create(AssignExpression,false,{ - fcall.nodes[0], - closure - }); - GenNode(instructions,assign,scope,contscope,brkscope,contI,brkI); - - instructions.push_back(new SimpleInstruction(POP)); - } - } - - } - } - void CodeGen::GetFunctionArgs(std::vector& args, SyntaxNode n) - { - AdvancedSyntaxNode sn; - if(std::holds_alternative(n) && (sn=std::get(n)).nodeName == CommaExpression && sn.nodes.size()==2) - { - GetFunctionArgs(args,sn.nodes[0]); - GetFunctionArgs(args,sn.nodes[1]); - } - else - { - args.push_back(n); - } - } - void CodeGen::GetFunctionArgs(std::vector& name, SyntaxNode n) - { - if(std::holds_alternative(n)) - return; - - - if(std::holds_alternative(n)) - { - auto res = std::get(n); - if(res.nodeName == ParenthesesExpression) - { - for(auto n : res.nodes) - GetFunctionArgs(name,n); - } - else if(res.nodeName == CommaExpression && res.nodes.size() == 2) - { - GetFunctionArgs(name,res.nodes[0]); - GetFunctionArgs(name,res.nodes[1]); - } - else if(res.nodeName == GetVariableExpression && res.nodes.size() == 1) - { - if(std::holds_alternative(res.nodes[0])) - { - name.push_back(GetString(std::get(res.nodes[0]))); - } } } } - - void CodeGen::GetFunctionName(std::vector& name,SyntaxNode n) - { - if(std::holds_alternative(n)) - { - auto res = std::get(n); - if(res.nodeName == GetFieldExpression && res.nodes.size() == 2) - { - GetFunctionName(name, res.nodes[0]); - if(std::holds_alternative(res.nodes[1])) - { - name.push_back(GetString(std::get(res.nodes[1]))); - } - - } - else if(res.nodeName == GetVariableExpression && res.nodes.size() == 1) - { - if(std::holds_alternative(res.nodes[0])) - { - name.push_back(GetString(std::get(res.nodes[0]))); - } - } - } - } - - void CodeGen::GenRoot(SyntaxNode n) - { - this->id = 0; - std::vector rootInstructions; - size_t index=this->chunks.size(); - this->chunks.resize(index+1); - - if(std::holds_alternative(n)) - { - auto res = std::get(n); - - if(res.nodeName == NodeList) - { - for(auto item : res.nodes) - { - if(std::holds_alternative(item)) - { - std::string documentation = ""; - auto res2 = std::get(item); - - if(res2.nodeName == DocumentationStatement) - { - if(res2.nodes.size() == 2) - { - if(std::holds_alternative(res2.nodes[0]) && std::holds_alternative(res2.nodes[1])) - { - documentation = std::get(res2.nodes[0]); - auto j = std::get(res2.nodes[1]); - if(j.nodeName == FunctionStatement || j.nodeName == EnumerableStatement) { - res2 = j; - } - } - } - } - if(res2.nodeName == EnumerableStatement) - { - res2 = AdvancedSyntaxNode::Create(FunctionStatement,false,{ - res2.nodes[0], - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}), - AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), res2.nodes[1]}) - }) - }) - }); - } - if(res2.nodeName == FunctionStatement) - { - if(res2.nodes.size()==2) - { - auto fcall = res2.nodes[0]; - if(std::holds_alternative(fcall)) - { - auto fcalli = std::get(fcall); - if(fcalli.nodeName == FunctionCallExpression) - { - if(fcalli.nodes.size() >= 1) - { - std::vector functionName; - std::vector args; - GetFunctionName(functionName,fcalli.nodes[0]); - functionName.insert(functionName.begin(),{GetString(documentation)}); - if(fcalli.nodes.size()==2) - GetFunctionArgs(args, fcalli.nodes[1]); - - std::vector fnInstructions; - size_t fnindex=this->chunks.size(); - this->chunks.resize(fnindex+1); - - GenNode(fnInstructions,res2.nodes[1],0,-1,-1,-1,-1); - - this->funcs.push_back(std::pair,uint32_t>(functionName,(uint32_t)fnindex)); - - this->chunks[fnindex] = std::pair,std::vector>(args, fnInstructions); - } - else - { - GenNode(rootInstructions,item,0,-1,-1,-1,-1); - GenPop(rootInstructions,item); - } - } - else - { - GenNode(rootInstructions,item,0,-1,-1,-1,-1); - GenPop(rootInstructions,item); - } - } - } - else - { - GenNode(rootInstructions,item,0,-1,-1,-1,-1); - GenPop(rootInstructions,item); - } - } - else - { - GenNode(rootInstructions,item,0,-1,-1,-1,-1); - GenPop(rootInstructions,item); - } - - } - } - } - else - { - GenNode(rootInstructions,n,0,-1,-1,-1,-1); - GenPop(rootInstructions,n); - } - - } - else - { - GenNode(rootInstructions,n,0,-1,-1,-1,-1); - GenPop(rootInstructions,n); - } - - this->chunks[index] = std::pair,std::vector>({},rootInstructions); - } - - uint32_t CodeGen::NewId() - { - return id++; - } - - void CodeGen::GenPop(std::vector& instrs,SyntaxNode n) - { - if(std::holds_alternative(n)) - { - if(std::get(n).isExpression) - instrs.push_back(new SimpleInstruction(POP)); - } - else - { - instrs.push_back(new SimpleInstruction(POP)); - } - } - - ResourceBase::~ResourceBase() - { - - } - - bool ResourceBase::IsEqual(ResourceBase* base) - { - return this == base; - } - - ResourceFile::ResourceFile() - { - - } - ResourceFile::ResourceFile(std::string f) - { - this->file = f; - } - ResourceFile::~ResourceFile() - { - } - - uint32_t ResourceFile::GetLength(std::shared_ptr embedFS) - { - if(embedFS == nullptr) return 0; - if(strm != nullptr) return strm->GetLength(); - this->strm = embedFS->OpenFile(this->file,"rb"); - if(strm != nullptr) return this->strm->GetLength(); - - return 0; - } - bool ResourceFile::IsEqual(ResourceBase* base) - { - auto res = dynamic_cast(base); - if(res != nullptr) return this->file == res->file; - return ResourceBase::IsEqual(base); - } - void ResourceFile::Write(std::shared_ptr output) - { - if(this->strm != nullptr) - this->strm->CopyTo(output); - } - - uint32_t ResourceByteArray::GetLength(std::shared_ptr embedFS) - { - return (uint32_t)this->data.size(); - } - void ResourceByteArray::Write(std::shared_ptr output) - { - output->WriteBlock(this->data.data(),this->data.size()); - } - } +void CodeGen::GetFunctionArgs(std::vector &args, SyntaxNode n) { + AdvancedSyntaxNode sn; + if (std::holds_alternative(n) && + (sn = std::get(n)).nodeName == CommaExpression && + sn.nodes.size() == 2) { + GetFunctionArgs(args, sn.nodes[0]); + GetFunctionArgs(args, sn.nodes[1]); + } else { + args.push_back(n); + } +} +void CodeGen::GetFunctionArgs(std::vector &name, SyntaxNode n) { + if (std::holds_alternative(n)) + return; + + if (std::holds_alternative(n)) { + auto res = std::get(n); + if (res.nodeName == ParenthesesExpression) { + for (auto n : res.nodes) + GetFunctionArgs(name, n); + } else if (res.nodeName == CommaExpression && res.nodes.size() == 2) { + GetFunctionArgs(name, res.nodes[0]); + GetFunctionArgs(name, res.nodes[1]); + } else if (res.nodeName == GetVariableExpression && + res.nodes.size() == 1) { + if (std::holds_alternative(res.nodes[0])) { + name.push_back(GetString(std::get(res.nodes[0]))); + } + } + } +} + +void CodeGen::GetFunctionName(std::vector &name, SyntaxNode n) { + if (std::holds_alternative(n)) { + auto res = std::get(n); + if (res.nodeName == GetFieldExpression && res.nodes.size() == 2) { + GetFunctionName(name, res.nodes[0]); + if (std::holds_alternative(res.nodes[1])) { + name.push_back(GetString(std::get(res.nodes[1]))); + } + + } else if (res.nodeName == GetVariableExpression && + res.nodes.size() == 1) { + if (std::holds_alternative(res.nodes[0])) { + name.push_back(GetString(std::get(res.nodes[0]))); + } + } + } +} + +void CodeGen::GenRoot(SyntaxNode n) { + this->id = 0; + std::vector rootInstructions; + size_t index = this->chunks.size(); + this->chunks.resize(index + 1); + + if (std::holds_alternative(n)) { + auto res = std::get(n); + + if (res.nodeName == NodeList) { + for (auto item : res.nodes) { + if (std::holds_alternative(item)) { + std::string documentation = ""; + auto res2 = std::get(item); + + if (res2.nodeName == DocumentationStatement) { + if (res2.nodes.size() == 2) { + if (std::holds_alternative( + res2.nodes[0]) && + std::holds_alternative( + res2.nodes[1])) { + documentation = + std::get(res2.nodes[0]); + auto j = + std::get(res2.nodes[1]); + if (j.nodeName == FunctionStatement || + j.nodeName == EnumerableStatement) { + res2 = j; + } + } + } + } + if (res2.nodeName == EnumerableStatement) { + res2 = AdvancedSyntaxNode::Create( + FunctionStatement, false, + {res2.nodes[0], + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {"YieldEmumerable"}), + AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create( + ParenthesesExpression, true, {}), + res2.nodes[1]})})})}); + } + if (res2.nodeName == FunctionStatement) { + if (res2.nodes.size() == 2) { + auto fcall = res2.nodes[0]; + if (std::holds_alternative( + fcall)) { + auto fcalli = + std::get(fcall); + if (fcalli.nodeName == FunctionCallExpression) { + if (fcalli.nodes.size() >= 1) { + std::vector functionName; + std::vector args; + GetFunctionName(functionName, + fcalli.nodes[0]); + functionName.insert( + functionName.begin(), + {GetString(documentation)}); + if (fcalli.nodes.size() == 2) + GetFunctionArgs(args, + fcalli.nodes[1]); + + std::vector + fnInstructions; + size_t fnindex = this->chunks.size(); + this->chunks.resize(fnindex + 1); + + GenNode(fnInstructions, res2.nodes[1], + 0, -1, -1, -1, -1); + + this->funcs.push_back( + std::pair, + uint32_t>( + functionName, + (uint32_t)fnindex)); + + this->chunks[fnindex] = std::pair< + std::vector, + std::vector>( + args, fnInstructions); + } else { + GenNode(rootInstructions, item, 0, -1, + -1, -1, -1); + GenPop(rootInstructions, item); + } + } else { + GenNode(rootInstructions, item, 0, -1, -1, + -1, -1); + GenPop(rootInstructions, item); + } + } + } else { + GenNode(rootInstructions, item, 0, -1, -1, -1, -1); + GenPop(rootInstructions, item); + } + } else { + GenNode(rootInstructions, item, 0, -1, -1, -1, -1); + GenPop(rootInstructions, item); + } + } + } + } else { + GenNode(rootInstructions, n, 0, -1, -1, -1, -1); + GenPop(rootInstructions, n); + } + + } else { + GenNode(rootInstructions, n, 0, -1, -1, -1, -1); + GenPop(rootInstructions, n); + } + + this->chunks[index] = + std::pair, std::vector>( + {}, rootInstructions); +} + +uint32_t CodeGen::NewId() { return id++; } + +void CodeGen::GenPop(std::vector &instrs, SyntaxNode n) { + if (std::holds_alternative(n)) { + if (std::get(n).isExpression) + instrs.push_back(new SimpleInstruction(POP)); + } else { + instrs.push_back(new SimpleInstruction(POP)); + } +} + +ResourceBase::~ResourceBase() {} + +bool ResourceBase::IsEqual(ResourceBase *base) { return this == base; } + +ResourceFile::ResourceFile() {} +ResourceFile::ResourceFile(std::string f) { this->file = f; } +ResourceFile::~ResourceFile() {} + +uint32_t ResourceFile::GetLength( + std::shared_ptr embedFS) { + if (embedFS == nullptr) + return 0; + if (strm != nullptr) + return strm->GetLength(); + this->strm = embedFS->OpenFile(this->file, "rb"); + if (strm != nullptr) + return this->strm->GetLength(); + + return 0; +} +bool ResourceFile::IsEqual(ResourceBase *base) { + auto res = dynamic_cast(base); + if (res != nullptr) + return this->file == res->file; + return ResourceBase::IsEqual(base); +} +void ResourceFile::Write( + std::shared_ptr output) { + if (this->strm != nullptr) + this->strm->CopyTo(output); +} + +uint32_t ResourceByteArray::GetLength( + std::shared_ptr embedFS) { + return (uint32_t)this->data.size(); +} +void ResourceByteArray::Write( + std::shared_ptr output) { + output->WriteBlock(this->data.data(), this->data.size()); +} + +} // namespace Tesses::CrossLang diff --git a/src/compiler/lexer.cpp b/src/compiler/lexer.cpp index 38a3c22..1ae66e8 100644 --- a/src/compiler/lexer.cpp +++ b/src/compiler/lexer.cpp @@ -1,695 +1,580 @@ #include "CrossLang.hpp" #include #include -namespace Tesses::CrossLang -{ - std::string EscapeString(std::string text,bool quote) - { - std::string str={}; - if(quote) str.push_back('\"'); - for(auto item : text) - { - if(item == '\\' || item == '\"' || item == '\'') - { - str.push_back('\\'); - str.push_back(item); - } - else if(item == '\n') - { - str.push_back('\\'); - str.push_back('n'); - } - else if(item == '\r') - { - str.push_back('\\'); - str.push_back('r'); - } - else if(item == '\t') - { - str.push_back('\\'); - str.push_back('t'); - } - else if(item == '\f') - { - str.push_back('\\'); - str.push_back('f'); - } - else if(item == '\0') - { - str.push_back('\\'); - str.push_back('0'); - } - else if(item == '\b') - { - str.push_back('\\'); - str.push_back('b'); - } - else if(item == '\a') - { - str.push_back('\\'); - str.push_back('a'); - } - else if(item == '\v') - { - str.push_back('\\'); - str.push_back('v'); - } - else if(item == '\x1B') - { - str.push_back('\\'); - str.push_back('e'); - } - else if((uint8_t)item < 32 || (uint8_t)item > 126) - { - str.append("\\x"); - str.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex(((uint8_t)item >> 4)&0x0F)); - str.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex((uint8_t)item & 0x0F)); - } - else - { - str.push_back(item); - } - } - - if(quote) str.push_back('\"'); - return str; - } - - void LexTokenLineInfo::Subtract(size_t len) - { - this->offset -= len; - this->column -= len; - } - void LexTokenLineInfo::Add(int c) - { - this->offset++; - switch(c) - { - case ' ': - this->column++; - break; - case '\n': - this->column=1; - this->line++; - break; - case '\t': - this->column += 4; - break; - case '\r': - this->column++; - break; - default: - this->column++; - break; +namespace Tesses::CrossLang { +std::string EscapeString(std::string text, bool quote) { + std::string str = {}; + if (quote) + str.push_back('\"'); + for (auto item : text) { + if (item == '\\' || item == '\"' || item == '\'') { + str.push_back('\\'); + str.push_back(item); + } else if (item == '\n') { + str.push_back('\\'); + str.push_back('n'); + } else if (item == '\r') { + str.push_back('\\'); + str.push_back('r'); + } else if (item == '\t') { + str.push_back('\\'); + str.push_back('t'); + } else if (item == '\f') { + str.push_back('\\'); + str.push_back('f'); + } else if (item == '\0') { + str.push_back('\\'); + str.push_back('0'); + } else if (item == '\b') { + str.push_back('\\'); + str.push_back('b'); + } else if (item == '\a') { + str.push_back('\\'); + str.push_back('a'); + } else if (item == '\v') { + str.push_back('\\'); + str.push_back('v'); + } else if (item == '\x1B') { + str.push_back('\\'); + str.push_back('e'); + } else if ((uint8_t)item < 32 || (uint8_t)item > 126) { + str.append("\\x"); + str.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex( + ((uint8_t)item >> 4) & 0x0F)); + str.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex( + (uint8_t)item & 0x0F)); + } else { + str.push_back(item); } } - - int Lex(std::string filename, std::istream& strm, std::vector& tokens) - { - int _peeked=-1; - auto Read = [&_peeked,&strm]()->int { - if(_peeked > -1) - { - int _peek2 = _peeked; - _peeked=-1; - return _peek2; - } - uint8_t b; + if (quote) + str.push_back('\"'); + return str; +} - strm.read((char*)&b,1); - if(strm.eof()) return -1; - return b; - }; +void LexTokenLineInfo::Subtract(size_t len) { + this->offset -= len; + this->column -= len; +} +void LexTokenLineInfo::Add(int c) { + this->offset++; + switch (c) { + case ' ': + this->column++; + break; + case '\n': + this->column = 1; + this->line++; + break; + case '\t': + this->column += 4; + break; + case '\r': + this->column++; + break; + default: + this->column++; + break; + } +} - auto Peek = [&_peeked,Read]()->int { - if(_peeked > -1) return _peeked; - _peeked = Read(); +int Lex(std::string filename, std::istream &strm, + std::vector &tokens) { + int _peeked = -1; + + auto Read = [&_peeked, &strm]() -> int { + if (_peeked > -1) { + int _peek2 = _peeked; + _peeked = -1; + return _peek2; + } + uint8_t b; + + strm.read((char *)&b, 1); + if (strm.eof()) + return -1; + return b; + }; + + auto Peek = [&_peeked, Read]() -> int { + if (_peeked > -1) return _peeked; - }; + _peeked = Read(); + return _peeked; + }; - int read; - int peek; + int read; + int peek; - std::string buffer={}; + std::string buffer = {}; - LexTokenLineInfo lineInfo; + LexTokenLineInfo lineInfo; - lineInfo.filename = filename; - lineInfo.column = 1; - lineInfo.line = 1; - lineInfo.offset = 0; + lineInfo.filename = filename; + lineInfo.column = 1; + lineInfo.line = 1; + lineInfo.offset = 0; - std::string whiteSpaceCharsBefore=""; - - auto Flush = [&buffer,&tokens,&lineInfo,&whiteSpaceCharsBefore]() -> void { - if(!buffer.empty()) - { - LexToken token; - token.text = buffer; - token.whiteSpaceCharsBefore = whiteSpaceCharsBefore; - token.type = LexTokenType::Identifier; - token.lineInfo = lineInfo; - token.lineInfo.Subtract(buffer.size()); - tokens.push_back(token); - buffer.clear(); + std::string whiteSpaceCharsBefore = ""; - whiteSpaceCharsBefore=""; - } - }; - - auto Symbol = [&tokens,&lineInfo,&whiteSpaceCharsBefore](std::initializer_list chrs)-> void { + auto Flush = [&buffer, &tokens, &lineInfo, + &whiteSpaceCharsBefore]() -> void { + if (!buffer.empty()) { LexToken token; - - token.type = LexTokenType::Symbol; + token.text = buffer; + token.whiteSpaceCharsBefore = whiteSpaceCharsBefore; + token.type = LexTokenType::Identifier; token.lineInfo = lineInfo; - - token.whiteSpaceCharsBefore=whiteSpaceCharsBefore; - - token.text.reserve(chrs.size()); - - for(auto i : chrs) - token.text.push_back((char)i); - + token.lineInfo.Subtract(buffer.size()); tokens.push_back(token); + buffer.clear(); - whiteSpaceCharsBefore=""; - }; + whiteSpaceCharsBefore = ""; + } + }; - auto ReadChr = [&lineInfo, &strm, Read]() -> std::pair { - int read=Read(); - lineInfo.Add(read); + auto Symbol = [&tokens, &lineInfo, &whiteSpaceCharsBefore]( + std::initializer_list chrs) -> void { + LexToken token; - if(read == -1) - { - - return std::pair(-1,false); + token.type = LexTokenType::Symbol; + token.lineInfo = lineInfo; + + token.whiteSpaceCharsBefore = whiteSpaceCharsBefore; + + token.text.reserve(chrs.size()); + + for (auto i : chrs) + token.text.push_back((char)i); + + tokens.push_back(token); + + whiteSpaceCharsBefore = ""; + }; + + auto ReadChr = [&lineInfo, &strm, Read]() -> std::pair { + int read = Read(); + lineInfo.Add(read); + + if (read == -1) { + + return std::pair(-1, false); + } + + if (read == '\\') { + read = Read(); + lineInfo.Add(read); + if (read == -1) { + return std::pair(-1, true); + } else if (read == 'n') { + return std::pair('\n', true); + } else if (read == 'r') { + return std::pair('\r', true); + } else if (read == 'f') { + return std::pair('\f', true); + } else if (read == 'b') { + return std::pair('\b', true); + } else if (read == 'a') { + return std::pair('\a', true); + } else if (read == '0') { + return std::pair('\0', true); + } else if (read == 'v') { + return std::pair('\v', true); + } else if (read == 'e') { + return std::pair('\x1B', true); + } else if (read == 't') { + return std::pair('\t', true); + } else if (read == 'x') { + int r1 = Read(); + lineInfo.Add(r1); + if (r1 == -1) { + return std::pair(-1, true); + } + int r2 = Read(); + lineInfo.Add(r2); + if (r2 == -1) { + return std::pair(-1, true); + } + + uint8_t c = (uint8_t)std::stoi(std::string{(char)r1, (char)r2}, + nullptr, 16); + + return std::pair(c, true); + } else { + return std::pair(read, true); } - + } else { + return std::pair(read, false); + } + }; + auto ParseString = [&lineInfo, &strm, Read, ReadChr, + &tokens](bool interopolated) -> int { + auto lI = lineInfo; - if(read == '\\') - { - read = Read(); - lineInfo.Add(read); - if(read == -1) - { - return std::pair(-1,true); - } - else if(read == 'n') - { - return std::pair('\n',true); - } - else if(read == 'r') - { - return std::pair('\r',true); - } - else if(read == 'f') - { - return std::pair('\f',true); - } - else if(read == 'b') - { - return std::pair('\b',true); - } - else if(read == 'a') - { - return std::pair('\a',true); - } - else if(read == '0') - { - return std::pair('\0',true); - } - else if(read == 'v') - { - return std::pair('\v',true); - } - else if(read == 'e') - { - return std::pair('\x1B',true); - } - else if(read == 't') - { - return std::pair('\t',true); - } - else if(read == 'x') - { - int r1 = Read(); - lineInfo.Add(r1); - if(r1 == -1) - { - return std::pair(-1,true); - } - int r2 = Read(); - lineInfo.Add(r2); - if(r2 == -1) - { - return std::pair(-1,true); - } - - uint8_t c = (uint8_t)std::stoi(std::string{(char)r1,(char)r2},nullptr,16); + std::string b = {}; - return std::pair(c,true); - } - else - { - return std::pair(read,true); - } - } - else - { - return std::pair(read,false); - } - }; + auto rChr = ReadChr(); + lineInfo.Add(rChr.first); + while (rChr.first != '\"' || rChr.second) { + if (rChr.first == -1) + return lineInfo.line; - auto ParseString = [&lineInfo, &strm, Read, ReadChr,&tokens](bool interopolated)->int { - auto lI = lineInfo; - - std::string b={}; - - - auto rChr = ReadChr(); + b.push_back((char)rChr.first); + rChr = ReadChr(); lineInfo.Add(rChr.first); + } - while(rChr.first != '\"' || rChr.second) - { - if(rChr.first == -1) return lineInfo.line; + if (interopolated) { + int e = 0; + int escapeI = 0; + std::string b2 = {}; - b.push_back((char)rChr.first); - rChr = ReadChr(); - lineInfo.Add(rChr.first); - } - - if(interopolated) - { - int e = 0; - int escapeI = 0; - std::string b2 = {}; - - for(size_t i = 0; i< b.size();i++) - { - if(b[i] == '{') - { - if((i+1 < b.size() && b[i+1] != '{') || escapeI >= 1) - { - if(b2.size() > 0 && escapeI < 1) - { - if(e > 0) - { - LexToken _tkn; - _tkn.type = LexTokenType::Symbol; - _tkn.text = "+"; - _tkn.lineInfo = lI; - tokens.push_back(_tkn); - } - LexToken _tkn2; - _tkn2.type = LexTokenType::String; - _tkn2.text = b2; - _tkn2.lineInfo = lI; - tokens.push_back(_tkn2); - b2.clear(); - e++; - - } - escapeI++; - if(escapeI > 1) - { - b2.push_back('{'); + for (size_t i = 0; i < b.size(); i++) { + if (b[i] == '{') { + if ((i + 1 < b.size() && b[i + 1] != '{') || escapeI >= 1) { + if (b2.size() > 0 && escapeI < 1) { + if (e > 0) { + LexToken _tkn; + _tkn.type = LexTokenType::Symbol; + _tkn.text = "+"; + _tkn.lineInfo = lI; + tokens.push_back(_tkn); } + LexToken _tkn2; + _tkn2.type = LexTokenType::String; + _tkn2.text = b2; + _tkn2.lineInfo = lI; + tokens.push_back(_tkn2); + b2.clear(); + e++; } - else - { + escapeI++; + if (escapeI > 1) { b2.push_back('{'); - i++; - } - } - else if(b[i] == '}') - { - if(escapeI >= 1) - { - escapeI--; - if(b2.size() > 0 && escapeI == 0) - { - if(e > 0) - { - LexToken _tkn; - _tkn.type = LexTokenType::Symbol; - _tkn.text = "+"; - _tkn.lineInfo = lI; - tokens.push_back(_tkn); - } - LexToken _tkn2; - _tkn2.type = LexTokenType::Symbol; - _tkn2.text = "("; - _tkn2.lineInfo = lI; - tokens.push_back(_tkn2); - std::stringstream strm2(b2,std::ios_base::in | std::ios_base::binary); - int res = Lex("lexGen", strm2, tokens); - if(res != 0) return res; - - _tkn2.text = ")"; - tokens.push_back(_tkn2); - - _tkn2.text = "."; - tokens.push_back(_tkn2); - _tkn2.type = LexTokenType::Identifier; - _tkn2.text = "ToString"; - tokens.push_back(_tkn2); - _tkn2.type = LexTokenType::Symbol; - _tkn2.text = "("; - tokens.push_back(_tkn2); - _tkn2.text = ")"; - tokens.push_back(_tkn2); - b2.clear(); - e++; - } - if(escapeI >= 1) - { - b2.push_back('}'); - } } } else { - b2.push_back(b[i]); + b2.push_back('{'); + i++; } - } - if(b2.size() > 0) - { - if(escapeI > 0) - { - if(e > 0) - { - LexToken _tkn; - _tkn.type = LexTokenType::Symbol; - _tkn.text = "+"; - _tkn.lineInfo = lI; - tokens.push_back(_tkn); - } - LexToken _tkn2; - _tkn2.type = LexTokenType::Symbol; - _tkn2.text = "("; - _tkn2.lineInfo = lI; - tokens.push_back(_tkn2); - std::stringstream strm2(b2,std::ios_base::in | std::ios_base::binary); - int res = Lex("lexGen", strm2, tokens); - if(res != 0) return res; - - _tkn2.text = ")"; - tokens.push_back(_tkn2); + } else if (b[i] == '}') { + if (escapeI >= 1) { + escapeI--; + if (b2.size() > 0 && escapeI == 0) { + if (e > 0) { + LexToken _tkn; + _tkn.type = LexTokenType::Symbol; + _tkn.text = "+"; + _tkn.lineInfo = lI; + tokens.push_back(_tkn); + } + LexToken _tkn2; + _tkn2.type = LexTokenType::Symbol; + _tkn2.text = "("; + _tkn2.lineInfo = lI; + tokens.push_back(_tkn2); + std::stringstream strm2( + b2, std::ios_base::in | std::ios_base::binary); + int res = Lex("lexGen", strm2, tokens); + if (res != 0) + return res; - _tkn2.text = "."; - tokens.push_back(_tkn2); - _tkn2.type = LexTokenType::Identifier; - _tkn2.text = "ToString"; - tokens.push_back(_tkn2); - _tkn2.type = LexTokenType::Symbol; - _tkn2.text = "("; - tokens.push_back(_tkn2); - _tkn2.text = ")"; - tokens.push_back(_tkn2); - b2.clear(); - e++; - - } - else - { - if(e > 0) - { - LexToken _tkn; - _tkn.type = LexTokenType::Symbol; - _tkn.text = "+"; - _tkn.lineInfo = lI; - tokens.push_back(_tkn); + _tkn2.text = ")"; + tokens.push_back(_tkn2); + + _tkn2.text = "."; + tokens.push_back(_tkn2); + _tkn2.type = LexTokenType::Identifier; + _tkn2.text = "ToString"; + tokens.push_back(_tkn2); + _tkn2.type = LexTokenType::Symbol; + _tkn2.text = "("; + tokens.push_back(_tkn2); + _tkn2.text = ")"; + tokens.push_back(_tkn2); + b2.clear(); + e++; + } + if (escapeI >= 1) { + b2.push_back('}'); } - LexToken _tkn2; - _tkn2.type = LexTokenType::String; - _tkn2.text = b2; - _tkn2.lineInfo = lI; - tokens.push_back(_tkn2); - b2.clear(); - e++; } + } else { + b2.push_back(b[i]); } - } else { - LexToken _tkn2; - _tkn2.type = LexTokenType::String; - _tkn2.text = b; - _tkn2.lineInfo = lI; - tokens.push_back(_tkn2); - } - return 0; - }; - - while((read = Read()) != -1) - { - - peek = Peek(); - - - switch(read) - { - case '$': - if(peek == '\"') - { - Flush(); - lineInfo.Add(Read()); - int re = ParseString(true); - if(re != 0) return re; + if (b2.size() > 0) { + if (escapeI > 0) { + if (e > 0) { + LexToken _tkn; + _tkn.type = LexTokenType::Symbol; + _tkn.text = "+"; + _tkn.lineInfo = lI; + tokens.push_back(_tkn); } - else - { - buffer.push_back('$'); + LexToken _tkn2; + _tkn2.type = LexTokenType::Symbol; + _tkn2.text = "("; + _tkn2.lineInfo = lI; + tokens.push_back(_tkn2); + std::stringstream strm2(b2, std::ios_base::in | + std::ios_base::binary); + int res = Lex("lexGen", strm2, tokens); + if (res != 0) + return res; + + _tkn2.text = ")"; + tokens.push_back(_tkn2); + + _tkn2.text = "."; + tokens.push_back(_tkn2); + _tkn2.type = LexTokenType::Identifier; + _tkn2.text = "ToString"; + tokens.push_back(_tkn2); + _tkn2.type = LexTokenType::Symbol; + _tkn2.text = "("; + tokens.push_back(_tkn2); + _tkn2.text = ")"; + tokens.push_back(_tkn2); + b2.clear(); + e++; + + } else { + if (e > 0) { + LexToken _tkn; + _tkn.type = LexTokenType::Symbol; + _tkn.text = "+"; + _tkn.lineInfo = lI; + tokens.push_back(_tkn); } - break; - case '\"': - { - Flush(); - int re = ParseString(false); - if(re != 0) return re; + LexToken _tkn2; + _tkn2.type = LexTokenType::String; + _tkn2.text = b2; + _tkn2.lineInfo = lI; + tokens.push_back(_tkn2); + b2.clear(); + e++; } + } + } else { + LexToken _tkn2; + _tkn2.type = LexTokenType::String; + _tkn2.text = b; + _tkn2.lineInfo = lI; + tokens.push_back(_tkn2); + } + return 0; + }; + + while ((read = Read()) != -1) { + + peek = Peek(); + + switch (read) { + case '$': + if (peek == '\"') { + Flush(); + lineInfo.Add(Read()); + int re = ParseString(true); + if (re != 0) + return re; + } else { + buffer.push_back('$'); + } + break; + case '\"': { + Flush(); + int re = ParseString(false); + if (re != 0) + return re; + } break; + case '\'': { + Flush(); + auto res = ReadChr(); + if (res.first == -1) + return lineInfo.line; + int r = Read(); + lineInfo.Add(r); + if (r != '\'') + return lineInfo.line; + LexToken token; + token.text = {(char)(uint8_t)res.first}; + token.lineInfo = lineInfo; + token.type = LexTokenType::Char; + + tokens.push_back(token); + } break; + case '#': + Flush(); + while (true) { + int r = Read(); + lineInfo.Add(r); + if (r == '\n' || r == -1) break; - case '\'': - { - Flush(); - auto res = ReadChr(); - if(res.first == -1) return lineInfo.line; + } + break; + case '/': + if (peek == '/') { + Flush(); + while (true) { int r = Read(); lineInfo.Add(r); - if(r != '\'') - return lineInfo.line; - LexToken token; - token.text = {(char)(uint8_t)res.first}; - token.lineInfo = lineInfo; - token.type = LexTokenType::Char; - - tokens.push_back(token); + if (r == '\n' || r == -1) + break; } - break; - case '#': - Flush(); - while(true) - { - int r = Read(); + } else if (peek == '*') { + Flush(); + while (true) { + int r = Read(); + lineInfo.Add(r); + if (r == -1) { + return lineInfo.line; + } + if (r == '*') { + r = Read(); lineInfo.Add(r); - if(r == '\n' || r == -1) break; + if (r == -1) + return lineInfo.line; + if (r == '/') + break; } - break; - case '/': - if(peek == '/') - { - Flush(); - while(true) - { - int r = Read(); - lineInfo.Add(r); - if(r == '\n' || r == -1) break; + } + } else if (peek == '^') { + Flush(); + lineInfo.Add(Read()); + std::string str = {}; + while (true) { + int r = Read(); + lineInfo.Add(r); + if (r == -1) { + return lineInfo.line; + } + if (r == '^') { + r = Read(); + lineInfo.Add(r); + if (r == -1) + return lineInfo.line; + if (r == '^') { + str.push_back('^'); + continue; } + if (r == '/') + break; + str.push_back('^'); } - else if(peek == '*') - { - Flush(); - while(true) - { - int r = Read(); - lineInfo.Add(r); - if(r == -1) - { - return lineInfo.line; - } - if(r == '*') - { - r = Read(); - lineInfo.Add(r); - if(r == -1) - return lineInfo.line; - if(r == '/') - break; - } - } - } - else if(peek == '^') - { - Flush(); - lineInfo.Add(Read()); - std::string str={}; - while(true) - { - int r = Read(); - lineInfo.Add(r); - if(r == -1) - { - return lineInfo.line; - } - if(r == '^') - { - r = Read(); - lineInfo.Add(r); - if(r == -1) - return lineInfo.line; - if(r == '^') - { - str.push_back('^'); - continue; - } - if(r == '/') - break; - str.push_back('^'); - } - str.push_back((char)r); - } - LexToken token; - - token.type = LexTokenType::Documentation; - token.lineInfo = lineInfo; - token.text = str; - tokens.push_back(token); - } - else if(peek == '=') - { - Flush(); - lineInfo.Add(Read()); - Symbol({read,peek}); - } - else - { - Flush(); - Symbol({read}); - } - break; - case '<': - case '?': - if(peek == read) - { - Flush(); - lineInfo.Add(Read()); - int peek2=Peek(); - if(peek2 == '=') - { - lineInfo.Add(Read()); - Symbol({read,peek,peek2}); - } - else - { - Symbol({read,peek}); - } - } - else if(peek == '=') - { - Flush(); - lineInfo.Add(Read()); - Symbol({read,peek}); - } - else - { - Flush(); - Symbol({read}); - } - break; - case '+': - case '-': - case '|': - case '&': - if(peek == '=' || peek == read) - { - Flush(); - lineInfo.Add(Read()); - Symbol({read,peek}); - } - else - { - Flush(); - Symbol({read}); - } - break; - case '=': - if(peek == '>') - { - Flush(); - lineInfo.Add(Read()); - Symbol({read,peek}); - } - else if(peek == '=') - { - Flush(); - lineInfo.Add(Read()); - Symbol({read,peek}); - } - else - { - Flush(); - Symbol({read}); - } - break; - case '^': - case '~': - case '!': - case '>': - case '*': - case '%': - //* - //*= - if(peek == '=') - { - Flush(); - lineInfo.Add(Read()); - Symbol({read,peek}); - } - else - { - Flush(); - Symbol({read}); - } - break; - case '(': - case ')': - case '[': - case ']': - case '{': - case '}': - case '.': - case ':': - case ';': - case ',': - Flush(); - Symbol({read}); - break; - case '\n': - case '\t': - case '\r': - case ' ': - Flush(); - whiteSpaceCharsBefore += read; - - break; - default: - buffer.push_back((char)read); - break; + str.push_back((char)r); + } + LexToken token; + + token.type = LexTokenType::Documentation; + token.lineInfo = lineInfo; + token.text = str; + tokens.push_back(token); + } else if (peek == '=') { + Flush(); + lineInfo.Add(Read()); + Symbol({read, peek}); + } else { + Flush(); + Symbol({read}); } - - lineInfo.Add(read); + break; + case '<': + case '?': + if (peek == read) { + Flush(); + lineInfo.Add(Read()); + int peek2 = Peek(); + if (peek2 == '=') { + lineInfo.Add(Read()); + Symbol({read, peek, peek2}); + } else { + Symbol({read, peek}); + } + } else if (peek == '=') { + Flush(); + lineInfo.Add(Read()); + Symbol({read, peek}); + } else { + Flush(); + Symbol({read}); + } + break; + case '+': + case '-': + case '|': + case '&': + if (peek == '=' || peek == read) { + Flush(); + lineInfo.Add(Read()); + Symbol({read, peek}); + } else { + Flush(); + Symbol({read}); + } + break; + case '=': + if (peek == '>') { + Flush(); + lineInfo.Add(Read()); + Symbol({read, peek}); + } else if (peek == '=') { + Flush(); + lineInfo.Add(Read()); + Symbol({read, peek}); + } else { + Flush(); + Symbol({read}); + } + break; + case '^': + case '~': + case '!': + case '>': + case '*': + case '%': + //* + //*= + if (peek == '=') { + Flush(); + lineInfo.Add(Read()); + Symbol({read, peek}); + } else { + Flush(); + Symbol({read}); + } + break; + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case '.': + case ':': + case ';': + case ',': + Flush(); + Symbol({read}); + break; + case '\n': + case '\t': + case '\r': + case ' ': + Flush(); + whiteSpaceCharsBefore += read; + + break; + default: + buffer.push_back((char)read); + break; } - Flush(); - return 0; + + lineInfo.Add(read); } -} \ No newline at end of file + Flush(); + return 0; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/compiler/parser.cpp b/src/compiler/parser.cpp index ce400c0..f0a0853 100644 --- a/src/compiler/parser.cpp +++ b/src/compiler/parser.cpp @@ -1,1986 +1,2046 @@ #include "CrossLang.hpp" #include #include -namespace Tesses::CrossLang -{ - SyntaxNode TObject2SyntaxNode(TObject o) - { - if(std::holds_alternative(o)) return Undefined(); - if(std::holds_alternative(o)) return nullptr; - if(std::holds_alternative(o)) return std::get(o); - if(std::holds_alternative(o)) return std::get(o); - if(std::holds_alternative(o)) return std::get(o); - if(std::holds_alternative(o)) return std::get(o); - if(std::holds_alternative(o)) return std::get(o); - TList* list; - TDictionary* dict; - TByteArray* byteArray; - - - if(GetObjectHeap(o,list)) - { - if(list->Count() == 0) return AdvancedSyntaxNode::Create(ArrayExpression, true, {}); - - SyntaxNode node = TObject2SyntaxNode(list->Get(0)); - - for(int64_t i = 1; i < list->Count(); i++) - node = AdvancedSyntaxNode::Create(CommaExpression,true,{node,TObject2SyntaxNode(list->Get(i))}); - - return AdvancedSyntaxNode::Create(ArrayExpression, true, {node}); - } - if(GetObjectHeap(o,dict)) - { - bool has=false; - SyntaxNode node=nullptr; - - for(auto item : dict->items) - { - if(has) - { - node = AdvancedSyntaxNode::Create(CommaExpression,true, {node,AdvancedSyntaxNode::Create(AssignExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{TObject2SyntaxNode(item.first)}), - TObject2SyntaxNode(item.second) - })}); - } - else { - node = AdvancedSyntaxNode::Create(AssignExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{TObject2SyntaxNode(item.first)}), - TObject2SyntaxNode(item.second) - }); - has=true; - - } - } - - if(has) return AdvancedSyntaxNode::Create(DictionaryExpression,true,{node}); - return AdvancedSyntaxNode::Create(DictionaryExpression,true,{}); - } - if(GetObjectHeap(o,byteArray)) { - return byteArray->data; - } +namespace Tesses::CrossLang { +SyntaxNode TObject2SyntaxNode(TObject o) { + if (std::holds_alternative(o)) return Undefined(); + if (std::holds_alternative(o)) + return nullptr; + if (std::holds_alternative(o)) + return std::get(o); + if (std::holds_alternative(o)) + return std::get(o); + if (std::holds_alternative(o)) + return std::get(o); + if (std::holds_alternative(o)) + return std::get(o); + if (std::holds_alternative(o)) + return std::get(o); + TList *list; + TDictionary *dict; + TByteArray *byteArray; + + if (GetObjectHeap(o, list)) { + if (list->Count() == 0) + return AdvancedSyntaxNode::Create(ArrayExpression, true, {}); + + SyntaxNode node = TObject2SyntaxNode(list->Get(0)); + + for (int64_t i = 1; i < list->Count(); i++) + node = AdvancedSyntaxNode::Create( + CommaExpression, true, + {node, TObject2SyntaxNode(list->Get(i))}); + + return AdvancedSyntaxNode::Create(ArrayExpression, true, {node}); } + if (GetObjectHeap(o, dict)) { + bool has = false; + SyntaxNode node = nullptr; - - std::string LexTokenType_ToString(LexTokenType t) - { - switch(t) - { - case LexTokenType::Char: - return "char"; - case LexTokenType::Documentation: - return "documentation"; - case LexTokenType::Identifier: - return "identifier"; - case LexTokenType::String: - return "string"; - case LexTokenType::Symbol: - return "symbol"; + for (auto item : dict->items) { + if (has) { + node = AdvancedSyntaxNode::Create( + CommaExpression, true, + {node, AdvancedSyntaxNode::Create( + AssignExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {TObject2SyntaxNode(item.first)}), + TObject2SyntaxNode(item.second)})}); + } else { + node = AdvancedSyntaxNode::Create( + AssignExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {TObject2SyntaxNode(item.first)}), + TObject2SyntaxNode(item.second)}); + has = true; + } } - return ""; + if (has) + return AdvancedSyntaxNode::Create(DictionaryExpression, true, + {node}); + return AdvancedSyntaxNode::Create(DictionaryExpression, true, {}); } - bool Parser::IsAnyIdentifier(std::initializer_list idents, bool pop) - { - if(i < tokens.size()) - { - if(tokens[i].type != LexTokenType::Identifier) return false; - for(auto item : idents) - { - if(item == tokens[i].text) - { + if (GetObjectHeap(o, byteArray)) { + return byteArray->data; + } + return Undefined(); +} + +std::string LexTokenType_ToString(LexTokenType t) { + switch (t) { + case LexTokenType::Char: + return "char"; + case LexTokenType::Documentation: + return "documentation"; + case LexTokenType::Identifier: + return "identifier"; + case LexTokenType::String: + return "string"; + case LexTokenType::Symbol: + return "symbol"; + } + + return ""; +} +bool Parser::IsAnyIdentifier(std::initializer_list idents, + bool pop) { + if (i < tokens.size()) { + if (tokens[i].type != LexTokenType::Identifier) + return false; + for (auto item : idents) { + if (item == tokens[i].text) { + tkn = tokens[i]; + if (pop) + i++; + return true; + } + } + } + return false; +} +bool Parser::IsIdentifier(std::string txt, bool pop) { + if (i < tokens.size()) { + if (tokens[i].type != LexTokenType::Identifier) + return false; + if (tokens[i].text == txt) { + tkn = tokens[i]; + if (pop) + i++; + return true; + } + } + return false; +} + +bool Parser::IsAnySymbol(std::initializer_list idents, bool pop) { + + if (i < tokens.size()) { + if (tokens[i].type != LexTokenType::Symbol) + return false; + for (auto item : idents) { + if (item == ">") { + if (i + 1 < tokens.size()) { + if ((tokens[i + 1].text == ">" || + tokens[i + 1].text == ">=") && + tokens[i + 1].type == LexTokenType::Symbol) + continue; + } + if (item == tokens[i].text) { tkn = tokens[i]; - if(pop) i++; + if (pop) + i++; + return true; + } + } else if (item == ">>=") { + if (i + 1 < tokens.size()) { + if (tokens[i].text == ">" && tokens[i + 1].text == ">=" && + tokens[i].type == LexTokenType::Symbol && + tokens[i + 1].type == LexTokenType::Symbol) { + tkn = tokens[i]; + tkn.text = ">>="; + if (pop) + i += 2; + return true; + } + } + } else if (item == ">>") { + if (i + 1 < tokens.size()) { + if (tokens[i].text == ">" && tokens[i + 1].text == ">" && + tokens[i].type == LexTokenType::Symbol && + tokens[i + 1].type == LexTokenType::Symbol) { + tkn = tokens[i]; + tkn.text = ">>"; + if (pop) + i += 2; + return true; + } + } + + } else { + if (item == tokens[i].text) { + tkn = tokens[i]; + if (pop) + i++; return true; } } } - return false; } - bool Parser::IsIdentifier(std::string txt,bool pop) - { - if(i < tokens.size()) - { - if(tokens[i].type != LexTokenType::Identifier) return false; - if(tokens[i].text == txt) - { + return false; +} +bool Parser::IsSymbol(std::string txt, bool pop) { + if (i < tokens.size()) { + if (tokens[i].type != LexTokenType::Symbol) + return false; + if (txt == ">") { + if (i + 1 < tokens.size()) { + if ((tokens[i + 1].text == ">" || tokens[i + 1].text == ">=") && + tokens[i + 1].type == LexTokenType::Symbol) + return false; + } + if (txt == tokens[i].text) { tkn = tokens[i]; - if(pop) i++; + if (pop) + i++; return true; } - } - return false; - } - - bool Parser::IsAnySymbol(std::initializer_list idents, bool pop) - { - - if(i < tokens.size()) - { - if(tokens[i].type != LexTokenType::Symbol) return false; - for(auto item : idents) - { - if(item == ">") - { - if(i+1" || tokens[i+1].text == ">=") && tokens[i+1].type == LexTokenType::Symbol) continue; - } - if(item == tokens[i].text) - { - tkn = tokens[i]; - if(pop) i++; - return true; - } - } - else if(item == ">>=") - { - if(i+1 < tokens.size()) - { - if(tokens[i].text == ">" && tokens[i+1].text == ">=" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol) - { - tkn = tokens[i]; - tkn.text = ">>="; - if(pop) i+=2; - return true; - } - } - } - else if(item == ">>") - { - if(i+1 < tokens.size()) - { - if(tokens[i].text == ">" && tokens[i+1].text == ">" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol) - { - tkn = tokens[i]; - tkn.text = ">>"; - if(pop) i+=2; - return true; - } - } + } else if (txt == ">>=") { + if (i + 1 < tokens.size()) { - } - else { - if(item == tokens[i].text) - { - tkn = tokens[i]; - if(pop) i++; - return true; - } + if (tokens[i].text == ">" && tokens[i + 1].text == ">=" && + tokens[i].type == LexTokenType::Symbol && + tokens[i + 1].type == LexTokenType::Symbol) { + tkn = tokens[i]; + tkn.text = ">>="; + if (pop) + i += 2; + return true; } } - } - return false; - } - bool Parser::IsSymbol(std::string txt,bool pop) - { - if(i < tokens.size()) - { - if(tokens[i].type != LexTokenType::Symbol) return false; - if(txt == ">") - { - if(i+1" || tokens[i+1].text == ">=") && tokens[i+1].type == LexTokenType::Symbol) return false; - } - if(txt == tokens[i].text) - { - tkn = tokens[i]; - if(pop) i++; - return true; - } - } - else if(txt == ">>=") - { - if(i+1 < tokens.size()) - { - - if(tokens[i].text == ">" && tokens[i+1].text == ">=" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol) - { - tkn = tokens[i]; - tkn.text = ">>="; - if(pop) i+=2; - return true; - } + } else if (txt == ">>") { + if (i + 1 < tokens.size()) { + if (tokens[i].text == ">" && tokens[i + 1].text == ">" && + tokens[i].type == LexTokenType::Symbol && + tokens[i + 1].type == LexTokenType::Symbol) { + tkn = tokens[i]; + tkn.text = ">>"; + if (pop) + i += 2; + return true; } } - else if(txt == ">>") - { - if(i+1 < tokens.size()) - { - if(tokens[i].text == ">" && tokens[i+1].text == ">" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol) - { - tkn = tokens[i]; - tkn.text = ">>"; - if(pop) i+=2; - return true; - } - } - } - else if(tokens[i].text == txt) - { - tkn = tokens[i]; - if(pop) i++; - return true; - } - } - return false; - } - static std::string EnsureSafeVariable(LexToken token) - { - if(token.text.find("__compGen") == 0) - { - throw SyntaxException(token.lineInfo,"__compGen* is reserved for compilers (this error is enforced by the compiler)"); - } - return token.text; - } - void Parser::EnsureSymbol(std::string txt) - { - if(i < tokens.size()) - { - - if(tokens[i].type != LexTokenType::Symbol) - { - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the " + LexTokenType_ToString(tokens[i].type) + " \"" + tokens[i].text + "\" which is not a symbol at all."); - } - if(txt == ">") - { - if(i+1" || tokens[i+1].text == ">=") && tokens[i+1].type == LexTokenType::Symbol) - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + tokens[i+1].text + "\"");; - } - if(txt == tokens[i].text) - { - - tkn = tokens[i]; - i++; - return; - } - } - if(txt == ">>=") - { - if(i+1 < tokens.size()) - { - if(tokens[i].text == ">" && tokens[i+1].text == ">=" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol) - { - - tkn = tokens[i]; - i+=2; - return; - } - - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + tokens[i+1].text + "\""); - } - - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + "\""); - } - else if(txt == ">>") - { - if(i+1 < tokens.size()) - { - if(tokens[i].text == ">" && tokens[i+1].text == ">" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol) - { - - tkn = tokens[i]; - i+=2; - return; - } - - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + tokens[i+1].text + "\""); - } - - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + "\""); - } - else if(tokens[i].text != txt) - { - - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + "\""); - } + } else if (tokens[i].text == txt) { tkn = tokens[i]; - i++; - return; + if (pop) + i++; + return true; } - throw std::out_of_range("End of file"); } - Parser::Parser(std::vector tokens) : Parser(tokens,nullptr,nullptr) - { - + return false; +} +static std::string EnsureSafeVariable(LexToken token) { + if (token.text.find("__compGen") == 0) { + throw SyntaxException(token.lineInfo, + "__compGen* is reserved for compilers (this " + "error is enforced by the compiler)"); } - Parser::Parser(std::vector tokens, std::shared_ptr gc, TRootEnvironment* env) - { - this->i = 0; - this->tokens = tokens; - this->gc = gc; - this->env = env; - } - void Parser::ParseHtml(std::vector& nodes,std::string var) - { - if(this->IsSymbol("!",true)) - { - if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::Identifier) - { - std::string identifier = this->tokens[this->i++].text; + return token.text; +} +void Parser::EnsureSymbol(std::string txt) { + if (i < tokens.size()) { - if(identifier == "DOCTYPE") - { - if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::Identifier) - { - std::string doctype_secArg = this->tokens[this->i++].text; - std::string r = ""; + if (tokens[i].type != LexTokenType::Symbol) { + throw SyntaxException( + tokens[i].lineInfo, + "expected the symbol \"" + txt + "\" but got the " + + LexTokenType_ToString(tokens[i].type) + " \"" + + tokens[i].text + "\" which is not a symbol at all."); + } + if (txt == ">") { + if (i + 1 < tokens.size()) { + if ((tokens[i + 1].text == ">" || tokens[i + 1].text == ">=") && + tokens[i + 1].type == LexTokenType::Symbol) + throw SyntaxException(tokens[i].lineInfo, + "expected the symbol \"" + txt + + "\" but got the symbol \"" + + tokens[i].text + + tokens[i + 1].text + "\""); + ; + } + if (txt == tokens[i].text) { - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),r})})); - this->EnsureSymbol(">"); - if(this->IsSymbol("<")) - { - ParseHtml(nodes,var); - } - } - } - + tkn = tokens[i]; + i++; + return; } } - else - { - auto parseFn = [this,var](std::vector& nodes,std::string tagName)->void{ - while(this->i < this->tokens.size()) - { - if(this->IsSymbol("<",false)) - { - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),Tesses::Framework::Http::HttpUtils::HtmlEncode(this->tokens[i].whiteSpaceCharsBefore)})})); - - this->i++; + if (txt == ">>=") { + if (i + 1 < tokens.size()) { + if (tokens[i].text == ">" && tokens[i + 1].text == ">=" && + tokens[i].type == LexTokenType::Symbol && + tokens[i + 1].type == LexTokenType::Symbol) { - if(this->IsSymbol("/")) - { - if(this->IsIdentifier("if",false) && tagName == "if") - { - this->i-=2; - break; - } - if(!this->IsIdentifier(tagName)) - { - //error - - } - this->EnsureSymbol(">"); - if(tagName != "if" && tagName != "true" && tagName != "false" && tagName != "for" && tagName != "while" && tagName != "do" && tagName != "each" && tagName != "null" && tagName != "return") - { - std::string myVal = ""; - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); - } - break; - } - else - { - ParseHtml(nodes,var); - } - } - else if(this->IsSymbol("{",false)) - { - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),Tesses::Framework::Http::HttpUtils::HtmlEncode(this->tokens[i].whiteSpaceCharsBefore)})})); - this->i++; - - auto expr = ParseExpression(); - - this->EnsureSymbol("}"); - - //Net.Http.HtmlEncode(expr.ToString()) - - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{ - AdvancedSyntaxNode::Create(AddExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}) - , - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true, { - AdvancedSyntaxNode::Create(GetVariableExpression,true, { - "Net" - }), - "Http" - }), - "HtmlEncode" - }), - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - AdvancedSyntaxNode::Create(ParenthesesExpression,true,{expr}) - , - "ToString" - }) - }) - }) - - - }) - })); - - } - else - { - std::string str = ""; - while(this->i < this->tokens.size() && !this->IsSymbol("{",false) && !this->IsSymbol("<",false)) - { - str+=this->tokens[this->i].whiteSpaceCharsBefore + this->tokens[this->i].text; - this->i++; - } - - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),Tesses::Framework::Http::HttpUtils::HtmlEncode(str)})})); - - } - } - - }; - - if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::Identifier) - { - std::string tagName = this->tokens[this->i++].text; - - - if(tagName == "raw") - { - EnsureSymbol("("); - SyntaxNode expr = ParseExpression(); - - EnsureSymbol(")"); - EnsureSymbol(">"); - - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{ - AdvancedSyntaxNode::Create(AddExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}), - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - expr - , - "ToString" - }) - }) - }) - })); + tkn = tokens[i]; + i += 2; + return; } - else if(tagName == "plink") - { - EnsureSymbol("("); - SyntaxNode expr = ParseExpression(); - - EnsureSymbol(")"); - EnsureSymbol(">"); - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{ - AdvancedSyntaxNode::Create(AddExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}), - AdvancedSyntaxNode::Create(AddExpression,true,{ - "

", - AdvancedSyntaxNode::Create(AddExpression,true,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Net"}), - "Http" - }) - , - "HtmlP" - }), - expr - }) - , - "

" - }) - }) - }) - })); + throw SyntaxException(tokens[i].lineInfo, + "expected the symbol \"" + txt + + "\" but got the symbol \"" + + tokens[i].text + tokens[i + 1].text + + "\""); + } + + throw SyntaxException(tokens[i].lineInfo, + "expected the symbol \"" + txt + + "\" but got the symbol \"" + + tokens[i].text + "\""); + } else if (txt == ">>") { + if (i + 1 < tokens.size()) { + if (tokens[i].text == ">" && tokens[i + 1].text == ">" && + tokens[i].type == LexTokenType::Symbol && + tokens[i + 1].type == LexTokenType::Symbol) { + + tkn = tokens[i]; + i += 2; + return; } - else if(tagName == "if") - { - EnsureSymbol("("); - SyntaxNode expr = ParseExpression(); - SyntaxNode truth = nullptr; - SyntaxNode falsey = nullptr; - - EnsureSymbol(")"); - EnsureSymbol(">"); - while(this->IsSymbol("<")) - { - if(this->IsSymbol("/")) - { - if(!this->IsIdentifier("if")) { this->i -= 3;} - this->EnsureSymbol(">"); + throw SyntaxException(tokens[i].lineInfo, + "expected the symbol \"" + txt + + "\" but got the symbol \"" + + tokens[i].text + tokens[i + 1].text + + "\""); + } + + throw SyntaxException(tokens[i].lineInfo, + "expected the symbol \"" + txt + + "\" but got the symbol \"" + + tokens[i].text + "\""); + } else if (tokens[i].text != txt) { + + throw SyntaxException(tokens[i].lineInfo, + "expected the symbol \"" + txt + + "\" but got the symbol \"" + + tokens[i].text + "\""); + } + tkn = tokens[i]; + i++; + return; + } + throw std::out_of_range("End of file"); +} +Parser::Parser(std::vector tokens) + : Parser(tokens, nullptr, nullptr) {} +Parser::Parser(std::vector tokens, std::shared_ptr gc, + TRootEnvironment *env) { + this->i = 0; + this->tokens = tokens; + this->gc = gc; + this->env = env; +} +void Parser::ParseHtml(std::vector &nodes, std::string var) { + if (this->IsSymbol("!", true)) { + if (this->i < this->tokens.size() && + this->tokens[this->i].type == LexTokenType::Identifier) { + std::string identifier = this->tokens[this->i++].text; + + if (identifier == "DOCTYPE") { + if (this->i < this->tokens.size() && + this->tokens[this->i].type == LexTokenType::Identifier) { + std::string doctype_secArg = this->tokens[this->i++].text; + std::string r = ""; + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {var}), + r})})); + this->EnsureSymbol(">"); + if (this->IsSymbol("<")) { + ParseHtml(nodes, var); + } + } + } + } + } else { + auto parseFn = [this, var](std::vector &nodes, + std::string tagName) -> void { + while (this->i < this->tokens.size()) { + if (this->IsSymbol("<", false)) { + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {var}), + Tesses::Framework::Http::HttpUtils::HtmlEncode( + this->tokens[i].whiteSpaceCharsBefore)})})); + + this->i++; + + if (this->IsSymbol("/")) { + if (this->IsIdentifier("if", false) && + tagName == "if") { + this->i -= 2; break; } - else if(this->IsIdentifier("true")) - { - this->EnsureSymbol(">"); - - std::vector _nodes; - parseFn(_nodes,"true"); - truth = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes); - + if (!this->IsIdentifier(tagName)) { + // error } - else if(this->IsIdentifier("false")) - { - this->EnsureSymbol(">"); - std::vector _nodes; - parseFn(_nodes,"false"); - falsey = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes); + this->EnsureSymbol(">"); + if (tagName != "if" && tagName != "true" && + tagName != "false" && tagName != "for" && + tagName != "while" && tagName != "do" && + tagName != "each" && tagName != "null" && + tagName != "return") { + std::string myVal = ""; + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, {var}), + myVal})})); } + break; + } else { + ParseHtml(nodes, var); } - nodes.push_back(AdvancedSyntaxNode::Create(IfStatement,false,{expr,truth,falsey})); - } - else if(tagName == "null") - { - EnsureSymbol(">"); - std::vector _nodes; - parseFn(_nodes,"null"); - nodes.push_back(AdvancedSyntaxNode::Create(ScopeNode,false,_nodes)); - - } - else if(tagName == "return") - { - EnsureSymbol(">"); - std::vector _nodes; - parseFn(_nodes,"return"); - nodes.push_back(AdvancedSyntaxNode::Create(ScopeNode,false,_nodes)); - } - else if(tagName == "while") - { - - EnsureSymbol("("); - SyntaxNode expr = ParseExpression(); - SyntaxNode body = nullptr; - - EnsureSymbol(")"); - EnsureSymbol(">"); - - - std::vector _nodes; - parseFn(_nodes,"while"); - body = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes); - - nodes.push_back(AdvancedSyntaxNode::Create(WhileStatement,false,{expr,body})); - - } - else if(tagName == "do") - { - EnsureSymbol("("); - SyntaxNode expr = ParseExpression(); - SyntaxNode body = nullptr; - - EnsureSymbol(")"); - EnsureSymbol(">"); - - std::vector _nodes; - parseFn(_nodes,"do"); - body = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes); - - nodes.push_back(AdvancedSyntaxNode::Create(DoStatement,false,{expr,body})); - } - else if(tagName == "for") - { - SyntaxNode init = nullptr; - SyntaxNode cond = true; - SyntaxNode inc = nullptr; - SyntaxNode body = nullptr; - EnsureSymbol("("); - if(!IsSymbol(";",false)) - { - init = ParseExpression(); - } - EnsureSymbol(";"); - if(!IsSymbol(";",false)) - { - cond = ParseExpression(); - } - EnsureSymbol(";"); - if(!IsSymbol(")",false)) - { - inc = ParseExpression(); - } + } else if (this->IsSymbol("{", false)) { + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {var}), + Tesses::Framework::Http::HttpUtils::HtmlEncode( + this->tokens[i].whiteSpaceCharsBefore)})})); + this->i++; - EnsureSymbol(")"); - EnsureSymbol(">"); - std::vector _nodes; - parseFn(_nodes,"for"); - body = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes); - - nodes.push_back(AdvancedSyntaxNode::Create(ForStatement,false,{init,cond,inc,body})); + auto expr = ParseExpression(); + this->EnsureSymbol("}"); - } - else if(tagName == "each") - { - SyntaxNode item = nullptr; - EnsureSymbol("("); - SyntaxNode list = ParseExpression(); - SyntaxNode body = nullptr; - if(IsSymbol(":") || IsIdentifier("in")) - { - item = list; - list = ParseExpression(); + // Net.Http.HtmlEncode(expr.ToString()) + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {var}), + AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {"Net"}), + "Http"}), + "HtmlEncode"}), + AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + ParenthesesExpression, true, + {expr}), + "ToString"})})}) + + })})); + + } else { + std::string str = ""; + while (this->i < this->tokens.size() && + !this->IsSymbol("{", false) && + !this->IsSymbol("<", false)) { + str += this->tokens[this->i].whiteSpaceCharsBefore + + this->tokens[this->i].text; + this->i++; } - EnsureSymbol(")"); - EnsureSymbol(">"); - - std::vector _nodes; - parseFn(_nodes,"each"); - body = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes); - - nodes.push_back(AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body})); + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {var}), + Tesses::Framework::Http::HttpUtils::HtmlEncode( + str)})})); } - - else - { - std::string s = "<"; - s.append(tagName); + } + }; - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),s})})); + if (this->i < this->tokens.size() && + this->tokens[this->i].type == LexTokenType::Identifier) { + std::string tagName = this->tokens[this->i++].text; - while(!this->IsSymbol(">")) - { - //we need to get a name=value - if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::Identifier) - { - std::string key = ""; + if (tagName == "raw") { + EnsureSymbol("("); + SyntaxNode expr = ParseExpression(); - while(this->i < this->tokens.size()) - { - if(this->tokens[i].type == Identifier) - { + EnsureSymbol(")"); + EnsureSymbol(">"); + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, true, + {var}), + AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {expr, "ToString"})})})})); + } else if (tagName == "plink") { + EnsureSymbol("("); + SyntaxNode expr = ParseExpression(); + + EnsureSymbol(")"); + EnsureSymbol(">"); + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, true, + {var}), + AdvancedSyntaxNode::Create( + AddExpression, true, + {"

", + AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, + true, {"Net"}), + "Http"}), + "HtmlP"}), + expr}), + "

"})})})})); + } else if (tagName == "if") { + EnsureSymbol("("); + SyntaxNode expr = ParseExpression(); + SyntaxNode truth = nullptr; + SyntaxNode falsey = nullptr; + + EnsureSymbol(")"); + EnsureSymbol(">"); + + while (this->IsSymbol("<")) { + if (this->IsSymbol("/")) { + if (!this->IsIdentifier("if")) { + this->i -= 3; + } + this->EnsureSymbol(">"); + break; + } else if (this->IsIdentifier("true")) { + this->EnsureSymbol(">"); + + std::vector _nodes; + parseFn(_nodes, "true"); + truth = AdvancedSyntaxNode::Create(ScopeNode, false, + _nodes); + + } else if (this->IsIdentifier("false")) { + this->EnsureSymbol(">"); + std::vector _nodes; + parseFn(_nodes, "false"); + falsey = AdvancedSyntaxNode::Create(ScopeNode, false, + _nodes); + } + } + nodes.push_back(AdvancedSyntaxNode::Create( + IfStatement, false, {expr, truth, falsey})); + } else if (tagName == "null") { + EnsureSymbol(">"); + std::vector _nodes; + parseFn(_nodes, "null"); + nodes.push_back( + AdvancedSyntaxNode::Create(ScopeNode, false, _nodes)); + + } else if (tagName == "return") { + EnsureSymbol(">"); + std::vector _nodes; + parseFn(_nodes, "return"); + nodes.push_back( + AdvancedSyntaxNode::Create(ScopeNode, false, _nodes)); + } else if (tagName == "while") { + + EnsureSymbol("("); + SyntaxNode expr = ParseExpression(); + SyntaxNode body = nullptr; + + EnsureSymbol(")"); + EnsureSymbol(">"); + + std::vector _nodes; + parseFn(_nodes, "while"); + body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes); + + nodes.push_back(AdvancedSyntaxNode::Create( + WhileStatement, false, {expr, body})); + + } else if (tagName == "do") { + EnsureSymbol("("); + SyntaxNode expr = ParseExpression(); + SyntaxNode body = nullptr; + + EnsureSymbol(")"); + EnsureSymbol(">"); + + std::vector _nodes; + parseFn(_nodes, "do"); + body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes); + + nodes.push_back(AdvancedSyntaxNode::Create(DoStatement, false, + {expr, body})); + } else if (tagName == "for") { + SyntaxNode init = nullptr; + SyntaxNode cond = true; + SyntaxNode inc = nullptr; + SyntaxNode body = nullptr; + EnsureSymbol("("); + if (!IsSymbol(";", false)) { + init = ParseExpression(); + } + EnsureSymbol(";"); + if (!IsSymbol(";", false)) { + cond = ParseExpression(); + } + EnsureSymbol(";"); + if (!IsSymbol(")", false)) { + inc = ParseExpression(); + } + + EnsureSymbol(")"); + EnsureSymbol(">"); + std::vector _nodes; + parseFn(_nodes, "for"); + body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes); + + nodes.push_back(AdvancedSyntaxNode::Create( + ForStatement, false, {init, cond, inc, body})); + + } else if (tagName == "each") { + SyntaxNode item = nullptr; + EnsureSymbol("("); + SyntaxNode list = ParseExpression(); + SyntaxNode body = nullptr; + if (IsSymbol(":") || IsIdentifier("in")) { + item = list; + list = ParseExpression(); + } + EnsureSymbol(")"); + EnsureSymbol(">"); + + std::vector _nodes; + parseFn(_nodes, "each"); + body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes); + + nodes.push_back(AdvancedSyntaxNode::Create(EachStatement, false, + {item, list, body})); + } + + else { + std::string s = "<"; + s.append(tagName); + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, true, + {var}), + s})})); + + while (!this->IsSymbol(">")) { + // we need to get a name=value + if (this->i < this->tokens.size() && + this->tokens[this->i].type == + LexTokenType::Identifier) { + std::string key = ""; + + while (this->i < this->tokens.size()) { + if (this->tokens[i].type == Identifier) { + key += this->tokens[i].text; + i++; + } else if (this->tokens[i].type == Symbol) { + if (this->tokens[i].text == "-" || + this->tokens[i].text == ":" || + this->tokens[i].text == "--" || + tokens[i].text == ".") { key += this->tokens[i].text; i++; - } - else if(this->tokens[i].type == Symbol) - { - if(this->tokens[i].text == "-" || this->tokens[i].text == ":" || this->tokens[i].text == "--" || tokens[i].text == ".") - { - key += this->tokens[i].text; - i++; - } - else break; - } - else break; - } - - if(this->IsSymbol(">")) - { - std::string myVal = " " + key; - - - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); - + } else + break; + } else break; - } - else if(this->IsSymbol("=")) - { + } - std::string myVal = " " + key + "=\""; - SyntaxNode expr; - if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::String) - { - expr = this->tokens[this->i++].text; - - } - else { + if (this->IsSymbol(">")) { + std::string myVal = " " + key; + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, {var}), + myVal})})); + + break; + } else if (this->IsSymbol("=")) { + + std::string myVal = " " + key + "=\""; + SyntaxNode expr; + if (this->i < this->tokens.size() && + this->tokens[this->i].type == + LexTokenType::String) { + expr = this->tokens[this->i++].text; + + } else { EnsureSymbol("{"); - expr = ParseExpression(); + expr = ParseExpression(); EnsureSymbol("}"); - } - if(std::holds_alternative(expr)) - { - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{ - AdvancedSyntaxNode::Create(AddExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}), - AdvancedSyntaxNode::Create(AddExpression,true,{ - myVal, - AdvancedSyntaxNode::Create(AddExpression,true,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true, { - AdvancedSyntaxNode::Create(GetVariableExpression,true, { - "Net" - }), - "Http" - }), - "HtmlEncode" - }), - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{ - expr - , - "ToString" - }) - }) - }), - "\"", - }) - - }) - }) - })); - - - - } - else if(std::holds_alternative(expr)) - { - myVal += std::to_string(std::get(expr)) + "\""; - - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); - } - else if(std::holds_alternative(expr)) - { - myVal += std::to_string(std::get(expr)) + "\""; - - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); - } - else if(std::holds_alternative(expr)) - { - myVal += std::holds_alternative(expr) ? "true\"" : "false\""; - - - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); - } - else if(std::holds_alternative(expr)) - { - myVal += Tesses::Framework::Http::HttpUtils::HtmlEncode(std::get(expr)) + "\""; - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); - } - //key = value - - - } - else { + if (std::holds_alternative( + expr)) { + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {var}), + AdvancedSyntaxNode::Create( + AddExpression, true, + {myVal, + AdvancedSyntaxNode::Create( + AddExpression, true, + { + AdvancedSyntaxNode::Create( + FunctionCallExpression, + true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, + true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, + true, + {AdvancedSyntaxNode:: + Create( + GetVariableExpression, + true, + {"Net"}), + "Http"}), + "HtmlEncode"}), + AdvancedSyntaxNode::Create( + FunctionCallExpression, + true, + {AdvancedSyntaxNode:: + Create( + GetFieldExpression, + true, + {expr, + "ToStr" + "in" + "g"})})}), + "\"", + }) - std::string myVal = " " + key; - - - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); - + })})})); + + } else if (std::holds_alternative(expr)) { + myVal += + std::to_string(std::get(expr)) + + "\""; + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {var}), + myVal})})); + } else if (std::holds_alternative(expr)) { + myVal += + std::to_string(std::get(expr)) + + "\""; + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {var}), + myVal})})); + } else if (std::holds_alternative(expr)) { + myVal += std::holds_alternative(expr) + ? "true\"" + : "false\""; + + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {var}), + myVal})})); + } else if (std::holds_alternative( + expr)) { + myVal += Tesses::Framework::Http::HttpUtils:: + HtmlEncode( + std::get(expr)) + + "\""; + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, + {var}), + myVal})})); } - } - } + // key = value - nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),">"})})); - - if(tagName != "img" && tagName != "input" && tagName != "br" && tagName != "hr" && tagName != "link" && tagName != "meta") - { - parseFn(nodes,tagName); - } - } - } - } - } - uint32_t Parser::NewId() - { - return id++; - } - SyntaxNode Parser::ParseValue() - { - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto tkn2 = tokens[i]; - SyntaxNode node = nullptr; - if(tokens[i].type == LexTokenType::String) - { - node = tkn2.text; - i++; - - } - else if(tokens[i].type == LexTokenType::Char) - { - node = tkn2.text.empty() ? '\0' : tkn2.text.front(); - i++; - - } - else if(tokens[i].type == LexTokenType::Symbol && tokens[i].text == ".") - { - i++; - if(IsSymbol("[")) - { - node = AdvancedSyntaxNode::Create(GetVariableExpression,true,{ParseExpression()}); - EnsureSymbol("]"); - } - else - { - node = AdvancedSyntaxNode::Create(RelativePathExpression, true, {}); - - } - } - else if(IsSymbol("<")) - { - uint32_t htmlId = NewId(); - std::string compHtml = "__compGenHtml"; - compHtml.append(std::to_string(htmlId)); - std::vector syntaxNode = { - compHtml - }; - ParseHtml(syntaxNode,compHtml); - - return AdvancedSyntaxNode::Create(HtmlRootExpression,true,syntaxNode); - } - else if(IsSymbol("[")) - { - if(IsSymbol("]",false)) - node = AdvancedSyntaxNode::Create(ArrayExpression, true, {}); - else - node = AdvancedSyntaxNode::Create(ArrayExpression, true, {ParseExpression()}); - EnsureSymbol("]"); - } - else if(IsSymbol("{")) - { - if(IsSymbol("}",false)) - node = AdvancedSyntaxNode::Create(DictionaryExpression,true,{}); - else - node = AdvancedSyntaxNode::Create(DictionaryExpression,true,{ParseExpression()}); - - EnsureSymbol("}"); - } - else if(IsSymbol("(")) - { - if(IsSymbol(")",false)) - node = AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}); - else - node = AdvancedSyntaxNode::Create(ParenthesesExpression,true,{ParseExpression()}); - EnsureSymbol(")"); - } - else if(IsIdentifier("var")) - { - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto variable = tokens[i]; - + } else { - i++; - if(variable.type == LexTokenType::Symbol && variable.text == ".") - { - EnsureSymbol("["); - node = AdvancedSyntaxNode::Create(DeclareExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression ,true,{ParseExpression()}) - }); - EnsureSymbol("]"); - } - else if(variable.type == LexTokenType::Symbol && variable.text == "[") - { - node = AdvancedSyntaxNode::Create(DeclareExpression,true,{ - AdvancedSyntaxNode::Create(ArrayExpression ,true,{ParseExpression()}) - }); - EnsureSymbol("]"); - } - else if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\""); - else - { - node = AdvancedSyntaxNode::Create(DeclareExpression,true,{EnsureSafeVariable(variable)}); - } - } - else if(IsIdentifier("const")) - { - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto variable = tokens[i]; + std::string myVal = " " + key; - i++; - if(variable.type == LexTokenType::Symbol && variable.text == ".") - { - EnsureSymbol("["); - node = AdvancedSyntaxNode::Create(ConstExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression ,true,{ParseExpression()}) - }); - EnsureSymbol("]"); - } - else if(variable.type == LexTokenType::Symbol && variable.text == "[") - { - node = AdvancedSyntaxNode::Create(ConstExpression,true,{ - AdvancedSyntaxNode::Create(ArrayExpression ,true,{ParseExpression()}) - }); - EnsureSymbol("]"); - } - else if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\""); - else - { - node = AdvancedSyntaxNode::Create(ConstExpression,true,{EnsureSafeVariable(variable)}); - } - } - else if(IsIdentifier("comptime")) - { - SyntaxNode n = nullptr; - if(IsSymbol("{",false)) - { - n = ParseNode(); - if(std::holds_alternative(n)) - { - std::get(n).nodeName = NodeList; - } - } else { - n = AdvancedSyntaxNode::Create(ReturnStatement,false,{ParseExpression()}); - } - if(gc != nullptr && env != nullptr) - { - GCList ls(gc); - - CodeGen gen; - gen.GenRoot(n); - - auto ms = std::make_shared(true); - - gen.Save(ms); - - ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin); - - TFile* f = TFile::Create(ls); - f->Load(gc,ms); - - node = TObject2SyntaxNode(env->LoadFile(gc,f)); - } - else { - node = Undefined(); - } - - } - else if(IsIdentifier("operator")) - { - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto variable = tokens[i]; - i++; - if(variable.type != LexTokenType::Identifier && variable.type != LexTokenType::Symbol) throw SyntaxException(variable.lineInfo, "Expected an identifier or a symbol got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\""); - node = AdvancedSyntaxNode::Create(GetVariableExpression, true,{"operator"+variable.text}); - - } - else if(IsIdentifier("new")) - { - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto variable = tokens[i]; - i++; - if(variable.type != LexTokenType::Identifier && variable.type != LexTokenType::Symbol) throw SyntaxException(variable.lineInfo, "Expected an identifier or a symbol got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\""); - node = AdvancedSyntaxNode::Create(GetFieldExpression, true, {AdvancedSyntaxNode::Create(GetVariableExpression,true,{"New"}), variable.text}); - } - else if(IsIdentifier("embed")) - { - EnsureSymbol("("); - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto embed = tokens[i]; - i++; - if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\""); - EnsureSymbol(")"); - node = AdvancedSyntaxNode::Create(EmbedExpression, true,{embed.text}); - } - else if(IsIdentifier("embedstrm")) - { - EnsureSymbol("("); - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto embed = tokens[i]; - i++; - if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\""); - EnsureSymbol(")"); - node = AdvancedSyntaxNode::Create(EmbedStreamExpression, true,{embed.text}); - } - else if(IsIdentifier("embeddir")) - { - EnsureSymbol("("); - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto embed = tokens[i]; - i++; - if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\""); - EnsureSymbol(")"); - node = AdvancedSyntaxNode::Create(EmbedDirectoryExpression, true,{embed.text}); - } - else if(tokens[i].type == LexTokenType::Identifier) - { - auto token=tokens[i]; - - i++; - - bool hasNumber=true; - int64_t lngNum = 0; - - if(token.text.size() == 1 && token.text[0] == '0') - { - lngNum = 0; - } - else - if(token.text.size() > 0 && token.text[0] == '0') - { - if(token.text.size() > 1 && token.text[1] == 'x') - { - lngNum = std::stoll(token.text.substr(2),nullptr,16); - } - else if(token.text.size() > 1 && token.text[1] == 'b') - { - lngNum = std::stoll(token.text.substr(2),nullptr,2); - } - else - { - lngNum = std::stoll(token.text.substr(1),nullptr,8); - } - - } - else if(token.text.size() > 0 && token.text[0] >= '0' && token.text[0] <= '9') - { - lngNum=std::stoll(token.text,nullptr,10); - } - else - { - hasNumber = false; - } - - if(hasNumber && this->IsSymbol(".",false) && i+1 < tokens.size() && tokens[i+1].type == LexTokenType::Identifier) - { - std::string myToken = tokens[i+1].text; - if(myToken.size() > 0 && myToken[0] >= '0' && myToken[0] <= '9') - { - i+=2; - std::string myN = std::to_string(lngNum) + "." + myToken; - - double v = std::stod(myN,nullptr); - - node = v; - } - else - { - node = lngNum; - } - } - else if(hasNumber) - { - - node = lngNum; - } - - if(!hasNumber) - { - if(token.text == "true") - node = true; - else if(token.text == "false") - node = false; - else if(token.text == "null") - node = nullptr; - else if(token.text == "undefined") - node = Undefined(); - else { - node = AdvancedSyntaxNode::Create(GetVariableExpression,true,{EnsureSafeVariable(token)}); - } - } - } - - - if(IsSymbol("=>")) - { - if(IsSymbol("{",false)) - { - node = AdvancedSyntaxNode::Create(ClosureExpression,true,{node,ParseNode()}); - } - else - { - node = AdvancedSyntaxNode::Create(ClosureExpression,true,{node, AdvancedSyntaxNode::Create(ReturnStatement,false,{ParseExpression()})}); - } - } - while(IsAnySymbol({".","[","("})) - { - if(tkn.text == ".") - { - if(i>=tokens.size()) throw std::out_of_range("End of file"); - if(IsSymbol("[")) - { - - node = AdvancedSyntaxNode::Create(GetFieldExpression, true, {node, ParseExpression()}); - EnsureSymbol("]"); - continue; - } - if(tokens[i].type != LexTokenType::Identifier) throw std::runtime_error("Not an identifier (member)"); - std::string name = tokens[i].text; - if(name == "operator") - { - if(i >= tokens.size()) throw std::out_of_range("End of file"); - auto op = tokens[i]; - if(op.type != LexTokenType::Identifier && op.type != LexTokenType::Symbol) throw SyntaxException(op.lineInfo, "Expected an identifier or a symbol got a " + LexTokenType_ToString(op.type) + " \"" + op.text + "\""); - - name += tokens[i+1].text; - i++; - } - i++; - node = AdvancedSyntaxNode::Create(GetFieldExpression, true, {node, name}); - } - else if(tkn.text == "[") - { - node = AdvancedSyntaxNode::Create(GetArrayExpression,true,{node,ParseExpression()}); - EnsureSymbol("]"); - } - else if(tkn.text == "(") - { - if(IsSymbol(")",false)) - { - node = AdvancedSyntaxNode::Create(FunctionCallExpression,true,{node}); - } - else - { - node = AdvancedSyntaxNode::Create(FunctionCallExpression,true,{node,ParseExpression()}); - - } - EnsureSymbol(")"); - } - } - - - if(IsSymbol("++")) - { - node = AdvancedSyntaxNode::Create(PostfixIncrementExpression,true,{node}); - } - else if(IsSymbol("--")) - { - node = AdvancedSyntaxNode::Create(PostfixDecrementExpression,true,{node}); - } - - - return node; - } - SyntaxNode Parser::ParseUnary() - { - if(IsSymbol("-")) - { - return AdvancedSyntaxNode::Create(NegativeExpression,true,{ParseUnary()}); - } - else if(IsSymbol("!")) - { - return AdvancedSyntaxNode::Create(NotExpression,true,{ParseUnary()}); - } - else if(IsSymbol("~")) - { - return AdvancedSyntaxNode::Create(BitwiseNotExpression,true,{ParseUnary()}); - } - else if(IsSymbol("++")) - { - return AdvancedSyntaxNode::Create(PrefixIncrementExpression,true,{ParseUnary()}); - } - else if(IsSymbol("--")) - { - return AdvancedSyntaxNode::Create(PrefixDecrementExpression,true,{ParseUnary()}); - } - else if(IsIdentifier("await")) - { - return AdvancedSyntaxNode::Create(YieldStatement,true,{ParseValue()}); - } - else if(IsIdentifier("async")) - { - auto tkn = this->tkn; - auto v = ParseValue(); - if(std::holds_alternative(v)) - { - auto asn = std::get(v); - if(asn.nodeName != ClosureExpression) - throw SyntaxException(tkn.lineInfo,"async must be used only with a closure"); - if(asn.nodes.size() != 2) - throw SyntaxException(tkn.lineInfo,"invalid closure"); - - - - - return AdvancedSyntaxNode::Create(ClosureExpression,true,{ - asn.nodes[0], - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}), - AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), asn.nodes[1]}) - }) - }) - }); - } - else { - throw SyntaxException(tkn.lineInfo,"async must be used only with a closure, not a simple value"); - } - } - else if(IsIdentifier("enumerable")) - { - - auto tkn = this->tkn; - auto v = ParseValue(); - if(std::holds_alternative(v)) - { - auto asn = std::get(v); - if(asn.nodeName != ClosureExpression) - throw SyntaxException(tkn.lineInfo,"enumerable must be used only with a closure"); - if(asn.nodes.size() != 2) - throw SyntaxException(tkn.lineInfo,"invalid closure"); - - - - - return AdvancedSyntaxNode::Create(ClosureExpression,true,{ - asn.nodes[0], - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}), - AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), asn.nodes[1]}) - }) - }) - }); - } - else { - throw SyntaxException(tkn.lineInfo,"enumerable must be used only with a closure, not a simple value"); - } - } - else if(IsSymbol("/")) - { - if(this->i < this->tokens.size() && (this->tokens[this->i].type == LexTokenType::String || this->tokens[this->i].type == LexTokenType::Identifier)) - { - return AdvancedSyntaxNode::Create(DivideExpression,true,{ - AdvancedSyntaxNode::Create(RootPathExpression,true,{}), - ParseValue() - }); - } - else { - return AdvancedSyntaxNode::Create(RootPathExpression,true,{}); - } - } - - - return ParseValue(); - } - - SyntaxNode Parser::ParseFactor() - { - SyntaxNode expr = ParseUnary(); - while(IsAnySymbol({"*","/","%"},true)) - { - if(tkn.text == "*") - { - expr = AdvancedSyntaxNode::Create(TimesExpression, true, {expr,ParseUnary()}); - } - else if(tkn.text == "/") - { - expr = AdvancedSyntaxNode::Create(DivideExpression, true, {expr,ParseUnary()}); - } - else if(tkn.text == "%") - { - expr = AdvancedSyntaxNode::Create(ModExpression, true, {expr,ParseUnary()}); - } - } - return expr; - } - SyntaxNode Parser::ParseSum() - { - SyntaxNode expr = ParseFactor(); - while(IsAnySymbol({"+","-"},true)) - { - if(tkn.text == "+") - { - expr = AdvancedSyntaxNode::Create(AddExpression, true, {expr,ParseFactor()}); - } - else if(tkn.text == "-") - { - expr = AdvancedSyntaxNode::Create(SubExpression, true, {expr,ParseFactor()}); - } - } - return expr; - } - SyntaxNode Parser::ParseAssignment() - { - SyntaxNode node = ParseTernary(); - if(IsSymbol("=")) - { - return AdvancedSyntaxNode::Create(AssignExpression,true,{node,ParseAssignment()}); - } - else if(IsSymbol("+=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("-=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(SubExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("*=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(TimesExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("/=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(DivideExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("%=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(ModExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("<<=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(LeftShiftExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol(">>=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(RightShiftExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("|=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(BitwiseOrExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("&=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(BitwiseAndExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("^=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(XOrExpression,true,{ node,ParseAssignment()})}); - } - else if(IsSymbol("?\?=")) - { - return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(NullCoalescingExpression,true,{ node,ParseAssignment()})}); - } - return node; - } - bool Parser::CanEmit(LexTokenLineInfo& ifo) - { - if(!this->debug) return false; - bool same = ifo.line == this->lastLine && ifo.filename == this->lastFile; - this->lastFile = ifo.filename; - this->lastLine = ifo.line; - - return !same; - } - SyntaxNode Parser::ParseNode(bool isRoot) - { - std::string documentation=""; - if(i < tokens.size() && !isRoot && tokens[i].type == Documentation) - { - auto txt = tokens[i].text; - i++; - if(i < tokens.size() && tokens[i].text == "class" && tokens[i].type == LexTokenType::Identifier) - documentation = txt; - else - return AdvancedSyntaxNode::Create(DocumentationStatement,false,{txt,ParseNode()}); - } - if(IsSymbol("{") || isRoot) - { - AdvancedSyntaxNode aSN; - aSN.isExpression=false; - aSN.nodeName = isRoot ? NodeList : ScopeNode; - - while(i < tokens.size() && (isRoot || !IsSymbol("}",false))) - { - auto token = tokens[i]; - if(CanEmit(token.lineInfo)) aSN.nodes.push_back(AdvancedSyntaxNode::Create(LineNode,false, {(int64_t)tokens[i].lineInfo.line,tokens[i].lineInfo.filename})); - aSN.nodes.push_back(ParseNode()); - IsSymbol(";"); - } - - if(!isRoot) i++; - return aSN; - } - - if(IsIdentifier("if")) - { - EnsureSymbol("("); - SyntaxNode cond = ParseExpression(); - EnsureSymbol(")"); - SyntaxNode truthy = nullptr; - SyntaxNode falsey = nullptr; - - if(!IsIdentifier("else",false)) - { - truthy = ParseNode(); - } - - if(IsIdentifier("else")) - { - falsey = ParseNode(); - } - - return AdvancedSyntaxNode::Create(IfStatement, false, {cond, truthy,falsey}); - } - if(IsIdentifier("switch")) - { - EnsureSymbol("("); - SyntaxNode cond = ParseExpression(); - EnsureSymbol(")"); - - SyntaxNode body = ParseNode(); - - return AdvancedSyntaxNode::Create(SwitchStatement,false,{cond,body}); - } - if(IsIdentifier("while")) - { - EnsureSymbol("("); - SyntaxNode cond = ParseExpression(); - EnsureSymbol(")"); - - SyntaxNode body = nullptr; - if(!IsSymbol(";")) - { - body = ParseNode(); - } - return AdvancedSyntaxNode::Create(WhileStatement,false,{cond,body}); - } - if(IsIdentifier("using")) - { - EnsureSymbol("("); - SyntaxNode expr = ParseExpression(); - EnsureSymbol(")"); - - SyntaxNode body = nullptr; - if(!IsSymbol(";")) - { - body = ParseNode(); - } - - return AdvancedSyntaxNode::Create(UsingStatement, false, {expr,body}); - } - if(IsIdentifier("do")) - { - EnsureSymbol("("); - SyntaxNode cond = ParseExpression(); - EnsureSymbol(")"); - - SyntaxNode body = nullptr; - if(!IsSymbol(";")) - { - body = ParseNode(); - } - return AdvancedSyntaxNode::Create(DoStatement,false,{cond,body}); - } - if(IsIdentifier("for")) - { - SyntaxNode init = nullptr; - SyntaxNode cond = true; - SyntaxNode inc = nullptr; - SyntaxNode body = nullptr; - EnsureSymbol("("); - if(!IsSymbol(";",false)) - { - init = ParseExpression(); - } - EnsureSymbol(";"); - if(!IsSymbol(";",false)) - { - cond = ParseExpression(); - } - EnsureSymbol(";"); - if(!IsSymbol(")",false)) - { - inc = ParseExpression(); - } - - EnsureSymbol(")"); - - - if(!IsSymbol(";")) - { - body = ParseNode(); - } - return AdvancedSyntaxNode::Create(ForStatement,false,{init,cond,inc,body}); - } - if(IsIdentifier("each")) - { - SyntaxNode item = nullptr; - EnsureSymbol("("); - SyntaxNode list = ParseExpression(); - SyntaxNode body = nullptr; - if(IsSymbol(":") || IsIdentifier("in")) - { - item = list; - list = ParseExpression(); - } - EnsureSymbol(")"); - - if(!IsSymbol(";")) - { - body = ParseNode(); - } - if(std::holds_alternative(item)) - item = AdvancedSyntaxNode::Create(DeclareExpression,true, { - AdvancedSyntaxNode::Create(GetVariableExpression,true,{"item"}) - }); - - return AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body}); - } - if(IsIdentifier("class")) - { - if(i < tokens.size()) - { - std::vector name_and_methods={documentation}; - - auto name = ParseExpression(); - name_and_methods.push_back(name); - - if(IsSymbol(":",true)) - { - name_and_methods.push_back(ParseExpression()); - } - else - { - name_and_methods.push_back(AdvancedSyntaxNode::Create(GetVariableExpression,true,{"ClassObject"})); - } - EnsureSymbol("{"); - - - while(!IsSymbol("}",false) && i < tokens.size()) - { - documentation=""; - - - if(tokens[i].type == LexTokenType::Documentation) - { - documentation = tokens[i++].text; - } - - if(i < tokens.size()) - { - if(IsAnyIdentifier({"public","private","protected","static"})) - { - auto myTkn = tkn; - if(IsIdentifier("abstract")) - { - if(myTkn.text == "static") throw SyntaxException(myTkn.lineInfo,"Static abstract function doesn't make sense"); - auto nameAndArgs = ParseExpression(); - EnsureSymbol(";"); - - - name_and_methods.push_back(AdvancedSyntaxNode::Create(AbstractMethodStatement,false,{documentation,myTkn.text,nameAndArgs})); - - - - } - else if(i + 1 < tokens.size() && (tokens[i+1].text == "=" || tokens[i+1].text == ";") && tokens[i+1].type == LexTokenType::Symbol) - { - auto setter = ParseExpression(); - EnsureSymbol(";"); - - SyntaxNode field = AdvancedSyntaxNode::Create(FieldStatement,false,{ - documentation, - myTkn.text, - - setter - }); - - name_and_methods.push_back(field); - - } - else - { - if(IsIdentifier("async")) - { - auto nameAndArgs = ParseExpression(); - - if(IsSymbol("{",false)) - { - - - name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs, - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}), - AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()}) - }) - }) - })); - - } - else - { - auto v = ParseExpression(); - EnsureSymbol(";"); - - name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs, - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}), - AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), AdvancedSyntaxNode::Create(ReturnStatement,false,{v})}) - }) - }) - })); - - - } - } - else if(IsIdentifier("enumerable")) - { - auto nameAndArgs = ParseExpression(); - - if(IsSymbol("{",false)) - { - - - name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs, - AdvancedSyntaxNode::Create(ReturnStatement,false,{ - AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ - AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}), - AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()}) - }) - }) - })); - - } - else - { - throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"{\" on enumerable but got the symbol or other token \"" + tokens[i].text + "\""); - - - } - } - else { - auto nameAndArgs = ParseExpression(); - - if(IsSymbol("{",false)) - { - - - name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,ParseNode()})); - - } - else - { - auto v = ParseExpression(); - EnsureSymbol(";"); - name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,AdvancedSyntaxNode::Create(ReturnStatement,false,{v})})); - - } - } - - } - } - else { - throw SyntaxException(tokens[i].lineInfo, "Need public, private, protected or static"); + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, true, {var}), + myVal})})); } } } - EnsureSymbol("}"); - return AdvancedSyntaxNode::Create(ClassStatement, false, name_and_methods); - } - else throw std::out_of_range("End of file"); - } - - if(IsIdentifier("enumerable",false) && i+1= tokens.size() || tokens[i].type != LexTokenType::String) - { - std::cout << "WARN: meta is a conditional keyword,\nif you suffix it with a string, it will be assumed to be a metadata tag" << std::endl; - i--; - } - else { - std::string name = tokens[i++].text; - EnsureSymbol("{"); - auto expr = ParseExpression(); - + nodes.push_back(AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create( + AddExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, true, + {var}), + ">"})})); - EnsureSymbol("}"); - - return AdvancedSyntaxNode::Create(MetadataStatement,false,{name, AdvancedSyntaxNode::Create(DictionaryExpression,true,{expr})}); - } - - } - if(IsIdentifier("func")) - { - - auto nameAndArgs = ParseExpression(); - - if(IsSymbol("{",false)) - { - return AdvancedSyntaxNode::Create(FunctionStatement,false,{nameAndArgs,ParseNode()}); - } - else - { - auto v = ParseExpression(); - - EnsureSymbol(";"); - return AdvancedSyntaxNode::Create(FunctionStatement,false,{nameAndArgs,AdvancedSyntaxNode::Create(ReturnStatement,false,{v})}); + if (tagName != "img" && tagName != "input" && tagName != "br" && + tagName != "hr" && tagName != "link" && tagName != "meta") { + parseFn(nodes, tagName); + } } } - if(IsIdentifier("break")) - { - EnsureSymbol(";"); - return AdvancedSyntaxNode::Create(BreakStatement,false,{}); - } - if(IsIdentifier("continue")) - { - EnsureSymbol(";"); - return AdvancedSyntaxNode::Create(ContinueStatement,false,{}); - } - if(IsIdentifier("case")) - { - auto r = AdvancedSyntaxNode::Create(CaseStatement,false,{ParseExpression()}); - EnsureSymbol(":"); - return r; - } - if(IsIdentifier("default")) - { - auto r = AdvancedSyntaxNode::Create(DefaultStatement,false,{}); - EnsureSymbol(":"); - return r; - } - - if(IsIdentifier("return")) - { - SyntaxNode v = Undefined(); - if(!IsSymbol(";",true)) - { - v = ParseExpression(); - EnsureSymbol(";"); - } - return AdvancedSyntaxNode::Create(ReturnStatement,false,{v}); - } - if(IsSymbol("<",false) && this->i+1 < this->tokens.size() && this->tokens[this->i+1].type == LexTokenType::Identifier && this->tokens[this->i+1].text == "return") - { - this->i++; - uint32_t htmlId = NewId(); - std::string compHtml = "__compGenHtml"; - compHtml.append(std::to_string(htmlId)); - std::vector syntaxNode = { - compHtml - }; - ParseHtml(syntaxNode,compHtml); - - auto thytoken = AdvancedSyntaxNode::Create(HtmlRootExpression,true,syntaxNode); - - return AdvancedSyntaxNode::Create(ReturnStatement,false,{thytoken}); - - } - - if(IsIdentifier("yield")) - { - SyntaxNode v = Undefined(); - if(!IsSymbol(";",true)) - { - v = ParseExpression(); - EnsureSymbol(";"); - } - return AdvancedSyntaxNode::Create(YieldStatement,false,{v}); - } - if(IsIdentifier("throw")) - { - auto tkn2 = tkn; - - auto v = ParseExpression(); - EnsureSymbol(";"); - return AdvancedSyntaxNode::Create(ThrowStatement,false,{v,tkn2.lineInfo.filename,(int64_t)tkn2.lineInfo.line,(int64_t)tkn2.lineInfo.column,(int64_t)tkn.lineInfo.offset}); - } - if(IsIdentifier("breakpoint")) - { - auto tkn2 = tkn; - - auto v = ParseExpression(); - EnsureSymbol(";"); - return AdvancedSyntaxNode::Create(BreakpointStatement,false,{v,tkn2.lineInfo.filename,(int64_t)tkn2.lineInfo.line,(int64_t)tkn2.lineInfo.column,(int64_t)tkn.lineInfo.offset}); - } - if(IsIdentifier("try")) - { - auto tryBody = ParseNode(); - SyntaxNode catchNode = nullptr; - SyntaxNode catchEx = nullptr; - SyntaxNode finally=nullptr; - if(IsIdentifier("catch")) - { - EnsureSymbol("("); - catchEx = ParseExpression(); - EnsureSymbol(")"); - catchNode = ParseNode(); - } - if(IsIdentifier("finally")) - { - finally = ParseNode(); - } - - return AdvancedSyntaxNode::Create(TryStatement, false, {tryBody,catchNode,catchEx, finally}); - } - if(IsIdentifier("defer")) - { - if(IsSymbol("{",false)) - { - return AdvancedSyntaxNode::Create(DeferStatement,false,{ParseNode()}); - } - else - { - auto v = ParseExpression(); - - EnsureSymbol(";"); - return AdvancedSyntaxNode::Create(DeferStatement,false,{AdvancedSyntaxNode::Create(ReturnStatement,false,{v})}); - } - } - auto v = ParseExpression(); - EnsureSymbol(";"); - return v; - } - SyntaxNode Parser::ParseNullCoalescing() - { - SyntaxNode expr = ParseLOr(); - while(IsSymbol("?\?")) - { - expr = AdvancedSyntaxNode::Create(NullCoalescingExpression,true,{expr,ParseLOr()}); - } - return expr; - } - SyntaxNode Parser::ParseTernary() - { - SyntaxNode node = ParseNullCoalescing(); - if(IsSymbol("?")) - { - auto yes = ParseTernary(); - EnsureSymbol(":"); - auto no = ParseTernary(); - - return AdvancedSyntaxNode::Create(TernaryExpression,true,{node,yes,no}); - } - return node; - } - SyntaxNode Parser::ParseShift() - { - SyntaxNode expr = ParseSum(); - while(IsAnySymbol({"<<",">>"},true)) - { - if(tkn.text == "<<") - { - expr = AdvancedSyntaxNode::Create(LeftShiftExpression, true, {expr,ParseSum()}); - } - else if(tkn.text == ">>") - { - expr = AdvancedSyntaxNode::Create(RightShiftExpression, true, {expr,ParseSum()}); - } - } - return expr; - } - - SyntaxNode Parser::ParseRel() - { - SyntaxNode expr = ParseShift(); - while(IsAnySymbol({"<",">","<=",">="},true)) - { - if(tkn.text == "<") - { - expr = AdvancedSyntaxNode::Create(LessThanExpression, true, {expr,ParseShift()}); - } - else if(tkn.text == ">") - { - expr = AdvancedSyntaxNode::Create(GreaterThanExpression, true, {expr,ParseShift()}); - } - else if(tkn.text == "<=") - { - expr = AdvancedSyntaxNode::Create(LessThanEqualsExpression, true, {expr,ParseShift()}); - } - else if(tkn.text == ">=") - { - expr = AdvancedSyntaxNode::Create(GreaterThanEqualsExpression, true, {expr,ParseShift()}); - } - } - return expr; - } - SyntaxNode Parser::ParseEq() - { - SyntaxNode expr = ParseRel(); - while(IsAnySymbol({"==","!="},true)) - { - if(tkn.text == "==") - { - expr = AdvancedSyntaxNode::Create(EqualsExpression, true, {expr,ParseRel()}); - } - else if(tkn.text == "!=") - { - expr = AdvancedSyntaxNode::Create(NotEqualsExpression, true, {expr,ParseRel()}); - } - } - return expr; - } - SyntaxNode Parser::ParseBAnd() - { - SyntaxNode expr = ParseEq(); - while(IsSymbol("&")) - { - expr = AdvancedSyntaxNode::Create(BitwiseAndExpression,true,{expr,ParseEq()}); - } - return expr; - } - SyntaxNode Parser::ParseExpression() - { - SyntaxNode expr = ParseAssignment(); - while(IsSymbol(",")) - { - expr = AdvancedSyntaxNode::Create(CommaExpression,true,{expr,ParseAssignment()}); - } - return expr; - } - SyntaxNode Parser::ParseXOr() - { - SyntaxNode expr = ParseBAnd(); - while(IsSymbol("^")) - { - expr = AdvancedSyntaxNode::Create(XOrExpression,true,{expr,ParseBAnd()}); - } - return expr; - } - SyntaxNode Parser::ParseBOr() - { - SyntaxNode expr = ParseXOr(); - while(IsSymbol("|")) - { - expr = AdvancedSyntaxNode::Create(BitwiseOrExpression,true,{expr,ParseXOr()}); - } - return expr; - } - SyntaxNode Parser::ParseLAnd() - { - SyntaxNode expr = ParseBOr(); - while(IsSymbol("&&")) - { - expr = AdvancedSyntaxNode::Create(LogicalAndExpression,true,{expr,ParseBOr()}); - } - return expr; - } - SyntaxNode Parser::ParseLOr() - { - SyntaxNode expr = ParseLAnd(); - while(IsSymbol("||")) - { - expr = AdvancedSyntaxNode::Create(LogicalOrExpression,true,{expr,ParseLAnd()}); - } - return expr; } } +uint32_t Parser::NewId() { return id++; } +SyntaxNode Parser::ParseValue() { + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto tkn2 = tokens[i]; + SyntaxNode node = nullptr; + if (tokens[i].type == LexTokenType::String) { + node = tkn2.text; + i++; + + } else if (tokens[i].type == LexTokenType::Char) { + node = tkn2.text.empty() ? '\0' : tkn2.text.front(); + i++; + + } else if (tokens[i].type == LexTokenType::Symbol && + tokens[i].text == ".") { + i++; + if (IsSymbol("[")) { + node = AdvancedSyntaxNode::Create(GetVariableExpression, true, + {ParseExpression()}); + EnsureSymbol("]"); + } else { + node = AdvancedSyntaxNode::Create(RelativePathExpression, true, {}); + } + } else if (IsSymbol("<")) { + uint32_t htmlId = NewId(); + std::string compHtml = "__compGenHtml"; + compHtml.append(std::to_string(htmlId)); + std::vector syntaxNode = {compHtml}; + ParseHtml(syntaxNode, compHtml); + + return AdvancedSyntaxNode::Create(HtmlRootExpression, true, syntaxNode); + } else if (IsSymbol("[")) { + if (IsSymbol("]", false)) + node = AdvancedSyntaxNode::Create(ArrayExpression, true, {}); + else + node = AdvancedSyntaxNode::Create(ArrayExpression, true, + {ParseExpression()}); + EnsureSymbol("]"); + } else if (IsSymbol("{")) { + if (IsSymbol("}", false)) + node = AdvancedSyntaxNode::Create(DictionaryExpression, true, {}); + else + node = AdvancedSyntaxNode::Create(DictionaryExpression, true, + {ParseExpression()}); + + EnsureSymbol("}"); + } else if (IsSymbol("(")) { + if (IsSymbol(")", false)) + node = AdvancedSyntaxNode::Create(ParenthesesExpression, true, {}); + else + node = AdvancedSyntaxNode::Create(ParenthesesExpression, true, + {ParseExpression()}); + EnsureSymbol(")"); + } else if (IsIdentifier("var")) { + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto variable = tokens[i]; + + i++; + if (variable.type == LexTokenType::Symbol && variable.text == ".") { + EnsureSymbol("["); + node = AdvancedSyntaxNode::Create( + DeclareExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, true, + {ParseExpression()})}); + EnsureSymbol("]"); + } else if (variable.type == LexTokenType::Symbol && + variable.text == "[") { + node = AdvancedSyntaxNode::Create( + DeclareExpression, true, + {AdvancedSyntaxNode::Create(ArrayExpression, true, + {ParseExpression()})}); + EnsureSymbol("]"); + } else if (variable.type != LexTokenType::Identifier) + throw SyntaxException(variable.lineInfo, + "Expected an identifier got a " + + LexTokenType_ToString(variable.type) + + " \"" + variable.text + "\""); + else { + node = AdvancedSyntaxNode::Create(DeclareExpression, true, + {EnsureSafeVariable(variable)}); + } + } else if (IsIdentifier("const")) { + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto variable = tokens[i]; + + i++; + if (variable.type == LexTokenType::Symbol && variable.text == ".") { + EnsureSymbol("["); + node = AdvancedSyntaxNode::Create( + ConstExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, true, + {ParseExpression()})}); + EnsureSymbol("]"); + } else if (variable.type == LexTokenType::Symbol && + variable.text == "[") { + node = AdvancedSyntaxNode::Create( + ConstExpression, true, + {AdvancedSyntaxNode::Create(ArrayExpression, true, + {ParseExpression()})}); + EnsureSymbol("]"); + } else if (variable.type != LexTokenType::Identifier) + throw SyntaxException(variable.lineInfo, + "Expected an identifier got a " + + LexTokenType_ToString(variable.type) + + " \"" + variable.text + "\""); + else { + node = AdvancedSyntaxNode::Create(ConstExpression, true, + {EnsureSafeVariable(variable)}); + } + } else if (IsIdentifier("comptime")) { + SyntaxNode n = nullptr; + if (IsSymbol("{", false)) { + n = ParseNode(); + if (std::holds_alternative(n)) { + std::get(n).nodeName = NodeList; + } + } else { + n = AdvancedSyntaxNode::Create(ReturnStatement, false, + {ParseExpression()}); + } + if (gc != nullptr && env != nullptr) { + GCList ls(gc); + + CodeGen gen; + gen.GenRoot(n); + + auto ms = + std::make_shared( + true); + + gen.Save(ms); + + ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin); + + TFile *f = TFile::Create(ls); + f->Load(gc, ms); + + node = TObject2SyntaxNode(env->LoadFile(gc, f)); + } else { + node = Undefined(); + } + + } else if (IsIdentifier("operator")) { + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto variable = tokens[i]; + i++; + if (variable.type != LexTokenType::Identifier && + variable.type != LexTokenType::Symbol) + throw SyntaxException(variable.lineInfo, + "Expected an identifier or a symbol got a " + + LexTokenType_ToString(variable.type) + + " \"" + variable.text + "\""); + node = AdvancedSyntaxNode::Create(GetVariableExpression, true, + {"operator" + variable.text}); + + } else if (IsIdentifier("new")) { + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto variable = tokens[i]; + i++; + if (variable.type != LexTokenType::Identifier && + variable.type != LexTokenType::Symbol) + throw SyntaxException(variable.lineInfo, + "Expected an identifier or a symbol got a " + + LexTokenType_ToString(variable.type) + + " \"" + variable.text + "\""); + node = AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, true, {"New"}), + variable.text}); + } else if (IsIdentifier("embed")) { + EnsureSymbol("("); + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto embed = tokens[i]; + i++; + if (embed.type != LexTokenType::String) + throw SyntaxException(embed.lineInfo, + "Expected an string for embed got a " + + LexTokenType_ToString(embed.type) + + " \"" + embed.text + "\""); + EnsureSymbol(")"); + node = AdvancedSyntaxNode::Create(EmbedExpression, true, {embed.text}); + } else if (IsIdentifier("embedstrm")) { + EnsureSymbol("("); + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto embed = tokens[i]; + i++; + if (embed.type != LexTokenType::String) + throw SyntaxException(embed.lineInfo, + "Expected an string for embed got a " + + LexTokenType_ToString(embed.type) + + " \"" + embed.text + "\""); + EnsureSymbol(")"); + node = AdvancedSyntaxNode::Create(EmbedStreamExpression, true, + {embed.text}); + } else if (IsIdentifier("embeddir")) { + EnsureSymbol("("); + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto embed = tokens[i]; + i++; + if (embed.type != LexTokenType::String) + throw SyntaxException(embed.lineInfo, + "Expected an string for embed got a " + + LexTokenType_ToString(embed.type) + + " \"" + embed.text + "\""); + EnsureSymbol(")"); + node = AdvancedSyntaxNode::Create(EmbedDirectoryExpression, true, + {embed.text}); + } else if (IsIdentifier("private")) { + node = AdvancedSyntaxNode::Create(GetPrivateExpression, true, {}); + } else if (tokens[i].type == LexTokenType::Identifier) { + auto token = tokens[i]; + + i++; + + bool hasNumber = true; + int64_t lngNum = 0; + + if (token.text.size() == 1 && token.text[0] == '0') { + lngNum = 0; + } else if (token.text.size() > 0 && token.text[0] == '0') { + if (token.text.size() > 1 && token.text[1] == 'x') { + lngNum = std::stoll(token.text.substr(2), nullptr, 16); + } else if (token.text.size() > 1 && token.text[1] == 'b') { + lngNum = std::stoll(token.text.substr(2), nullptr, 2); + } else { + lngNum = std::stoll(token.text.substr(1), nullptr, 8); + } + + } else if (token.text.size() > 0 && token.text[0] >= '0' && + token.text[0] <= '9') { + lngNum = std::stoll(token.text, nullptr, 10); + } else { + hasNumber = false; + } + + if (hasNumber && this->IsSymbol(".", false) && i + 1 < tokens.size() && + tokens[i + 1].type == LexTokenType::Identifier) { + std::string myToken = tokens[i + 1].text; + if (myToken.size() > 0 && myToken[0] >= '0' && myToken[0] <= '9') { + i += 2; + std::string myN = std::to_string(lngNum) + "." + myToken; + + double v = std::stod(myN, nullptr); + + node = v; + } else { + node = lngNum; + } + } else if (hasNumber) { + + node = lngNum; + } + + if (!hasNumber) { + if (token.text == "true") + node = true; + else if (token.text == "false") + node = false; + else if (token.text == "null") + node = nullptr; + else if (token.text == "undefined") + node = Undefined(); + else { + node = AdvancedSyntaxNode::Create(GetVariableExpression, true, + {EnsureSafeVariable(token)}); + } + } + } + + if (IsSymbol("=>")) { + if (IsSymbol("{", false)) { + node = AdvancedSyntaxNode::Create(ClosureExpression, true, + {node, ParseNode()}); + } else { + node = AdvancedSyntaxNode::Create( + ClosureExpression, true, + {node, AdvancedSyntaxNode::Create(ReturnStatement, false, + {ParseExpression()})}); + } + } + while (IsAnySymbol({".", "[", "("})) { + if (tkn.text == ".") { + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + if (IsSymbol("[")) { + + node = AdvancedSyntaxNode::Create(GetFieldExpression, true, + {node, ParseExpression()}); + EnsureSymbol("]"); + continue; + } + if (tokens[i].type != LexTokenType::Identifier) + throw std::runtime_error("Not an identifier (member)"); + std::string name = tokens[i].text; + if (name == "operator") { + if (i >= tokens.size()) + throw std::out_of_range("End of file"); + auto op = tokens[i]; + if (op.type != LexTokenType::Identifier && + op.type != LexTokenType::Symbol) + throw SyntaxException( + op.lineInfo, + "Expected an identifier or a symbol got a " + + LexTokenType_ToString(op.type) + " \"" + op.text + + "\""); + + name += tokens[i + 1].text; + i++; + } + i++; + node = AdvancedSyntaxNode::Create(GetFieldExpression, true, + {node, name}); + } else if (tkn.text == "[") { + node = AdvancedSyntaxNode::Create(GetArrayExpression, true, + {node, ParseExpression()}); + EnsureSymbol("]"); + } else if (tkn.text == "(") { + if (IsSymbol(")", false)) { + node = AdvancedSyntaxNode::Create(FunctionCallExpression, true, + {node}); + } else { + node = AdvancedSyntaxNode::Create(FunctionCallExpression, true, + {node, ParseExpression()}); + } + EnsureSymbol(")"); + } + } + + if (IsSymbol("++")) { + node = AdvancedSyntaxNode::Create(PostfixIncrementExpression, true, + {node}); + } else if (IsSymbol("--")) { + node = AdvancedSyntaxNode::Create(PostfixDecrementExpression, true, + {node}); + } + + return node; +} +SyntaxNode Parser::ParseUnary() { + if (IsSymbol("-")) { + return AdvancedSyntaxNode::Create(NegativeExpression, true, + {ParseUnary()}); + } else if (IsSymbol("!")) { + return AdvancedSyntaxNode::Create(NotExpression, true, {ParseUnary()}); + } else if (IsSymbol("~")) { + return AdvancedSyntaxNode::Create(BitwiseNotExpression, true, + {ParseUnary()}); + } else if (IsSymbol("++")) { + return AdvancedSyntaxNode::Create(PrefixIncrementExpression, true, + {ParseUnary()}); + } else if (IsSymbol("--")) { + return AdvancedSyntaxNode::Create(PrefixDecrementExpression, true, + {ParseUnary()}); + } else if (IsIdentifier("await")) { + return AdvancedSyntaxNode::Create(YieldStatement, true, {ParseValue()}); + } else if (IsIdentifier("async")) { + auto tkn = this->tkn; + auto v = ParseValue(); + if (std::holds_alternative(v)) { + auto asn = std::get(v); + if (asn.nodeName != ClosureExpression) + throw SyntaxException(tkn.lineInfo, + "async must be used only with a closure"); + if (asn.nodes.size() != 2) + throw SyntaxException(tkn.lineInfo, "invalid closure"); + + return AdvancedSyntaxNode::Create( + ClosureExpression, true, + {asn.nodes[0], + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {"Task"}), + "AsyncClosure"}), + AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create(ParenthesesExpression, + true, {}), + asn.nodes[1]})})})}); + } else { + throw SyntaxException( + tkn.lineInfo, + "async must be used only with a closure, not a simple value"); + } + } else if (IsIdentifier("enumerable")) { + + auto tkn = this->tkn; + auto v = ParseValue(); + if (std::holds_alternative(v)) { + auto asn = std::get(v); + if (asn.nodeName != ClosureExpression) + throw SyntaxException( + tkn.lineInfo, + "enumerable must be used only with a closure"); + if (asn.nodes.size() != 2) + throw SyntaxException(tkn.lineInfo, "invalid closure"); + + return AdvancedSyntaxNode::Create( + ClosureExpression, true, + {asn.nodes[0], + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {"YieldEmumerable"}), + AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create(ParenthesesExpression, + true, {}), + asn.nodes[1]})})})}); + } else { + throw SyntaxException(tkn.lineInfo, + "enumerable must be used only with a " + "closure, not a simple value"); + } + } else if (IsSymbol("/")) { + if (this->i < this->tokens.size() && + (this->tokens[this->i].type == LexTokenType::String || + this->tokens[this->i].type == LexTokenType::Identifier)) { + return AdvancedSyntaxNode::Create( + DivideExpression, true, + {AdvancedSyntaxNode::Create(RootPathExpression, true, {}), + ParseValue()}); + } else { + return AdvancedSyntaxNode::Create(RootPathExpression, true, {}); + } + } + + return ParseValue(); +} + +SyntaxNode Parser::ParseFactor() { + SyntaxNode expr = ParseUnary(); + while (IsAnySymbol({"*", "/", "%"}, true)) { + if (tkn.text == "*") { + expr = AdvancedSyntaxNode::Create(TimesExpression, true, + {expr, ParseUnary()}); + } else if (tkn.text == "/") { + expr = AdvancedSyntaxNode::Create(DivideExpression, true, + {expr, ParseUnary()}); + } else if (tkn.text == "%") { + expr = AdvancedSyntaxNode::Create(ModExpression, true, + {expr, ParseUnary()}); + } + } + return expr; +} +SyntaxNode Parser::ParseSum() { + SyntaxNode expr = ParseFactor(); + while (IsAnySymbol({"+", "-"}, true)) { + if (tkn.text == "+") { + expr = AdvancedSyntaxNode::Create(AddExpression, true, + {expr, ParseFactor()}); + } else if (tkn.text == "-") { + expr = AdvancedSyntaxNode::Create(SubExpression, true, + {expr, ParseFactor()}); + } + } + return expr; +} +SyntaxNode Parser::ParseAssignment() { + SyntaxNode node = ParseTernary(); + if (IsSymbol("=")) { + return AdvancedSyntaxNode::Create(AssignExpression, true, + {node, ParseAssignment()}); + } else if (IsSymbol("+=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(AddExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("-=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(SubExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("*=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(TimesExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("/=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(DivideExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("%=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(ModExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("<<=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(LeftShiftExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol(">>=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(RightShiftExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("|=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(BitwiseOrExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("&=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(BitwiseAndExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("^=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(XOrExpression, true, + {node, ParseAssignment()})}); + } else if (IsSymbol("?\?=")) { + return AdvancedSyntaxNode::Create( + CompoundAssignExpression, true, + {AdvancedSyntaxNode::Create(NullCoalescingExpression, true, + {node, ParseAssignment()})}); + } + return node; +} +bool Parser::CanEmit(LexTokenLineInfo &ifo) { + if (!this->debug) + return false; + bool same = ifo.line == this->lastLine && ifo.filename == this->lastFile; + this->lastFile = ifo.filename; + this->lastLine = ifo.line; + + return !same; +} +SyntaxNode Parser::ParseNode(bool isRoot) { + std::string documentation = ""; + if (i < tokens.size() && !isRoot && tokens[i].type == Documentation) { + auto txt = tokens[i].text; + i++; + if (i < tokens.size() && tokens[i].text == "class" && + tokens[i].type == LexTokenType::Identifier) + documentation = txt; + else + return AdvancedSyntaxNode::Create(DocumentationStatement, false, + {txt, ParseNode()}); + } + if (IsSymbol("{") || isRoot) { + AdvancedSyntaxNode aSN; + aSN.isExpression = false; + aSN.nodeName = isRoot ? NodeList : ScopeNode; + + while (i < tokens.size() && (isRoot || !IsSymbol("}", false))) { + auto token = tokens[i]; + if (CanEmit(token.lineInfo)) + aSN.nodes.push_back(AdvancedSyntaxNode::Create( + LineNode, false, + {(int64_t)tokens[i].lineInfo.line, + tokens[i].lineInfo.filename})); + aSN.nodes.push_back(ParseNode()); + IsSymbol(";"); + } + + if (!isRoot) + i++; + return aSN; + } + + if (IsIdentifier("if")) { + EnsureSymbol("("); + SyntaxNode cond = ParseExpression(); + EnsureSymbol(")"); + SyntaxNode truthy = nullptr; + SyntaxNode falsey = nullptr; + + if (!IsIdentifier("else", false)) { + truthy = ParseNode(); + } + + if (IsIdentifier("else")) { + falsey = ParseNode(); + } + + return AdvancedSyntaxNode::Create(IfStatement, false, + {cond, truthy, falsey}); + } + if (IsIdentifier("switch")) { + EnsureSymbol("("); + SyntaxNode cond = ParseExpression(); + EnsureSymbol(")"); + + SyntaxNode body = ParseNode(); + + return AdvancedSyntaxNode::Create(SwitchStatement, false, {cond, body}); + } + if (IsIdentifier("while")) { + EnsureSymbol("("); + SyntaxNode cond = ParseExpression(); + EnsureSymbol(")"); + + SyntaxNode body = nullptr; + if (!IsSymbol(";")) { + body = ParseNode(); + } + return AdvancedSyntaxNode::Create(WhileStatement, false, {cond, body}); + } + if (IsIdentifier("using")) { + EnsureSymbol("("); + SyntaxNode expr = ParseExpression(); + EnsureSymbol(")"); + + SyntaxNode body = nullptr; + if (!IsSymbol(";")) { + body = ParseNode(); + } + + return AdvancedSyntaxNode::Create(UsingStatement, false, {expr, body}); + } + if (IsIdentifier("do")) { + EnsureSymbol("("); + SyntaxNode cond = ParseExpression(); + EnsureSymbol(")"); + + SyntaxNode body = nullptr; + if (!IsSymbol(";")) { + body = ParseNode(); + } + return AdvancedSyntaxNode::Create(DoStatement, false, {cond, body}); + } + if (IsIdentifier("for")) { + SyntaxNode init = nullptr; + SyntaxNode cond = true; + SyntaxNode inc = nullptr; + SyntaxNode body = nullptr; + EnsureSymbol("("); + if (!IsSymbol(";", false)) { + init = ParseExpression(); + } + EnsureSymbol(";"); + if (!IsSymbol(";", false)) { + cond = ParseExpression(); + } + EnsureSymbol(";"); + if (!IsSymbol(")", false)) { + inc = ParseExpression(); + } + + EnsureSymbol(")"); + + if (!IsSymbol(";")) { + body = ParseNode(); + } + return AdvancedSyntaxNode::Create(ForStatement, false, + {init, cond, inc, body}); + } + if (IsIdentifier("each")) { + SyntaxNode item = nullptr; + EnsureSymbol("("); + SyntaxNode list = ParseExpression(); + SyntaxNode body = nullptr; + if (IsSymbol(":") || IsIdentifier("in")) { + item = list; + list = ParseExpression(); + } + EnsureSymbol(")"); + + if (!IsSymbol(";")) { + body = ParseNode(); + } + if (std::holds_alternative(item)) + item = AdvancedSyntaxNode::Create( + DeclareExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, true, + {"item"})}); + + return AdvancedSyntaxNode::Create(EachStatement, false, + {item, list, body}); + } + if (IsIdentifier("class")) { + if (i < tokens.size()) { + std::vector name_and_methods = {documentation}; + + auto name = ParseExpression(); + name_and_methods.push_back(name); + + if (IsSymbol(":", true)) { + name_and_methods.push_back(ParseExpression()); + } else { + name_and_methods.push_back(AdvancedSyntaxNode::Create( + GetVariableExpression, true, {"ClassObject"})); + } + EnsureSymbol("{"); + + while (!IsSymbol("}", false) && i < tokens.size()) { + documentation = ""; + + if (tokens[i].type == LexTokenType::Documentation) { + documentation = tokens[i++].text; + } + + if (i < tokens.size()) { + if (IsAnyIdentifier( + {"public", "private", "protected", "static"})) { + auto myTkn = tkn; + if (IsIdentifier("abstract")) { + if (myTkn.text == "static") + throw SyntaxException( + myTkn.lineInfo, "Static abstract function " + "doesn't make sense"); + auto nameAndArgs = ParseExpression(); + EnsureSymbol(";"); + + name_and_methods.push_back( + AdvancedSyntaxNode::Create( + AbstractMethodStatement, false, + {documentation, myTkn.text, nameAndArgs})); + + } else if (i + 1 < tokens.size() && + (tokens[i + 1].text == "=" || + tokens[i + 1].text == ";") && + tokens[i + 1].type == LexTokenType::Symbol) { + auto setter = ParseExpression(); + EnsureSymbol(";"); + + SyntaxNode field = AdvancedSyntaxNode::Create( + FieldStatement, false, + {documentation, myTkn.text, + + setter}); + + name_and_methods.push_back(field); + + } else { + if (IsIdentifier("async")) { + auto nameAndArgs = ParseExpression(); + + if (IsSymbol("{", false)) { + + name_and_methods.push_back(AdvancedSyntaxNode::Create( + MethodStatement, false, + {documentation, myTkn.text, nameAndArgs, + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, + true, {"Task"}), + "AsyncClosure"}), + AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create( + ParenthesesExpression, + true, {}), + ParseNode()})})})})); + + } else { + auto v = ParseExpression(); + EnsureSymbol(";"); + + name_and_methods.push_back(AdvancedSyntaxNode::Create( + MethodStatement, false, + {documentation, myTkn.text, nameAndArgs, + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, + true, {"Task"}), + "AsyncClosure"}), + AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create( + ParenthesesExpression, + true, {}), + AdvancedSyntaxNode:: + Create( + ReturnStatement, + false, + {v})})})})})); + } + } else if (IsIdentifier("enumerable")) { + auto nameAndArgs = ParseExpression(); + + if (IsSymbol("{", false)) { + + name_and_methods.push_back( + AdvancedSyntaxNode::Create( + MethodStatement, false, + {documentation, myTkn.text, + nameAndArgs, + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, + true, + {AdvancedSyntaxNode::Create( + GetVariableExpression, + true, + {"YieldEmumerable"}), + AdvancedSyntaxNode::Create( + ClosureExpression, + true, + {AdvancedSyntaxNode:: + Create( + ParenthesesExpression, + true, {}), + ParseNode()})})})})); + + } else { + throw SyntaxException( + tokens[i].lineInfo, + "expected the symbol \"{\" on " + "enumerable but got the symbol or " + "other token \"" + + tokens[i].text + "\""); + } + } else { + auto nameAndArgs = ParseExpression(); + + if (IsSymbol("{", false)) { + + name_and_methods.push_back( + AdvancedSyntaxNode::Create( + MethodStatement, false, + {documentation, myTkn.text, + nameAndArgs, ParseNode()})); + + } else { + auto v = ParseExpression(); + EnsureSymbol(";"); + name_and_methods.push_back( + AdvancedSyntaxNode::Create( + MethodStatement, false, + {documentation, myTkn.text, + nameAndArgs, + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {v})})); + } + } + } + } else { + throw SyntaxException( + tokens[i].lineInfo, + "Need public, private, protected or static"); + } + } + } + EnsureSymbol("}"); + return AdvancedSyntaxNode::Create(ClassStatement, false, + name_and_methods); + } else + throw std::out_of_range("End of file"); + } + + if (IsIdentifier("enumerable", false) && i + 1 < tokens.size() && + tokens[i + 1].text == "func" && i + 1 < tokens.size() && + tokens[i + 1].type == LexTokenType::Identifier) { + i += 2; + auto nameAndArgs = ParseExpression(); + + if (IsSymbol("{", false)) { + return AdvancedSyntaxNode::Create( + FunctionStatement, false, + {nameAndArgs, + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {"YieldEmumerable"}), + AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create(ParenthesesExpression, + true, {}), + ParseNode()})})})}); + } else { + throw SyntaxException(tokens[i].lineInfo, + "expected the symbol \"{\" on enumerable but " + "got the symbol or other token \"" + + tokens[i].text + "\""); + } + } + if (IsIdentifier("async", false) && i + 1 < tokens.size() && + tokens[i + 1].text == "func" && + tokens[i + 1].type == LexTokenType::Identifier) { + i += 2; + // async func + auto nameAndArgs = ParseExpression(); + + if (IsSymbol("{", false)) { + return AdvancedSyntaxNode::Create( + FunctionStatement, false, + {nameAndArgs, + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {"Task"}), + "AsyncClosure"}), + AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create(ParenthesesExpression, + true, {}), + ParseNode()})})})}); + } else { + auto v = ParseExpression(); + + EnsureSymbol(";"); + return AdvancedSyntaxNode::Create( + FunctionStatement, false, + {nameAndArgs, + AdvancedSyntaxNode::Create( + ReturnStatement, false, + {AdvancedSyntaxNode::Create( + FunctionCallExpression, true, + {AdvancedSyntaxNode::Create( + GetFieldExpression, true, + {AdvancedSyntaxNode::Create(GetVariableExpression, + true, {"Task"}), + "AsyncClosure"}), + AdvancedSyntaxNode::Create( + ClosureExpression, true, + {AdvancedSyntaxNode::Create(ParenthesesExpression, + true, {}), + AdvancedSyntaxNode::Create(ReturnStatement, + false, {v})})})})}); + } + } + if (IsIdentifier("meta")) { + if (i >= tokens.size() || tokens[i].type != LexTokenType::String) { + std::cout + << "WARN: meta is a conditional keyword,\nif you suffix it " + "with a string, it will be assumed to be a metadata tag" + << std::endl; + i--; + } else { + std::string name = tokens[i++].text; + EnsureSymbol("{"); + auto expr = ParseExpression(); + + EnsureSymbol("}"); + + return AdvancedSyntaxNode::Create( + MetadataStatement, false, + {name, AdvancedSyntaxNode::Create(DictionaryExpression, true, + {expr})}); + } + } + if (IsIdentifier("func")) { + + auto nameAndArgs = ParseExpression(); + + if (IsSymbol("{", false)) { + return AdvancedSyntaxNode::Create(FunctionStatement, false, + {nameAndArgs, ParseNode()}); + } else { + auto v = ParseExpression(); + + EnsureSymbol(";"); + return AdvancedSyntaxNode::Create( + FunctionStatement, false, + {nameAndArgs, + AdvancedSyntaxNode::Create(ReturnStatement, false, {v})}); + } + } + if (IsIdentifier("break")) { + EnsureSymbol(";"); + return AdvancedSyntaxNode::Create(BreakStatement, false, {}); + } + if (IsIdentifier("continue")) { + EnsureSymbol(";"); + return AdvancedSyntaxNode::Create(ContinueStatement, false, {}); + } + if (IsIdentifier("case")) { + auto r = AdvancedSyntaxNode::Create(CaseStatement, false, + {ParseExpression()}); + EnsureSymbol(":"); + return r; + } + if (IsIdentifier("default")) { + auto r = AdvancedSyntaxNode::Create(DefaultStatement, false, {}); + EnsureSymbol(":"); + return r; + } + + if (IsIdentifier("return")) { + SyntaxNode v = Undefined(); + if (!IsSymbol(";", true)) { + v = ParseExpression(); + EnsureSymbol(";"); + } + return AdvancedSyntaxNode::Create(ReturnStatement, false, {v}); + } + if (IsSymbol("<", false) && this->i + 1 < this->tokens.size() && + this->tokens[this->i + 1].type == LexTokenType::Identifier && + this->tokens[this->i + 1].text == "return") { + this->i++; + uint32_t htmlId = NewId(); + std::string compHtml = "__compGenHtml"; + compHtml.append(std::to_string(htmlId)); + std::vector syntaxNode = {compHtml}; + ParseHtml(syntaxNode, compHtml); + + auto thytoken = + AdvancedSyntaxNode::Create(HtmlRootExpression, true, syntaxNode); + + return AdvancedSyntaxNode::Create(ReturnStatement, false, {thytoken}); + } + + if (IsIdentifier("yield")) { + SyntaxNode v = Undefined(); + if (!IsSymbol(";", true)) { + v = ParseExpression(); + EnsureSymbol(";"); + } + return AdvancedSyntaxNode::Create(YieldStatement, false, {v}); + } + if (IsIdentifier("throw")) { + auto tkn2 = tkn; + + auto v = ParseExpression(); + EnsureSymbol(";"); + return AdvancedSyntaxNode::Create( + ThrowStatement, false, + {v, tkn2.lineInfo.filename, (int64_t)tkn2.lineInfo.line, + (int64_t)tkn2.lineInfo.column, (int64_t)tkn.lineInfo.offset}); + } + if (IsIdentifier("breakpoint")) { + auto tkn2 = tkn; + + auto v = ParseExpression(); + EnsureSymbol(";"); + return AdvancedSyntaxNode::Create( + BreakpointStatement, false, + {v, tkn2.lineInfo.filename, (int64_t)tkn2.lineInfo.line, + (int64_t)tkn2.lineInfo.column, (int64_t)tkn.lineInfo.offset}); + } + if (IsIdentifier("try")) { + auto tryBody = ParseNode(); + SyntaxNode catchNode = nullptr; + SyntaxNode catchEx = nullptr; + SyntaxNode finally = nullptr; + if (IsIdentifier("catch")) { + EnsureSymbol("("); + catchEx = ParseExpression(); + EnsureSymbol(")"); + catchNode = ParseNode(); + } + if (IsIdentifier("finally")) { + finally = ParseNode(); + } + + return AdvancedSyntaxNode::Create( + TryStatement, false, {tryBody, catchNode, catchEx, finally}); + } + if (IsIdentifier("defer")) { + if (IsSymbol("{", false)) { + return AdvancedSyntaxNode::Create(DeferStatement, false, + {ParseNode()}); + } else { + auto v = ParseExpression(); + + EnsureSymbol(";"); + return AdvancedSyntaxNode::Create( + DeferStatement, false, + {AdvancedSyntaxNode::Create(ReturnStatement, false, {v})}); + } + } + auto v = ParseExpression(); + EnsureSymbol(";"); + return v; +} +SyntaxNode Parser::ParseNullCoalescing() { + SyntaxNode expr = ParseLOr(); + while (IsSymbol("?\?")) { + expr = AdvancedSyntaxNode::Create(NullCoalescingExpression, true, + {expr, ParseLOr()}); + } + return expr; +} +SyntaxNode Parser::ParseTernary() { + SyntaxNode node = ParseNullCoalescing(); + if (IsSymbol("?")) { + auto yes = ParseTernary(); + EnsureSymbol(":"); + auto no = ParseTernary(); + + return AdvancedSyntaxNode::Create(TernaryExpression, true, + {node, yes, no}); + } + return node; +} +SyntaxNode Parser::ParseShift() { + SyntaxNode expr = ParseSum(); + while (IsAnySymbol({"<<", ">>"}, true)) { + if (tkn.text == "<<") { + expr = AdvancedSyntaxNode::Create(LeftShiftExpression, true, + {expr, ParseSum()}); + } else if (tkn.text == ">>") { + expr = AdvancedSyntaxNode::Create(RightShiftExpression, true, + {expr, ParseSum()}); + } + } + return expr; +} + +SyntaxNode Parser::ParseRel() { + SyntaxNode expr = ParseShift(); + while (IsAnySymbol({"<", ">", "<=", ">="}, true)) { + if (tkn.text == "<") { + expr = AdvancedSyntaxNode::Create(LessThanExpression, true, + {expr, ParseShift()}); + } else if (tkn.text == ">") { + expr = AdvancedSyntaxNode::Create(GreaterThanExpression, true, + {expr, ParseShift()}); + } else if (tkn.text == "<=") { + expr = AdvancedSyntaxNode::Create(LessThanEqualsExpression, true, + {expr, ParseShift()}); + } else if (tkn.text == ">=") { + expr = AdvancedSyntaxNode::Create(GreaterThanEqualsExpression, true, + {expr, ParseShift()}); + } + } + return expr; +} +SyntaxNode Parser::ParseEq() { + SyntaxNode expr = ParseRel(); + while (IsAnySymbol({"==", "!="}, true)) { + if (tkn.text == "==") { + expr = AdvancedSyntaxNode::Create(EqualsExpression, true, + {expr, ParseRel()}); + } else if (tkn.text == "!=") { + expr = AdvancedSyntaxNode::Create(NotEqualsExpression, true, + {expr, ParseRel()}); + } + } + return expr; +} +SyntaxNode Parser::ParseBAnd() { + SyntaxNode expr = ParseEq(); + while (IsSymbol("&")) { + expr = AdvancedSyntaxNode::Create(BitwiseAndExpression, true, + {expr, ParseEq()}); + } + return expr; +} +SyntaxNode Parser::ParseExpression() { + SyntaxNode expr = ParseAssignment(); + while (IsSymbol(",")) { + expr = AdvancedSyntaxNode::Create(CommaExpression, true, + {expr, ParseAssignment()}); + } + return expr; +} +SyntaxNode Parser::ParseXOr() { + SyntaxNode expr = ParseBAnd(); + while (IsSymbol("^")) { + expr = AdvancedSyntaxNode::Create(XOrExpression, true, + {expr, ParseBAnd()}); + } + return expr; +} +SyntaxNode Parser::ParseBOr() { + SyntaxNode expr = ParseXOr(); + while (IsSymbol("|")) { + expr = AdvancedSyntaxNode::Create(BitwiseOrExpression, true, + {expr, ParseXOr()}); + } + return expr; +} +SyntaxNode Parser::ParseLAnd() { + SyntaxNode expr = ParseBOr(); + while (IsSymbol("&&")) { + expr = AdvancedSyntaxNode::Create(LogicalAndExpression, true, + {expr, ParseBOr()}); + } + return expr; +} +SyntaxNode Parser::ParseLOr() { + SyntaxNode expr = ParseLAnd(); + while (IsSymbol("||")) { + expr = AdvancedSyntaxNode::Create(LogicalOrExpression, true, + {expr, ParseLAnd()}); + } + return expr; +} +} // namespace Tesses::CrossLang diff --git a/src/crossasmcli.cpp b/src/crossasmcli.cpp deleted file mode 100644 index 4100c22..0000000 --- a/src/crossasmcli.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "CrossLang.hpp" - -int main(int argc, char** argv) -{ - using namespace Tesses::Framework; - using namespace Tesses::Framework::Streams; - using namespace Tesses::Framework::Filesystem; - using namespace Tesses::CrossLang; - TF_Init(); - if(argc > 1 && strcmp(argv[1],"--help")) - { - std::cout << "Run this command in directory you want to assemble (with the crossasm.json)" << std::endl; - return 0; - } - auto curdir = VFSPath::GetAbsoluteCurrentDirectory(); - auto sdfs=std::make_shared(LocalFS,curdir); - auto path = Assemble(sdfs); - path.relative = true; - std::cout << "Output: " << (curdir / path).ToString() << std::endl; - - return 0; -} \ No newline at end of file diff --git a/src/crossdisasmcli.cpp b/src/crossdisasmcli.cpp deleted file mode 100644 index f121c80..0000000 --- a/src/crossdisasmcli.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "CrossLang.hpp" - -void help(char* program) -{ - std::cout << "USAGE: " << program << " [flags] FILE.CRVM" << std::endl; - std::cout << "USAGE: " << program << " [flags] FILE.CRVM DIR" << std::endl; - std::cout << "Flags:" << std::endl; - std::cout << "--no-json\tNo json" << std::endl; - std::cout << "--no-resources\nNo resources" << std::endl; - - exit(0); -} -int main(int argc, char** argv) -{ - - using namespace Tesses::Framework; - using namespace Tesses::Framework::Streams; - using namespace Tesses::Framework::Filesystem; - using namespace Tesses::CrossLang; - TF_Init(); - - std::string file; - Tesses::Framework::Filesystem::VFSPath path = VFSPath::GetAbsoluteCurrentDirectory(); - int curPos = 0; - bool json=true; - bool resources = true; - for(int i = 1; i < argc; i++) - { - if(strcmp(argv[i],"--no-json") == 0) - { - json = false; - } - else if(strcmp(argv[i],"--no-resources") == 0) - { - resources = false; - } - else if(strcmp(argv[i],"--help") == 0) - { - help(argv[0]); - } - else { - if(curPos == 0) - { - file = argv[i]; - curPos++; - } - else if(curPos == 1) - { - path = LocalFS->SystemToVFSPath(argv[i]); - } - } - } - if(file.empty()) - { - help(argv[0]); - } - auto strm = LocalFS->OpenFile(file,"rb"); - auto sdir = std::make_shared(LocalFS,path); - if(strm->CanRead()) - Disassemble(strm, sdir,json,resources); - - return 0; -} \ No newline at end of file diff --git a/src/crosslangcompiler.cpp b/src/crosslangcompiler.cpp deleted file mode 100644 index 0b1da19..0000000 --- a/src/crosslangcompiler.cpp +++ /dev/null @@ -1,285 +0,0 @@ -#include "CrossLang.hpp" -#include -#include -using namespace Tesses::CrossLang; -using namespace Tesses::Framework; -using namespace Tesses::Framework::Filesystem; -void Help(const char* filename) -{ - printf("USAGE: %s [OPTIONS] source_file1 source_file2 source_file_n \n", filename); - printf("OPTIONS:\n"); - printf(" -o: Output directory (OUTDIR, defaults to ./bin)\n"); - printf(" -i: Set info (ex {\"maintainer\": \"Mike Nolan\", \"repo\": \"https://example.com/\", \"homepage\": \"https://example.com/\",\"license\":\"MIT\"})\n"); - printf(" -I: Set icon resource name (in the resource folder), should be a 128x128 png\n"); - printf(" -v: Set version (1.0.0.0-prod defaults to 1.0.0.0-dev)\n"); - printf(" -d: Add dependency (DependencyName-1.0.0.0-prod)\n"); - printf(" -D: enable debug)\n"); - printf(" -t: Declare a tool (ToolName-1.0.0.0-prod)\n"); - printf(" -n: Set name (MyAppOrLibName defaults to out)\n"); - printf(" -r: Set resource directory (RESDIR defaults to res)\n"); - printf(" -h, --help: Prints help\n"); - printf(" -e: Set comptime permissions defaults to none, none for no support, \"secure\" for sane without file access, \"secure_file\" for sane with file access to current directory and sub directories, \"full\" has full runtime.\n"); - printf("Options except for help have flag with arg like this: -F ARG\n"); - exit(1); -} -int main(int argc, char** argv) -{ - /*std::ifstream strm(argv[1],std::ios_base::in|std::ios_base::binary); - std::vector tokens; - Lex(argv[1],strm,tokens); - - Parser parser(tokens); - - CodeGen gen; - gen.GenRoot(parser.ParseRoot()); - std::vector data; - ByteCodeVectorWriter w(data); - gen.Save(std::filesystem::current_path(),w); - */ - TF_InitWithConsole(); - std::filesystem::path outputDir = std::filesystem::current_path() / "bin"; - std::vector source; - std::filesystem::path resourceDir = std::filesystem::current_path() / "res"; - std::vector> dependencies; - std::vector> tools; - std::string name="out"; - std::string info="{}"; - std::string icon=""; - std::string comptime="none"; - TVMVersion version; - bool debug=false; - - - - for(int i = 1; i < argc; i++) - { - if(strcmp(argv[i],"--help") == 0 || strcmp(argv[i],"-h")==0) - { - Help(argv[0]); - } - - else if(strcmp(argv[i], "-o") == 0) - { - i++; - if(i < argc) - { - outputDir = argv[i]; - } - } - else if(strcmp(argv[i], "-r") == 0) - { - i++; - if(i < argc) - { - resourceDir = argv[i]; - } - } - else if(strcmp(argv[i], "-e") == 0) - { - i++; - if(i < argc) - { - comptime = argv[i]; - } - } - - else if(strcmp(argv[i], "-i") == 0) - { - i++; - if(i < argc) - { - info = argv[i]; - } - } - else if(strcmp(argv[i],"-I") == 0) - { - i++; - if(i < argc) - { - icon = argv[i]; - } - } - else if(strcmp(argv[i], "-d") == 0) - { - i++; - if(i < argc) - { - std::string str = argv[i]; - auto lastDash = str.find_last_of('-'); - if(lastDash < str.size()) - { - std::string str2 = str.substr(lastDash+1); - if(str2 == "dev" || str2 == "alpha" || str2 == "beta" || str2 == "prod") - { - lastDash = str.find_last_of('-',lastDash-1); - } - std::string str1 = str.substr(0,lastDash); - str2 = str.substr(lastDash+1); - - TVMVersion v2; - if(!TVMVersion::TryParse(str2,v2)) - { - printf("ERROR: Invalid syntax for version\n"); - printf("Expected MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]]]]\n"); - exit(1); - } - dependencies.push_back(std::pair(str1,v2)); - - } - else - { - printf("ERROR: Dependency must have version\n"); - exit(1); - } - } - } - else if(strcmp(argv[i], "-t") == 0) - { - i++; - if(i < argc) - { - std::string str = argv[i]; - auto lastDash = str.find_last_of('-'); - if(lastDash < str.size()) - { - std::string str2 = str.substr(lastDash+1); - if(str2 == "dev" || str2 == "alpha" || str2 == "beta" || str2 == "prod") - { - lastDash = str.find_last_of('-',lastDash-1); - } - std::string str1 = str.substr(0,lastDash); - str2 = str.substr(lastDash+1); - - TVMVersion v2; - if(!TVMVersion::TryParse(str2,v2)) - { - printf("ERROR: Invalid syntax for version\n"); - printf("Expected MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]]]]\n"); - exit(1); - } - tools.push_back(std::pair(str1,v2)); - - } - else - { - printf("ERROR: Tool must have version\n"); - exit(1); - } - } - } - else if(strcmp(argv[i], "-n") == 0) - { - i++; - if(i < argc) - { - name = argv[i]; - } - } - else if(strcmp(argv[i], "-v") == 0) - { - i++; - if(i < argc) - { - - if(!TVMVersion::TryParse(argv[i],version)) - { - printf("ERROR: Invalid syntax for version\n"); - printf("Expected MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]]]]\n"); - exit(1); - } - } - } - else if(strcmp(argv[i],"-D") == 0) - { - debug = true; - } - else { - source.push_back(argv[i]); - } - } - if(source.empty()) - { - Help(argv[0]); - } - - - std::vector tokens; - - for(auto src : source) - { - std::ifstream strm(src,std::ios_base::in|std::ios_base::binary); - int res = Lex(std::filesystem::absolute(src).string(),strm,tokens); - - } - - std::shared_ptr gc; - std::shared_ptr ls; - TRootEnvironment* env=nullptr; - if(comptime != "none") - { - gc = std::make_shared(); - gc->Start(); - ls = std::make_shared(gc); - env = TRootEnvironment::Create(*ls,TDictionary::Create(*ls)); - - if(comptime == "secure") - { - TStd::RegisterConsole(gc,env); - TStd::RegisterClass(gc,env); - TStd::RegisterCrypto(gc,env); - TStd::RegisterDictionary(gc,env); - TStd::RegisterJson(gc,env); - TStd::RegisterRoot(gc,env); - TStd::RegisterIO(gc,env,false); - env->permissions.locked=true; - } - else if(comptime == "secure_file") - { - TStd::RegisterConsole(gc,env); - TStd::RegisterClass(gc,env); - TStd::RegisterCrypto(gc,env); - TStd::RegisterDictionary(gc,env); - TStd::RegisterJson(gc,env); - TStd::RegisterRoot(gc,env); - TStd::RegisterIO(gc,env,false); - env->permissions.locked=true; - auto fs = env->EnsureDictionary(gc,"FS"); - fs->SetValue("Local", std::make_shared(LocalFS,Tesses::Framework::Filesystem::VFSPath::GetAbsoluteCurrentDirectory())); - } - else if(comptime == "full") - { - TStd::RegisterStd(gc,env); - env->permissions.locked=true; - } - } - - Parser parser(tokens,gc,env); - parser.debug = debug; - CodeGen gen; - - auto sfs = std::make_shared(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string())); - gen.embedFS = sfs; - - gen.GenRoot(parser.ParseRoot()); - gen.name = name; - gen.version = version; - gen.info = info; - gen.icon = icon; - for(auto deps : dependencies) - { - gen.dependencies.push_back(deps); - } - for(auto tool : tools) - { - gen.tools.push_back(tool); - } - - std::filesystem::create_directory(outputDir); - - { - auto strm = std::make_shared(outputDir / (name + "-" + version.ToString() + ".crvm"),"wb"); - - gen.Save(strm); - } - return 0; -} \ No newline at end of file diff --git a/src/crossmergecli.cpp b/src/crossmergecli.cpp deleted file mode 100644 index 24deb19..0000000 --- a/src/crossmergecli.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "CrossLang.hpp" -void help(char* program) -{ - std::cout << "USAGE: " << program << " FILE.CRVM DEST.CRVM" << std::endl; - - exit(0); -} -int main(int argc, char** argv) -{ - using namespace Tesses::Framework; - using namespace Tesses::Framework::Streams; - using namespace Tesses::Framework::Filesystem; - using namespace Tesses::CrossLang; - TF_Init(); - - if(argc < 3) - { - help(argv[0]); - } - - std::string src=argv[1]; - std::string dest=argv[2]; - - - - VFSPath srcF = src; - VFSPath destF = dest; - srcF.MakeAbsolute(); - destF.MakeAbsolute(); - - - auto sdir = std::make_shared(LocalFS,srcF.GetParent()); - auto ddir = std::make_shared(LocalFS,destF+"_tmp"); - - - auto outpath = Merge(sdir,"/"+srcF.GetFileName(), ddir); - outpath.relative=true; - outpath = (destF+"_tmp") / outpath; - LocalFS->MoveFile(outpath,destF); - LocalFS->DeleteDirectoryRecurse(destF+"_tmp"); - - - return 0; -} \ No newline at end of file diff --git a/src/crossthumbnailer.cpp b/src/crossthumbnailer.cpp index 951ba40..ca6ae8c 100644 --- a/src/crossthumbnailer.cpp +++ b/src/crossthumbnailer.cpp @@ -3,57 +3,49 @@ #include #include #include +#include #include #include -#include -int main(int argc,char** argv) -{ +int main(int argc, char **argv) { Tesses::Framework::TF_Init(); std::string p = argv[0]; - auto emptyThumb =Tesses::Framework::Platform::Environment::GetRealExecutablePath(p).GetParent().GetParent() / "share" / "icons" / "crosslang.png"; - - if(argc < 3) - { + auto emptyThumb = + Tesses::Framework::Platform::Environment::GetRealExecutablePath(p) + .GetParent() + .GetParent() / + "share" / "icons" / "crosslang.png"; + + if (argc < 3) { std::cout << "USAGE: " << argv[0] << " CRVMFILE NEWPNG" << std::endl; return 1; } std::string crvm = argv[1]; std::string png = argv[2]; - - if(Tesses::Framework::Filesystem::LocalFS->FileExists(crvm)) - { - - Tesses::CrossLang::TFile file; - auto f = Tesses::Framework::Filesystem::LocalFS->OpenFile(crvm, "rb"); - - file.Load(nullptr,f); + if (Tesses::Framework::Filesystem::LocalFS->FileExists(crvm)) { + Tesses::CrossLang::TFile file; + auto f = Tesses::Framework::Filesystem::LocalFS->OpenFile(crvm, "rb"); - if(file.icon >= 0 && file.icon < file.resources.size()) - { - auto f2 = Tesses::Framework::Filesystem::LocalFS->OpenFile(png, "wb"); - if(f2 != nullptr) - { - auto& icon = file.resources[file.icon]; - f2->WriteBlock(icon.data(),icon.size()); - - } - return 0; - + file.Load(nullptr, f); + + if (file.icon >= 0 && file.icon < file.resources.size()) { + auto f2 = + Tesses::Framework::Filesystem::LocalFS->OpenFile(png, "wb"); + if (f2 != nullptr) { + auto &icon = file.resources[file.icon]; + f2->WriteBlock(icon.data(), icon.size()); + } + return 0; } - - } - if(Tesses::Framework::Filesystem::LocalFS->FileExists(emptyThumb)) - { - auto src = Tesses::Framework::Filesystem::LocalFS->OpenFile(emptyThumb,"rb"); - auto dest = Tesses::Framework::Filesystem::LocalFS->OpenFile(png,"wb"); - if(src != nullptr && dest != nullptr) - { + if (Tesses::Framework::Filesystem::LocalFS->FileExists(emptyThumb)) { + auto src = + Tesses::Framework::Filesystem::LocalFS->OpenFile(emptyThumb, "rb"); + auto dest = Tesses::Framework::Filesystem::LocalFS->OpenFile(png, "wb"); + if (src != nullptr && dest != nullptr) { src->CopyTo(dest); } - } return 0; } \ No newline at end of file diff --git a/src/markedtobject.cpp b/src/markedtobject.cpp index ba3450b..675c334 100644 --- a/src/markedtobject.cpp +++ b/src/markedtobject.cpp @@ -1,37 +1,25 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - SharedPtrTObject::SharedPtrTObject(std::shared_ptr gc, TObject o) - { - this->ls = new GCList(gc); - this->ls->Add(o); - this->o = o; - } - TObject& SharedPtrTObject::GetObject() - { - return this->o; - } - SharedPtrTObject::~SharedPtrTObject() - { - if(this->ls) +namespace Tesses::CrossLang { +SharedPtrTObject::SharedPtrTObject(std::shared_ptr gc, TObject o) { + this->ls = new GCList(gc); + this->ls->Add(o); + this->o = o; +} +TObject &SharedPtrTObject::GetObject() { return this->o; } +SharedPtrTObject::~SharedPtrTObject() { + if (this->ls) delete this->ls; - } - std::shared_ptr SharedPtrTObject::GetGC() - { - return this->ls->GetGC(); - } - MarkedTObject CreateMarkedTObject(std::shared_ptr gc, TObject o) - { - return std::make_shared(gc,o); - } - - MarkedTObject CreateMarkedTObject(GCList* gc, TObject o) - { - return CreateMarkedTObject(gc->GetGC(),o); - } - MarkedTObject CreateMarkedTObject(GCList& gc, TObject o) - { - return CreateMarkedTObject(gc.GetGC(),o); - } -} \ No newline at end of file +} +std::shared_ptr SharedPtrTObject::GetGC() { return this->ls->GetGC(); } +MarkedTObject CreateMarkedTObject(std::shared_ptr gc, TObject o) { + return std::make_shared(gc, o); +} + +MarkedTObject CreateMarkedTObject(GCList *gc, TObject o) { + return CreateMarkedTObject(gc->GetGC(), o); +} +MarkedTObject CreateMarkedTObject(GCList &gc, TObject o) { + return CreateMarkedTObject(gc.GetGC(), o); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/program_lib/crossarchivecreate.cpp b/src/program_lib/crossarchivecreate.cpp index 19e7006..a3d9bb3 100644 --- a/src/program_lib/crossarchivecreate.cpp +++ b/src/program_lib/crossarchivecreate.cpp @@ -3,12 +3,15 @@ namespace Tesses::CrossLang::Programs { using namespace Tesses::Framework::Filesystem; using namespace Tesses::Framework::Streams; -static void Help(std::string& filename) -{ - std::cout << "USAGE: " << filename << " [OPTIONS] " << std::endl; +static void Help(std::string &filename) { + std::cout << "USAGE: " << filename + << " [OPTIONS] " << std::endl; printf("OPTIONS:\n"); - printf(" -i: Set info (ex {\"maintainer\": \"Mike Nolan\", \"repo\": \"https://example.com/\", \"homepage\": \"https://example.com/\",\"license\":\"MIT\"})\n"); - printf(" -I: Set icon name (relative to dirasroot), should be a 128x128 png\n"); + printf(" -i: Set info (ex {\"maintainer\": \"Mike Nolan\", \"repo\": " + "\"https://example.com/\", \"homepage\": " + "\"https://example.com/\",\"license\":\"MIT\"})\n"); + printf(" -I: Set icon name (relative to dirasroot), should be a 128x128 " + "png\n"); printf(" -v: Set version (1.0.0.0-prod defaults to 1.0.0.0-dev)\n"); printf(" -n: Set name (MyAppOrLibName defaults to out)\n"); printf(" -h, --help: Prints help\n"); @@ -16,80 +19,66 @@ static void Help(std::string& filename) exit(1); } -int64_t CrossArchiveCreate(std::vector& argv) -{ +int64_t CrossArchiveCreate(std::vector &argv) { Tesses::Framework::TF_Init(); - std::string name="out"; - std::string info="{}"; - TVMVersion version; - std::string icon=""; - std::vector args; - for(int i = 1; i < argv.size(); i++) - { - if(argv[i] == "--help" || argv[i] == "-h") - { + std::string name = "out"; + std::string info = "{}"; + TVMVersion version; + std::string icon = ""; + std::vector args; + for (int i = 1; i < argv.size(); i++) { + if (argv[i] == "--help" || argv[i] == "-h") { Help(argv[0]); - } - else if(argv[i] == "-i") - { + } else if (argv[i] == "-i") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { info = argv[i]; } - } - else if(argv[i] == "-I") - { + } else if (argv[i] == "-I") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { icon = argv[i]; } - } - else if(argv[i] == "-n") - { + } else if (argv[i] == "-n") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { name = argv[i]; } - } - else if(argv[i] == "-v") - { + } else if (argv[i] == "-v") { i++; - if(i < argv.size()) - { - - if(!TVMVersion::TryParse(argv[i],version)) - { + if (i < argv.size()) { + + if (!TVMVersion::TryParse(argv[i], version)) { printf("ERROR: Invalid syntax for version\n"); - printf("Expected MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]]]]\n"); + printf("Expected " + "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]" + "]]]\n"); exit(1); } } - } - else { + } else { args.push_back(argv[i]); } - } + } - if(args.size() < 2) Help(argv[0]); - - - auto path = Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(args[0]); + if (args.size() < 2) + Help(argv[0]); + + auto path = + Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(args[0]); Tesses::Framework::Filesystem::LocalFS->CreateDirectory(path); - auto sdfs = std::make_shared(Tesses::Framework::Filesystem::LocalFS,path); + auto sdfs = std::make_shared( + Tesses::Framework::Filesystem::LocalFS, path); - FILE* f = fopen(args[1].c_str(),"wb"); - if(f == NULL) - { + FILE *f = fopen(args[1].c_str(), "wb"); + if (f == NULL) { printf("ERROR: could not open %s\n", args[1].c_str()); return 1; } - auto strm = std::make_shared(f,true,"wb",true); - CrossArchiveCreate(sdfs,strm,name,version,info,icon); + auto strm = std::make_shared(f, true, "wb", true); + CrossArchiveCreate(sdfs, strm, name, version, info, icon); return 0; } -} \ No newline at end of file +} // namespace Tesses::CrossLang::Programs \ No newline at end of file diff --git a/src/program_lib/crossarchiveextract.cpp b/src/program_lib/crossarchiveextract.cpp index 610b680..85248b0 100644 --- a/src/program_lib/crossarchiveextract.cpp +++ b/src/program_lib/crossarchiveextract.cpp @@ -5,25 +5,23 @@ namespace Tesses::CrossLang::Programs { using namespace Tesses::Framework::Filesystem; using namespace Tesses::Framework::Streams; -int64_t CrossArchiveExtract(std::vector& argv) -{ +int64_t CrossArchiveExtract(std::vector &argv) { Tesses::Framework::TF_Init(); - if(argv.size() < 3) - { - std::cout << "USAGE: " << argv[0] << " " << std::endl; + if (argv.size() < 3) { + std::cout << "USAGE: " << argv[0] << " " + << std::endl; return 1; } - auto sdfs= std::make_shared(Tesses::Framework::Filesystem::LocalFS,std::string(argv[2])); - auto strm= LocalFS->OpenFile(argv[1], "rb"); - if(strm->CanRead()) - { + auto sdfs = std::make_shared( + Tesses::Framework::Filesystem::LocalFS, std::string(argv[2])); + auto strm = LocalFS->OpenFile(argv[1], "rb"); + if (!strm->CanRead()) { std::cout << "ERROR: could not open " << argv[1] << std::endl; return 1; } - - auto res = Tesses::CrossLang::CrossArchiveExtract(strm,sdfs); + auto res = Tesses::CrossLang::CrossArchiveExtract(strm, sdfs); std::cout << "Crvm Name: " << res.first.first << std::endl; std::cout << "Crvm Version: " << res.first.second.ToString() << std::endl; @@ -31,4 +29,4 @@ int64_t CrossArchiveExtract(std::vector& argv) return 0; } -} \ No newline at end of file +} // namespace Tesses::CrossLang::Programs diff --git a/src/program_lib/crossdump.cpp b/src/program_lib/crossdump.cpp index 67c9d89..98941ae 100644 --- a/src/program_lib/crossdump.cpp +++ b/src/program_lib/crossdump.cpp @@ -1,38 +1,37 @@ #include "CrossLang.hpp" #include namespace Tesses::CrossLang::Programs { -static void Ensure(std::shared_ptr strm,uint8_t* buffer, size_t len) -{ - if(strm->ReadBlock(buffer,len) != len) - { - throw VMException("Could not read " + std::to_string(len) + " byte(s)."); +static void Ensure(std::shared_ptr strm, + uint8_t *buffer, size_t len) { + if (strm->ReadBlock(buffer, len) != len) { + throw VMException("Could not read " + std::to_string(len) + + " byte(s)."); } } -static uint32_t EnsureInt(std::shared_ptr strm) -{ +static uint32_t +EnsureInt(std::shared_ptr strm) { uint8_t buff[4]; - Ensure(strm,buff,sizeof(buff)); + Ensure(strm, buff, sizeof(buff)); return BitConverter::ToUint32BE(buff[0]); } -static std::string EnsureString(std::shared_ptr strm) -{ +static std::string +EnsureString(std::shared_ptr strm) { size_t len = (size_t)EnsureInt(strm); - std::string myStr={}; + std::string myStr = {}; myStr.resize(len); - Ensure(strm,(uint8_t*)myStr.data(), len); + Ensure(strm, (uint8_t *)myStr.data(), len); return myStr; } -void CrossLangDump(std::shared_ptr strm) -{ +void CrossLangDump(std::shared_ptr strm) { uint8_t main_header[18]; - Ensure(strm,main_header,sizeof(main_header)); - if(strncmp((const char*)main_header,"TCROSSVM",8) != 0) throw VMException("Invalid TCrossVM image."); - TVMVersion version(main_header+8); - if(version.CompareToRuntime() == 1) - { + Ensure(strm, main_header, sizeof(main_header)); + if (strncmp((const char *)main_header, "TCROSSVM", 8) != 0) + throw VMException("Invalid TCrossVM image."); + TVMVersion version(main_header + 8); + if (version.CompareToRuntime() == 1) { throw VMException("Runtime is too old."); } - TVMVersion v2(main_header+13); + TVMVersion v2(main_header + 13); std::cout << "Version: " << v2.ToString() << std::endl; size_t _len = (size_t)EnsureInt(strm); @@ -41,215 +40,188 @@ void CrossLangDump(std::shared_ptr strm) std::vector strs; - std::unordered_map> funs; - std::vector> closures; + std::unordered_map> funs; + std::vector> closures; - + char table_name[4]; + bool hasIcon = false; - char table_name[4]; - bool hasIcon=false; + for (size_t i = 0; i < _len; i++) { + Ensure(strm, (uint8_t *)table_name, sizeof(table_name)); + size_t tableLen = (size_t)EnsureInt(strm); + std::string tableName(table_name, 4); + if (tableName == "ICON") { + hasIcon = true; + } else if (tableName == "STRS") { + size_t strsLen = (size_t)EnsureInt(strm); + for (size_t j = 0; j < strsLen; j++) { + strs.push_back(EnsureString(strm)); + } + } else if (tableName == "DEPS") { - for(size_t i = 0; i < _len; i++) - { - Ensure(strm,(uint8_t*)table_name,sizeof(table_name)); - size_t tableLen = (size_t)EnsureInt(strm); - std::string tableName(table_name,4); - if(tableName == "ICON") - { - hasIcon=true; + std::string name = strs.at((size_t)EnsureInt(strm)); + + uint8_t version_bytes[5]; + Ensure(strm, version_bytes, sizeof(version_bytes)); + TVMVersion depVersion(version_bytes); + std::cout << "Dependency: " << name << "-" << depVersion.ToString() + << std::endl; + } else if (tableName == "NAME") { + std::cout << "Name: " << strs.at((size_t)EnsureInt(strm)) + << std::endl; + } else if (tableName == "CLSS") { + std::cout << "Classes:\n"; + uint32_t clss_cnt = EnsureInt(strm); + for (uint32_t j = 0; j < clss_cnt; j++) { + std::cout << "\t/^" << strs.at(EnsureInt(strm)) << "^/" + << std::endl; + uint32_t fnPartsC = EnsureInt(strm); + std::cout << "\tName: "; + for (uint32_t k = 0; k < fnPartsC; k++) { + if (k > 0) + std::cout << "."; + std::cout << strs.at(EnsureInt(strm)); } - else if(tableName == "STRS") - { - size_t strsLen = (size_t)EnsureInt(strm); - for(size_t j = 0;j < strsLen;j++) - { - strs.push_back(EnsureString(strm)); + std::cout << std::endl; + fnPartsC = EnsureInt(strm); + std::cout << "\tInherits: "; + for (uint32_t k = 0; k < fnPartsC; k++) { + if (k > 0) + std::cout << "."; + std::cout << strs.at(EnsureInt(strm)); + } + std::cout << std::endl; + + uint32_t ents = EnsureInt(strm); + + for (uint8_t k = 0; k < ents; k++) { + Ensure(strm, main_header, 1); + uint8_t flags = main_header[0]; + std::cout << "\t\t/^" << strs.at(EnsureInt(strm)) << "^/" + << std::endl; + std::string fnname = strs.at(EnsureInt(strm)); + std::string fnargs; + uint32_t argParts = EnsureInt(strm); + + for (uint32_t l = 0; l < argParts; l++) { + if (l > 0) + fnargs += ", "; + fnargs += strs.at(EnsureInt(strm)); } - } - else if(tableName == "DEPS") - { - - std::string name = strs.at((size_t)EnsureInt(strm)); - - uint8_t version_bytes[5]; - Ensure(strm,version_bytes,sizeof(version_bytes)); - TVMVersion depVersion(version_bytes); - std::cout << "Dependency: " << name << "-" << depVersion.ToString() << std::endl; - } - else if(tableName == "NAME") - { - std::cout << "Name: " << strs.at((size_t)EnsureInt(strm)) << std::endl; - } - else if(tableName == "CLSS") - { - std::cout << "Classes:\n"; - uint32_t clss_cnt= EnsureInt(strm); - for(uint32_t j = 0; j < clss_cnt; j++) - { - std::cout << "\t/^" << strs.at(EnsureInt(strm)) << "^/" << std::endl; - uint32_t fnPartsC = EnsureInt(strm); - std::cout << "\tName: "; - for(uint32_t k = 0; k < fnPartsC; k++) - { - if(k > 0) std::cout << "."; - std::cout << strs.at(EnsureInt(strm)); - } - std::cout << std::endl; - fnPartsC = EnsureInt(strm); - std::cout << "\tInherits: "; - for(uint32_t k = 0; k < fnPartsC; k++) - { - if(k > 0) std::cout << "."; - std::cout << strs.at(EnsureInt(strm)); - } - std::cout << std::endl; - - uint32_t ents = EnsureInt(strm); - - for(uint8_t k = 0; k < ents; k++) - { - Ensure(strm,main_header,1); - uint8_t flags = main_header[0]; - std::cout << "\t\t/^" << strs.at(EnsureInt(strm)) << "^/" << std::endl; - std::string fnname = strs.at(EnsureInt(strm)); - std::string fnargs; - uint32_t argParts = EnsureInt(strm); - - for(uint32_t l = 0; l < argParts; l++) - { - if(l > 0) fnargs += ", "; - fnargs += strs.at(EnsureInt(strm)); - } - uint32_t fnchunk = EnsureInt(strm); - switch(flags & 3) - { - case 0: - std::cout << "\t\tprivate "; - break; - case 1: - std::cout << "\t\tprotected "; - break; - case 2: - std::cout << "\t\tpublic "; - break; - case 3: - std::cout << "\t\tstatic "; - break; - } - - switch((flags >> 2) & 3) - { - case 0: - std::cout << "func " << fnname << "(" << fnargs << "), chunk = " << fnchunk << std::endl; - - break; - case 1: - std::cout << "field " << fnname << ", chunk = " << fnchunk << std::endl; - break; - case 2: - std::cout << "abstract " << fnname << "(" << fnargs << ")" << std::endl; - break; - case 3: - std::cout << "unset_field " << fnname << std::endl; - break; - } - std::cout << std::endl; - } - } - } - else if(tableName == "CHKS") - { - size_t chunkCount = (size_t)EnsureInt(strm); - - for(size_t j = 0; j < chunkCount; j++) - { - std::vector args; - size_t argCount = (size_t)EnsureInt(strm); - for(size_t k = 0; k < argCount; k++) - { - args.push_back(strs.at(EnsureInt(strm))); - } - auto len = EnsureInt(strm); - - strm->Seek(len,Tesses::Framework::Streams::SeekOrigin::Current); - - closures.push_back(args); - } - } - else if(tableName == "FUNS") - { - size_t funLength = (size_t)EnsureInt(strm); - - for(size_t j = 0; j < funLength;j++) - { - std::vector fnParts; - uint32_t fnPartsC = EnsureInt(strm); - for(uint32_t k = 0; k < fnPartsC; k++) - { - fnParts.push_back(strs.at(EnsureInt(strm))); + uint32_t fnchunk = EnsureInt(strm); + switch (flags & 3) { + case 0: + std::cout << "\t\tprivate "; + break; + case 1: + std::cout << "\t\tprotected "; + break; + case 2: + std::cout << "\t\tpublic "; + break; + case 3: + std::cout << "\t\tstatic "; + break; } - uint32_t fnNumber = EnsureInt(strm); - funs[fnNumber] = fnParts; - - } - } - else if(tableName == "INFO") - { + switch ((flags >> 2) & 3) { + case 0: + std::cout << "func " << fnname << "(" << fnargs + << "), chunk = " << fnchunk << std::endl; - std::cout << "Info: " << strs.at((size_t)EnsureInt(strm)) << std::endl; - - } - else - { - strm->Seek((int64_t)tableLen,Tesses::Framework::Streams::SeekOrigin::Current); + break; + case 1: + std::cout << "field " << fnname + << ", chunk = " << fnchunk << std::endl; + break; + case 2: + std::cout << "abstract " << fnname << "(" << fnargs + << ")" << std::endl; + break; + case 3: + std::cout << "unset_field " << fnname << std::endl; + break; + } + std::cout << std::endl; } } - if(hasIcon) - std::cout << "Has Icon: yes" << std::endl; - else - std::cout << "Has Icon: no" << std::endl; + } else if (tableName == "CHKS") { + size_t chunkCount = (size_t)EnsureInt(strm); - for(size_t i = 1; i < closures.size(); i++) - { - if(funs.count((uint32_t)i) > 0) - { - std::cout << "Func: "; - auto res = funs[(uint32_t)i]; - if(!res.empty()) { - std::cout << "/^" << res[0] << "^/ "; - } - for(size_t i = 1; i < res.size(); i++) - { - if(i > 1) std::cout << "."; - std::cout << res[i]; - } + for (size_t j = 0; j < chunkCount; j++) { + std::vector args; + size_t argCount = (size_t)EnsureInt(strm); + for (size_t k = 0; k < argCount; k++) { + args.push_back(strs.at(EnsureInt(strm))); } - else - { - std::cout << "Closure: "; - } - std::cout << "("; - bool first=true; - for(auto arg : closures[i]) - { - if(!first) std::cout << ", "; - std::cout << arg; + auto len = EnsureInt(strm); - if(first) first=false; - } - std::cout << ")" << std::endl; + strm->Seek(len, + Tesses::Framework::Streams::SeekOrigin::Current); + + closures.push_back(args); } - std::cout << std::endl; - std::cout << "String Table:" << std::endl; + } else if (tableName == "FUNS") { + size_t funLength = (size_t)EnsureInt(strm); - for(auto str : strs) { - std::cout << EscapeString(str, true) << std::endl; + for (size_t j = 0; j < funLength; j++) { + std::vector fnParts; + uint32_t fnPartsC = EnsureInt(strm); + for (uint32_t k = 0; k < fnPartsC; k++) { + fnParts.push_back(strs.at(EnsureInt(strm))); + } + + uint32_t fnNumber = EnsureInt(strm); + funs[fnNumber] = fnParts; } - - - - + } else if (tableName == "INFO") { + + std::cout << "Info: " << strs.at((size_t)EnsureInt(strm)) + << std::endl; + + } else { + strm->Seek((int64_t)tableLen, + Tesses::Framework::Streams::SeekOrigin::Current); + } + } + if (hasIcon) + std::cout << "Has Icon: yes" << std::endl; + else + std::cout << "Has Icon: no" << std::endl; + + for (size_t i = 1; i < closures.size(); i++) { + if (funs.count((uint32_t)i) > 0) { + std::cout << "Func: "; + auto res = funs[(uint32_t)i]; + if (!res.empty()) { + std::cout << "/^" << res[0] << "^/ "; + } + for (size_t i = 1; i < res.size(); i++) { + if (i > 1) + std::cout << "."; + std::cout << res[i]; + } + } else { + std::cout << "Closure: "; + } + std::cout << "("; + bool first = true; + for (auto arg : closures[i]) { + if (!first) + std::cout << ", "; + std::cout << arg; + + if (first) + first = false; + } + std::cout << ")" << std::endl; + } + std::cout << std::endl; + std::cout << "String Table:" << std::endl; + + for (auto str : strs) { + std::cout << EscapeString(str, true) << std::endl; + } } -} \ No newline at end of file +} // namespace Tesses::CrossLang::Programs \ No newline at end of file diff --git a/src/program_lib/crosslang.cpp b/src/program_lib/crosslang.cpp index 2cf5559..f115bf0 100644 --- a/src/program_lib/crosslang.cpp +++ b/src/program_lib/crosslang.cpp @@ -6,153 +6,150 @@ using namespace Tesses::Framework; using namespace Tesses::Framework::Http; -namespace Tesses::CrossLang::Programs -{ +namespace Tesses::CrossLang::Programs { -static bool Download(Tesses::Framework::Filesystem::VFSPath filename,std::shared_ptr vfs) -{ - auto inContainer=Platform::Environment::GetVariable("CROSSLANG_CONTAINER"); - if(inContainer && (*inContainer=="1" || *inContainer=="y" || *inContainer=="Y")) - { +static bool Download(Tesses::Framework::Filesystem::VFSPath filename, + std::shared_ptr vfs) { + auto inContainer = + Platform::Environment::GetVariable("CROSSLANG_CONTAINER"); + if (inContainer && + (*inContainer == "1" || *inContainer == "y" || *inContainer == "Y")) { HttpRequest req; - req.followRedirects=true; + req.followRedirects = true; req.url = "https://redirect.tesses.net/crosslang-shell"; req.method = "GET"; HttpResponse resp(req); - if(resp.statusCode == StatusCode::OK) - { + if (resp.statusCode == StatusCode::OK) { auto strm = resp.ReadAsStream(); CrossLang::CrossArchiveExtract(strm, vfs); return true; - } - else - { - std::cout << "Error when fetching the script error: " << std::to_string(resp.statusCode) << " " << HttpUtils::StatusCodeString(resp.statusCode) << std::endl; + } else { + std::cout << "Error when fetching the script error: " + << std::to_string(resp.statusCode) << " " + << HttpUtils::StatusCodeString(resp.statusCode) + << std::endl; return false; } } - while(true) - { - std::cout << "File " << filename.ToString() << " not found, do you want to download the installer from: https://redirect.tesses.net/crosslang-shell (this may install other stuff as well) (Y/n)? "; + while (true) { + std::cout << "File " << filename.ToString() + << " not found, do you want to download the installer from: " + "https://redirect.tesses.net/crosslang-shell (this may " + "install other stuff as well) (Y/n)? "; std::string line; - std::getline(std::cin,line); - if(line == "Y" || line == "y") - { + std::getline(std::cin, line); + if (line == "Y" || line == "y") { HttpRequest req; req.followRedirects = true; req.url = "https://redirect.tesses.net/crosslang-shell"; req.method = "GET"; HttpResponse resp(req); - if(resp.statusCode == StatusCode::OK) - { + if (resp.statusCode == StatusCode::OK) { auto strm = resp.ReadAsStream(); CrossLang::CrossArchiveExtract(strm, vfs); return true; - } - else - { - std::cout << "Error when fetching the script error: " << std::to_string(resp.statusCode) << " " << HttpUtils::StatusCodeString(resp.statusCode) << std::endl; + } else { + std::cout << "Error when fetching the script error: " + << std::to_string(resp.statusCode) << " " + << HttpUtils::StatusCodeString(resp.statusCode) + << std::endl; return false; } - } - else if(line == "N" || line == "n") - { - std::cout << "Looks like you will need to install manually" << std::endl; + } else if (line == "N" || line == "n") { + std::cout << "Looks like you will need to install manually" + << std::endl; return false; - } - else - { + } else { std::cout << "Please use Y or N (case insensitive)" << std::endl; - } } return false; } -TObject CrossLangShell(GCList& ls, std::vector& argv) -{ +TObject CrossLangShell(GCList &ls, std::vector &argv) { Tesses::Framework::Filesystem::VFSPath dir = GetCrossLangConfigDir(); - Tesses::Framework::Filesystem::VFSPath filename = dir / "Shell" / "Shell.crvm"; + Tesses::Framework::Filesystem::VFSPath filename = + dir / "Shell" / "Shell.crvm"; - - auto p = Tesses::Framework::Platform::Environment::GetRealExecutablePath(Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(argv[0])).GetParent().GetParent() / "share" / "Tesses" / "CrossLang" / "Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm"; - if(argv.size() == 2 && argv[1] == "configdir") - { + auto p = + Tesses::Framework::Platform::Environment::GetRealExecutablePath( + Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(argv[0])) + .GetParent() + .GetParent() / + "share" / "Tesses" / "CrossLang" / + "Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm"; + if (argv.size() == 2 && argv[1] == "configdir") { std::cout << dir.ToString() << std::endl; return 0; } - if(argv.size() > 1 && argv[1] == "update-shell") - { + if (argv.size() > 1 && argv[1] == "update-shell") { - auto subdir = std::make_shared(Tesses::Framework::Filesystem::LocalFS,dir); + auto subdir = + std::make_shared( + Tesses::Framework::Filesystem::LocalFS, dir); HttpRequest req; - req.followRedirects=true; - req.url = "https://redirect.tesses.net/crosslang-shell"; - req.method = "GET"; - HttpResponse resp(req); - if(resp.statusCode == StatusCode::OK) - { - auto strm = resp.ReadAsStream(); - CrossLang::CrossArchiveExtract(strm, subdir); + req.followRedirects = true; + req.url = "https://redirect.tesses.net/crosslang-shell"; + req.method = "GET"; + HttpResponse resp(req); + if (resp.statusCode == StatusCode::OK) { + auto strm = resp.ReadAsStream(); + CrossLang::CrossArchiveExtract(strm, subdir); - return 0; - } - else - { - std::cout << "Error when fetching the script error: " << std::to_string(resp.statusCode) << " " << HttpUtils::StatusCodeString(resp.statusCode) << std::endl; - return 1; - } + return 0; + } else { + std::cout << "Error when fetching the script error: " + << std::to_string(resp.statusCode) << " " + << HttpUtils::StatusCodeString(resp.statusCode) + << std::endl; + return 1; + } return 0; } - if(!Tesses::Framework::Filesystem::LocalFS->RegularFileExists(filename)) - { - auto subdir = std::make_shared(Tesses::Framework::Filesystem::LocalFS,dir); - if(Tesses::Framework::Filesystem::LocalFS->RegularFileExists(p)) - { - std::cout << "Installing " << p.ToString() << " -> " << dir.ToString() << std::endl; - auto strm = Tesses::Framework::Filesystem::LocalFS->OpenFile(p,"rb"); - if(strm != nullptr) - { + if (!Tesses::Framework::Filesystem::LocalFS->RegularFileExists(filename)) { + auto subdir = + std::make_shared( + Tesses::Framework::Filesystem::LocalFS, dir); + if (Tesses::Framework::Filesystem::LocalFS->RegularFileExists(p)) { + std::cout << "Installing " << p.ToString() << " -> " + << dir.ToString() << std::endl; + auto strm = + Tesses::Framework::Filesystem::LocalFS->OpenFile(p, "rb"); + if (strm != nullptr) { CrossLang::CrossArchiveExtract(strm, subdir); - } - else - { + } else { return 1; } - } - else - { - if(!Download(filename,subdir)) return 1; + } else { + if (!Download(filename, subdir)) + return 1; return 0; } } + TRootEnvironment *env = + TRootEnvironment::Create(ls, TDictionary::Create(ls)); - TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls)); + TStd::RegisterStd(ls.GetGC(), env); + env->LoadFileWithDependencies( + ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, filename); - TStd::RegisterStd(ls.GetGC(),env); - - - env->LoadFileWithDependencies(ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, filename); - - - TList* args = TList::Create(ls); + TList *args = TList::Create(ls); args->Add(filename.ToString()); - for(size_t arg=1;argAdd(std::string(argv[arg])); - return env->CallFunctionWithFatalError(ls,"main",{args}); - + return env->CallFunctionWithFatalError(ls, "main", {args}); } -} +} // namespace Tesses::CrossLang::Programs diff --git a/src/program_lib/crosslangcompiler.cpp b/src/program_lib/crosslangcompiler.cpp index 98eed9d..143b572 100644 --- a/src/program_lib/crosslangcompiler.cpp +++ b/src/program_lib/crosslangcompiler.cpp @@ -1,16 +1,20 @@ #include "CrossLang.hpp" -#include #include +#include using namespace Tesses::Framework; using namespace Tesses::Framework::Filesystem; namespace Tesses::CrossLang::Programs { -static void Help(std::string filename) -{ - std::cout << "USAGE: " << filename << " [OPTIONS] source_file1 source_file2 source_file_n" << std::endl; +static void Help(std::string filename) { + std::cout << "USAGE: " << filename + << " [OPTIONS] source_file1 source_file2 source_file_n" + << std::endl; printf("OPTIONS:\n"); printf(" -o: Output directory (OUTDIR, defaults to ./bin)\n"); - printf(" -i: Set info (ex {\"maintainer\": \"Mike Nolan\", \"repo\": \"https://example.com/\", \"homepage\": \"https://example.com/\",\"license\":\"MIT\"})\n"); - printf(" -I: Set icon resource name (in the resource folder), should be a 128x128 png\n"); + printf(" -i: Set info (ex {\"maintainer\": \"Mike Nolan\", \"repo\": " + "\"https://example.com/\", \"homepage\": " + "\"https://example.com/\",\"license\":\"MIT\"})\n"); + printf(" -I: Set icon resource name (in the resource folder), should be " + "a 128x128 png\n"); printf(" -v: Set version (1.0.0.0-prod defaults to 1.0.0.0-dev)\n"); printf(" -d: Add dependency (DependencyName-1.0.0.0-prod)\n"); printf(" -D: enable debug)\n"); @@ -18,12 +22,14 @@ static void Help(std::string filename) printf(" -n: Set name (MyAppOrLibName defaults to out)\n"); printf(" -r: Set resource directory (RESDIR defaults to res)\n"); printf(" -h, --help: Prints help\n"); - printf(" -e: Set comptime permissions defaults to none, none for no support, \"secure\" for sane without file access, \"secure_file\" for sane with file access to current directory and sub directories, \"full\" has full runtime.\n"); + printf(" -e: Set comptime permissions defaults to none, none for no " + "support, \"secure\" for sane without file access, \"secure_file\" " + "for sane with file access to current directory and sub " + "directories, \"full\" has full runtime.\n"); printf("Options except for help have flag with arg like this: -F ARG\n"); exit(1); } -void CrossLangCompiler(std::vector& argv) -{ +void CrossLangCompiler(std::vector &argv) { /*std::ifstream strm(argv[1],std::ios_base::in|std::ios_base::binary); std::vector tokens; Lex(argv[1],strm,tokens); @@ -36,228 +42,189 @@ void CrossLangCompiler(std::vector& argv) ByteCodeVectorWriter w(data); gen.Save(std::filesystem::current_path(),w); */ - TF_InitWithConsole(); - std::filesystem::path outputDir = std::filesystem::current_path() / "bin"; - std::vector source; - std::filesystem::path resourceDir = std::filesystem::current_path() / "res"; - std::vector> dependencies; - std::vector> tools; - std::string name="out"; - std::string info="{}"; - std::string icon=""; - std::string comptime="none"; - TVMVersion version; - bool debug=false; + TF_InitWithConsole(); + std::filesystem::path outputDir = std::filesystem::current_path() / "bin"; + std::vector source; + std::filesystem::path resourceDir = std::filesystem::current_path() / "res"; + std::vector> dependencies; + std::vector> tools; + std::string name = "out"; + std::string info = "{}"; + std::string icon = ""; + std::string comptime = "none"; + TVMVersion version; + bool debug = false; - - - for(size_t i = 1; i < argv.size(); i++) - { - if(argv[i] == "--help" || argv[i] == "-h") - { + for (size_t i = 1; i < argv.size(); i++) { + if (argv[i] == "--help" || argv[i] == "-h") { Help(argv[0]); } - - else if(argv[i] == "-o") - { + + else if (argv[i] == "-o") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { outputDir = argv[i]; } - } - else if(argv[i] == "-r") - { + } else if (argv[i] == "-r") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { resourceDir = argv[i]; } - } - else if(argv[i] == "-e") - { + } else if (argv[i] == "-e") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { comptime = argv[i]; } } - - else if(argv[i] == "-i") - { + + else if (argv[i] == "-i") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { info = argv[i]; } - } - else if(argv[i] == "-I") - { + } else if (argv[i] == "-I") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { icon = argv[i]; } - } - else if(argv[i] == "-d") - { + } else if (argv[i] == "-d") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { std::string str = argv[i]; auto lastDash = str.find_last_of('-'); - if(lastDash < str.size()) - { - std::string str2 = str.substr(lastDash+1); - if(str2 == "dev" || str2 == "alpha" || str2 == "beta" || str2 == "prod") - { - lastDash = str.find_last_of('-',lastDash-1); + if (lastDash < str.size()) { + std::string str2 = str.substr(lastDash + 1); + if (str2 == "dev" || str2 == "alpha" || str2 == "beta" || + str2 == "prod") { + lastDash = str.find_last_of('-', lastDash - 1); } - std::string str1 = str.substr(0,lastDash); - str2 = str.substr(lastDash+1); - + std::string str1 = str.substr(0, lastDash); + str2 = str.substr(lastDash + 1); + TVMVersion v2; - if(!TVMVersion::TryParse(str2,v2)) - { + if (!TVMVersion::TryParse(str2, v2)) { printf("ERROR: Invalid syntax for version\n"); - printf("Expected MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]]]]\n"); + printf("Expected " + "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-" + "prod]]]]\n"); exit(1); } - dependencies.push_back(std::pair(str1,v2)); - - } - else - { + dependencies.push_back( + std::pair(str1, v2)); + + } else { printf("ERROR: Dependency must have version\n"); exit(1); } } - } - else if(argv[i] == "-t") - { + } else if (argv[i] == "-t") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { std::string str = argv[i]; auto lastDash = str.find_last_of('-'); - if(lastDash < str.size()) - { - std::string str2 = str.substr(lastDash+1); - if(str2 == "dev" || str2 == "alpha" || str2 == "beta" || str2 == "prod") - { - lastDash = str.find_last_of('-',lastDash-1); + if (lastDash < str.size()) { + std::string str2 = str.substr(lastDash + 1); + if (str2 == "dev" || str2 == "alpha" || str2 == "beta" || + str2 == "prod") { + lastDash = str.find_last_of('-', lastDash - 1); } - std::string str1 = str.substr(0,lastDash); - str2 = str.substr(lastDash+1); - + std::string str1 = str.substr(0, lastDash); + str2 = str.substr(lastDash + 1); + TVMVersion v2; - if(!TVMVersion::TryParse(str2,v2)) - { + if (!TVMVersion::TryParse(str2, v2)) { printf("ERROR: Invalid syntax for version\n"); - printf("Expected MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]]]]\n"); + printf("Expected " + "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-" + "prod]]]]\n"); exit(1); } - tools.push_back(std::pair(str1,v2)); - - } - else - { + tools.push_back( + std::pair(str1, v2)); + + } else { printf("ERROR: Tool must have version\n"); exit(1); } } - } - else if(argv[i] == "-n") - { + } else if (argv[i] == "-n") { i++; - if(i < argv.size()) - { + if (i < argv.size()) { name = argv[i]; } - } - else if(argv[i] == "-v") - { + } else if (argv[i] == "-v") { i++; - if(i < argv.size()) - { - - if(!TVMVersion::TryParse(argv[i],version)) - { + if (i < argv.size()) { + + if (!TVMVersion::TryParse(argv[i], version)) { printf("ERROR: Invalid syntax for version\n"); - printf("Expected MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]]]]\n"); + printf("Expected " + "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]" + "]]]\n"); exit(1); } } - } - else if(argv[i] == "-D" || argv[i] == "--debug") - { + } else if (argv[i] == "-D" || argv[i] == "--debug") { debug = true; - } - else { + } else { source.push_back(argv[i]); } - } - if(source.empty()) - { + } + if (source.empty()) { Help(argv[0]); - } - + } std::vector tokens; - for(auto src : source) - { - std::ifstream strm(src,std::ios_base::in|std::ios_base::binary); - int res = Lex(std::filesystem::absolute(src).string(),strm,tokens); - + for (auto src : source) { + std::ifstream strm(src, std::ios_base::in | std::ios_base::binary); + int res = Lex(std::filesystem::absolute(src).string(), strm, tokens); } std::shared_ptr gc; std::shared_ptr ls; - TRootEnvironment* env=nullptr; - if(comptime != "none") - { - std::shared_ptr gc= std::make_shared(); + TRootEnvironment *env = nullptr; + if (comptime != "none") { + std::shared_ptr gc = std::make_shared(); gc->Start(); ls = std::make_shared(gc); - env = TRootEnvironment::Create(*ls,TDictionary::Create(*ls)); + env = TRootEnvironment::Create(*ls, TDictionary::Create(*ls)); - if(comptime == "secure") - { - TStd::RegisterConsole(gc,env); - TStd::RegisterClass(gc,env); - TStd::RegisterCrypto(gc,env); - TStd::RegisterDictionary(gc,env); - TStd::RegisterJson(gc,env); - TStd::RegisterRoot(gc,env); - TStd::RegisterIO(gc,env,false); - env->permissions.locked=true; - } - else if(comptime == "secure_file") - { - TStd::RegisterConsole(gc,env); - TStd::RegisterClass(gc,env); - TStd::RegisterCrypto(gc,env); - TStd::RegisterDictionary(gc,env); - TStd::RegisterJson(gc,env); - TStd::RegisterRoot(gc,env); - TStd::RegisterIO(gc,env,false); - env->permissions.locked=true; - auto fs = env->EnsureDictionary(gc,"FS"); - fs->SetValue("Local", std::make_shared(LocalFS,Tesses::Framework::Filesystem::VFSPath::GetAbsoluteCurrentDirectory())); - } - else if(comptime == "full") - { - TStd::RegisterStd(gc,env); - env->permissions.locked=true; + if (comptime == "secure") { + TStd::RegisterConsole(gc, env); + TStd::RegisterClass(gc, env); + TStd::RegisterCrypto(gc, env); + TStd::RegisterDictionary(gc, env); + TStd::RegisterJson(gc, env); + TStd::RegisterRoot(gc, env); + TStd::RegisterIO(gc, env, false); + env->permissions.locked = true; + } else if (comptime == "secure_file") { + TStd::RegisterConsole(gc, env); + TStd::RegisterClass(gc, env); + TStd::RegisterCrypto(gc, env); + TStd::RegisterDictionary(gc, env); + TStd::RegisterJson(gc, env); + TStd::RegisterRoot(gc, env); + TStd::RegisterIO(gc, env, false); + env->permissions.locked = true; + auto fs = env->EnsureDictionary(gc, "FS"); + fs->SetValue("Local", + std::make_shared( + LocalFS, Tesses::Framework::Filesystem::VFSPath:: + GetAbsoluteCurrentDirectory())); + } else if (comptime == "full") { + TStd::RegisterStd(gc, env); + env->permissions.locked = true; } } - - Parser parser(tokens,gc,env); + + Parser parser(tokens, gc, env); parser.debug = debug; CodeGen gen; - auto sfs = std::make_shared(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string())); + auto sfs = std::make_shared( + LocalFS, LocalFS->SystemToVFSPath(resourceDir.string())); gen.embedFS = sfs; gen.GenRoot(parser.ParseRoot()); @@ -265,21 +232,20 @@ void CrossLangCompiler(std::vector& argv) gen.version = version; gen.info = info; gen.icon = icon; - for(auto deps : dependencies) - { + for (auto deps : dependencies) { gen.dependencies.push_back(deps); } - for(auto tool : tools) - { + for (auto tool : tools) { gen.tools.push_back(tool); } - + std::filesystem::create_directory(outputDir); { - auto strm = std::make_shared(outputDir / (name + "-" + version.ToString() + ".crvm"),"wb"); - + auto strm = std::make_shared( + outputDir / (name + "-" + version.ToString() + ".crvm"), "wb"); + gen.Save(strm); } } -} \ No newline at end of file +} // namespace Tesses::CrossLang::Programs \ No newline at end of file diff --git a/src/program_lib/crosslanginterperter.cpp b/src/program_lib/crosslanginterperter.cpp index 22bff37..d956975 100644 --- a/src/program_lib/crosslanginterperter.cpp +++ b/src/program_lib/crosslanginterperter.cpp @@ -1,124 +1,114 @@ #include "CrossLang.hpp" -#include #include +#include #include #include using namespace Tesses::Framework; using namespace Tesses::Framework::Filesystem; namespace Tesses::CrossLang::Programs { -TObject CrossLangInterperter(GCList& ls,TRootEnvironment* env,std::vector& argv) -{ - std::shared_ptr gc = ls.GetGC(); - if(argv.size() > 1) - { - std::ifstream strm(argv[1],std::ios_base::in|std::ios_base::binary); +TObject CrossLangInterperter(GCList &ls, TRootEnvironment *env, + std::vector &argv) { + std::shared_ptr gc = ls.GetGC(); + if (argv.size() > 1) { + std::ifstream strm(argv[1], std::ios_base::in | std::ios_base::binary); std::vector tokens; - Lex(argv[1],strm,tokens); + Lex(argv[1], strm, tokens); Parser parser(tokens); CodeGen gen; - auto sfs = std::make_shared(LocalFS,VFSPath(".")); + auto sfs = std::make_shared(LocalFS, VFSPath(".")); gen.embedFS = sfs; gen.GenRoot(parser.ParseRoot()); std::vector data; { - auto strm2 = std::make_shared(true); + auto strm2 = + std::make_shared( + true); gen.Save(strm2); - { - TFile* file = TFile::Create(ls); + TFile *file = TFile::Create(ls); + + strm2->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin); + file->Load(gc, strm2); - strm2->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin); - file->Load(gc,strm2); - env->LoadFile(gc, file); - - } } - TList* args = TList::Create(ls); - for(int arg=1;argAdd(std::string(argv[arg])); - - return env->CallFunctionWithFatalError(ls,"main",{args}); - - - } - else - { - - - while(true) - { + + return env->CallFunctionWithFatalError(ls, "main", {args}); + + } else { + + while (true) { std::cout << "> "; std::string source; - std::getline(std::cin,source); + std::getline(std::cin, source); - auto strm2 = std::make_shared(true); + auto strm2 = + std::make_shared( + true); - if(source.find("loadfile ") == 0) - { + if (source.find("loadfile ") == 0) { std::string filename = source.substr(9); - std::ifstream strm(filename,std::ios_base::in|std::ios_base::binary); + std::ifstream strm(filename, + std::ios_base::in | std::ios_base::binary); std::vector tokens; - Lex(filename,strm,tokens); + Lex(filename, strm, tokens); Parser parser(tokens); CodeGen gen; - auto sfs = std::make_shared(LocalFS,VFSPath(".")); + auto sfs = + std::make_shared(LocalFS, VFSPath(".")); gen.embedFS = sfs; gen.GenRoot(parser.ParseRoot()); - + gen.Save(strm2); - } - else if(source == "exit") - { + } else if (source == "exit") { return (int64_t)0; - } - else - { + } else { std::vector tokens; - std::stringstream strm(source,std::ios_base::in | std::ios_base::binary); - Lex("lexed.tcross",strm,tokens); + std::stringstream strm(source, std::ios_base::in | + std::ios_base::binary); + Lex("lexed.tcross", strm, tokens); Parser parser(tokens); CodeGen gen; - auto sfs = std::make_shared(LocalFS,VFSPath(".")); + auto sfs = + std::make_shared(LocalFS, VFSPath(".")); gen.embedFS = sfs; gen.GenRoot(parser.ParseRoot()); - + gen.Save(strm2); } { - - TFile* file = TFile::Create(ls); - strm2->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin); - file->Load(gc,strm2); - - env->LoadFile(gc, file); + TFile *file = TFile::Create(ls); - - } + strm2->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin); + file->Load(gc, strm2); - + env->LoadFile(gc, file); + } } } return (int64_t)0; } -} \ No newline at end of file +} // namespace Tesses::CrossLang::Programs \ No newline at end of file diff --git a/src/program_lib/crosslangvm.cpp b/src/program_lib/crosslangvm.cpp index 96e0da3..75f114c 100644 --- a/src/program_lib/crosslangvm.cpp +++ b/src/program_lib/crosslangvm.cpp @@ -1,61 +1,58 @@ #include "CrossLang.hpp" using namespace Tesses::Framework; namespace Tesses::CrossLang::Programs { - TObject CrossLangVM(GCList& ls,TRootEnvironment* env, std::vector& argv) - { - if(argv.size() < 2) - { - std::cout << "USAGE: " << (argv.empty() ? (std::string)"crossvm" : argv[0]) << " " << std::endl; - return 1; - } - - env->LoadFileWithDependencies(ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(argv[1])); - - if(env->HasVariable("WebAppMain")) - { - Args args(argv); - int port = 4206; - for(auto& item : args.options) - { - if(item.first == "port") - { - port = std::stoi(item.second); - } - } - - env->EnsureDictionary(ls.GetGC(),"Net")->SetValue("WebServerPort", (int64_t)port); - TList* args2 = TList::Create(ls); - for(auto& item : args.positional) - { - args2->Add(item); - } - - auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2}); - auto svr2 = Tesses::CrossLang::ToHttpServer(ls.GetGC(),res); - if(svr2 == nullptr) return 1; - Tesses::Framework::Http::HttpServer svr(port,svr2); - svr.StartAccepting(); - TF_RunEventLoop(); - TDictionary* _dict; - TClassObject* _co; - if(GetObjectHeap(res,_dict)) - { - _dict->CallMethod(ls,"Close",{}); - } - if(GetObjectHeap(res,_co)) - { - _co->CallMethod(ls,"","Close",{}); - } - TF_Quit(); - return 0; - } - else { - TList* args = TList::Create(ls); - for(size_t arg=1;argAdd(std::string(argv[arg])); - - return env->CallFunctionWithFatalError(ls,"main",{args}); - - } +TObject CrossLangVM(GCList &ls, TRootEnvironment *env, + std::vector &argv) { + if (argv.size() < 2) { + std::cout << "USAGE: " + << (argv.empty() ? (std::string) "crossvm" : argv[0]) + << " " << std::endl; + return 1; } -} \ No newline at end of file + + env->LoadFileWithDependencies( + ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, + Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(argv[1])); + + if (env->HasVariable("WebAppMain")) { + Args args(argv); + int port = 4206; + for (auto &item : args.options) { + if (item.first == "port") { + port = std::stoi(item.second); + } + } + + env->EnsureDictionary(ls.GetGC(), "Net") + ->SetValue("WebServerPort", (int64_t)port); + TList *args2 = TList::Create(ls); + for (auto &item : args.positional) { + args2->Add(item); + } + + auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2}); + auto svr2 = Tesses::CrossLang::ToHttpServer(ls.GetGC(), res); + if (svr2 == nullptr) + return 1; + Tesses::Framework::Http::HttpServer svr(port, svr2); + svr.StartAccepting(); + TF_RunEventLoop(); + TDictionary *_dict; + TClassObject *_co; + if (GetObjectHeap(res, _dict)) { + _dict->CallMethod(ls, "Close", {}); + } + if (GetObjectHeap(res, _co)) { + _co->CallMethod(ls, "", "Close", {}); + } + TF_Quit(); + return 0; + } else { + TList *args = TList::Create(ls); + for (size_t arg = 1; arg < argv.size(); arg++) + args->Add(std::string(argv[arg])); + + return env->CallFunctionWithFatalError(ls, "main", {args}); + } +} +} // namespace Tesses::CrossLang::Programs \ No newline at end of file diff --git a/src/programs/crossarchivecreate.cpp b/src/programs/crossarchivecreate.cpp deleted file mode 100644 index b20d00c..0000000 --- a/src/programs/crossarchivecreate.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "CrossLang.hpp" - -int main(int argc, char** argv) -{ - std::vector args(argc); - for(int i = 0; i < argc; i++) - args[i] = argv[i]; - return (int)Tesses::CrossLang::Programs::CrossArchiveCreate(args); -} \ No newline at end of file diff --git a/src/programs/crossarchiveextract.cpp b/src/programs/crossarchiveextract.cpp deleted file mode 100644 index dc24378..0000000 --- a/src/programs/crossarchiveextract.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "CrossLang.hpp" - -int main(int argc, char** argv) -{ - std::vector args(argc); - for(int i = 0; i < argc; i++) - args[i] = argv[i]; - return (int)Tesses::CrossLang::Programs::CrossArchiveExtract(args); -} \ No newline at end of file diff --git a/src/programs/crosslang.cpp b/src/programs/crosslang.cpp deleted file mode 100644 index 0365c7c..0000000 --- a/src/programs/crosslang.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "CrossLang.hpp" - -using namespace Tesses::Framework; -using namespace Tesses::CrossLang; -using namespace Tesses::Framework::Filesystem; -int main(int argc, char** argv) -{ - TF_InitWithConsole(); - if(argc > 0) - TF_AllowPortable(argv[0]); - std::shared_ptr gc= std::make_shared(); - gc->Start(); - GCList ls(gc); - - - std::vector args(argc); - for(int i = 0; i < argc; i++) - args[i] = argv[i]; - auto res = Programs::CrossLangShell(ls, args); - - int64_t myi64; - if(GetObject(res,myi64)) - return (int)myi64; - return 0; -} \ No newline at end of file diff --git a/src/programs/crosslangcompiler.cpp b/src/programs/crosslangcompiler.cpp deleted file mode 100644 index d57f0d7..0000000 --- a/src/programs/crosslangcompiler.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "CrossLang.hpp" -#include -#include -#include -#include -using namespace Tesses::Framework; -using namespace Tesses::CrossLang; -using namespace Tesses::Framework::Filesystem; -int main(int argc, char** argv) -{ - TF_InitWithConsole(); - if(argc > 0) - TF_AllowPortable(argv[0]); - - - - std::vector args(argc); - for(int i = 0; i < argc; i++) - args[i] = argv[i]; - Programs::CrossLangCompiler(args); - - return 0; -} \ No newline at end of file diff --git a/src/programs/crosslangdump.cpp b/src/programs/crosslangdump.cpp deleted file mode 100644 index ae4d10b..0000000 --- a/src/programs/crosslangdump.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "CrossLang.hpp" -#include -#include -#include -#include -using namespace Tesses::Framework; -using namespace Tesses::CrossLang; -using namespace Tesses::Framework::Filesystem; -int main(int argc, char** argv) -{ - TF_InitWithConsole(); - if(argc > 0) - TF_AllowPortable(argv[0]); - - for(int i = 1; i < argc; i++) - { - VFSPath path(argv[i]); - if(LocalFS->FileExists(path)) - { - std::cout << "File: " << path.ToString() << std::endl; - auto strm = LocalFS->OpenFile(path, "rb"); - Programs::CrossLangDump(strm); - } - else { - std::cout << "File: " << path.ToString() << " does not exist." << std::endl; - } - } -} \ No newline at end of file diff --git a/src/programs/crosslanginterperter.cpp b/src/programs/crosslanginterperter.cpp deleted file mode 100644 index 9788d00..0000000 --- a/src/programs/crosslanginterperter.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "CrossLang.hpp" -#include -#include -#include -#include -using namespace Tesses::Framework; -using namespace Tesses::CrossLang; -using namespace Tesses::Framework::Filesystem; - -int main(int argc, char** argv) -{ - TF_InitWithConsole(); - if(argc > 0) - TF_AllowPortable(argv[0]); - std::shared_ptr gc= std::make_shared(); - gc->Start(); - GCList ls(gc); - TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls)); - TStd::RegisterStd(gc,env); - - std::vector args(argc); - for(int i = 0; i < argc; i++) - args[i] = argv[i]; - auto res = Programs::CrossLangInterperter(ls, env, args); - - int64_t myi64; - if(GetObject(res,myi64)) - return (int)myi64; - return 0; -} diff --git a/src/programs/crosslangvm.cpp b/src/programs/crosslangvm.cpp deleted file mode 100644 index bf35b58..0000000 --- a/src/programs/crosslangvm.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "CrossLang.hpp" -#include -#include -#include -#include -using namespace Tesses::Framework; -using namespace Tesses::CrossLang; -using namespace Tesses::Framework::Filesystem; - -int main(int argc, char** argv) -{ - TF_InitWithConsole(); - if(argc > 0) - TF_AllowPortable(argv[0]); - std::shared_ptr gc= std::make_shared(); - gc->Start(); - GCList ls(gc); - TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls)); - TStd::RegisterStd(gc,env); - - std::vector args(argc); - for(int i = 0; i < argc; i++) - args[i] = argv[i]; - auto res = Programs::CrossLangVM(ls, env, args); - - int64_t myi64; - if(GetObject(res,myi64)) - return (int)myi64; - return 0; -} diff --git a/src/programs/slim.cpp b/src/programs/slim.cpp index d9b861c..838d77c 100644 --- a/src/programs/slim.cpp +++ b/src/programs/slim.cpp @@ -4,173 +4,190 @@ using namespace Tesses::Framework; using namespace Tesses::CrossLang; using namespace Tesses::Framework::Filesystem; -int main(int argc, char** argv) -{ - //crosslang crossint - //crosslang - //crosslang ... - - std::string programName = "crosslang"; +int main(int argc, char **argv) { TF_InitWithConsole(); - if(argc > 0) - { - TF_AllowPortable(argv[0]); - Tesses::Framework::Filesystem::VFSPath path=(std::string)argv[0]; - path.RemoveExtension(); - programName = path.GetFileName(); - } + TF_AllowPortable(); std::vector args(argc); - for(int i = 0; i < argc; i++) + + for (int i = 0; i < argc; i++) args[i] = argv[i]; - if(programName == "crossint") - { - - int64_t myi64=0; - - std::shared_ptr gc= std::make_shared(); + + auto execName = TF_GetExecutableName(); + + if (!execName.empty()) { + Tesses::Framework::Filesystem::VFSPath execPath = execName; + if (execPath.HasExtension()) { + execPath.RemoveExtension(); + } + + if (Tesses::Framework::Filesystem::LocalFS->FileExists(execPath + + ".crvm")) { + + if (args.empty()) + args.push_back(execPath.GetFileName()); + + auto crvmFile = execPath + ".crvm"; + + args.insert(args.begin() + 1, crvmFile.ToString()); + int64_t myi64 = 0; + + args.erase(args.begin()); + std::shared_ptr gc = std::make_shared(); gc->Start(); GCList ls(gc); - TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls)); - TStd::RegisterStd(gc,env); - auto res= Programs::CrossLangInterperter(ls, env, args); - - GetObject(res,myi64); - - + TRootEnvironment *env = + TRootEnvironment::Create(ls, TDictionary::Create(ls)); + TStd::RegisterStd(gc, env); + auto res = Programs::CrossLangVM(ls, env, args); + GetObject(res, myi64); return (int)myi64; } - else if(programName == "crossc") - { - Programs::CrossLangCompiler(args); - return 0; - } - else if(programName == "crossarchivecreate") - { - Programs::CrossArchiveCreate(args); - return 0; - } - else if(programName == "crossarchiveextract") - { - Programs::CrossArchiveExtract(args); - return 0; - } - else if(programName == "crossdump") - { - for(size_t i = 1; i < args.size(); i++) - { - VFSPath path = args[i]; - if(LocalFS->FileExists(path)) - { - std::cout << "File: " << path.ToString() << std::endl; - auto strm = LocalFS->OpenFile(path, "rb"); - Programs::CrossLangDump(strm); - } - else { - std::cout << "File: " << path.ToString() << " does not exist." << std::endl; - } - } - return 0; - } - else if(programName == "crossvm") - { - std::shared_ptr gc= std::make_shared(); - gc->Start(); - int64_t myi64=0; - - - GCList ls(gc); - TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls)); - TStd::RegisterStd(gc,env); - auto res= Programs::CrossLangVM(ls, env, args); - GetObject(res,myi64); - - return (int)myi64; - } - else if(args.size() > 1) - { - if(args[1] == "crossint") - { - int64_t myi64=0; + if (args.size() > 1) { + if (args[1] == "--help") { + if (!Tesses::Framework::Filesystem::LocalFS->FileExists( + GetCrossLangConfigDir() / "Shell" / "Shell.crvm")) { + Console::WriteLine(args[0] + " COMMAND"); + Console::WriteLine("COMMANDS:"); + Console::WriteLine( + "int: interperter, used to be crossint"); + Console::WriteLine( + "c: the compiler, used to be crossc"); + Console::WriteLine("archivecreate: create archives, used to " + "be crossarchivecreate"); + Console::WriteLine("archiveextract: extract archives, used to " + "be crossarchiveextract"); + Console::WriteLine("thumbnailer: create thumbnails on " + "freedesktop, used to be crossthumbnailer"); + Console::WriteLine("dump: dump metadata about crvm " + "file, used to be crossdump"); + Console::WriteLine("vm: interpert bytecode file, " + "used to be crossvm"); + Console::WriteLine("update-shell: update the shell"); + Console::WriteLine( + "configdir: print the config directory"); + + Console::WriteLine(""); + Console::WriteLine("NOTE: As you don't have the shell, these " + "commands are limited"); + Console::WriteLine( + "NOTE: You can put this binary in a folder with a crvm " + "file, as long as filename matches (ignoring extension) it " + "will directly launch the crvm file"); + return 1; + } + } + if (args[1] == "int") { + int64_t myi64 = 0; args.erase(args.begin()); - std::shared_ptr gc= std::make_shared(); + std::shared_ptr gc = std::make_shared(); gc->Start(); GCList ls(gc); - TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls)); - TStd::RegisterStd(gc,env); - auto res= Programs::CrossLangInterperter(ls, env, args); + TRootEnvironment *env = + TRootEnvironment::Create(ls, TDictionary::Create(ls)); + TStd::RegisterStd(gc, env); + auto res = Programs::CrossLangInterperter(ls, env, args); + + GetObject(res, myi64); - GetObject(res,myi64); - return (int)myi64; - } - else if(args[1] == "crossc") - { + } else if (args[1] == "c") { args.erase(args.begin()); Programs::CrossLangCompiler(args); return 0; - } - else if(args[1] == "crossarchivecreate") - { + } else if (args[1] == "archivecreate") { args.erase(args.begin()); Programs::CrossArchiveCreate(args); return 0; - } - else if(args[1] == "crossarchiveextract") - { + } else if (args[1] == "archiveextract") { args.erase(args.begin()); Programs::CrossArchiveExtract(args); return 0; - } - else if(args[1] == "crossdump") - { - for(size_t i = 2; i < args.size(); i++) - { - VFSPath path = args[i]; - if(LocalFS->FileExists(path)) - { - std::cout << "File: " << path.ToString() << std::endl; - auto strm = LocalFS->OpenFile(path, "rb"); - Programs::CrossLangDump(strm); + } else if (args[1] == "thumbnailer") { + Tesses::Framework::Filesystem::VFSPath execPath = + TF_GetExecutableName(); + auto emptyThumb = execPath.GetParent().GetParent() / "share" / + "icons" / "crosslang.png"; + if (argc < 4) { + std::cout << "USAGE: " << argv[0] + << " thumbnailer CRVMFILE NEWPNG" << std::endl; + return 1; + } + + std::string crvm = argv[2]; + std::string png = argv[3]; + + if (Tesses::Framework::Filesystem::LocalFS->FileExists(crvm)) { + + Tesses::CrossLang::TFile file; + auto f = Tesses::Framework::Filesystem::LocalFS->OpenFile(crvm, + "rb"); + + file.Load(nullptr, f); + + if (file.icon >= 0 && file.icon < file.resources.size()) { + auto f2 = Tesses::Framework::Filesystem::LocalFS->OpenFile( + png, "wb"); + if (f2 != nullptr) { + auto &icon = file.resources[file.icon]; + f2->WriteBlock(icon.data(), icon.size()); + } + return 0; } - else { - std::cout << "File: " << path.ToString() << " does not exist." << std::endl; + } + if (Tesses::Framework::Filesystem::LocalFS->FileExists( + emptyThumb)) { + auto src = Tesses::Framework::Filesystem::LocalFS->OpenFile( + emptyThumb, "rb"); + auto dest = + Tesses::Framework::Filesystem::LocalFS->OpenFile(png, "wb"); + if (src != nullptr && dest != nullptr) { + src->CopyTo(dest); } } return 0; - } - else if(args[1] == "crossvm") - { - int64_t myi64=0; + } else if (args[1] == "dump") { + for (size_t i = 2; i < args.size(); i++) { + VFSPath path = args[i]; + if (LocalFS->FileExists(path)) { + std::cout << "File: " << path.ToString() << std::endl; + auto strm = LocalFS->OpenFile(path, "rb"); + Programs::CrossLangDump(strm); + } else { + std::cout << "File: " << path.ToString() + << " does not exist." << std::endl; + } + } + return 0; + } else if (args[1] == "vm") { + int64_t myi64 = 0; args.erase(args.begin()); - std::shared_ptr gc= std::make_shared(); + std::shared_ptr gc = std::make_shared(); gc->Start(); GCList ls(gc); - TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls)); - TStd::RegisterStd(gc,env); - auto res= Programs::CrossLangVM(ls, env, args); - GetObject(res,myi64); - + TRootEnvironment *env = + TRootEnvironment::Create(ls, TDictionary::Create(ls)); + TStd::RegisterStd(gc, env); + auto res = Programs::CrossLangVM(ls, env, args); + GetObject(res, myi64); return (int)myi64; } } { - int64_t myi64=0; - std::shared_ptr gc= std::make_shared(); + int64_t myi64 = 0; + std::shared_ptr gc = std::make_shared(); gc->Start(); - GCList ls(gc); - auto res= Programs::CrossLangShell(ls, args); + GCList ls(gc); + auto res = Programs::CrossLangShell(ls, args); - GetObject(res,myi64); + GetObject(res, myi64); - - return (int)myi64; } } diff --git a/src/runtime_methods/class.cpp b/src/runtime_methods/class.cpp index 3427e3c..80dce4e 100644 --- a/src/runtime_methods/class.cpp +++ b/src/runtime_methods/class.cpp @@ -1,287 +1,255 @@ #include "CrossLang.hpp" +namespace Tesses::CrossLang { +static TList *VectorOfStringToList(GCList &ls, std::vector &strs) { + TList *list = TList::Create(ls); + ls.GetGC()->BarrierBegin(); + for (auto &item : strs) + list->Add(item); + ls.GetGC()->BarrierEnd(); + return list; +} +static TList *EntriesToList(GCList &ls, std::vector &ents) { + TList *list = TList::Create(ls); + ls.GetGC()->BarrierBegin(); + for (auto &item : ents) { + std::string modifier = "public"; + switch (item.modifier) { + case TClassModifier::Public: + modifier = "public"; + break; + case TClassModifier::Private: + modifier = "private"; + break; + case TClassModifier::Protected: + modifier = "protected"; + break; + case TClassModifier::Static: + modifier = "static"; + break; + } -namespace Tesses::CrossLang -{ - static TList* VectorOfStringToList(GCList& ls, std::vector& strs) - { - TList* list = TList::Create(ls); - ls.GetGC()->BarrierBegin(); - for(auto& item : strs) - list->Add(item); - ls.GetGC()->BarrierEnd(); - return list; + list->Add(TDictionary::Create( + ls, + {TDItem("Name", item.name), TDItem("IsAbstract", item.isAbstract), + TDItem("IsFunction", item.isFunction), + TDItem("Documentation", item.documentation), + TDItem("ChunkId", (int64_t)item.chunkId), + TDItem("Arguments", VectorOfStringToList(ls, item.args)), + TDItem("Modifier", modifier)})); } - static TList* EntriesToList(GCList& ls, std::vector& ents) - { - TList* list=TList::Create(ls); - ls.GetGC()->BarrierBegin(); - for(auto& item : ents) - { - std::string modifier = "public"; - switch(item.modifier) - { - case TClassModifier::Public: - modifier = "public"; - break; - case TClassModifier::Private: - modifier = "private"; - break; - case TClassModifier::Protected: - modifier = "protected"; - break; - case TClassModifier::Static: - modifier = "static"; - break; - } - - list->Add(TDictionary::Create(ls,{ - TDItem("Name",item.name), - TDItem("IsAbstract",item.isAbstract), - TDItem("IsFunction",item.isFunction), - TDItem("Documentation",item.documentation), - TDItem("ChunkId",(int64_t)item.chunkId), - TDItem("Arguments",VectorOfStringToList(ls,item.args)), - TDItem("Modifier",modifier) - })); + ls.GetGC()->BarrierEnd(); + return list; +} +static TList *ClassInstanceToList(GCList &ls, TClassObject *co) { + TList *list = TList::Create(ls); + ls.GetGC()->BarrierBegin(); + for (auto &item : co->entries) { + if (item.modifier == TClassModifier::Public) { + list->Add(TDictionary::Create( + ls, + {TDItem("Name", item.name), TDItem("IsFunction", !item.canSet), + TDItem("Owner", item.owner), TDItem("Value", item.value)})); } - ls.GetGC()->BarrierEnd(); - return list; } - static TList* ClassInstanceToList(GCList& ls, TClassObject* co) - { - TList* list=TList::Create(ls); - ls.GetGC()->BarrierBegin(); - for(auto& item : co->entries) - { - if(item.modifier == TClassModifier::Public) - { - list->Add(TDictionary::Create(ls, { - TDItem( - "Name", item.name - ), - TDItem( - "IsFunction", !item.canSet - ), - TDItem( - "Owner", item.owner - ), - TDItem( - "Value", item.value - ) - })); - } - } - ls.GetGC()->BarrierEnd(); - return list; - } - TObject GetClassInfo(GCList& ls,TFile* f, uint32_t index) - { - return TDictionary::Create(ls,{ - TDItem("Name", JoinPeriod(f->classes.at(index).name)), - TDItem("NameParts",VectorOfStringToList(ls,f->classes.at(index).name)), - TDItem("Inherits", JoinPeriod(f->classes.at(index).inherits)), - TDItem("InheritsParts",VectorOfStringToList(ls,f->classes.at(index).inherits)), - TDItem("Documentation",f->classes.at(index).documentation), - TDItem("Entries",EntriesToList(ls,f->classes.at(index).entry)) - }); - } - static TObject Class_CreateInstance(TRootEnvironment* env,GCList& ls, std::vector args) - { - TList* args_ls; - if(!GetArgumentHeap(args,1,args_ls)) return nullptr; - TList* list; - TClassObject* obj; - std::string str; - if(GetArgumentHeap(args,0,list)) - { - std::vector clsName; - for(int64_t i = 0; i < list->Count(); i++) - { - auto o = list->Get(i); - if(GetObject(o,str)) clsName.push_back(str); - } - for(auto& item : env->classes) - { - auto& f=item.first->classes.at(item.second); - - if(f.name.size() != clsName.size()) continue; - - bool found=true; - for(size_t i = 0; i < f.name.size(); i++) - if(f.name[i] != clsName[i]) - { - found=false; - break; - } - if(found) - { - return TClassObject::Create(ls,item.first,item.second,env,args_ls->items); - } - else - continue; - } - } - else if(GetArgument(args,0,str)) - { - std::vector clsName=Tesses::Framework::Http::HttpUtils::SplitString(str,"."); - for(auto& item : env->classes) - { - auto& f=item.first->classes.at(item.second); - - if(f.name.size() != clsName.size()) continue; - - bool found=true; - for(size_t i = 0; i < f.name.size(); i++) - if(f.name[i] != clsName[i]) - { - found=false; - break; - } - if(found) - { - return TClassObject::Create(ls,item.first,item.second,env,args_ls->items); - - } - else - continue; - } - } + ls.GetGC()->BarrierEnd(); + return list; +} +TObject GetClassInfo(GCList &ls, TFile *f, uint32_t index) { + return TDictionary::Create( + ls, {TDItem("Name", JoinPeriod(f->classes.at(index).name)), + TDItem("NameParts", + VectorOfStringToList(ls, f->classes.at(index).name)), + TDItem("Inherits", JoinPeriod(f->classes.at(index).inherits)), + TDItem("InheritsParts", + VectorOfStringToList(ls, f->classes.at(index).inherits)), + TDItem("Documentation", f->classes.at(index).documentation), + TDItem("Entries", EntriesToList(ls, f->classes.at(index).entry))}); +} +static TObject Class_CreateInstance(TRootEnvironment *env, GCList &ls, + std::vector args) { + TList *args_ls; + if (!GetArgumentHeap(args, 1, args_ls)) return nullptr; - } - static TObject Class_GetClassNames(TRootEnvironment* env,GCList& ls, std::vector args) - { - TList* list = TList::Create(ls); - ls.GetGC()->BarrierBegin(); - for(auto& item : env->classes) - { - list->Add(JoinPeriod(item.first->classes.at(item.second).name)); + TList *list; + TClassObject *obj; + std::string str; + if (GetArgumentHeap(args, 0, list)) { + std::vector clsName; + for (int64_t i = 0; i < list->Count(); i++) { + auto o = list->Get(i); + if (GetObject(o, str)) + clsName.push_back(str); } - ls.GetGC()->BarrierEnd(); - return list; - } - static TObject Class_GetInfo(TRootEnvironment* env,GCList& ls, std::vector args) - { - - TList* list; - TClassObject* obj; - std::string str; - if(GetArgumentHeap(args,0,list)) - { - std::vector clsName; - for(int64_t i = 0; i < list->Count(); i++) - { - auto o = list->Get(i); - if(GetObject(o,str)) clsName.push_back(str); - } - for(auto& item : env->classes) - { - auto& f=item.first->classes.at(item.second); - - if(f.name.size() != clsName.size()) continue; - - bool found=true; - for(size_t i = 0; i < f.name.size(); i++) - if(f.name[i] != clsName[i]) - { - found=false; - break; - } - if(found) - { - return GetClassInfo(ls,item.first,item.second); + for (auto &item : env->classes) { + auto &f = item.first->classes.at(item.second); + + if (f.name.size() != clsName.size()) + continue; + + bool found = true; + for (size_t i = 0; i < f.name.size(); i++) + if (f.name[i] != clsName[i]) { + found = false; + break; } - else - continue; - } + if (found) { + return TClassObject::Create(ls, item.first, item.second, env, + args_ls->items); + } else + continue; } - else if(GetArgument(args,0,str)) - { - std::vector clsName=Tesses::Framework::Http::HttpUtils::SplitString(str,"."); - for(auto& item : env->classes) - { - auto& f=item.first->classes.at(item.second); - - if(f.name.size() != clsName.size()) continue; - - bool found=true; - for(size_t i = 0; i < f.name.size(); i++) - if(f.name[i] != clsName[i]) - { - found=false; - break; - } - if(found) - { - return GetClassInfo(ls,item.first,item.second); + } else if (GetArgument(args, 0, str)) { + std::vector clsName = + Tesses::Framework::Http::HttpUtils::SplitString(str, "."); + for (auto &item : env->classes) { + auto &f = item.first->classes.at(item.second); + + if (f.name.size() != clsName.size()) + continue; + + bool found = true; + for (size_t i = 0; i < f.name.size(); i++) + if (f.name[i] != clsName[i]) { + found = false; + break; } - else - continue; - } - } - else if(GetArgumentHeap(args,0,obj)) - { - return GetClassInfo(ls,obj->file,obj->classIndex); - } + if (found) { + return TClassObject::Create(ls, item.first, item.second, env, + args_ls->items); - return nullptr; + } else + continue; + } } - void TStd::RegisterClass(std::shared_ptr gc, TRootEnvironment* env) - { - GCList ls(gc); - env->permissions.canRegisterClass=true; - TDictionary* cls= env->EnsureDictionary(gc, "Class"); - gc->BarrierBegin(); - - TExternalMethod* ext = TExternalMethod::Create(ls ,"Get the class info",{"classInstanceOrClassName"},[env](GCList& ls, std::vector args)->TObject { - return Class_GetInfo(env,ls,args); - }); - ext->watch.push_back(env); - - cls->SetValue("GetInfo",ext); + return nullptr; +} +static TObject Class_GetClassNames(TRootEnvironment *env, GCList &ls, + std::vector args) { + TList *list = TList::Create(ls); + ls.GetGC()->BarrierBegin(); + for (auto &item : env->classes) { + list->Add(JoinPeriod(item.first->classes.at(item.second).name)); + } + ls.GetGC()->BarrierEnd(); + return list; +} +static TObject Class_GetInfo(TRootEnvironment *env, GCList &ls, + std::vector args) { - ext = TExternalMethod::Create(ls ,"Get the class names",{},[env](GCList& ls, std::vector args)->TObject { - return Class_GetClassNames(env,ls,args); - }); - ext->watch.push_back(env); - - cls->SetValue("GetClassNames",ext); - ext = TExternalMethod::Create(ls ,"Create an instance of class",{"name","args"},[env](GCList& ls, std::vector args)->TObject { - return Class_CreateInstance(env,ls,args); - }); - ext->watch.push_back(env); - - cls->SetValue("CreateInstance",ext); - cls->DeclareFunction(gc,"Name","Get class name via instance",{"instance"},[](GCList& ls, std::vector args)->TObject { - TClassObject* cls; - if(GetArgumentHeap(args,0,cls)) - { - return cls->name; - } - return ""; - }); + TList *list; + TClassObject *obj; + std::string str; + if (GetArgumentHeap(args, 0, list)) { + std::vector clsName; + for (int64_t i = 0; i < list->Count(); i++) { + auto o = list->Get(i); + if (GetObject(o, str)) + clsName.push_back(str); + } + for (auto &item : env->classes) { + auto &f = item.first->classes.at(item.second); + if (f.name.size() != clsName.size()) + continue; - cls->DeclareFunction(gc, "GetInstanceInfo", "Get the instance specific info, including current values", {}, [](GCList& ls, std::vector args)->TObject { - TClassObject* co; - if(GetArgumentHeap(args, 0, co)) - { + bool found = true; + for (size_t i = 0; i < f.name.size(); i++) + if (f.name[i] != clsName[i]) { + found = false; + break; + } + if (found) { + return GetClassInfo(ls, item.first, item.second); + } else + continue; + } + } else if (GetArgument(args, 0, str)) { + std::vector clsName = + Tesses::Framework::Http::HttpUtils::SplitString(str, "."); + for (auto &item : env->classes) { + auto &f = item.first->classes.at(item.second); + + if (f.name.size() != clsName.size()) + continue; + + bool found = true; + for (size_t i = 0; i < f.name.size(); i++) + if (f.name[i] != clsName[i]) { + found = false; + break; + } + if (found) { + return GetClassInfo(ls, item.first, item.second); + } else + continue; + } + } else if (GetArgumentHeap(args, 0, obj)) { + return GetClassInfo(ls, obj->file, obj->classIndex); + } + + return nullptr; +} +void TStd::RegisterClass(std::shared_ptr gc, TRootEnvironment *env) { + GCList ls(gc); + env->permissions.canRegisterClass = true; + TDictionary *cls = env->EnsureDictionary(gc, "Class"); + gc->BarrierBegin(); + + TExternalMethod *ext = TExternalMethod::Create( + ls, "Get the class info", {"classInstanceOrClassName"}, + [env](GCList &ls, std::vector args) -> TObject { + return Class_GetInfo(env, ls, args); + }); + ext->watch.push_back(env); + + cls->SetValue("GetInfo", ext); + + ext = TExternalMethod::Create( + ls, "Get the class names", {}, + [env](GCList &ls, std::vector args) -> TObject { + return Class_GetClassNames(env, ls, args); + }); + ext->watch.push_back(env); + + cls->SetValue("GetClassNames", ext); + ext = TExternalMethod::Create( + ls, "Create an instance of class", {"name", "args"}, + [env](GCList &ls, std::vector args) -> TObject { + return Class_CreateInstance(env, ls, args); + }); + ext->watch.push_back(env); + + cls->SetValue("CreateInstance", ext); + cls->DeclareFunction(gc, "Name", "Get class name via instance", + {"instance"}, + [](GCList &ls, std::vector args) -> TObject { + TClassObject *cls; + if (GetArgumentHeap(args, 0, cls)) { + return cls->name; + } + return ""; + }); + + cls->DeclareFunction( + gc, "GetInstanceInfo", + "Get the instance specific info, including current values", {}, + [](GCList &ls, std::vector args) -> TObject { + TClassObject *co; + if (GetArgumentHeap(args, 0, co)) { ls.GetGC()->BarrierBegin(); - auto res= TDictionary::Create(ls, - { - TDItem("Name", co->name), - TDItem("File", co->file), - TDItem("ClassIndex", (int64_t)co->classIndex), - TDItem("InheritList", VectorOfStringToList(ls, co->inherit_tree)), - TDItem("Entries", ClassInstanceToList(ls,co)) - } - ); + auto res = TDictionary::Create( + ls, {TDItem("Name", co->name), TDItem("File", co->file), + TDItem("ClassIndex", (int64_t)co->classIndex), + TDItem("InheritList", + VectorOfStringToList(ls, co->inherit_tree)), + TDItem("Entries", ClassInstanceToList(ls, co))}); ls.GetGC()->BarrierEnd(); return res; } return nullptr; }); - - gc->BarrierEnd(); - } -} \ No newline at end of file + + gc->BarrierEnd(); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/runtime_methods/console.cpp b/src/runtime_methods/console.cpp index 6aae55e..fdb9206 100644 --- a/src/runtime_methods/console.cpp +++ b/src/runtime_methods/console.cpp @@ -2,334 +2,237 @@ #include "CrossLang.hpp" #include -#if defined(GEKKO) || defined(__SWITCH__) || defined(_WIN32) -#undef CROSSLANG_ENABLE_TERMIOS -#endif - -#ifdef CROSSLANG_ENABLE_TERMIOS -#include -#include -#include -#endif namespace Tesses::CrossLang { - #ifdef CROSSLANG_ENABLE_TERMIOS - struct termios orig_termios; - static void disableRawMode() - { - tcsetattr(0, TCSAFLUSH, &orig_termios); - } - #endif - TObject Console_getEcho(GCList& ls, std::vector args) - { - #ifdef CROSSLANG_ENABLE_TERMIOS - struct termios raw; - tcgetattr(0, &raw); - return (raw.c_lflag & ECHO) > 0; - - #endif - return false; - } - TObject Console_setEcho(GCList& ls, std::vector args) - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - bool cooked = std::get(args[0]); - #ifdef CROSSLANG_ENABLE_TERMIOS - struct termios raw; - tcgetattr(0, &raw); - if(cooked) - { - raw.c_lflag |= ECHO; - } - else - { - raw.c_lflag &= ~(ECHO); - } - - tcsetattr(0, TCSAFLUSH, &raw); - #endif - return cooked; - } +TObject Console_getIsTTY(GCList &ls, std::vector args) { + + return Tesses::Framework::Console::IsTTY(); +} +TObject Console_getEcho(GCList &ls, std::vector args) { + + return Tesses::Framework::Console::GetEcho(); +} +TObject Console_setEcho(GCList &ls, std::vector args) { + if (args.size() == 1 && std::holds_alternative(args[0])) { + bool cooked = std::get(args[0]); + Tesses::Framework::Console::SetEcho(cooked); + return cooked; + } + return Undefined(); +} +TObject Console_getCanonical(GCList &ls, std::vector args) { + return Tesses::Framework::Console::GetCanonical(); +} +TObject Console_setCanonical(GCList &ls, std::vector args) { + if (args.size() == 1 && std::holds_alternative(args[0])) { + bool cooked = std::get(args[0]); + Tesses::Framework::Console::SetCanonical(cooked); + return cooked; + } + return Undefined(); +} +TObject Console_getSignals(GCList &ls, std::vector args) { + return Tesses::Framework::Console::GetSignals(); +} +TObject Console_setSignals(GCList &ls, std::vector args) { + if (args.size() == 1 && std::holds_alternative(args[0])) { + bool cooked = std::get(args[0]); + Tesses::Framework::Console::SetSignals(cooked); + return cooked; + } + return Undefined(); +} + +TObject Console_Read(GCList &ls, std::vector args) { + return (int64_t)Tesses::Framework::Console::Read(); +} +TObject Console_ReadLine(GCList &ls, std::vector args) { + return Tesses::Framework::Console::ReadLine(); +} +TObject Console_ReadPassword(GCList &ls, std::vector args) { + return Tesses::Framework::Console::ReadPassword(); +} +TObject Console_Write(GCList &ls, std::vector args) { + if (args.size() < 1) { return Undefined(); } - TObject Console_getCanonical(GCList& ls, std::vector args) - { - #ifdef CROSSLANG_ENABLE_TERMIOS - struct termios raw; - tcgetattr(0, &raw); - return (raw.c_lflag & ICANON) > 0; - - #endif - return false; - } - TObject Console_setCanonical(GCList& ls, std::vector args) - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - bool cooked = std::get(args[0]); - #ifdef CROSSLANG_ENABLE_TERMIOS - struct termios raw; - tcgetattr(0, &raw); - if(cooked) - { - raw.c_lflag |= ICANON; - } - else - { - raw.c_lflag &= ~(ICANON); - } - - tcsetattr(0, TCSAFLUSH, &raw); - - #endif - return cooked; - } - return Undefined(); - } - TObject Console_getSignals(GCList& ls, std::vector args) - { - #ifdef CROSSLANG_ENABLE_TERMIOS - struct termios raw; - tcgetattr(0, &raw); - return (raw.c_lflag & ISIG) > 0; - - #endif - return false; - } - TObject Console_setSignals(GCList& ls, std::vector args) - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - bool cooked = std::get(args[0]); - #ifdef CROSSLANG_ENABLE_TERMIOS - struct termios raw; - tcgetattr(0, &raw); - if(cooked) - { - raw.c_lflag |= ISIG; - } - else - { - raw.c_lflag &= ~(ISIG); - } - - tcsetattr(0, TCSAFLUSH, &raw); - - #endif - return cooked; - } - return Undefined(); - } - - TObject Console_Read(GCList& ls, std::vector args) - { - uint8_t byte; - std::cin.read((char*)&byte,1); - return std::cin.eof() ? (int64_t)-1 : (int64_t)byte; - } - TObject Console_ReadLine(GCList& ls, std::vector args) - { - std::string str; - std::getline(std::cin,str); - return str; - } - TObject Console_Write(GCList& ls, std::vector args) - { - if(args.size() < 1) - { - return Undefined(); - } - std::cout << ToString(ls.GetGC(),args[0]); - return Undefined(); - } - TObject Console_Fatal(GCList& ls, std::vector args) - { - if(args.size() < 1) - { - std::cout << "FATAL: " << std::endl; - exit(1); - } - std::cout << "FATAL: " << ToString(ls.GetGC(),args[0]) << std::endl; + Tesses::Framework::Console::Write(ToString(ls.GetGC(), args[0])); + return Undefined(); +} +TObject Console_Fatal(GCList &ls, std::vector args) { + if (args.size() < 1) { + Tesses::Framework::Console::ErrorLine("FATAL: "); exit(1); } - TObject Console_WriteLine(GCList& ls, std::vector args) - { - if(args.size() < 1) - { - std::cout << "\n"; - return Undefined(); - } - std::cout << ToString(ls.GetGC(),args[0]) << "\n"; - return Undefined(); - } - TObject Console_Error(GCList& ls, std::vector args) - { - if(args.size() < 1) - { - return Undefined(); - } - std::cerr << ToString(ls.GetGC(),args[0]); - return Undefined(); - } - TObject Console_ErrorLine(GCList& ls, std::vector args) - { - if(args.size() < 1) - { - std::cout << "\n"; - return Undefined(); - } - std::cerr << ToString(ls.GetGC(),args[0]) << "\n"; - return Undefined(); - } - TObject Console_getIn(GCList& ls, std::vector args) - { - return std::make_shared(stdin,false,"r",false); - } - - TObject Console_getOut(GCList& ls, std::vector args) - { - return std::make_shared(stdout,false,"w",false); - } - TObject Console_getError(GCList& ls, std::vector args) - { - return std::make_shared(stderr,false,"w",false); - } - TObject Console_Clear(GCList& ls, std::vector args) - { - //because I just really want a clear function - #if defined(_WIN32) - system("cls"); - #else - std::cout << "\x1b[2J\x1b[H" << std::flush; //because of wii and stuff (dont want to rely on clear command) - #endif - return Undefined(); - } - static void con_sz(int& w, int& h) - { - w = 0; - h = 0; - - - #if defined(_WIN32) - - #elif defined(CROSSLANG_ENABLE_TERMIOS) - if(!isatty(STDOUT_FILENO)) - return; - struct winsize ws; - if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) - { - w = ws.ws_col; - h = ws.ws_row; - } - #endif - } - - TObject Console_ProgressBar(GCList& ls, std::vector args) - { - //[=== ] 50% - bool showBar = true; - #if defined(CROSSLANG_ENABLE_TERMIOS) - if(!isatty(STDOUT_FILENO)) showBar=false; - #endif - int64_t progress = 0; - double pdbl = 0; - GetArgument(args,0,pdbl); - if(GetArgument(args,0,progress)) pdbl = progress / 100.0; - if(pdbl < 0) pdbl=0; - if(pdbl > 1) pdbl=1; - - std::cout << "\r"; - if(showBar) - { - int w,h; - con_sz(w,h); - - int totalBlocks = w - 10; - if(totalBlocks > 0) - { - std::cout << "[\033[0;32m"; - int i; - int off = pdbl * totalBlocks; - for(int i = 0; i < totalBlocks; i++) - { - if(i < off) - std::cout << "="; - else - std::cout << " "; - } - - std::cout << "\033[0m] "; - } - } - - std::cout << std::setw(3) << (int)(pdbl*100) << "%" << std::flush; - return Undefined(); - } - TObject Console_getSize(GCList& ls, std::vector args) - { - #if defined(CROSSLANG_ENABLE_TERMIOS) - if(!isatty(STDOUT_FILENO)) return nullptr; - #endif - int w, h; - con_sz(w,h); - TDictionary* dict = TDictionary::Create(ls,{ - TDItem("Width", (int64_t)w), - TDItem("Height",(int64_t)h) - }); - - return dict; - } - void TStd::RegisterConsole(std::shared_ptr gc,TRootEnvironment* env) - { - env->permissions.canRegisterConsole=true; - if(env->permissions.customConsole != nullptr) - { - gc->BarrierBegin(); - env->DeclareVariable("Console", env->permissions.customConsole ); - gc->BarrierEnd(); - return; - } - - #ifdef CROSSLANG_ENABLE_TERMIOS - tcgetattr(0, &orig_termios); - atexit(disableRawMode); - #endif - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - - dict->DeclareFunction(gc,"getEcho","Get whether terminal is echoing characters read",{},Console_getEcho); - dict->DeclareFunction(gc,"setEcho","Set whether terminal is echoing characters read",{"flag"},Console_setEcho); - dict->DeclareFunction(gc,"getCanonical","Get whether terminal is buffering line by line (true) or byte by byte (false)",{},Console_getCanonical); - dict->DeclareFunction(gc,"setCanonical","Set whether terminal is buffering line by line (true) or byte by byte (false)",{"flag"},Console_setCanonical); - dict->DeclareFunction(gc,"getSignals","Get whether terminal is sending signals for CTRL+C (true) or via read (false)",{},Console_getSignals); - dict->DeclareFunction(gc,"setSignals","Set whether terminal is sending signals for CTRL+C (true) or via read (false)",{"flag"},Console_setSignals); - dict->DeclareFunction(gc,"Clear", "Clear the console",{},Console_Clear); - dict->DeclareFunction(gc,"Read", "Reads a byte from stdin",{},Console_Read); - dict->DeclareFunction(gc,"ReadLine","Reads line from stdin",{},Console_ReadLine); - dict->DeclareFunction(gc,"Write","Write text \"text\" to stdout",{"text"},Console_Write); - dict->DeclareFunction(gc,"WriteLine","Write text \"text\" to stdout with new line",{"$text"},Console_WriteLine); - dict->DeclareFunction(gc,"Error", "Write text \"error\" to stderr",{"error"},Console_Error); - dict->DeclareFunction(gc,"ErrorLine","Write text \"error\" to stderr",{"$error"},Console_ErrorLine); - dict->DeclareFunction(gc,"ProgressBar","Draw progressbar", {}, Console_ProgressBar); - if(env->permissions.canRegisterEverything) - dict->DeclareFunction(gc,"Fatal","Stop the program with an optional error message",{"$text"},Console_Fatal); - dict->DeclareFunction(gc,"getIn","Get stdin Stream",{},Console_getIn); - dict->DeclareFunction(gc,"getOut","Get stdout Stream",{},Console_getOut); - dict->DeclareFunction(gc,"getError", "Get stderr Stream",{},Console_getError); - dict->DeclareFunction(gc, "getSize", "Get console size",{},Console_getSize); - gc->BarrierBegin(); - env->DeclareVariable("Console", dict); - auto _new = env->EnsureDictionary(gc,"New"); - _new->DeclareFunction(gc,"ConsoleReader","Read from console",{},[](GCList& ls,std::vector args)->TObject { - return std::make_shared(); - }); - _new->DeclareFunction(gc,"ConsoleWriter","Write to console",{"$isStderr"},[](GCList& ls,std::vector args)->TObject { - bool err; - if(GetArgument(args,0,err)) return std::make_shared(err); - return std::make_shared(); - }); - gc->BarrierEnd(); - } + Tesses::Framework::Console::ErrorLine("FATAL: " + + ToString(ls.GetGC(), args[0])); + exit(1); } +TObject Console_WriteLine(GCList &ls, std::vector args) { + if (args.size() < 1) { + Tesses::Framework::Console::WriteLineView(""); + return Undefined(); + } + Tesses::Framework::Console::WriteLine(ToString(ls.GetGC(), args[0])); + + return Undefined(); +} +TObject Console_Error(GCList &ls, std::vector args) { + if (args.size() < 1) { + return Undefined(); + } + Tesses::Framework::Console::Error(ToString(ls.GetGC(), args[0])); + return Undefined(); +} +TObject Console_ErrorLine(GCList &ls, std::vector args) { + if (args.size() < 1) { + Tesses::Framework::Console::ErrorLine(""); + return Undefined(); + } + Tesses::Framework::Console::ErrorLine(ToString(ls.GetGC(), args[0])); + + return Undefined(); +} +TObject Console_getIn(GCList &ls, std::vector args) { + return std::make_shared( + stdin, false, "r", false); +} + +TObject Console_getOut(GCList &ls, std::vector args) { + return std::make_shared( + stdout, false, "w", false); +} +TObject Console_getError(GCList &ls, std::vector args) { + return std::make_shared( + stderr, false, "w", false); +} +TObject Console_Clear(GCList &ls, std::vector args) { + Tesses::Framework::Console::Clear(); + return Undefined(); +} + +TObject Console_ProgressBar(GCList &ls, std::vector args) { + double dbl; + int64_t i64; + if (GetArgument(args, 0, i64)) { + Tesses::Framework::Console::ProgressBar((int)i64); + } else if (GetArgument(args, 0, dbl)) { + Tesses::Framework::Console::ProgressBar(dbl); + } + + return Undefined(); +} +TObject Console_getSize(GCList &ls, std::vector args) { + auto sz = Tesses::Framework::Console::GetSize(); + TDictionary *dict = + TDictionary::Create(ls, {TDItem("Width", (int64_t)sz.first), + TDItem("Height", (int64_t)sz.second)}); + + return dict; +} +TObject Console_List(GCList &ls, std::vector args) { + if (!args.empty()) { + GCList ls2(ls.GetGC()); + auto enumerator = TEnumerator::CreateFromObject(ls2, args[0]); + std::vector items; + + while (enumerator->MoveNext(ls2.GetGC())) { + auto item = enumerator->GetCurrent(ls2); + items.push_back(ToString(ls2.GetGC(), item)); + } + + return (int64_t)Tesses::Framework::Console::List(items); + } + return 0; +} +void TStd::RegisterConsole(std::shared_ptr gc, TRootEnvironment *env) { + env->permissions.canRegisterConsole = true; + if (env->permissions.customConsole != nullptr) { + gc->BarrierBegin(); + env->DeclareVariable("Console", env->permissions.customConsole); + gc->BarrierEnd(); + return; + } + + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); + dict->DeclareFunction( + gc, "getIsTTY", + "Get whether terminal is a terminal or just piped to file", {}, + Console_getIsTTY); + dict->DeclareFunction(gc, "getEcho", + "Get whether terminal is echoing characters read", {}, + Console_getEcho); + dict->DeclareFunction(gc, "setEcho", + "Set whether terminal is echoing characters read", + {"flag"}, Console_setEcho); + dict->DeclareFunction(gc, "getCanonical", + "Get whether terminal is buffering line by line " + "(true) or byte by byte (false)", + {}, Console_getCanonical); + dict->DeclareFunction(gc, "setCanonical", + "Set whether terminal is buffering line by line " + "(true) or byte by byte (false)", + {"flag"}, Console_setCanonical); + dict->DeclareFunction(gc, "getSignals", + "Get whether terminal is sending signals for CTRL+C " + "(true) or via read (false)", + {}, Console_getSignals); + dict->DeclareFunction(gc, "setSignals", + "Set whether terminal is sending signals for CTRL+C " + "(true) or via read (false)", + {"flag"}, Console_setSignals); + dict->DeclareFunction(gc, "Clear", "Clear the console", {}, Console_Clear); + dict->DeclareFunction(gc, "Read", "Reads a byte from stdin", {}, + Console_Read); + dict->DeclareFunction(gc, "ReadLine", "Reads line from stdin", {}, + Console_ReadLine); + dict->DeclareFunction(gc, "ReadPassword", "Reads password from stdin", {}, + Console_ReadPassword); + dict->DeclareFunction(gc, "Write", "Write text \"text\" to stdout", + {"text"}, Console_Write); + dict->DeclareFunction(gc, "WriteLine", + "Write text \"text\" to stdout with new line", + {"$text"}, Console_WriteLine); + dict->DeclareFunction(gc, "Error", "Write text \"error\" to stderr", + {"error"}, Console_Error); + dict->DeclareFunction(gc, "ErrorLine", "Write text \"error\" to stderr", + {"$error"}, Console_ErrorLine); + dict->DeclareFunction(gc, "ProgressBar", "Draw progressbar", {}, + Console_ProgressBar); + dict->DeclareFunction(gc, "List", "Draw list", {"itemsitterator"}, + Console_List); + if (env->permissions.canRegisterEverything) + dict->DeclareFunction(gc, "Fatal", + "Stop the program with an optional error message", + {"$text"}, Console_Fatal); + dict->DeclareFunction(gc, "getIn", "Get stdin Stream", {}, Console_getIn); + dict->DeclareFunction(gc, "getOut", "Get stdout Stream", {}, + Console_getOut); + dict->DeclareFunction(gc, "getError", "Get stderr Stream", {}, + Console_getError); + dict->DeclareFunction(gc, "getSize", "Get console size", {}, + Console_getSize); + gc->BarrierBegin(); + env->DeclareVariable("Console", dict); + auto _new = env->EnsureDictionary(gc, "New"); + _new->DeclareFunction( + gc, "ConsoleReader", "Read from console", {}, + [](GCList &ls, std::vector args) -> TObject { + return std::make_shared< + Tesses::Framework::TextStreams::ConsoleReader>(); + }); + _new->DeclareFunction( + gc, "ConsoleWriter", "Write to console", {"$isStderr"}, + [](GCList &ls, std::vector args) -> TObject { + bool err; + if (GetArgument(args, 0, err)) + return std::make_shared< + Tesses::Framework::TextStreams::ConsoleWriter>(err); + return std::make_shared< + Tesses::Framework::TextStreams::ConsoleWriter>(); + }); + gc->BarrierEnd(); +} +} // namespace Tesses::CrossLang #endif diff --git a/src/runtime_methods/crypto.cpp b/src/runtime_methods/crypto.cpp index 5336d30..de974a9 100644 --- a/src/runtime_methods/crypto.cpp +++ b/src/runtime_methods/crypto.cpp @@ -2,183 +2,173 @@ using namespace Tesses::Framework::Crypto; -namespace Tesses::CrossLang -{ - static TObject Crypto_RandomBytes(GCList& ls, std::vector args) - { - - int64_t size; - std::string personalStr; - if(GetArgument(args,0,size) && GetArgument(args,1,personalStr)) - { +namespace Tesses::CrossLang { +static TObject Crypto_RandomBytes(GCList &ls, std::vector args) { - std::vector bytes; - bytes.resize((size_t)size); - if(RandomBytes(bytes,personalStr)) - { - auto ba = TByteArray::Create(ls); - ba->data = bytes; - return ba; - } - return nullptr; - - + int64_t size; + std::string personalStr; + if (GetArgument(args, 0, size) && GetArgument(args, 1, personalStr)) { + + std::vector bytes; + bytes.resize((size_t)size); + if (RandomBytes(bytes, personalStr)) { + auto ba = TByteArray::Create(ls); + ba->data = bytes; + return ba; } return nullptr; } - static TObject Crypto_PBKDF2(GCList& ls, std::vector args) - { - std::string pass; - TByteArray* bArraySalt; - int64_t itterations; - int64_t keylength; - int64_t shanum; - if(GetArgument(args,0,pass) && GetArgumentHeap(args,1, bArraySalt) && GetArgument(args,2, itterations) && GetArgument(args,3,keylength) && GetArgument(args,4,shanum)) - { - ShaVersion version = VERSION_SHA384; - - switch(shanum) - { - case 1: - version = VERSION_SHA1; - break; - case 224: - version = VERSION_SHA224; - break; - case 256: - version = VERSION_SHA256; - break; - default: - case 384: - version = VERSION_SHA384; - break; - case 512: - version = VERSION_SHA512; - break; - } - - + return nullptr; +} +static TObject Crypto_PBKDF2(GCList &ls, std::vector args) { + std::string pass; + TByteArray *bArraySalt; + int64_t itterations; + int64_t keylength; + int64_t shanum; + if (GetArgument(args, 0, pass) && GetArgumentHeap(args, 1, bArraySalt) && + GetArgument(args, 2, itterations) && GetArgument(args, 3, keylength) && + GetArgument(args, 4, shanum)) { + ShaVersion version = VERSION_SHA384; - std::vector key; - key.resize((size_t)keylength); - - if(PBKDF2(key,pass,bArraySalt->data,(long)itterations,version)) - { - TByteArray* ba = TByteArray::Create(ls); - ba->data = key; - return ba; - } - + switch (shanum) { + case 1: + version = VERSION_SHA1; + break; + case 224: + version = VERSION_SHA224; + break; + case 256: + version = VERSION_SHA256; + break; + default: + case 384: + version = VERSION_SHA384; + break; + case 512: + version = VERSION_SHA512; + break; + } + + std::vector key; + key.resize((size_t)keylength); + + if (PBKDF2(key, pass, bArraySalt->data, (long)itterations, version)) { + TByteArray *ba = TByteArray::Create(ls); + ba->data = key; + return ba; } - return nullptr; } + return nullptr; +} +static TObject Crypto_Base64Encode(GCList &ls, std::vector args) { + TByteArray *byteArray; - static TObject Crypto_Base64Encode(GCList& ls, std::vector args) - { - TByteArray* byteArray; - - if(GetArgumentHeap(args,0,byteArray)) - { - return Tesses::Framework::Crypto::Base64_Encode(byteArray->data); - + if (GetArgumentHeap(args, 0, byteArray)) { + return Tesses::Framework::Crypto::Base64_Encode(byteArray->data); + } + return ""; +} +static TObject Crypto_Base64Decode(GCList &ls, std::vector args) { + std::string str; + if (GetArgument(args, 0, str)) { + TByteArray *bArray = TByteArray::Create(ls); + bArray->data = Tesses::Framework::Crypto::Base64_Decode(str); - } - return ""; - } - static TObject Crypto_Base64Decode(GCList& ls, std::vector args) - { - std::string str; - if(GetArgument(args,0,str)) - { - TByteArray* bArray = TByteArray::Create(ls); - bArray->data = Tesses::Framework::Crypto::Base64_Decode(str); + return bArray; + } + return nullptr; +} +void TStd::RegisterCrypto(std::shared_ptr gc, TRootEnvironment *env) { - return bArray; - - } - return nullptr; - } - void TStd::RegisterCrypto(std::shared_ptr gc,TRootEnvironment* env) - { + env->permissions.canRegisterCrypto = true; + if (!HaveCrypto()) + return; + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); + dict->DeclareFunction(gc, "PBKDF2", "Hash passwords with PBKDF2", + {"pass", "salt", "itterations", "keylen", "shanum"}, + Crypto_PBKDF2); + dict->DeclareFunction(gc, "RandomBytes", + "Create bytearray but with random bytes in it " + "instead of zeros (this uses mbedtls by the way)", + {"byteCount", "personalString"}, Crypto_RandomBytes); - env->permissions.canRegisterCrypto=true; - if(!HaveCrypto()) return; - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - dict->DeclareFunction(gc, "PBKDF2","Hash passwords with PBKDF2",{"pass","salt","itterations","keylen","shanum"},Crypto_PBKDF2); - dict->DeclareFunction(gc, "RandomBytes","Create bytearray but with random bytes in it instead of zeros (this uses mbedtls by the way)",{"byteCount","personalString"},Crypto_RandomBytes); - - dict->DeclareFunction(gc, "Base64Encode","Base64 encode",{"data"},Crypto_Base64Encode); - dict->DeclareFunction(gc, "Base64Decode","Base64 decode",{"str"},Crypto_Base64Decode); - dict->DeclareFunction(gc, "Sha1", "Hash with sha1 algorithm (please don't use sha1 unless you need to)",{"strm"}, [](GCList& ls, std::vector args)->TObject { - TByteArray* baSrc; + dict->DeclareFunction(gc, "Base64Encode", "Base64 encode", {"data"}, + Crypto_Base64Encode); + dict->DeclareFunction(gc, "Base64Decode", "Base64 decode", {"str"}, + Crypto_Base64Decode); + dict->DeclareFunction( + gc, "Sha1", + "Hash with sha1 algorithm (please don't use sha1 unless you need to)", + {"strm"}, [](GCList &ls, std::vector args) -> TObject { + TByteArray *baSrc; std::shared_ptr sho; - if(GetArgument(args, 0, sho)) - { + if (GetArgument(args, 0, sho)) { auto bytes = Sha1::ComputeHash(sho); auto ba = TByteArray::Create(ls); ba->data = bytes; return ba; } - if(GetArgumentHeap(args,0,baSrc)) - { - auto bytes = Sha1::ComputeHash(baSrc->data.data(), baSrc->data.size()); + if (GetArgumentHeap(args, 0, baSrc)) { + auto bytes = + Sha1::ComputeHash(baSrc->data.data(), baSrc->data.size()); auto ba = TByteArray::Create(ls); ba->data = bytes; return ba; } return Undefined(); }); - dict->DeclareFunction(gc, "Sha256", "Hash with sha256 algorithm",{"strm","$is224"}, [](GCList& ls, std::vector args)->TObject { - TByteArray* baSrc; + dict->DeclareFunction( + gc, "Sha256", "Hash with sha256 algorithm", {"strm", "$is224"}, + [](GCList &ls, std::vector args) -> TObject { + TByteArray *baSrc; std::shared_ptr sho; - bool is224=false; - GetArgument(args,1,is224); + bool is224 = false; + GetArgument(args, 1, is224); - if(GetArgument(args, 0, sho)) - { - auto bytes = Sha256::ComputeHash(sho,is224); + if (GetArgument(args, 0, sho)) { + auto bytes = Sha256::ComputeHash(sho, is224); auto ba = TByteArray::Create(ls); ba->data = bytes; return ba; } - if(GetArgumentHeap(args,0,baSrc)) - { - auto bytes = Sha256::ComputeHash(baSrc->data.data(), baSrc->data.size(), is224); + if (GetArgumentHeap(args, 0, baSrc)) { + auto bytes = Sha256::ComputeHash(baSrc->data.data(), + baSrc->data.size(), is224); auto ba = TByteArray::Create(ls); ba->data = bytes; return ba; } return Undefined(); }); - dict->DeclareFunction(gc, "Sha512", "Hash with sha512 algorithm",{"strm","$is384"}, [](GCList& ls, std::vector args)->TObject { - TByteArray* baSrc; + dict->DeclareFunction( + gc, "Sha512", "Hash with sha512 algorithm", {"strm", "$is384"}, + [](GCList &ls, std::vector args) -> TObject { + TByteArray *baSrc; std::shared_ptr sho; - bool is384=false; - GetArgument(args,1,is384); + bool is384 = false; + GetArgument(args, 1, is384); - if(GetArgument(args, 0, sho)) - { - auto bytes = Sha512::ComputeHash(sho,is384); + if (GetArgument(args, 0, sho)) { + auto bytes = Sha512::ComputeHash(sho, is384); auto ba = TByteArray::Create(ls); ba->data = bytes; return ba; } - if(GetArgumentHeap(args,0,baSrc)) - { - auto bytes = Sha512::ComputeHash(baSrc->data.data(), baSrc->data.size(), is384); + if (GetArgumentHeap(args, 0, baSrc)) { + auto bytes = Sha512::ComputeHash(baSrc->data.data(), + baSrc->data.size(), is384); auto ba = TByteArray::Create(ls); ba->data = bytes; return ba; } return Undefined(); }); - gc->BarrierBegin(); - env->DeclareVariable("Crypto", dict); - gc->BarrierEnd(); - - - } + gc->BarrierBegin(); + env->DeclareVariable("Crypto", dict); + gc->BarrierEnd(); } +} // namespace Tesses::CrossLang diff --git a/src/runtime_methods/dictionary.cpp b/src/runtime_methods/dictionary.cpp index 0295a60..da206b0 100644 --- a/src/runtime_methods/dictionary.cpp +++ b/src/runtime_methods/dictionary.cpp @@ -1,149 +1,137 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - TObject Dictionary_FindByKey(GCList& ls, std::vector args) - { - TList* dest = TList::Create(ls); - ls.GetGC()->BarrierBegin(); - std::string key; - if(GetArgument(args,1,key)) - { +namespace Tesses::CrossLang { +TObject Dictionary_FindByKey(GCList &ls, std::vector args) { + TList *dest = TList::Create(ls); + ls.GetGC()->BarrierBegin(); + std::string key; + if (GetArgument(args, 1, key)) { - std::function crawl; - crawl = [&](TObject o) -> void { - TDictionary* dict; - TList* list; - TAssociativeArray* aa; - if(GetObjectHeap(o,aa)) - { - std::string k0; - for(auto& item : aa->items) - { - - if(GetObject(item.first,k0) && k0 == key) dest->Add(item.second); - crawl(item.second); - } + std::function crawl; + crawl = [&](TObject o) -> void { + TDictionary *dict; + TList *list; + TAssociativeArray *aa; + if (GetObjectHeap(o, aa)) { + std::string k0; + for (auto &item : aa->items) { + + if (GetObject(item.first, k0) && k0 == key) + dest->Add(item.second); + crawl(item.second); } - if(GetObjectHeap(o,dict)) - { - for(auto& item : dict->items) - { - if(item.first == key) dest->Add(item.second); - crawl(item.second); - } + } + if (GetObjectHeap(o, dict)) { + for (auto &item : dict->items) { + if (item.first == key) + dest->Add(item.second); + crawl(item.second); } - if(GetObjectHeap(o,list)) - { - for(auto& item : list->items) - { - crawl(item); - } + } + if (GetObjectHeap(o, list)) { + for (auto &item : list->items) { + crawl(item); } - }; - crawl(args[0]); - } - ls.GetGC()->BarrierEnd(); - return dest; + } + }; + crawl(args[0]); } - TObject Dictionary_Items(GCList& ls, std::vector args) - { - - TDictionary* dict; - TDynamicDictionary* dynDict; - if(GetArgumentHeap(args,0,dynDict)) - { - TDictionary* enumerableItem = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); + ls.GetGC()->BarrierEnd(); + return dest; +} +TObject Dictionary_Items(GCList &ls, std::vector args) { - auto fn = TExternalMethod::Create(ls,"Get Enumerator for Dictionary",{},[dynDict](GCList& ls2, std::vector args)->TObject { + TDictionary *dict; + TDynamicDictionary *dynDict; + if (GetArgumentHeap(args, 0, dynDict)) { + TDictionary *enumerableItem = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + + auto fn = TExternalMethod::Create( + ls, "Get Enumerator for Dictionary", {}, + [dynDict](GCList &ls2, std::vector args) -> TObject { return dynDict->GetEnumerator(ls2); }); - fn->watch.push_back(dynDict); - - enumerableItem->SetValue("GetEnumerator", fn); - - ls.GetGC()->BarrierEnd(); + fn->watch.push_back(dynDict); - return enumerableItem; - - } - if(GetArgumentHeap(args,0,dict)) - { - TDictionary* enumerableItem = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); + enumerableItem->SetValue("GetEnumerator", fn); - auto fn = TExternalMethod::Create(ls,"Get Enumerator for Dictionary",{"dict"},[dict](GCList& ls2, std::vector args)->TObject { - return TDictionaryEnumerator::Create(ls2,dict); + ls.GetGC()->BarrierEnd(); + + return enumerableItem; + } + if (GetArgumentHeap(args, 0, dict)) { + TDictionary *enumerableItem = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + + auto fn = TExternalMethod::Create( + ls, "Get Enumerator for Dictionary", {"dict"}, + [dict](GCList &ls2, std::vector args) -> TObject { + return TDictionaryEnumerator::Create(ls2, dict); }); - fn->watch.push_back(dict); - - enumerableItem->SetValue("GetEnumerator", fn); - + fn->watch.push_back(dict); + + enumerableItem->SetValue("GetEnumerator", fn); + + ls.GetGC()->BarrierEnd(); + + return enumerableItem; + } + + return Undefined(); +} +TObject Dictionary_GetField(GCList &ls, std::vector args) { + TDictionary *dict; + TDynamicDictionary *dynDict; + std::string key; + if (GetArgument(args, 1, key)) { + if (GetArgumentHeap(args, 0, dict)) { + ls.GetGC()->BarrierBegin(); + auto res = dict->GetValue(key); ls.GetGC()->BarrierEnd(); - - return enumerableItem; - + return res; + } else if (GetArgumentHeap(args, 0, dynDict)) { + return dynDict->GetField(ls, key); } - - return Undefined(); } - TObject Dictionary_GetField(GCList& ls, std::vector args) - { - TDictionary* dict; - TDynamicDictionary* dynDict; - std::string key; - if(GetArgument(args,1,key)) - { - if(GetArgumentHeap(args,0,dict)) - { - ls.GetGC()->BarrierBegin(); - auto res = dict->GetValue(key); - ls.GetGC()->BarrierEnd(); - return res; - } - else if(GetArgumentHeap(args,0,dynDict)) - { - return dynDict->GetField(ls,key); - } + return nullptr; +} +TObject Dictionary_SetField(GCList &ls, std::vector args) { + TDictionary *dict; + TDynamicDictionary *dynDict; + std::string key; + if (args.size() == 3 && GetArgument(args, 1, key)) { + if (GetArgumentHeap(args, 0, dict)) { + ls.GetGC()->BarrierBegin(); + dict->SetValue(key, args[2]); + ls.GetGC()->BarrierEnd(); + } else if (GetArgumentHeap(args, 0, dynDict)) { + dynDict->SetField(ls, key, args[2]); } - return nullptr; } - TObject Dictionary_SetField(GCList& ls, std::vector args) - { - TDictionary* dict; - TDynamicDictionary* dynDict; - std::string key; - if(args.size() == 3 && GetArgument(args,1,key)) - { - if(GetArgumentHeap(args,0,dict)) - { - ls.GetGC()->BarrierBegin(); - dict->SetValue(key,args[2]); - ls.GetGC()->BarrierEnd(); - } - else if(GetArgumentHeap(args,0,dynDict)) - { - dynDict->SetField(ls,key,args[2]); - } - } - return nullptr; - } - void TStd::RegisterDictionary(std::shared_ptr gc,TRootEnvironment* env) - { + return nullptr; +} +void TStd::RegisterDictionary(std::shared_ptr gc, TRootEnvironment *env) { - env->permissions.canRegisterDictionary=true; - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - + env->permissions.canRegisterDictionary = true; + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); - gc->BarrierBegin(); - dict->DeclareFunction(gc, "FindByKey","Scan object recursively, return list of items with key",{"obj","key"}, Dictionary_FindByKey); - dict->DeclareFunction(gc, "Items","Get Dictionary Item Enumerable, for the each(item : Dictionary.Items(myDict)){item.Key; item.Value;}",{"dictionary"},Dictionary_Items); - dict->DeclareFunction(gc, "SetField","Set a field in dictionary",{"dict","key","value"},Dictionary_SetField); - dict->DeclareFunction(gc, "GetField","Get a field in dictionary",{"dict","key"},Dictionary_GetField); + gc->BarrierBegin(); + dict->DeclareFunction( + gc, "FindByKey", + "Scan object recursively, return list of items with key", + {"obj", "key"}, Dictionary_FindByKey); + dict->DeclareFunction(gc, "Items", + "Get Dictionary Item Enumerable, for the each(item : " + "Dictionary.Items(myDict)){item.Key; item.Value;}", + {"dictionary"}, Dictionary_Items); + dict->DeclareFunction(gc, "SetField", "Set a field in dictionary", + {"dict", "key", "value"}, Dictionary_SetField); + dict->DeclareFunction(gc, "GetField", "Get a field in dictionary", + {"dict", "key"}, Dictionary_GetField); - env->DeclareVariable("Dictionary", dict); - gc->BarrierEnd(); - } -} \ No newline at end of file + env->DeclareVariable("Dictionary", dict); + gc->BarrierEnd(); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/runtime_methods/env.cpp b/src/runtime_methods/env.cpp index 44dc007..da4cc9d 100644 --- a/src/runtime_methods/env.cpp +++ b/src/runtime_methods/env.cpp @@ -5,165 +5,152 @@ #include #endif -namespace Tesses::CrossLang -{ - using namespace Tesses::Framework::Platform::Environment; - #if defined(_WIN32) - static char EnvPathSeperator=';'; - #else - static char EnvPathSeperator=':'; - #endif +namespace Tesses::CrossLang { +using namespace Tesses::Framework::Platform::Environment; +#if defined(_WIN32) +static char EnvPathSeperator = ';'; +#else +static char EnvPathSeperator = ':'; +#endif - Tesses::Framework::Filesystem::VFSPath CrossLangConfigPath(""); +Tesses::Framework::Filesystem::VFSPath CrossLangConfigPath(""); - - Tesses::Framework::Filesystem::VFSPath GetCrossLangConfigDir() - { - if(!CrossLangConfigPath.path.empty()) - return CrossLangConfigPath; - - return SpecialFolders::GetConfig() / "Tesses" / "CrossLang"; - } +Tesses::Framework::Filesystem::VFSPath GetCrossLangConfigDir() { + if (!CrossLangConfigPath.path.empty()) + return CrossLangConfigPath; - - - static TObject Env_getCrossLangConfig(GCList& ls, std::vector args) - { - return GetCrossLangConfigDir(); - } - static TObject Env_getPlatform(GCList& ls, std::vector args) - { - return Tesses::Framework::Platform::Environment::GetPlatform(); - } - static TObject Env_GetAt(GCList& ls, std::vector args) - { - std::string key; - if(GetArgument(args,0,key)) - { - auto v = GetVariable(key); - if(v) return v.value(); - - } - return nullptr; - } - static TObject Env_SetAt(GCList& ls, std::vector args) - { - std::string key; - std::string value; - if(GetArgument(args,0,key)) - { - if(GetArgument(args,1,value)) - { - SetVariable(key,value); - - return value; - } - else - { - SetVariable(key,std::nullopt); - } - } - return nullptr; - } - static TObject Env_getDownloads(GCList& ls, std::vector args) - { - return SpecialFolders::GetDownloads(); - } - static TObject Env_getMusic(GCList& ls, std::vector args) - { - return SpecialFolders::GetMusic(); - } - static TObject Env_getPictures(GCList& ls, std::vector args) - { - return SpecialFolders::GetPictures(); - } - static TObject Env_getVideos(GCList& ls, std::vector args) - { - return SpecialFolders::GetVideos(); - } - static TObject Env_getDocuments(GCList& ls, std::vector args) - { - return SpecialFolders::GetDocuments(); - } - static TObject Env_getConfig(GCList& ls, std::vector args) - { - return SpecialFolders::GetConfig(); - } - - static TObject Env_getDesktop(GCList& ls, std::vector args) - { - return SpecialFolders::GetDesktop(); - } - static TObject Env_getState(GCList& ls, std::vector args) - { - return SpecialFolders::GetState(); - } - static TObject Env_getCache(GCList& ls, std::vector args) - { - return SpecialFolders::GetCache(); - } - static TObject Env_getData(GCList& ls, std::vector args) - { - return SpecialFolders::GetData(); - } - static TObject Env_getUser(GCList& ls, std::vector args) - { - return SpecialFolders::GetHomeFolder(); - } - static TObject Env_GetRealExecutablePath(GCList& ls, std::vector args) - { - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgumentAsPath(args,0,p)) - { - return GetRealExecutablePath(p); - } - return Tesses::Framework::Filesystem::VFSPath(); - } - static TObject Env_GetAll(GCList& ls, std::vector args) - { - ls.GetGC()->BarrierBegin(); - TList* list = TList::Create(ls); - std::vector> env; - Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env); - for(auto& item : env) - { - list->Add(TDictionary::Create(ls,{TDItem("Key",item.first),TDItem("Value",item.second)})); - } - ls.GetGC()->BarrierEnd(); - return list; - } - static TObject Env_getLittleEndian(GCList& ls, std::vector args) - { - return Tesses::Framework::Serialization::BitConverter::IsLittleEndian(); - } - void TStd::RegisterEnv(std::shared_ptr gc, TRootEnvironment* env) - { - - env->permissions.canRegisterEnv=true; - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - dict->DeclareFunction(gc,"GetAt","Get environment variable", {"key"}, Env_GetAt); - dict->DeclareFunction(gc,"SetAt","Set environment variable", {"key","value"}, Env_SetAt); - dict->DeclareFunction(gc,"GetAll","Get all of the environment variables",{},Env_GetAll); - - dict->DeclareFunction(gc,"getDesktop","Get desktop folder",{},Env_getDesktop); - dict->DeclareFunction(gc,"getDownloads","Get downloads folder",{},Env_getDownloads); - dict->DeclareFunction(gc,"getDocuments","Get documents folder",{},Env_getDocuments); - dict->DeclareFunction(gc,"getMusic","Get music folder",{},Env_getMusic); - dict->DeclareFunction(gc,"getPictures","Get pictures folder",{},Env_getPictures); - dict->DeclareFunction(gc,"getVideos","Get videos folder",{},Env_getVideos); - dict->DeclareFunction(gc,"getState","Get state folder",{},Env_getState); - dict->DeclareFunction(gc,"getCache","Get cache folder",{},Env_getCache); - dict->DeclareFunction(gc,"getConfig","Get config folder",{},Env_getConfig); - dict->DeclareFunction(gc,"getCrossLangConfig","Get crosslang configuration folder",{}, Env_getCrossLangConfig); - dict->DeclareFunction(gc,"getData","Get data folder",{},Env_getData); - dict->DeclareFunction(gc,"getUser","Get user folder",{},Env_getUser); - dict->DeclareFunction(gc,"getPlatform","Get platform name",{},Env_getPlatform); - dict->DeclareFunction(gc,"GetRealExecutablePath", "Get the absolute path for executable", {"path"},Env_GetRealExecutablePath); - dict->DeclareFunction(gc, "getLittleEndian", "Is the platform little endian", {},Env_getLittleEndian); - gc->BarrierBegin(); - dict->SetValue("EnvPathSeperator",EnvPathSeperator); - env->SetVariable("Env", dict); - gc->BarrierEnd(); - } + return SpecialFolders::GetConfig() / "Tesses" / "CrossLang"; } + +static TObject Env_getCrossLangConfig(GCList &ls, std::vector args) { + return GetCrossLangConfigDir(); +} +static TObject Env_getPlatform(GCList &ls, std::vector args) { + return Tesses::Framework::Platform::Environment::GetPlatform(); +} +static TObject Env_GetAt(GCList &ls, std::vector args) { + std::string key; + if (GetArgument(args, 0, key)) { + auto v = GetVariable(key); + if (v) + return v.value(); + } + return nullptr; +} +static TObject Env_SetAt(GCList &ls, std::vector args) { + std::string key; + std::string value; + if (GetArgument(args, 0, key)) { + if (GetArgument(args, 1, value)) { + SetVariable(key, value); + + return value; + } else { + SetVariable(key, std::nullopt); + } + } + return nullptr; +} +static TObject Env_getDownloads(GCList &ls, std::vector args) { + return SpecialFolders::GetDownloads(); +} +static TObject Env_getMusic(GCList &ls, std::vector args) { + return SpecialFolders::GetMusic(); +} +static TObject Env_getPictures(GCList &ls, std::vector args) { + return SpecialFolders::GetPictures(); +} +static TObject Env_getVideos(GCList &ls, std::vector args) { + return SpecialFolders::GetVideos(); +} +static TObject Env_getDocuments(GCList &ls, std::vector args) { + return SpecialFolders::GetDocuments(); +} +static TObject Env_getConfig(GCList &ls, std::vector args) { + return SpecialFolders::GetConfig(); +} + +static TObject Env_getDesktop(GCList &ls, std::vector args) { + return SpecialFolders::GetDesktop(); +} +static TObject Env_getState(GCList &ls, std::vector args) { + return SpecialFolders::GetState(); +} +static TObject Env_getCache(GCList &ls, std::vector args) { + return SpecialFolders::GetCache(); +} +static TObject Env_getData(GCList &ls, std::vector args) { + return SpecialFolders::GetData(); +} +static TObject Env_getUser(GCList &ls, std::vector args) { + return SpecialFolders::GetHomeFolder(); +} +static TObject Env_GetRealExecutablePath(GCList &ls, + std::vector args) { + Tesses::Framework::Filesystem::VFSPath p; + if (GetArgumentAsPath(args, 0, p)) { + return GetRealExecutablePath(p); + } + return Tesses::Framework::Filesystem::VFSPath(); +} +static TObject Env_GetAll(GCList &ls, std::vector args) { + ls.GetGC()->BarrierBegin(); + TList *list = TList::Create(ls); + std::vector> env; + Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env); + for (auto &item : env) { + list->Add(TDictionary::Create( + ls, {TDItem("Key", item.first), TDItem("Value", item.second)})); + } + ls.GetGC()->BarrierEnd(); + return list; +} +static TObject Env_getLittleEndian(GCList &ls, std::vector args) { + return Tesses::Framework::Serialization::BitConverter::IsLittleEndian(); +} +void TStd::RegisterEnv(std::shared_ptr gc, TRootEnvironment *env) { + + env->permissions.canRegisterEnv = true; + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); + dict->DeclareFunction(gc, "GetAt", "Get environment variable", {"key"}, + Env_GetAt); + dict->DeclareFunction(gc, "SetAt", "Set environment variable", + {"key", "value"}, Env_SetAt); + dict->DeclareFunction(gc, "GetAll", "Get all of the environment variables", + {}, Env_GetAll); + + dict->DeclareFunction(gc, "getDesktop", "Get desktop folder", {}, + Env_getDesktop); + dict->DeclareFunction(gc, "getDownloads", "Get downloads folder", {}, + Env_getDownloads); + dict->DeclareFunction(gc, "getDocuments", "Get documents folder", {}, + Env_getDocuments); + dict->DeclareFunction(gc, "getMusic", "Get music folder", {}, Env_getMusic); + dict->DeclareFunction(gc, "getPictures", "Get pictures folder", {}, + Env_getPictures); + dict->DeclareFunction(gc, "getVideos", "Get videos folder", {}, + Env_getVideos); + dict->DeclareFunction(gc, "getState", "Get state folder", {}, Env_getState); + dict->DeclareFunction(gc, "getCache", "Get cache folder", {}, Env_getCache); + dict->DeclareFunction(gc, "getConfig", "Get config folder", {}, + Env_getConfig); + dict->DeclareFunction(gc, "getCrossLangConfig", + "Get crosslang configuration folder", {}, + Env_getCrossLangConfig); + dict->DeclareFunction(gc, "getData", "Get data folder", {}, Env_getData); + dict->DeclareFunction(gc, "getUser", "Get user folder", {}, Env_getUser); + dict->DeclareFunction(gc, "getPlatform", "Get platform name", {}, + Env_getPlatform); + dict->DeclareFunction(gc, "GetRealExecutablePath", + "Get the absolute path for executable", {"path"}, + Env_GetRealExecutablePath); + dict->DeclareFunction(gc, "getLittleEndian", + "Is the platform little endian", {}, + Env_getLittleEndian); + gc->BarrierBegin(); + dict->SetValue("EnvPathSeperator", EnvPathSeperator); + env->SetVariable("Env", dict); + gc->BarrierEnd(); +} +} // namespace Tesses::CrossLang diff --git a/src/runtime_methods/helpers.cpp b/src/runtime_methods/helpers.cpp index 719fc06..69cfe5f 100644 --- a/src/runtime_methods/helpers.cpp +++ b/src/runtime_methods/helpers.cpp @@ -1,57 +1,53 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { - static TObject Helpers_CopyToProgress(GCList& ls, std::vector args) - { - std::shared_ptr src; - std::shared_ptr dest; - double precision=1000.0; - TCallable* callable; - if(GetArgument(args,0,src) && GetArgument(args,1,dest) && GetArgumentHeap(args,2,callable)) - { - GetArgument(args,3,precision); - auto len = src->GetLength(); - callable->Call(ls,{0.0}); - if(len > 0) - { - std::vector buff(1024); - int64_t pos=0; - int curPercent=0; - int lastPercent=0; - size_t read = 0; - do { - read = src->ReadBlock(buff.data(),buff.size()); - dest->WriteBlock(buff.data(),read); +static TObject Helpers_CopyToProgress(GCList &ls, std::vector args) { + std::shared_ptr src; + std::shared_ptr dest; + double precision = 1000.0; + TCallable *callable; + if (GetArgument(args, 0, src) && GetArgument(args, 1, dest) && + GetArgumentHeap(args, 2, callable)) { + GetArgument(args, 3, precision); + auto len = src->GetLength(); + callable->Call(ls, {0.0}); + if (len > 0) { + std::vector buff(1024); + int64_t pos = 0; + int curPercent = 0; + int lastPercent = 0; + size_t read = 0; + do { + read = src->ReadBlock(buff.data(), buff.size()); + dest->WriteBlock(buff.data(), read); - if(read == 0) break; - pos += (int64_t)read; + if (read == 0) + break; + pos += (int64_t)read; - double percent = ((double)pos / len); - percent *= precision; - - curPercent = (int)percent; + double percent = ((double)pos / len); + percent *= precision; - - if(curPercent > lastPercent) - { - lastPercent = curPercent; - callable->Call(ls,{curPercent/precision}); - } + curPercent = (int)percent; + if (curPercent > lastPercent) { + lastPercent = curPercent; + callable->Call(ls, {curPercent / precision}); + } - } while(read != 0); - } - else { - src->CopyTo(dest); - - } - callable->Call(ls,{1.0}); + } while (read != 0); + } else { + src->CopyTo(dest); } - return Undefined(); + callable->Call(ls, {1.0}); } - void TStd::RegisterHelpers(std::shared_ptr gc, TRootEnvironment* env) - { - auto helpers=env->EnsureDictionary(gc,"Helpers"); - helpers->DeclareFunction(gc,"CopyToProgress","Copy Stream to another (but with progress event)",{"src","dest","progressCB","$precision"},Helpers_CopyToProgress); - } -} \ No newline at end of file + return Undefined(); +} +void TStd::RegisterHelpers(std::shared_ptr gc, TRootEnvironment *env) { + auto helpers = env->EnsureDictionary(gc, "Helpers"); + helpers->DeclareFunction(gc, "CopyToProgress", + "Copy Stream to another (but with progress event)", + {"src", "dest", "progressCB", "$precision"}, + Helpers_CopyToProgress); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/runtime_methods/io.cpp b/src/runtime_methods/io.cpp index 0daa9a4..f5972aa 100644 --- a/src/runtime_methods/io.cpp +++ b/src/runtime_methods/io.cpp @@ -1,322 +1,341 @@ #include "CrossLang.hpp" +namespace Tesses::CrossLang { +static TObject FS_CreateArchive(GCList &ls, std::vector args) { + std::shared_ptr vfs; + std::shared_ptr strm; -namespace Tesses::CrossLang -{ - static TObject FS_CreateArchive(GCList& ls, std::vector args) - { - std::shared_ptr vfs; - - std::shared_ptr strm; - - std::string name; - std::string version; - std::string info; - std::string icon=""; - TVMVersion version2; + std::string name; + std::string version; + std::string info; + std::string icon = ""; + TVMVersion version2; - if(GetArgument(args,0,vfs) && GetArgument(args,1,strm) && GetArgument(args,2,name) && GetArgument(args,4,info) && ((GetArgument(args,3,version) && TVMVersion::TryParse(version,version2)) || GetArgument(args,3,version2))) - { - GetArgument(args,5,icon); - CrossArchiveCreate(vfs,strm,name,version2,info,icon); - } - return nullptr; + if (GetArgument(args, 0, vfs) && GetArgument(args, 1, strm) && + GetArgument(args, 2, name) && GetArgument(args, 4, info) && + ((GetArgument(args, 3, version) && + TVMVersion::TryParse(version, version2)) || + GetArgument(args, 3, version2))) { + GetArgument(args, 5, icon); + CrossArchiveCreate(vfs, strm, name, version2, info, icon); } - static TObject FS_ExtractArchive(GCList& ls, std::vector args) - { - std::shared_ptr vfs; - - std::shared_ptr strm; - - - if(GetArgument(args,0,strm) && GetArgument(args,1,vfs)) - { - auto res = CrossArchiveExtract(strm,vfs); + return nullptr; +} +static TObject FS_ExtractArchive(GCList &ls, std::vector args) { + std::shared_ptr vfs; - TDictionary* dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Name",res.first.first); - dict->SetValue("Version",res.first.second.ToString()); - dict->SetValue("Info",res.second); - ls.GetGC()->BarrierEnd(); - return dict; - } - return nullptr; + std::shared_ptr strm; + + if (GetArgument(args, 0, strm) && GetArgument(args, 1, vfs)) { + auto res = CrossArchiveExtract(strm, vfs); + + TDictionary *dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Name", res.first.first); + dict->SetValue("Version", res.first.second.ToString()); + dict->SetValue("Info", res.second); + ls.GetGC()->BarrierEnd(); + return dict; } + return nullptr; +} - static TObject FS_ReadAllText(GCList& ls, std::vector args) - { - Tesses::Framework::Filesystem::VFSPath path; +static TObject FS_ReadAllText(GCList &ls, std::vector args) { + Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr vfs; - - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path)) - { - return Tesses::Framework::Filesystem::Helpers::ReadAllText(vfs,path); - } - return ""; + std::shared_ptr vfs; + + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path)) { + return Tesses::Framework::Filesystem::Helpers::ReadAllText(vfs, path); } + return ""; +} - static TObject FS_ReadAllLines(GCList& ls, std::vector args) - { - Tesses::Framework::Filesystem::VFSPath path; +static TObject FS_ReadAllLines(GCList &ls, std::vector args) { + Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr vfs; - - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path)) - { - std::vector lines; + std::shared_ptr vfs; - Tesses::Framework::Filesystem::Helpers::ReadAllLines(vfs,path,lines); + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path)) { + std::vector lines; - ls.GetGC()->BarrierBegin(); - auto items = TList::Create(ls); - for(auto& l : lines) { items->Add(l);} - ls.GetGC()->BarrierEnd(); - return items; + Tesses::Framework::Filesystem::Helpers::ReadAllLines(vfs, path, lines); + + ls.GetGC()->BarrierBegin(); + auto items = TList::Create(ls); + for (auto &l : lines) { + items->Add(l); } - return nullptr; + ls.GetGC()->BarrierEnd(); + return items; } + return nullptr; +} - static TObject FS_ReadAllBytes(GCList& ls, std::vector args) - { - Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr vfs; - - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path)) - { - auto res = TByteArray::Create(ls); - Tesses::Framework::Filesystem::Helpers::ReadAllBytes(vfs,path,res->data); - - return res; - } - return nullptr; +static TObject FS_ReadAllBytes(GCList &ls, std::vector args) { + Tesses::Framework::Filesystem::VFSPath path; + std::shared_ptr vfs; + + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path)) { + auto res = TByteArray::Create(ls); + Tesses::Framework::Filesystem::Helpers::ReadAllBytes(vfs, path, + res->data); + + return res; } + return nullptr; +} +static TObject FS_WriteAllLines(GCList &ls, std::vector args) { + Tesses::Framework::Filesystem::VFSPath path; + std::shared_ptr vfs; - static TObject FS_WriteAllLines(GCList& ls, std::vector args) - { - Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr vfs; - - - TList* lines; - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path) && GetArgumentHeap(args,2,lines)) - { - std::vector content; - ls.GetGC()->BarrierBegin(); - for(auto& item : lines->items) - { - if(std::holds_alternative(item)) + TList *lines; + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path) && + GetArgumentHeap(args, 2, lines)) { + std::vector content; + ls.GetGC()->BarrierBegin(); + for (auto &item : lines->items) { + if (std::holds_alternative(item)) content.push_back(std::get(item)); + } + ls.GetGC()->BarrierEnd(); + Tesses::Framework::Filesystem::Helpers::WriteAllLines(vfs, path, + content); + } + return nullptr; +} +static TObject FS_WriteAllText(GCList &ls, std::vector args) { + Tesses::Framework::Filesystem::VFSPath path; + std::shared_ptr vfs; + + std::string content; + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path) && + GetArgument(args, 2, content)) { + Tesses::Framework::Filesystem::Helpers::WriteAllText(vfs, path, + content); + } + return nullptr; +} +static TObject FS_WriteAllBytes(GCList &ls, std::vector args) { + Tesses::Framework::Filesystem::VFSPath path; + + std::shared_ptr vfs; + + TByteArray *bArray; + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path) && + GetArgumentHeap(args, 2, bArray)) { + Tesses::Framework::Filesystem::Helpers::WriteAllBytes(vfs, path, + bArray->data); + } + return nullptr; +} + +class FS_Watcher : public TNativeObject { + public: + std::shared_ptr watcher; + + FS_Watcher( + std::shared_ptr watcher) + : watcher(watcher) {} + + TObject CallMethod(GCList &ls, std::string name, + std::vector args) { + if (name == "getPath") { + return watcher->GetPath(); + } + if (name == "getFilesystem") { + return watcher->GetFilesystem(); + } + if (name == "setEnabled") { + bool enabled; + if (GetArgument(args, 0, enabled)) { + watcher->SetEnabled(enabled); + return enabled; } - ls.GetGC()->BarrierEnd(); - Tesses::Framework::Filesystem::Helpers::WriteAllLines(vfs,path,content); } - return nullptr; - } - static TObject FS_WriteAllText(GCList& ls, std::vector args) - { - Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr vfs; - - - std::string content; - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path) && GetArgument(args,2,content)) - { - Tesses::Framework::Filesystem::Helpers::WriteAllText(vfs,path,content); + if (name == "getEnabled") { + return watcher->GetEnabled(); } - return nullptr; - } - static TObject FS_WriteAllBytes(GCList& ls, std::vector args) - { - Tesses::Framework::Filesystem::VFSPath path; - - std::shared_ptr vfs; - - TByteArray* bArray; - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path) && GetArgumentHeap(args,2,bArray)) - { - Tesses::Framework::Filesystem::Helpers::WriteAllBytes(vfs,path,bArray->data); + if (name == "setEvents") { + int64_t evts; + if (GetArgument(args, 0, evts)) { + watcher->events = + (Tesses::Framework::Filesystem::FSWatcherEventType)evts; + return evts; + } } - return nullptr; - } - - - - - - class FS_Watcher : public TNativeObject { - public: - std::shared_ptr watcher; - - FS_Watcher(std::shared_ptr watcher): watcher(watcher) - {} - - TObject CallMethod(GCList& ls, std::string name, std::vector args) - { - if(name == "getPath") - { - return watcher->GetPath(); - } - if(name == "getFilesystem") - { - return watcher->GetFilesystem(); - } - if(name == "setEnabled") - { - bool enabled; - if(GetArgument(args,0,enabled)) - { - watcher->SetEnabled(enabled); - return enabled; - } - } - if(name == "getEnabled") - { - return watcher->GetEnabled(); - } - if(name == "setEvents") - { - int64_t evts; - if(GetArgument(args,0,evts)) - { - watcher->events = (Tesses::Framework::Filesystem::FSWatcherEventType)evts; - return evts; - } - } - if(name == "getEvents") - { - return (int64_t)watcher->events; - } - if(name == "setCallback") - { - TCallable* callable=nullptr; - if(GetArgumentHeap(args,0,callable)) - { - auto markedT = CreateMarkedTObject(ls,callable); - watcher->event = [markedT](Tesses::Framework::Filesystem::FSWatcherEvent& evt) -> void { - GCList ls(markedT->GetGC()); - TObject o = markedT->GetObject(); - TCallable* callable; - if(GetObjectHeap(o,callable)) - { - auto isEvent = TExternalMethod::Create(ls,"",{},[evt](GCList& ls, std::vector args)->TObject - { + if (name == "getEvents") { + return (int64_t)watcher->events; + } + if (name == "setCallback") { + TCallable *callable = nullptr; + if (GetArgumentHeap(args, 0, callable)) { + auto markedT = CreateMarkedTObject(ls, callable); + watcher->event = + [markedT]( + Tesses::Framework::Filesystem::FSWatcherEvent &evt) + -> void { + GCList ls(markedT->GetGC()); + TObject o = markedT->GetObject(); + TCallable *callable; + if (GetObjectHeap(o, callable)) { + auto isEvent = TExternalMethod::Create( + ls, "", {}, + [evt](GCList &ls, + std::vector args) -> TObject { int64_t n; - if(GetArgument(args,0,n)) - { + if (GetArgument(args, 0, n)) { auto myevt = evt; - return myevt.IsEvent((Tesses::Framework::Filesystem::FSWatcherEventType)n); - + return myevt.IsEvent( + (Tesses::Framework::Filesystem:: + FSWatcherEventType)n); } return false; }); - auto toString = TExternalMethod::Create(ls,"",{},[evt](GCList& ls, std::vector args)->TObject - { + auto toString = TExternalMethod::Create( + ls, "", {}, + [evt](GCList &ls, + std::vector args) -> TObject { auto myevt = evt; return myevt.ToString(); }); - auto dict = TDictionary::Create(ls, {TDItem("IsDirectory",evt.isDir),TDItem("Type",(int64_t)evt.type),TDItem("Source",evt.src), TDItem("Destination",evt.dest),TDItem("ToString",toString),TDItem("IsEvent",isEvent)}); - callable->Call(ls,{dict}); - } - }; + auto dict = TDictionary::Create( + ls, {TDItem("IsDirectory", evt.isDir), + TDItem("Type", (int64_t)evt.type), + TDItem("Source", evt.src), + TDItem("Destination", evt.dest), + TDItem("ToString", toString), + TDItem("IsEvent", isEvent)}); + callable->Call(ls, {dict}); } - else { - watcher->event=nullptr; - } - return nullptr; - } - if(name == "Start") - { - watcher->SetEnabled(true); - } - if(name == "Stop") - { - watcher->SetEnabled(false); - } - if(name == "ToString") - { - return "FSWatcher"; - } - return Undefined(); + }; + } else { + watcher->event = nullptr; } - - std::string TypeName() { - return "FSWatcher"; - } - }; - - TObject New_FSWatcher(GCList& ls, std::vector args) - { - std::shared_ptr vfs; - Tesses::Framework::Filesystem::VFSPath path; - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path)) - { - return TNativeObject::Create(ls,Tesses::Framework::Filesystem::FSWatcher::Create(vfs,path)); + return nullptr; } - return nullptr; + if (name == "Start") { + watcher->SetEnabled(true); + } + if (name == "Stop") { + watcher->SetEnabled(false); + } + if (name == "ToString") { + return "FSWatcher"; + } + return Undefined(); } - void TStd::RegisterIO(std::shared_ptr gc,TRootEnvironment* env, bool enable) - { - if(enable) - { - RegisterIO(gc,env,std::make_shared(Tesses::Framework::Filesystem::LocalFS, Tesses::Framework::Filesystem::VFSPath::GetAbsoluteCurrentDirectory())); - } - else - { - RegisterIO(gc,env,nullptr); - } + + std::string TypeName() { return "FSWatcher"; } +}; + +TObject New_FSWatcher(GCList &ls, std::vector args) { + std::shared_ptr vfs; + Tesses::Framework::Filesystem::VFSPath path; + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path)) { + return TNativeObject::Create( + ls, Tesses::Framework::Filesystem::FSWatcher::Create(vfs, path)); } - void TStd::RegisterIO(std::shared_ptr gc,TRootEnvironment* env,std::shared_ptr fs) - { + return nullptr; +} +void TStd::RegisterIO(std::shared_ptr gc, TRootEnvironment *env, + bool enable) { + if (enable) { + RegisterIO( + gc, env, + std::make_shared( + Tesses::Framework::Filesystem::LocalFS, + Tesses::Framework::Filesystem::VFSPath:: + GetAbsoluteCurrentDirectory())); + } else { + RegisterIO(gc, env, nullptr); + } +} +void TStd::RegisterIO( + std::shared_ptr gc, TRootEnvironment *env, + std::shared_ptr fs) { - env->permissions.canRegisterIO=true; - env->permissions.localfs = fs; - GCList ls(gc); - - gc->BarrierBegin(); - auto newDict = env->EnsureDictionary(gc, "New"); - newDict->DeclareFunction(gc,"FSWatcher","Watch a file/directory",{"vfs","path"}, New_FSWatcher); - auto dict = env->EnsureDictionary(gc,"FS"); - dict->SetValue("SEEK_SET",(int64_t)Tesses::Framework::Streams::SeekOrigin::Begin); - dict->SetValue("SEEK_CUR",(int64_t)Tesses::Framework::Streams::SeekOrigin::Current); - dict->SetValue("SEEK_END",(int64_t)Tesses::Framework::Streams::SeekOrigin::End); - dict->SetValue("FSWatcherEvents",TDictionary::Create(ls, - { - TDItem("None", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::None), - TDItem("Accessed", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Accessed), - TDItem("AttributeChanged", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::AttributeChanged), - TDItem("Writen", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Writen), - TDItem("Read", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Read), - TDItem("Created", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Created), - TDItem("Deleted", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Deleted), - TDItem("WatchEntryDeleted", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::WatchEntryDeleted), - TDItem("Modified", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Modified), - TDItem("WatchEntryMoved", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::WatchEntryMoved), - TDItem("MoveOld", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::MoveOld), - TDItem("MoveNew", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::MoveNew), - TDItem("Opened", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Opened), - TDItem("Closed", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Closed), - TDItem("Moved", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::Moved), - TDItem("All", (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType::All) - } - )); + env->permissions.canRegisterIO = true; + env->permissions.localfs = fs; + GCList ls(gc); - if(fs) - { - - - dict->SetValue("Local", fs); - dict->DeclareFunction(gc, "MakeFull", "Make absolute path from relative path",{"path"},[fs](GCList& ls, std::vector args)->TObject{ + gc->BarrierBegin(); + auto newDict = env->EnsureDictionary(gc, "New"); + newDict->DeclareFunction(gc, "FSWatcher", "Watch a file/directory", + {"vfs", "path"}, New_FSWatcher); + auto dict = env->EnsureDictionary(gc, "FS"); + dict->SetValue("SEEK_SET", + (int64_t)Tesses::Framework::Streams::SeekOrigin::Begin); + dict->SetValue("SEEK_CUR", + (int64_t)Tesses::Framework::Streams::SeekOrigin::Current); + dict->SetValue("SEEK_END", + (int64_t)Tesses::Framework::Streams::SeekOrigin::End); + dict->SetValue( + "FSWatcherEvents", + TDictionary::Create( + ls, + {TDItem( + "None", + (int64_t) + Tesses::Framework::Filesystem::FSWatcherEventType::None), + TDItem("Accessed", (int64_t)Tesses::Framework::Filesystem:: + FSWatcherEventType::Accessed), + TDItem("AttributeChanged", + (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType:: + AttributeChanged), + TDItem( + "Writen", + (int64_t) + Tesses::Framework::Filesystem::FSWatcherEventType::Writen), + TDItem( + "Read", + (int64_t) + Tesses::Framework::Filesystem::FSWatcherEventType::Read), + TDItem("Created", (int64_t)Tesses::Framework::Filesystem:: + FSWatcherEventType::Created), + TDItem("Deleted", (int64_t)Tesses::Framework::Filesystem:: + FSWatcherEventType::Deleted), + TDItem("WatchEntryDeleted", + (int64_t)Tesses::Framework::Filesystem::FSWatcherEventType:: + WatchEntryDeleted), + TDItem("Modified", (int64_t)Tesses::Framework::Filesystem:: + FSWatcherEventType::Modified), + TDItem("WatchEntryMoved", (int64_t)Tesses::Framework::Filesystem:: + FSWatcherEventType::WatchEntryMoved), + TDItem("MoveOld", (int64_t)Tesses::Framework::Filesystem:: + FSWatcherEventType::MoveOld), + TDItem("MoveNew", (int64_t)Tesses::Framework::Filesystem:: + FSWatcherEventType::MoveNew), + TDItem( + "Opened", + (int64_t) + Tesses::Framework::Filesystem::FSWatcherEventType::Opened), + TDItem( + "Closed", + (int64_t) + Tesses::Framework::Filesystem::FSWatcherEventType::Closed), + TDItem( + "Moved", + (int64_t) + Tesses::Framework::Filesystem::FSWatcherEventType::Moved), + TDItem( + "All", + (int64_t) + Tesses::Framework::Filesystem::FSWatcherEventType::All)})); + + if (fs) { + + dict->SetValue("Local", fs); + dict->DeclareFunction( + gc, "MakeFull", "Make absolute path from relative path", {"path"}, + [fs](GCList &ls, std::vector args) -> TObject { Tesses::Framework::Filesystem::VFSPath path; - if(GetArgumentAsPath(args,0,path)) - { - if(path.relative) - { + if (GetArgumentAsPath(args, 0, path)) { + if (path.relative) { auto myPath = fs->GetWorking() / path; myPath = myPath.CollapseRelativeParents(); return myPath; @@ -325,37 +344,47 @@ namespace Tesses::CrossLang } return nullptr; }); - dict->DeclareFunction(gc,"getCurrentPath","Get current path",{},[fs](GCList& ls, std::vector args)->TObject{ + dict->DeclareFunction( + gc, "getCurrentPath", "Get current path", {}, + [fs](GCList &ls, std::vector args) -> TObject { return fs->GetWorking(); }); - dict->DeclareFunction(gc,"setCurrentPath","Set the current path",{"path"}, [fs](GCList& ls, std::vector args)->TObject { + dict->DeclareFunction( + gc, "setCurrentPath", "Set the current path", {"path"}, + [fs](GCList &ls, std::vector args) -> TObject { Tesses::Framework::Filesystem::VFSPath path; - if(GetArgumentAsPath(args,0,path)) - { - if(path.relative) - { - fs->SetWorking(path.MakeAbsolute(fs->GetWorking())); - } - else { - fs->SetWorking(path); - } + if (GetArgumentAsPath(args, 0, path)) { + if (path.relative) { + fs->SetWorking(path.MakeAbsolute(fs->GetWorking())); + } else { + fs->SetWorking(path); + } } return path; }); - } - - dict->DeclareFunction(gc, "ReadAllText","Read all text from file", {"fs","filename"},FS_ReadAllText); - dict->DeclareFunction(gc, "WriteAllText","Write all text to file", {"fs","filename","content"},FS_WriteAllText); - - dict->DeclareFunction(gc, "ReadAllLines","Read all lines from file", {"fs","filename"},FS_ReadAllLines); - dict->DeclareFunction(gc, "WriteAllLines","Write all lines to file", {"fs","filename","lines"},FS_WriteAllLines); - - dict->DeclareFunction(gc, "ReadAllBytes","Read all bytes from file", {"fs","filename"},FS_ReadAllBytes); - dict->DeclareFunction(gc, "WriteAllBytes","Write all bytes to file", {"fs","filename","content"},FS_WriteAllBytes); - - dict->DeclareFunction(gc, "CreateArchive", "Create a crvm archive",{"fs","strm","name","version","info"},FS_CreateArchive); - dict->DeclareFunction(gc,"ExtractArchive", "Extract a crvm archive",{"strm","vfs"},FS_ExtractArchive); - - gc->BarrierEnd(); } -} \ No newline at end of file + + dict->DeclareFunction(gc, "ReadAllText", "Read all text from file", + {"fs", "filename"}, FS_ReadAllText); + dict->DeclareFunction(gc, "WriteAllText", "Write all text to file", + {"fs", "filename", "content"}, FS_WriteAllText); + + dict->DeclareFunction(gc, "ReadAllLines", "Read all lines from file", + {"fs", "filename"}, FS_ReadAllLines); + dict->DeclareFunction(gc, "WriteAllLines", "Write all lines to file", + {"fs", "filename", "lines"}, FS_WriteAllLines); + + dict->DeclareFunction(gc, "ReadAllBytes", "Read all bytes from file", + {"fs", "filename"}, FS_ReadAllBytes); + dict->DeclareFunction(gc, "WriteAllBytes", "Write all bytes to file", + {"fs", "filename", "content"}, FS_WriteAllBytes); + + dict->DeclareFunction(gc, "CreateArchive", "Create a crvm archive", + {"fs", "strm", "name", "version", "info"}, + FS_CreateArchive); + dict->DeclareFunction(gc, "ExtractArchive", "Extract a crvm archive", + {"strm", "vfs"}, FS_ExtractArchive); + + gc->BarrierEnd(); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/runtime_methods/json.cpp b/src/runtime_methods/json.cpp index 1235831..dc4bfb0 100644 --- a/src/runtime_methods/json.cpp +++ b/src/runtime_methods/json.cpp @@ -2,206 +2,193 @@ #include "CrossLang.hpp" using namespace Tesses::Framework::Serialization::Json; -namespace Tesses::CrossLang -{ +namespace Tesses::CrossLang { - static bool IsValidForJson(TObject v) - { - if(std::holds_alternative(v)) return true; +static bool IsValidForJson(TObject v) { + if (std::holds_alternative(v)) + return true; - if(std::holds_alternative(v)) return true; + if (std::holds_alternative(v)) + return true; - if(std::holds_alternative(v)) return true; + if (std::holds_alternative(v)) + return true; + if (std::holds_alternative(v)) + return true; - if(std::holds_alternative(v)) return true; + if (std::holds_alternative(v)) + return true; - - if(std::holds_alternative(v)) return true; - - - if(std::holds_alternative(v)) - { - auto res = std::get(v); - auto ls = dynamic_cast(res.obj); - auto dict = dynamic_cast(res.obj); - if(ls != nullptr) return true; - if(dict != nullptr) return true; - } - return false; + if (std::holds_alternative(v)) { + auto res = std::get(v); + auto ls = dynamic_cast(res.obj); + auto dict = dynamic_cast(res.obj); + if (ls != nullptr) + return true; + if (dict != nullptr) + return true; } - static JToken JsonSerialize(TObject v) - { - if(std::holds_alternative(v)) return nullptr; - if(std::holds_alternative(v)) return std::get(v); - if(std::holds_alternative(v)) return std::get(v); - if(std::holds_alternative(v)) return std::get(v); - if(std::holds_alternative(v)) return std::get(v); - if(std::holds_alternative(v)) - { - auto obj = std::get(v).obj; - auto ls = dynamic_cast(obj); - auto dict = dynamic_cast(obj); - - if(ls != nullptr) - { - JArray items; - for(int64_t i = 0; i < ls->Count(); i++) - { - auto val = ls->Get(i); - if(IsValidForJson(val)) - items.Add(JsonSerialize(val)); - } - return items; - } - - if(dict != nullptr) - { - JObject obj; - for(auto item : dict->items) - { - if(IsValidForJson(item.second)) - obj.SetValue(item.first,JsonSerialize(item.second)); - } - return obj; - } - } - + return false; +} +static JToken JsonSerialize(TObject v) { + if (std::holds_alternative(v)) return nullptr; - } - static TObject JsonEncode(GCList& ls2, std::vector args) - { - if(args.size() >= 1) - { - bool indent = (args.size() == 2 && std::holds_alternative(args[1]) && std::get(args[1])); - - auto json = JsonSerialize(args[0]); + if (std::holds_alternative(v)) + return std::get(v); + if (std::holds_alternative(v)) + return std::get(v); + if (std::holds_alternative(v)) + return std::get(v); + if (std::holds_alternative(v)) + return std::get(v); + if (std::holds_alternative(v)) { + auto obj = std::get(v).obj; + auto ls = dynamic_cast(obj); + auto dict = dynamic_cast(obj); - return Json::Encode(json,indent); - } - return "null"; - } - static TObject JsonDocEncode(GCList& ls2, std::vector args) - { - if(args.size() >= 1) - { - bool indent = (args.size() == 2 && std::holds_alternative(args[1]) && std::get(args[1])); - - auto json = JsonSerialize(args[0]); - JArray ar; - if(TryGetJToken(json,ar)) - return Json::DocEncode(ar,indent); - - - } - return ""; - } - static TObject JsonDeserialize(GCList& ls2,JToken json) - { - if(std::holds_alternative(json)) return nullptr; - if(std::holds_alternative(json)) return nullptr; - bool b; - int64_t _i64; - double _f64; - std::string str; - JArray arr; - JObject obj; - if(TryGetJToken(json,b)) return b; - if(TryGetJToken(json,_i64)) return _i64; - if(TryGetJToken(json,_f64)) return _f64; - if(TryGetJToken(json,str)) return str; - if(TryGetJToken(json,arr)) - { - TList* ls = TList::Create(ls2); - - for(auto& item : arr) - { - auto itemRes = JsonDeserialize(ls2,item); - ls2.GetGC()->BarrierBegin(); - ls->Add(itemRes); - ls2.GetGC()->BarrierEnd(); + if (ls != nullptr) { + JArray items; + for (int64_t i = 0; i < ls->Count(); i++) { + auto val = ls->Get(i); + if (IsValidForJson(val)) + items.Add(JsonSerialize(val)); } - return ls; + return items; } - if(TryGetJToken(json,obj)) - { - TDictionary* dict = TDictionary::Create(ls2); - - - for(auto& item : obj) - { - - auto itemRes = JsonDeserialize(ls2,item.second); - ls2.GetGC()->BarrierBegin(); - dict->SetValue(item.first,itemRes); - ls2.GetGC()->BarrierEnd(); + if (dict != nullptr) { + JObject obj; + for (auto item : dict->items) { + if (IsValidForJson(item.second)) + obj.SetValue(item.first, JsonSerialize(item.second)); } - return dict; + return obj; } - return Undefined(); } - static TObject JsonDecode(GCList& ls2,std::vector args) - { - if(args.size() > 0 && std::holds_alternative(args[0])) - { - - - return JsonDeserialize(ls2, Json::Decode(std::get(args[0]))); - - - } - return Undefined(); - } - static TObject JsonDocDecode(GCList& ls2,std::vector args) - { - if(args.size() > 0 && std::holds_alternative(args[0])) - { - - - return JsonDeserialize(ls2, Json::DocDecode(std::get(args[0]))); - - - } - return Undefined(); - } - std::string Json_Encode(TObject o,bool indent) - { - return Json::Encode(JsonSerialize(o),indent); - } - TObject Json_Decode(GCList ls,std::string str) - { - return JsonDeserialize(ls,Json::Decode(str)); - } - std::string Json_DocEncode(TObject o,bool indent) - { - auto obj = JsonSerialize(o); - JArray ls; - if(TryGetJToken(obj,ls)) - return Json::DocEncode(ls,indent); - return ""; - } - TObject Json_DocDecode(GCList ls,std::string str) - { - return JsonDeserialize(ls,Json::DocDecode(str)); - } - void TStd::RegisterJson(std::shared_ptr gc,TRootEnvironment* env) - { + return nullptr; +} +static TObject JsonEncode(GCList &ls2, std::vector args) { + if (args.size() >= 1) { + bool indent = + (args.size() == 2 && std::holds_alternative(args[1]) && + std::get(args[1])); - env->permissions.canRegisterJSON=true; - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - dict->DeclareFunction(gc, "Decode","Deserialize Json",{"jsonString"},JsonDecode); - dict->DeclareFunction(gc, "Encode","Serialize Json",{"any","$indent"},JsonEncode); - dict->DeclareFunction(gc, "DocDecode", "Deserialize JsonDoc", {"jsonDocString"},JsonDocDecode); - dict->DeclareFunction(gc, "DocEncode", "Serialize JsonDoc", {"ls","$indent"},JsonDocEncode); - - - - gc->BarrierBegin(); - env->DeclareVariable("Json", dict); - gc->BarrierEnd(); + auto json = JsonSerialize(args[0]); + + return Json::Encode(json, indent); } - -} \ No newline at end of file + return "null"; +} +static TObject JsonDocEncode(GCList &ls2, std::vector args) { + if (args.size() >= 1) { + bool indent = + (args.size() == 2 && std::holds_alternative(args[1]) && + std::get(args[1])); + + auto json = JsonSerialize(args[0]); + JArray ar; + if (TryGetJToken(json, ar)) + return Json::DocEncode(ar, indent); + } + return ""; +} +static TObject JsonDeserialize(GCList &ls2, JToken json) { + if (std::holds_alternative(json)) + return nullptr; + if (std::holds_alternative(json)) + return nullptr; + bool b; + int64_t _i64; + double _f64; + std::string str; + JArray arr; + JObject obj; + if (TryGetJToken(json, b)) + return b; + if (TryGetJToken(json, _i64)) + return _i64; + if (TryGetJToken(json, _f64)) + return _f64; + if (TryGetJToken(json, str)) + return str; + if (TryGetJToken(json, arr)) { + TList *ls = TList::Create(ls2); + + for (auto &item : arr) { + auto itemRes = JsonDeserialize(ls2, item); + ls2.GetGC()->BarrierBegin(); + ls->Add(itemRes); + ls2.GetGC()->BarrierEnd(); + } + return ls; + } + if (TryGetJToken(json, obj)) { + + TDictionary *dict = TDictionary::Create(ls2); + + for (auto &item : obj) { + + auto itemRes = JsonDeserialize(ls2, item.second); + ls2.GetGC()->BarrierBegin(); + dict->SetValue(item.first, itemRes); + ls2.GetGC()->BarrierEnd(); + } + return dict; + } + return Undefined(); +} +static TObject JsonDecode(GCList &ls2, std::vector args) { + if (args.size() > 0 && std::holds_alternative(args[0])) { + + return JsonDeserialize(ls2, + Json::Decode(std::get(args[0]))); + } + return Undefined(); +} +static TObject JsonDocDecode(GCList &ls2, std::vector args) { + if (args.size() > 0 && std::holds_alternative(args[0])) { + + return JsonDeserialize(ls2, + Json::DocDecode(std::get(args[0]))); + } + + return Undefined(); +} +std::string Json_Encode(TObject o, bool indent) { + return Json::Encode(JsonSerialize(o), indent); +} +TObject Json_Decode(GCList ls, std::string str) { + return JsonDeserialize(ls, Json::Decode(str)); +} +std::string Json_DocEncode(TObject o, bool indent) { + auto obj = JsonSerialize(o); + JArray ls; + if (TryGetJToken(obj, ls)) + return Json::DocEncode(ls, indent); + return ""; +} +TObject Json_DocDecode(GCList ls, std::string str) { + return JsonDeserialize(ls, Json::DocDecode(str)); +} +void TStd::RegisterJson(std::shared_ptr gc, TRootEnvironment *env) { + + env->permissions.canRegisterJSON = true; + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); + dict->DeclareFunction(gc, "Decode", "Deserialize Json", {"jsonString"}, + JsonDecode); + dict->DeclareFunction(gc, "Encode", "Serialize Json", {"any", "$indent"}, + JsonEncode); + dict->DeclareFunction(gc, "DocDecode", "Deserialize JsonDoc", + {"jsonDocString"}, JsonDocDecode); + dict->DeclareFunction(gc, "DocEncode", "Serialize JsonDoc", + {"ls", "$indent"}, JsonDocEncode); + + gc->BarrierBegin(); + env->DeclareVariable("Json", dict); + gc->BarrierEnd(); +} + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/runtime_methods/net.cpp b/src/runtime_methods/net.cpp index 3e43243..fd24df0 100644 --- a/src/runtime_methods/net.cpp +++ b/src/runtime_methods/net.cpp @@ -5,1692 +5,1577 @@ #include #include #include -#include #include -#include #include +#include +#include using namespace Tesses::Framework::Streams; using namespace Tesses::Framework::Http; using namespace Tesses::Framework::Mail; -namespace Tesses::CrossLang -{ - static std::shared_ptr TObjectToSMTPBody(GCList& ls,std::string mimeType, TObject obj) - { - std::shared_ptr body; - std::string text; - TByteArray* ba; - std::shared_ptr sho; - if(GetObject(obj,text)) - { - body = std::make_shared(text,mimeType); - } - else if(GetObjectHeap(obj,ba)) { - std::shared_ptr ms = std::make_shared(true); - ms->WriteBlock(ba->data.data(), ba->data.size()); - ms->Seek(0L, SeekOrigin::Begin); - - body = std::make_shared(mimeType,ms); - } - else if(GetObject(obj,sho)) - { - ls.Add(sho); - body = std::make_shared(mimeType,sho); - } - return body; +namespace Tesses::CrossLang { +static std::shared_ptr +TObjectToSMTPBody(GCList &ls, std::string mimeType, TObject obj) { + std::shared_ptr body; + std::string text; + TByteArray *ba; + std::shared_ptr sho; + if (GetObject(obj, text)) { + body = std::make_shared(text, mimeType); + } else if (GetObjectHeap(obj, ba)) { + std::shared_ptr ms = std::make_shared(true); + ms->WriteBlock(ba->data.data(), ba->data.size()); + ms->Seek(0L, SeekOrigin::Begin); + + body = std::make_shared(mimeType, ms); + } else if (GetObject(obj, sho)) { + ls.Add(sho); + body = std::make_shared(mimeType, sho); } - - - class TNativeObjectThatReturnsHttpDictionary : public TNativeObject { - public: - virtual bool IsAvailable()=0; - }; - class DummyTNativeObjectThatReturnsHttpDictionary : public TNativeObjectThatReturnsHttpDictionary { - bool isAvail; - public: - DummyTNativeObjectThatReturnsHttpDictionary() - { - this->isAvail=true; - } - bool IsAvailable() - { - return this->isAvail; - } - void Close() - { - this->isAvail=false; - } - std::string TypeName() - { - return "Dummy"; - } - TObject CallMethod(GCList& ls, std::string key, std::vector args) - { - return Undefined(); - } - }; + return body; +} - class THttpDictionary : public TNativeObject { - TNativeObjectThatReturnsHttpDictionary* ctx; - HttpDictionary* dict; - public: - THttpDictionary(HttpDictionary* dict, TNativeObjectThatReturnsHttpDictionary* ctx) - { - this->dict = dict; - this->ctx = ctx; +class TNativeObjectThatReturnsHttpDictionary : public TNativeObject { + public: + virtual bool IsAvailable() = 0; +}; +class DummyTNativeObjectThatReturnsHttpDictionary + : public TNativeObjectThatReturnsHttpDictionary { + bool isAvail; + + public: + DummyTNativeObjectThatReturnsHttpDictionary() { this->isAvail = true; } + bool IsAvailable() { return this->isAvail; } + void Close() { this->isAvail = false; } + std::string TypeName() { return "Dummy"; } + TObject CallMethod(GCList &ls, std::string key, std::vector args) { + return Undefined(); + } +}; + +class THttpDictionary : public TNativeObject { + TNativeObjectThatReturnsHttpDictionary *ctx; + HttpDictionary *dict; + + public: + THttpDictionary(HttpDictionary *dict, + TNativeObjectThatReturnsHttpDictionary *ctx) { + this->dict = dict; + this->ctx = ctx; + } + std::string TypeName() { return "Net.Http.HttpDictionary"; } + void Mark() { + if (this->marked) + return; + this->marked = true; + ctx->Mark(); + } + + TObject CallMethod(GCList &ls, std::string key, std::vector args) { + if (!ctx->IsAvailable()) + return Undefined(); + else if (key == "AddValue") { + std::string key; + std::string value; + int64_t i64; + double d64; + std::shared_ptr da; + if (GetArgument(args, 0, key)) { + if (GetArgument(args, 1, value)) + this->dict->AddValue(key, value); + else if (GetArgument(args, 1, i64)) + this->dict->AddValue(key, i64); + else if (GetArgument(args, 1, d64)) + this->dict->AddValue(key, d64); + else if (GetArgument(args, 1, da)) + this->dict->AddValue(key, *da); } - std::string TypeName() - { - return "Net.Http.HttpDictionary"; + } else if (key == "SetValue") { + std::string key; + std::string value; + int64_t i64; + double d64; + std::shared_ptr da; + if (GetArgument(args, 0, key)) { + if (GetArgument(args, 1, value)) + this->dict->SetValue(key, value); + else if (GetArgument(args, 1, i64)) + this->dict->SetValue(key, i64); + else if (GetArgument(args, 1, d64)) + this->dict->SetValue(key, d64); + else if (GetArgument(args, 1, da)) + this->dict->SetValue(key, *da); } - void Mark() - { - if(this->marked) return; - this->marked=true; - ctx->Mark(); + } else if (key == "Clear") { + std::string key; + bool existsAfter; + if (GetArgument(args, 0, key) && GetArgument(args, 0, existsAfter)) + dict->Clear(key, existsAfter); + else + dict->Clear(); + + } else if (key == "GetFirstBoolean") { + std::string key; + if (GetArgument(args, 0, key)) { + return dict->GetFirstBoolean(key); } - - - TObject CallMethod(GCList& ls, std::string key, std::vector args) - { - if(!ctx->IsAvailable()) return Undefined(); - else if(key == "AddValue") - { - std::string key; - std::string value; - int64_t i64; - double d64; - std::shared_ptr da; - if(GetArgument(args,0,key) ) - { - if(GetArgument(args,1,value)) - this->dict->AddValue(key,value); - else if(GetArgument(args,1,i64)) - this->dict->AddValue(key,i64); - else if(GetArgument(args,1,d64)) - this->dict->AddValue(key, d64); - else if(GetArgument(args,1,da)) - this->dict->AddValue(key, *da); - } - } - else if(key == "SetValue") - { - std::string key; - std::string value; - int64_t i64; - double d64; - std::shared_ptr da; - if(GetArgument(args,0,key) ) - { - if(GetArgument(args,1,value)) - this->dict->SetValue(key,value); - else if(GetArgument(args,1,i64)) - this->dict->SetValue(key,i64); - else if(GetArgument(args,1,d64)) - this->dict->SetValue(key, d64); - else if(GetArgument(args,1,da)) - this->dict->SetValue(key, *da); - } - } - else if(key == "Clear") - { - std::string key; - bool existsAfter; - if(GetArgument(args,0,key) && GetArgument(args,0, existsAfter)) - dict->Clear(key,existsAfter); - else dict->Clear(); - - } - else if(key == "GetFirstBoolean") - { - std::string key; - if(GetArgument(args,0,key)) - { - return dict->GetFirstBoolean(key); - } - return false; - } - else if(key == "TryGetFirst") - { - std::string key; - std::string value; - if(GetArgument(args,0,key) && dict->TryGetFirst(key,value)) - { - return value; - } - return nullptr; - } - else if(key == "TryGetFirstDouble") - { - std::string key; - double value; - if(GetArgument(args,0,key) && dict->TryGetFirstDouble(key,value)) - { - return value; - } - return nullptr; - } - else if(key == "TryGetFirstInt") - { - std::string key; - int64_t value; - if(GetArgument(args,0,key) && dict->TryGetFirstInt(key,value)) - { - return value; - } - return nullptr; - } - else if(key == "TryGetFirstDate") - { - std::string key; - Tesses::Framework::Date::DateTime value; - if(GetArgument(args,0,key) && dict->TryGetFirstDate(key,value)) - { - return std::make_shared(value); - } - return nullptr; - } - else if(key == "ToList") - { - TList* _ls = TList::Create(ls); - for(auto item : dict->kvp) - { - for(auto i : item.second) - { - auto d = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - d->SetValue("Key", item.first); - d->SetValue("Value", i); - _ls->Add(d); - ls.GetGC()->BarrierEnd(); - } - } - return _ls; - } - else if(key == "SetContentDisposition") - { - std::string type; - std::string filename; - std::string fieldName; - - if(GetArgument(args,0,filename) && GetArgument(args,1,type)) - { - ContentDisposition dispo; - dispo.filename = filename; - dispo.type = type; - - if(GetArgument(args,2, fieldName)) - dispo.fieldName = fieldName; - - this->dict->SetValue("Content-Disposition", dispo.ToString()); - } - return nullptr; - } - else if(key == "TryGetContentDisposition") - { - std::string cdStr; - ContentDisposition cd; - - if(this->dict->TryGetFirst("Content-Disposition", cdStr) && ContentDisposition::TryParse(cdStr,cd)) - { - return TDictionary::Create(ls,{ - TDItem("Type",cd.type), - TDItem("FileName",cd.filename), - TDItem("FieldName",cd.fieldName) - }); - } - - return nullptr; - } - return Undefined(); + return false; + } else if (key == "TryGetFirst") { + std::string key; + std::string value; + if (GetArgument(args, 0, key) && dict->TryGetFirst(key, value)) { + return value; } - }; - - class TServerContext : public TNativeObjectThatReturnsHttpDictionary - { - ServerContext* ctx; - public: - TServerContext(ServerContext* ctx) - { - this->ctx = ctx; + return nullptr; + } else if (key == "TryGetFirstDouble") { + std::string key; + double value; + if (GetArgument(args, 0, key) && + dict->TryGetFirstDouble(key, value)) { + return value; } - std::string TypeName() - { - return "Net.Http.ServerContext"; + return nullptr; + } else if (key == "TryGetFirstInt") { + std::string key; + int64_t value; + if (GetArgument(args, 0, key) && dict->TryGetFirstInt(key, value)) { + return value; } - bool IsAvailable() - { - return ctx != nullptr; + return nullptr; + } else if (key == "TryGetFirstDate") { + std::string key; + Tesses::Framework::Date::DateTime value; + if (GetArgument(args, 0, key) && + dict->TryGetFirstDate(key, value)) { + return std::make_shared( + value); } - ServerContext* GetContext() - { - return this->ctx; - } - TObject CallMethod(GCList& ls,std::string key, std::vector args) - { - if(this->ctx == nullptr) return Undefined(); - else if(key == "getEncrypted") return ctx->encrypted; - else if(key == "getMethod") return ctx->method; - else if(key == "getIP") return ctx->ip; - else if(key == "getPort") return ctx->port; - else if(key == "getOriginalPath") return ctx->originalPath; - else if(key == "getPath") return ctx->path; - else if(key == "setPath") { - std::string str; - if(GetArgument(args,0,str)) - { - ctx->path = str; - return str; - } + return nullptr; + } else if (key == "ToList") { + TList *_ls = TList::Create(ls); + for (auto item : dict->kvp) { + for (auto i : item.second) { + auto d = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + d->SetValue("Key", item.first); + d->SetValue("Value", i); + _ls->Add(d); + ls.GetGC()->BarrierEnd(); } - else if(key == "getVersion") return ctx->version; - else if(key == "setStatusCode") { - int64_t sc; - if(GetArgument(args,0,sc)) - { - ctx->statusCode = (StatusCode)sc; - return sc; - } - } - else if(key == "getStatusCode") return ctx->statusCode; - else if(key == "getQueryParams") return TNativeObject::Create(ls, &ctx->queryParams,this); - else if(key == "getRequestHeaders") return TNativeObject::Create(ls, &ctx->requestHeaders,this); - else if(key == "getResponseHeaders") return TNativeObject::Create(ls, &ctx->responseHeaders,this); - else if(key == "getPathArguments") return TNativeObject::Create(ls,&ctx->pathArguments, this); - else if(key == "GetStream") return ctx->GetStream(); - else if(key == "OpenRequestStream") return ctx->OpenRequestStream(); - else if(key == "OpenResponseStream") return ctx->OpenResponseStream(); - else if(key == "ParseFormData") - { - TCallable* callable; - std::shared_ptr vfs; - - if(GetArgumentHeap(args, 0, callable)) - { - ctx->ParseFormData([callable,&ls](std::string a,std::string b, std::string c)->std::shared_ptr { - auto res = callable->Call(ls,{a,b,c}); - std::shared_ptr strm; - if(GetObject(res,strm)) - { - return strm; - } - return nullptr; - }); - } - else if(GetArgument(args,0,vfs)) - { - int i = 1; - std::vector response; - ctx->ParseFormData([vfs,&response,&ls,&i](std::string mime,std::string filename, std::string name)->std::shared_ptr { - std::string realFileName = "/" + std::to_string(i) + ".bin"; - i++; - response.push_back(TDictionary::Create(ls,{ - TDItem("RealFileName", realFileName), - TDItem("FileName", filename), - TDItem("Mime", mime), - TDItem("Name", name) - })); + } + return _ls; + } else if (key == "SetContentDisposition") { + std::string type; + std::string filename; + std::string fieldName; - auto strm = vfs->OpenFile(realFileName,"wb"); - + if (GetArgument(args, 0, filename) && GetArgument(args, 1, type)) { + ContentDisposition dispo; + dispo.filename = filename; + dispo.type = type; + if (GetArgument(args, 2, fieldName)) + dispo.fieldName = fieldName; + + this->dict->SetValue("Content-Disposition", dispo.ToString()); + } + return nullptr; + } else if (key == "TryGetContentDisposition") { + std::string cdStr; + ContentDisposition cd; + + if (this->dict->TryGetFirst("Content-Disposition", cdStr) && + ContentDisposition::TryParse(cdStr, cd)) { + return TDictionary::Create(ls, + {TDItem("Type", cd.type), + TDItem("FileName", cd.filename), + TDItem("FieldName", cd.fieldName)}); + } + + return nullptr; + } + return Undefined(); + } +}; + +class TServerContext : public TNativeObjectThatReturnsHttpDictionary { + ServerContext *ctx; + + public: + TServerContext(ServerContext *ctx) { this->ctx = ctx; } + std::string TypeName() { return "Net.Http.ServerContext"; } + bool IsAvailable() { return ctx != nullptr; } + ServerContext *GetContext() { return this->ctx; } + TObject CallMethod(GCList &ls, std::string key, std::vector args) { + if (this->ctx == nullptr) + return Undefined(); + else if (key == "getEncrypted") + return ctx->encrypted; + else if (key == "getMethod") + return ctx->method; + else if (key == "getIP") + return ctx->ip; + else if (key == "getPort") + return ctx->port; + else if (key == "getOriginalPath") + return ctx->originalPath; + else if (key == "getPath") + return ctx->path; + else if (key == "setPath") { + std::string str; + if (GetArgument(args, 0, str)) { + ctx->path = str; + return str; + } + } else if (key == "getVersion") + return ctx->version; + else if (key == "setStatusCode") { + int64_t sc; + if (GetArgument(args, 0, sc)) { + ctx->statusCode = (StatusCode)sc; + return sc; + } + } else if (key == "getStatusCode") + return ctx->statusCode; + else if (key == "getQueryParams") + return TNativeObject::Create(ls, &ctx->queryParams, + this); + else if (key == "getRequestHeaders") + return TNativeObject::Create( + ls, &ctx->requestHeaders, this); + else if (key == "getResponseHeaders") + return TNativeObject::Create( + ls, &ctx->responseHeaders, this); + else if (key == "getPathArguments") + return TNativeObject::Create( + ls, &ctx->pathArguments, this); + else if (key == "GetStream") + return ctx->GetStream(); + else if (key == "OpenRequestStream") + return ctx->OpenRequestStream(); + else if (key == "OpenResponseStream") + return ctx->OpenResponseStream(); + else if (key == "ParseFormData") { + TCallable *callable; + std::shared_ptr vfs; + + if (GetArgumentHeap(args, 0, callable)) { + ctx->ParseFormData( + [callable, &ls](std::string a, std::string b, std::string c) + -> std::shared_ptr { + auto res = callable->Call(ls, {a, b, c}); + std::shared_ptr + strm; + if (GetObject(res, strm)) { return strm; - }); - - return TList::Create(ls, response.begin(), response.end()); - } - } - else if(key == "getNeedToParseFormData") return ctx->NeedToParseFormData(); - else if(key == "ReadString") return ctx->ReadString(); - else if(key == "ReadStream") { - std::shared_ptr strm; - if(GetArgument(args,0,strm)) - { - ctx->ReadStream(strm); - } - } - else if(key == "ReadJson") - { - return Json_Decode(ls,ctx->ReadString()); - } - else if(key == "SendJson") - { - if(args.size() > 0) - { - ctx->WithMimeType("application/json").SendText(Json_Encode(args[0])); - } - } - else if(key == "SendText") - { - std::string text; - if(GetArgument(args,0,text)) - ctx->SendText(text); - } - else if(key == "WithMimeType") - { - std::string text; - if(GetArgument(args,0,text)) - ctx->WithMimeType(text); - return this; - } - else if(key == "WithLastModified") - { - std::shared_ptr da; - if(GetArgument(args,0,da)) - ctx->WithLastModified(*da); - return this; - } - else if(key == "WithDebug") - { - bool debug=true; - GetArgument(args,0,debug); - - ctx->WithDebug(debug); - - return this; - } - - else if(key == "getDebug") - { - return ctx->Debug(); - } - else if(key == "SendServerSentEvents") - { - if(!args.empty() && std::holds_alternative>(args[0])) - { - ctx->SendServerSentEvents(std::get>(args[0])); - } - - } - else if(key == "WithHeaderIntercepter") - { - TCallable* callable; - if(GetArgumentHeap(args, 0, callable)) - { - auto marked = CreateMarkedTObject(ls.GetGC(),callable); - ctx->WithHeaderIntercepter([marked](ServerContext& ctx)->bool { - auto obj = marked->GetObject(); - TCallable* callable; - if(GetObjectHeap(obj, callable)) - { - GCList ls(marked->GetGC()); - - auto ptr=TNativeObject::Create(ls, &ctx); - - auto res = callable->Call(ls, {ptr}); - ptr->Finish(); - bool r0; - if(GetObject(res, r0)) return r0; - - - } - - return false; - }); - } - return this; - } - else if(key == "WithContentDisposition") - { - std::string filename; - bool isInline; - if(GetArgument(args,0,filename) && GetArgument(args,1,isInline)) - ctx->WithContentDisposition(filename,isInline); - return this; - } - else if(key == "WithHeader") - { - std::string key; - std::string value; - if(GetArgument(args,0,key) && GetArgument(args,1,value)) - ctx->WithHeader(key,value); - return this; - } - else if(key == "WithSingleHeader") - { - std::string key; - std::string value; - if(GetArgument(args,0,key) && GetArgument(args,1,value)) - ctx->WithSingleHeader(key,value); - return this; - } - else if(key == "SendStream") - { - std::shared_ptr strm; - if(GetArgument(args,0,strm)) - ctx->SendStream(strm); - - } - else if(key == "SendBytes") - { - TByteArray* ba; - if(GetArgumentHeap(args,0,ba)) - ctx->SendBytes(ba->data); - } - else if(key == "GetUrlWithQuery") - { - return ctx->GetUrlWithQuery(); - } - else if(key == "GetOriginalPathWithQuery") - { - return ctx->GetOriginalPathWithQuery(); - } - else if(key == "MakeAbsolute") - { - std::string path; - if(GetArgument(args,0,path)) - { - return ctx->MakeAbsolute(path); - - } - return nullptr; - } - else if(key == "WithLocationHeader") - { - std::string path; - if(GetArgument(args,0,path)) - { - int64_t sc; - if(GetArgument(args,1,sc)) - { - ctx->WithLocationHeader(path,(StatusCode)sc); - return nullptr; } - ctx->WithLocationHeader(path); - - } - return this; - } - else if(key == "GetServerRoot") - { - return ctx->GetServerRoot(); - } - else if(key == "SendRedirect") - { - std::string path; - if(GetArgument(args,0,path)) - { - int64_t sc; - if(GetArgument(args,1,sc)) - { - ctx->SendRedirect(path,(StatusCode)sc); - return nullptr; - } - ctx->SendRedirect(path); - - } - return nullptr; - } - else if(key == "WriteHeaders") ctx->WriteHeaders(); - else if(key == "StartWebSocketSession") { - TDictionary* dict; - TClassObject* cls; - if(GetArgumentHeap(args,0,dict)) - { - - - ctx->StartWebSocketSession([dict,&ls](std::function sendMessage,std::function ping,std::function close)->void{ - GCList ls2(ls.GetGC()); - dict->CallMethod(ls2,"Open",{ - TExternalMethod::Create(ls2,"Send a message",{"messageTextOrByteArray"},[sendMessage](GCList& ls,std::vector args)->TObject{ - std::string str; - TByteArray* bArray; - if(GetArgument(args,0,str)) - { - WebSocketMessage msg(str); - sendMessage(msg); - } - else if(GetArgumentHeap(args,0,bArray)) - { - WebSocketMessage msg(bArray->data); - sendMessage(msg); - } - return nullptr; - }), - TExternalMethod::Create(ls2, "Ping client", {},[ping](GCList& ls,std::vector args)->TObject { - ping(); - return nullptr; - }), - TExternalMethod::Create(ls2, "Close client",{},[close](GCList& ls,std::vector args)->TObject { - close(); - return nullptr; - }) + return nullptr; }); - }, [dict,&ls](WebSocketMessage& msg)->void { - GCList ls2(ls.GetGC()); + } else if (GetArgument(args, 0, vfs)) { + int i = 1; + std::vector response; + ctx->ParseFormData( + [vfs, &response, &ls, &i](std::string mime, + std::string filename, + std::string name) + -> std::shared_ptr { + std::string realFileName = + "/" + std::to_string(i) + ".bin"; + i++; + response.push_back(TDictionary::Create( + ls, {TDItem("RealFileName", realFileName), + TDItem("FileName", filename), + TDItem("Mime", mime), TDItem("Name", name)})); - TObject v; + auto strm = vfs->OpenFile(realFileName, "wb"); - if(msg.isBinary) - { - auto r = TByteArray::Create(ls2); - r->data = msg.data; - v = r; - } - else - { - v = msg.ToString(); - } - - dict->CallMethod(ls2,"Receive",{v}); - }, [dict,&ls](bool close)->void { - GCList ls2(ls.GetGC()); - dict->CallMethod(ls2,"Close",{close}); - }); - } else if(GetArgumentHeap(args, 0, cls)) - { - ctx->StartWebSocketSession([cls,&ls](std::function sendMessage,std::function ping,std::function close)->void{ - GCList ls2(ls.GetGC()); - cls->CallMethod(ls2,"","Open",{ - TExternalMethod::Create(ls2,"Send a message",{"messageTextOrByteArray"},[sendMessage](GCList& ls,std::vector args)->TObject{ - std::string str; - TByteArray* bArray; - if(GetArgument(args,0,str)) - { - WebSocketMessage msg(str); - sendMessage(msg); - } - else if(GetArgumentHeap(args,0,bArray)) - { - WebSocketMessage msg(bArray->data); - sendMessage(msg); - } - return nullptr; - }), - TExternalMethod::Create(ls2, "Ping client", {},[ping](GCList& ls,std::vector args)->TObject { - ping(); - return nullptr; - }), - TExternalMethod::Create(ls2, "Close client",{},[close](GCList& ls,std::vector args)->TObject { - close(); - return nullptr; - }) + return strm; }); - }, [cls,&ls](WebSocketMessage& msg)->void { - GCList ls2(ls.GetGC()); - TObject v; - - if(msg.isBinary) - { - auto r = TByteArray::Create(ls2); - r->data = msg.data; - v = r; - } - else - { - v = msg.ToString(); - } - - cls->CallMethod(ls2,"","Receive",{v}); - }, [cls,&ls](bool close)->void { - GCList ls2(ls.GetGC()); - cls->CallMethod(ls2,"","Close",{close}); - }); + return TList::Create(ls, response.begin(), response.end()); } - - } - - return Undefined(); - } - - void Finish() - { - this->ctx = nullptr; - } - }; - - TObjectHttpServer::TObjectHttpServer(std::shared_ptr gc,TObject obj) - { - this->ls=new GCList(gc); - this->ls->Add(obj); - this->obj = obj; - } - - class TDictionaryHttpRequestBody : public HttpRequestBody - { - std::shared_ptr gc; - TDictionary* req; - public: - TDictionaryHttpRequestBody(std::shared_ptr gc,TDictionary* req) - { - this->gc = gc; - this->req = req; - } - - void HandleHeaders(HttpDictionary& dict) - { - GCList ls(gc); - auto dummy = TNativeObject::Create(ls); - auto res=TNativeObject::Create(ls,&dict, dummy); - req->CallMethod(ls,"HandleHeaders",{res}); - dummy->Close(); - } - void Write(std::shared_ptr strm) - { - GCList ls(gc); - - req->CallMethod(ls,"Write",{strm}); - - } - - ~TDictionaryHttpRequestBody() - { - GCList ls(gc); - req->CallMethod(ls,"Close",{}); - } - }; - - bool TObjectHttpServer::Handle(ServerContext& ctx) - { - TCallable* callable; - TDictionary* dict; - TClassObject* clsObj; - if(GetObjectHeap(this->obj,callable)) - { - GCList ls2(this->ls->GetGC()); - auto res = TNativeObject::Create(ls2, &ctx); - bool result; - auto out = callable->Call(ls2,{res}); - if(GetObject(out,result)) - { - res->Finish(); - return result; - } - res->Finish(); - } - else if(GetObjectHeap(this->obj,dict)) - { - GCList ls2(this->ls->GetGC()); - auto res = TNativeObject::Create(ls2, &ctx); - bool result; - auto out = dict->CallMethod(ls2,"Handle",{res}); - if(GetObject(out,result)) - { - res->Finish(); - return result; - } - res->Finish(); - } - else if(GetObjectHeap(this->obj,clsObj) && clsObj->HasMethod("","Handle")) - { - GCList ls2(this->ls->GetGC()); - auto res = TNativeObject::Create(ls2, &ctx); - bool result; - this->ls->GetGC()->BarrierBegin(); - auto callableO = clsObj->GetValue("","Handle"); - this->ls->GetGC()->BarrierEnd(); - TCallable* callable; - if(GetObjectHeap(callableO, callable)) - { - auto out = callable->Call(ls2,{res}); - if(GetObject(out,result)) - { - res->Finish(); - return result; - } - res->Finish(); - } - - } - - return false; - } - TObjectHttpServer::~TObjectHttpServer() - { - delete ls; - } - - static TObject Net_UrlDecode(GCList& ls, std::vector args) - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - return HttpUtils::UrlDecode(std::get(args[0])); - } - return Undefined(); - } - static TObject Net_HtmlEncode(GCList& ls, std::vector args) - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - return HttpUtils::HtmlEncode(std::get(args[0])); - } - return Undefined(); - } - static TObject Net_UrlEncode(GCList& ls, std::vector args) - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - return HttpUtils::UrlEncode(std::get(args[0])); - } - return Undefined(); - } - static TObject Net_UrlPathDecode(GCList& ls, std::vector args) - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - return HttpUtils::UrlPathDecode(std::get(args[0])); - } - return Undefined(); - } - static TObject Net_UrlPathEncode(GCList& ls, std::vector args) - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - return HttpUtils::UrlPathEncode(std::get(args[0])); - } - return Undefined(); - } - static TObject New_NetworkStream(GCList& ls, std::vector args) - { - bool ipv6; - bool datagram; - if(GetArgument(args,0,ipv6) && GetArgument(args,1,datagram)) - { - return std::make_shared(ipv6,datagram); - } - return nullptr; - } - class HttpServerNativeObject : public TNativeObject - { - HttpServer* server; - public: - HttpServerNativeObject(uint16_t port, std::shared_ptr httpServer,bool printIps) - { - server=new HttpServer(port,httpServer,printIps); - } - HttpServerNativeObject(std::string unixPath, std::shared_ptr httpServer) - { - server=new HttpServer(unixPath,httpServer); - } - std::string TypeName() - { - return "Net.Http.HttpServer"; - } - TObject CallMethod(GCList& ls, std::string key, std::vector args) - { - if(key == "getPort") - { - return (int64_t)server->GetPort(); - } - if(key == "StartAccepting") - server->StartAccepting(); - return nullptr; - } - ~HttpServerNativeObject() - { - delete server; - } - }; - - static TObject New_HttpServer(GCList& ls, std::vector args,TRootEnvironment* env) - { - int64_t port; - std::string pathStr; - if(GetArgument(args,1,port)) - { - bool printIPs=true; - GetArgument(args,2,printIPs); - - std::shared_ptr httpSvr = ToHttpServer(ls.GetGC(),args[0]); - - if(httpSvr) { - uint16_t p = (uint16_t)port; - return TNativeObject::Create(ls,port,httpSvr,printIPs); - } - - } - - if(GetArgument(args,1,pathStr) && env->permissions.localfs) - { - std::shared_ptr httpSvr = ToHttpServer(ls.GetGC(),args[0]); - - - if(httpSvr) { - return TNativeObject::Create(ls,pathStr,httpSvr); - } - - - } - return nullptr; - } - static TObject Net_Http_ListenSimpleWithLoop(GCList& ls, std::vector args) - { - int64_t port; - if(GetArgument(args,1,port)) - { - std::shared_ptr httpSvr = ToHttpServer(ls.GetGC(),args[0]); - - if(httpSvr) { - uint16_t p = (uint16_t)port; - HttpServer server(p,httpSvr); - server.StartAccepting(); - Tesses::Framework::TF_RunEventLoop(); - } - - } - return nullptr; - } - static TObject Net_Http_ListenOnUnusedPort(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr httpSvr=ToHttpServer(ls.GetGC(),args.front()); - if(httpSvr) { - uint16_t p = 0; - HttpServer server(p,httpSvr); - std::cout << "Port: " << server.GetPort() << std::endl; - server.StartAccepting(); - - Tesses::Framework::TF_RunEventLoop(); - } - - return nullptr; - } - static TObject Net_Http_MimeType(GCList& ls, std::vector args) - { - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgumentAsPath(args,0,p)) - { - std::filesystem::path p2 = p.GetFileName(); - return HttpUtils::MimeType(p2); - } - return std::string("application/octet-stream"); - } - class THttpRequestBody : public TNativeObject { - HttpRequestBody* body; - public: - THttpRequestBody(HttpRequestBody* body) - { - this->body = body; - } - bool IsClosed() - { - return body == nullptr; - } - HttpRequestBody* GetBody() - { - return this->body; - } - - std::string TypeName() - { - return "Net.Http.HttpRequestBody"; - } - - TObject CallMethod(GCList& ls, std::string key, std::vector args) - { - return Undefined(); - } - - void Close() - { - delete this->body; - this->body = nullptr; - } - }; - - class THttpResponse : public TNativeObjectThatReturnsHttpDictionary - { - HttpResponse* response; - public: - THttpResponse(HttpResponse* resp) - { - this->response = resp; - } - bool IsAvailable() - { - return this->response != nullptr; - } - - void Close() - { - delete this->response; - this->response = nullptr; - } - - ~THttpResponse() - { - delete this->response; - this->response = nullptr; - } - std::string TypeName() - { - return "Net.Http.HttpResponse"; - } - - TObject CallMethod(GCList& ls, std::string key, std::vector args) - { - if(!this->IsAvailable()) return Undefined(); - - else if(key == "CopyToStream") - { - std::shared_ptr strm; - if(GetArgument(args,0,strm)) - { - response->CopyToStream(strm); - } - } - else if(key == "ReadAsString") - { - return response->ReadAsString(); - } - else if(key == "ReadAsJson") - { - return Json_Decode(ls, response->ReadAsString()); - } - else if(key == "ReadAsStream") - { - - - return response->ReadAsStream(); - } - else if(key == "getStatusCode") - { - return (int64_t)response->statusCode; - } - else if(key == "getVersion") - { - return response->version; - } - else if(key == "getResponseHeaders") - { - return TNativeObject::Create(ls,&response->responseHeaders, this); - } - - return Undefined(); - } - }; - - static TObject Net_Http_MakeRequest(GCList& ls, std::vector args,TRootEnvironment* env) - { - auto gc = ls.GetGC(); - std::string url; - - if(GetArgument(args,0,url)) - { - TDictionary* body1=nullptr; - THttpRequestBody* body2=nullptr; - HttpRequest req; - req.method = "GET"; - req.ignoreSSLErrors=false; - req.followRedirects=false; - req.trusted_root_cert_bundle=""; - req.url = url; - req.body = nullptr; - - TDictionary* options; - if(GetArgumentHeap(args,1,options)) - { - gc->BarrierBegin(); - auto _obj = options->GetValue("Method"); - GetObject(_obj,req.method); - _obj = options->GetValue("IgnoreSSLErrors"); - GetObject(_obj,req.ignoreSSLErrors); - _obj = options->GetValue("FollowRedirects"); - GetObject(_obj,req.followRedirects); - _obj = options->GetValue("TrustedRootCertBundle"); - GetObject(_obj,req.trusted_root_cert_bundle); - if(env->permissions.localfs) - { - _obj = options->GetValue("UnixSocket"); - GetObject(_obj,req.unixSocket); - } - - _obj = options->GetValue("RequestHeaders"); - - TList* headers; - - if(GetObjectHeap(_obj, headers)) - { - for(int64_t index = 0; index < headers->Count();index ++) - { - _obj = headers->Get(index); - TDictionary* dict; - if(GetObjectHeap(_obj,dict)) - { - std::string key={}; - std::string value={}; - _obj = dict->GetValue("Key"); - GetObject(_obj,key); - _obj = dict->GetValue("Value"); - GetObject(_obj,value); - - req.requestHeaders.AddValue(key,value); - } - } - } - _obj = options->GetValue("Body"); - - - - if(GetObjectHeap(_obj, body1)) - { - req.body = new TDictionaryHttpRequestBody(gc,body1); - } - else if(GetObjectHeap(_obj,body2) && !body2->IsClosed()) - { - req.body = body2->GetBody(); - } - - - gc->BarrierEnd(); - } - - - HttpResponse* resp = new HttpResponse(req); - - if(req.body != nullptr) - { - if(body2 != nullptr) - { - body2->Close(); - } - else if(body1 != nullptr) - { - delete req.body; - } - } - - - return TNativeObject::Create(ls, resp); - - } - - - return nullptr; - } - - static TObject Net_Smtp_Send(GCList& ls, std::vector args) - { - TDictionary* dict; - if(GetArgumentHeap(args,0,dict)) - { - //the body should be either type text/plain or text/html - //the body and attachment data can also point to bytearray of stream - //server can also be a stream - //as of right now the email is fire and forget (ie no error checking) - //check function return type just in case (this function returns a empty string if no error) - //we rolled our own smtp client - - /* - dict looks like this from crosslang's point of view - { - server = { - host = "smtp.example.com", - tls = true - }, - auth = { - username = "from", - password = "THEPASSWORD" - }, - domain = "example.com", - from = { - name = "The name shown in the mail where it is from", - email = "from@example.com" - }, - to = "to@example.com", - subject = "My little message", - body = { - type = "text/html", - data = "

Hello, world

" - }, - attachments = [ - { - name = "myimg.png", - type = "image/png", - data = embed("myimg.png") - } - ] - } - */ - ls.GetGC()->BarrierBegin(); - auto server = dict->GetValue("server"); - TDictionary* dict2; + } else if (key == "getNeedToParseFormData") + return ctx->NeedToParseFormData(); + else if (key == "ReadString") + return ctx->ReadString(); + else if (key == "ReadStream") { std::shared_ptr strm; - bool ownsStream=true; - std::shared_ptr objStrm; - if(GetObjectHeap(server,dict2)) - { - auto tlsO = dict2->GetValue("tls"); - auto hostO = dict2->GetValue("host"); - auto portO = dict2->GetValue("port"); - std::string host; - bool tls=false; - int64_t port; - GetObject(tlsO,tls); - - if(!GetObject(portO, port)) port = tls ? 465 : 25; - - GetObject(hostO,host); - strm = std::make_shared(host,(uint16_t)port,false,false,false); - if(tls) - { - strm = std::make_shared(strm,true,host); - } + if (GetArgument(args, 0, strm)) { + ctx->ReadStream(strm); + } + } else if (key == "ReadJson") { + return Json_Decode(ls, ctx->ReadString()); + } else if (key == "SendJson") { + if (args.size() > 0) { + ctx->WithMimeType("application/json") + .SendText(Json_Encode(args[0])); + } + } else if (key == "SendText") { + std::string text; + if (GetArgument(args, 0, text)) + ctx->SendText(text); + } else if (key == "WithMimeType") { + std::string text; + if (GetArgument(args, 0, text)) + ctx->WithMimeType(text); + return this; + } else if (key == "WithLastModified") { + std::shared_ptr da; + if (GetArgument(args, 0, da)) + ctx->WithLastModified(*da); + return this; + } else if (key == "WithDebug") { + bool debug = true; + GetArgument(args, 0, debug); - } - else if (GetObject(server, objStrm)) { - ownsStream=false; - strm = objStrm; - } + ctx->WithDebug(debug); - Tesses::Framework::Mail::SMTPClient client(strm); - auto o = dict->GetValue("domain"); - - GetObject(o,client.domain); - o = dict->GetValue("to"); - GetObject(o,client.to); - o = dict->GetValue("subject"); - GetObject(o,client.subject); - o = dict->GetValue("auth"); - if(GetObjectHeap(o, dict2)) - { - o = dict2->GetValue("username"); - GetObject(o,client.username); - o = dict2->GetValue("password"); - GetObject(o, client.password); - } - o = dict->GetValue("from"); - if(GetObjectHeap(o, dict2)) - { - o = dict2->GetValue("email"); - GetObject(o,client.from); - o = dict2->GetValue("name"); - GetObject(o, client.from_name); - } - o = dict->GetValue("body"); - if(GetObjectHeap(o, dict2)) - { - //type, data - std::string type = "text/plain"; - o = dict2->GetValue("type"); - GetObject(o,type); - o = dict2->GetValue("data"); - client.body = TObjectToSMTPBody(ls,type,o); - } - o = dict->GetValue("attachments"); - TList* als; - if(GetObjectHeap(o,als)) - { - for(int64_t i = 0; i < als->Count(); i++) - { - auto item = als->Get(i); - if(GetObjectHeap(item, dict2)) - { - o = dict2->GetValue("name"); - std::string name; - GetObject(o,name); - std::string type = "text/plain"; - o = dict2->GetValue("type"); - GetObject(o,type); - o = dict2->GetValue("data"); - - client.attachments.push_back(std::pair>(name,TObjectToSMTPBody(ls, type, o))); - } - } - } - - ls.GetGC()->BarrierEnd(); - client.Send(); - return ""; + return this; } - return nullptr; - } - static TObject Net_Http_WebSocketClient(GCList& ls, std::vector args) - { - std::string url; - TList* headers; - TDictionary* dict; - TClassObject* co; - TCallable* callable=nullptr; - - - - TObject _obj; - if(GetArgument(args,0,url) && GetArgumentHeap(args,1,headers) && GetArgumentHeap(args,2,dict)) - { - GetArgumentHeap(args,3,callable); - HttpDictionary hdict; - for(int64_t index = 0; index < headers->Count();index ++) - { - _obj = headers->Get(index); - TDictionary* dict; - if(GetObjectHeap(_obj,dict)) - { - std::string key={}; - std::string value={}; - _obj = dict->GetValue("Key"); - GetObject(_obj,key); - _obj = dict->GetValue("Value"); - GetObject(_obj,value); - hdict.AddValue(key,value); - } - } - auto conn = std::make_shared([dict,&ls](std::function sendMessage,std::function ping,std::function close)->void{ - GCList ls2(ls.GetGC()); - dict->CallMethod(ls2,"Open",{ - TExternalMethod::Create(ls2,"Send a message",{"messageTextOrByteArray"},[sendMessage](GCList& ls,std::vector args)->TObject{ - std::string str; - TByteArray* bArray; - if(GetArgument(args,0,str)) - { - WebSocketMessage msg(str); - sendMessage(msg); - } - else if(GetArgumentHeap(args,0,bArray)) - { - WebSocketMessage msg(bArray->data); - sendMessage(msg); - } - return nullptr; - }), - TExternalMethod::Create(ls2, "Ping client", {},[ping](GCList& ls,std::vector args)->TObject { - ping(); - return nullptr; - }), - TExternalMethod::Create(ls2, "Close client",{},[close](GCList& ls,std::vector args)->TObject { - close(); - return nullptr; - }) - }); - }, [dict,&ls](WebSocketMessage& msg)->void { - GCList ls2(ls.GetGC()); - - TObject v; - - if(msg.isBinary) - { - auto r = TByteArray::Create(ls2); - r->data = msg.data; - v = r; - } - else - { - v = msg.ToString(); - } - - dict->CallMethod(ls2,"Receive",{v}); - }, [dict,&ls](bool close)->void { - GCList ls2(ls.GetGC()); - dict->CallMethod(ls2,"Close",{close}); - }); - WebSocketClient(url, hdict, conn, [&ls,callable](Tesses::Framework::Http::HttpDictionary& dict, bool success)->bool { - if(callable != nullptr) - { - auto dummy = TNativeObject::Create(ls); - bool res= ToBool(callable->Call(ls,{TNativeObject::Create(ls,&dict,dummy),success})); - dummy->Close(); - return res; - } - return true; - }); - } - else if(GetArgument(args,0, url) && GetArgumentHeap(args,1,co)) { - TObject hobj; - if(co->HasMethod("","GetRequestHeaders")) - hobj = co->CallMethod(ls,"","GetRequestHeaders",{}); - else if(co->HasField("","RequestHeaders")) - hobj = co->GetValue("","RequestHeaders"); - else return Undefined(); - - if(!GetObjectHeap(hobj,headers)) return Undefined(); - - HttpDictionary hdict; - for(int64_t index = 0; index < headers->Count();index ++) - { - _obj = headers->Get(index); - TDictionary* dict; - if(GetObjectHeap(_obj,dict)) - { - std::string key={}; - std::string value={}; - _obj = dict->GetValue("Key"); - GetObject(_obj,key); - _obj = dict->GetValue("Value"); - GetObject(_obj,value); - hdict.AddValue(key,value); - } + else if (key == "getDebug") { + return ctx->Debug(); + } else if (key == "SendServerSentEvents") { + if (!args.empty() && + std::holds_alternative< + std::shared_ptr>( + args[0])) { + ctx->SendServerSentEvents( + std::get>(args[0])); } - auto conn = std::make_shared([co,&ls](std::function sendMessage,std::function ping,std::function close)->void{ - GCList ls2(ls.GetGC()); - co->CallMethod(ls2,"","Open",{ - TExternalMethod::Create(ls2,"Send a message",{"messageTextOrByteArray"},[sendMessage](GCList& ls,std::vector args)->TObject{ - std::string str; - TByteArray* bArray; - if(GetArgument(args,0,str)) - { - WebSocketMessage msg(str); - sendMessage(msg); - } - else if(GetArgumentHeap(args,0,bArray)) - { - WebSocketMessage msg(bArray->data); - sendMessage(msg); - } - return nullptr; - }), - TExternalMethod::Create(ls2, "Ping client", {},[ping](GCList& ls,std::vector args)->TObject { - ping(); - return nullptr; - }), - TExternalMethod::Create(ls2, "Close client",{},[close](GCList& ls,std::vector args)->TObject { - close(); - return nullptr; - }) - }); - }, [co,&ls](WebSocketMessage& msg)->void { - GCList ls2(ls.GetGC()); + } else if (key == "WithHeaderIntercepter") { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) { + auto marked = CreateMarkedTObject(ls.GetGC(), callable); + ctx->WithHeaderIntercepter( + [marked](ServerContext &ctx) -> bool { + auto obj = marked->GetObject(); + TCallable *callable; + if (GetObjectHeap(obj, callable)) { + GCList ls(marked->GetGC()); - TObject v; + auto ptr = + TNativeObject::Create(ls, &ctx); - if(msg.isBinary) - { - auto r = TByteArray::Create(ls2); - r->data = msg.data; - v = r; + auto res = callable->Call(ls, {ptr}); + ptr->Finish(); + bool r0; + if (GetObject(res, r0)) + return r0; + } + + return false; + }); + } + return this; + } else if (key == "WithContentDisposition") { + std::string filename; + bool isInline; + if (GetArgument(args, 0, filename) && + GetArgument(args, 1, isInline)) + ctx->WithContentDisposition(filename, isInline); + return this; + } else if (key == "WithHeader") { + std::string key; + std::string value; + if (GetArgument(args, 0, key) && GetArgument(args, 1, value)) + ctx->WithHeader(key, value); + return this; + } else if (key == "WithSingleHeader") { + std::string key; + std::string value; + if (GetArgument(args, 0, key) && GetArgument(args, 1, value)) + ctx->WithSingleHeader(key, value); + return this; + } else if (key == "SendStream") { + std::shared_ptr strm; + if (GetArgument(args, 0, strm)) + ctx->SendStream(strm); + + } else if (key == "SendBytes") { + TByteArray *ba; + if (GetArgumentHeap(args, 0, ba)) + ctx->SendBytes(ba->data); + } else if (key == "GetUrlWithQuery") { + return ctx->GetUrlWithQuery(); + } else if (key == "GetOriginalPathWithQuery") { + return ctx->GetOriginalPathWithQuery(); + } else if (key == "MakeAbsolute") { + std::string path; + if (GetArgument(args, 0, path)) { + return ctx->MakeAbsolute(path); + } + return nullptr; + } else if (key == "WithLocationHeader") { + std::string path; + if (GetArgument(args, 0, path)) { + int64_t sc; + if (GetArgument(args, 1, sc)) { + ctx->WithLocationHeader(path, (StatusCode)sc); + return nullptr; } - else - { - v = msg.ToString(); + ctx->WithLocationHeader(path); + } + return this; + } else if (key == "GetServerRoot") { + return ctx->GetServerRoot(); + } else if (key == "SendRedirect") { + std::string path; + if (GetArgument(args, 0, path)) { + int64_t sc; + if (GetArgument(args, 1, sc)) { + ctx->SendRedirect(path, (StatusCode)sc); + return nullptr; } - - co->CallMethod(ls2,"","Receive",{v}); - }, [co,&ls](bool close)->void { - GCList ls2(ls.GetGC()); - co->CallMethod(ls2,"","Close",{close}); - }); - WebSocketClient(url, hdict, conn, [&ls,co](Tesses::Framework::Http::HttpDictionary& dict, bool success)->bool { - if(co->HasMethod("","HandleResponseHeaders")) - { - auto dummy = TNativeObject::Create(ls); - bool res= ToBool(co->CallMethod(ls,"","HandleResponseHeaders",{TNativeObject::Create(ls,&dict,dummy),success})); - dummy->Close(); - return res; - } - - return true; - }); + ctx->SendRedirect(path); + } + return nullptr; + } else if (key == "WriteHeaders") + ctx->WriteHeaders(); + else if (key == "StartWebSocketSession") { + TDictionary *dict; + TClassObject *cls; + if (GetArgumentHeap(args, 0, dict)) { + + ctx->StartWebSocketSession( + [dict, + &ls](std::function sendMessage, + std::function ping, + std::function close) -> void { + GCList ls2(ls.GetGC()); + dict->CallMethod( + ls2, "Open", + {TExternalMethod::Create( + ls2, "Send a message", + {"messageTextOrByteArray"}, + [sendMessage]( + GCList &ls, + std::vector args) -> TObject { + std::string str; + TByteArray *bArray; + if (GetArgument(args, 0, str)) { + WebSocketMessage msg(str); + sendMessage(msg); + } else if (GetArgumentHeap(args, 0, + bArray)) { + WebSocketMessage msg(bArray->data); + sendMessage(msg); + } + return nullptr; + }), + TExternalMethod::Create( + ls2, "Ping client", {}, + [ping](GCList &ls, + std::vector args) -> TObject { + ping(); + return nullptr; + }), + TExternalMethod::Create( + ls2, "Close client", {}, + [close](GCList &ls, + std::vector args) -> TObject { + close(); + return nullptr; + })}); + }, + [dict, &ls](WebSocketMessage &msg) -> void { + GCList ls2(ls.GetGC()); + + TObject v; + + if (msg.isBinary) { + auto r = TByteArray::Create(ls2); + r->data = msg.data; + v = r; + } else { + v = msg.ToString(); + } + + dict->CallMethod(ls2, "Receive", {v}); + }, + [dict, &ls](bool close) -> void { + GCList ls2(ls.GetGC()); + dict->CallMethod(ls2, "Close", {close}); + }); + } else if (GetArgumentHeap(args, 0, cls)) { + ctx->StartWebSocketSession( + [cls, + &ls](std::function sendMessage, + std::function ping, + std::function close) -> void { + GCList ls2(ls.GetGC()); + cls->CallMethod( + ls2, "", "Open", + {TExternalMethod::Create( + ls2, "Send a message", + {"messageTextOrByteArray"}, + [sendMessage]( + GCList &ls, + std::vector args) -> TObject { + std::string str; + TByteArray *bArray; + if (GetArgument(args, 0, str)) { + WebSocketMessage msg(str); + sendMessage(msg); + } else if (GetArgumentHeap(args, 0, + bArray)) { + WebSocketMessage msg(bArray->data); + sendMessage(msg); + } + return nullptr; + }), + TExternalMethod::Create( + ls2, "Ping client", {}, + [ping](GCList &ls, + std::vector args) -> TObject { + ping(); + return nullptr; + }), + TExternalMethod::Create( + ls2, "Close client", {}, + [close](GCList &ls, + std::vector args) -> TObject { + close(); + return nullptr; + })}); + }, + [cls, &ls](WebSocketMessage &msg) -> void { + GCList ls2(ls.GetGC()); + + TObject v; + + if (msg.isBinary) { + auto r = TByteArray::Create(ls2); + r->data = msg.data; + v = r; + } else { + v = msg.ToString(); + } + + cls->CallMethod(ls2, "", "Receive", {v}); + }, + [cls, &ls](bool close) -> void { + GCList ls2(ls.GetGC()); + cls->CallMethod(ls2, "", "Close", {close}); + }); + } } + return Undefined(); - //Net.Http.CreateWebSocketConnection("wss://example.com/",[],conn, (dict, success)=>{ return true;}) - } - static TObject Net_Http_DownloadToString(GCList& ls, std::vector args) - { - std::string url; - if(GetArgument(args,0,url)) - return DownloadToStringSimple(url); - return nullptr; - } - static TObject Net_Http_DownloadToStream(GCList& ls, std::vector args) - { - std::string url; - std::shared_ptr strm; - if(GetArgument(args,0,url) && GetArgument(args,1,strm)) - { - DownloadToStreamSimple(url,strm); - } - return nullptr; - } - static TObject Net_Http_DownloadToFile(GCList& ls, std::vector args) - { - std::string url; - std::shared_ptr vfs; - Tesses::Framework::Filesystem::VFSPath path; - if(GetArgument(args,0,url) && GetArgument(args,1,vfs) && GetArgumentAsPath(args,2, path)) - { - DownloadToFileSimple(url,vfs,path); - } - return nullptr; - } - bool IHttpServer_Handle(std::shared_ptr svr,std::vector& args) - { - TServerContext* ctx; - if(GetArgumentHeap(args,0,ctx)) - { - return svr->Handle(*ctx->GetContext()); - } - return false; } - std::shared_ptr ToHttpServer(std::shared_ptr gc, TObject obj) - { - if(std::holds_alternative>(obj)) return std::get>(obj); - TDictionary* dict; - TClassObject* clo; - TCallable* call; - if(GetObjectHeap(obj,dict)) - { - return std::make_shared(gc,dict); - } - else if(GetObjectHeap(obj,clo)) - { - return std::make_shared(gc,clo); - } - else if(GetObjectHeap(obj,call)) - { - return std::make_shared(gc,call); - } - return nullptr; + void Finish() { this->ctx = nullptr; } +}; + +TObjectHttpServer::TObjectHttpServer(std::shared_ptr gc, TObject obj) { + this->ls = new GCList(gc); + this->ls->Add(obj); + this->obj = obj; +} + +class TDictionaryHttpRequestBody : public HttpRequestBody { + std::shared_ptr gc; + TDictionary *req; + + public: + TDictionaryHttpRequestBody(std::shared_ptr gc, TDictionary *req) { + this->gc = gc; + this->req = req; } - static TObject Net_Http_HtmlP(GCList& ls, std::vector args) - { - std::string str; - if(GetArgument(args,0,str)) - { - return HttpUtils::HtmlP(str); - } - return ""; + void HandleHeaders(HttpDictionary &dict) { + GCList ls(gc); + auto dummy = + TNativeObject::Create( + ls); + auto res = TNativeObject::Create(ls, &dict, dummy); + req->CallMethod(ls, "HandleHeaders", {res}); + dummy->Close(); } - - static TObject Net_Http_StatusCodeString(GCList& ls, std::vector args) - { - int64_t sc; - if(GetArgument(args,0,sc)) - { - return HttpUtils::StatusCodeString((StatusCode)sc); - } - return ""; - } - static TObject New_FileServer(GCList& ls, std::vector args) - { - std::shared_ptr vfs; - bool allowlisting; - bool spa; - if(GetArgument(args,0,vfs) && GetArgument(args,1,allowlisting) && GetArgument(args,2,spa)) - { - return std::make_shared(vfs,allowlisting,spa); - - } - return nullptr; - } - static TObject New_BasicAuthServer(GCList& ls, std::vector args) - { - auto bAuth = std::make_shared(); - - TCallable* cb; - if(!args.empty()) - bAuth->server = ToHttpServer(ls.GetGC(),args[0]); - - if(GetArgumentHeap(args,1,cb)) - { - auto marked= CreateMarkedTObject(ls, cb); - bAuth->authorization = [marked](std::string user,std::string password)->bool { - GCList ls(marked->GetGC()); - TCallable* callable; - if(GetObjectHeap(marked->GetObject(), callable)) - { - return ToBool(callable->Call(ls,{user,password})); - } - return false; - }; - } - GetArgument(args,2,bAuth->realm); - return bAuth; - } - static TObject New_MountableServer(GCList& ls, std::vector args) - { - if(args.empty()) return std::make_shared(); - return std::make_shared(ToHttpServer(ls.GetGC(),args[0])); - } - static TObject New_RouteServer(GCList& ls, std::vector args) - { - if(args.empty()) return std::make_shared(); - return std::make_shared(ToHttpServer(ls.GetGC(),args[0])); - } - static TObject New_StreamHttpRequestBody(GCList& ls, std::vector args) - { - std::shared_ptr strm; - std::string mimeType; - - if(GetArgument(args,0,strm) && GetArgument(args, 1, mimeType)) - { - return TNativeObject::Create(ls, new StreamHttpRequestBody(strm, mimeType)); - } - return nullptr; - } - static TObject New_TextHttpRequestBody(GCList& ls, std::vector args) - { - std::string text; - std::string mimeType; - if(GetArgument(args, 0, text) && GetArgument(args, 1, mimeType)) - { - return TNativeObject::Create(ls,new TextHttpRequestBody(text, mimeType)); - - } - return nullptr; - } - static TObject New_JsonHttpRequestBody(GCList& ls, std::vector args) - { - - if(!args.empty()) - { - return TNativeObject::Create(ls,new TextHttpRequestBody(Json_Encode(args[0]), "application/json")); - - } - return nullptr; - - } - - static TObject New_ServerSentEvents(GCList& ls, std::vector args) - { - return std::make_shared(); - } - - void TStd::RegisterNet(std::shared_ptr gc, TRootEnvironment* env) - { - - env->permissions.canRegisterNet=true; + void Write(std::shared_ptr strm) { GCList ls(gc); - gc->BarrierBegin(); - TDictionary* dict = env->EnsureDictionary(gc,"Net"); - TDictionary* _new = env->EnsureDictionary(gc,"New"); - _new->DeclareFunction(gc, "StreamHttpRequestBody","Create a stream request body",{"stream","mimeType"},New_StreamHttpRequestBody); - _new->DeclareFunction(gc, "TextHttpRequestBody","Create a text request body",{"text","mimeType"},New_TextHttpRequestBody); - _new->DeclareFunction(gc, "JsonHttpRequestBody","Create a text request body",{"json"},New_JsonHttpRequestBody); - _new->DeclareFunction(gc, "HttpServer", "Create a http server (allows multiple)",{"server","portOrUnixPath","$printIPs"},[env](GCList& ls, std::vector args)->TObject{ - return New_HttpServer(ls,args,env); - }); + req->CallMethod(ls, "Write", {strm}); + } - _new->DeclareFunction(gc, "RouteServer","Create a routeserver",{"$root"}, New_RouteServer); - _new->DeclareFunction(gc, "FileServer","Create a file server",{"vfs","allowlisting","spa"}, New_FileServer); - _new->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", {"$server","$auth","$realm"},New_BasicAuthServer); - _new->DeclareFunction(gc, "MountableServer","Create a server you can mount to, must mount parents before child",{"root"}, New_MountableServer); - _new->DeclareFunction(gc, "NetworkStream","Create a network stream",{"ipv6","datagram"},New_NetworkStream); - - _new->DeclareFunction(gc, "ServerSentEvents", "Create server sent events object",{""},New_ServerSentEvents); - + ~TDictionaryHttpRequestBody() { + GCList ls(gc); + req->CallMethod(ls, "Close", {}); + } +}; - TDictionary* http = TDictionary::Create(ls); - TDictionary* smtp = TDictionary::Create(ls); - http->DeclareFunction(gc, "StatusCodeString", "Get the status code string",{"statusCode"},Net_Http_StatusCodeString); - http->DeclareFunction(gc, "HtmlP", "Linkify text", {"text"},Net_Http_HtmlP); - http->DeclareFunction(gc, "HtmlEncode","Html encode",{"param"}, Net_HtmlEncode); - - http->DeclareFunction(gc, "UrlEncode","Url encode query param",{"param"}, Net_UrlEncode); - http->DeclareFunction(gc, "UrlDecode","Url decode query param",{"param"}, Net_UrlDecode); - http->DeclareFunction(gc, "UrlPathEncode","Url encode path",{"path"}, Net_UrlPathEncode); - http->DeclareFunction(gc, "UrlPathDecode","Url decode path",{"path"}, Net_UrlPathDecode); - http->DeclareFunction(gc, "MimeType","Get mimetype from extension",{"ext"},Net_Http_MimeType); +bool TObjectHttpServer::Handle(ServerContext &ctx) { + TCallable *callable; + TDictionary *dict; + TClassObject *clsObj; + if (GetObjectHeap(this->obj, callable)) { + GCList ls2(this->ls->GetGC()); + auto res = TNativeObject::Create(ls2, &ctx); + bool result; + auto out = callable->Call(ls2, {res}); + if (GetObject(out, result)) { + res->Finish(); + return result; + } + res->Finish(); + } else if (GetObjectHeap(this->obj, dict)) { + GCList ls2(this->ls->GetGC()); + auto res = TNativeObject::Create(ls2, &ctx); + bool result; + auto out = dict->CallMethod(ls2, "Handle", {res}); + if (GetObject(out, result)) { + res->Finish(); + return result; + } + res->Finish(); + } else if (GetObjectHeap(this->obj, clsObj) && + clsObj->HasMethod("", "Handle")) { + GCList ls2(this->ls->GetGC()); + auto res = TNativeObject::Create(ls2, &ctx); + bool result; + this->ls->GetGC()->BarrierBegin(); + auto callableO = clsObj->GetValue("", "Handle"); + this->ls->GetGC()->BarrierEnd(); + TCallable *callable; + if (GetObjectHeap(callableO, callable)) { + auto out = callable->Call(ls2, {res}); + if (GetObject(out, result)) { + res->Finish(); + return result; + } + res->Finish(); + } + } - - http->DeclareFunction(gc, "StreamHttpRequestBody","Create a stream request body",{"stream","mimeType"},New_StreamHttpRequestBody); - http->DeclareFunction(gc, "TextHttpRequestBody","Create a text request body",{"text","mimeType"},New_TextHttpRequestBody); - http->DeclareFunction(gc, "JsonHttpRequestBody","Create a text request body",{"json"},New_JsonHttpRequestBody); - http->DeclareFunction(gc, "MakeRequest", "Create an http request", {"url","$extra"}, [env](GCList& ls, std::vector args)->TObject {return Net_Http_MakeRequest(ls,args,env);}); - http->DeclareFunction(gc, "WebSocketClient", "Create a websocket connection",{"url","headers","conn","$successCB"},Net_Http_WebSocketClient); - http->DeclareFunction(gc, "DownloadToString","Return the http file's contents as a string",{"url"},Net_Http_DownloadToString); - http->DeclareFunction(gc, "DownloadToStream","Download file to stream",{"url","stream"},Net_Http_DownloadToStream); - http->DeclareFunction(gc, "DownloadToFile","Download file to file in vfs",{"url","vfs","path"},Net_Http_DownloadToFile); - http->DeclareFunction(gc, "HttpServer", "Create a http server (allows multiple)",{"server","portOrUnixPath","$printIPs"},[env](GCList& ls, std::vector args)->TObject{ - return New_HttpServer(ls,args,env); - }); - http->DeclareFunction(gc, "ListenSimpleWithLoop", "Listen (creates application loop)", {"server","port"},Net_Http_ListenSimpleWithLoop); - http->DeclareFunction(gc, "ListenOnUnusedPort","Listen on unused localhost port and print Port: theport",{"server"},Net_Http_ListenOnUnusedPort); - //FileServer svr() + return false; +} +TObjectHttpServer::~TObjectHttpServer() { delete ls; } - http->DeclareFunction(gc, "RouteServer","Create a routeserver",{"$root"}, New_RouteServer); - http->DeclareFunction(gc, "FileServer","Create a file server",{"vfs","allowlisting","spa"}, New_FileServer); - http->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", {"$server","$auth","$realm"},New_BasicAuthServer); - http->DeclareFunction(gc, "BasicAuthGetCreds","Get creds from str",{"ctx"},[](GCList& ls, std::vector args)->TObject { - TServerContext* sc; - if(GetArgumentHeap(args,0,sc)) +static TObject Net_UrlDecode(GCList &ls, std::vector args) { + if (args.size() == 1 && std::holds_alternative(args[0])) { + return HttpUtils::UrlDecode(std::get(args[0])); + } + return Undefined(); +} +static TObject Net_HtmlEncode(GCList &ls, std::vector args) { + if (args.size() == 1 && std::holds_alternative(args[0])) { + return HttpUtils::HtmlEncode(std::get(args[0])); + } + return Undefined(); +} +static TObject Net_UrlEncode(GCList &ls, std::vector args) { + if (args.size() == 1 && std::holds_alternative(args[0])) { + return HttpUtils::UrlEncode(std::get(args[0])); + } + return Undefined(); +} +static TObject Net_UrlPathDecode(GCList &ls, std::vector args) { + if (args.size() == 1 && std::holds_alternative(args[0])) { + return HttpUtils::UrlPathDecode(std::get(args[0])); + } + return Undefined(); +} +static TObject Net_UrlPathEncode(GCList &ls, std::vector args) { + if (args.size() == 1 && std::holds_alternative(args[0])) { + return HttpUtils::UrlPathEncode(std::get(args[0])); + } + return Undefined(); +} +static TObject New_NetworkStream(GCList &ls, std::vector args) { + bool ipv6; + bool datagram; + if (GetArgument(args, 0, ipv6) && GetArgument(args, 1, datagram)) { + return std::make_shared(ipv6, datagram); + } + return nullptr; +} +class HttpServerNativeObject : public TNativeObject { + HttpServer *server; + + public: + HttpServerNativeObject(uint16_t port, + std::shared_ptr httpServer, + bool printIps) { + server = new HttpServer(port, httpServer, printIps); + } + HttpServerNativeObject(std::string unixPath, + std::shared_ptr httpServer) { + server = new HttpServer(unixPath, httpServer); + } + std::string TypeName() { return "Net.Http.HttpServer"; } + TObject CallMethod(GCList &ls, std::string key, std::vector args) { + if (key == "getPort") { + return (int64_t)server->GetPort(); + } + if (key == "StartAccepting") + server->StartAccepting(); + return nullptr; + } + ~HttpServerNativeObject() { delete server; } +}; + +static TObject New_HttpServer(GCList &ls, std::vector args, + TRootEnvironment *env) { + int64_t port; + std::string pathStr; + if (GetArgument(args, 1, port)) { + bool printIPs = true; + GetArgument(args, 2, printIPs); + + std::shared_ptr httpSvr = + ToHttpServer(ls.GetGC(), args[0]); + + if (httpSvr) { + uint16_t p = (uint16_t)port; + return TNativeObject::Create( + ls, port, httpSvr, printIPs); + } + } + + if (GetArgument(args, 1, pathStr) && env->permissions.localfs) { + std::shared_ptr httpSvr = + ToHttpServer(ls.GetGC(), args[0]); + + if (httpSvr) { + return TNativeObject::Create(ls, pathStr, + httpSvr); + } + } + return nullptr; +} +static TObject Net_Http_ListenSimpleWithLoop(GCList &ls, + std::vector args) { + int64_t port; + if (GetArgument(args, 1, port)) { + std::shared_ptr httpSvr = + ToHttpServer(ls.GetGC(), args[0]); + + if (httpSvr) { + uint16_t p = (uint16_t)port; + HttpServer server(p, httpSvr); + server.StartAccepting(); + Tesses::Framework::TF_RunEventLoop(); + } + } + return nullptr; +} +static TObject Net_Http_ListenOnUnusedPort(GCList &ls, + std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr httpSvr = + ToHttpServer(ls.GetGC(), args.front()); + if (httpSvr) { + uint16_t p = 0; + HttpServer server(p, httpSvr); + std::cout << "Port: " << server.GetPort() << std::endl; + server.StartAccepting(); + + Tesses::Framework::TF_RunEventLoop(); + } + + return nullptr; +} +static TObject Net_Http_MimeType(GCList &ls, std::vector args) { + Tesses::Framework::Filesystem::VFSPath p; + if (GetArgumentAsPath(args, 0, p)) { + std::filesystem::path p2 = p.GetFileName(); + return HttpUtils::MimeType(p2); + } + return std::string("application/octet-stream"); +} +class THttpRequestBody : public TNativeObject { + HttpRequestBody *body; + + public: + THttpRequestBody(HttpRequestBody *body) { this->body = body; } + bool IsClosed() { return body == nullptr; } + HttpRequestBody *GetBody() { return this->body; } + + std::string TypeName() { return "Net.Http.HttpRequestBody"; } + + TObject CallMethod(GCList &ls, std::string key, std::vector args) { + return Undefined(); + } + + void Close() { + delete this->body; + this->body = nullptr; + } +}; + +class THttpResponse : public TNativeObjectThatReturnsHttpDictionary { + HttpResponse *response; + + public: + THttpResponse(HttpResponse *resp) { this->response = resp; } + bool IsAvailable() { return this->response != nullptr; } + + void Close() { + delete this->response; + this->response = nullptr; + } + + ~THttpResponse() { + delete this->response; + this->response = nullptr; + } + std::string TypeName() { return "Net.Http.HttpResponse"; } + + TObject CallMethod(GCList &ls, std::string key, std::vector args) { + if (!this->IsAvailable()) + return Undefined(); + + else if (key == "CopyToStream") { + std::shared_ptr strm; + if (GetArgument(args, 0, strm)) { + response->CopyToStream(strm); + } + } else if (key == "ReadAsString") { + return response->ReadAsString(); + } else if (key == "ReadAsJson") { + return Json_Decode(ls, response->ReadAsString()); + } else if (key == "ReadAsStream") { + + return response->ReadAsStream(); + } else if (key == "getStatusCode") { + return (int64_t)response->statusCode; + } else if (key == "getVersion") { + return response->version; + } else if (key == "getResponseHeaders") { + return TNativeObject::Create( + ls, &response->responseHeaders, this); + } + + return Undefined(); + } +}; + +static TObject Net_Http_MakeRequest(GCList &ls, std::vector args, + TRootEnvironment *env) { + auto gc = ls.GetGC(); + std::string url; + + if (GetArgument(args, 0, url)) { + TDictionary *body1 = nullptr; + THttpRequestBody *body2 = nullptr; + HttpRequest req; + req.method = "GET"; + req.ignoreSSLErrors = false; + req.followRedirects = false; + req.trusted_root_cert_bundle = ""; + req.url = url; + req.body = nullptr; + + TDictionary *options; + if (GetArgumentHeap(args, 1, options)) { + gc->BarrierBegin(); + auto _obj = options->GetValue("Method"); + GetObject(_obj, req.method); + _obj = options->GetValue("IgnoreSSLErrors"); + GetObject(_obj, req.ignoreSSLErrors); + _obj = options->GetValue("FollowRedirects"); + GetObject(_obj, req.followRedirects); + _obj = options->GetValue("TrustedRootCertBundle"); + GetObject(_obj, req.trusted_root_cert_bundle); + if (env->permissions.localfs) { + _obj = options->GetValue("UnixSocket"); + GetObject(_obj, req.unixSocket); + } + + _obj = options->GetValue("RequestHeaders"); + + TList *headers; + + if (GetObjectHeap(_obj, headers)) { + for (int64_t index = 0; index < headers->Count(); index++) { + _obj = headers->Get(index); + TDictionary *dict; + if (GetObjectHeap(_obj, dict)) { + std::string key = {}; + std::string value = {}; + _obj = dict->GetValue("Key"); + GetObject(_obj, key); + _obj = dict->GetValue("Value"); + GetObject(_obj, value); + + req.requestHeaders.AddValue(key, value); + } + } + } + _obj = options->GetValue("Body"); + + if (GetObjectHeap(_obj, body1)) { + req.body = new TDictionaryHttpRequestBody(gc, body1); + } else if (GetObjectHeap(_obj, body2) && !body2->IsClosed()) { + req.body = body2->GetBody(); + } + + gc->BarrierEnd(); + } + + HttpResponse *resp = new HttpResponse(req); + + if (req.body != nullptr) { + if (body2 != nullptr) { + body2->Close(); + } else if (body1 != nullptr) { + delete req.body; + } + } + + return TNativeObject::Create(ls, resp); + } + + return nullptr; +} + +static TObject Net_Smtp_Send(GCList &ls, std::vector args) { + TDictionary *dict; + if (GetArgumentHeap(args, 0, dict)) { + // the body should be either type text/plain or text/html + // the body and attachment data can also point to bytearray of stream + // server can also be a stream + // as of right now the email is fire and forget (ie no error checking) + // check function return type just in case (this function returns a + // empty string if no error) we rolled our own smtp client + + /* + dict looks like this from crosslang's point of view { + server = { + host = "smtp.example.com", + tls = true + }, + auth = { + username = "from", + password = "THEPASSWORD" + }, + domain = "example.com", + from = { + name = "The name shown in the mail where it is from", + email = "from@example.com" + }, + to = "to@example.com", + subject = "My little message", + body = { + type = "text/html", + data = "

Hello, world

" + }, + attachments = [ + { + name = "myimg.png", + type = "image/png", + data = embed("myimg.png") + } + ] + } + */ + ls.GetGC()->BarrierBegin(); + auto server = dict->GetValue("server"); + TDictionary *dict2; + std::shared_ptr strm; + bool ownsStream = true; + std::shared_ptr objStrm; + if (GetObjectHeap(server, dict2)) { + auto tlsO = dict2->GetValue("tls"); + auto hostO = dict2->GetValue("host"); + auto portO = dict2->GetValue("port"); + std::string host; + bool tls = false; + int64_t port; + GetObject(tlsO, tls); + + if (!GetObject(portO, port)) + port = tls ? 465 : 25; + + GetObject(hostO, host); + strm = std::make_shared(host, (uint16_t)port, false, + false, false); + if (tls) { + strm = std::make_shared( + strm, true, host); + } + + } else if (GetObject(server, objStrm)) { + ownsStream = false; + strm = objStrm; + } + + Tesses::Framework::Mail::SMTPClient client(strm); + auto o = dict->GetValue("domain"); + + GetObject(o, client.domain); + o = dict->GetValue("to"); + GetObject(o, client.to); + o = dict->GetValue("subject"); + GetObject(o, client.subject); + o = dict->GetValue("auth"); + if (GetObjectHeap(o, dict2)) { + o = dict2->GetValue("username"); + GetObject(o, client.username); + o = dict2->GetValue("password"); + GetObject(o, client.password); + } + o = dict->GetValue("from"); + if (GetObjectHeap(o, dict2)) { + o = dict2->GetValue("email"); + GetObject(o, client.from); + o = dict2->GetValue("name"); + GetObject(o, client.from_name); + } + o = dict->GetValue("body"); + if (GetObjectHeap(o, dict2)) { + // type, data + std::string type = "text/plain"; + o = dict2->GetValue("type"); + GetObject(o, type); + o = dict2->GetValue("data"); + client.body = TObjectToSMTPBody(ls, type, o); + } + o = dict->GetValue("attachments"); + TList *als; + if (GetObjectHeap(o, als)) { + for (int64_t i = 0; i < als->Count(); i++) { + auto item = als->Get(i); + if (GetObjectHeap(item, dict2)) { + o = dict2->GetValue("name"); + std::string name; + GetObject(o, name); + std::string type = "text/plain"; + o = dict2->GetValue("type"); + GetObject(o, type); + o = dict2->GetValue("data"); + + client.attachments.push_back( + std::pair>( + name, TObjectToSMTPBody(ls, type, o))); + } + } + } + + ls.GetGC()->BarrierEnd(); + client.Send(); + return ""; + } + return nullptr; +} +static TObject Net_Http_WebSocketClient(GCList &ls, std::vector args) { + std::string url; + TList *headers; + TDictionary *dict; + TClassObject *co; + + TCallable *callable = nullptr; + + TObject _obj; + if (GetArgument(args, 0, url) && GetArgumentHeap(args, 1, headers) && + GetArgumentHeap(args, 2, dict)) { + GetArgumentHeap(args, 3, callable); + HttpDictionary hdict; + for (int64_t index = 0; index < headers->Count(); index++) { + _obj = headers->Get(index); + TDictionary *dict; + if (GetObjectHeap(_obj, dict)) { + std::string key = {}; + std::string value = {}; + _obj = dict->GetValue("Key"); + GetObject(_obj, key); + _obj = dict->GetValue("Value"); + GetObject(_obj, value); + hdict.AddValue(key, value); + } + } + auto conn = std::make_shared( + [dict, &ls](std::function sendMessage, + std::function ping, + std::function close) -> void { + GCList ls2(ls.GetGC()); + dict->CallMethod( + ls2, "Open", + {TExternalMethod::Create( + ls2, "Send a message", {"messageTextOrByteArray"}, + [sendMessage](GCList &ls, + std::vector args) -> TObject { + std::string str; + TByteArray *bArray; + if (GetArgument(args, 0, str)) { + WebSocketMessage msg(str); + sendMessage(msg); + } else if (GetArgumentHeap(args, 0, bArray)) { + WebSocketMessage msg(bArray->data); + sendMessage(msg); + } + return nullptr; + }), + TExternalMethod::Create( + ls2, "Ping client", {}, + [ping](GCList &ls, + std::vector args) -> TObject { + ping(); + return nullptr; + }), + TExternalMethod::Create( + ls2, "Close client", {}, + [close](GCList &ls, + std::vector args) -> TObject { + close(); + return nullptr; + })}); + }, + [dict, &ls](WebSocketMessage &msg) -> void { + GCList ls2(ls.GetGC()); + + TObject v; + + if (msg.isBinary) { + auto r = TByteArray::Create(ls2); + r->data = msg.data; + v = r; + } else { + v = msg.ToString(); + } + + dict->CallMethod(ls2, "Receive", {v}); + }, + [dict, &ls](bool close) -> void { + GCList ls2(ls.GetGC()); + dict->CallMethod(ls2, "Close", {close}); + }); + WebSocketClient( + url, hdict, conn, + [&ls, callable](Tesses::Framework::Http::HttpDictionary &dict, + bool success) -> bool { + if (callable != nullptr) { + auto dummy = TNativeObject::Create< + DummyTNativeObjectThatReturnsHttpDictionary>(ls); + bool res = ToBool(callable->Call( + ls, {TNativeObject::Create(ls, &dict, + dummy), + success})); + dummy->Close(); + return res; + } + return true; + }); + } else if (GetArgument(args, 0, url) && GetArgumentHeap(args, 1, co)) { + TObject hobj; + if (co->HasMethod("", "GetRequestHeaders")) + hobj = co->CallMethod(ls, "", "GetRequestHeaders", {}); + else if (co->HasField("", "RequestHeaders")) + hobj = co->GetValue("", "RequestHeaders"); + else + return Undefined(); + + if (!GetObjectHeap(hobj, headers)) + return Undefined(); + + HttpDictionary hdict; + for (int64_t index = 0; index < headers->Count(); index++) { + _obj = headers->Get(index); + TDictionary *dict; + if (GetObjectHeap(_obj, dict)) { + std::string key = {}; + std::string value = {}; + _obj = dict->GetValue("Key"); + GetObject(_obj, key); + _obj = dict->GetValue("Value"); + GetObject(_obj, value); + hdict.AddValue(key, value); + } + } + + auto conn = std::make_shared( + [co, &ls](std::function sendMessage, + std::function ping, + std::function close) -> void { + GCList ls2(ls.GetGC()); + co->CallMethod( + ls2, "", "Open", + {TExternalMethod::Create( + ls2, "Send a message", {"messageTextOrByteArray"}, + [sendMessage](GCList &ls, + std::vector args) -> TObject { + std::string str; + TByteArray *bArray; + if (GetArgument(args, 0, str)) { + WebSocketMessage msg(str); + sendMessage(msg); + } else if (GetArgumentHeap(args, 0, bArray)) { + WebSocketMessage msg(bArray->data); + sendMessage(msg); + } + return nullptr; + }), + TExternalMethod::Create( + ls2, "Ping client", {}, + [ping](GCList &ls, + std::vector args) -> TObject { + ping(); + return nullptr; + }), + TExternalMethod::Create( + ls2, "Close client", {}, + [close](GCList &ls, + std::vector args) -> TObject { + close(); + return nullptr; + })}); + }, + [co, &ls](WebSocketMessage &msg) -> void { + GCList ls2(ls.GetGC()); + + TObject v; + + if (msg.isBinary) { + auto r = TByteArray::Create(ls2); + r->data = msg.data; + v = r; + } else { + v = msg.ToString(); + } + + co->CallMethod(ls2, "", "Receive", {v}); + }, + [co, &ls](bool close) -> void { + GCList ls2(ls.GetGC()); + co->CallMethod(ls2, "", "Close", {close}); + }); + WebSocketClient( + url, hdict, conn, + [&ls, co](Tesses::Framework::Http::HttpDictionary &dict, + bool success) -> bool { + if (co->HasMethod("", "HandleResponseHeaders")) { + auto dummy = TNativeObject::Create< + DummyTNativeObjectThatReturnsHttpDictionary>(ls); + bool res = ToBool( + co->CallMethod(ls, "", "HandleResponseHeaders", + {TNativeObject::Create( + ls, &dict, dummy), + success})); + dummy->Close(); + return res; + } + + return true; + }); + } + return Undefined(); + // Net.Http.CreateWebSocketConnection("wss://example.com/",[],conn, (dict, + // success)=>{ return true;}) +} +static TObject Net_Http_DownloadToString(GCList &ls, + std::vector args) { + std::string url; + if (GetArgument(args, 0, url)) + return DownloadToStringSimple(url); + return nullptr; +} +static TObject Net_Http_DownloadToStream(GCList &ls, + std::vector args) { + std::string url; + std::shared_ptr strm; + if (GetArgument(args, 0, url) && GetArgument(args, 1, strm)) { + DownloadToStreamSimple(url, strm); + } + return nullptr; +} +static TObject Net_Http_DownloadToFile(GCList &ls, std::vector args) { + std::string url; + std::shared_ptr vfs; + Tesses::Framework::Filesystem::VFSPath path; + if (GetArgument(args, 0, url) && GetArgument(args, 1, vfs) && + GetArgumentAsPath(args, 2, path)) { + DownloadToFileSimple(url, vfs, path); + } + return nullptr; +} +bool IHttpServer_Handle(std::shared_ptr svr, + std::vector &args) { + TServerContext *ctx; + if (GetArgumentHeap(args, 0, ctx)) { + return svr->Handle(*ctx->GetContext()); + } + return false; +} + +std::shared_ptr ToHttpServer(std::shared_ptr gc, TObject obj) { + if (std::holds_alternative>(obj)) + return std::get>(obj); + TDictionary *dict; + TClassObject *clo; + TCallable *call; + if (GetObjectHeap(obj, dict)) { + return std::make_shared(gc, dict); + } else if (GetObjectHeap(obj, clo)) { + return std::make_shared(gc, clo); + } else if (GetObjectHeap(obj, call)) { + return std::make_shared(gc, call); + } + return nullptr; +} + +static TObject Net_Http_HtmlP(GCList &ls, std::vector args) { + std::string str; + if (GetArgument(args, 0, str)) { + return HttpUtils::HtmlP(str); + } + return ""; +} + +static TObject Net_Http_StatusCodeString(GCList &ls, + std::vector args) { + int64_t sc; + if (GetArgument(args, 0, sc)) { + return HttpUtils::StatusCodeString((StatusCode)sc); + } + return ""; +} +static TObject New_FileServer(GCList &ls, std::vector args) { + std::shared_ptr vfs; + bool allowlisting; + bool spa; + if (GetArgument(args, 0, vfs) && GetArgument(args, 1, allowlisting) && + GetArgument(args, 2, spa)) { + return std::make_shared(vfs, allowlisting, spa); + } + return nullptr; +} +static TObject New_BasicAuthServer(GCList &ls, std::vector args) { + auto bAuth = std::make_shared(); + + TCallable *cb; + if (!args.empty()) + bAuth->server = ToHttpServer(ls.GetGC(), args[0]); + + if (GetArgumentHeap(args, 1, cb)) { + auto marked = CreateMarkedTObject(ls, cb); + bAuth->authorization = [marked](std::string user, + std::string password) -> bool { + GCList ls(marked->GetGC()); + TCallable *callable; + if (GetObjectHeap(marked->GetObject(), callable)) { + return ToBool(callable->Call(ls, {user, password})); + } + return false; + }; + } + GetArgument(args, 2, bAuth->realm); + return bAuth; +} +static TObject New_MountableServer(GCList &ls, std::vector args) { + if (args.empty()) + return std::make_shared(); + return std::make_shared(ToHttpServer(ls.GetGC(), args[0])); +} +static TObject New_RouteServer(GCList &ls, std::vector args) { + if (args.empty()) + return std::make_shared(); + return std::make_shared(ToHttpServer(ls.GetGC(), args[0])); +} +static TObject New_StreamHttpRequestBody(GCList &ls, + std::vector args) { + std::shared_ptr strm; + std::string mimeType; + + if (GetArgument(args, 0, strm) && GetArgument(args, 1, mimeType)) { + return TNativeObject::Create( + ls, new StreamHttpRequestBody(strm, mimeType)); + } + return nullptr; +} +static TObject New_TextHttpRequestBody(GCList &ls, std::vector args) { + std::string text; + std::string mimeType; + if (GetArgument(args, 0, text) && GetArgument(args, 1, mimeType)) { + return TNativeObject::Create( + ls, new TextHttpRequestBody(text, mimeType)); + } + return nullptr; +} +static TObject New_JsonHttpRequestBody(GCList &ls, std::vector args) { + + if (!args.empty()) { + return TNativeObject::Create( + ls, + new TextHttpRequestBody(Json_Encode(args[0]), "application/json")); + } + return nullptr; +} + +static TObject New_ServerSentEvents(GCList &ls, std::vector args) { + return std::make_shared(); +} + +void TStd::RegisterNet(std::shared_ptr gc, TRootEnvironment *env) { + + env->permissions.canRegisterNet = true; + GCList ls(gc); + + gc->BarrierBegin(); + TDictionary *dict = env->EnsureDictionary(gc, "Net"); + TDictionary *_new = env->EnsureDictionary(gc, "New"); + _new->DeclareFunction(gc, "StreamHttpRequestBody", + "Create a stream request body", + {"stream", "mimeType"}, New_StreamHttpRequestBody); + _new->DeclareFunction(gc, "TextHttpRequestBody", + "Create a text request body", {"text", "mimeType"}, + New_TextHttpRequestBody); + _new->DeclareFunction(gc, "JsonHttpRequestBody", + "Create a text request body", {"json"}, + New_JsonHttpRequestBody); + _new->DeclareFunction( + gc, "HttpServer", "Create a http server (allows multiple)", + {"server", "portOrUnixPath", "$printIPs"}, + [env](GCList &ls, std::vector args) -> TObject { + return New_HttpServer(ls, args, env); + }); + + _new->DeclareFunction(gc, "RouteServer", "Create a routeserver", {"$root"}, + New_RouteServer); + _new->DeclareFunction(gc, "FileServer", "Create a file server", + {"vfs", "allowlisting", "spa"}, New_FileServer); + _new->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", + {"$server", "$auth", "$realm"}, New_BasicAuthServer); + _new->DeclareFunction( + gc, "MountableServer", + "Create a server you can mount to, must mount parents before child", + {"root"}, New_MountableServer); + _new->DeclareFunction(gc, "NetworkStream", "Create a network stream", + {"ipv6", "datagram"}, New_NetworkStream); + + _new->DeclareFunction(gc, "ServerSentEvents", + "Create server sent events object", {""}, + New_ServerSentEvents); + + TDictionary *http = TDictionary::Create(ls); + TDictionary *smtp = TDictionary::Create(ls); + http->DeclareFunction(gc, "StatusCodeString", "Get the status code string", + {"statusCode"}, Net_Http_StatusCodeString); + http->DeclareFunction(gc, "HtmlP", "Linkify text", {"text"}, + Net_Http_HtmlP); + http->DeclareFunction(gc, "HtmlEncode", "Html encode", {"param"}, + Net_HtmlEncode); + + http->DeclareFunction(gc, "UrlEncode", "Url encode query param", {"param"}, + Net_UrlEncode); + http->DeclareFunction(gc, "UrlDecode", "Url decode query param", {"param"}, + Net_UrlDecode); + http->DeclareFunction(gc, "UrlPathEncode", "Url encode path", {"path"}, + Net_UrlPathEncode); + http->DeclareFunction(gc, "UrlPathDecode", "Url decode path", {"path"}, + Net_UrlPathDecode); + http->DeclareFunction(gc, "MimeType", "Get mimetype from extension", + {"ext"}, Net_Http_MimeType); + + http->DeclareFunction(gc, "StreamHttpRequestBody", + "Create a stream request body", + {"stream", "mimeType"}, New_StreamHttpRequestBody); + http->DeclareFunction(gc, "TextHttpRequestBody", + "Create a text request body", {"text", "mimeType"}, + New_TextHttpRequestBody); + http->DeclareFunction(gc, "JsonHttpRequestBody", + "Create a text request body", {"json"}, + New_JsonHttpRequestBody); + http->DeclareFunction( + gc, "MakeRequest", "Create an http request", {"url", "$extra"}, + [env](GCList &ls, std::vector args) -> TObject { + return Net_Http_MakeRequest(ls, args, env); + }); + http->DeclareFunction( + gc, "WebSocketClient", "Create a websocket connection", + {"url", "headers", "conn", "$successCB"}, Net_Http_WebSocketClient); + http->DeclareFunction(gc, "DownloadToString", + "Return the http file's contents as a string", + {"url"}, Net_Http_DownloadToString); + http->DeclareFunction(gc, "DownloadToStream", "Download file to stream", + {"url", "stream"}, Net_Http_DownloadToStream); + http->DeclareFunction(gc, "DownloadToFile", "Download file to file in vfs", + {"url", "vfs", "path"}, Net_Http_DownloadToFile); + http->DeclareFunction( + gc, "HttpServer", "Create a http server (allows multiple)", + {"server", "portOrUnixPath", "$printIPs"}, + [env](GCList &ls, std::vector args) -> TObject { + return New_HttpServer(ls, args, env); + }); + http->DeclareFunction(gc, "ListenSimpleWithLoop", + "Listen (creates application loop)", + {"server", "port"}, Net_Http_ListenSimpleWithLoop); + http->DeclareFunction( + gc, "ListenOnUnusedPort", + "Listen on unused localhost port and print Port: theport", {"server"}, + Net_Http_ListenOnUnusedPort); + // FileServer svr() + + http->DeclareFunction(gc, "RouteServer", "Create a routeserver", {"$root"}, + New_RouteServer); + http->DeclareFunction(gc, "FileServer", "Create a file server", + {"vfs", "allowlisting", "spa"}, New_FileServer); + http->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", + {"$server", "$auth", "$realm"}, New_BasicAuthServer); + http->DeclareFunction( + gc, "BasicAuthGetCreds", "Get creds from str", {"ctx"}, + [](GCList &ls, std::vector args) -> TObject { + TServerContext *sc; + if (GetArgumentHeap(args, 0, sc)) { std::string user; std::string pass; - if(sc->IsAvailable() && BasicAuthServer::GetCreds(*sc->GetContext(),user,pass)) - { - return TDictionary::Create(ls,{ - TDItem("Username",user), - TDItem("Password",pass) - }); + if (sc->IsAvailable() && + BasicAuthServer::GetCreds(*sc->GetContext(), user, pass)) { + return TDictionary::Create(ls, {TDItem("Username", user), + TDItem("Password", pass)}); } } return nullptr; }); - http->DeclareFunction(gc, "MountableServer","Create a server you can mount to, must mount parents before child",{"root"}, New_MountableServer); - dict->DeclareFunction(gc, "NetworkStream","Create a network stream",{"ipv6","datagram"},New_NetworkStream); - smtp->DeclareFunction(gc, "Send","Send email via smtp server",{"messageStruct"},Net_Smtp_Send); - dict->DeclareFunction(gc, "getIPAddresses","Get the ip addresses of this machine",{"$ipv6"},[](GCList& ls, std::vector args)->TObject{ - TList* a = TList::Create(ls); - bool ipv6=false; - GetArgument(args,0,ipv6); + http->DeclareFunction( + gc, "MountableServer", + "Create a server you can mount to, must mount parents before child", + {"root"}, New_MountableServer); + dict->DeclareFunction(gc, "NetworkStream", "Create a network stream", + {"ipv6", "datagram"}, New_NetworkStream); + smtp->DeclareFunction(gc, "Send", "Send email via smtp server", + {"messageStruct"}, Net_Smtp_Send); + dict->DeclareFunction( + gc, "getIPAddresses", "Get the ip addresses of this machine", {"$ipv6"}, + [](GCList &ls, std::vector args) -> TObject { + TList *a = TList::Create(ls); + bool ipv6 = false; + GetArgument(args, 0, ipv6); ls.GetGC()->BarrierBegin(); - for(auto item : Tesses::Framework::Streams::NetworkStream::GetIPs(ipv6)) - { - a->Add(TDictionary::Create(ls,{ - TDItem("Interface", item.first), - TDItem("Address", item.second) - })); + for (auto item : + Tesses::Framework::Streams::NetworkStream::GetIPs(ipv6)) { + a->Add( + TDictionary::Create(ls, {TDItem("Interface", item.first), + TDItem("Address", item.second)})); } - ls.GetGC()->BarrierEnd();; + ls.GetGC()->BarrierEnd(); + ; return a; }); - dict->SetValue("Http", http); - dict->SetValue("Smtp", smtp); - gc->BarrierEnd(); - } - - Tesses::Framework::Http::ServerRequestHandler TCallable::ToRouteServerRequestHandler(std::shared_ptr gc) - { - auto value = CreateMarkedTObject(gc,this); - return [value,this](ServerContext& ctx)->bool { - auto v=value; - auto gc = v->GetGC(); - GCList ls(gc); - auto res = TNativeObject::Create(ls, &ctx); - bool result; - auto out = this->Call(ls,{res}); - if(GetObject(out,result)) - { - res->Finish(); - return result; - } - res->Finish(); - - return false; - }; - } + dict->SetValue("Http", http); + dict->SetValue("Smtp", smtp); + gc->BarrierEnd(); } + +Tesses::Framework::Http::ServerRequestHandler +TCallable::ToRouteServerRequestHandler(std::shared_ptr gc) { + auto value = CreateMarkedTObject(gc, this); + return [value, this](ServerContext &ctx) -> bool { + auto v = value; + auto gc = v->GetGC(); + GCList ls(gc); + auto res = TNativeObject::Create(ls, &ctx); + bool result; + auto out = this->Call(ls, {res}); + if (GetObject(out, result)) { + res->Finish(); + return result; + } + res->Finish(); + + return false; + }; +} +} // namespace Tesses::CrossLang diff --git a/src/runtime_methods/ogc.cpp b/src/runtime_methods/ogc.cpp index fd48789..7129a49 100644 --- a/src/runtime_methods/ogc.cpp +++ b/src/runtime_methods/ogc.cpp @@ -1,84 +1,75 @@ #include "CrossLang.hpp" #if defined(GEKKO) -#include #include #include +#include #if defined(HW_RVL) #include #endif #endif -namespace Tesses::CrossLang -{ - #if defined(GEKKO) - #if defined(HW_RVL) - static TObject OGC_WPAD_ScanPads(GCList& ls, std::vector args) - { - return (int64_t)WPAD_ScanPads(); - } - static TObject OGC_WPAD_ButtonsUp(GCList& ls, std::vector args) - { - int64_t chan; - if(GetArgument(args,0,chan)) +namespace Tesses::CrossLang { +#if defined(GEKKO) +#if defined(HW_RVL) +static TObject OGC_WPAD_ScanPads(GCList &ls, std::vector args) { + return (int64_t)WPAD_ScanPads(); +} +static TObject OGC_WPAD_ButtonsUp(GCList &ls, std::vector args) { + int64_t chan; + if (GetArgument(args, 0, chan)) return (int64_t)WPAD_ButtonsUp((int)chan); - return 0; - } - static TObject OGC_WPAD_ButtonsDown(GCList& ls, std::vector args) - { - int64_t chan; - if(GetArgument(args,0,chan)) + return 0; +} +static TObject OGC_WPAD_ButtonsDown(GCList &ls, std::vector args) { + int64_t chan; + if (GetArgument(args, 0, chan)) return (int64_t)WPAD_ButtonsDown((int)chan); - return 0; - } - static TObject OGC_WPAD_ButtonsHeld(GCList& ls, std::vector args) - { - int64_t chan; - if(GetArgument(args,0,chan)) + return 0; +} +static TObject OGC_WPAD_ButtonsHeld(GCList &ls, std::vector args) { + int64_t chan; + if (GetArgument(args, 0, chan)) return (int64_t)WPAD_ButtonsDown((int)chan); - return 0; - } - static TObject OGC_WPAD_BatteryLevel(GCList& ls, std::vector args) - { - int64_t chan; - if(GetArgument(args,0,chan)) + return 0; +} +static TObject OGC_WPAD_BatteryLevel(GCList &ls, std::vector args) { + int64_t chan; + if (GetArgument(args, 0, chan)) return (int64_t)WPAD_BatteryLevel((int)chan); - return 0; - } - #endif - #endif - void TStd::RegisterOGC(std::shared_ptr gc, TRootEnvironment* env) - { - GCList ls(gc); - #if defined(GEKKO) - - - gc->BarrierBegin(); + return 0; +} +#endif +#endif +void TStd::RegisterOGC(std::shared_ptr gc, TRootEnvironment *env) { + GCList ls(gc); +#if defined(GEKKO) - TDictionary* dict_ogc_pad = TDictionary::Create(ls); - #if defined(HW_RVL) - TDictionary* dict_rvl_wpad = TDictionary::Create(ls); - dict_rvl_wpad->DeclareFunction(gc, "ScanPads","Scan wiimotes",{},OGC_WPAD_ScanPads); - dict_rvl_wpad->DeclareFunction(gc, "ButtonsDown","Is button down",{"pad"},OGC_WPAD_ButtonsDown); - dict_rvl_wpad->SetValue("BUTTON_A",(int64_t)WPAD_BUTTON_A); - dict_rvl_wpad->SetValue("BUTTON_B",(int64_t)WPAD_BUTTON_B); - dict_rvl_wpad->SetValue("BUTTON_HOME",(int64_t)WPAD_BUTTON_HOME); - dict_rvl_wpad->SetValue("BUTTON_UP",(int64_t)WPAD_BUTTON_UP); - dict_rvl_wpad->SetValue("BUTTON_DOWN",(int64_t)WPAD_BUTTON_DOWN); - dict_rvl_wpad->SetValue("BUTTON_LEFT",(int64_t)WPAD_BUTTON_LEFT); - dict_rvl_wpad->SetValue("BUTTON_RIGHT",(int64_t)WPAD_BUTTON_RIGHT); - dict_rvl_wpad->SetValue("BUTTON_1",(int64_t)WPAD_BUTTON_1); - dict_rvl_wpad->SetValue("BUTTON_2",(int64_t)WPAD_BUTTON_2); - dict_rvl_wpad->SetValue("BUTTON_PLUS",(int64_t)WPAD_BUTTON_PLUS); - dict_rvl_wpad->SetValue("BUTTON_MINUS",(int64_t)WPAD_BUTTON_MINUS); - env->DeclareVariable("WPAD", dict_rvl_wpad); - - #endif - env->DeclareVariable("PAD", dict_ogc_pad); - gc->BarrierEnd(); - #endif - env->permissions.canRegisterOGC=true; - + gc->BarrierBegin(); - - } -} \ No newline at end of file + TDictionary *dict_ogc_pad = TDictionary::Create(ls); +#if defined(HW_RVL) + TDictionary *dict_rvl_wpad = TDictionary::Create(ls); + dict_rvl_wpad->DeclareFunction(gc, "ScanPads", "Scan wiimotes", {}, + OGC_WPAD_ScanPads); + dict_rvl_wpad->DeclareFunction(gc, "ButtonsDown", "Is button down", {"pad"}, + OGC_WPAD_ButtonsDown); + dict_rvl_wpad->SetValue("BUTTON_A", (int64_t)WPAD_BUTTON_A); + dict_rvl_wpad->SetValue("BUTTON_B", (int64_t)WPAD_BUTTON_B); + dict_rvl_wpad->SetValue("BUTTON_HOME", (int64_t)WPAD_BUTTON_HOME); + dict_rvl_wpad->SetValue("BUTTON_UP", (int64_t)WPAD_BUTTON_UP); + dict_rvl_wpad->SetValue("BUTTON_DOWN", (int64_t)WPAD_BUTTON_DOWN); + dict_rvl_wpad->SetValue("BUTTON_LEFT", (int64_t)WPAD_BUTTON_LEFT); + dict_rvl_wpad->SetValue("BUTTON_RIGHT", (int64_t)WPAD_BUTTON_RIGHT); + dict_rvl_wpad->SetValue("BUTTON_1", (int64_t)WPAD_BUTTON_1); + dict_rvl_wpad->SetValue("BUTTON_2", (int64_t)WPAD_BUTTON_2); + dict_rvl_wpad->SetValue("BUTTON_PLUS", (int64_t)WPAD_BUTTON_PLUS); + dict_rvl_wpad->SetValue("BUTTON_MINUS", (int64_t)WPAD_BUTTON_MINUS); + env->DeclareVariable("WPAD", dict_rvl_wpad); + +#endif + env->DeclareVariable("PAD", dict_ogc_pad); + gc->BarrierEnd(); +#endif + env->permissions.canRegisterOGC = true; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/runtime_methods/path.cpp b/src/runtime_methods/path.cpp index 3cf65ae..b900a5f 100644 --- a/src/runtime_methods/path.cpp +++ b/src/runtime_methods/path.cpp @@ -1,83 +1,76 @@ #include "CrossLang.hpp" - - -namespace Tesses::CrossLang -{ - bool GetObjectAsPath(TObject& obj, Tesses::Framework::Filesystem::VFSPath& path, bool allowString) - { - if(GetObject(obj,path)) return true; - std::string str; - if(allowString && GetObject(obj,str)) - { - path = Tesses::Framework::Filesystem::VFSPath(str); - return true; - } - return false; +namespace Tesses::CrossLang { +bool GetObjectAsPath(TObject &obj, Tesses::Framework::Filesystem::VFSPath &path, + bool allowString) { + if (GetObject(obj, path)) + return true; + std::string str; + if (allowString && GetObject(obj, str)) { + path = Tesses::Framework::Filesystem::VFSPath(str); + return true; } - bool GetArgumentAsPath(std::vector& args, size_t index, Tesses::Framework::Filesystem::VFSPath& path,bool allowString) - { - if(GetArgument(args,index,path)) return true; - std::string str; - if(allowString && GetArgument(args,index,str)) - { - path = Tesses::Framework::Filesystem::VFSPath(str); - return true; - } - return false; + return false; +} +bool GetArgumentAsPath(std::vector &args, size_t index, + Tesses::Framework::Filesystem::VFSPath &path, + bool allowString) { + if (GetArgument(args, index, path)) + return true; + std::string str; + if (allowString && GetArgument(args, index, str)) { + path = Tesses::Framework::Filesystem::VFSPath(str); + return true; } - - static TObject Path_Root(GCList& ls, std::vector args) - { - auto res = Tesses::Framework::Filesystem::VFSPath();\ - res.relative=false; + return false; +} + +static TObject Path_Root(GCList &ls, std::vector args) { + auto res = Tesses::Framework::Filesystem::VFSPath(); + res.relative = false; + return res; +} +static TObject Path_FromString(GCList &ls, std::vector args) { + std::string str; + if (GetArgument(args, 0, str)) { + return Tesses::Framework::Filesystem::VFSPath(str); + } + return nullptr; +} +static TObject Path_Create(GCList &ls, std::vector args) { + TList *myls; + bool relative; + if (GetArgument(args, 0, relative) && GetArgumentHeap(args, 1, myls)) { + std::vector items; + for (int64_t i = 0; i < myls->Count(); i++) { + std::string str; + TObject o = myls->Get(i); + if (GetObject(o, str)) { + items.push_back(str); + } + } + auto res = Tesses::Framework::Filesystem::VFSPath(items); + res.relative = relative; return res; } - static TObject Path_FromString(GCList& ls, std::vector args) - { - std::string str; - if(GetArgument(args,0,str)) - { - return Tesses::Framework::Filesystem::VFSPath(str); - } - return nullptr; - } - static TObject Path_Create(GCList& ls, std::vector args) - { - TList* myls; - bool relative; - if(GetArgument(args,0,relative) && GetArgumentHeap(args,1,myls)) - { - std::vector items; - for(int64_t i = 0; i < myls->Count(); i++) - { - std::string str; - TObject o =myls->Get(i); - if(GetObject(o,str)) - { - items.push_back(str); - } - } - auto res = Tesses::Framework::Filesystem::VFSPath(items); - res.relative = relative; - return res; - } - return nullptr; - } - void TStd::RegisterPath(std::shared_ptr gc,TRootEnvironment* env) - { + return nullptr; +} +void TStd::RegisterPath(std::shared_ptr gc, TRootEnvironment *env) { - env->permissions.canRegisterPath=true; - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - - gc->BarrierBegin(); - dict->DeclareFunction(gc,"FromString","Create a Path from string",{"path"},Path_FromString); - - dict->DeclareFunction(gc,"Create","Create a Path from parts",{"relative","parts"},Path_Create); - dict->DeclareFunction(gc,"Root","Create Absolute Root Path",{}, Path_Root); - env->DeclareVariable("Path", dict); - gc->BarrierEnd(); - } -} \ No newline at end of file + env->permissions.canRegisterPath = true; + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); + + gc->BarrierBegin(); + dict->DeclareFunction(gc, "FromString", "Create a Path from string", + {"path"}, Path_FromString); + + dict->DeclareFunction(gc, "Create", "Create a Path from parts", + {"relative", "parts"}, Path_Create); + dict->DeclareFunction(gc, "Root", "Create Absolute Root Path", {}, + Path_Root); + env->DeclareVariable("Path", dict); + gc->BarrierEnd(); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/runtime_methods/process.cpp b/src/runtime_methods/process.cpp index 2395983..3add70e 100644 --- a/src/runtime_methods/process.cpp +++ b/src/runtime_methods/process.cpp @@ -1,321 +1,285 @@ #include "CrossLang.hpp" +namespace Tesses::CrossLang { +class ProcessObject : public TNativeObject { + public: + ProcessObject() { + arguments = nullptr; + environment = nullptr; + } + ProcessObject(GCList &ls) { + arguments = TList::Create(ls); + environment = TList::Create(ls); + process.includeThisEnv = true; + process.redirectStdIn = false; + process.redirectStdOut = false; -namespace Tesses::CrossLang -{ - class ProcessObject : public TNativeObject { - public: - ProcessObject() - { - arguments=nullptr; - environment=nullptr; - - } - ProcessObject(GCList& ls) - { - arguments = TList::Create(ls); - environment = TList::Create(ls); - process.includeThisEnv=true; - process.redirectStdIn=false; - - process.redirectStdOut=false; - - process.redirectStdErr=false; - } - TList* arguments; - TList* environment; - Tesses::Framework::Platform::Process process; - std::string TypeName() - { - return "Process"; - } - void Mark() - { - if(this->marked) return; - this->marked=true; - if(arguments != nullptr) arguments->Mark(); - if(environment != nullptr) environment->Mark(); - } - TObject CallMethod(GCList& ls, std::string key, std::vector args) - { - if(key == "setFileName" && GetArgument(args,0,process.name)) - { - return process.name; - } - if(key == "getFileName") - { - return process.name; - } - - if(key == "setRedirectStandardInput" && GetArgument(args,0,process.redirectStdIn)) - { - return process.redirectStdIn; - } - if(key == "getRedirectStandardInput") - { - return process.redirectStdIn; - } - if(key == "setRedirectStandardOutput" && GetArgument(args,0,process.redirectStdOut)) - { - return process.redirectStdOut; - } - if(key == "getRedirectStandardOutput") - { - return process.redirectStdOut; - } - if(key == "setRedirectStandardError" && GetArgument(args,0,process.redirectStdErr)) - { - return process.redirectStdErr; - } - if(key == "getRedirectStandardError") - { - return process.redirectStdErr; - } - if(key == "setWorkingDirectory" && GetArgument(args,0,process.workingDirectory)) - { - return process.workingDirectory; - } - if(key == "getWorkingDirectory") - { - return process.workingDirectory; - } - if(key == "setInheritParentEnvironment" && GetArgument(args,0,process.includeThisEnv)) - { - return process.includeThisEnv; - } - if(key == "getInheritParentEnvironment") - { - return process.includeThisEnv; - } - if(key == "getArguments") - { - if(arguments == nullptr) return nullptr; - return arguments; - } - if(key == "setArguments") - { - if(GetArgumentHeap(args,0,arguments)) - { - return arguments; - } - } - if(key == "getEnvironment") - { - if(environment == nullptr) return nullptr; - return environment; - } - if(key == "getEnvironment") - { - if(GetArgumentHeap(args,0,environment)) - { - return environment; - } - } - if(key == "Start") - { - this->process.args.push_back(process.name); - if(arguments != nullptr) - { - for(int64_t i = 0; i < arguments->Count(); i++) - { - TObject argVal=arguments->Get(i); - std::string argValStr; - if(GetObject(argVal,argValStr)) - this->process.args.push_back(argValStr); - } - } - if(environment != nullptr) - { - for(int64_t i = 0; i < environment->Count(); i++) - { - TObject arg = environment->Get(i); - std::string argstr; - if(GetObject(arg,argstr)) - { - auto kvp = Tesses::Framework::Http::HttpUtils::SplitString(argstr,"=",2); - if(kvp.size()==2) - { - process.env.push_back(std::pair(kvp[0],kvp[1])); - } - else if(kvp.size()==1) - { - process.env.push_back(std::pair(kvp[0],"")); - } - } - } - } - return process.Start(); - } - if(key == "Join" || key == "WaitForExit") - { - return (int64_t)process.WaitForExit(); - } - if(key == "getHasExited") - { - return process.HasExited(); - } - if(key == "Terminate") - { - process.Kill(SIGTERM); - } - if(key == "CloseStdInNow") - { - process.CloseStdInNow(); - - } - int64_t k; - if(key == "Kill" && GetArgument(args,0,k)) - { - process.Kill((int)k); - } - if(key == "getStandardInput") - { - return process.GetStdinStream(); - } - if(key == "getStandardOutput") - { - return process.GetStdoutStream(); - } - if(key == "getStandardError") - { - return process.GetStderrStream(); - } - return Undefined(); - } - }; - static TObject Process_Start(GCList& ls, std::vector args, TRootEnvironment* env) - { - - //Process.Start({ - // FileName = "git", - // Arguments = ["clone","https://gitea.site.tesses.net/tesses50/crosslang.git"], - // Environment = [], - // InheritParentEnvironment=true - //}) - - TDictionary* dict; - - if(GetArgumentHeap(args,0,dict)) - { - auto process = TNativeObject::Create(ls); - auto name = dict->GetValue("FileName"); - auto inh = dict->GetValue("InheritParentEnvironment"); - auto rStdIn = dict->GetValue("RedirectStandardInput"); - auto rStdOut = dict->GetValue("RedirectStandardOutput"); - - auto rStdErr = dict->GetValue("RedirectStandardError"); - auto workingDirectory = dict->GetValue("WorkingDirectory"); - process->process.includeThisEnv=true; - process->process.redirectStdIn=false; - - process->process.redirectStdOut=false; - - process->process.redirectStdErr=false; - GetObject(inh,process->process.includeThisEnv); - GetObject(rStdIn,process->process.redirectStdIn); - GetObject(rStdOut,process->process.redirectStdOut); - GetObject(rStdErr,process->process.redirectStdErr); - - GetObject(name,process->process.name); - - Tesses::Framework::Filesystem::VFSPath wdPath; - if(env->permissions.localfs) - { - process->process.workingDirectory = env->permissions.localfs->GetWorking().ToString(); - } - - if(GetObject(workingDirectory,wdPath)) - { - process->process.workingDirectory= wdPath.MakeAbsolute().ToString(); - } - - GetObject(workingDirectory,process->process.workingDirectory); - - - - process->process.args.push_back(process->process.name); - auto argumentsO = dict->GetValue("Arguments"); - TList* arguments; - if(GetObjectHeap(argumentsO,arguments)) - { - for(int64_t i = 0; i < arguments->Count(); i++) - { - TObject arg = arguments->Get(i); - std::string argstr; - if(GetObject(arg,argstr)) - { - process->process.args.push_back(argstr); - } - } - } - argumentsO = dict->GetValue("Environment"); - if(GetObjectHeap(argumentsO,arguments)) - { - for(int64_t i = 0; i < arguments->Count(); i++) - { - TObject arg = arguments->Get(i); - std::string argstr; - if(GetObject(arg,argstr)) - { - auto kvp = Tesses::Framework::Http::HttpUtils::SplitString(argstr,"=",2); - if(kvp.size()==2) - { - process->process.env.push_back(std::pair(kvp[0],kvp[1])); - } - else if(kvp.size()==1) - { - process->process.env.push_back(std::pair(kvp[0],"")); - } - } - } - } - if(process->process.Start()) - { - return process; - } + process.redirectStdErr = false; + } + TList *arguments; + TList *environment; + Tesses::Framework::Platform::Process process; + std::string TypeName() { return "Process"; } + void Mark() { + if (this->marked) + return; + this->marked = true; + if (arguments != nullptr) + arguments->Mark(); + if (environment != nullptr) + environment->Mark(); + } + TObject CallMethod(GCList &ls, std::string key, std::vector args) { + if (key == "setFileName" && GetArgument(args, 0, process.name)) { + return process.name; + } + if (key == "getFileName") { + return process.name; } - return nullptr; - } - - - void TStd::RegisterProcess(std::shared_ptr gc,TRootEnvironment* env) - { - - env->permissions.canRegisterProcess=true; - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - - gc->BarrierBegin(); - auto processStart = TExternalMethod::Create(ls,"Start a process",{"process_object"},[env](GCList& ls, std::vector args)->TObject{ - return Process_Start(ls,args,env); - }); - processStart->watch.push_back(env); - dict->SetValue("Start",processStart); - - - env->SetVariable("Process",dict); - auto process = env->EnsureDictionary(gc,"New"); - auto newProcess = TExternalMethod::Create(ls, "Create process",{},[env](GCList& ls, std::vector args)->TObject { - auto obj= TNativeObject::Create(ls,ls); - if(env->permissions.localfs) - { - obj->process.workingDirectory = env->permissions.localfs->GetWorking().ToString(); + if (key == "setRedirectStandardInput" && + GetArgument(args, 0, process.redirectStdIn)) { + return process.redirectStdIn; + } + if (key == "getRedirectStandardInput") { + return process.redirectStdIn; + } + if (key == "setRedirectStandardOutput" && + GetArgument(args, 0, process.redirectStdOut)) { + return process.redirectStdOut; + } + if (key == "getRedirectStandardOutput") { + return process.redirectStdOut; + } + if (key == "setRedirectStandardError" && + GetArgument(args, 0, process.redirectStdErr)) { + return process.redirectStdErr; + } + if (key == "getRedirectStandardError") { + return process.redirectStdErr; + } + if (key == "setWorkingDirectory" && + GetArgument(args, 0, process.workingDirectory)) { + return process.workingDirectory; + } + if (key == "getWorkingDirectory") { + return process.workingDirectory; + } + if (key == "setInheritParentEnvironment" && + GetArgument(args, 0, process.includeThisEnv)) { + return process.includeThisEnv; + } + if (key == "getInheritParentEnvironment") { + return process.includeThisEnv; + } + if (key == "getArguments") { + if (arguments == nullptr) + return nullptr; + return arguments; + } + if (key == "setArguments") { + if (GetArgumentHeap(args, 0, arguments)) { + return arguments; } - return obj; + } + if (key == "getEnvironment") { + if (environment == nullptr) + return nullptr; + return environment; + } + if (key == "getEnvironment") { + if (GetArgumentHeap(args, 0, environment)) { + return environment; + } + } + if (key == "Start") { + this->process.args.push_back(process.name); + if (arguments != nullptr) { + for (int64_t i = 0; i < arguments->Count(); i++) { + TObject argVal = arguments->Get(i); + std::string argValStr; + if (GetObject(argVal, argValStr)) + this->process.args.push_back(argValStr); + } + } + if (environment != nullptr) { + for (int64_t i = 0; i < environment->Count(); i++) { + TObject arg = environment->Get(i); + std::string argstr; + if (GetObject(arg, argstr)) { + auto kvp = + Tesses::Framework::Http::HttpUtils::SplitString( + argstr, "=", 2); + if (kvp.size() == 2) { + process.env.push_back( + std::pair(kvp[0], + kvp[1])); + } else if (kvp.size() == 1) { + process.env.push_back( + std::pair(kvp[0], + "")); + } + } + } + } + return process.Start(); + } + if (key == "Join" || key == "WaitForExit") { + return (int64_t)process.WaitForExit(); + } + if (key == "getHasExited") { + return process.HasExited(); + } + if (key == "Terminate") { + process.Kill(SIGTERM); + } + if (key == "CloseStdInNow") { + process.CloseStdInNow(); + } + int64_t k; + if (key == "Kill" && GetArgument(args, 0, k)) { + process.Kill((int)k); + } + if (key == "getStandardInput") { + return process.GetStdinStream(); + } + if (key == "getStandardOutput") { + return process.GetStdoutStream(); + } + if (key == "getStandardError") { + return process.GetStderrStream(); + } + return Undefined(); + } +}; +static TObject Process_Start(GCList &ls, std::vector args, + TRootEnvironment *env) { + + // Process.Start({ + // FileName = "git", + // Arguments = + // ["clone","https://gitea.site.tesses.net/tesses50/crosslang.git"], + // Environment = [], + // InheritParentEnvironment=true + // }) + + TDictionary *dict; + + if (GetArgumentHeap(args, 0, dict)) { + auto process = TNativeObject::Create(ls); + auto name = dict->GetValue("FileName"); + auto inh = dict->GetValue("InheritParentEnvironment"); + auto rStdIn = dict->GetValue("RedirectStandardInput"); + auto rStdOut = dict->GetValue("RedirectStandardOutput"); + + auto rStdErr = dict->GetValue("RedirectStandardError"); + auto workingDirectory = dict->GetValue("WorkingDirectory"); + process->process.includeThisEnv = true; + process->process.redirectStdIn = false; + + process->process.redirectStdOut = false; + + process->process.redirectStdErr = false; + GetObject(inh, process->process.includeThisEnv); + GetObject(rStdIn, process->process.redirectStdIn); + GetObject(rStdOut, process->process.redirectStdOut); + GetObject(rStdErr, process->process.redirectStdErr); + + GetObject(name, process->process.name); + + Tesses::Framework::Filesystem::VFSPath wdPath; + if (env->permissions.localfs) { + process->process.workingDirectory = + env->permissions.localfs->GetWorking().ToString(); + } + + if (GetObject(workingDirectory, wdPath)) { + process->process.workingDirectory = + wdPath.MakeAbsolute().ToString(); + } + + GetObject(workingDirectory, process->process.workingDirectory); + + process->process.args.push_back(process->process.name); + auto argumentsO = dict->GetValue("Arguments"); + TList *arguments; + if (GetObjectHeap(argumentsO, arguments)) { + for (int64_t i = 0; i < arguments->Count(); i++) { + TObject arg = arguments->Get(i); + std::string argstr; + if (GetObject(arg, argstr)) { + process->process.args.push_back(argstr); + } + } + } + argumentsO = dict->GetValue("Environment"); + if (GetObjectHeap(argumentsO, arguments)) { + for (int64_t i = 0; i < arguments->Count(); i++) { + TObject arg = arguments->Get(i); + std::string argstr; + if (GetObject(arg, argstr)) { + auto kvp = Tesses::Framework::Http::HttpUtils::SplitString( + argstr, "=", 2); + if (kvp.size() == 2) { + process->process.env.push_back( + std::pair(kvp[0], + kvp[1])); + } else if (kvp.size() == 1) { + process->process.env.push_back( + std::pair(kvp[0], "")); + } + } + } + } + if (process->process.Start()) { + return process; + } + } + + return nullptr; +} + +void TStd::RegisterProcess(std::shared_ptr gc, TRootEnvironment *env) { + + env->permissions.canRegisterProcess = true; + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); + + gc->BarrierBegin(); + auto processStart = TExternalMethod::Create( + ls, "Start a process", {"process_object"}, + [env](GCList &ls, std::vector args) -> TObject { + return Process_Start(ls, args, env); }); - newProcess->watch.push_back(env); - process->SetValue("Process",newProcess); - //process->DeclareFunction(gc, "Process", "Create process",{},New_Process); - process->DeclareFunction(gc, "CGIServer", "Create a CGI Server",{"path"},[](GCList& ls, std::vector args)->TObject{ + processStart->watch.push_back(env); + dict->SetValue("Start", processStart); + + env->SetVariable("Process", dict); + auto process = env->EnsureDictionary(gc, "New"); + auto newProcess = TExternalMethod::Create( + ls, "Create process", {}, + [env](GCList &ls, std::vector args) -> TObject { + auto obj = TNativeObject::Create(ls, ls); + if (env->permissions.localfs) { + obj->process.workingDirectory = + env->permissions.localfs->GetWorking().ToString(); + } + return obj; + }); + newProcess->watch.push_back(env); + process->SetValue("Process", newProcess); + // process->DeclareFunction(gc, "Process", "Create process",{},New_Process); + process->DeclareFunction( + gc, "CGIServer", "Create a CGI Server", {"path"}, + [](GCList &ls, std::vector args) -> TObject { Tesses::Framework::Filesystem::VFSPath path; - if(GetArgumentAsPath(args,0,path)) - { - return std::make_shared(path); + if (GetArgumentAsPath(args, 0, path)) { + return std::make_shared( + path); } return Undefined(); }); - gc->BarrierEnd(); - } + gc->BarrierEnd(); } +} // namespace Tesses::CrossLang diff --git a/src/runtime_methods/sqlite.cpp b/src/runtime_methods/sqlite.cpp index f42a3f6..0fde954 100644 --- a/src/runtime_methods/sqlite.cpp +++ b/src/runtime_methods/sqlite.cpp @@ -3,228 +3,192 @@ #include namespace Tesses::CrossLang { - #if defined(TESSESFRAMEWORK_ENABLE_SQLITE) - using namespace Tesses::Framework::Serialization; - TObject Sqlite_Escape(GCList& ls, std::vector args) - { - int64_t n; - double d; - bool b; +#if defined(TESSESFRAMEWORK_ENABLE_SQLITE) +using namespace Tesses::Framework::Serialization; +TObject Sqlite_Escape(GCList &ls, std::vector args) { + int64_t n; + double d; + bool b; - - std::string str; - if(GetArgument(args,0,str)) - { - return SQLiteDatabase::Escape(str); - } - if(GetArgument(args,0,n)) - { - return std::to_string(n); - } - if(GetArgument(args,0,b)) - { - return b ? "1" : "0"; - } - if(GetArgument(args,0,d)) - { - return std::to_string(d); - } - - return "NULL"; + std::string str; + if (GetArgument(args, 0, str)) { + return SQLiteDatabase::Escape(str); } - - TObject Sqlite_Prepare(GCList& ls, std::vector args) - { - std::string str; - TList* list; - - std::string newStr = ""; - if(GetArgument(args,0,str) && GetArgumentHeap(args,1,list)) - { - int64_t item = 0; - - - for(size_t i = 0; i < str.size(); i++) - { - if(str[i] == '@' && (i+1>=str.size() || str[i+1] != '@')) - { - auto v = list->Get(item); - int64_t n; - double d; - bool b; - - - std::string str; - if(GetObject(v,str)) - { - newStr+= SQLiteDatabase::Escape(str); - } - else if(GetObject(v,n)) - { - newStr+= std::to_string(n); - } - else if(GetObject(v,b)) - { - newStr+= (b ? "1" : "0"); - } - else if(GetObject(v,d)) - { - newStr+= std::to_string(d); - } - else { - - newStr+= "NULL"; - } - } - else { - newStr+=str[i]; - } - } - - - } - return newStr; + if (GetArgument(args, 0, n)) { + return std::to_string(n); } - - class SQLiteObject : public TNativeObject - { - public: - SQLiteDatabase* db; - SQLiteObject(Tesses::Framework::Filesystem::VFSPath path) - { - db=new SQLiteDatabase(path); - } - - std::string TypeName() - { - return "SQLiteDatabase"; - } - void Close() - { - if(this->db == nullptr) return; - delete this->db; - this->db = nullptr; - - } - bool ToBool() - { - return this->db != nullptr; - } - - TObject CallMethod(GCList& ls,std::string name, std::vector args) - { - if(name == "Close") this->Close(); - if(name == "Escape") { - return Sqlite_Escape(ls,args); - } - if(name == "Prepare") { - return Sqlite_Prepare(ls,args); - } - if(name == "Exec") - { - std::string arg; - if(GetArgument(args,0,arg)) - { - if(this->db == nullptr) return nullptr; - std::vector>>> res; - - this->db->Exec(arg,res); - - TList* list = TList::Create(ls); - - for(auto& item : res) - { - TDictionary* dict = TDictionary::Create(ls); - for(auto& item2 : item) - { - if(item2.second) - dict->SetValue(item2.first,item2.second.value()); - else - dict->SetValue(item2.first,nullptr); - } - - list->Add(dict); - } - - return list; - } - } - return Undefined(); - } - - - ~SQLiteObject() - { - if(this->db != nullptr) - delete this->db; - } - }; - - - TObject Sqlite_Open(GCList& ls, std::vector args,TRootEnvironment* env) - { - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgumentAsPath(args,0,p)) - { - if(env->permissions.sqlite3Scoped) - { - p = env->permissions.sqliteOffsetPath / p.CollapseRelativeParents(); - } - - return TNativeObject::Create(ls,p); - } - - return Undefined(); - + if (GetArgument(args, 0, b)) { + return b ? "1" : "0"; } - TObject Sqlite_Exec(GCList& ls, std::vector args) - { - SQLiteObject* sql; - std::string cmd; - if(GetArgumentHeap(args,0,sql) && GetArgument(args,1,cmd)) - { - try { - return sql->CallMethod(ls,"Exec",{cmd}); - } catch(std::runtime_error& ex) - { - return (std::string)ex.what(); - } - } - - return Undefined(); - + if (GetArgument(args, 0, d)) { + return std::to_string(d); } - TObject Sqlite_Close(GCList& ls, std::vector args) - { - SQLiteObject* sql; - if(GetArgumentHeap(args,0,sql)) - { - sql->Close(); - } - return Undefined(); - } - - - #endif - void TStd::RegisterSqlite(std::shared_ptr gc,TRootEnvironment* env) - { - - env->permissions.canRegisterSqlite=true; - #if defined(TESSESFRAMEWORK_ENABLE_SQLITE) - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - dict->DeclareFunction(gc,"Open","Opens the database (returns database handle or an error message as string or undefined)",{"filename"},[env](GCList& ls, std::vector args)->TObject { - return Sqlite_Open(ls,args,env); - }); - dict->DeclareFunction(gc,"Exec","Execute sql (returns dictionary of columns key=value, an error message as string or undefined)",{"handle","sql"},Sqlite_Exec); - dict->DeclareFunction(gc,"Close","Close sql database",{"handle"},Sqlite_Close); - dict->DeclareFunction(gc,"Escape","Escape sql text",{"text"},Sqlite_Escape); - dict->DeclareFunction(gc,"Prepare", "Prepare sql",{"sql","items"}, Sqlite_Prepare); - - gc->BarrierBegin(); - env->DeclareVariable("Sqlite", dict); - gc->BarrierEnd(); - #endif - } + return "NULL"; } + +TObject Sqlite_Prepare(GCList &ls, std::vector args) { + std::string str; + TList *list; + + std::string newStr = ""; + if (GetArgument(args, 0, str) && GetArgumentHeap(args, 1, list)) { + int64_t item = 0; + + for (size_t i = 0; i < str.size(); i++) { + if (str[i] == '@' && (i + 1 >= str.size() || str[i + 1] != '@')) { + auto v = list->Get(item); + int64_t n; + double d; + bool b; + + std::string str; + if (GetObject(v, str)) { + newStr += SQLiteDatabase::Escape(str); + } else if (GetObject(v, n)) { + newStr += std::to_string(n); + } else if (GetObject(v, b)) { + newStr += (b ? "1" : "0"); + } else if (GetObject(v, d)) { + newStr += std::to_string(d); + } else { + + newStr += "NULL"; + } + } else { + newStr += str[i]; + } + } + } + return newStr; +} + +class SQLiteObject : public TNativeObject { + public: + SQLiteDatabase *db; + SQLiteObject(Tesses::Framework::Filesystem::VFSPath path) { + db = new SQLiteDatabase(path); + } + + std::string TypeName() { return "SQLiteDatabase"; } + void Close() { + if (this->db == nullptr) + return; + delete this->db; + this->db = nullptr; + } + bool ToBool() { return this->db != nullptr; } + + TObject CallMethod(GCList &ls, std::string name, + std::vector args) { + if (name == "Close") + this->Close(); + if (name == "Escape") { + return Sqlite_Escape(ls, args); + } + if (name == "Prepare") { + return Sqlite_Prepare(ls, args); + } + if (name == "Exec") { + std::string arg; + if (GetArgument(args, 0, arg)) { + if (this->db == nullptr) + return nullptr; + std::vector>>> + res; + + this->db->Exec(arg, res); + + TList *list = TList::Create(ls); + + for (auto &item : res) { + TDictionary *dict = TDictionary::Create(ls); + for (auto &item2 : item) { + if (item2.second) + dict->SetValue(item2.first, item2.second.value()); + else + dict->SetValue(item2.first, nullptr); + } + + list->Add(dict); + } + + return list; + } + } + return Undefined(); + } + + ~SQLiteObject() { + if (this->db != nullptr) + delete this->db; + } +}; + +TObject Sqlite_Open(GCList &ls, std::vector args, + TRootEnvironment *env) { + Tesses::Framework::Filesystem::VFSPath p; + if (GetArgumentAsPath(args, 0, p)) { + if (env->permissions.sqlite3Scoped) { + p = env->permissions.sqliteOffsetPath / p.CollapseRelativeParents(); + } + + return TNativeObject::Create(ls, p); + } + + return Undefined(); +} +TObject Sqlite_Exec(GCList &ls, std::vector args) { + SQLiteObject *sql; + std::string cmd; + if (GetArgumentHeap(args, 0, sql) && GetArgument(args, 1, cmd)) { + try { + return sql->CallMethod(ls, "Exec", {cmd}); + } catch (std::runtime_error &ex) { + return (std::string)ex.what(); + } + } + + return Undefined(); +} + +TObject Sqlite_Close(GCList &ls, std::vector args) { + SQLiteObject *sql; + if (GetArgumentHeap(args, 0, sql)) { + sql->Close(); + } + return Undefined(); +} + +#endif +void TStd::RegisterSqlite(std::shared_ptr gc, TRootEnvironment *env) { + + env->permissions.canRegisterSqlite = true; +#if defined(TESSESFRAMEWORK_ENABLE_SQLITE) + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); + dict->DeclareFunction( + gc, "Open", + "Opens the database (returns database handle or an error message as " + "string or undefined)", + {"filename"}, [env](GCList &ls, std::vector args) -> TObject { + return Sqlite_Open(ls, args, env); + }); + dict->DeclareFunction(gc, "Exec", + "Execute sql (returns dictionary of columns " + "key=value, an error message as string or undefined)", + {"handle", "sql"}, Sqlite_Exec); + dict->DeclareFunction(gc, "Close", "Close sql database", {"handle"}, + Sqlite_Close); + dict->DeclareFunction(gc, "Escape", "Escape sql text", {"text"}, + Sqlite_Escape); + dict->DeclareFunction(gc, "Prepare", "Prepare sql", {"sql", "items"}, + Sqlite_Prepare); + + gc->BarrierBegin(); + env->DeclareVariable("Sqlite", dict); + gc->BarrierEnd(); +#endif +} +} // namespace Tesses::CrossLang diff --git a/src/runtime_methods/std.cpp b/src/runtime_methods/std.cpp index c5181ef..fe5ae5d 100644 --- a/src/runtime_methods/std.cpp +++ b/src/runtime_methods/std.cpp @@ -6,7 +6,7 @@ #include #include #include -#if defined(CROSSLANG_ENABLE_SHARED) +#if !defined(CROSSLANG_STATIC) #if defined(CROSSLANG_ENABLE_FFI) #include #endif @@ -32,1574 +32,1609 @@ #endif #endif - - - - -namespace Tesses::CrossLang -{ +namespace Tesses::CrossLang { #if defined(_WIN32) - std::string SharedExtension = ".dll"; +std::string SharedExtension = ".dll"; #elif defined(__APPLE__) - std::string SharedExtension = ".dylib"; +std::string SharedExtension = ".dylib"; #else - std::string SharedExtension = ".so"; +std::string SharedExtension = ".so"; #endif +class TMuxex : public TNativeObject { + public: + Tesses::Framework::Threading::Mutex mtx; - class TMuxex : public TNativeObject - { - public: - Tesses::Framework::Threading::Mutex mtx; + std::string TypeName() { return "Mutex"; } - std::string TypeName() - { - return "Mutex"; - } - - TObject CallMethod(GCList& ls, std::string key, std::vector args) - { - if(key == "Lock") - { - mtx.Lock(); - } - else if(key == "Unlock") - { - mtx.Unlock(); - } - else if(key == "TryLock") - { - return mtx.TryLock(); - } - - return Undefined(); - } - }; - - - - - - #if defined(CROSSLANG_ENABLE_SHARED) - class DL { - void* handle; - public: - DL(Tesses::Framework::Filesystem::VFSPath p) - { - Tesses::Framework::Filesystem::LocalFilesystem lfs; - std::string str = lfs.VFSPathToSystem(p); - #if defined(_WIN32) - handle = LoadLibraryExA(str.c_str() , NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); - #else - handle = dlopen(str.c_str(), RTLD_LAZY); - #endif - } - template - T Resolve(std::string name) - { - #if defined(_WIN32) - return (T)GetProcAddress((HMODULE)handle,name.c_str()); - #else - return (T)dlsym(handle,name.c_str()); - - #endif - } - ~DL() - { - #if defined(_WIN32) - FreeLibrary((HMODULE)handle); - #else - dlclose(handle); - #endif - } - }; - #endif - #if defined(CROSSLANG_ENABLE_FFI) - typedef union { - ffi_arg v_arg; - ffi_sarg v_sarg; - uint64_t v_u64; - int64_t v_i64; - double v_f64; - void* v_ptr; - - } ffi_tmp_type_t; - - template - class ffi_my_struct_t { - char ffi_my_struct_chr; - T ffi_my_struct_val; - - public: - static int64_t GetPadding() - { - ffi_my_struct_t s; - return ((int64_t)&s.ffi_my_struct_val - (int64_t)&s.ffi_my_struct_chr); - } - }; - - - - ffi_tmp_type_t FFI_ConvertTObjectToFFIType(TObject& arg,std::string t) - { - - if(std::holds_alternative(arg)) - { - if(t == "char" || t == "i8" || t == "i16" || t == "i32") - { - return (ffi_tmp_type_t){.v_sarg = std::get(arg)}; - } - else if(t == "u8" || t == "u16" || t == "u32") - { - return (ffi_tmp_type_t){.v_arg = (uint8_t)std::get(arg)}; - } - else if(t == "u64") - { - return (ffi_tmp_type_t){.v_u64 = (uint8_t)std::get(arg)}; - } - else if(t == "i64") - { - return (ffi_tmp_type_t){.v_i64 = std::get(arg)}; - } - } - else if(std::holds_alternative(arg)) - { - if(t == "u8" || t == "u16" || t == "u32") - { - return (ffi_tmp_type_t){.v_arg = (ffi_arg)(uint64_t)std::get(arg)}; - } - else if(t == "char" || t == "i8" || t == "i16" || t == "i32") - { - return (ffi_tmp_type_t){.v_sarg = (ffi_sarg)std::get(arg)}; - } - else if(t == "u64") - { - return (ffi_tmp_type_t){.v_u64 = (uint64_t)std::get(arg)}; - } - else if(t == "i64") - { - return (ffi_tmp_type_t){.v_i64 =std::get(arg)}; - } - else if(t == "pointer" || t == "string") - { - return (ffi_tmp_type_t){.v_ptr = (void*)std::get(arg)}; - } - } - else if(std::holds_alternative(arg)) - { - if(t == "f64") - { - return (ffi_tmp_type_t){.v_f64 =std::get(arg)}; - } - } - else if(std::holds_alternative(arg)) - { - if(t == "pointer" || t == "string") - { - return (ffi_tmp_type_t){.v_ptr = (void*)std::get(arg).c_str()}; - } - } - else if(std::holds_alternative(arg)) - { - auto obj = std::get(arg).obj; - auto bA = dynamic_cast(obj); - auto nat = dynamic_cast(obj); - if(bA != nullptr) - { - if(t == "pointer" || t == "string") - { - return (ffi_tmp_type_t){.v_ptr = (void*)bA->data.data() }; - } - } - if(nat != nullptr) - { - if(t == "pointer" || t == "string") - { - return (ffi_tmp_type_t){.v_ptr = nat->GetPointer() }; - } - } + TObject CallMethod(GCList &ls, std::string key, std::vector args) { + if (key == "Lock") { + mtx.Lock(); + } else if (key == "Unlock") { + mtx.Unlock(); + } else if (key == "TryLock") { + return mtx.TryLock(); } + return Undefined(); + } +}; - return {0}; +#if !defined(CROSSLANG_STATIC) +class DL { + void *handle; + + public: + DL(Tesses::Framework::Filesystem::VFSPath p) { + Tesses::Framework::Filesystem::LocalFilesystem lfs; + std::string str = lfs.VFSPathToSystem(p); +#if defined(_WIN32) + handle = + LoadLibraryExA(str.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); +#else + handle = dlopen(str.c_str(), RTLD_LAZY); +#endif + } + template T Resolve(std::string name) { +#if defined(_WIN32) + return (T)GetProcAddress((HMODULE)handle, name.c_str()); +#else + return (T)dlsym(handle, name.c_str()); + +#endif + } + ~DL() { +#if defined(_WIN32) + FreeLibrary((HMODULE)handle); +#else + dlclose(handle); +#endif + } +}; +#endif +#if defined(CROSSLANG_ENABLE_FFI) +typedef union { + ffi_arg v_arg; + ffi_sarg v_sarg; + uint64_t v_u64; + int64_t v_i64; + double v_f64; + void *v_ptr; + +} ffi_tmp_type_t; + +template class ffi_my_struct_t { + char ffi_my_struct_chr; + T ffi_my_struct_val; + + public: + static int64_t GetPadding() { + ffi_my_struct_t s; + return ((int64_t)&s.ffi_my_struct_val - (int64_t)&s.ffi_my_struct_chr); + } +}; + +ffi_tmp_type_t FFI_ConvertTObjectToFFIType(TObject &arg, std::string t) { + + if (std::holds_alternative(arg)) { + if (t == "char" || t == "i8" || t == "i16" || t == "i32") { + return (ffi_tmp_type_t){.v_sarg = std::get(arg)}; + } else if (t == "u8" || t == "u16" || t == "u32") { + return (ffi_tmp_type_t){.v_arg = (uint8_t)std::get(arg)}; + } else if (t == "u64") { + return (ffi_tmp_type_t){.v_u64 = (uint8_t)std::get(arg)}; + } else if (t == "i64") { + return (ffi_tmp_type_t){.v_i64 = std::get(arg)}; + } + } else if (std::holds_alternative(arg)) { + if (t == "u8" || t == "u16" || t == "u32") { + return (ffi_tmp_type_t){ + .v_arg = (ffi_arg)(uint64_t)std::get(arg)}; + } else if (t == "char" || t == "i8" || t == "i16" || t == "i32") { + return (ffi_tmp_type_t){.v_sarg = (ffi_sarg)std::get(arg)}; + } else if (t == "u64") { + return (ffi_tmp_type_t){.v_u64 = (uint64_t)std::get(arg)}; + } else if (t == "i64") { + return (ffi_tmp_type_t){.v_i64 = std::get(arg)}; + } else if (t == "pointer" || t == "string") { + return (ffi_tmp_type_t){.v_ptr = (void *)std::get(arg)}; + } + } else if (std::holds_alternative(arg)) { + if (t == "f64") { + return (ffi_tmp_type_t){.v_f64 = std::get(arg)}; + } + } else if (std::holds_alternative(arg)) { + if (t == "pointer" || t == "string") { + return (ffi_tmp_type_t){ + .v_ptr = (void *)std::get(arg).c_str()}; + } + } else if (std::holds_alternative(arg)) { + auto obj = std::get(arg).obj; + auto bA = dynamic_cast(obj); + auto nat = dynamic_cast(obj); + if (bA != nullptr) { + if (t == "pointer" || t == "string") { + return (ffi_tmp_type_t){.v_ptr = (void *)bA->data.data()}; + } + } + if (nat != nullptr) { + if (t == "pointer" || t == "string") { + return (ffi_tmp_type_t){.v_ptr = nat->GetPointer()}; + } + } } - ffi_type* FFI_ConvertStringToFFIType(std::string t) - { - if(t == "char") - { - return &ffi_type_schar; - } - else if(t == "i8") - { - return &ffi_type_sint8; - } - else if(t == "u8") - { - return &ffi_type_uint8; - } - else if(t == "i16") - { - return &ffi_type_sint16; - } - else if(t == "u16") - { - return &ffi_type_uint16; - } - else if(t == "i32") - { - return &ffi_type_sint32; - } - else if(t == "u32") - { - return &ffi_type_uint32; - } - else if(t == "i64") - { - return &ffi_type_sint64; - } - else if(t == "u64") - { - return &ffi_type_uint64; - } - else if(t == "float") - { - return &ffi_type_float; - } - else if(t == "double") - { - return &ffi_type_double; - } - else if(t == "void") - { - return &ffi_type_void; - } - else if(t == "pointer" || t == "string") - { - return &ffi_type_pointer; - } - return nullptr; + return {0}; +} + +ffi_type *FFI_ConvertStringToFFIType(std::string t) { + if (t == "char") { + return &ffi_type_schar; + } else if (t == "i8") { + return &ffi_type_sint8; + } else if (t == "u8") { + return &ffi_type_uint8; + } else if (t == "i16") { + return &ffi_type_sint16; + } else if (t == "u16") { + return &ffi_type_uint16; + } else if (t == "i32") { + return &ffi_type_sint32; + } else if (t == "u32") { + return &ffi_type_uint32; + } else if (t == "i64") { + return &ffi_type_sint64; + } else if (t == "u64") { + return &ffi_type_uint64; + } else if (t == "float") { + return &ffi_type_float; + } else if (t == "double") { + return &ffi_type_double; + } else if (t == "void") { + return &ffi_type_void; + } else if (t == "pointer" || t == "string") { + return &ffi_type_pointer; } - TExternalMethod* FFI_CreateFunction(GCList& ls,TNative* native,std::string retVal,std::vector listArgs,ffi_abi abi,bool freeRet) - { - ffi_type* retTypeT = FFI_ConvertStringToFFIType(retVal); - std::vector argTypes; + return nullptr; +} +TExternalMethod *FFI_CreateFunction(GCList &ls, TNative *native, + std::string retVal, + std::vector listArgs, + ffi_abi abi, bool freeRet) { + ffi_type *retTypeT = FFI_ConvertStringToFFIType(retVal); + std::vector argTypes; - argTypes.resize(listArgs.size()); - for(size_t i = 0; i < listArgs.size();i++) - { - argTypes[i] = FFI_ConvertStringToFFIType(listArgs[i]); - } - auto cb = TExternalMethod::Create(ls,"FFI Generated function, returns: " + retVal,listArgs, [retVal,listArgs,abi,native,freeRet,argTypes,retTypeT](GCList& ls, std::vector args)->TObject { - if(args.size() != listArgs.size()) throw VMException("Args must be " + std::to_string(listArgs.size()) + "but got " + std::to_string(args.size()) + "."); - ffi_cif cif; - - std::vector argVals; - std::vector tmpTypes; - argVals.resize(listArgs.size()); - tmpTypes.resize(listArgs.size()); - for(size_t i = 0; i < argTypes.size(); i++) - { - - tmpTypes[i] = FFI_ConvertTObjectToFFIType(args[i],listArgs[i]); - if(listArgs[i] == "char" || listArgs[i] == "i8" || listArgs[i] == "i16" || listArgs[i] == "i32" || listArgs[i] == "u8" || listArgs[i] == "u16" || listArgs[i] == "u32") - { - argVals[i] = (void*)&(tmpTypes[i].v_arg); - } - - else if(listArgs[i] == "u64" || listArgs[i] == "i64") - { - argVals[i] = (void*)&(tmpTypes[i].v_u64); - } - else if(listArgs[i] == "pointer" || listArgs[i] == "string") - { - argVals[i] = (void*)&(tmpTypes[i].v_ptr); - } - else if(listArgs[i] == "f64") - { - argVals[i] = (void*)&(tmpTypes[i].v_f64); - } - } - ffi_prep_cif(&cif, abi,(unsigned int)listArgs.size(),retTypeT,(ffi_type**)argTypes.data()); - - ffi_tmp_type_t retObj; - void* retPtr=NULL; - if(retVal == "char" || retVal == "i8" || retVal == "u8" || retVal == "i16" || retVal == "u16" || retVal == "i32" || retVal == "u32") - { - retPtr = (void*)&(retObj.v_arg); - } - else if(retVal == "i64" || retVal == "u64") - { - retPtr = (void*)&(retObj.v_u64); - } - else if(retVal == "f64") - { - retPtr = (void*)&(retObj.v_f64); - } - else if(retVal == "pointer" || retVal == "string") - { - retPtr = (void*)&(retObj.v_ptr); - } - - - ffi_call(&cif, (void(*)())native->GetPointer() , retPtr, argVals.data()); - - - - if(retVal == "char") return (char)retObj.v_sarg; - if(retVal == "i8" || retVal == "i16" || retVal == "i32") return (int64_t)retObj.v_sarg; - if(retVal == "u8" || retVal == "u16" || retVal == "u32") return (int64_t)retObj.v_arg; - if(retVal == "i64" || retVal == "u64") return retObj.v_i64; - if(retVal == "f64") return retObj.v_f64; - if(retVal == "string") - { - std::string res = (char*)retObj.v_ptr; - if(freeRet) - free(retObj.v_ptr); - return res; - } - if(retVal == "pointer") - { - TNative* native3 = TNative::Create(ls,retObj.v_ptr,[freeRet](void* _ptr)->void { - if(freeRet) free(_ptr); - }); - native3->other = native; - return native3; - } - return nullptr; - }); - cb->watch.push_back(native); - return cb; + argTypes.resize(listArgs.size()); + for (size_t i = 0; i < listArgs.size(); i++) { + argTypes[i] = FFI_ConvertStringToFFIType(listArgs[i]); } + auto cb = TExternalMethod::Create( + ls, "FFI Generated function, returns: " + retVal, listArgs, + [retVal, listArgs, abi, native, freeRet, argTypes, + retTypeT](GCList &ls, std::vector args) -> TObject { + if (args.size() != listArgs.size()) + throw VMException("Args must be " + + std::to_string(listArgs.size()) + "but got " + + std::to_string(args.size()) + "."); + ffi_cif cif; - - + std::vector argVals; + std::vector tmpTypes; + argVals.resize(listArgs.size()); + tmpTypes.resize(listArgs.size()); + for (size_t i = 0; i < argTypes.size(); i++) { - void RegisterFFI(std::shared_ptr gc, TDictionary* dict) - { - dict->SetValue("SizeOfChar",(int64_t)sizeof(char)); - dict->SetValue("SizeOfShort",(int64_t)sizeof(short)); - dict->SetValue("SizeOfInt",(int64_t)sizeof(int)); - dict->SetValue("SizeOfLong",(int64_t)sizeof(long)); - dict->SetValue("SizeOfLongLong",(int64_t)sizeof(long long)); - dict->SetValue("SizeOfInt8",(int64_t)sizeof(int8_t)); - dict->SetValue("SizeOfInt16",(int64_t)sizeof(int16_t)); - dict->SetValue("SizeOfInt32",(int64_t)sizeof(int32_t)); - dict->SetValue("SizeOfInt64",(int64_t)sizeof(int64_t)); - dict->SetValue("SizeOfFloat",(int64_t)sizeof(float)); - dict->SetValue("SizeOfDouble",(int64_t)sizeof(double)); - dict->SetValue("SizeOfPointer",(int64_t)sizeof(void*)); - dict->SetValue("PaddingOfShort",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfInt",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfLong",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfLongLong",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfInt16",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfInt32",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfInt64",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfFloat",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfDouble",ffi_my_struct_t::GetPadding()); - dict->SetValue("PaddingOfPointer",ffi_my_struct_t::GetPadding()); + tmpTypes[i] = FFI_ConvertTObjectToFFIType(args[i], listArgs[i]); + if (listArgs[i] == "char" || listArgs[i] == "i8" || + listArgs[i] == "i16" || listArgs[i] == "i32" || + listArgs[i] == "u8" || listArgs[i] == "u16" || + listArgs[i] == "u32") { + argVals[i] = (void *)&(tmpTypes[i].v_arg); + } - union { - uint8_t c[2]; - uint16_t num; - } endian; - endian.c[0] = 0x01; - endian.c[1] = 0xA4; + else if (listArgs[i] == "u64" || listArgs[i] == "i64") { + argVals[i] = (void *)&(tmpTypes[i].v_u64); + } else if (listArgs[i] == "pointer" || + listArgs[i] == "string") { + argVals[i] = (void *)&(tmpTypes[i].v_ptr); + } else if (listArgs[i] == "f64") { + argVals[i] = (void *)&(tmpTypes[i].v_f64); + } + } + ffi_prep_cif(&cif, abi, (unsigned int)listArgs.size(), retTypeT, + (ffi_type **)argTypes.data()); - dict->SetValue("IsLittleEndian", (bool)(endian.num != 420)); + ffi_tmp_type_t retObj; + void *retPtr = NULL; + if (retVal == "char" || retVal == "i8" || retVal == "u8" || + retVal == "i16" || retVal == "u16" || retVal == "i32" || + retVal == "u32") { + retPtr = (void *)&(retObj.v_arg); + } else if (retVal == "i64" || retVal == "u64") { + retPtr = (void *)&(retObj.v_u64); + } else if (retVal == "f64") { + retPtr = (void *)&(retObj.v_f64); + } else if (retVal == "pointer" || retVal == "string") { + retPtr = (void *)&(retObj.v_ptr); + } + ffi_call(&cif, (void (*)())native->GetPointer(), retPtr, + argVals.data()); - dict->DeclareFunction(gc, "Open","Open a shared object",{"path"},[](GCList& ls, std::vector args)->TObject { - Tesses::Framework::Filesystem::VFSPath path; - if(GetArgumentAsPath(args,0,path)) - { - return TNative::Create(ls,static_cast(new DL(path)),[](void* ptr)->void { - delete static_cast(ptr); - }); + if (retVal == "char") + return (char)retObj.v_sarg; + if (retVal == "i8" || retVal == "i16" || retVal == "i32") + return (int64_t)retObj.v_sarg; + if (retVal == "u8" || retVal == "u16" || retVal == "u32") + return (int64_t)retObj.v_arg; + if (retVal == "i64" || retVal == "u64") + return retObj.v_i64; + if (retVal == "f64") + return retObj.v_f64; + if (retVal == "string") { + std::string res = (char *)retObj.v_ptr; + if (freeRet) + free(retObj.v_ptr); + return res; + } + if (retVal == "pointer") { + TNative *native3 = TNative::Create( + ls, retObj.v_ptr, [freeRet](void *_ptr) -> void { + if (freeRet) + free(_ptr); + }); + native3->other = native; + return native3; } return nullptr; }); - dict->DeclareFunction(gc, "Symbol","Get current symbol",{"sharedObj","name"},[](GCList& ls, std::vector args)->TObject { - TNative* native; + cb->watch.push_back(native); + return cb; +} + +void RegisterFFI(std::shared_ptr gc, TDictionary *dict) { + dict->SetValue("SizeOfChar", (int64_t)sizeof(char)); + dict->SetValue("SizeOfShort", (int64_t)sizeof(short)); + dict->SetValue("SizeOfInt", (int64_t)sizeof(int)); + dict->SetValue("SizeOfLong", (int64_t)sizeof(long)); + dict->SetValue("SizeOfLongLong", (int64_t)sizeof(long long)); + dict->SetValue("SizeOfInt8", (int64_t)sizeof(int8_t)); + dict->SetValue("SizeOfInt16", (int64_t)sizeof(int16_t)); + dict->SetValue("SizeOfInt32", (int64_t)sizeof(int32_t)); + dict->SetValue("SizeOfInt64", (int64_t)sizeof(int64_t)); + dict->SetValue("SizeOfFloat", (int64_t)sizeof(float)); + dict->SetValue("SizeOfDouble", (int64_t)sizeof(double)); + dict->SetValue("SizeOfPointer", (int64_t)sizeof(void *)); + dict->SetValue("PaddingOfShort", ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfInt", ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfLong", ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfLongLong", + ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfInt16", ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfInt32", ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfInt64", ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfFloat", ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfDouble", ffi_my_struct_t::GetPadding()); + dict->SetValue("PaddingOfPointer", ffi_my_struct_t::GetPadding()); + + union { + uint8_t c[2]; + uint16_t num; + } endian; + endian.c[0] = 0x01; + endian.c[1] = 0xA4; + + dict->SetValue("IsLittleEndian", (bool)(endian.num != 420)); + + dict->DeclareFunction( + gc, "Open", "Open a shared object", {"path"}, + [](GCList &ls, std::vector args) -> TObject { + Tesses::Framework::Filesystem::VFSPath path; + if (GetArgumentAsPath(args, 0, path)) { + return TNative::Create( + ls, static_cast(new DL(path)), + [](void *ptr) -> void { delete static_cast
(ptr); }); + } + return nullptr; + }); + dict->DeclareFunction( + gc, "Symbol", "Get current symbol", {"sharedObj", "name"}, + [](GCList &ls, std::vector args) -> TObject { + TNative *native; std::string name; - if(GetArgumentHeap(args,0,native) && GetArgument(args,1,name)) { - if(native->GetDestroyed()) return nullptr; - DL* dl = static_cast(native->GetPointer()); - auto native2= TNative::Create(ls,dl->Resolve(name), [](void* _e)->void {}); + if (GetArgumentHeap(args, 0, native) && + GetArgument(args, 1, name)) { + if (native->GetDestroyed()) + return nullptr; + DL *dl = static_cast
(native->GetPointer()); + auto native2 = TNative::Create(ls, dl->Resolve(name), + [](void *_e) -> void {}); native2->other = native; return native2; } return nullptr; }); - dict->DeclareFunction(gc, "Close", "Closes the shared object",{"sharedObj"},[](GCList& ls, std::vector args)->TObject { - TNative* native; - if(GetArgumentHeap(args,0,native)) native->Destroy(); + dict->DeclareFunction(gc, "Close", "Closes the shared object", + {"sharedObj"}, + [](GCList &ls, std::vector args) -> TObject { + TNative *native; + if (GetArgumentHeap(args, 0, native)) + native->Destroy(); - return nullptr; - }); - + return nullptr; + }); - dict->DeclareFunction(gc, "CreateFunction","Create a function", {"functionPtr","returnVal","args","$abi","$freeRet"},[](GCList& ls, std::vector args)->TObject { - TNative* native; + dict->DeclareFunction( + gc, "CreateFunction", "Create a function", + {"functionPtr", "returnVal", "args", "$abi", "$freeRet"}, + [](GCList &ls, std::vector args) -> TObject { + TNative *native; std::string retVal; - TList* listArgsO; - int64_t abi=(int64_t)FFI_DEFAULT_ABI; - bool freeRet=false; - if(GetArgumentHeap(args,0,native) && GetArgument(args,1,retVal) && GetArgumentHeap(args,2,listArgsO)) - { - GetArgument(args,3,abi); - GetArgument(args,4,freeRet); + TList *listArgsO; + int64_t abi = (int64_t)FFI_DEFAULT_ABI; + bool freeRet = false; + if (GetArgumentHeap(args, 0, native) && + GetArgument(args, 1, retVal) && + GetArgumentHeap(args, 2, listArgsO)) { + GetArgument(args, 3, abi); + GetArgument(args, 4, freeRet); std::vector listArgs; - for(int64_t i = 0; i < listArgsO->Count(); i++) - { + for (int64_t i = 0; i < listArgsO->Count(); i++) { auto item = listArgsO->Get(i); std::string typ; - if(GetObject(item, typ)) listArgs.push_back(typ); + if (GetObject(item, typ)) + listArgs.push_back(typ); } - - return FFI_CreateFunction(ls,native,retVal,listArgs,(ffi_abi)abi,freeRet); + return FFI_CreateFunction(ls, native, retVal, listArgs, + (ffi_abi)abi, freeRet); } return nullptr; }); - } - #endif - - Tesses::Framework::Filesystem::VFSPath GetPluginPath(Tesses::Framework::Filesystem::VFSPath path) - { - using namespace Tesses::Framework::Filesystem; - if(!path.relative) return path; - - auto pluginConfigDir = GetCrossLangConfigDir() / "Plugins"; - if(LocalFS->DirectoryExists(pluginConfigDir)) - { - if(LocalFS->FileExists(pluginConfigDir / path + SharedExtension)) - return pluginConfigDir / path + SharedExtension; - auto path2 = pluginConfigDir / path.GetParent() / "lib" + path.GetFileName() + SharedExtension; - if(LocalFS->FileExists(path2)) return path2; - } +} +#endif +Tesses::Framework::Filesystem::VFSPath +GetPluginPath(Tesses::Framework::Filesystem::VFSPath path) { + using namespace Tesses::Framework::Filesystem; + if (!path.relative) return path; + + auto pluginConfigDir = GetCrossLangConfigDir() / "Plugins"; + if (LocalFS->DirectoryExists(pluginConfigDir)) { + if (LocalFS->FileExists(pluginConfigDir / path + SharedExtension)) + return pluginConfigDir / path + SharedExtension; + auto path2 = pluginConfigDir / path.GetParent() / "lib" + + path.GetFileName() + SharedExtension; + if (LocalFS->FileExists(path2)) + return path2; } + return path; +} - void LoadPlugin(std::shared_ptr gc, TRootEnvironment* env, Tesses::Framework::Filesystem::VFSPath sharedObjectPath) - { - - #if defined(CROSSLANG_ENABLE_SHARED) - auto ptr = std::make_shared
(GetPluginPath(sharedObjectPath)); - auto cb = ptr->Resolve("CrossLangPluginInit"); - if(cb == nullptr) return; - gc->RegisterEverythingCallback([ptr,cb](std::shared_ptr gc, TRootEnvironment* env)-> void{ - cb(gc,env); +void LoadPlugin(std::shared_ptr gc, TRootEnvironment *env, + Tesses::Framework::Filesystem::VFSPath sharedObjectPath) { + +#if !defined(CROSSLANG_STATIC) + auto ptr = std::make_shared
(GetPluginPath(sharedObjectPath)); + auto cb = ptr->Resolve("CrossLangPluginInit"); + if (cb == nullptr) + return; + gc->RegisterEverythingCallback( + [ptr, cb](std::shared_ptr gc, TRootEnvironment *env) -> void { + cb(gc, env); }); - cb(gc,env); - #endif - } - static TObject TypeIsClass(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - if(args.empty()) return nullptr; - TClassObject* co; - return GetArgumentHeap(args,0,co); - } - - static TObject TypeIsDefined(GCList& ls,std::vector args) - { - if(args.empty()) return nullptr; - return (!std::holds_alternative(args[0]) && !std::holds_alternative(args[0])); - } - static TObject TypeIsHeap(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - return std::holds_alternative(args[0]); - } - static TObject TypeIsNumber(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - return std::holds_alternative(args[0]) || std::holds_alternative(args[0]); - } - static TObject TypeIsLong(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - return std::holds_alternative(args[0]); - } - static TObject TypeIsDouble(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - return std::holds_alternative(args[0]); - } - static TObject TypeIsString(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - return std::holds_alternative(args[0]); - } - static TObject TypeIsCallable(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - TCallable* call; - return GetArgumentHeap(args,0,call); - } - static TObject TypeIsDictionary(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - TDictionary* dict; - TDynamicDictionary* dynDict; - return GetArgumentHeap(args,0,dict) || GetArgumentHeap(args,0,dynDict); - } - static TObject TypeIsList(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - TList* list; - TDynamicList* dynList; - return GetArgumentHeap(args,0,list) || GetArgumentHeap(args,0, dynList); - } - static TObject TypeIsStream(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr strm; - return GetArgument(args,0,strm); - } - static TObject TypeIsTextReader(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr strm; - return GetArgument(args,0,strm); - } - static TObject TypeIsTextWriter(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr strm; - return GetArgument(args,0,strm); - } - static TObject TypeIsByteReader(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr strm; - return GetArgument(args,0,strm); - } - static TObject TypeIsByteWriter(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr strm; - return GetArgument(args,0,strm); - } - static TObject TypeIsUuid(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - return std::holds_alternative(args[0]); - } - static TObject TypeIsVFS(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr vfs; - return GetArgument(args,0,vfs); - } - - static TObject TypeIsDateTime(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr dt; - return GetArgument(args,0,dt); - } - static TObject TypeIsTimeSpan(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - std::shared_ptr dt; - return GetArgument(args,0,dt); - } - static TObject TypeIsQueryable(GCList& ls, std::vector args) - { - if(args.empty()) return nullptr; - TQueryable* queryable; - return GetArgumentHeap(args,0,queryable); - } - static TObject New_SubdirFilesystem(GCList& ls, std::vector args) - { - std::shared_ptr vfs; - - Tesses::Framework::Filesystem::VFSPath path; - - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path)) - { - return std::make_shared(vfs,path); - } + cb(gc, env); +#endif +} +static TObject TypeIsClass(GCList &ls, std::vector args) { + if (args.empty()) return nullptr; - } - static TObject New_MountableFilesystem(GCList& ls, std::vector args) - { - std::shared_ptr vfs; - - if(GetArgument(args,0,vfs)) - { - return std::make_shared(vfs); - } + if (args.empty()) return nullptr; - } - static TObject New_MemoryStream(GCList& ls, std::vector args) - { - bool writable; - if(GetArgument(args,0,writable)) - { - return std::make_shared(writable); - } + TClassObject *co; + return GetArgumentHeap(args, 0, co); +} + +static TObject TypeIsDefined(GCList &ls, std::vector args) { + if (args.empty()) return nullptr; - } - - - static TObject New_Filesystem(GCList& ls, std::vector args) - { - TDictionary* dict; - if(GetArgumentHeap(args,0,dict)) - { - return std::make_shared(ls.GetGC(),dict); - } + return (!std::holds_alternative(args[0]) && + !std::holds_alternative(args[0])); +} +static TObject TypeIsHeap(GCList &ls, std::vector args) { + if (args.empty()) return nullptr; - } - static TObject New_TempFS(GCList& ls, std::vector args) - { - std::shared_ptr vfs; - if(GetArgument(args,0,vfs)) - { - bool deleteOnDispose=true; - GetArgument(args,1,deleteOnDispose); - return std::make_shared(vfs,deleteOnDispose); - } - else { - bool deleteOnDispose; - if(GetArgument(args,0,deleteOnDispose)) - { - return std::make_shared(deleteOnDispose); - } - - } - return std::make_shared(); - } - static TObject New_Stream(GCList& ls, std::vector args) - { - TDictionary* dict; - if(GetArgumentHeap(args,0,dict)) - { - return std::make_shared(ls.GetGC(), dict); - } + return std::holds_alternative(args[0]); +} +static TObject TypeIsNumber(GCList &ls, std::vector args) { + if (args.empty()) return nullptr; - } - static TObject New_DateTime(GCList& ls, std::vector args) - { - int64_t year; - if(GetArgument(args,0,year)) - { - if(args.size()==1) - { - return std::make_shared(year); - - } - else - { - int64_t month=1; - int64_t day=1; - int64_t hour=0; - int64_t minute=0; - int64_t second=0; - bool isLocal=true; - GetArgument(args,1,month); - GetArgument(args,2,day); - GetArgument(args,3,hour); - GetArgument(args,4,minute); - GetArgument(args,5,second); - GetArgument(args,6,isLocal); - - - return std::make_shared((int)year,(int)month,(int)day,(int)hour,(int)minute,(int)second,isLocal); - } - } + return std::holds_alternative(args[0]) || + std::holds_alternative(args[0]); +} +static TObject TypeIsLong(GCList &ls, std::vector args) { + if (args.empty()) return nullptr; - } - static TObject New_TimeSpan(GCList& ls, std::vector args) - { - - int64_t arg1; - if(GetArgument(args,0,arg1)) - { - if(args.size()==1) - { - return std::make_shared(arg1); - } - else if(args.size() >= 3) - { - int64_t arg2; - int64_t arg3; - if(GetArgument(args,1,arg2) && GetArgument(args,2,arg3)) - { - int64_t arg4; - if(GetArgument(args,3,arg4)) - { - return std::make_shared((int)arg1,(int)arg2,(int)arg3,(int)arg4); - - } - else - { - return std::make_shared((int)arg1,(int)arg2,(int)arg3);; - - } - } - } - - } + return std::holds_alternative(args[0]); +} +static TObject TypeIsDouble(GCList &ls, std::vector args) { + if (args.empty()) return nullptr; + return std::holds_alternative(args[0]); +} +static TObject TypeIsString(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + return std::holds_alternative(args[0]); +} +static TObject TypeIsCallable(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + TCallable *call; + return GetArgumentHeap(args, 0, call); +} +static TObject TypeIsDictionary(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + TDictionary *dict; + TDynamicDictionary *dynDict; + return GetArgumentHeap(args, 0, dict) || GetArgumentHeap(args, 0, dynDict); +} +static TObject TypeIsList(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + TList *list; + TDynamicList *dynList; + return GetArgumentHeap(args, 0, list) || GetArgumentHeap(args, 0, dynList); +} +static TObject TypeIsStream(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr strm; + return GetArgument(args, 0, strm); +} +static TObject TypeIsTextReader(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr strm; + return GetArgument(args, 0, strm); +} +static TObject TypeIsTextWriter(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr strm; + return GetArgument(args, 0, strm); +} +static TObject TypeIsByteReader(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr strm; + return GetArgument(args, 0, strm); +} +static TObject TypeIsByteWriter(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr strm; + return GetArgument(args, 0, strm); +} +static TObject TypeIsUuid(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + return std::holds_alternative(args[0]); +} +static TObject TypeIsVFS(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr vfs; + return GetArgument(args, 0, vfs); +} + +static TObject TypeIsDateTime(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr dt; + return GetArgument(args, 0, dt); +} +static TObject TypeIsTimeSpan(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + std::shared_ptr dt; + return GetArgument(args, 0, dt); +} +static TObject TypeIsQueryable(GCList &ls, std::vector args) { + if (args.empty()) + return nullptr; + TQueryable *queryable; + return GetArgumentHeap(args, 0, queryable); +} +static TObject New_SubdirFilesystem(GCList &ls, std::vector args) { + std::shared_ptr vfs; + + Tesses::Framework::Filesystem::VFSPath path; + + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path)) { + return std::make_shared< + Tesses::Framework::Filesystem::SubdirFilesystem>(vfs, path); } - - std::string GetObjectTypeString(TObject _obj) - { - if(std::holds_alternative>(_obj)) return "Timer"; + return nullptr; +} +static TObject New_MountableFilesystem(GCList &ls, std::vector args) { + std::shared_ptr vfs; - if(std::holds_alternative>(_obj)) return "ServerSentEvents"; - if(std::holds_alternative(_obj)) return "Regex"; - if(std::holds_alternative(_obj)) return "Undefined"; - if(std::holds_alternative(_obj)) return "Null"; - if(std::holds_alternative(_obj)) return "Boolean"; - if(std::holds_alternative(_obj)) return "Long"; - if(std::holds_alternative(_obj)) return "Double"; - if(std::holds_alternative(_obj)) return "Char"; - if(std::holds_alternative(_obj)) return "MethodInvoker"; - if(std::holds_alternative(_obj)) return "String"; - - if(std::holds_alternative(_obj)) return "Path"; - if(std::holds_alternative(_obj)) return "Version"; - if(std::holds_alternative>(_obj)) return "DateTime"; - if(std::holds_alternative>(_obj)) return "TimeSpan"; - if(std::holds_alternative>(_obj)) return "ByteReader"; - - if(std::holds_alternative>(_obj)) return "ByteWriter"; - - if(std::holds_alternative(_obj)) return "Uuid"; - if(std::holds_alternative>(_obj)) - { - auto strm = std::get>(_obj); - if(strm != nullptr) - { - auto netStrm = std::dynamic_pointer_cast(strm); - if(netStrm != nullptr) - { - return "NetworkStream"; - } - - - - } - return "Stream"; - } - if(std::holds_alternative>(_obj)) - { - auto svr = std::get>(_obj); - if(svr != nullptr) - { - auto fileServer = std::dynamic_pointer_cast(svr); - auto mountableServer = std::dynamic_pointer_cast(svr); - auto routableServer = std::dynamic_pointer_cast(svr); - if(fileServer != nullptr) - { - return "FileServer"; - } - if(mountableServer != nullptr) - { - return "MountableServer"; - } - if(routableServer != nullptr) - { - return "RoutableServer"; - } - } - return "HttpServer"; - - } - if(std::holds_alternative>(_obj)) - { - auto textReader = std::get>(_obj); - if(textReader != nullptr) - { - auto stringReader = std::dynamic_pointer_cast(textReader); - auto streamReader = std::dynamic_pointer_cast(textReader); - auto consoleReader = std::dynamic_pointer_cast(textReader); - if(stringReader != nullptr) - { - return "StringReader"; - } - if(streamReader != nullptr) - { - return "StreamReader"; - } - if(consoleReader != nullptr) - { - return "ConsoleReader"; - } - } - - return "TextReader"; - - } - if(std::holds_alternative>(_obj)) - { - auto textWriter = std::get>(_obj); - if(textWriter != nullptr) - { - auto stringWriter = std::dynamic_pointer_cast(textWriter); - auto streamWriter = std::dynamic_pointer_cast(textWriter); - auto consoleWriter = std::dynamic_pointer_cast(textWriter); - if(stringWriter != nullptr) - { - return "StringWriter"; - } - if(streamWriter != nullptr) - { - return "StreamWriter"; - } - if(consoleWriter != nullptr) - { - return "ConsoleWriter"; - } - } - - return "TextReader"; - - } - if(std::holds_alternative>(_obj)) - { - auto vfs = std::get>(_obj); - if(vfs != nullptr) - { - auto rfs = std::dynamic_pointer_cast(vfs); - auto localVFS = std::dynamic_pointer_cast(vfs); - auto mountableVFS = std::dynamic_pointer_cast(vfs); - auto subFS = std::dynamic_pointer_cast(vfs); - auto tempFS = std::dynamic_pointer_cast(vfs); - if(rfs) return "RelativeFilesystem"; - if(localVFS != nullptr) return "LocalFilesystem"; - if(subFS != nullptr) return "SubdirFilesystem"; - if(mountableVFS != nullptr) return "MountableFilesystem"; - if(tempFS != nullptr) return "TempFS"; - - - } - return "VFS"; - } - if(std::holds_alternative(_obj)) - { - auto obj = std::get(_obj).obj; - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - - auto list = dynamic_cast(obj); - auto dynList = dynamic_cast(obj); - auto argWrapper = dynamic_cast(obj); - auto closure = dynamic_cast(obj); - auto externalMethod = dynamic_cast(obj); - auto byteArray = dynamic_cast(obj); - auto native = dynamic_cast(obj); - auto any = dynamic_cast(obj); - - auto cse = dynamic_cast(obj); - auto rootEnv = dynamic_cast(obj); - auto subEnv = dynamic_cast(obj); - auto env = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cobj = dynamic_cast(obj); - auto aarray = dynamic_cast(obj); - auto file = dynamic_cast(obj); - auto queryable = dynamic_cast(obj); - - if(rootEnv != nullptr) return "RootEnvironment"; - if(subEnv != nullptr) return "SubEnvironment"; - if(env != nullptr) return "Environment"; - if(cobj != nullptr) return cobj->TypeName(); - - if(cse != nullptr) return "YieldedClosure"; - if(dynDict != nullptr) return "DynamicDictionary"; - if(dynList != nullptr) return "DynamicList"; - if(aarray != nullptr) return "AssociativeArray"; - if(natObj != nullptr) return natObj->TypeName(); - - if(dict != nullptr) return "Dictionary"; - if(list != nullptr) return "List"; - if(argWrapper != nullptr) return "ArgWrapper"; - if(closure != nullptr) return "Closure"; - if(externalMethod != nullptr) return "ExternalMethod"; - if(byteArray != nullptr) return "ByteArray"; - if(native != nullptr) return "Native"; - if(any != nullptr) return "Any"; - if(file != nullptr) return "File"; - if(queryable != nullptr) return "Queryable"; - - return "HeapObject"; - } - - return "Object"; + if (GetArgument(args, 0, vfs)) { + return std::make_shared< + Tesses::Framework::Filesystem::MountableFilesystem>(vfs); } - - static TObject TypeOf(GCList& ls, std::vector args) - { - if(args.size() < 1) return "Undefined"; - return GetObjectTypeString(args[0]); + return nullptr; +} +static TObject New_MemoryStream(GCList &ls, std::vector args) { + bool writable; + if (GetArgument(args, 0, writable)) { + return std::make_shared( + writable); } - - TObject ByteArray(GCList& ls, std::vector args) - { - auto res= TByteArray::Create(ls); - if(args.size() == 1){ - - if(std::holds_alternative(args[0])) + return nullptr; +} + +static TObject New_Filesystem(GCList &ls, std::vector args) { + TDictionary *dict; + if (GetArgumentHeap(args, 0, dict)) { + return std::make_shared(ls.GetGC(), dict); + } + return nullptr; +} +static TObject New_TempFS(GCList &ls, std::vector args) { + std::shared_ptr vfs; + if (GetArgument(args, 0, vfs)) { + bool deleteOnDispose = true; + GetArgument(args, 1, deleteOnDispose); + return std::make_shared( + vfs, deleteOnDispose); + } else { + bool deleteOnDispose; + if (GetArgument(args, 0, deleteOnDispose)) { + return std::make_shared( + deleteOnDispose); + } + } + return std::make_shared(); +} +static TObject New_Stream(GCList &ls, std::vector args) { + TDictionary *dict; + if (GetArgumentHeap(args, 0, dict)) { + return std::make_shared(ls.GetGC(), dict); + } + return nullptr; +} +static TObject New_DateTime(GCList &ls, std::vector args) { + int64_t year; + if (GetArgument(args, 0, year)) { + if (args.size() == 1) { + return std::make_shared(year); + + } else { + int64_t month = 1; + int64_t day = 1; + int64_t hour = 0; + int64_t minute = 0; + int64_t second = 0; + bool isLocal = true; + GetArgument(args, 1, month); + GetArgument(args, 2, day); + GetArgument(args, 3, hour); + GetArgument(args, 4, minute); + GetArgument(args, 5, second); + GetArgument(args, 6, isLocal); + + return std::make_shared( + (int)year, (int)month, (int)day, (int)hour, (int)minute, + (int)second, isLocal); + } + } + return nullptr; +} +static TObject New_TimeSpan(GCList &ls, std::vector args) { + + int64_t arg1; + if (GetArgument(args, 0, arg1)) { + if (args.size() == 1) { + return std::make_shared(arg1); + } else if (args.size() >= 3) { + int64_t arg2; + int64_t arg3; + if (GetArgument(args, 1, arg2) && GetArgument(args, 2, arg3)) { + int64_t arg4; + if (GetArgument(args, 3, arg4)) { + return std::make_shared( + (int)arg1, (int)arg2, (int)arg3, (int)arg4); + + } else { + return std::make_shared( + (int)arg1, (int)arg2, (int)arg3); + ; + } + } + } + } + return nullptr; +} + +std::string GetObjectTypeString(TObject _obj) { + if (std::holds_alternative< + std::shared_ptr>(_obj)) + return "Timer"; + + if (std::holds_alternative< + std::shared_ptr>(_obj)) + return "ServerSentEvents"; + if (std::holds_alternative(_obj)) + return "Regex"; + if (std::holds_alternative(_obj)) + return "Undefined"; + if (std::holds_alternative(_obj)) + return "Null"; + if (std::holds_alternative(_obj)) + return "Boolean"; + if (std::holds_alternative(_obj)) + return "Long"; + if (std::holds_alternative(_obj)) + return "Double"; + if (std::holds_alternative(_obj)) + return "Char"; + if (std::holds_alternative(_obj)) + return "MethodInvoker"; + if (std::holds_alternative(_obj)) + return "String"; + + if (std::holds_alternative(_obj)) + return "Path"; + if (std::holds_alternative(_obj)) + return "Version"; + if (std::holds_alternative< + std::shared_ptr>(_obj)) + return "DateTime"; + if (std::holds_alternative< + std::shared_ptr>(_obj)) + return "TimeSpan"; + if (std::holds_alternative< + std::shared_ptr>(_obj)) + return "ByteReader"; + + if (std::holds_alternative< + std::shared_ptr>(_obj)) + return "ByteWriter"; + + if (std::holds_alternative(_obj)) + return "Uuid"; + if (std::holds_alternative< + std::shared_ptr>(_obj)) { + auto strm = + std::get>(_obj); + if (strm != nullptr) { + auto netStrm = std::dynamic_pointer_cast< + Tesses::Framework::Streams::NetworkStream>(strm); + if (netStrm != nullptr) { + return "NetworkStream"; + } + } + return "Stream"; + } + if (std::holds_alternative< + std::shared_ptr>(_obj)) { + auto svr = + std::get>( + _obj); + if (svr != nullptr) { + auto fileServer = + std::dynamic_pointer_cast( + svr); + auto mountableServer = std::dynamic_pointer_cast< + Tesses::Framework::Http::MountableServer>(svr); + auto routableServer = + std::dynamic_pointer_cast( + svr); + if (fileServer != nullptr) { + return "FileServer"; + } + if (mountableServer != nullptr) { + return "MountableServer"; + } + if (routableServer != nullptr) { + return "RoutableServer"; + } + } + return "HttpServer"; + } + if (std::holds_alternative< + std::shared_ptr>( + _obj)) { + auto textReader = std::get< + std::shared_ptr>(_obj); + if (textReader != nullptr) { + auto stringReader = std::dynamic_pointer_cast< + Tesses::Framework::TextStreams::StringReader>(textReader); + auto streamReader = std::dynamic_pointer_cast< + Tesses::Framework::TextStreams::StreamReader>(textReader); + auto consoleReader = std::dynamic_pointer_cast< + Tesses::Framework::TextStreams::ConsoleReader>(textReader); + if (stringReader != nullptr) { + return "StringReader"; + } + if (streamReader != nullptr) { + return "StreamReader"; + } + if (consoleReader != nullptr) { + return "ConsoleReader"; + } + } + + return "TextReader"; + } + if (std::holds_alternative< + std::shared_ptr>( + _obj)) { + auto textWriter = std::get< + std::shared_ptr>(_obj); + if (textWriter != nullptr) { + auto stringWriter = std::dynamic_pointer_cast< + Tesses::Framework::TextStreams::StringWriter>(textWriter); + auto streamWriter = std::dynamic_pointer_cast< + Tesses::Framework::TextStreams::StreamWriter>(textWriter); + auto consoleWriter = std::dynamic_pointer_cast< + Tesses::Framework::TextStreams::ConsoleReader>(textWriter); + if (stringWriter != nullptr) { + return "StringWriter"; + } + if (streamWriter != nullptr) { + return "StreamWriter"; + } + if (consoleWriter != nullptr) { + return "ConsoleWriter"; + } + } + + return "TextReader"; + } + if (std::holds_alternative< + std::shared_ptr>(_obj)) { + auto vfs = + std::get>(_obj); + if (vfs != nullptr) { + auto rfs = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::RelativeFilesystem>(vfs); + auto localVFS = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::LocalFilesystem>(vfs); + auto mountableVFS = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::MountableFilesystem>(vfs); + auto subFS = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::SubdirFilesystem>(vfs); + auto tempFS = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::TempFS>(vfs); + if (rfs) + return "RelativeFilesystem"; + if (localVFS != nullptr) + return "LocalFilesystem"; + if (subFS != nullptr) + return "SubdirFilesystem"; + if (mountableVFS != nullptr) + return "MountableFilesystem"; + if (tempFS != nullptr) + return "TempFS"; + } + return "VFS"; + } + if (std::holds_alternative(_obj)) { + auto obj = std::get(_obj).obj; + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + + auto list = dynamic_cast(obj); + auto dynList = dynamic_cast(obj); + auto argWrapper = dynamic_cast(obj); + auto closure = dynamic_cast(obj); + auto externalMethod = dynamic_cast(obj); + auto byteArray = dynamic_cast(obj); + auto native = dynamic_cast(obj); + auto any = dynamic_cast(obj); + + auto cse = dynamic_cast(obj); + auto rootEnv = dynamic_cast(obj); + auto subEnv = dynamic_cast(obj); + auto env = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cobj = dynamic_cast(obj); + auto aarray = dynamic_cast(obj); + auto file = dynamic_cast(obj); + auto queryable = dynamic_cast(obj); + + if (rootEnv != nullptr) + return "RootEnvironment"; + if (subEnv != nullptr) + return "SubEnvironment"; + if (env != nullptr) + return "Environment"; + if (cobj != nullptr) + return cobj->TypeName(); + + if (cse != nullptr) + return "YieldedClosure"; + if (dynDict != nullptr) + return "DynamicDictionary"; + if (dynList != nullptr) + return "DynamicList"; + if (aarray != nullptr) + return "AssociativeArray"; + if (natObj != nullptr) + return natObj->TypeName(); + + if (dict != nullptr) + return "Dictionary"; + if (list != nullptr) + return "List"; + if (argWrapper != nullptr) + return "ArgWrapper"; + if (closure != nullptr) + return "Closure"; + if (externalMethod != nullptr) + return "ExternalMethod"; + if (byteArray != nullptr) + return "ByteArray"; + if (native != nullptr) + return "Native"; + if (any != nullptr) + return "Any"; + if (file != nullptr) + return "File"; + if (queryable != nullptr) + return "Queryable"; + + return "HeapObject"; + } + + return "Object"; +} + +static TObject TypeOf(GCList &ls, std::vector args) { + if (args.size() < 1) + return "Undefined"; + return GetObjectTypeString(args[0]); +} + +TObject ByteArray(GCList &ls, std::vector args) { + auto res = TByteArray::Create(ls); + if (args.size() == 1) { + + if (std::holds_alternative(args[0])) res->data.resize((size_t)std::get(args[0])); - else if(std::holds_alternative(args[0])) - { - std::string& txt = std::get(args[0]); - res->data.insert(res->data.end(), txt.begin(),txt.end()); - } - + else if (std::holds_alternative(args[0])) { + std::string &txt = std::get(args[0]); + res->data.insert(res->data.end(), txt.begin(), txt.end()); } - return res; - } - TObject ParseLong(GCList& ls, std::vector args) - { - - if(args.size() >= 1) - { - int base = 10; - - if(args.size() == 2 && std::holds_alternative(args[1])) - { - base = (int)std::get(args[1]); - } + return res; +} +TObject ParseLong(GCList &ls, std::vector args) { - size_t pos; + if (args.size() >= 1) { + int base = 10; + if (args.size() == 2 && std::holds_alternative(args[1])) { + base = (int)std::get(args[1]); + } - std::string str = ToString(ls.GetGC(),args[0]); - - try { - int64_t v = std::stoll(str,&pos,base); - if(pos < str.size()) return nullptr; - return v; - }catch(std::exception& ex) - { + size_t pos; + + std::string str = ToString(ls.GetGC(), args[0]); + + try { + int64_t v = std::stoll(str, &pos, base); + if (pos < str.size()) return nullptr; - } - + return v; + } catch (std::exception &ex) { + return nullptr; } - return nullptr; - } - TObject ParseDouble(GCList& ls, std::vector args) - { - - if(args.size() == 1) - { - + return nullptr; +} +TObject ParseDouble(GCList &ls, std::vector args) { - size_t pos; + if (args.size() == 1) { + size_t pos; - std::string str = ToString(ls.GetGC(),args[0]); - - try { - double v = std::stod(str,&pos); - if(pos < str.size()) return nullptr; - return v; - }catch(std::exception& ex) - { + std::string str = ToString(ls.GetGC(), args[0]); + + try { + double v = std::stod(str, &pos); + if (pos < str.size()) return nullptr; - } - + return v; + } catch (std::exception &ex) { + return nullptr; } - return nullptr; - } + return nullptr; +} - +EnvironmentPermissions::EnvironmentPermissions() { + this->canRegisterConsole = false; + this->canRegisterCrypto = false; + this->canRegisterDictionary = false; + this->canRegisterEnv = false; + this->canRegisterIO = false; + this->canRegisterJSON = false; + this->canRegisterNet = false; + this->canRegisterOGC = false; + this->canRegisterPath = false; + this->canRegisterProcess = false; + this->canRegisterRoot = false; + this->canRegisterSqlite = false; + this->canRegisterVM = false; + this->locked = false; + this->sqlite3Scoped = false; +} - EnvironmentPermissions::EnvironmentPermissions() - { - this->canRegisterConsole=false; - this->canRegisterCrypto=false; - this->canRegisterDictionary=false; - this->canRegisterEnv=false; - this->canRegisterIO=false; - this->canRegisterJSON=false; - this->canRegisterNet=false; - this->canRegisterOGC=false; - this->canRegisterPath=false; - this->canRegisterProcess=false; - this->canRegisterRoot=false; - this->canRegisterSqlite=false; - this->canRegisterVM = false; - this->locked=false; - this->sqlite3Scoped=false; - - } +static TObject YieldEnumerableFunc(GCList &ls, std::vector args) { + TClosure *closure; + if (GetArgumentHeap(args, 0, closure)) { + TDictionary *enumerableItem = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); - static TObject YieldEnumerableFunc(GCList& ls, std::vector args) - { - TClosure* closure; - if(GetArgumentHeap(args,0,closure)) - { - TDictionary* enumerableItem = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - - auto fn = TExternalMethod::Create(ls,"Get Enumerator for yield",{},[closure](GCList& ls2, std::vector args)->TObject { - return TYieldEnumerator::Create(ls2,closure); + auto fn = TExternalMethod::Create( + ls, "Get Enumerator for yield", {}, + [closure](GCList &ls2, std::vector args) -> TObject { + return TYieldEnumerator::Create(ls2, closure); }); - fn->watch.push_back(closure); - - enumerableItem->SetValue("GetEnumerator", fn); - - ls.GetGC()->BarrierEnd(); + fn->watch.push_back(closure); - return enumerableItem; - - } + enumerableItem->SetValue("GetEnumerator", fn); - return Undefined(); + ls.GetGC()->BarrierEnd(); + + return enumerableItem; } - - static TObject DateTime_Sleep(GCList& ls, std::vector args) - { - int64_t msec; - if(GetArgument(args,0,msec)) - { - #if defined(_WIN32) - Sleep((int)msec); - #else - usleep(1000*msec); - #endif - } - return nullptr; - } - static TObject DateTime_getNow(GCList& ls, std::vector args) - { - - return std::make_shared(Tesses::Framework::Date::DateTime::Now()); - } - static TObject DateTime_getNowUTC(GCList& ls, std::vector args) - { - return std::make_shared(Tesses::Framework::Date::DateTime::NowUTC()); - } - static TObject DateTime_getNowEpoch(GCList& ls, std::vector args) - { - - return (int64_t)time(NULL); - } - static TObject DateTime_TryParseHttpDate(GCList& ls, std::vector args) - { - std::string d; - Tesses::Framework::Date::DateTime dt; - if(GetArgument(args,0,d) && Tesses::Framework::Date::DateTime::TryParseHttpDate(d,dt)) - { - return std::make_shared(dt); - } - return nullptr; - } - static TObject New_Promise(GCList& ls, std::vector args) - { - TCallable* call; + return Undefined(); +} - if(GetArgumentHeap(args,0,call)) - { - - TTask* task = TTask::Create(ls); +static TObject DateTime_Sleep(GCList &ls, std::vector args) { + int64_t msec; + if (GetArgument(args, 0, msec)) { +#if defined(_WIN32) + Sleep((int)msec); +#else + usleep(1000 * msec); +#endif + } + return nullptr; +} +static TObject DateTime_getNow(GCList &ls, std::vector args) { - TExternalMethod* resolve = TExternalMethod::Create(ls, "fulfill the promise",{"arg"},[task](GCList& ls,std::vector args)->TObject { - if(!args.empty()) - { + return std::make_shared( + Tesses::Framework::Date::DateTime::Now()); +} +static TObject DateTime_getNowUTC(GCList &ls, std::vector args) { + return std::make_shared( + Tesses::Framework::Date::DateTime::NowUTC()); +} +static TObject DateTime_getNowEpoch(GCList &ls, std::vector args) { + + return (int64_t)time(NULL); +} +static TObject DateTime_TryParseHttpDate(GCList &ls, + std::vector args) { + std::string d; + Tesses::Framework::Date::DateTime dt; + if (GetArgument(args, 0, d) && + Tesses::Framework::Date::DateTime::TryParseHttpDate(d, dt)) { + return std::make_shared(dt); + } + return nullptr; +} +static TObject New_Promise(GCList &ls, std::vector args) { + TCallable *call; + + if (GetArgumentHeap(args, 0, call)) { + + TTask *task = TTask::Create(ls); + + TExternalMethod *resolve = TExternalMethod::Create( + ls, "fulfill the promise", {"arg"}, + [task](GCList &ls, std::vector args) -> TObject { + if (!args.empty()) { task->SetSucceeded(args[0]); } return Undefined(); }); - resolve->watch.push_back(task); - TExternalMethod* reject = TExternalMethod::Create(ls, "reject the promise",{"arg"},[task](GCList& ls,std::vector args)->TObject { - if(!args.empty()) - { + resolve->watch.push_back(task); + TExternalMethod *reject = TExternalMethod::Create( + ls, "reject the promise", {"arg"}, + [task](GCList &ls, std::vector args) -> TObject { + if (!args.empty()) { auto item = args[0]; - if(!std::holds_alternative(item)) - { + if (!std::holds_alternative(item)) { try { - VMByteCodeException ex(ls.GetGC(),item,nullptr); + VMByteCodeException ex(ls.GetGC(), item, nullptr); throw ex; - } - catch(...) - { + } catch (...) { task->SetFailed(std::current_exception()); } } } return Undefined(); }); - reject->watch.push_back(task); + reject->watch.push_back(task); - call->Call(ls,{resolve,reject}); + call->Call(ls, {resolve, reject}); - return task; - } - return nullptr; + return task; } - static TObject TimeSpan_Parse(GCList& ls, std::vector args) - { - std::string t; - Tesses::Framework::Date::TimeSpan ts; - if(GetArgument(args,0,t) && Tesses::Framework::Date::TimeSpan::TryParse(t,ts)) - { - return std::make_shared(ts); - } - return nullptr; + return nullptr; +} +static TObject TimeSpan_Parse(GCList &ls, std::vector args) { + std::string t; + Tesses::Framework::Date::TimeSpan ts; + if (GetArgument(args, 0, t) && + Tesses::Framework::Date::TimeSpan::TryParse(t, ts)) { + return std::make_shared(ts); } - static TObject TimeSpan_FromSeconds(GCList& ls, std::vector args) - { - int64_t n; + return nullptr; +} +static TObject TimeSpan_FromSeconds(GCList &ls, std::vector args) { + int64_t n; - if(GetArgument(args,0,n)) - { - return std::make_shared(n); - } - return nullptr; + if (GetArgument(args, 0, n)) { + return std::make_shared(n); } - static TObject TimeSpan_FromMinutes(GCList& ls, std::vector args) - { - int64_t n; + return nullptr; +} +static TObject TimeSpan_FromMinutes(GCList &ls, std::vector args) { + int64_t n; - if(GetArgument(args,0,n)) - { - return std::make_shared(n*60); - } - return nullptr; + if (GetArgument(args, 0, n)) { + return std::make_shared(n * 60); } - static TObject TimeSpan_FromHours(GCList& ls, std::vector args) - { - int64_t n; + return nullptr; +} +static TObject TimeSpan_FromHours(GCList &ls, std::vector args) { + int64_t n; - if(GetArgument(args,0,n)) - { - return std::make_shared(n*3600); - } - return nullptr; + if (GetArgument(args, 0, n)) { + return std::make_shared(n * 3600); } - static TObject TimeSpan_FromDays(GCList& ls, std::vector args) - { - int64_t n; + return nullptr; +} +static TObject TimeSpan_FromDays(GCList &ls, std::vector args) { + int64_t n; - if(GetArgument(args,0,n)) - { - return std::make_shared(n*86400); - } - return nullptr; + if (GetArgument(args, 0, n)) { + return std::make_shared(n * 86400); } - static TObject New_StreamReader(GCList& ls, std::vector args) - { - std::shared_ptr strm; - std::shared_ptr vfs; - Tesses::Framework::Filesystem::VFSPath path; + return nullptr; +} +static TObject New_StreamReader(GCList &ls, std::vector args) { + std::shared_ptr strm; + std::shared_ptr vfs; + Tesses::Framework::Filesystem::VFSPath path; - if(GetArgument(args,0,strm)) - { - return std::make_shared(strm); - } - else if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path)) - { - strm = vfs->OpenFile(path,"rb"); - return std::make_shared(strm); - } - return nullptr; + if (GetArgument(args, 0, strm)) { + return std::make_shared( + strm); + } else if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path)) { + strm = vfs->OpenFile(path, "rb"); + return std::make_shared( + strm); + } + return nullptr; +} + +static TObject New_StreamWriter(GCList &ls, std::vector args) { + + std::shared_ptr strm; + std::shared_ptr vfs; + Tesses::Framework::Filesystem::VFSPath path; + + if (GetArgument(args, 0, strm)) { + return std::make_shared( + strm); + } else if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path)) { + bool append = false; + GetArgument(args, 2, append); + + strm = vfs->OpenFile(path, append ? "ab" : "wb"); + return std::make_shared( + strm); + } + return nullptr; +} +static TObject New_StringReader(GCList &ls, std::vector args) { + std::string str; + if (GetArgument(args, 0, str)) { + return std::make_shared( + str); + } + return nullptr; +} +static TObject New_StringWriter(GCList &ls, std::vector args) { + std::string str; + if (GetArgument(args, 0, str)) { + return std::make_shared( + str); } - static TObject New_StreamWriter(GCList& ls, std::vector args) - { - - std::shared_ptr strm; - std::shared_ptr vfs; - Tesses::Framework::Filesystem::VFSPath path; + return std::make_shared(); +} +static TObject Task_FromResult(GCList &ls, std::vector args) { + if (!args.empty()) { + return TTask::FromResult(ls, args[0]); + } + return nullptr; +} +static TObject New_ByteReader(GCList &ls, std::vector args) { + std::shared_ptr strm; + if (GetArgument(args, 0, strm)) + return std::make_shared(strm); + return nullptr; +} +static TObject New_ByteWriter(GCList &ls, std::vector args) { + std::shared_ptr strm; + if (GetArgument(args, 0, strm)) + return std::make_shared(strm); + return nullptr; +} +static void empty() {} +static TObject New_Timer(GCList &ls, std::vector args) { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) { + int64_t interval = 1000; + bool enabled = true; + GetArgument(args, 1, interval); + GetArgument(args, 2, enabled); - if(GetArgument(args,0,strm)) - { - return std::make_shared(strm); - } - else if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path)) - { - bool append=false; - GetArgument(args,2,append); + auto obj = CreateMarkedTObject(ls.GetGC(), callable); - strm = vfs->OpenFile(path,append ? "ab" : "wb"); - return std::make_shared(strm); - } - return nullptr; - } - static TObject New_StringReader(GCList& ls, std::vector args) - { - std::string str; - if(GetArgument(args,0,str)) - { - return std::make_shared(str); - } - return nullptr; - } - static TObject New_StringWriter(GCList& ls, std::vector args) - { - std::string str; - if(GetArgument(args,0,str)) - { - return std::make_shared(str); - } - - return std::make_shared(); - } - static TObject Task_FromResult(GCList& ls, std::vector args) - { - if(!args.empty()) - { - return TTask::FromResult(ls,args[0]); - } - return nullptr; - } - static TObject New_ByteReader(GCList& ls, std::vector args) - { - std::shared_ptr strm; - if(GetArgument(args, 0, strm)) - return std::make_shared(strm); - return nullptr; - } - static TObject New_ByteWriter(GCList& ls, std::vector args) - { - std::shared_ptr strm; - if(GetArgument(args, 0, strm)) - return std::make_shared(strm); - return nullptr; - } - static void empty(){} - static TObject New_Timer(GCList& ls, std::vector args) - { - TCallable* callable; - if(GetArgumentHeap(args, 0, callable)) - { - int64_t interval = 1000; - bool enabled=true; - GetArgument(args,1, interval); - GetArgument(args,2,enabled); - - auto obj = CreateMarkedTObject(ls.GetGC(), callable); - - return Tesses::Framework::TF_Timer([obj]()->void { - TCallable* callable; - if(GetObjectHeap(obj->GetObject(), callable)) - { + return Tesses::Framework::TF_Timer( + [obj]() -> void { + TCallable *callable; + if (GetObjectHeap(obj->GetObject(), callable)) { GCList ls(obj->GetGC()); - callable->Call(ls,{}); + callable->Call(ls, {}); } - }, interval , enabled); - } - - - return Tesses::Framework::TF_Timer(empty, 1000L, false); + }, + interval, enabled); } - static TObject New_RelativeFilesystem(GCList& ls, std::vector args) - { - std::shared_ptr vfs; - Tesses::Framework::Filesystem::VFSPath path; - if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path) && !path.relative) - { - return std::make_shared(vfs,path); - } - return nullptr; + return Tesses::Framework::TF_Timer(empty, 1000L, false); +} + +static TObject New_RelativeFilesystem(GCList &ls, std::vector args) { + std::shared_ptr vfs; + Tesses::Framework::Filesystem::VFSPath path; + if (GetArgument(args, 0, vfs) && GetArgumentAsPath(args, 1, path) && + !path.relative) { + return std::make_shared< + Tesses::Framework::Filesystem::RelativeFilesystem>(vfs, path); } + return nullptr; +} - static TObject New_Queryable(GCList& ls, std::vector args) - { - if(!args.empty()) - { - return TQueryable::Create(ls, args.front()); - } - return nullptr; +static TObject New_Queryable(GCList &ls, std::vector args) { + if (!args.empty()) { + return TQueryable::Create(ls, args.front()); } - + return nullptr; +} - void TStd::RegisterRoot(std::shared_ptr gc, TRootEnvironment* env) - { - GCList ls(gc); - - gc->BarrierBegin(); - - env->permissions.canRegisterRoot=true; - RegisterHelpers(gc,env); - RegisterUuid(gc, env); - - - auto date =env->EnsureDictionary(gc,"DateTime"); - date->DeclareFunction(gc, "Sleep","Sleep for a specified amount of milliseconds (multiply seconds by 1000 to get milliseconds)", {"ms"},DateTime_Sleep); - date->DeclareFunction(gc, "getNow", "Get the current time",{},DateTime_getNow); - date->DeclareFunction(gc, "getNowUTC","Get the current time in UTC",{},DateTime_getNowUTC); - date->DeclareFunction(gc, "getNowEpoch","Get the time_t time now",{},DateTime_getNowEpoch); - date->DeclareFunction(gc, "TryParseHttpDate","Parse the http date",{},DateTime_TryParseHttpDate); - - - date->SetValue("Zone", (int64_t)Tesses::Framework::Date::GetTimeZone()); - date->SetValue("SupportsDaylightSavings",Tesses::Framework::Date::TimeZoneSupportDST()); +void TStd::RegisterRoot(std::shared_ptr gc, TRootEnvironment *env) { + GCList ls(gc); + gc->BarrierBegin(); - auto ts = env->EnsureDictionary(gc, "TimeSpan"); - ts->DeclareFunction(gc, "Parse", "Parse timespan",{"tsStr"}, TimeSpan_Parse); - ts->DeclareFunction(gc,"FromSeconds","Create timespan from seconds", {"seconds"}, TimeSpan_FromSeconds); - ts->DeclareFunction(gc,"FromMinutes","Create timespan from minutes", {"minutes"}, TimeSpan_FromMinutes); - ts->DeclareFunction(gc,"FromHours","Create timespan from hours", {"hours"}, TimeSpan_FromHours); - ts->DeclareFunction(gc,"FromDays","Create timespan from days", {"days"}, TimeSpan_FromDays); + env->permissions.canRegisterRoot = true; + RegisterHelpers(gc, env); + RegisterUuid(gc, env); - - auto task = env->EnsureDictionary(gc,"Task"); + auto date = env->EnsureDictionary(gc, "DateTime"); + date->DeclareFunction(gc, "Sleep", + "Sleep for a specified amount of milliseconds " + "(multiply seconds by 1000 to get milliseconds)", + {"ms"}, DateTime_Sleep); + date->DeclareFunction(gc, "getNow", "Get the current time", {}, + DateTime_getNow); + date->DeclareFunction(gc, "getNowUTC", "Get the current time in UTC", {}, + DateTime_getNowUTC); + date->DeclareFunction(gc, "getNowEpoch", "Get the time_t time now", {}, + DateTime_getNowEpoch); + date->DeclareFunction(gc, "TryParseHttpDate", "Parse the http date", {}, + DateTime_TryParseHttpDate); - task->DeclareFunction(gc,"AsyncClosure","Create async closure (internal for compiler to generate calls to)",{"closure"},[](GCList& ls, std::vector args)->TObject { - TClosure* closure; - if(GetArgumentHeap(args,0,closure)) - return TTask::FromClosure(ls,closure); + date->SetValue("Zone", (int64_t)Tesses::Framework::Date::GetTimeZone()); + date->SetValue("SupportsDaylightSavings", + Tesses::Framework::Date::TimeZoneSupportDST()); + + auto ts = env->EnsureDictionary(gc, "TimeSpan"); + ts->DeclareFunction(gc, "Parse", "Parse timespan", {"tsStr"}, + TimeSpan_Parse); + ts->DeclareFunction(gc, "FromSeconds", "Create timespan from seconds", + {"seconds"}, TimeSpan_FromSeconds); + ts->DeclareFunction(gc, "FromMinutes", "Create timespan from minutes", + {"minutes"}, TimeSpan_FromMinutes); + ts->DeclareFunction(gc, "FromHours", "Create timespan from hours", + {"hours"}, TimeSpan_FromHours); + ts->DeclareFunction(gc, "FromDays", "Create timespan from days", {"days"}, + TimeSpan_FromDays); + + auto task = env->EnsureDictionary(gc, "Task"); + + task->DeclareFunction( + gc, "AsyncClosure", + "Create async closure (internal for compiler to generate calls to)", + {"closure"}, [](GCList &ls, std::vector args) -> TObject { + TClosure *closure; + if (GetArgumentHeap(args, 0, closure)) + return TTask::FromClosure(ls, closure); return nullptr; }); - task->DeclareFunction(gc,"Run","Run code async",{"callable"},[](GCList& ls, std::vector args)->TObject { - TCallable* closure; - if(GetArgumentHeap(args,0,closure)) - return TTask::Run(ls,closure); - return nullptr; - }); - task->DeclareFunction(gc, "FromResult", "async from result", {"result"}, Task_FromResult); + task->DeclareFunction(gc, "Run", "Run code async", {"callable"}, + [](GCList &ls, std::vector args) -> TObject { + TCallable *closure; + if (GetArgumentHeap(args, 0, closure)) + return TTask::Run(ls, closure); + return nullptr; + }); + task->DeclareFunction(gc, "FromResult", "async from result", {"result"}, + Task_FromResult); - TDictionary* newTypes = env->EnsureDictionary(gc, "New"); + TDictionary *newTypes = env->EnsureDictionary(gc, "New"); - newTypes->DeclareFunction(gc, "ByteReader","Read binary data from stream",{"stream"},New_ByteReader); + newTypes->DeclareFunction(gc, "ByteReader", "Read binary data from stream", + {"stream"}, New_ByteReader); - newTypes->DeclareFunction(gc, "ByteWriter","Write binary data to stream",{"stream"},New_ByteWriter); - //newTypes->DeclareFunction(gc,) - newTypes->DeclareFunction(gc, "Promise", "Create an async object",{"resolve","reject"},New_Promise); - newTypes->DeclareFunction(gc, "DateTime","Create a DateTime object, if only one arg is provided year is epoch, isLocal defaults to true unless epoch",{"year","$month","$day","$hour","$minute","$second","$isLocal"},New_DateTime); - newTypes->DeclareFunction(gc, "TimeSpan","Create a DateTime object, if only one arg is provided days is totalSeconds, if there are only three arguments days will be hours, hours will be minutes, minutes will be seconds (according to the argument documentation)",{"days","$hours","$minutes","$seconds"},New_TimeSpan); + newTypes->DeclareFunction(gc, "ByteWriter", "Write binary data to stream", + {"stream"}, New_ByteWriter); + // newTypes->DeclareFunction(gc,) + newTypes->DeclareFunction(gc, "Promise", "Create an async object", + {"resolve", "reject"}, New_Promise); + newTypes->DeclareFunction( + gc, "DateTime", + "Create a DateTime object, if only one arg is provided year is epoch, " + "isLocal defaults to true unless epoch", + {"year", "$month", "$day", "$hour", "$minute", "$second", "$isLocal"}, + New_DateTime); + newTypes->DeclareFunction( + gc, "TimeSpan", + "Create a DateTime object, if only one arg is provided days is " + "totalSeconds, if there are only three arguments days will be hours, " + "hours will be minutes, minutes will be seconds (according to the " + "argument documentation)", + {"days", "$hours", "$minutes", "$seconds"}, New_TimeSpan); - newTypes->DeclareFunction(gc, "MountableFilesystem","Create a mountable filesystem",{"root"}, New_MountableFilesystem); - newTypes->DeclareFunction(gc, "SubdirFilesystem","Create a subdir filesystem",{"fs","subdir"}, New_SubdirFilesystem); - newTypes->DeclareFunction(gc, "MemoryStream","Create a memory stream",{"writable"}, New_MemoryStream); - newTypes->DeclareFunction(gc, "Filesystem","Create filesystem", {"fs"},New_Filesystem); - newTypes->DeclareFunction(gc, "RelativeFilesystem", "Create relativefs",{"parent", "absoluteDir"}, New_RelativeFilesystem); - newTypes->DeclareFunction(gc, "TempFS","Create a temp directory",{"",""}, New_TempFS); - newTypes->DeclareFunction(gc, "Timer", "Create a timer",{"$cb","$interval","$enabled"}, New_Timer); - newTypes->DeclareFunction(gc, "Stream","Create stream", {"strm"},New_Stream); + newTypes->DeclareFunction(gc, "MountableFilesystem", + "Create a mountable filesystem", {"root"}, + New_MountableFilesystem); + newTypes->DeclareFunction(gc, "SubdirFilesystem", + "Create a subdir filesystem", {"fs", "subdir"}, + New_SubdirFilesystem); + newTypes->DeclareFunction(gc, "MemoryStream", "Create a memory stream", + {"writable"}, New_MemoryStream); + newTypes->DeclareFunction(gc, "Filesystem", "Create filesystem", {"fs"}, + New_Filesystem); + newTypes->DeclareFunction(gc, "RelativeFilesystem", "Create relativefs", + {"parent", "absoluteDir"}, + New_RelativeFilesystem); + newTypes->DeclareFunction(gc, "TempFS", "Create a temp directory", {"", ""}, + New_TempFS); + newTypes->DeclareFunction(gc, "Timer", "Create a timer", + {"$cb", "$interval", "$enabled"}, New_Timer); + newTypes->DeclareFunction(gc, "Stream", "Create stream", {"strm"}, + New_Stream); - - newTypes->DeclareFunction(gc,"Version","Create a version object",{"$major","$minor","$patch","$build","$stage"},[](GCList& ls, std::vector args)->TObject{ - int64_t major=1; - int64_t minor=0; - int64_t patch=0; - int64_t build=0; - std::string stageS="prod"; - TVMVersionStage stage=TVMVersionStage::ProductionVersion; - GetArgument(args, 0,major); - GetArgument(args, 1,minor); - GetArgument(args, 2,patch); - GetArgument(args, 3,build); - GetArgument(args, 4,stageS); - if(stageS == "dev") + newTypes->DeclareFunction( + gc, "Version", "Create a version object", + {"$major", "$minor", "$patch", "$build", "$stage"}, + [](GCList &ls, std::vector args) -> TObject { + int64_t major = 1; + int64_t minor = 0; + int64_t patch = 0; + int64_t build = 0; + std::string stageS = "prod"; + TVMVersionStage stage = TVMVersionStage::ProductionVersion; + GetArgument(args, 0, major); + GetArgument(args, 1, minor); + GetArgument(args, 2, patch); + GetArgument(args, 3, build); + GetArgument(args, 4, stageS); + if (stageS == "dev") stage = TVMVersionStage::DevVersion; - else if(stageS == "alpha") + else if (stageS == "alpha") stage = TVMVersionStage::AlphaVersion; - else if(stageS == "beta") + else if (stageS == "beta") stage = TVMVersionStage::BetaVersion; - return TVMVersion((uint8_t)major,(uint8_t)minor,(uint8_t)patch,(uint16_t)build,stage); + return TVMVersion((uint8_t)major, (uint8_t)minor, (uint8_t)patch, + (uint16_t)build, stage); }); - newTypes->DeclareFunction(gc,"Random","Create random number generator",{"$seed"}, [](GCList& ls,std::vector args)->TObject{ + newTypes->DeclareFunction( + gc, "Random", "Create random number generator", {"$seed"}, + [](GCList &ls, std::vector args) -> TObject { int64_t seed; - if(GetArgument(args,0,seed)) - { + if (GetArgument(args, 0, seed)) { return TNativeObject::Create(ls, (uint64_t)seed); } return TNativeObject::Create(ls); }); - newTypes->DeclareFunction(gc, "StreamReader","Create a StreamReader", {"strmOrVFS","$pathIfVFS"},New_StreamReader); - newTypes->DeclareFunction(gc, "StreamWriter","Create a StreamWriter", {"strmOrVFS","$pathIfVFS","$appendIfVFS"},New_StreamWriter); - newTypes->DeclareFunction(gc, "StringReader","Create a StringReader", {"str"},New_StringReader); - newTypes->DeclareFunction(gc, "StringWriter","Create a StringWriter", {"$str"},New_StringWriter); - - env->DeclareFunction(gc, "ParseLong","Parse Long from String",{"arg","$base"},ParseLong); - env->DeclareFunction(gc, "ParseDouble","Parse Double from String",{"arg"},ParseDouble); - env->DeclareFunction(gc, "YieldEmumerable","Turn yield in function into enumerable",{"closure"},YieldEnumerableFunc); - env->DeclareFunction(gc, "TypeOf","Get type of object",{"object"},TypeOf); - env->DeclareFunction(gc, "TypeIsDefined","Get whether object is not null or undefined",{"object"},TypeIsDefined); - env->DeclareFunction(gc, "TypeIsHeap","Get whether object is susceptible to garbage collection",{"object"},TypeIsHeap); - env->DeclareFunction(gc, "TypeIsNumber","Get whether object is a number",{"object"},TypeIsNumber); - env->DeclareFunction(gc, "TypeIsLong","Get whether object is a long (not a double)",{"object"},TypeIsLong); - env->DeclareFunction(gc, "TypeIsDouble","Get whether object is a double (not a long)",{"object"},TypeIsDouble); - env->DeclareFunction(gc, "TypeIsString","Get whether object is a string",{"object"},TypeIsString); - env->DeclareFunction(gc, "TypeIsCallable","Get whether object is callable",{"object"},TypeIsCallable); + newTypes->DeclareFunction(gc, "StreamReader", "Create a StreamReader", + {"strmOrVFS", "$pathIfVFS"}, New_StreamReader); + newTypes->DeclareFunction(gc, "StreamWriter", "Create a StreamWriter", + {"strmOrVFS", "$pathIfVFS", "$appendIfVFS"}, + New_StreamWriter); + newTypes->DeclareFunction(gc, "StringReader", "Create a StringReader", + {"str"}, New_StringReader); + newTypes->DeclareFunction(gc, "StringWriter", "Create a StringWriter", + {"$str"}, New_StringWriter); - env->DeclareFunction(gc, "TypeIsClass","Get whether object is class instance",{"object"},TypeIsClass); - env->DeclareFunction(gc, "TypeIsDictionary","Get whether object is a dictionary or dynamic dictionary",{"object"},TypeIsDictionary); - env->DeclareFunction(gc, "TypeIsList","Get whether object is a list or dynamic list",{"object"},TypeIsList); - env->DeclareFunction(gc, "TypeIsStream","Get whether object is a stream",{"object"},TypeIsStream); - env->DeclareFunction(gc, "TypeIsVFS","Get whether object is a virtual filesystem",{"object"},TypeIsVFS); - env->DeclareFunction(gc, "TypeIsDateTime","Get whether object is a DateTime",{"object"},TypeIsDateTime); - env->DeclareFunction(gc, "TypeIsTimeSpan","Get whether object is a TimeSpan",{"object"},TypeIsTimeSpan); - env->DeclareFunction(gc, "TypeIsTextReader","Get whether object is a TextReader",{"object"},TypeIsTextReader); - env->DeclareFunction(gc, "TypeIsTextWriter","Get whether object is a TextWriter",{"object"},TypeIsTextWriter); - env->DeclareFunction(gc, "TypeIsByteReader","Get whether object is a ByteReader",{"object"},TypeIsByteReader); - env->DeclareFunction(gc, "TypeIsByteWriter","Get whether object is a ByteWriter",{"object"},TypeIsByteWriter); - env->DeclareFunction(gc, "TypeIsUuid","Get whether object is a Uuid",{"object"},TypeIsUuid); - env->DeclareFunction(gc, "TypeIsQueryable","Get whether object is a Queryable",{"object"},TypeIsQueryable); - - newTypes->DeclareFunction(gc, "Regex", "Create regex object",{"regex"},[](GCList& ls,std::vector args)->TObject { + env->DeclareFunction(gc, "ParseLong", "Parse Long from String", + {"arg", "$base"}, ParseLong); + env->DeclareFunction(gc, "ParseDouble", "Parse Double from String", {"arg"}, + ParseDouble); + env->DeclareFunction(gc, "YieldEmumerable", + "Turn yield in function into enumerable", {"closure"}, + YieldEnumerableFunc); + env->DeclareFunction(gc, "TypeOf", "Get type of object", {"object"}, + TypeOf); + env->DeclareFunction(gc, "TypeIsDefined", + "Get whether object is not null or undefined", + {"object"}, TypeIsDefined); + env->DeclareFunction( + gc, "TypeIsHeap", + "Get whether object is susceptible to garbage collection", {"object"}, + TypeIsHeap); + env->DeclareFunction(gc, "TypeIsNumber", "Get whether object is a number", + {"object"}, TypeIsNumber); + env->DeclareFunction(gc, "TypeIsLong", + "Get whether object is a long (not a double)", + {"object"}, TypeIsLong); + env->DeclareFunction(gc, "TypeIsDouble", + "Get whether object is a double (not a long)", + {"object"}, TypeIsDouble); + env->DeclareFunction(gc, "TypeIsString", "Get whether object is a string", + {"object"}, TypeIsString); + env->DeclareFunction(gc, "TypeIsCallable", "Get whether object is callable", + {"object"}, TypeIsCallable); + + env->DeclareFunction(gc, "TypeIsClass", + "Get whether object is class instance", {"object"}, + TypeIsClass); + env->DeclareFunction( + gc, "TypeIsDictionary", + "Get whether object is a dictionary or dynamic dictionary", {"object"}, + TypeIsDictionary); + env->DeclareFunction(gc, "TypeIsList", + "Get whether object is a list or dynamic list", + {"object"}, TypeIsList); + env->DeclareFunction(gc, "TypeIsStream", "Get whether object is a stream", + {"object"}, TypeIsStream); + env->DeclareFunction(gc, "TypeIsVFS", + "Get whether object is a virtual filesystem", + {"object"}, TypeIsVFS); + env->DeclareFunction(gc, "TypeIsDateTime", + "Get whether object is a DateTime", {"object"}, + TypeIsDateTime); + env->DeclareFunction(gc, "TypeIsTimeSpan", + "Get whether object is a TimeSpan", {"object"}, + TypeIsTimeSpan); + env->DeclareFunction(gc, "TypeIsTextReader", + "Get whether object is a TextReader", {"object"}, + TypeIsTextReader); + env->DeclareFunction(gc, "TypeIsTextWriter", + "Get whether object is a TextWriter", {"object"}, + TypeIsTextWriter); + env->DeclareFunction(gc, "TypeIsByteReader", + "Get whether object is a ByteReader", {"object"}, + TypeIsByteReader); + env->DeclareFunction(gc, "TypeIsByteWriter", + "Get whether object is a ByteWriter", {"object"}, + TypeIsByteWriter); + env->DeclareFunction(gc, "TypeIsUuid", "Get whether object is a Uuid", + {"object"}, TypeIsUuid); + env->DeclareFunction(gc, "TypeIsQueryable", + "Get whether object is a Queryable", {"object"}, + TypeIsQueryable); + + newTypes->DeclareFunction( + gc, "Regex", "Create regex object", {"regex"}, + [](GCList &ls, std::vector args) -> TObject { std::string str; - if(GetArgument(args,0,str)) - { + if (GetArgument(args, 0, str)) { std::regex regex(str); return regex; } return nullptr; }); - newTypes->DeclareFunction(gc, "Mutex", "Create mutex",{}, [](GCList& ls,std::vector args)->TObject { - + newTypes->DeclareFunction( + gc, "Mutex", "Create mutex", {}, + [](GCList &ls, std::vector args) -> TObject { return TNativeObject::Create(ls); }); - newTypes->DeclareFunction(gc, "Thread","Create thread",{"callback"},[](GCList& ls, std::vector args)-> TObject - { - if(args.size() == 1 && std::holds_alternative(args[0])) - { - auto cb = dynamic_cast(std::get(args[0]).obj); - if(cb != nullptr) - { - return CreateThread(ls,cb,false); + newTypes->DeclareFunction( + gc, "Thread", "Create thread", {"callback"}, + [](GCList &ls, std::vector args) -> TObject { + if (args.size() == 1 && + std::holds_alternative(args[0])) { + auto cb = dynamic_cast( + std::get(args[0]).obj); + if (cb != nullptr) { + return CreateThread(ls, cb, false); } } return Undefined(); }); - newTypes->DeclareFunction(gc,"DynamicList","Create a dynamic list",{},[](GCList& ls,std::vector args)->TObject { - TCallable* callable; - if(GetArgumentHeap(args,0,callable)) - return TDynamicList::Create(ls,callable); + newTypes->DeclareFunction( + gc, "DynamicList", "Create a dynamic list", {}, + [](GCList &ls, std::vector args) -> TObject { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) + return TDynamicList::Create(ls, callable); return nullptr; }); - newTypes->DeclareFunction(gc,"DynamicDictionary","Create a dynamic dictionary",{},[](GCList& ls, std::vector args)->TObject { - TCallable* callable; - if(GetArgumentHeap(args,0,callable)) - return TDynamicDictionary::Create(ls,callable); + newTypes->DeclareFunction( + gc, "DynamicDictionary", "Create a dynamic dictionary", {}, + [](GCList &ls, std::vector args) -> TObject { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) + return TDynamicDictionary::Create(ls, callable); return nullptr; }); - newTypes->DeclareFunction(gc,"AssociativeArray","Create a new AssociativeArray",{},[](GCList& ls, std::vector args)->TObject { + newTypes->DeclareFunction( + gc, "AssociativeArray", "Create a new AssociativeArray", {}, + [](GCList &ls, std::vector args) -> TObject { return TAssociativeArray::Create(ls); }); - newTypes->DeclareFunction(gc,"AArray","alias for new AssociativeArray",{},[](GCList& ls, std::vector args)->TObject { + newTypes->DeclareFunction( + gc, "AArray", "alias for new AssociativeArray", {}, + [](GCList &ls, std::vector args) -> TObject { return TAssociativeArray::Create(ls); }); - newTypes->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray); - newTypes->DeclareFunction(gc, "Queryable", "Create a queryable", {"enumerable"}, New_Queryable); - - env->DeclareVariable("Version", TDictionary::Create(ls,{ - TDItem("Parse",TExternalMethod::Create(ls,"Parse version from string",{"versionStr"},[](GCList& ls, std::vector args)->TObject{ - std::string str; - TVMVersion v; - if(GetArgument(args,0,v)) return v; - if(GetArgument(args, 0, str)) - { - TVMVersion version; - if(TVMVersion::TryParse(str,version)) - { - return version; - } - } - return nullptr; - })), - TDItem("FromByteArray",TExternalMethod::Create(ls,"Create from ByteArray",{"byteArray","$offset"},[](GCList& ls,std::vector args)->TObject { - TByteArray* ba; - if(GetArgumentHeap(args,0, ba)) - { - int64_t offset=0; - GetArgument(args, 1, offset); - if(ba->data.size() < 5) throw VMException("ByteArray too small"); - size_t o = (size_t)offset; - if((o + 5) > ba->data.size() || (o + 5) < 5) throw VMException("ByteArray too small"); - - return TVMVersion(ba->data.data()+o); - } - return nullptr; - })), - TDItem("FromLong", TExternalMethod::Create(ls, "Create from long",{"longBasedVersion"},[](GCList& ls, std::vector args)->TObject { - int64_t num; - if(GetArgument(args,0,num)) - { - return TVMVersion((uint64_t)num); - } - return nullptr; - })) - })); - env->DeclareVariable("InvokeMethod",MethodInvoker()); + newTypes->DeclareFunction( + gc, "ByteArray", + "Create bytearray, with optional either size (to size it) or string " + "argument (to fill byte array)", + {"$data"}, ByteArray); + newTypes->DeclareFunction(gc, "Queryable", "Create a queryable", + {"enumerable"}, New_Queryable); + env->DeclareVariable( + "Version", + TDictionary::Create( + ls, + {TDItem("Parse", + TExternalMethod::Create( + ls, "Parse version from string", {"versionStr"}, + [](GCList &ls, std::vector args) -> TObject { + std::string str; + TVMVersion v; + if (GetArgument(args, 0, v)) + return v; + if (GetArgument(args, 0, str)) { + TVMVersion version; + if (TVMVersion::TryParse(str, version)) { + return version; + } + } + return nullptr; + })), + TDItem("FromByteArray", + TExternalMethod::Create( + ls, "Create from ByteArray", {"byteArray", "$offset"}, + [](GCList &ls, std::vector args) -> TObject { + TByteArray *ba; + if (GetArgumentHeap(args, 0, ba)) { + int64_t offset = 0; + GetArgument(args, 1, offset); + if (ba->data.size() < 5) + throw VMException("ByteArray too small"); + size_t o = (size_t)offset; + if ((o + 5) > ba->data.size() || (o + 5) < 5) + throw VMException("ByteArray too small"); - - gc->BarrierEnd(); - } - void TStd::RegisterStd(std::shared_ptr gc, TRootEnvironment* env) - { - RegisterStd(gc, env, std::make_shared(Tesses::Framework::Filesystem::LocalFS, Tesses::Framework::Filesystem::VFSPath::GetAbsoluteCurrentDirectory())); - } - void TStd::RegisterStd(std::shared_ptr gc, TRootEnvironment* env,std::shared_ptr localfs) - { - env->permissions.canRegisterEverything=true; - RegisterEnv(gc, env); - RegisterRoot(gc,env); - RegisterPath(gc,env); - - RegisterConsole(gc, env); - RegisterIO(gc, env, localfs); - RegisterNet(gc, env); - RegisterSqlite(gc, env); - RegisterVM(gc, env); - RegisterJson(gc, env); - RegisterDictionary(gc, env); - RegisterCrypto(gc,env); - RegisterOGC(gc, env); - RegisterProcess(gc,env); - RegisterClass(gc,env); + return TVMVersion(ba->data.data() + o); + } + return nullptr; + })), + TDItem("FromLong", + TExternalMethod::Create( + ls, "Create from long", {"longBasedVersion"}, + [](GCList &ls, std::vector args) -> TObject { + int64_t num; + if (GetArgument(args, 0, num)) { + return TVMVersion((uint64_t)num); + } + return nullptr; + }))})); + env->DeclareVariable("InvokeMethod", MethodInvoker()); - gc->RegisterEverything(env); + gc->BarrierEnd(); +} +void TStd::RegisterStd(std::shared_ptr gc, TRootEnvironment *env) { + RegisterStd( + gc, env, + std::make_shared( + Tesses::Framework::Filesystem::LocalFS, + Tesses::Framework::Filesystem::VFSPath:: + GetAbsoluteCurrentDirectory())); +} +void TStd::RegisterStd( + std::shared_ptr gc, TRootEnvironment *env, + std::shared_ptr + localfs) { + env->permissions.canRegisterEverything = true; + RegisterEnv(gc, env); + RegisterRoot(gc, env); + RegisterPath(gc, env); - GCList ls(gc); + RegisterConsole(gc, env); + RegisterIO(gc, env, localfs); + RegisterNet(gc, env); + RegisterSqlite(gc, env); + RegisterVM(gc, env); + RegisterJson(gc, env); + RegisterDictionary(gc, env); + RegisterCrypto(gc, env); + RegisterOGC(gc, env); + RegisterProcess(gc, env); + RegisterClass(gc, env); - TDictionary* dict = TDictionary::Create(ls); - TDictionary* gc_dict = TDictionary::Create(ls); - #if defined(CROSSLANG_ENABLE_FFI) - TDictionary* ffi = TDictionary::Create(ls); - RegisterFFI(gc,ffi); - #endif - dict->DeclareFunction(gc,"LoadNativePlugin","Load a native plugin, requires a dynamic linker and shared build of libcrosslang",{"path"},[gc,env](GCList& ls, std::vector args)->TObject { + gc->RegisterEverything(env); + + GCList ls(gc); + + TDictionary *dict = TDictionary::Create(ls); + TDictionary *gc_dict = TDictionary::Create(ls); +#if defined(CROSSLANG_ENABLE_FFI) + TDictionary *ffi = TDictionary::Create(ls); + RegisterFFI(gc, ffi); +#endif + dict->DeclareFunction( + gc, "LoadNativePlugin", + "Load a native plugin, requires a dynamic linker and shared build of " + "libcrosslang", + {"path"}, [gc, env](GCList &ls, std::vector args) -> TObject { Tesses::Framework::Filesystem::VFSPath path; - if(GetArgumentAsPath(args,0,path)) - { - LoadPlugin(gc,env,path); + if (GetArgumentAsPath(args, 0, path)) { + LoadPlugin(gc, env, path); } return nullptr; }); - gc_dict->DeclareFunction(gc,"Collect","Collect garbage",{},[](GCList& ls, std::vector args)->TObject{ + gc_dict->DeclareFunction( + gc, "Collect", "Collect garbage", {}, + [](GCList &ls, std::vector args) -> TObject { ls.GetGC()->Collect(); return nullptr; }); - gc_dict->DeclareFunction(gc,"BarrierBegin","Lock globally",{},[](GCList& ls,std::vector args)->TObject { + gc_dict->DeclareFunction( + gc, "BarrierBegin", "Lock globally", {}, + [](GCList &ls, std::vector args) -> TObject { ls.GetGC()->BarrierBegin(); return nullptr; }); - gc_dict->DeclareFunction(gc, "BarrierEnd","Unlock globally",{},[](GCList& ls, std::vector args)->TObject { + gc_dict->DeclareFunction( + gc, "BarrierEnd", "Unlock globally", {}, + [](GCList &ls, std::vector args) -> TObject { ls.GetGC()->BarrierEnd(); - return nullptr; + return nullptr; }); - gc->BarrierBegin(); - #if defined(CROSSLANG_ENABLE_FFI) - env->SetVariable("FFI", ffi); - #endif - env->SetVariable("Reflection",dict); - env->SetVariable("GC", gc_dict); - gc->BarrierEnd(); - env->permissions.locked=true; - } + gc->BarrierBegin(); +#if defined(CROSSLANG_ENABLE_FFI) + env->SetVariable("FFI", ffi); +#endif + env->SetVariable("Reflection", dict); + env->SetVariable("GC", gc_dict); + gc->BarrierEnd(); + env->permissions.locked = true; } +} // namespace Tesses::CrossLang diff --git a/src/runtime_methods/uuid.cpp b/src/runtime_methods/uuid.cpp index 263f5a2..42556d7 100644 --- a/src/runtime_methods/uuid.cpp +++ b/src/runtime_methods/uuid.cpp @@ -1,40 +1,42 @@ +#include "TessesFramework/Uuid.hpp" #include "CrossLang.hpp" #include "TessesFramework/Serialization/BitConverter.hpp" -#include "TessesFramework/Uuid.hpp" namespace Tesses::CrossLang { - static TObject Uuid_NewUuid(GCList& ls, std::vector args) - { - return Tesses::Framework::Uuid::Generate(); +static TObject Uuid_NewUuid(GCList &ls, std::vector args) { + return Tesses::Framework::Uuid::Generate(); +} +static TObject Uuid_TryParse(GCList &ls, std::vector args) { + std::string str; + Tesses::Framework::Uuid uuid; + if (GetArgument(args, 0, str) && + Tesses::Framework::Uuid::TryParse(str, uuid)) + return uuid; + return nullptr; +} +static TObject Uuid_FromBytes(GCList &ls, std::vector args) { + TByteArray *ba; + int64_t index; + if (GetArgumentHeap(args, 0, ba) && GetArgument(args, 1, index) && + (size_t)index < ba->data.size() && + (size_t)index + 16 <= ba->data.size()) { + return Tesses::Framework::Serialization::BitConverter::ToUuid( + ba->data[(size_t)index]); } - static TObject Uuid_TryParse(GCList& ls, std::vector args) - { - std::string str; - Tesses::Framework::Uuid uuid; - if(GetArgument(args, 0, str) && Tesses::Framework::Uuid::TryParse(str,uuid)) - return uuid; - return nullptr; - } - static TObject Uuid_FromBytes(GCList& ls, std::vector args) - { - TByteArray* ba; - int64_t index; - if(GetArgumentHeap(args,0,ba) && GetArgument(args, 1, index) && (size_t)index < ba->data.size() && (size_t)index + 16 <= ba->data.size()) - { - return Tesses::Framework::Serialization::BitConverter::ToUuid(ba->data[(size_t)index]); - } - return nullptr; - } - - void TStd::RegisterUuid(std::shared_ptr gc, TRootEnvironment* env) - { - gc->BarrierBegin(); - TDictionary* guid = env->EnsureDictionary(gc, "Uuid"); - guid->DeclareFunction(gc,"NewUuid","Create random uuid",{},Uuid_NewUuid); - guid->DeclareFunction(gc, "TryParse","Try to parse",{"str"}, Uuid_TryParse); - guid->DeclareFunction(gc, "FromBytes", "From bytes (big endian)",{"byteArray","offset"}, Uuid_FromBytes); - - gc->BarrierEnd(); - } -} \ No newline at end of file + return nullptr; +} + +void TStd::RegisterUuid(std::shared_ptr gc, TRootEnvironment *env) { + gc->BarrierBegin(); + TDictionary *guid = env->EnsureDictionary(gc, "Uuid"); + guid->DeclareFunction(gc, "NewUuid", "Create random uuid", {}, + Uuid_NewUuid); + guid->DeclareFunction(gc, "TryParse", "Try to parse", {"str"}, + Uuid_TryParse); + guid->DeclareFunction(gc, "FromBytes", "From bytes (big endian)", + {"byteArray", "offset"}, Uuid_FromBytes); + + gc->BarrierEnd(); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/runtime_methods/vm.cpp b/src/runtime_methods/vm.cpp index e7b7107..3f2d353 100644 --- a/src/runtime_methods/vm.cpp +++ b/src/runtime_methods/vm.cpp @@ -1,123 +1,104 @@ #include "CrossLang.hpp" -#include #include +#include #include -namespace Tesses::CrossLang -{ +namespace Tesses::CrossLang { - static TObject AstToTObject(GCList& ls,SyntaxNode node) - { - if(std::holds_alternative(node)) +static TObject AstToTObject(GCList &ls, SyntaxNode node) { + if (std::holds_alternative(node)) return nullptr; - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { return std::get(node); } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { return std::get(node); } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { return std::get(node); } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { std::string str = std::get(node); return str; } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { char c = std::get(node); return c; } - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { auto r = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - r->SetValue("Type",std::string(UndefinedExpression)); + r->SetValue("Type", std::string(UndefinedExpression)); ls.GetGC()->BarrierEnd(); return r; - } - - if(std::holds_alternative(node)) - { + if (std::holds_alternative(node)) { auto asn = std::get(node); auto r = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - r->SetValue("Type",asn.nodeName); - r->SetValue("IsExpression",asn.isExpression); - TList* ls2 = TList::Create(ls); - for(auto item : asn.nodes) - { - ls2->Add(AstToTObject(ls,item)); + r->SetValue("Type", asn.nodeName); + r->SetValue("IsExpression", asn.isExpression); + TList *ls2 = TList::Create(ls); + for (auto item : asn.nodes) { + ls2->Add(AstToTObject(ls, item)); } r->SetValue("Arguments", ls2); ls.GetGC()->BarrierEnd(); return r; } - return nullptr; - } - static TObject VM_SourceToAst(GCList& ls, std::vector args) - { - std::string str; - if(GetArgument(args,0,str)) - { - std::stringstream strm(str); - std::vector tokens; - int res = Lex("memory.tcross",strm,tokens); - if(res != 0) - { - throw VMException("Lex error at line: " + std::to_string(res)); - } - Parser p(tokens); - auto res2 =p.ParseRoot(); - return AstToTObject(ls,res2); + return nullptr; +} +static TObject VM_SourceToAst(GCList &ls, std::vector args) { + std::string str; + if (GetArgument(args, 0, str)) { + std::stringstream strm(str); + std::vector tokens; + int res = Lex("memory.tcross", strm, tokens); + if (res != 0) { + throw VMException("Lex error at line: " + std::to_string(res)); } - return nullptr; + Parser p(tokens); + auto res2 = p.ParseRoot(); + return AstToTObject(ls, res2); } - static TObject VM_Eval(GCList& ls, std::vector args) - { - std::string str; - if(GetArgument(args,0,str)) - { - if(current_function != nullptr) - { - return current_function->env->Eval(ls,str); - } + return nullptr; +} +static TObject VM_Eval(GCList &ls, std::vector args) { + std::string str; + if (GetArgument(args, 0, str)) { + if (current_function != nullptr) { + return current_function->env->Eval(ls, str); } - return nullptr; } - static TObject Failure(GCList& ls, std::string reason) - { - TDictionary* dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Success",false); - dict->SetValue("Reason", reason); - ls.GetGC()->BarrierEnd(); - return dict; - } - static TObject Success(GCList& ls) - { - TDictionary* dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Success",true); - ls.GetGC()->BarrierEnd(); - return dict; - } - static TObject VM_getCurrentEnvironment(GCList& ls2,std::vector args) - { - if(current_function != nullptr) return current_function->env; - return Undefined(); - } - static TObject VM_Compile(GCList& ls, std::vector args) - { - try { - TDictionary* dict; - if(!GetArgumentHeap(args,0,dict)) return Undefined(); + return nullptr; +} +static TObject Failure(GCList &ls, std::string reason) { + TDictionary *dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Success", false); + dict->SetValue("Reason", reason); + ls.GetGC()->BarrierEnd(); + return dict; +} +static TObject Success(GCList &ls) { + TDictionary *dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Success", true); + ls.GetGC()->BarrierEnd(); + return dict; +} +static TObject VM_getCurrentEnvironment(GCList &ls2, + std::vector args) { + if (current_function != nullptr) + return current_function->env; + return Undefined(); +} +static TObject VM_Compile(GCList &ls, std::vector args) { + try { + TDictionary *dict; + if (!GetArgumentHeap(args, 0, dict)) + return Undefined(); /* VM.Compile { @@ -127,18 +108,20 @@ namespace Tesses::CrossLang Version = "", Dependencies = [{Name="Name", Version}], ResourceDirectory = "", - - } + + } */ std::string name = "Out"; - std::vector> sources; - TVMVersion version(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE); - std::vector> dependencies; - std::vector> tools; + std::vector> sources; + TVMVersion version(CROSSLANG_BYTECODE_MAJOR, CROSSLANG_BYTECODE_MINOR, + CROSSLANG_BYTECODE_PATCH, CROSSLANG_BYTECODE_BUILD, + CROSSLANG_BYTECODE_VERSIONSTAGE); + std::vector> dependencies; + std::vector> tools; std::string info; std::string icon; - bool debug=false; + bool debug = false; std::shared_ptr vfs; ls.GetGC()->BarrierBegin(); @@ -151,116 +134,110 @@ namespace Tesses::CrossLang TObject _icon = dict->GetValue("Icon"); TObject _comptime = dict->GetValue("CompTime"); TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem"); - + TObject _out = dict->GetValue("Output"); TObject _dbg = dict->GetValue("Debug"); - TList* _toolList; - TList* _depList; TList* srcLst; - TRootEnvironment* comptimeEnv=nullptr; - GetObject(_name,name); - GetObject(_info,info); - GetObject(_icon,icon); + TList *_toolList; + TList *_depList; + TList *srcLst; + TRootEnvironment *comptimeEnv = nullptr; + GetObject(_name, name); + GetObject(_info, info); + GetObject(_icon, icon); GetObject(_resourceFileSystem, vfs); - GetObjectHeap(_comptime,comptimeEnv); - GetObject(_dbg,debug); + GetObjectHeap(_comptime, comptimeEnv); + GetObject(_dbg, debug); std::string v2; - if(GetObject(_version,v2)) + if (GetObject(_version, v2)) TVMVersion::TryParse(v2, version); else - GetObject(_version,version); + GetObject(_version, version); - if(GetObjectHeap(_dependencies,_depList)) - { - for(int64_t i = 0; i < _depList->Count(); i++) - { + if (GetObjectHeap(_dependencies, _depList)) { + for (int64_t i = 0; i < _depList->Count(); i++) { TObject _dep = _depList->Get(i); - TDictionary* _depD; - if(GetObjectHeap(_dep, _depD)) - { + TDictionary *_depD; + if (GetObjectHeap(_dep, _depD)) { TObject _name2 = _depD->GetValue("Name"); TObject _version2 = _depD->GetValue("Version"); std::string name2; std::string version2; TVMVersion version02; - if(GetObject(_name2,name2) && GetObject(_version2,version2) && TVMVersion::TryParse(version2,version02)) - { - dependencies.push_back(std::pair(name2, version02)); - } - else if(GetObject(_name2,name2) && GetObject(_version2,version02)) - { - dependencies.push_back(std::pair(name2, version02)); + if (GetObject(_name2, name2) && + GetObject(_version2, version2) && + TVMVersion::TryParse(version2, version02)) { + dependencies.push_back( + std::pair(name2, + version02)); + } else if (GetObject(_name2, name2) && + GetObject(_version2, version02)) { + dependencies.push_back( + std::pair(name2, + version02)); } } } - } - if(GetObjectHeap(_tools,_toolList)) - { - for(int64_t i = 0; i < _toolList->Count(); i++) - { + if (GetObjectHeap(_tools, _toolList)) { + for (int64_t i = 0; i < _toolList->Count(); i++) { TObject _dep = _toolList->Get(i); - TDictionary* _depD; - if(GetObjectHeap(_dep, _depD)) - { + TDictionary *_depD; + if (GetObjectHeap(_dep, _depD)) { TObject _name2 = _depD->GetValue("Name"); TObject _version2 = _depD->GetValue("Version"); std::string name2; std::string version2; TVMVersion version02; - if(GetObject(_name2,name2) && GetObject(_version2,version2) && TVMVersion::TryParse(version2,version02)) - { - tools.push_back(std::pair(name2, version02)); - } - else if(GetObject(_name2,name2) && GetObject(_version2,version02)) - { - tools.push_back(std::pair(name2, version02)); + if (GetObject(_name2, name2) && + GetObject(_version2, version2) && + TVMVersion::TryParse(version2, version02)) { + tools.push_back(std::pair( + name2, version02)); + } else if (GetObject(_name2, name2) && + GetObject(_version2, version02)) { + tools.push_back(std::pair( + name2, version02)); } } } - } - if(GetObjectHeap(_sources,srcLst)) - { - for(int64_t i = 0; i < srcLst->Count(); i++) - { + if (GetObjectHeap(_sources, srcLst)) { + for (int64_t i = 0; i < srcLst->Count(); i++) { TObject _src = srcLst->Get(i); - TDictionary* _srcD; - if(GetObjectHeap(_src, _srcD)) - { + TDictionary *_srcD; + if (GetObjectHeap(_src, _srcD)) { TObject _sourceTxt = _srcD->GetValue("Source"); TObject _filename = _srcD->GetValue("FileName"); - std::string srctxt = ""; - std::string filename = "memory_" + std::to_string(i) + ".tcross"; + std::string filename = + "memory_" + std::to_string(i) + ".tcross"; bool fromFile = false; - GetObject(_sourceTxt,srctxt); - GetObject(_filename,filename); - - - sources.push_back(std::pair(srctxt,filename)); + GetObject(_sourceTxt, srctxt); + GetObject(_filename, filename); + + sources.push_back( + std::pair(srctxt, filename)); } } - } - + ls.GetGC()->BarrierEnd(); std::vector tokens; - for(auto source : sources) - { + for (auto source : sources) { std::stringstream strm(source.first); int res = Lex(source.second, strm, tokens); - if(res != 0) - { - return Failure(ls, "Lex error in file \"" + source.second + "\":" + std::to_string(res)); + if (res != 0) { + return Failure(ls, "Lex error in file \"" + source.second + + "\":" + std::to_string(res)); } } - Parser parser(tokens,ls.GetGC(),comptimeEnv); + Parser parser(tokens, ls.GetGC(), comptimeEnv); parser.debug = debug; SyntaxNode n = parser.ParseRoot(); CodeGen gen; @@ -274,147 +251,136 @@ namespace Tesses::CrossLang gen.icon = icon; std::string outpath; std::shared_ptr stream; - if(GetObject(_out, stream)) - { + if (GetObject(_out, stream)) { gen.Save(stream); } - - return Success(ls); - } catch(std::exception& ex) - { - return Failure(ls, ex.what()); - } + } catch (std::exception &ex) { + return Failure(ls, ex.what()); } - static TObject VM_GetStacktrace(GCList& ls, std::vector args) - { - if(current_function != nullptr) - { - if(current_function->thread != nullptr) - { - TList* list = TList::Create(ls); - ls.GetGC()->BarrierBegin(); - for(auto item : current_function->thread->call_stack_entries) - { - auto dict = TDictionary::Create(ls); - if(item->callable->closure->name) - dict->SetValue("Name", *item->callable->closure->name); - - dict->SetValue("Closure", item->callable->closure); - dict->SetValue("FileName", item->callable->file->name + "-" + item->callable->file->version.ToString() + ".crvm"); - dict->SetValue("IP",(int64_t)item->ip); - if(item->srcline >= 1) - { - dict->SetValue("SourceFile", item->srcfile); - dict->SetValue("SourceLine",item->srcline); - } - list->Add(dict); - } - ls.GetGC()->BarrierEnd(); - return list; - } - } - return nullptr; - } - void TStd::RegisterVM(std::shared_ptr gc,TRootEnvironment* env) - { - env->permissions.canRegisterVM=true; - GCList ls(gc); +} +static TObject VM_GetStacktrace(GCList &ls, std::vector args) { + if (current_function != nullptr) { + if (current_function->thread != nullptr) { + TList *list = TList::Create(ls); + ls.GetGC()->BarrierBegin(); + for (auto item : current_function->thread->call_stack_entries) { + auto dict = TDictionary::Create(ls); + if (item->callable->closure->name) + dict->SetValue("Name", *item->callable->closure->name); - TDictionary* dict = TDictionary::Create(ls); - dict->DeclareFunction(gc, "GetStacktrace","Get the current stack trace", {}, VM_GetStacktrace); - dict->DeclareFunction(gc, "getRootEnvironmentAsDictionary","Get root environment as a dictionary",{},[env](GCList& ls, std::vector args)-> TObject{ + dict->SetValue("Closure", item->callable->closure); + dict->SetValue("FileName", + item->callable->file->name + "-" + + item->callable->file->version.ToString() + + ".crvm"); + dict->SetValue("IP", (int64_t)item->ip); + if (item->srcline >= 1) { + dict->SetValue("SourceFile", item->srcfile); + dict->SetValue("SourceLine", item->srcline); + } + list->Add(dict); + } + ls.GetGC()->BarrierEnd(); + return list; + } + } + return nullptr; +} +void TStd::RegisterVM(std::shared_ptr gc, TRootEnvironment *env) { + env->permissions.canRegisterVM = true; + GCList ls(gc); + + TDictionary *dict = TDictionary::Create(ls); + dict->DeclareFunction(gc, "GetStacktrace", "Get the current stack trace", + {}, VM_GetStacktrace); + dict->DeclareFunction( + gc, "getRootEnvironmentAsDictionary", + "Get root environment as a dictionary", {}, + [env](GCList &ls, std::vector args) -> TObject { return env->GetDictionary(); }); - dict->DeclareFunction(gc, "getRootEnvironment","Get root environment, for reflection purposes",{},[env](GCList& ls2,std::vector args)->TObject {return env;}); - dict->DeclareFunction(gc, "getCurrentEnvironment","Get current environment, for reflection purposes",{},VM_getCurrentEnvironment); - dict->DeclareFunction(gc, "CreateEnvironment","Create root environment",{"$dict"},[env](GCList& ls,std::vector args)->TObject{ - TDictionary* dict; - if(GetArgumentHeap(args,0,dict)) - { - auto renv = TRootEnvironment::Create(ls,dict); - renv->permissions.customConsole = env->permissions.customConsole; + dict->DeclareFunction( + gc, "getRootEnvironment", + "Get root environment, for reflection purposes", {}, + [env](GCList &ls2, std::vector args) -> TObject { + return env; + }); + dict->DeclareFunction(gc, "getCurrentEnvironment", + "Get current environment, for reflection purposes", + {}, VM_getCurrentEnvironment); + dict->DeclareFunction( + gc, "CreateEnvironment", "Create root environment", {"$dict"}, + [env](GCList &ls, std::vector args) -> TObject { + TDictionary *dict; + if (GetArgumentHeap(args, 0, dict)) { + auto renv = TRootEnvironment::Create(ls, dict); + renv->permissions.customConsole = + env->permissions.customConsole; return renv; - } - else - { - auto renv = TRootEnvironment::Create(ls,TDictionary::Create(ls)); - renv->permissions.customConsole = env->permissions.customConsole; + } else { + auto renv = + TRootEnvironment::Create(ls, TDictionary::Create(ls)); + renv->permissions.customConsole = + env->permissions.customConsole; return renv; } }); - dict->DeclareFunction(gc, "LoadExecutable", "Load a crossvm executable",{"stream"},[](GCList& ls,std::vector args)->TObject{ + dict->DeclareFunction( + gc, "LoadExecutable", "Load a crossvm executable", {"stream"}, + [](GCList &ls, std::vector args) -> TObject { std::shared_ptr strm; - if(GetArgument(args,0,strm)) - { - TFile* f =TFile::Create(ls); - f->Load(ls.GetGC(),strm); + if (GetArgument(args, 0, strm)) { + TFile *f = TFile::Create(ls); + f->Load(ls.GetGC(), strm); return f; } return nullptr; }); - #if defined(CROSSLANG_ENABLE_SUPERSLIM) - dict->SetValue("SuperSlim", true); - #else - dict->SetValue("SuperSlim", false); - #endif - dict->DeclareFunction(gc, "Eval", "Eval source code",{"source"}, VM_Eval); - dict->DeclareFunction(gc, "Compile", "Compile Source",{"dict"},VM_Compile); - - dict->DeclareFunction(gc, "SourceToAst", "Convert source to ast", {"source"}, VM_SourceToAst); - dict->DeclareFunction(gc, "getRuntimeVersion","Get the runtime version",{},[](GCList& ls,std::vector args)->TObject { - return TVMVersion(CROSSLANG_MAJOR,CROSSLANG_MINOR,CROSSLANG_PATCH,0,TVMVersionStage::DevVersion); - }); - dict->DeclareFunction(gc, "getBytecodeVersion","Get the bytecode version",{},[](GCList& ls,std::vector args)->TObject { - return TVMVersion(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE); - }); - dict->DeclareFunction(gc, "getIsRunning","Is the program still running",{},[](GCList& ls, std::vector args)->TObject { - return Tesses::Framework::TF_IsRunning(); - }); - dict->DeclareFunction(gc, "RunEventLoopItteration","Run Event Loop Itteration",{},[](GCList& ls, std::vector args)->TObject { - Tesses::Framework::TF_RunEventLoopItteration(); - return Undefined(); - }); - dict->DeclareFunction(gc, "RunEventLoop","Run Event Loop",{},[](GCList& ls, std::vector args)->TObject { - Tesses::Framework::TF_RunEventLoop(); - return Undefined(); - }); - dict->DeclareFunction(gc, "Merge", "Merge crvm files", {"srcVFS","sourcePath","destVFS"},[](GCList& ls, std::vector args)->TObject { - std::shared_ptr srcVFS; - std::shared_ptr destVFS; - Tesses::Framework::Filesystem::VFSPath sourcePath; - if(GetArgument(args,0, srcVFS) && GetArgumentAsPath(args,1,sourcePath) && GetArgument(args,2,destVFS)) - return Merge(srcVFS, sourcePath, destVFS); - return Undefined(); - }); - dict->DeclareFunction(gc, "Disassemble","Disassemble crvm file",{"strm","vfs","$generateJSON","$extractResources"},[](GCList& ls, std::vector args)->TObject { - std::shared_ptr strm; - std::shared_ptr vfs; - bool generateJSON=true; - bool extractResources=true; - if(GetArgument(args,0,strm) && GetArgument(args,1, vfs)) - { - GetArgument(args,2,generateJSON); - GetArgument(args,3,extractResources); - Disassemble(strm,vfs, generateJSON, extractResources); - } - return Undefined(); - }); - dict->DeclareFunction(gc, "Assemble", "Assemble crvm file",{"vfs"},[](GCList& ls, std::vector args)->TObject { - std::shared_ptr vfs; - if(GetArgument(args,0, vfs)) - return Assemble(vfs); - return Undefined(); - }); - - gc->BarrierBegin(); - - - env->DeclareVariable("VM", dict); - - gc->BarrierEnd(); - } - -} \ No newline at end of file + dict->DeclareFunction(gc, "Eval", "Eval source code", {"source"}, VM_Eval); + dict->DeclareFunction(gc, "Compile", "Compile Source", {"dict"}, + VM_Compile); + + dict->DeclareFunction(gc, "SourceToAst", "Convert source to ast", + {"source"}, VM_SourceToAst); + dict->DeclareFunction( + gc, "getRuntimeVersion", "Get the runtime version", {}, + [](GCList &ls, std::vector args) -> TObject { + return TVMVersion(CROSSLANG_MAJOR, CROSSLANG_MINOR, CROSSLANG_PATCH, + 0, TVMVersionStage::DevVersion); + }); + dict->DeclareFunction( + gc, "getBytecodeVersion", "Get the bytecode version", {}, + [](GCList &ls, std::vector args) -> TObject { + return TVMVersion( + CROSSLANG_BYTECODE_MAJOR, CROSSLANG_BYTECODE_MINOR, + CROSSLANG_BYTECODE_PATCH, CROSSLANG_BYTECODE_BUILD, + CROSSLANG_BYTECODE_VERSIONSTAGE); + }); + dict->DeclareFunction(gc, "getIsRunning", "Is the program still running", + {}, + [](GCList &ls, std::vector args) -> TObject { + return Tesses::Framework::TF_IsRunning(); + }); + dict->DeclareFunction(gc, "RunEventLoopItteration", + "Run Event Loop Itteration", {}, + [](GCList &ls, std::vector args) -> TObject { + Tesses::Framework::TF_RunEventLoopItteration(); + return Undefined(); + }); + dict->DeclareFunction(gc, "RunEventLoop", "Run Event Loop", {}, + [](GCList &ls, std::vector args) -> TObject { + Tesses::Framework::TF_RunEventLoop(); + return Undefined(); + }); + + gc->BarrierBegin(); + + env->DeclareVariable("VM", dict); + + gc->BarrierEnd(); +} + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/any.cpp b/src/types/any.cpp index 39ab631..a98f01e 100644 --- a/src/types/any.cpp +++ b/src/types/any.cpp @@ -1,28 +1,26 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { - TAny* TAny::Create(GCList& ls) - { - TAny* anyObj = new TAny(); - - std::shared_ptr gc = ls.GetGC(); - ls.Add(anyObj); - gc->Watch(anyObj); - return anyObj; - } - TAny* TAny::Create(GCList* ls) - { - TAny* anyObj = new TAny(); - - std::shared_ptr gc = ls->GetGC(); - ls->Add(anyObj); - gc->Watch(anyObj); - return anyObj; - } - void TAny::Mark() - { - if(this->marked) return; - this->marked=true; - GC::Mark(this->other); - } -} \ No newline at end of file +TAny *TAny::Create(GCList &ls) { + TAny *anyObj = new TAny(); + + std::shared_ptr gc = ls.GetGC(); + ls.Add(anyObj); + gc->Watch(anyObj); + return anyObj; +} +TAny *TAny::Create(GCList *ls) { + TAny *anyObj = new TAny(); + + std::shared_ptr gc = ls->GetGC(); + ls->Add(anyObj); + gc->Watch(anyObj); + return anyObj; +} +void TAny::Mark() { + if (this->marked) + return; + this->marked = true; + GC::Mark(this->other); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/associativearray.cpp b/src/types/associativearray.cpp index 529d97f..b3cf6ab 100644 --- a/src/types/associativearray.cpp +++ b/src/types/associativearray.cpp @@ -1,116 +1,96 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - - TAssociativeArray* TAssociativeArray::Create(GCList& ls) - { - TAssociativeArray* list=new TAssociativeArray(); - std::shared_ptr _gc = ls.GetGC(); - ls.Add(list); - _gc->Watch(list); - return list; - } - TAssociativeArray* TAssociativeArray::Create(GCList* ls) - { - TAssociativeArray* list=new TAssociativeArray(); - std::shared_ptr _gc = ls->GetGC(); - ls->Add(list); - _gc->Watch(list); - return list; - } - void TAssociativeArray::Set(std::shared_ptr gc, TObject key, TObject value) - { - if(std::holds_alternative(key)) return; - gc->BarrierBegin(); - for(auto index = this->items.begin(); index < this->items.end(); index++) - { - auto first= index->first; - gc->BarrierEnd(); - auto eq = Equals(gc,key,first); - gc->BarrierBegin(); - if(eq) - { - if(std::holds_alternative(value)) - { - this->items.erase(index); - } - else - { - index->second = value; - } - gc->BarrierEnd(); - return; - } - } - this->items.push_back(std::pair(key,value)); - gc->BarrierEnd(); - } - TObject TAssociativeArray::Get(std::shared_ptr gc, TObject key) - { - if(std::holds_alternative(key)) return Undefined(); - gc->BarrierBegin(); - for(auto& item : this->items) - { - auto first= item.first; - gc->BarrierEnd(); - auto eq = Equals(gc,key,first); - gc->BarrierBegin(); - if(eq) - { - gc->BarrierEnd(); - return item.second; - } - } - gc->BarrierEnd(); - return Undefined(); - } - TObject TAssociativeArray::GetKey(int64_t index) - { - if(index >= 0 && index < (int64_t)this->items.size()) - { - return this->items[index].first; - } - return Undefined(); - } - TObject TAssociativeArray::GetValue(int64_t index) - { - if(index >= 0 && index < (int64_t)this->items.size()) - { - return this->items[index].second; - } - return Undefined(); - } - void TAssociativeArray::SetKey(int64_t index, TObject key) - { +namespace Tesses::CrossLang { - if(std::holds_alternative(key)) return; - if(index >= 0 && index < (int64_t)this->items.size()) - { - this->items[index].first=key; - } - - } - void TAssociativeArray::SetValue(int64_t index,TObject value) - { - if(std::holds_alternative(value)) return; - if(index >= 0 && index < (int64_t)this->items.size()) - { - this->items[index].first=value; +TAssociativeArray *TAssociativeArray::Create(GCList &ls) { + TAssociativeArray *list = new TAssociativeArray(); + std::shared_ptr _gc = ls.GetGC(); + ls.Add(list); + _gc->Watch(list); + return list; +} +TAssociativeArray *TAssociativeArray::Create(GCList *ls) { + TAssociativeArray *list = new TAssociativeArray(); + std::shared_ptr _gc = ls->GetGC(); + ls->Add(list); + _gc->Watch(list); + return list; +} +void TAssociativeArray::Set(std::shared_ptr gc, TObject key, + TObject value) { + if (std::holds_alternative(key)) + return; + gc->BarrierBegin(); + for (auto index = this->items.begin(); index < this->items.end(); index++) { + auto first = index->first; + gc->BarrierEnd(); + auto eq = Equals(gc, key, first); + gc->BarrierBegin(); + if (eq) { + if (std::holds_alternative(value)) { + this->items.erase(index); + } else { + index->second = value; + } + gc->BarrierEnd(); + return; } } - int64_t TAssociativeArray::Count() - { - return (int64_t)this->items.size(); - } - void TAssociativeArray::Mark() - { - if(this->marked) return; - this->marked=true; - for(auto& item : this->items) - { - GC::Mark(item.first); - GC::Mark(item.second); + this->items.push_back(std::pair(key, value)); + gc->BarrierEnd(); +} +TObject TAssociativeArray::Get(std::shared_ptr gc, TObject key) { + if (std::holds_alternative(key)) + return Undefined(); + gc->BarrierBegin(); + for (auto &item : this->items) { + auto first = item.first; + gc->BarrierEnd(); + auto eq = Equals(gc, key, first); + gc->BarrierBegin(); + if (eq) { + gc->BarrierEnd(); + return item.second; } } -} \ No newline at end of file + gc->BarrierEnd(); + return Undefined(); +} +TObject TAssociativeArray::GetKey(int64_t index) { + if (index >= 0 && index < (int64_t)this->items.size()) { + return this->items[index].first; + } + return Undefined(); +} +TObject TAssociativeArray::GetValue(int64_t index) { + if (index >= 0 && index < (int64_t)this->items.size()) { + return this->items[index].second; + } + return Undefined(); +} +void TAssociativeArray::SetKey(int64_t index, TObject key) { + + if (std::holds_alternative(key)) + return; + if (index >= 0 && index < (int64_t)this->items.size()) { + this->items[index].first = key; + } +} +void TAssociativeArray::SetValue(int64_t index, TObject value) { + if (std::holds_alternative(value)) + return; + if (index >= 0 && index < (int64_t)this->items.size()) { + this->items[index].first = value; + } +} +int64_t TAssociativeArray::Count() { return (int64_t)this->items.size(); } +void TAssociativeArray::Mark() { + if (this->marked) + return; + this->marked = true; + for (auto &item : this->items) { + GC::Mark(item.first); + GC::Mark(item.second); + } +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/async.cpp b/src/types/async.cpp index 7e234bb..4980e07 100644 --- a/src/types/async.cpp +++ b/src/types/async.cpp @@ -1,261 +1,228 @@ #include "CrossLang.hpp" -//THANKS TO https://www.youtube.com/watch?v=R-z2Hv-7nxk +// THANKS TO https://www.youtube.com/watch?v=R-z2Hv-7nxk namespace Tesses::CrossLang { - TTask::TTask(std::shared_ptr gc) - { - this->gc = gc; - } - TTask* TTask::Create(GCList& ls) - { - TTask* task = new TTask(ls.GetGC()); - ls.Add(task); - task->gc->Watch(task); - return task; - } - bool TTask::IsCompleted() - { - gc->BarrierBegin(); - bool r = this->isCompleted; - gc->BarrierEnd(); +TTask::TTask(std::shared_ptr gc) { this->gc = gc; } +TTask *TTask::Create(GCList &ls) { + TTask *task = new TTask(ls.GetGC()); + ls.Add(task); + task->gc->Watch(task); + return task; +} +bool TTask::IsCompleted() { + gc->BarrierBegin(); + bool r = this->isCompleted; + gc->BarrierEnd(); - return r; - } - TTask* TTask::ContinueWith(GCList& ls, TCallable* callable) - { - TTask* task = TTask::Create(ls); + return r; +} +TTask *TTask::ContinueWith(GCList &ls, TCallable *callable) { + TTask *task = TTask::Create(ls); - TExternalMethod* em = TExternalMethod::Create(ls,"Internal async thing",{"_asyncObj"},[callable,task](GCList& ls,std::vector args)->TObject{ + TExternalMethod *em = TExternalMethod::Create( + ls, "Internal async thing", {"_asyncObj"}, + [callable, task](GCList &ls, std::vector args) -> TObject { try { - task->SetSucceeded(callable->Call(ls,args)); - } catch(...) { + task->SetSucceeded(callable->Call(ls, args)); + } catch (...) { task->SetFailed(std::current_exception()); } return nullptr; }); - em->watch = {callable,task}; - - this->gc->BarrierBegin(); - if(this->isCompleted) - { - this->gc->BarrierEnd(); - std::shared_ptr ls=std::make_shared(gc); - auto cobj = this->obj; - ls->Add(cobj); - ls->Add(em); - this->gc->GetPool()->Schedule([ls,em,cobj](size_t s)->void { - em->Call(*ls,{cobj}); - }); - return task; - } - else - { - this->cont = em; - } + em->watch = {callable, task}; + this->gc->BarrierBegin(); + if (this->isCompleted) { this->gc->BarrierEnd(); + std::shared_ptr ls = std::make_shared(gc); + auto cobj = this->obj; + ls->Add(cobj); + ls->Add(em); + this->gc->GetPool()->Schedule( + [ls, em, cobj](size_t s) -> void { em->Call(*ls, {cobj}); }); return task; + } else { + this->cont = em; } - void TTask::ContinueWith(TCallable* callable) - { - this->gc->BarrierBegin(); - if(this->isCompleted) - { - this->gc->BarrierEnd(); - std::shared_ptr ls=std::make_shared(gc); - auto cobj = this->obj; - ls->Add(cobj); - ls->Add(callable); - this->gc->GetPool()->Schedule([ls,callable,cobj](size_t s)->void { - callable->Call(*ls,{cobj}); - - }); - return; - } - else - { - this->cont = callable; - } + this->gc->BarrierEnd(); + return task; +} +void TTask::ContinueWith(TCallable *callable) { + this->gc->BarrierBegin(); + if (this->isCompleted) { this->gc->BarrierEnd(); - } - - - - - void TTask::SetFailed(std::exception_ptr ex) - { - this->ex = ex; - this->SetSucceeded(nullptr); - } - void TTask::SetSucceeded(TObject v) - { - gc->BarrierBegin(); - if(this->isCompleted) - { - gc->BarrierEnd(); - return; - } - this->isCompleted=true; - this->obj = v; - auto cont = this->cont; - gc->BarrierEnd(); - if(cont != nullptr) - { - std::shared_ptr ls=std::make_shared(gc); - - auto callable = cont; - ls->Add(v); - ls->Add(callable); - this->gc->GetPool()->Schedule([ls,callable,v](size_t s)->void { - callable->Call(*ls,{v}); - }); - } - } - - TObject TTask::Wait() - { - while(true) - { - gc->BarrierBegin(); - if(this->isCompleted) - { - if(this->ex) - { - auto error = this->ex; - gc->BarrierEnd(); - std::rethrow_exception(error); - } - - auto o = this->obj; - gc->BarrierEnd(); - return o; - - } - gc->BarrierEnd(); - } - } - void TTask::Mark() - { - if(this->marked) return; - this->marked=true; - GC::Mark(this->obj); - if(this->cont != nullptr) - this->cont->Mark(); - } - - TTask* TTask::Run(GCList& ls, TCallable* callable) - { - TTask* task = TTask::Create(ls); - std::shared_ptr ls2=std::make_shared(ls.GetGC()); - ls2->Add(callable); - ls2->Add(task); - - ls.GetGC()->GetPool()->Schedule([ls2,callable,task](size_t s)->void { - try - { - task->SetSucceeded(callable->Call(*ls2,{})); - } - catch(...) - { - task->SetFailed(std::current_exception()); - } + std::shared_ptr ls = std::make_shared(gc); + auto cobj = this->obj; + ls->Add(cobj); + ls->Add(callable); + this->gc->GetPool()->Schedule([ls, callable, cobj](size_t s) -> void { + callable->Call(*ls, {cobj}); }); - - return task; + return; + } else { + this->cont = callable; } - TTask* TTask::FromResult(GCList& ls, TObject v) - { - TTask* task = TTask::Create(ls); - task->SetSucceeded(v); - return task; - } + this->gc->BarrierEnd(); +} - class TTaskCseObj { - std::shared_ptr gc; - TTask* task; - public: - TTaskCseObj(std::shared_ptr gc, TTask* task) - { - this->gc = gc; - this->task = task; +void TTask::SetFailed(std::exception_ptr ex) { + this->ex = ex; + this->SetSucceeded(nullptr); +} +void TTask::SetSucceeded(TObject v) { + gc->BarrierBegin(); + if (this->isCompleted) { + gc->BarrierEnd(); + return; + } + this->isCompleted = true; + this->obj = v; + auto cont = this->cont; + gc->BarrierEnd(); + if (cont != nullptr) { + std::shared_ptr ls = std::make_shared(gc); + + auto callable = cont; + ls->Add(v); + ls->Add(callable); + this->gc->GetPool()->Schedule( + [ls, callable, v](size_t s) -> void { callable->Call(*ls, {v}); }); + } +} + +TObject TTask::Wait() { + while (true) { + gc->BarrierBegin(); + if (this->isCompleted) { + if (this->ex) { + auto error = this->ex; + gc->BarrierEnd(); + std::rethrow_exception(error); } - void Invoke(std::shared_ptr shared_o,CallStackEntry* cse, TObject o) - { - try { - GCList ls(gc); - cse->Push(gc,o); - auto res = cse->Resume(ls); - CallStackEntry* cse2; - if(GetObjectHeap(res,cse2)) - { - auto taskPiece=cse2->Pop(ls); - TTask* task; - if(GetObjectHeap(taskPiece,task)) - { - auto em = TExternalMethod::Create(ls,"",{"obj"},[cse2,task,shared_o](GCList& ls, std::vector args)->TObject { - - shared_o->Invoke(shared_o,cse2,args.empty() ? (TObject)Undefined():args[0]); + auto o = this->obj; + gc->BarrierEnd(); + return o; + } + gc->BarrierEnd(); + } +} +void TTask::Mark() { + if (this->marked) + return; + this->marked = true; + GC::Mark(this->obj); + if (this->cont != nullptr) + this->cont->Mark(); +} + +TTask *TTask::Run(GCList &ls, TCallable *callable) { + TTask *task = TTask::Create(ls); + std::shared_ptr ls2 = std::make_shared(ls.GetGC()); + ls2->Add(callable); + ls2->Add(task); + + ls.GetGC()->GetPool()->Schedule([ls2, callable, task](size_t s) -> void { + try { + task->SetSucceeded(callable->Call(*ls2, {})); + } catch (...) { + task->SetFailed(std::current_exception()); + } + }); + + return task; +} + +TTask *TTask::FromResult(GCList &ls, TObject v) { + TTask *task = TTask::Create(ls); + task->SetSucceeded(v); + return task; +} + +class TTaskCseObj { + std::shared_ptr gc; + TTask *task; + + public: + TTaskCseObj(std::shared_ptr gc, TTask *task) { + this->gc = gc; + this->task = task; + } + + void Invoke(std::shared_ptr shared_o, CallStackEntry *cse, + TObject o) { + try { + GCList ls(gc); + cse->Push(gc, o); + auto res = cse->Resume(ls); + CallStackEntry *cse2; + if (GetObjectHeap(res, cse2)) { + auto taskPiece = cse2->Pop(ls); + TTask *task; + if (GetObjectHeap(taskPiece, task)) { + auto em = TExternalMethod::Create( + ls, "", {"obj"}, + [cse2, task, shared_o]( + GCList &ls, std::vector args) -> TObject { + shared_o->Invoke(shared_o, cse2, + args.empty() ? (TObject)Undefined() + : args[0]); return nullptr; }); - em->watch.push_back(task); - em->watch.push_back(cse2); - - task->ContinueWith(em); - } - } - else { - this->task->SetSucceeded(res); - } - } catch(...) { - this->task->SetFailed(std::current_exception()); + em->watch.push_back(task); + em->watch.push_back(cse2); + + task->ContinueWith(em); } + } else { + this->task->SetSucceeded(res); } - }; - TTask* TTask::FromClosure(GCList& ls, TClosure* closure) - { - auto res = closure->Call(ls,{}); - CallStackEntry* ent; - if(GetObjectHeap(res,ent)) - { - return FromCallStackEntry(ls,ent); + } catch (...) { + this->task->SetFailed(std::current_exception()); } - return FromResult(ls,res); } - TTask* TTask::FromCallStackEntry(GCList& ls, CallStackEntry* ent) - { - TTask* task = TTask::Create(ls); - - //try { - GCList ls2(ls.GetGC()); - std::shared_ptr gc = ls.GetGC(); - - std::shared_ptr obj = std::make_shared(gc,task); - - - ls2.Add(task); - auto res = ent->Pop(ls2); - TTask* task2; - if(GetObjectHeap(res,task2)) - { - auto em = TExternalMethod::Create(ls2,"",{},[ent,task,obj](GCList& ls, std::vector args)->TObject { - - obj->Invoke(obj,ent,args.empty() ? (TObject)Undefined():args[0]); - - return nullptr; - }); - em->watch.push_back(task); - em->watch.push_back(ent); - - task2->ContinueWith(em); - } - - /*} catch(...) { - task->SetFailed(std::current_exception()); - }*/ - - return task; +}; +TTask *TTask::FromClosure(GCList &ls, TClosure *closure) { + auto res = closure->Call(ls, {}); + CallStackEntry *ent; + if (GetObjectHeap(res, ent)) { + return FromCallStackEntry(ls, ent); } -} \ No newline at end of file + return FromResult(ls, res); +} +TTask *TTask::FromCallStackEntry(GCList &ls, CallStackEntry *ent) { + TTask *task = TTask::Create(ls); + + // try { + GCList ls2(ls.GetGC()); + std::shared_ptr gc = ls.GetGC(); + + std::shared_ptr obj = std::make_shared(gc, task); + + ls2.Add(task); + auto res = ent->Pop(ls2); + TTask *task2; + if (GetObjectHeap(res, task2)) { + auto em = TExternalMethod::Create( + ls2, "", {}, + [ent, task, obj](GCList &ls, std::vector args) -> TObject { + obj->Invoke(obj, ent, + args.empty() ? (TObject)Undefined() : args[0]); + + return nullptr; + }); + em->watch.push_back(task); + em->watch.push_back(ent); + + task2->ContinueWith(em); + } + + /*} catch(...) { + task->SetFailed(std::current_exception()); + }*/ + + return task; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/class.cpp b/src/types/class.cpp index 2c1162d..a953a9a 100644 --- a/src/types/class.cpp +++ b/src/types/class.cpp @@ -1,247 +1,248 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - std::string TClassObject::TypeName() - { - std::string type = "class "; - type += this->name; - for(auto& item : this->inherit_tree) type += " : " + item; - return type; +namespace Tesses::CrossLang { +std::string TClassObject::TypeName() { + std::string type = "class "; + type += this->name; + for (auto &item : this->inherit_tree) + type += " : " + item; + return type; +} +TObject TClassObject::CallMethod(GCList &ls, std::string className, + std::string name, std::vector args) { + auto value = this->GetValue(className, name); + TCallable *callable; + if (GetObjectHeap(value, callable)) { + return callable->Call(ls, args); } - TObject TClassObject::CallMethod(GCList& ls, std::string className, std::string name,std::vector args) - { - auto value = this->GetValue(className,name); - TCallable* callable; - if(GetObjectHeap(value, callable)) - { - return callable->Call(ls,args); - } - return Undefined(); - } - TClassObjectEntry* TClassObject::GetEntry(std::string classN, std::string key) - { - for(auto& item : this->entries) - { - if(item.name == key) - { - switch(item.modifier) - { - case TClassModifier::Private: - if(classN != item.owner) return nullptr; - break; - case TClassModifier::Protected: - if(classN.empty()) return nullptr; - if(classN != item.owner) - { - for(auto inh : this->inherit_tree) - { - if(inh == classN) { - - return &item; - } - } - return nullptr; - } - - break; - default: - //DO NOTHING - break; - } - return &item; - } - } - return nullptr; - } - TClassObject* TClassObject::Create(GCList& ls, TFile* f, uint32_t classIndex, TEnvironment* env, std::vector args) - { - return Create(&ls,f,classIndex,env,args); - } - std::string JoinPeriod(std::vector& p) - { - std::string newStr = ""; - for(size_t i = 0; i < p.size(); i++) - { - if(i > 0) newStr.push_back('.'); - newStr += p[i]; - } - return newStr; - } - TClassObject* TClassObject::Create(GCList* ls, TFile* f, uint32_t classIndex, TEnvironment* env, std::vector args) - { - if(ls == nullptr) return nullptr; - TClassObject* obj = new TClassObject(); - obj->file = f; - obj->classIndex = classIndex; - obj->ogEnv=env; - obj->env = TClassEnvironment::Create(ls,env,obj); - obj->name = JoinPeriod(f->classes[classIndex].name); - bool hasToString=false; - - for(auto entry : f->classes[classIndex].entry) - { - if(entry.modifier == TClassModifier::Static) continue; - TClassObjectEntry ent; - ent.name = entry.name; - ent.modifier = entry.modifier; - ent.canSet = !entry.isFunction; - ent.owner = obj->name; - - if(entry.isFunction) - { - if(ent.name == "ToString") hasToString=true; - if(entry.isAbstract) - { - delete obj; - throw VMException("Method " + ent.name + " in " + ent.owner + " is abstract."); - } - else - { - auto clos = TClosure::Create(ls,obj->env,obj->file,entry.chunkId); - clos->documentation = entry.documentation; - clos->className = ent.owner; - ent.value = clos; - } - } - else { - if(entry.isAbstract) ent.value = Undefined(); - else { - auto clos = TClosure::Create(ls,obj->env,obj->file,entry.chunkId); - - clos->className=ent.owner; - ent.value = clos->Call(*ls,{}); - } - } - - obj->entries.push_back(ent); - } - - TClass* clsCur = &f->classes[classIndex]; - TRootEnvironment* rEnv = env->GetRootEnvironment(); - while(!clsCur->inherits.empty() && !(clsCur->inherits.size() == 1 && clsCur->inherits[0] == "ClassObject")) - { - obj->inherit_tree.push_back(JoinPeriod(clsCur->inherits)); - size_t idx; - if(rEnv->TryFindClass(clsCur->inherits,idx)) - { - auto file = rEnv->classes[idx].first; - clsCur = &rEnv->classes[idx].first->classes.at(rEnv->classes[idx].second); - auto ownerNow = JoinPeriod(clsCur->name); - for(auto entry : clsCur->entry) - { - if(entry.modifier == TClassModifier::Static) continue; - bool cont=false; - for(auto e : obj->entries) - if(e.name == entry.name) - { - cont=true; - break; - } - if(cont) continue; + return Undefined(); +} +TClassObjectEntry *TClassObject::GetEntry(std::string classN, std::string key) { + for (auto &item : this->entries) { + if (item.name == key) { + switch (item.modifier) { + case TClassModifier::Private: + if (classN != item.owner) + return nullptr; + break; + case TClassModifier::Protected: + if (classN.empty()) + return nullptr; + if (classN != item.owner) { + for (auto inh : this->inherit_tree) { + if (inh == classN) { - TClassObjectEntry ent; - ent.name = entry.name; - ent.modifier = entry.modifier; - ent.canSet = !entry.isFunction; - ent.owner = ownerNow; - - if(entry.isFunction) - { - - if(ent.name == "ToString") hasToString=true; - if(entry.isAbstract) - { - delete obj; - throw VMException("Method " + ent.name + " in " + ownerNow + " is abstract."); + return &item; + } } - else - { - auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId); + return nullptr; + } + + break; + default: + // DO NOTHING + break; + } + return &item; + } + } + return nullptr; +} +TClassObject *TClassObject::Create(GCList &ls, TFile *f, uint32_t classIndex, + TEnvironment *env, + std::vector args) { + return Create(&ls, f, classIndex, env, args); +} +std::string JoinPeriod(std::vector &p) { + std::string newStr = ""; + for (size_t i = 0; i < p.size(); i++) { + if (i > 0) + newStr.push_back('.'); + newStr += p[i]; + } + return newStr; +} +TClassObject *TClassObject::Create(GCList *ls, TFile *f, uint32_t classIndex, + TEnvironment *env, + std::vector args) { + if (ls == nullptr) + return nullptr; + TClassObject *obj = new TClassObject(); + obj->file = f; + obj->classIndex = classIndex; + obj->ogEnv = env; + obj->env = TClassEnvironment::Create(ls, env, obj); + obj->name = JoinPeriod(f->classes[classIndex].name); + + bool hasToString = false; + + for (auto &entry : f->classes[classIndex].entry) { + if (entry.modifier == TClassModifier::Static) + continue; + TClassObjectEntry ent; + ent.name = entry.name; + ent.modifier = entry.modifier; + ent.canSet = !entry.isFunction; + ent.owner = obj->name; + + if (entry.isFunction) { + if (entry.name == "ToString") + hasToString = true; + if (entry.isAbstract) { + delete obj; + throw VMException("Method " + ent.name + " in " + ent.owner + + " is abstract."); + } else { + auto clos = + TClosure::Create(ls, obj->env, obj->file, entry.chunkId); + clos->documentation = entry.documentation; + clos->className = ent.owner; + ent.value = clos; + } + } else { + if (entry.isAbstract) + ent.value = Undefined(); + else { + auto clos = + TClosure::Create(ls, obj->env, obj->file, entry.chunkId); + + clos->className = ent.owner; + ent.value = clos->Call(*ls, {}); + } + } + + obj->entries.push_back(ent); + } + + TClass *clsCur = &f->classes[classIndex]; + TRootEnvironment *rEnv = env->GetRootEnvironment(); + while (!clsCur->inherits.empty() && + !(clsCur->inherits.size() == 1 && + clsCur->inherits[0] == "ClassObject")) { + obj->inherit_tree.push_back(JoinPeriod(clsCur->inherits)); + size_t idx; + if (rEnv->TryFindClass(clsCur->inherits, idx)) { + auto file = rEnv->classes[idx].first; + clsCur = &rEnv->classes[idx].first->classes.at( + rEnv->classes[idx].second); + auto ownerNow = JoinPeriod(clsCur->name); + for (auto &entry : clsCur->entry) { + if (entry.modifier == TClassModifier::Static) + continue; + bool cont = false; + for (auto e : obj->entries) + if (e.name == entry.name) { + cont = true; + break; + } + if (cont) + continue; + + TClassObjectEntry ent; + ent.name = entry.name; + ent.modifier = entry.modifier; + ent.canSet = !entry.isFunction; + ent.owner = ownerNow; + + if (entry.isFunction) { + + if (entry.name == "ToString") + hasToString = true; + if (entry.isAbstract) { + delete obj; + throw VMException("Method " + ent.name + " in " + + ownerNow + " is abstract."); + } else { + auto clos = + TClosure::Create(ls, obj->env, file, entry.chunkId); clos->closure->name = obj->name + "::" + ent.name; clos->className = ownerNow; clos->documentation = entry.documentation; ent.value = clos; } - } - else { - if(entry.isAbstract) ent.value = Undefined(); + } else { + if (entry.isAbstract) + ent.value = Undefined(); else { - auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId); + auto clos = + TClosure::Create(ls, obj->env, file, entry.chunkId); clos->closure->name = obj->name + "::" + ent.name; clos->className = ownerNow; - ent.value = clos->Call(*ls,{}); + ent.value = clos->Call(*ls, {}); } - } - + } + obj->entries.push_back(ent); } - - } } - if(!hasToString) - { - TClassObjectEntry ent; - ent.canSet=false; - ent.modifier = TClassModifier::Public; - ent.name = "ToString"; - ent.owner = obj->name; - ent.value = TExternalMethod::Create(ls,"The ToString",{},[obj](GCList& ls,std::vector args)->TObject { return obj->TypeName();}); - obj->entries.push_back(ent); - } - TCallable* call=nullptr; - std::string fnName = f->classes[classIndex].name[f->classes[classIndex].name.size()-1]; - for(auto& item : obj->entries) - if(item.name == fnName) - { - GetObjectHeap(item.value,call); - break; - } - ls->Add(obj); - ls->GetGC()->Watch(obj); - - if(call != nullptr) call->Call(*ls,args); - return obj; } + if (!hasToString) { + TClassObjectEntry ent; + ent.canSet = false; + ent.modifier = TClassModifier::Public; + ent.name = "ToString"; + ent.owner = obj->name; + ent.value = TExternalMethod::Create( + ls, "The ToString", {}, + [obj](GCList &ls, std::vector args) -> TObject { + return obj->TypeName(); + }); + obj->entries.push_back(ent); + } + TCallable *call = nullptr; + std::string fnName = + f->classes[classIndex].name[f->classes[classIndex].name.size() - 1]; + for (auto &item : obj->entries) + if (item.name == fnName) { + GetObjectHeap(item.value, call); + break; + } + ls->Add(obj); + ls->GetGC()->Watch(obj); - TObject TClassObject::GetValue(std::string className, std::string key) - { - auto ent = GetEntry(className,key); - if(ent == nullptr) return Undefined(); - return ent->value; - } - void TClassObject::SetValue(std::string className, std::string key,TObject value) - { - auto ent = GetEntry(className,key); - if(ent == nullptr) return; - if(ent->canSet) ent->value = value; - } - bool TClassObject::HasValue(std::string className,std::string key) - { - auto ent = GetEntry(className,key); - return ent != nullptr; - - } - bool TClassObject::HasField(std::string className,std::string key) - { - auto ent = GetEntry(className,key); - if(ent == nullptr) return false; - return ent->canSet; - } - bool TClassObject::HasMethod(std::string className,std::string key) - { - auto ent = GetEntry(className,key); - if(ent == nullptr) return false; - TCallable* call; - return GetObjectHeap(ent->value,call); - } - void TClassObject::Mark() - { - if(this->marked) return; - this->marked=true; - this->env->Mark(); - this->file->Mark(); - this->ogEnv->Mark(); - for(auto& item : this->entries) GC::Mark(item.value); - - } -} \ No newline at end of file + if (call != nullptr) + call->Call(*ls, args); + return obj; +} + +TObject TClassObject::GetValue(std::string className, std::string key) { + auto ent = GetEntry(className, key); + if (ent == nullptr) + return Undefined(); + return ent->value; +} +void TClassObject::SetValue(std::string className, std::string key, + TObject value) { + auto ent = GetEntry(className, key); + if (ent == nullptr) + return; + if (ent->canSet) + ent->value = value; +} +bool TClassObject::HasValue(std::string className, std::string key) { + auto ent = GetEntry(className, key); + return ent != nullptr; +} +bool TClassObject::HasField(std::string className, std::string key) { + auto ent = GetEntry(className, key); + if (ent == nullptr) + return false; + return ent->canSet; +} +bool TClassObject::HasMethod(std::string className, std::string key) { + auto ent = GetEntry(className, key); + if (ent == nullptr) + return false; + TCallable *call; + return GetObjectHeap(ent->value, call); +} +void TClassObject::Mark() { + if (this->marked) + return; + this->marked = true; + this->env->Mark(); + this->file->Mark(); + this->ogEnv->Mark(); + for (auto &item : this->entries) + GC::Mark(item.value); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/classenvironment.cpp b/src/types/classenvironment.cpp index bf64532..e5af5e5 100644 --- a/src/types/classenvironment.cpp +++ b/src/types/classenvironment.cpp @@ -1,130 +1,142 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { - bool TClassEnvironment::HasConstForSet(std::string key) - { - if(this->env->HasVariableRecurse(key)) - { - return this->env->HasConstForSet(key); - } - return false; +bool TClassEnvironment::HasConstForSet(std::string key) { + if (this->env->HasVariableRecurse(key)) { + return this->env->HasConstForSet(key); } - TClassEnvironment* TClassEnvironment::Create(GCList* gc,TEnvironment* env,TClassObject* obj) - { - - TClassEnvironment* env2=new TClassEnvironment(env,obj); - - std::shared_ptr _gc = gc->GetGC(); - gc->Add(env2); - _gc->Watch(env2); - return env2; - } - TClassEnvironment* TClassEnvironment::Create(GCList& gc,TEnvironment* env,TClassObject* obj) - { + return false; +} +TClassEnvironment *TClassEnvironment::Create(GCList *gc, TEnvironment *env, + TClassObject *obj) { - TClassEnvironment* env2=new TClassEnvironment(env,obj); - - std::shared_ptr _gc = gc.GetGC(); - gc.Add(env2); - _gc->Watch(env2); - return env2; - } - TClassEnvironment::TClassEnvironment(TEnvironment* env,TClassObject* obj) - { - this->env = env; - this->clsObj=obj; - } - bool TClassEnvironment::HasVariable(std::string key) - { - if(key == "this") return true; - if(this->clsObj->HasValue(current_function == nullptr ? "" : current_function->callable->className,key)) return true; - return false; - } - bool TClassEnvironment::HasVariableRecurse(std::string key) - { - if(HasVariable(key)) return true; - return this->env->HasVariableRecurse(key); - } - bool TClassEnvironment::HasVariableOrFieldRecurse(std::string key, bool setting) - { - if(key == "this") return true; - std::string clsName = current_function == nullptr ? "" : current_function->callable->className; - if(clsObj->HasMethod(clsName,(setting ? "set" : "get")+key)) return true; - if(clsObj->HasValue(clsName,key)) return true; - return env->HasVariableOrFieldRecurse(key,setting); - } - - TObject TClassEnvironment::GetVariable(std::string key) - { - if(key == "this") return this->clsObj; - - std::string clsName = current_function == nullptr ? "" : current_function->callable->className; - - if(clsObj->HasValue(clsName,key)) return this->clsObj->GetValue(clsName,key); - return env->GetVariable(key); - } - void TClassEnvironment::SetVariable(std::string key, TObject value) - { - if(key == "this") return; - - std::string clsName = current_function == nullptr ? "" : current_function->callable->className; - - if(clsObj->HasValue(clsName,key)) - { - this->clsObj->SetValue(clsName,key,value); - return; - } - this->env->SetVariable(key,value); + TClassEnvironment *env2 = new TClassEnvironment(env, obj); + + std::shared_ptr _gc = gc->GetGC(); + gc->Add(env2); + _gc->Watch(env2); + return env2; +} +TClassEnvironment *TClassEnvironment::Create(GCList &gc, TEnvironment *env, + TClassObject *obj) { + + TClassEnvironment *env2 = new TClassEnvironment(env, obj); + + std::shared_ptr _gc = gc.GetGC(); + gc.Add(env2); + _gc->Watch(env2); + return env2; +} +TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) { + this->env = env; + this->clsObj = obj; +} +bool TClassEnvironment::HasVariable(std::string key) { + if (key == "this") + return true; + if (this->clsObj->HasValue(current_function == nullptr + ? "" + : current_function->callable->className, + key)) + return true; + return false; +} +bool TClassEnvironment::HasVariableRecurse(std::string key) { + if (HasVariable(key)) + return true; + return this->env->HasVariableRecurse(key); +} +bool TClassEnvironment::HasVariableOrFieldRecurse(std::string key, + bool setting) { + if (key == "this") + return true; + std::string clsName = current_function == nullptr + ? "" + : current_function->callable->className; + if (clsObj->HasMethod(clsName, (setting ? "set" : "get") + key)) + return true; + if (clsObj->HasValue(clsName, key)) + return true; + return env->HasVariableOrFieldRecurse(key, setting); +} + +TObject TClassEnvironment::GetVariable(std::string key) { + if (key == "this") + return this->clsObj; + + std::string clsName = current_function == nullptr + ? "" + : current_function->callable->className; + + if (clsObj->HasValue(clsName, key)) + return this->clsObj->GetValue(clsName, key); + return env->GetVariable(key); +} +void TClassEnvironment::SetVariable(std::string key, TObject value) { + if (key == "this") + return; + + std::string clsName = current_function == nullptr + ? "" + : current_function->callable->className; + + if (clsObj->HasValue(clsName, key)) { + this->clsObj->SetValue(clsName, key, value); return; } - TObject TClassEnvironment::GetVariable(GCList& ls, std::string key) - { - if(key == "this") return this->clsObj; - - std::string clsName = current_function == nullptr ? "" : current_function->callable->className; - if(this->clsObj->HasMethod(clsName,"get"+key)) - { - auto res=this->clsObj->GetValue(clsName,"get"+key); - TCallable* call; - if(GetObjectHeap(res,call)) return call->Call(ls,{}); - } - if(this->clsObj->HasValue(clsName,key)) return this->clsObj->GetValue(clsName,key); - return this->env->GetVariable(ls,key); - } - TObject TClassEnvironment::SetVariable(GCList& ls, std::string key, TObject v) - { - if(key == "this") return this->clsObj; - - std::string clsName = current_function == nullptr ? "" : current_function->callable->className; - if(this->clsObj->HasMethod(clsName,"set"+key)) - { - auto res=this->clsObj->GetValue(clsName,"set"+key); - TCallable* call; - if(GetObjectHeap(res,call)) return call->Call(ls,{v}); - } - if(this->clsObj->HasValue(clsName,key)) { this->clsObj->SetValue(clsName,key,v); return v;} - - return this->env->SetVariable(ls,key,v); - } - - void TClassEnvironment::DeclareVariable(std::string key, TObject value) - { + this->env->SetVariable(key, value); + return; +} +TObject TClassEnvironment::GetVariable(GCList &ls, std::string key) { + if (key == "this") + return this->clsObj; + std::string clsName = current_function == nullptr + ? "" + : current_function->callable->className; + if (this->clsObj->HasMethod(clsName, "get" + key)) { + auto res = this->clsObj->GetValue(clsName, "get" + key); + TCallable *call; + if (GetObjectHeap(res, call)) + return call->Call(ls, {}); } - TRootEnvironment* TClassEnvironment::GetRootEnvironment() - { - return this->env->GetRootEnvironment(); + if (this->clsObj->HasValue(clsName, key)) + return this->clsObj->GetValue(clsName, key); + return this->env->GetVariable(ls, key); +} +TObject TClassEnvironment::SetVariable(GCList &ls, std::string key, TObject v) { + if (key == "this") + return this->clsObj; + + std::string clsName = current_function == nullptr + ? "" + : current_function->callable->className; + if (this->clsObj->HasMethod(clsName, "set" + key)) { + auto res = this->clsObj->GetValue(clsName, "set" + key); + TCallable *call; + if (GetObjectHeap(res, call)) + return call->Call(ls, {v}); } - TEnvironment* TClassEnvironment::GetParentEnvironment() - { - return this->env; + if (this->clsObj->HasValue(clsName, key)) { + this->clsObj->SetValue(clsName, key, v); + return v; } - - void TClassEnvironment::Mark() - { - if(this->marked) return; - this->marked=true; - this->clsObj->Mark(); - this->env->Mark(); - for(auto item : this->defers) item->Mark(); - } -} \ No newline at end of file + + return this->env->SetVariable(ls, key, v); +} + +void TClassEnvironment::DeclareVariable(std::string key, TObject value) {} +TRootEnvironment *TClassEnvironment::GetRootEnvironment() { + return this->env->GetRootEnvironment(); +} +TEnvironment *TClassEnvironment::GetParentEnvironment() { return this->env; } + +void TClassEnvironment::Mark() { + if (this->marked) + return; + this->marked = true; + this->clsObj->Mark(); + this->env->Mark(); + for (auto item : this->defers) + item->Mark(); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/closure.cpp b/src/types/closure.cpp index 8e12ad7..055cfb3 100644 --- a/src/types/closure.cpp +++ b/src/types/closure.cpp @@ -1,99 +1,97 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { - TArgWrapper* TArgWrapper::Create(GCList& ls, TCallable* callable) - { - TArgWrapper* argWrapper = new TArgWrapper(); - argWrapper->callable = callable; - std::shared_ptr gc = ls.GetGC(); - ls.Add(argWrapper); - gc->Watch(argWrapper); - return argWrapper; - } - TArgWrapper* TArgWrapper::Create(GCList* ls, TCallable* callable) - { - TArgWrapper* argWrapper = new TArgWrapper(); - argWrapper->callable = callable; - std::shared_ptr gc = ls->GetGC(); - ls->Add(argWrapper); - gc->Watch(argWrapper); - return argWrapper; - } - TObject TArgWrapper::Call(GCList& ls,std::vector args) - { - auto cse = current_function; - TList* argList = TList::Create(ls); - argList->items = args; - TObject v=this->callable->Call(ls,{argList}); - current_function = cse; - return v; - } - void TArgWrapper::Mark() - { - if(this->marked) return; - this->marked = true; - this->callable->Mark(); - GC::Mark(this->tag); - } - void TCallable::Mark() - { - if(this->marked) return; - this->marked=true; - GC::Mark(this->tag); - } - void TClosure::Mark() - { - if(this->marked) return; - this->marked=true; - this->file->Mark(); - this->env->Mark(); - this->closure->Mark(); - GC::Mark(this->tag); - } - TClosure* TClosure::Create(GCList& ls,TEnvironment* env,TFile* file,uint32_t chunkId,bool ownScope) - { - TClosure* closure = new TClosure(); - closure->className=""; - closure->ownScope=ownScope; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(closure); - _gc->Watch(closure); - closure->chunkId = chunkId; - if(chunkId < file->chunks.size()) +TArgWrapper *TArgWrapper::Create(GCList &ls, TCallable *callable) { + TArgWrapper *argWrapper = new TArgWrapper(); + argWrapper->callable = callable; + std::shared_ptr gc = ls.GetGC(); + ls.Add(argWrapper); + gc->Watch(argWrapper); + return argWrapper; +} +TArgWrapper *TArgWrapper::Create(GCList *ls, TCallable *callable) { + TArgWrapper *argWrapper = new TArgWrapper(); + argWrapper->callable = callable; + std::shared_ptr gc = ls->GetGC(); + ls->Add(argWrapper); + gc->Watch(argWrapper); + return argWrapper; +} +TObject TArgWrapper::Call(GCList &ls, std::vector args) { + auto cse = current_function; + TList *argList = TList::Create(ls); + argList->items = args; + TObject v = this->callable->Call(ls, {argList}); + current_function = cse; + return v; +} +void TArgWrapper::Mark() { + if (this->marked) + return; + this->marked = true; + this->callable->Mark(); + GC::Mark(this->tag); +} +void TCallable::Mark() { + if (this->marked) + return; + this->marked = true; + GC::Mark(this->tag); +} +void TClosure::Mark() { + if (this->marked) + return; + this->marked = true; + this->file->Mark(); + this->env->Mark(); + this->closure->Mark(); + GC::Mark(this->tag); +} +TClosure *TClosure::Create(GCList &ls, TEnvironment *env, TFile *file, + uint32_t chunkId, bool ownScope) { + TClosure *closure = new TClosure(); + closure->className = ""; + closure->ownScope = ownScope; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(closure); + _gc->Watch(closure); + closure->chunkId = chunkId; + if (chunkId < file->chunks.size()) closure->closure = file->chunks[chunkId]; - else throw VMException("ChunkId out of bounds."); - closure->env = env; - closure->file = file; - - return closure; - } - TClosure* TClosure::Create(GCList* ls,TEnvironment* env,TFile* file,uint32_t chunkId,bool ownScope) - { - TClosure* closure = new TClosure(); - closure->className=""; - closure->ownScope=ownScope; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(closure); - _gc->Watch(closure); - closure->chunkId = chunkId; - if(chunkId < file->chunks.size()) + else + throw VMException("ChunkId out of bounds."); + closure->env = env; + closure->file = file; + + return closure; +} +TClosure *TClosure::Create(GCList *ls, TEnvironment *env, TFile *file, + uint32_t chunkId, bool ownScope) { + TClosure *closure = new TClosure(); + closure->className = ""; + closure->ownScope = ownScope; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(closure); + _gc->Watch(closure); + closure->chunkId = chunkId; + if (chunkId < file->chunks.size()) closure->closure = file->chunks[chunkId]; - else throw VMException("ChunkId out of bounds."); - closure->env = env; - closure->file = file; - - return closure; - } - - TObject TClosure::Call(GCList& ls,std::vector args) - { - auto cse = current_function; - InterperterThread* thrd=InterperterThread::Create(ls); - thrd->AddCallStackEntry(ls,this, args); + else + throw VMException("ChunkId out of bounds."); + closure->env = env; + closure->file = file; - thrd->Execute(ls.GetGC()); + return closure; +} - TObject v= thrd->call_stack_entries[0]->Pop(ls); - current_function = cse; - return v; - } -} \ No newline at end of file +TObject TClosure::Call(GCList &ls, std::vector args) { + auto cse = current_function; + InterperterThread *thrd = InterperterThread::Create(ls); + thrd->AddCallStackEntry(ls, this, args); + + thrd->Execute(ls.GetGC()); + + TObject v = thrd->call_stack_entries[0]->Pop(ls); + current_function = cse; + return v; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/dictionary.cpp b/src/types/dictionary.cpp index d5a17b8..34edcd9 100644 --- a/src/types/dictionary.cpp +++ b/src/types/dictionary.cpp @@ -1,221 +1,206 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang { - TDynamicDictionary* TDynamicDictionary::Create(GCList& ls,TCallable* callable) - { +namespace Tesses::CrossLang { +TDynamicDictionary *TDynamicDictionary::Create(GCList &ls, + TCallable *callable) { - TDynamicDictionary* dict=new TDynamicDictionary(); - dict->cb = callable; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(dict); - _gc->Watch(dict); - return dict; - } - TDynamicDictionary* TDynamicDictionary::Create(GCList* ls,TCallable* callable) - { - TDynamicDictionary* dict=new TDynamicDictionary(); - dict->cb = callable; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(dict); - _gc->Watch(dict); - return dict; - } + TDynamicDictionary *dict = new TDynamicDictionary(); + dict->cb = callable; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(dict); + _gc->Watch(dict); + return dict; +} +TDynamicDictionary *TDynamicDictionary::Create(GCList *ls, + TCallable *callable) { + TDynamicDictionary *dict = new TDynamicDictionary(); + dict->cb = callable; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(dict); + _gc->Watch(dict); + return dict; +} - void TDynamicDictionary::Mark() - { - if(this->marked) return; - this->marked=true; - this->cb->Mark(); - } +void TDynamicDictionary::Mark() { + if (this->marked) + return; + this->marked = true; + this->cb->Mark(); +} - TObject TDynamicDictionary::GetField(GCList& ls, std::string key) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "GetField"); - dict->SetValue("Key", key); - ls.GetGC()->BarrierEnd(); - return this->cb->Call(ls,{dict}); - } +TObject TDynamicDictionary::GetField(GCList &ls, std::string key) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "GetField"); + dict->SetValue("Key", key); + ls.GetGC()->BarrierEnd(); + return this->cb->Call(ls, {dict}); +} - TObject TDynamicDictionary::SetField(GCList& ls, std::string key, TObject value) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "SetField"); - dict->SetValue("Key", key); - dict->SetValue("Value", value); - ls.GetGC()->BarrierEnd(); - return this->cb->Call(ls,{dict}); - } +TObject TDynamicDictionary::SetField(GCList &ls, std::string key, + TObject value) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "SetField"); + dict->SetValue("Key", key); + dict->SetValue("Value", value); + ls.GetGC()->BarrierEnd(); + return this->cb->Call(ls, {dict}); +} - TObject TDynamicDictionary::CallMethod(GCList& ls, std::string name, std::vector args) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "CallMethod"); - dict->SetValue("Name", name); - auto argVal = TList::Create(ls); - argVal->items = args; - dict->SetValue("Arguments", argVal); - ls.GetGC()->BarrierEnd(); - return this->cb->Call(ls,{dict}); - } +TObject TDynamicDictionary::CallMethod(GCList &ls, std::string name, + std::vector args) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "CallMethod"); + dict->SetValue("Name", name); + auto argVal = TList::Create(ls); + argVal->items = args; + dict->SetValue("Arguments", argVal); + ls.GetGC()->BarrierEnd(); + return this->cb->Call(ls, {dict}); +} - TEnumerator* TDynamicDictionary::GetEnumerator(GCList& ls) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "GetEnumerator"); +TEnumerator *TDynamicDictionary::GetEnumerator(GCList &ls) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "GetEnumerator"); - ls.GetGC()->BarrierEnd(); + ls.GetGC()->BarrierEnd(); - return TEnumerator::CreateFromObject(ls,this->cb->Call(ls,{dict})); - } - bool TDictionary::MethodExists(GCList& ls,std::string method) - { - ls.GetGC()->BarrierBegin(); - auto r = this->GetValue(method); - TCallable* callable; - bool res = GetObjectHeap(r,callable); - ls.GetGC()->BarrierEnd(); - return res; - } - bool TDynamicDictionary::MethodExists(GCList& ls,std::string name) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "MethodExists"); - dict->SetValue("Name", name); + return TEnumerator::CreateFromObject(ls, this->cb->Call(ls, {dict})); +} +bool TDictionary::MethodExists(GCList &ls, std::string method) { + ls.GetGC()->BarrierBegin(); + auto r = this->GetValue(method); + TCallable *callable; + bool res = GetObjectHeap(r, callable); + ls.GetGC()->BarrierEnd(); + return res; +} +bool TDynamicDictionary::MethodExists(GCList &ls, std::string name) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "MethodExists"); + dict->SetValue("Name", name); - ls.GetGC()->BarrierEnd(); + ls.GetGC()->BarrierEnd(); - auto res = this->cb->Call(ls,{dict}); - bool r2; - if(GetObject(res,r2)) return r2; - return false; - } + auto res = this->cb->Call(ls, {dict}); + bool r2; + if (GetObject(res, r2)) + return r2; + return false; +} - TDynamicDictionary::~TDynamicDictionary() - { +TDynamicDictionary::~TDynamicDictionary() {} +TObject TDictionary::CallMethod(GCList &ls, std::string key, + std::vector args) { + ls.GetGC()->BarrierBegin(); + auto res = this->GetValue(key); + ls.GetGC()->BarrierEnd(); + TCallable *callable; - } - TObject TDictionary::CallMethod(GCList& ls, std::string key, std::vector args) - { - ls.GetGC()->BarrierBegin(); - auto res = this->GetValue(key); - ls.GetGC()->BarrierEnd(); - TCallable* callable; + if (GetObjectHeap(res, callable)) { + auto closure = dynamic_cast(callable); + if (closure != nullptr && !closure->closure->args.empty() && + closure->closure->args.front() == "this") { + std::vector args2; + args2.push_back(this); + args2.insert(args2.end(), args.begin(), args.end()); + return closure->Call(ls, args2); - if(GetObjectHeap(res,callable)) - { - auto closure = dynamic_cast(callable); - if(closure != nullptr && !closure->closure->args.empty() && closure->closure->args.front() == "this") - { - std::vector args2; - args2.push_back(this); - args2.insert(args2.end(), args.begin(),args.end()); - return closure->Call(ls,args2); - - } - else - { - return callable->Call(ls,args); - - } - } - return Undefined(); - } - TObject TDictionary::CallMethodWithFatalError(GCList& ls, std::string key, std::vector args) - { - ls.GetGC()->BarrierBegin(); - auto res = this->GetValue(key); - ls.GetGC()->BarrierEnd(); - TCallable* callable; - - if(GetObjectHeap(res,callable)) - { - auto closure = dynamic_cast(callable); - if(closure != nullptr && !closure->closure->args.empty() && closure->closure->args.front() == "this") - { - std::vector args2; - args2.push_back(this); - args2.insert(args2.end(), args.begin(),args.end()); - return closure->CallWithFatalError(ls,args2); - - } - else - { - return callable->CallWithFatalError(ls,args); - - } - } - return Undefined(); - } - - void TDictionary::DeclareFunction(std::shared_ptr gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb) - { - gc->BarrierBegin(); - GCList ls(gc); - this->SetValue(key, TExternalMethod::Create(ls,documentation,argNames,cb)); - gc->BarrierEnd(); - } - - void TDictionary::DeclareFunction(std::shared_ptr gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb,std::function destroy) - { - gc->BarrierBegin(); - GCList ls(gc); - this->SetValue(key, TExternalMethod::Create(ls,documentation,argNames,cb,destroy)); - gc->BarrierEnd(); - } - - TObject TDictionary::GetValue(std::string key) - { - if(this->items.empty()) return Undefined(); - if(this->items.count(key) > 0) - return this->items[key]; - return Undefined(); - } - void TDictionary::SetValue(std::string key, TObject value) - { - if(std::holds_alternative(value)) - { - if(this->items.count(key) > 0) - this->items.erase(key); - } - else - { - this->items[key] = value; + } else { + return callable->Call(ls, args); } } - bool TDictionary::HasValue(std::string key) - { - return this->items.count(key) > 0; - } - void TDictionary::Mark() - { - if(this->marked) return; - this->marked = true; - for(auto item : this->items) - { - GC::Mark(item.second); + return Undefined(); +} +TObject TDictionary::CallMethodWithFatalError(GCList &ls, std::string key, + std::vector args) { + ls.GetGC()->BarrierBegin(); + auto res = this->GetValue(key); + ls.GetGC()->BarrierEnd(); + TCallable *callable; + + if (GetObjectHeap(res, callable)) { + auto closure = dynamic_cast(callable); + if (closure != nullptr && !closure->closure->args.empty() && + closure->closure->args.front() == "this") { + std::vector args2; + args2.push_back(this); + args2.insert(args2.end(), args.begin(), args.end()); + return closure->CallWithFatalError(ls, args2); + + } else { + return callable->CallWithFatalError(ls, args); } } - TDictionary* TDictionary::Create(GCList* gc) - { - TDictionary* dict=new TDictionary(); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(dict); - _gc->Watch(dict); - return dict; - } - TDictionary* TDictionary::Create(GCList& gc) - { - TDictionary* dict=new TDictionary(); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(dict); - _gc->Watch(dict); - return dict; - } + return Undefined(); +} -}; +void TDictionary::DeclareFunction( + std::shared_ptr gc, std::string key, std::string documentation, + std::vector argNames, + std::function args)> cb) { + gc->BarrierBegin(); + GCList ls(gc); + this->SetValue(key, + TExternalMethod::Create(ls, documentation, argNames, cb)); + gc->BarrierEnd(); +} + +void TDictionary::DeclareFunction( + std::shared_ptr gc, std::string key, std::string documentation, + std::vector argNames, + std::function args)> cb, + std::function destroy) { + gc->BarrierBegin(); + GCList ls(gc); + this->SetValue( + key, TExternalMethod::Create(ls, documentation, argNames, cb, destroy)); + gc->BarrierEnd(); +} + +TObject TDictionary::GetValue(std::string key) { + if (this->items.empty()) + return Undefined(); + if (this->items.count(key) > 0) + return this->items[key]; + return Undefined(); +} +void TDictionary::SetValue(std::string key, TObject value) { + if (std::holds_alternative(value)) { + if (this->items.count(key) > 0) + this->items.erase(key); + } else { + this->items[key] = value; + } +} +bool TDictionary::HasValue(std::string key) { + return this->items.count(key) > 0; +} +void TDictionary::Mark() { + if (this->marked) + return; + this->marked = true; + for (auto item : this->items) { + GC::Mark(item.second); + } +} +TDictionary *TDictionary::Create(GCList *gc) { + TDictionary *dict = new TDictionary(); + std::shared_ptr _gc = gc->GetGC(); + gc->Add(dict); + _gc->Watch(dict); + return dict; +} +TDictionary *TDictionary::Create(GCList &gc) { + TDictionary *dict = new TDictionary(); + std::shared_ptr _gc = gc.GetGC(); + gc.Add(dict); + _gc->Watch(dict); + return dict; +} + +}; // namespace Tesses::CrossLang diff --git a/src/types/embed.cpp b/src/types/embed.cpp index e9f775e..24fb6ce 100644 --- a/src/types/embed.cpp +++ b/src/types/embed.cpp @@ -2,166 +2,146 @@ namespace Tesses::CrossLang { - EmbedStream::EmbedStream(std::shared_ptr gc, TFile* file, uint32_t resource) - { - this->offset = 0; - this->resource = resource; - this->file = CreateMarkedTObject(gc,file); - } - bool EmbedStream::CanRead() - { - TFile* file; - if(GetObjectHeap(this->file->GetObject(),file)) - { - if(this->resource >= file->resources.size()) return false; - if(this->offset >= file->resources[this->resource].size()) return false; - return true; - } - return false; - } - bool EmbedStream::CanSeek() - { +EmbedStream::EmbedStream(std::shared_ptr gc, TFile *file, + uint32_t resource) { + this->offset = 0; + this->resource = resource; + this->file = CreateMarkedTObject(gc, file); +} +bool EmbedStream::CanRead() { + TFile *file; + if (GetObjectHeap(this->file->GetObject(), file)) { + if (this->resource >= file->resources.size()) + return false; + if (this->offset >= file->resources[this->resource].size()) + return false; return true; } - bool EmbedStream::EndOfStream() - { - return !CanRead(); - } - size_t EmbedStream::Read(uint8_t* buff, size_t len) - { - TFile* file; - - if(GetObjectHeap(this->file->GetObject(),file)) - { - if(this->resource >= file->resources.size()) return 0; - auto flen = file->resources[this->resource].size(); - if(this->offset >= flen) return 0; - - len = std::min(len, std::min( - flen, - flen - this->offset - )); + return false; +} +bool EmbedStream::CanSeek() { return true; } +bool EmbedStream::EndOfStream() { return !CanRead(); } +size_t EmbedStream::Read(uint8_t *buff, size_t len) { + TFile *file; - memcpy(buff,file->resources[this->resource].data() + this->offset,len); - this->offset += len; - return len; - } - return 0; + if (GetObjectHeap(this->file->GetObject(), file)) { + if (this->resource >= file->resources.size()) + return 0; + auto flen = file->resources[this->resource].size(); + if (this->offset >= flen) + return 0; + + len = std::min(len, std::min(flen, flen - this->offset)); + + memcpy(buff, file->resources[this->resource].data() + this->offset, + len); + this->offset += len; + return len; } - int64_t EmbedStream::GetPosition() - { - return (int64_t)this->offset; + return 0; +} +int64_t EmbedStream::GetPosition() { return (int64_t)this->offset; } +int64_t EmbedStream::GetLength() { + TFile *file; + + if (GetObjectHeap(this->file->GetObject(), file)) { + if (this->resource >= file->resources.size()) + return 0; + return (int64_t)file->resources[this->resource].size(); } - int64_t EmbedStream::GetLength() - { - TFile* file; - - if(GetObjectHeap(this->file->GetObject(),file)) - { - if(this->resource >= file->resources.size()) return 0; - return (int64_t)file->resources[this->resource].size(); + return 0; +} +void EmbedStream::Seek(int64_t pos, + Tesses::Framework::Streams::SeekOrigin whence) { + switch (whence) { + case Tesses::Framework::Streams::SeekOrigin::Begin: + this->offset = (uint32_t)pos; + break; + case Tesses::Framework::Streams::SeekOrigin::Current: { + int64_t cur = this->offset; + cur += pos; + this->offset = (uint32_t)cur; + } break; + case Tesses::Framework::Streams::SeekOrigin::End: { + TFile *file; + + if (GetObjectHeap(this->file->GetObject(), file)) { + if (this->resource >= file->resources.size()) + return; + int64_t cur = (int64_t)file->resources[this->resource].size(); + cur += pos; + this->offset = (uint32_t)cur; } - return 0; + break; } - void EmbedStream::Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence) - { - switch(whence) - { - case Tesses::Framework::Streams::SeekOrigin::Begin: - this->offset = (uint32_t)pos; - break; - case Tesses::Framework::Streams::SeekOrigin::Current: - { - int64_t cur = this->offset; - cur += pos; - this->offset = (uint32_t)cur; - } - break; - case Tesses::Framework::Streams::SeekOrigin::End: - { - TFile* file; - - if(GetObjectHeap(this->file->GetObject(),file)) - { - if(this->resource >= file->resources.size()) return; - int64_t cur = (int64_t)file->resources[this->resource].size(); - cur += pos; - this->offset = (uint32_t)cur; - } - break; - } - } } - TObject EmbedDirectory::getEntry(Tesses::Framework::Filesystem::VFSPath path) - { - path = path.CollapseRelativeParents(); - auto curEntry = this->dir->GetObject(); - for(auto item : path.path) - { - TDictionary* dict; - if(GetObjectHeap(curEntry,dict) && dict->HasValue(item)) - { - curEntry = dict->GetValue(item); - continue; //don't want to return undefined now do we - } - return Undefined(); - } - return curEntry; - } - - std::shared_ptr EmbedDirectory::OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode) - { - if(mode != "r" && mode != "rb") return nullptr; - - auto ent = getEntry(path); - TCallable* call; - if(GetObjectHeap(ent,call)) - { - GCList ls(this->dir->GetGC()); - auto fileO = call->Call(ls,{}); - std::shared_ptr strm; - if(GetObject(fileO,strm)) return strm; +} +TObject EmbedDirectory::getEntry(Tesses::Framework::Filesystem::VFSPath path) { + path = path.CollapseRelativeParents(); + auto curEntry = this->dir->GetObject(); + for (auto item : path.path) { + TDictionary *dict; + if (GetObjectHeap(curEntry, dict) && dict->HasValue(item)) { + curEntry = dict->GetValue(item); + continue; // don't want to return undefined now do we } + return Undefined(); + } + return curEntry; +} + +std::shared_ptr +EmbedDirectory::OpenFile(Tesses::Framework::Filesystem::VFSPath path, + std::string mode) { + if (mode != "r" && mode != "rb") return nullptr; - } - - bool EmbedDirectory::Stat(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Filesystem::StatData& data) - { - auto ent = getEntry(path); + auto ent = getEntry(path); + TCallable *call; + if (GetObjectHeap(ent, call)) { + GCList ls(this->dir->GetGC()); + auto fileO = call->Call(ls, {}); + std::shared_ptr strm; + if (GetObject(fileO, strm)) + return strm; + } + return nullptr; +} - TDictionary* dict; - if(GetObjectHeap(ent,dict)) - { - data.Size = 0; - data.Mode = Tesses::Framework::Filesystem::MODE_DIRECTORY | 0755; - data.BlockCount = 0; - data.BlockSize = 0; - data.Device = 0; - data.DeviceId = 0; - data.GroupId = 0; - data.HardLinks = 1; - data.Inode = 0; - data.LastAccess = Tesses::Framework::Date::DateTime(0); - data.LastModified = Tesses::Framework::Date::DateTime(0); - data.LastStatus = Tesses::Framework::Date::DateTime(0); - data.UserId = 0; - - return true; - } - TCallable* cal; - if(GetObjectHeap(ent, cal)) - { - GCList ls(this->dir->GetGC()); - auto fileO= cal->Call(ls, {}); - std::shared_ptr strm; - if(GetObject(fileO,strm)) { +bool EmbedDirectory::Stat(Tesses::Framework::Filesystem::VFSPath path, + Tesses::Framework::Filesystem::StatData &data) { + auto ent = getEntry(path); + + TDictionary *dict; + if (GetObjectHeap(ent, dict)) { + data.Size = 0; + data.Mode = Tesses::Framework::Filesystem::MODE_DIRECTORY | 0755; + data.BlockCount = 0; + data.BlockSize = 0; + data.Device = 0; + data.DeviceId = 0; + data.GroupId = 0; + data.HardLinks = 1; + data.Inode = 0; + data.LastAccess = Tesses::Framework::Date::DateTime(0); + data.LastModified = Tesses::Framework::Date::DateTime(0); + data.LastStatus = Tesses::Framework::Date::DateTime(0); + data.UserId = 0; + + return true; + } + TCallable *cal; + if (GetObjectHeap(ent, cal)) { + GCList ls(this->dir->GetGC()); + auto fileO = cal->Call(ls, {}); + std::shared_ptr strm; + if (GetObject(fileO, strm)) { data.Size = (uint64_t)strm->GetLength(); - data.Mode = Tesses::Framework::Filesystem::MODE_REGULAR | 0755; + data.Mode = Tesses::Framework::Filesystem::MODE_REGULAR | 0755; data.BlockSize = 512; data.BlockCount = data.Size / data.BlockSize; - + data.Device = 0; data.DeviceId = 0; data.GroupId = 0; @@ -171,84 +151,70 @@ namespace Tesses::CrossLang { data.LastModified = Tesses::Framework::Date::DateTime(0); data.LastStatus = Tesses::Framework::Date::DateTime(0); data.UserId = 0; - + return true; - } } - return false; - } + } + return false; +} - class DICT_DIRENUM - { - GCList ls; - TDictionary* dict; - std::map::iterator current; - bool hasStarted = false; - public: - std::string GetCurrent() - { - return this->current->first; - } - DICT_DIRENUM(std::shared_ptr gc, TDictionary* dict) : ls(gc), dict(dict) - { - ls.Add(dict); - } - bool MoveNext() - { - if(!this->hasStarted) - { - this->hasStarted=true; - this->current = this->dict->items.begin(); - return !this->dict->items.empty(); - } - else - { - this->current++; - return this->current != this->dict->items.end(); - } - } +class DICT_DIRENUM { + GCList ls; + TDictionary *dict; + std::map::iterator current; + bool hasStarted = false; - }; - - - Tesses::Framework::Filesystem::VFSPathEnumerator EmbedDirectory::EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path) - { - auto ent = getEntry(path); - TDictionary* dict; - if(GetObjectHeap(ent,dict)) - { - DICT_DIRENUM* dir2 = new DICT_DIRENUM(this->dir->GetGC(), dict); - - Tesses::Framework::Filesystem::VFSPathEnumerator er( - [dir2,path](Tesses::Framework::Filesystem::VFSPath& path2)->bool { - if(dir2->MoveNext()) - { - path2 = path / dir2->GetCurrent(); - return true; - } - return false; - }, - [dir2]()->void { - delete dir2; - } - ); - - return er; + public: + std::string GetCurrent() { return this->current->first; } + DICT_DIRENUM(std::shared_ptr gc, TDictionary *dict) + : ls(gc), dict(dict) { + ls.Add(dict); + } + bool MoveNext() { + if (!this->hasStarted) { + this->hasStarted = true; + this->current = this->dict->items.begin(); + return !this->dict->items.empty(); + } else { + this->current++; + return this->current != this->dict->items.end(); } - return Tesses::Framework::Filesystem::VFSPathEnumerator(); } +}; - EmbedDirectory::EmbedDirectory(std::shared_ptr gc, TDictionary* dict) - { - this->dir = CreateMarkedTObject(gc, dict); +Tesses::Framework::Filesystem::VFSPathEnumerator +EmbedDirectory::EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path) { + auto ent = getEntry(path); + TDictionary *dict; + if (GetObjectHeap(ent, dict)) { + DICT_DIRENUM *dir2 = new DICT_DIRENUM(this->dir->GetGC(), dict); + + Tesses::Framework::Filesystem::VFSPathEnumerator er( + [dir2, + path](Tesses::Framework::Filesystem::VFSPath &path2) -> bool { + if (dir2->MoveNext()) { + path2 = path / dir2->GetCurrent(); + return true; + } + return false; + }, + [dir2]() -> void { delete dir2; }); + + return er; } - - std::string EmbedDirectory::VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path) - { - return path.ToString(); - } - Tesses::Framework::Filesystem::VFSPath EmbedDirectory::SystemToVFSPath(std::string path) - { - return path; - } -} \ No newline at end of file + return Tesses::Framework::Filesystem::VFSPathEnumerator(); +} + +EmbedDirectory::EmbedDirectory(std::shared_ptr gc, TDictionary *dict) { + this->dir = CreateMarkedTObject(gc, dict); +} + +std::string +EmbedDirectory::VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path) { + return path.ToString(); +} +Tesses::Framework::Filesystem::VFSPath +EmbedDirectory::SystemToVFSPath(std::string path) { + return path; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/externalmethod.cpp b/src/types/externalmethod.cpp index 6777413..c97dd12 100644 --- a/src/types/externalmethod.cpp +++ b/src/types/externalmethod.cpp @@ -1,54 +1,64 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - TExternalMethod::TExternalMethod(std::function args)> cb,std::string documentation, std::vector argNames,std::function destroy) - { - - this->cb = cb; - this->args = argNames; - this->documentation = documentation; - this->destroy = destroy; - } - TExternalMethod* TExternalMethod::Create(GCList& ls,std::string documentation,std::vector argNames,std::function args)> cb,std::function destroy) - { - auto gc = ls.GetGC(); - TExternalMethod* method = new TExternalMethod(cb,documentation,argNames,destroy); - ls.Add(method); - gc->Watch(method); - return method; - } - TExternalMethod* TExternalMethod::Create(GCList* ls,std::string documentation, std::vector argNames,std::function args)> cb,std::function destroy) - { - auto gc = ls->GetGC(); - TExternalMethod* method = new TExternalMethod(cb,documentation,argNames,destroy); - ls->Add(method); - gc->Watch(method); - return method; - } - TExternalMethod* TExternalMethod::Create(GCList& ls,std::string documentation, std::vector argNames,std::function args)> cb) - { - auto gc = ls.GetGC(); - TExternalMethod* method = new TExternalMethod(cb,documentation,argNames,[]()->void{}); - ls.Add(method); - gc->Watch(method); - return method; - } - TExternalMethod* TExternalMethod::Create(GCList* ls,std::string documentation, std::vector argNames,std::function args)> cb) - { - auto gc = ls->GetGC(); - TExternalMethod* method = new TExternalMethod(cb,documentation,argNames,[]()->void{}); - ls->Add(method); - gc->Watch(method); - return method; - } - TObject TExternalMethod::Call(GCList& ls, std::vector args) - { - if(cb == nullptr) return Undefined(); - return this->cb(ls,args); - } - TExternalMethod::~TExternalMethod() - { - if(this->destroy != nullptr) +namespace Tesses::CrossLang { +TExternalMethod::TExternalMethod( + std::function args)> cb, + std::string documentation, std::vector argNames, + std::function destroy) { + + this->cb = cb; + this->args = argNames; + this->documentation = documentation; + this->destroy = destroy; +} +TExternalMethod *TExternalMethod::Create( + GCList &ls, std::string documentation, std::vector argNames, + std::function args)> cb, + std::function destroy) { + auto gc = ls.GetGC(); + TExternalMethod *method = + new TExternalMethod(cb, documentation, argNames, destroy); + ls.Add(method); + gc->Watch(method); + return method; +} +TExternalMethod *TExternalMethod::Create( + GCList *ls, std::string documentation, std::vector argNames, + std::function args)> cb, + std::function destroy) { + auto gc = ls->GetGC(); + TExternalMethod *method = + new TExternalMethod(cb, documentation, argNames, destroy); + ls->Add(method); + gc->Watch(method); + return method; +} +TExternalMethod *TExternalMethod::Create( + GCList &ls, std::string documentation, std::vector argNames, + std::function args)> cb) { + auto gc = ls.GetGC(); + TExternalMethod *method = + new TExternalMethod(cb, documentation, argNames, []() -> void {}); + ls.Add(method); + gc->Watch(method); + return method; +} +TExternalMethod *TExternalMethod::Create( + GCList *ls, std::string documentation, std::vector argNames, + std::function args)> cb) { + auto gc = ls->GetGC(); + TExternalMethod *method = + new TExternalMethod(cb, documentation, argNames, []() -> void {}); + ls->Add(method); + gc->Watch(method); + return method; +} +TObject TExternalMethod::Call(GCList &ls, std::vector args) { + if (cb == nullptr) + return Undefined(); + return this->cb(ls, args); +} +TExternalMethod::~TExternalMethod() { + if (this->destroy != nullptr) this->destroy(); - } -} \ No newline at end of file +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/ittr.cpp b/src/types/ittr.cpp index 2ca87f6..d471258 100644 --- a/src/types/ittr.cpp +++ b/src/types/ittr.cpp @@ -1,433 +1,393 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - bool TYieldEnumerator::MoveNext(std::shared_ptr ls) - { - CallStackEntry* ent; - GCList ls2(ls); - if(!this->hasStarted) - { - TClosure* clos; - if(!GetObjectHeap(this->enumerator,clos)) return false; - auto _enumerator= clos->Call(ls2,{}); +namespace Tesses::CrossLang { +bool TYieldEnumerator::MoveNext(std::shared_ptr ls) { + CallStackEntry *ent; + GCList ls2(ls); + if (!this->hasStarted) { + TClosure *clos; + if (!GetObjectHeap(this->enumerator, clos)) + return false; + auto _enumerator = clos->Call(ls2, {}); + ls->BarrierBegin(); + this->enumerator = _enumerator; + this->hasStarted = true; + ls->BarrierEnd(); + } else { + + if (GetObjectHeap(this->enumerator, ent)) { + auto _enumerator = ent->Resume(ls2); ls->BarrierBegin(); this->enumerator = _enumerator; - this->hasStarted=true; ls->BarrierEnd(); - } - else { - - if(GetObjectHeap(this->enumerator,ent)) - { - auto _enumerator= ent->Resume(ls2); - ls->BarrierBegin(); - this->enumerator = _enumerator; - ls->BarrierEnd(); - - } else return false; - } - - if(GetObjectHeap(this->enumerator,ent)) - { - ls->BarrierBegin(); - this->current = ent->Pop(ls2); - ls->BarrierEnd(); - return true; - } - return false; - } - TObject TYieldEnumerator::GetCurrent(GCList& ls) - { - ls.Add(this->current); - return this->current; - } - void TYieldEnumerator::Mark() - { - if(this->marked) return; - this->marked=true; - GC::Mark(this->current); - GC::Mark(this->enumerator); - } - TYieldEnumerator* TYieldEnumerator::Create(GCList& ls,TObject v) - { - TYieldEnumerator* yieldEnum = new TYieldEnumerator(); - yieldEnum->current=nullptr; - yieldEnum->hasStarted=false; - yieldEnum->enumerator = v; - - std::shared_ptr _gc = ls.GetGC(); - ls.Add(yieldEnum); - _gc->Watch(yieldEnum); - return yieldEnum; - } - TYieldEnumerator* TYieldEnumerator::Create(GCList* ls,TObject v) - { - TYieldEnumerator* yieldEnum = new TYieldEnumerator(); - yieldEnum->current=nullptr; - yieldEnum->hasStarted=false; - yieldEnum->enumerator = v; - - std::shared_ptr _gc = ls->GetGC(); - ls->Add(yieldEnum); - _gc->Watch(yieldEnum); - return yieldEnum; + } else + return false; } - - bool TCustomEnumerator::MoveNext(std::shared_ptr ls) - { - GCList ls2(ls); - auto res = this->dict->CallMethod(ls2,"MoveNext",{}); - bool out; - if(GetObject(res,out)) return out; - return false; - } - TObject TCustomEnumerator::GetCurrent(GCList& ls) - { - TObject res=Undefined(); - ls.GetGC()->BarrierBegin(); - auto getCurrent = this->dict->GetValue("getCurrent"); - TCallable* call; - if(GetObjectHeap(getCurrent,call)) - { - ls.GetGC()->BarrierEnd(); - res=call->Call(ls,{}); - ls.GetGC()->BarrierBegin(); - }else{ - res=this->dict->GetValue("Current"); - } + if (GetObjectHeap(this->enumerator, ent)) { + ls->BarrierBegin(); + this->current = ent->Pop(ls2); + ls->BarrierEnd(); + return true; + } + return false; +} +TObject TYieldEnumerator::GetCurrent(GCList &ls) { + ls.Add(this->current); + return this->current; +} +void TYieldEnumerator::Mark() { + if (this->marked) + return; + this->marked = true; + GC::Mark(this->current); + GC::Mark(this->enumerator); +} +TYieldEnumerator *TYieldEnumerator::Create(GCList &ls, TObject v) { + TYieldEnumerator *yieldEnum = new TYieldEnumerator(); + yieldEnum->current = nullptr; + yieldEnum->hasStarted = false; + yieldEnum->enumerator = v; + + std::shared_ptr _gc = ls.GetGC(); + ls.Add(yieldEnum); + _gc->Watch(yieldEnum); + return yieldEnum; +} +TYieldEnumerator *TYieldEnumerator::Create(GCList *ls, TObject v) { + + TYieldEnumerator *yieldEnum = new TYieldEnumerator(); + yieldEnum->current = nullptr; + yieldEnum->hasStarted = false; + yieldEnum->enumerator = v; + + std::shared_ptr _gc = ls->GetGC(); + ls->Add(yieldEnum); + _gc->Watch(yieldEnum); + return yieldEnum; +} + +bool TCustomEnumerator::MoveNext(std::shared_ptr ls) { + GCList ls2(ls); + auto res = this->dict->CallMethod(ls2, "MoveNext", {}); + bool out; + if (GetObject(res, out)) + return out; + return false; +} +TObject TCustomEnumerator::GetCurrent(GCList &ls) { + TObject res = Undefined(); + ls.GetGC()->BarrierBegin(); + auto getCurrent = this->dict->GetValue("getCurrent"); + TCallable *call; + if (GetObjectHeap(getCurrent, call)) { ls.GetGC()->BarrierEnd(); - return res; + res = call->Call(ls, {}); + ls.GetGC()->BarrierBegin(); + } else { + + res = this->dict->GetValue("Current"); } - void TCustomEnumerator::Mark() - { - if(this->marked) return; - this->dict->Mark(); - } - TCustomEnumerator* TCustomEnumerator::Create(GCList* ls, TDictionary* dict) - { - TCustomEnumerator* customEnum = new TCustomEnumerator(); - customEnum->dict = dict; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(customEnum); - _gc->Watch(customEnum); - return customEnum; - } - TCustomEnumerator* TCustomEnumerator::Create(GCList& ls, TDictionary* dict) - { - TCustomEnumerator* customEnum = new TCustomEnumerator(); - customEnum->dict = dict; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(customEnum); - _gc->Watch(customEnum); - return customEnum; - } - TEnumerator* TEnumerator::CreateFromObject(GCList& ls, TObject obj) - { - std::string str; - TList* mls; - TDynamicList* dynList; - TDynamicDictionary* dynDict; - TDictionary* dict; - TEnumerator* enumerator; - TQueryable* q; - if(GetObject(obj,str)) - { - return TStringEnumerator::Create(ls, str); - } - else if(GetObjectHeap(obj,mls)) - { - return TListEnumerator::Create(ls,mls); - } - else if(GetObjectHeap(obj,dynList)) - { - return TDynamicListEnumerator::Create(ls,dynList); - } - else if(GetObjectHeap(obj,dict)) - { - auto res=dict->CallMethod(ls,"GetEnumerator",{}); - if(GetObjectHeap(res,dict)) - { - return TCustomEnumerator::Create(ls,dict); - } - else if(GetObjectHeap(res,enumerator)) - { - return enumerator; - } - } - else if(GetObjectHeap(obj, q)) - { - return q->GetEnumerator(ls); - } - else if(GetObjectHeap(obj, enumerator)) - { + ls.GetGC()->BarrierEnd(); + return res; +} +void TCustomEnumerator::Mark() { + if (this->marked) + return; + this->dict->Mark(); +} +TCustomEnumerator *TCustomEnumerator::Create(GCList *ls, TDictionary *dict) { + TCustomEnumerator *customEnum = new TCustomEnumerator(); + customEnum->dict = dict; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(customEnum); + _gc->Watch(customEnum); + return customEnum; +} +TCustomEnumerator *TCustomEnumerator::Create(GCList &ls, TDictionary *dict) { + TCustomEnumerator *customEnum = new TCustomEnumerator(); + customEnum->dict = dict; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(customEnum); + _gc->Watch(customEnum); + return customEnum; +} +TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) { + std::string str; + TList *mls; + TDynamicList *dynList; + TDynamicDictionary *dynDict; + TDictionary *dict; + TEnumerator *enumerator; + TQueryable *q; + if (GetObject(obj, str)) { + return TStringEnumerator::Create(ls, str); + } else if (GetObjectHeap(obj, mls)) { + return TListEnumerator::Create(ls, mls); + } else if (GetObjectHeap(obj, dynList)) { + return TDynamicListEnumerator::Create(ls, dynList); + } else if (GetObjectHeap(obj, dict)) { + auto res = dict->CallMethod(ls, "GetEnumerator", {}); + if (GetObjectHeap(res, dict)) { + return TCustomEnumerator::Create(ls, dict); + } else if (GetObjectHeap(res, enumerator)) { return enumerator; } - return nullptr; + } else if (GetObjectHeap(obj, q)) { + return q->GetEnumerator(ls); + } else if (GetObjectHeap(obj, enumerator)) { + return enumerator; } - TVFSPathEnumerator* TVFSPathEnumerator::Create(GCList& ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) - { - TVFSPathEnumerator* vfspathe = new TVFSPathEnumerator(); - vfspathe->enumerator = enumerator; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(vfspathe); - _gc->Watch(vfspathe); - return vfspathe; + return nullptr; +} +TVFSPathEnumerator *TVFSPathEnumerator::Create( + GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) { + TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator(); + vfspathe->enumerator = enumerator; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(vfspathe); + _gc->Watch(vfspathe); + return vfspathe; +} +TVFSPathEnumerator *TVFSPathEnumerator::Create( + GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) { + TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator(); + vfspathe->enumerator = enumerator; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(vfspathe); + _gc->Watch(vfspathe); + return vfspathe; +} +bool TVFSPathEnumerator::MoveNext(std::shared_ptr ls) { + return enumerator.MoveNext(); +} +TObject TVFSPathEnumerator::GetCurrent(GCList &ls) { + return enumerator.Current; +} +TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList &ls, + TDictionary *dict) { + TDictionaryEnumerator *dicte = new TDictionaryEnumerator(); + dicte->dict = dict; + dicte->hasStarted = false; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(dicte); + _gc->Watch(dicte); + return dicte; +} +TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList *ls, + TDictionary *dict) { + TDictionaryEnumerator *dicte = new TDictionaryEnumerator(); + dicte->dict = dict; + dicte->hasStarted = false; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(dicte); + _gc->Watch(dicte); + return dicte; +} + +bool TDictionaryEnumerator::MoveNext(std::shared_ptr ls) { + if (!this->hasStarted) { + this->hasStarted = true; + this->ittr = this->dict->items.begin(); + return !this->dict->items.empty(); + } else { + this->ittr++; + return this->ittr != this->dict->items.end(); } - TVFSPathEnumerator* TVFSPathEnumerator::Create(GCList* ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) - { - TVFSPathEnumerator* vfspathe = new TVFSPathEnumerator(); - vfspathe->enumerator = enumerator; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(vfspathe); - _gc->Watch(vfspathe); - return vfspathe; - } - bool TVFSPathEnumerator::MoveNext(std::shared_ptr ls) - { - return enumerator.MoveNext(); - } - TObject TVFSPathEnumerator::GetCurrent(GCList& ls) - { - return enumerator.Current; - } - TDictionaryEnumerator* TDictionaryEnumerator::Create(GCList& ls, TDictionary* dict) - { - TDictionaryEnumerator* dicte=new TDictionaryEnumerator(); - dicte->dict = dict; - dicte->hasStarted=false; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(dicte); - _gc->Watch(dicte); - return dicte; - } - TDictionaryEnumerator* TDictionaryEnumerator::Create(GCList* ls, TDictionary* dict) - { - TDictionaryEnumerator* dicte=new TDictionaryEnumerator(); - dicte->dict = dict; - dicte->hasStarted=false; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(dicte); - _gc->Watch(dicte); - return dicte; - } - - bool TDictionaryEnumerator::MoveNext(std::shared_ptr ls) - { - if(!this->hasStarted) - { - this->hasStarted=true; - this->ittr = this->dict->items.begin(); - return !this->dict->items.empty(); - } - else - { - this->ittr++; - return this->ittr != this->dict->items.end(); - } - } - TObject TDictionaryEnumerator::GetCurrent(GCList& ls) - { - if(!this->hasStarted) return Undefined(); - if(this->ittr != this->dict->items.end()) - { - ls.GetGC()->BarrierBegin(); - std::string key = this->ittr->first; - TObject value = this->ittr->second; - auto kvp = TDictionary::Create(ls); - kvp->SetValue("Key",key); - kvp->SetValue("Value",value); - ls.GetGC()->BarrierEnd(); - return kvp; - } +} +TObject TDictionaryEnumerator::GetCurrent(GCList &ls) { + if (!this->hasStarted) return Undefined(); - } - void TDictionaryEnumerator::Mark() - { - if(this->marked) return; - this->marked=true; - this->dict->Mark(); - } - - - TListEnumerator* TListEnumerator::Create(GCList& ls, TList* list) - { - TListEnumerator* liste=new TListEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(liste); - _gc->Watch(liste); - return liste; - } - TListEnumerator* TListEnumerator::Create(GCList* ls, TList* list) - { - TListEnumerator* liste=new TListEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(liste); - _gc->Watch(liste); - return liste; - } - bool TListEnumerator::MoveNext(std::shared_ptr ls) - { - this->index++; - return this->index >= 0 && this->index < this->ls->Count(); - } - TObject TListEnumerator::GetCurrent(GCList& ls) - { - - if(this->index < -1) return nullptr; - if(this->ls->Count() == 0) return nullptr; - if(this->index >= this->ls->Count()) return nullptr; + if (this->ittr != this->dict->items.end()) { ls.GetGC()->BarrierBegin(); - TObject o = this->ls->Get(index); + std::string key = this->ittr->first; + TObject value = this->ittr->second; + auto kvp = TDictionary::Create(ls); + kvp->SetValue("Key", key); + kvp->SetValue("Value", value); ls.GetGC()->BarrierEnd(); - return o; - } - void TListEnumerator::Mark() - { - if(this->marked) return; - this->marked = true; - this->ls->Mark(); + return kvp; } + return Undefined(); +} +void TDictionaryEnumerator::Mark() { + if (this->marked) + return; + this->marked = true; + this->dict->Mark(); +} - TAssociativeArrayEnumerator* TAssociativeArrayEnumerator::Create(GCList& ls, TAssociativeArray* list) - { - TAssociativeArrayEnumerator* liste=new TAssociativeArrayEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(liste); - _gc->Watch(liste); - return liste; - } - TAssociativeArrayEnumerator* TAssociativeArrayEnumerator::Create(GCList* ls, TAssociativeArray* list) - { - TAssociativeArrayEnumerator* liste=new TAssociativeArrayEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(liste); - _gc->Watch(liste); - return liste; - } - bool TAssociativeArrayEnumerator::MoveNext(std::shared_ptr ls) - { - this->index++; - return this->index >= 0 && this->index < this->ls->Count(); - } - TObject TAssociativeArrayEnumerator::GetCurrent(GCList& ls) - { - - if(this->index < -1) return nullptr; - if(this->ls->Count() == 0) return nullptr; - if(this->index >= this->ls->Count()) return nullptr; - ls.GetGC()->BarrierBegin(); - TDictionary* dict = TDictionary::Create(ls); - dict->SetValue("Key",this->ls->GetKey(this->index)); - dict->SetValue("Value",this->ls->GetValue(this->index)); - ls.GetGC()->BarrierEnd(); - return dict; - } - void TAssociativeArrayEnumerator::Mark() - { - if(this->marked) return; - this->marked = true; - this->ls->Mark(); - } +TListEnumerator *TListEnumerator::Create(GCList &ls, TList *list) { + TListEnumerator *liste = new TListEnumerator(); + liste->ls = list; + liste->index = -1; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(liste); + _gc->Watch(liste); + return liste; +} +TListEnumerator *TListEnumerator::Create(GCList *ls, TList *list) { + TListEnumerator *liste = new TListEnumerator(); + liste->ls = list; + liste->index = -1; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(liste); + _gc->Watch(liste); + return liste; +} +bool TListEnumerator::MoveNext(std::shared_ptr ls) { + this->index++; + return this->index >= 0 && this->index < this->ls->Count(); +} +TObject TListEnumerator::GetCurrent(GCList &ls) { - - - TDynamicListEnumerator* TDynamicListEnumerator::Create(GCList& ls, TDynamicList* list) - { - TDynamicListEnumerator* liste=new TDynamicListEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(liste); - _gc->Watch(liste); - return liste; - } - TDynamicListEnumerator* TDynamicListEnumerator::Create(GCList* ls, TDynamicList* list) - { - TDynamicListEnumerator* liste=new TDynamicListEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(liste); - _gc->Watch(liste); - return liste; - } - bool TDynamicListEnumerator::MoveNext(std::shared_ptr ls) - { - this->index++; - GCList ls2(ls); - return this->index >= 0 && this->index < this->ls->Count(ls2); - } - TObject TDynamicListEnumerator::GetCurrent(GCList& ls) - { - - if(this->index < -1) return nullptr; - auto r = this->ls->Count(ls); - if(r == 0) return nullptr; - if(this->index >= r) return nullptr; - ls.GetGC()->BarrierBegin(); - TObject o = this->ls->GetAt(ls,index); - ls.GetGC()->BarrierEnd(); - return o; - } - void TDynamicListEnumerator::Mark() - { - if(this->marked) return; - this->marked = true; - this->ls->Mark(); - } - - - TStringEnumerator* TStringEnumerator::Create(GCList& ls,std::string str) - { - TStringEnumerator* stre=new TStringEnumerator(); - stre->str = str; - stre->hasStarted=false; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(stre); - _gc->Watch(stre); - return stre; - } - TStringEnumerator* TStringEnumerator::Create(GCList* ls,std::string str) - { - TStringEnumerator* stre=new TStringEnumerator(); - stre->str = str; - stre->hasStarted=false; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(stre); - _gc->Watch(stre); - return stre; - } - bool TStringEnumerator::MoveNext(std::shared_ptr ls) - { - if(!this->hasStarted) - { - this->hasStarted=true; - this->index = 0; - return !this->str.empty(); - } - else - { - if(this->index >= this->str.size()) return false; - this->index++; - return this->index < this->str.size(); - } - } - TObject TStringEnumerator::GetCurrent(GCList& ls) - { - if(!this->hasStarted) return nullptr; - if(this->index < this->str.size()) return this->str[this->index]; + if (this->index < -1) return nullptr; - } + if (this->ls->Count() == 0) + return nullptr; + if (this->index >= this->ls->Count()) + return nullptr; + ls.GetGC()->BarrierBegin(); + TObject o = this->ls->Get(index); + ls.GetGC()->BarrierEnd(); + return o; +} +void TListEnumerator::Mark() { + if (this->marked) + return; + this->marked = true; + this->ls->Mark(); +} -}; \ No newline at end of file +TAssociativeArrayEnumerator * +TAssociativeArrayEnumerator::Create(GCList &ls, TAssociativeArray *list) { + TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator(); + liste->ls = list; + liste->index = -1; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(liste); + _gc->Watch(liste); + return liste; +} +TAssociativeArrayEnumerator * +TAssociativeArrayEnumerator::Create(GCList *ls, TAssociativeArray *list) { + TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator(); + liste->ls = list; + liste->index = -1; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(liste); + _gc->Watch(liste); + return liste; +} +bool TAssociativeArrayEnumerator::MoveNext(std::shared_ptr ls) { + this->index++; + return this->index >= 0 && this->index < this->ls->Count(); +} +TObject TAssociativeArrayEnumerator::GetCurrent(GCList &ls) { + + if (this->index < -1) + return nullptr; + if (this->ls->Count() == 0) + return nullptr; + if (this->index >= this->ls->Count()) + return nullptr; + ls.GetGC()->BarrierBegin(); + TDictionary *dict = TDictionary::Create(ls); + dict->SetValue("Key", this->ls->GetKey(this->index)); + dict->SetValue("Value", this->ls->GetValue(this->index)); + ls.GetGC()->BarrierEnd(); + return dict; +} +void TAssociativeArrayEnumerator::Mark() { + if (this->marked) + return; + this->marked = true; + this->ls->Mark(); +} + +TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList &ls, + TDynamicList *list) { + TDynamicListEnumerator *liste = new TDynamicListEnumerator(); + liste->ls = list; + liste->index = -1; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(liste); + _gc->Watch(liste); + return liste; +} +TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList *ls, + TDynamicList *list) { + TDynamicListEnumerator *liste = new TDynamicListEnumerator(); + liste->ls = list; + liste->index = -1; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(liste); + _gc->Watch(liste); + return liste; +} +bool TDynamicListEnumerator::MoveNext(std::shared_ptr ls) { + this->index++; + GCList ls2(ls); + return this->index >= 0 && this->index < this->ls->Count(ls2); +} +TObject TDynamicListEnumerator::GetCurrent(GCList &ls) { + + if (this->index < -1) + return nullptr; + auto r = this->ls->Count(ls); + if (r == 0) + return nullptr; + if (this->index >= r) + return nullptr; + ls.GetGC()->BarrierBegin(); + TObject o = this->ls->GetAt(ls, index); + ls.GetGC()->BarrierEnd(); + return o; +} +void TDynamicListEnumerator::Mark() { + if (this->marked) + return; + this->marked = true; + this->ls->Mark(); +} + +TStringEnumerator *TStringEnumerator::Create(GCList &ls, std::string str) { + TStringEnumerator *stre = new TStringEnumerator(); + stre->str = str; + stre->hasStarted = false; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(stre); + _gc->Watch(stre); + return stre; +} +TStringEnumerator *TStringEnumerator::Create(GCList *ls, std::string str) { + TStringEnumerator *stre = new TStringEnumerator(); + stre->str = str; + stre->hasStarted = false; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(stre); + _gc->Watch(stre); + return stre; +} +bool TStringEnumerator::MoveNext(std::shared_ptr ls) { + if (!this->hasStarted) { + this->hasStarted = true; + this->index = 0; + return !this->str.empty(); + } else { + if (this->index >= this->str.size()) + return false; + this->index++; + return this->index < this->str.size(); + } +} +TObject TStringEnumerator::GetCurrent(GCList &ls) { + if (!this->hasStarted) + return nullptr; + if (this->index < this->str.size()) + return this->str[this->index]; + return nullptr; +} + +}; // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/list.cpp b/src/types/list.cpp index d1c2b1c..37615c2 100644 --- a/src/types/list.cpp +++ b/src/types/list.cpp @@ -1,223 +1,184 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { - TDynamicList* TDynamicList::Create(GCList& ls,TCallable* callable) - { - TDynamicList* list=new TDynamicList(); - list->cb = callable; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(list); - _gc->Watch(list); - return list; - } - TDynamicList* TDynamicList::Create(GCList* ls,TCallable* callable) - { - TDynamicList* list=new TDynamicList(); - list->cb = callable; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(list); - _gc->Watch(list); - return list; - } +TDynamicList *TDynamicList::Create(GCList &ls, TCallable *callable) { + TDynamicList *list = new TDynamicList(); + list->cb = callable; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(list); + _gc->Watch(list); + return list; +} +TDynamicList *TDynamicList::Create(GCList *ls, TCallable *callable) { + TDynamicList *list = new TDynamicList(); + list->cb = callable; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(list); + _gc->Watch(list); + return list; +} - void TDynamicList::Mark() - { - if(this->marked) return; - this->marked=true; - this->cb->Mark(); - } +void TDynamicList::Mark() { + if (this->marked) + return; + this->marked = true; + this->cb->Mark(); +} - int64_t TDynamicList::Count(GCList& ls) - { - - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Count"); - ls.GetGC()->BarrierEnd(); - auto res = cb->Call(ls,{dict}); - int64_t n; - if(GetObject(res,n)) return n; - return 0; - } - TObject TDynamicList::Add(GCList& ls, TObject v) - { - - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Add"); - dict->SetValue("Value",v); - ls.GetGC()->BarrierEnd(); - return cb->Call(ls,{dict}); - - } - TObject TDynamicList::Insert(GCList& ls, int64_t index, TObject v) - { - - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Insert"); - dict->SetValue("Index",index); - dict->SetValue("Value",v); - ls.GetGC()->BarrierEnd(); - return cb->Call(ls,{dict}); - - } - TObject TDynamicList::Clear(GCList& ls) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Clear"); - ls.GetGC()->BarrierEnd(); - return cb->Call(ls,{dict}); - } - TObject TDynamicList::Remove(GCList& ls, TObject obj) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Remove"); - dict->SetValue("Value", obj); - ls.GetGC()->BarrierEnd(); - - return cb->Call(ls,{dict}); - } - TObject TDynamicList::RemoveAllEqual(GCList& ls, TObject obj) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "RemoveAllEqual"); - dict->SetValue("Value", obj); - ls.GetGC()->BarrierEnd(); - - return cb->Call(ls,{dict}); - } - TObject TDynamicList::RemoveAt(GCList& ls, int64_t index) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "RemoveAt"); - dict->SetValue("Index", index); - ls.GetGC()->BarrierEnd(); - - return cb->Call(ls,{dict}); - } - TObject TDynamicList::ToString(GCList& ls) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "ToString"); - ls.GetGC()->BarrierEnd(); - - return cb->Call(ls,{dict}); - } +int64_t TDynamicList::Count(GCList &ls) { - TObject TDynamicList::GetAt(GCList& ls, int64_t index) - { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "Count"); + ls.GetGC()->BarrierEnd(); + auto res = cb->Call(ls, {dict}); + int64_t n; + if (GetObject(res, n)) + return n; + return 0; +} +TObject TDynamicList::Add(GCList &ls, TObject v) { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "GetAt"); - dict->SetValue("Index",index); - ls.GetGC()->BarrierEnd(); - return cb->Call(ls,{dict}); - } + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "Add"); + dict->SetValue("Value", v); + ls.GetGC()->BarrierEnd(); + return cb->Call(ls, {dict}); +} +TObject TDynamicList::Insert(GCList &ls, int64_t index, TObject v) { - TObject TDynamicList::SetAt(GCList& ls, int64_t index, TObject val) - { - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "SetAt"); - dict->SetValue("Index",index); - dict->SetValue("Value",val); - ls.GetGC()->BarrierEnd(); - return cb->Call(ls,{dict}); - } + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "Insert"); + dict->SetValue("Index", index); + dict->SetValue("Value", v); + ls.GetGC()->BarrierEnd(); + return cb->Call(ls, {dict}); +} +TObject TDynamicList::Clear(GCList &ls) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "Clear"); + ls.GetGC()->BarrierEnd(); + return cb->Call(ls, {dict}); +} +TObject TDynamicList::Remove(GCList &ls, TObject obj) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "Remove"); + dict->SetValue("Value", obj); + ls.GetGC()->BarrierEnd(); - TDynamicList::~TDynamicList() - { + return cb->Call(ls, {dict}); +} +TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "RemoveAllEqual"); + dict->SetValue("Value", obj); + ls.GetGC()->BarrierEnd(); - } - + return cb->Call(ls, {dict}); +} +TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "RemoveAt"); + dict->SetValue("Index", index); + ls.GetGC()->BarrierEnd(); - TByteArray* TByteArray::Create(GCList& ls) - { - TByteArray* arr=new TByteArray(); - std::shared_ptr _gc = ls.GetGC(); - ls.Add(arr); - _gc->Watch(arr); - return arr; - } + return cb->Call(ls, {dict}); +} +TObject TDynamicList::ToString(GCList &ls) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "ToString"); + ls.GetGC()->BarrierEnd(); - TByteArray* TByteArray::Create(GCList* ls) - { - TByteArray* arr=new TByteArray(); - std::shared_ptr _gc = ls->GetGC(); - ls->Add(arr); - _gc->Watch(arr); - return arr; + return cb->Call(ls, {dict}); +} + +TObject TDynamicList::GetAt(GCList &ls, int64_t index) { + + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "GetAt"); + dict->SetValue("Index", index); + ls.GetGC()->BarrierEnd(); + return cb->Call(ls, {dict}); +} + +TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "SetAt"); + dict->SetValue("Index", index); + dict->SetValue("Value", val); + ls.GetGC()->BarrierEnd(); + return cb->Call(ls, {dict}); +} + +TDynamicList::~TDynamicList() {} + +TByteArray *TByteArray::Create(GCList &ls) { + TByteArray *arr = new TByteArray(); + std::shared_ptr _gc = ls.GetGC(); + ls.Add(arr); + _gc->Watch(arr); + return arr; +} + +TByteArray *TByteArray::Create(GCList *ls) { + TByteArray *arr = new TByteArray(); + std::shared_ptr _gc = ls->GetGC(); + ls->Add(arr); + _gc->Watch(arr); + return arr; +} +TList *TList::Create(GCList *gc) { + TList *list = new TList(); + std::shared_ptr _gc = gc->GetGC(); + gc->Add(list); + _gc->Watch(list); + return list; +} +TList *TList::Create(GCList &gc) { + TList *list = new TList(); + std::shared_ptr _gc = gc.GetGC(); + gc.Add(list); + _gc->Watch(list); + return list; +} +void TList::Add(TObject value) { this->items.push_back(value); } +void TList::Set(int64_t index, TObject value) { + if (index >= 0 && index < this->Count()) { + this->items[index] = value; } - TList* TList::Create(GCList* gc) - { - TList* list=new TList(); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(list); - _gc->Watch(list); - return list; +} +TObject TList::Get(int64_t index) { + if (index >= 0 && index < this->Count()) { + return this->items[index]; } - TList* TList::Create(GCList& gc) - { - TList* list=new TList(); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(list); - _gc->Watch(list); - return list; + return Undefined(); +} +int64_t TList::Count() { return (int64_t)this->items.size(); } +void TList::Insert(int64_t index, TObject value) { + if (index >= 0 && index <= this->Count()) { + this->items.insert(this->items.begin() + index, value); } - void TList::Add(TObject value) - { - this->items.push_back(value); +} +void TList::RemoveAt(int64_t index) { + if (index >= 0 && index < this->Count()) { + this->items.erase(this->items.begin() + index); } - void TList::Set(int64_t index, TObject value) - { - if(index >= 0 && index < this->Count()) - { - this->items[index] = value; - } +} +void TList::Clear() { this->items.clear(); } +void TList::Mark() { + if (this->marked) + return; + this->marked = true; + for (auto item : this->items) { + GC::Mark(item); } - TObject TList::Get(int64_t index) - { - if(index >= 0 && index < this->Count()) - { - return this->items[index]; - } - return Undefined(); - } - int64_t TList::Count() - { - return (int64_t)this->items.size(); - } - void TList::Insert(int64_t index, TObject value) - { - if(index >= 0 && index <= this->Count()) - { - this->items.insert(this->items.begin()+index,value); - } - } - void TList::RemoveAt(int64_t index) - { - if(index >= 0 && index < this->Count()) - { - this->items.erase(this->items.begin()+index); - } - } - void TList::Clear() - { - this->items.clear(); - } - void TList::Mark() - { - if(this->marked) return; - this->marked = true; - for(auto item : this->items) - { - GC::Mark(item); - } - } -}; \ No newline at end of file +} +}; // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/native.cpp b/src/types/native.cpp index 76cf797..18a5f61 100644 --- a/src/types/native.cpp +++ b/src/types/native.cpp @@ -1,75 +1,53 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - TNativeObject::~TNativeObject() - { +namespace Tesses::CrossLang { +TNativeObject::~TNativeObject() {} - } - - TNative::TNative(void* ptr,std::function destroy) - { - this->ptr = ptr; - this->destroyed=false; - this->destroy = destroy; - - } - bool TNative::GetDestroyed() - { - return this->destroyed; - } - void* TNative::GetPointer() - { - return this->ptr; - } - void TNative::Mark() - { - if(this->marked) return; - this->marked=true; - - GC::Mark(this->other); - - } - void TNative::Destroy() - { - if(this->destroyed) return; - if(this->destroy != nullptr) - { - this->destroyed=true; - this->destroy(this->ptr); - } - } - bool TNativeObject::ToBool() - { - return true; - } - bool TNativeObject::Equals(std::shared_ptr gc, TObject right) - { - if(std::holds_alternative(right)) - { - return this == std::get(right).obj; - } - return false; - } - TNative* TNative::Create(GCList& ls, void* ptr,std::function destroy) - { - TNative* native = new TNative(ptr,destroy); - std::shared_ptr gc = ls.GetGC(); - ls.Add(native); - gc->Watch(native); - return native; - } - TNative* TNative::Create(GCList* ls, void* ptr,std::function destroy) - { - TNative* native = new TNative(ptr,destroy); - std::shared_ptr gc = ls->GetGC(); - ls->Add(native); - gc->Watch(native); - return native; - } - TNative::~TNative() - { - this->Destroy(); - } - +TNative::TNative(void *ptr, std::function destroy) { + this->ptr = ptr; + this->destroyed = false; + this->destroy = destroy; } +bool TNative::GetDestroyed() { return this->destroyed; } +void *TNative::GetPointer() { return this->ptr; } +void TNative::Mark() { + if (this->marked) + return; + this->marked = true; + + GC::Mark(this->other); +} +void TNative::Destroy() { + if (this->destroyed) + return; + if (this->destroy != nullptr) { + this->destroyed = true; + this->destroy(this->ptr); + } +} +bool TNativeObject::ToBool() { return true; } +bool TNativeObject::Equals(std::shared_ptr gc, TObject right) { + if (std::holds_alternative(right)) { + return this == std::get(right).obj; + } + return false; +} +TNative *TNative::Create(GCList &ls, void *ptr, + std::function destroy) { + TNative *native = new TNative(ptr, destroy); + std::shared_ptr gc = ls.GetGC(); + ls.Add(native); + gc->Watch(native); + return native; +} +TNative *TNative::Create(GCList *ls, void *ptr, + std::function destroy) { + TNative *native = new TNative(ptr, destroy); + std::shared_ptr gc = ls->GetGC(); + ls->Add(native); + gc->Watch(native); + return native; +} +TNative::~TNative() { this->Destroy(); } + +} // namespace Tesses::CrossLang diff --git a/src/types/queryable.cpp b/src/types/queryable.cpp index cc76b97..f2f64b6 100644 --- a/src/types/queryable.cpp +++ b/src/types/queryable.cpp @@ -1,522 +1,476 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - TQueryable::TQueryable(TObject parent) : TQueryable(parent,TQueryableMode::Passthrough, {}) - { +namespace Tesses::CrossLang { +TQueryable::TQueryable(TObject parent) + : TQueryable(parent, TQueryableMode::Passthrough, {}) {} +TQueryable::TQueryable(TObject parent, TQueryableMode mode, + std::vector args) + : parent(parent), mode(mode), args(args) {} - } - TQueryable::TQueryable(TObject parent, TQueryableMode mode, std::vector args): parent(parent), mode(mode), args(args) - { +TQueryable *TQueryable::Skip(GCList &ls, int64_t no) { + return TQueryable::Create(ls, this, TQueryableMode::Skip, {no}); +} +TQueryable *TQueryable::SkipWhile(GCList &ls, TCallable *call) { + return TQueryable::Create(ls, this, TQueryableMode::SkipWhile, {call}); +} +TQueryable *TQueryable::Take(GCList &ls, int64_t no) { + return TQueryable::Create(ls, this, TQueryableMode::Take, {no}); +} +TQueryable *TQueryable::TakeWhile(GCList &ls, TCallable *call) { + return TQueryable::Create(ls, this, TQueryableMode::TakeWhile, {call}); +} +TQueryable *TQueryable::Select(GCList &ls, TCallable *call) { + return TQueryable::Create(ls, this, TQueryableMode::Select, {call}); +} +TQueryable *TQueryable::Where(GCList &ls, TCallable *call) { + return TQueryable::Create(ls, this, TQueryableMode::Where, {call}); +} +TList *TQueryable::ToList(GCList &ls) { + auto gc = ls.GetGC(); + GCList ls2(gc); + auto enumerator = this->GetEnumerator(ls); + if (enumerator == nullptr) + return nullptr; + auto list = TList::Create(ls); + while (enumerator->MoveNext(gc)) { + gc->BarrierBegin(); + list->Add(enumerator->GetCurrent(ls)); + gc->BarrierEnd(); } + return list; +} +TQueryable *TQueryable::Create(GCList &ls, TObject parent) { + TQueryable *queryable = new TQueryable(parent); + std::shared_ptr gc = ls.GetGC(); + ls.Add(queryable); + gc->Watch(queryable); + return queryable; +} +TQueryable *TQueryable::Create(GCList &ls, TObject parent, TQueryableMode mode, + std::vector args) { + TQueryable *queryable = new TQueryable(parent, mode, args); + std::shared_ptr gc = ls.GetGC(); + ls.Add(queryable); + gc->Watch(queryable); + return queryable; +} - TQueryable* TQueryable::Skip(GCList& ls,int64_t no) - { - return TQueryable::Create(ls,this,TQueryableMode::Skip, {no}); - } - TQueryable* TQueryable::SkipWhile(GCList& ls, TCallable* call) - { - return TQueryable::Create(ls,this,TQueryableMode::SkipWhile, {call}); - } - TQueryable* TQueryable::Take(GCList& ls, int64_t no) - { - return TQueryable::Create(ls,this,TQueryableMode::Take, {no}); - } - TQueryable* TQueryable::TakeWhile(GCList& ls, TCallable* call) - { - return TQueryable::Create(ls,this,TQueryableMode::TakeWhile, {call}); - } - TQueryable* TQueryable::Select(GCList& ls, TCallable* call) - { - return TQueryable::Create(ls,this,TQueryableMode::Select, {call}); - } - TQueryable* TQueryable::Where(GCList& ls, TCallable* call) - { - return TQueryable::Create(ls,this,TQueryableMode::Where, {call}); - } - - TList* TQueryable::ToList(GCList& ls) - { - auto gc = ls.GetGC(); +void TQueryable::Mark() { + if (this->marked) + return; + this->marked = true; + + GC::Mark(this->parent); + for (auto &item : args) + GC::Mark(item); +} + +void TQueryable::ForEach(std::shared_ptr gc, TCallable *call) { + if (call == nullptr) + return; + GCList ls(gc); + auto enumerator = this->GetEnumerator(ls); + if (enumerator == nullptr) + return; + while (enumerator->MoveNext(gc)) { GCList ls2(gc); - auto enumerator = this->GetEnumerator(ls); - if(enumerator == nullptr) return nullptr; - auto list = TList::Create(ls); - while(enumerator->MoveNext(gc)) - { - gc->BarrierBegin(); - list->Add(enumerator->GetCurrent(ls)); - gc->BarrierEnd(); - } - return list; + call->Call(ls2, {enumerator->GetCurrent(ls2)}); } - TQueryable* TQueryable::Create(GCList& ls, TObject parent) - { - TQueryable* queryable = new TQueryable(parent); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; - } - TQueryable* TQueryable::Create(GCList& ls, TObject parent, TQueryableMode mode, std::vector args) - { - TQueryable* queryable = new TQueryable(parent, mode,args); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; - } - - - void TQueryable::Mark() - { - if(this->marked) return; - this->marked=true; - - GC::Mark(this->parent); - for(auto& item : args) - GC::Mark(item); - } - - void TQueryable::ForEach(std::shared_ptr gc, TCallable* call) - { - if(call == nullptr) return; - GCList ls(gc); - auto enumerator = this->GetEnumerator(ls); - if(enumerator == nullptr) return; - while(enumerator->MoveNext(gc)) - { - GCList ls2(gc); - call->Call(ls2,{enumerator->GetCurrent(ls2)}); - } - } - int64_t TQueryable::Count(std::shared_ptr gc, TCallable* call) - { - if(call == nullptr) return 0; - GCList ls(gc); - auto enumerator = this->GetEnumerator(ls); - if(enumerator == nullptr) return 0; - int64_t count=0; - while(enumerator->MoveNext(gc)) - { - GCList ls2(gc); - if(ToBool(call->Call(ls2,{enumerator->GetCurrent(ls2)}))) count++; - } - return count; - } - int64_t TQueryable::Count(std::shared_ptr gc) - { - GCList ls(gc); - auto enumerator = this->GetEnumerator(ls); - if(enumerator == nullptr) return 0; - int64_t count=0; - while(enumerator->MoveNext(gc)) - { +} +int64_t TQueryable::Count(std::shared_ptr gc, TCallable *call) { + if (call == nullptr) + return 0; + GCList ls(gc); + auto enumerator = this->GetEnumerator(ls); + if (enumerator == nullptr) + return 0; + int64_t count = 0; + while (enumerator->MoveNext(gc)) { + GCList ls2(gc); + if (ToBool(call->Call(ls2, {enumerator->GetCurrent(ls2)}))) count++; - } - return count; } - bool TQueryable::Contains(std::shared_ptr gc, TObject value) - { - GCList ls(gc); - auto enumerator = this->GetEnumerator(ls); - if(enumerator == nullptr) return false; - while(enumerator->MoveNext(gc)) - { - GCList ls2(gc); - + return count; +} +int64_t TQueryable::Count(std::shared_ptr gc) { + GCList ls(gc); + auto enumerator = this->GetEnumerator(ls); + if (enumerator == nullptr) + return 0; + int64_t count = 0; + while (enumerator->MoveNext(gc)) { + count++; + } + return count; +} +bool TQueryable::Contains(std::shared_ptr gc, TObject value) { + GCList ls(gc); + auto enumerator = this->GetEnumerator(ls); + if (enumerator == nullptr) + return false; + while (enumerator->MoveNext(gc)) { + GCList ls2(gc); - if(Equals(gc,value,enumerator->GetCurrent(ls2))) - return true; - - } - return false; + if (Equals(gc, value, enumerator->GetCurrent(ls2))) + return true; } - bool TQueryable::Any(std::shared_ptr gc, TCallable* call) - { - if(call == nullptr) return false; - GCList ls(gc); - auto enumerator = this->GetEnumerator(ls); - if(enumerator == nullptr) return false; - - while(enumerator->MoveNext(gc)) - { - GCList ls2(gc); - if(ToBool(call->Call(ls2,{enumerator->GetCurrent(ls2)}))) return true; - } + return false; +} +bool TQueryable::Any(std::shared_ptr gc, TCallable *call) { + if (call == nullptr) return false; + GCList ls(gc); + auto enumerator = this->GetEnumerator(ls); + if (enumerator == nullptr) + return false; + + while (enumerator->MoveNext(gc)) { + GCList ls2(gc); + if (ToBool(call->Call(ls2, {enumerator->GetCurrent(ls2)}))) + return true; } - bool TQueryable::All(std::shared_ptr gc, TCallable* call) - { - if(call == nullptr) return true; - GCList ls(gc); - auto enumerator = this->GetEnumerator(ls); - if(enumerator == nullptr) return true; - - while(enumerator->MoveNext(gc)) - { - GCList ls2(gc); - if(!ToBool(call->Call(ls2,{enumerator->GetCurrent(ls2)}))) return false; - } + return false; +} +bool TQueryable::All(std::shared_ptr gc, TCallable *call) { + if (call == nullptr) return true; + GCList ls(gc); + auto enumerator = this->GetEnumerator(ls); + if (enumerator == nullptr) + return true; + + while (enumerator->MoveNext(gc)) { + GCList ls2(gc); + if (!ToBool(call->Call(ls2, {enumerator->GetCurrent(ls2)}))) + return false; } + return true; +} - class SkipItterator : public TEnumerator { - private: - TEnumerator* parentEnum; - int64_t skipCount; - SkipItterator(TEnumerator* parentEnum, int64_t skipCount) : parentEnum(parentEnum), skipCount(skipCount) - { +class SkipItterator : public TEnumerator { + private: + TEnumerator *parentEnum; + int64_t skipCount; + SkipItterator(TEnumerator *parentEnum, int64_t skipCount) + : parentEnum(parentEnum), skipCount(skipCount) {} - } - public: - static SkipItterator* Create(GCList& ls, TEnumerator* parentEnum, int64_t skipCount) - { - SkipItterator* queryable = new SkipItterator(parentEnum, skipCount); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; - } - bool MoveNext(std::shared_ptr ls) - { - if(this->parentEnum == nullptr) return false; - while(skipCount > 0) - { - if(!this->parentEnum->MoveNext(ls)) { - skipCount=0; - return false; - } - skipCount--; - } - return this->parentEnum->MoveNext(ls); - } - TObject GetCurrent(GCList& ls) - { - return this->parentEnum->GetCurrent(ls); - } - void Mark() - { - if(this->marked) return; - this->marked=true; - - if(parentEnum != nullptr) parentEnum->Mark(); - } - }; - class TakeItterator : public TEnumerator { - private: - TEnumerator* parentEnum; - int64_t takeCount; - TakeItterator(TEnumerator* parentEnum, int64_t takeCount) : parentEnum(parentEnum), takeCount(takeCount) - { - - } - public: - static TakeItterator* Create(GCList& ls, TEnumerator* parentEnum, int64_t takeCount) - { - TakeItterator* queryable = new TakeItterator(parentEnum, takeCount); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; - } - bool MoveNext(std::shared_ptr ls) - { - if(this->parentEnum == nullptr) return false; - if(takeCount > 0) - { - takeCount--; - return this->parentEnum->MoveNext(ls); - } + public: + static SkipItterator *Create(GCList &ls, TEnumerator *parentEnum, + int64_t skipCount) { + SkipItterator *queryable = new SkipItterator(parentEnum, skipCount); + std::shared_ptr gc = ls.GetGC(); + ls.Add(queryable); + gc->Watch(queryable); + return queryable; + } + bool MoveNext(std::shared_ptr ls) { + if (this->parentEnum == nullptr) + return false; + while (skipCount > 0) { + if (!this->parentEnum->MoveNext(ls)) { + skipCount = 0; return false; } - TObject GetCurrent(GCList& ls) - { - return this->parentEnum->GetCurrent(ls); - } - void Mark() - { - if(this->marked) return; - this->marked=true; - - if(parentEnum != nullptr) parentEnum->Mark(); - } - }; - class SkipWhileItterator : public TEnumerator { - private: - TEnumerator* parentEnum; - TCallable* callable; - SkipWhileItterator(TEnumerator* parentEnum, TCallable* callable) : parentEnum(parentEnum), callable(callable) - { - - } - public: - static SkipWhileItterator* Create(GCList& ls, TEnumerator* parentEnum, TCallable* callable) - { - SkipWhileItterator* queryable = new SkipWhileItterator(parentEnum, callable); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; - } - bool MoveNext(std::shared_ptr ls) - { - if(this->parentEnum == nullptr) return false; - ls->BarrierBegin(); - auto callable = this->callable; - ls->BarrierEnd(); - - if(callable != nullptr) - { - while(true) - { - if(this->parentEnum->MoveNext(ls)) - { - GCList ls2(ls); - auto result = callable->Call(ls2,{this->parentEnum->GetCurrent(ls2)}); - if(!ToBool(result)) - { - ls->BarrierBegin(); - this->callable=nullptr; - ls->BarrierEnd(); - return true; - } - - } - else - { - ls->BarrierBegin(); - this->callable=nullptr; - ls->BarrierEnd(); - return false; - } - } - } - else { - return this->parentEnum->MoveNext(ls); - } - return false; - } - TObject GetCurrent(GCList& ls) - { - return this->parentEnum->GetCurrent(ls); - } - void Mark() - { - if(this->marked) return; - this->marked=true; - - if(parentEnum != nullptr) parentEnum->Mark(); - if(callable != nullptr) callable->Mark(); - } - }; - class TakeWhileItterator : public TEnumerator { - private: - TEnumerator* parentEnum; - TCallable* callable; - TakeWhileItterator(TEnumerator* parentEnum, TCallable* callable) : parentEnum(parentEnum), callable(callable) - { - - } - public: - static TakeWhileItterator* Create(GCList& ls, TEnumerator* parentEnum, TCallable* callable) - { - TakeWhileItterator* queryable = new TakeWhileItterator(parentEnum, callable); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; - } - bool MoveNext(std::shared_ptr ls) - { - if(this->parentEnum == nullptr) return false; - ls->BarrierBegin(); - auto callable = this->callable; - ls->BarrierEnd(); - if(callable != nullptr) - { - if(this->parentEnum->MoveNext(ls)) - { - GCList ls2(ls); - auto result = callable->Call(ls2,{this->parentEnum->GetCurrent(ls2)}); - if(!ToBool(result)) - { - ls->BarrierBegin(); - this->callable=nullptr; - ls->BarrierEnd(); - return false; - } - return true; - } - } - return false; - } - TObject GetCurrent(GCList& ls) - { - return this->parentEnum->GetCurrent(ls); - } - void Mark() - { - if(this->marked) return; - this->marked=true; - - if(parentEnum != nullptr) parentEnum->Mark(); - if(callable != nullptr) callable->Mark(); - } - }; - class WhereItterator : public TEnumerator { - private: - TEnumerator* parentEnum; - TCallable* callable; - WhereItterator(TEnumerator* parentEnum, TCallable* callable) : parentEnum(parentEnum), callable(callable) - { - - } - public: - static WhereItterator* Create(GCList& ls, TEnumerator* parentEnum, TCallable* callable) - { - WhereItterator* queryable = new WhereItterator(parentEnum, callable); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; - } - bool MoveNext(std::shared_ptr ls) - { - if(this->parentEnum == nullptr || this->callable == nullptr) return false; - while(this->parentEnum->MoveNext(ls)) - { - GCList ls2(ls); - auto cur = this->parentEnum->GetCurrent(ls2); - if(ToBool(callable->Call(ls2,{cur}))) - return true; - - } - return false; - } - TObject GetCurrent(GCList& ls) - { - return this->parentEnum->GetCurrent(ls); - } - void Mark() - { - if(this->marked) return; - this->marked=true; - - if(parentEnum != nullptr) parentEnum->Mark(); - if(callable != nullptr) callable->Mark(); - } - }; - class SelectItterator : public TEnumerator { - private: - TEnumerator* parentEnum; - TCallable* callable; - TObject value; - SelectItterator(TEnumerator* parentEnum, TCallable* callable) : parentEnum(parentEnum), callable(callable) - { - - } - public: - static SelectItterator* Create(GCList& ls, TEnumerator* parentEnum, TCallable* callable) - { - SelectItterator* queryable = new SelectItterator(parentEnum, callable); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; - } - bool MoveNext(std::shared_ptr ls) - { - if(this->parentEnum == nullptr || this->callable == nullptr) return false; - if(this->parentEnum->MoveNext(ls)) - { - GCList ls2(ls); - auto cur = this->parentEnum->GetCurrent(ls2); - auto value = this->callable->Call(ls2,{cur}); - - ls->BarrierBegin(); - this->value = value; - ls->BarrierEnd(); - - return true; - } - return false; - } - TObject GetCurrent(GCList& ls) - { - ls.GetGC()->BarrierBegin(); - auto value=this->value; - ls.GetGC()->BarrierEnd(); - return value; - } - void Mark() - { - if(this->marked) return; - this->marked=true; - - if(parentEnum != nullptr) parentEnum->Mark(); - if(callable != nullptr) callable->Mark(); - - GC::Mark(this->value); - } - }; - - - TEnumerator* TQueryable::GetEnumerator(GCList& ls) - { - switch(this->mode) - { - case TQueryableMode::Skip: - { - int64_t skipCount; - if(GetArgument(args,0,skipCount)) - return SkipItterator::Create(ls, TEnumerator::CreateFromObject(ls, this->parent), skipCount); - } - break; - case TQueryableMode::Take: - { - int64_t takeCount; - if(GetArgument(args,0,takeCount)) - return TakeItterator::Create(ls, TEnumerator::CreateFromObject(ls, this->parent), takeCount); - - } - break; - case TQueryableMode::SkipWhile: - { - TCallable* callable; - if(GetArgumentHeap(args,0,callable)) - return SkipWhileItterator::Create(ls, TEnumerator::CreateFromObject(ls, this->parent), callable); - - } - break; - case TQueryableMode::TakeWhile: - { - TCallable* callable; - if(GetArgumentHeap(args,0,callable)) - return TakeWhileItterator::Create(ls, TEnumerator::CreateFromObject(ls, this->parent), callable); - - } - break; - case TQueryableMode::Select: - { - TCallable* callable; - if(GetArgumentHeap(args,0,callable)) - return SelectItterator::Create(ls, TEnumerator::CreateFromObject(ls, this->parent), callable); - - } - break; - case TQueryableMode::Where: - { - TCallable* callable; - if(GetArgumentHeap(args,0,callable)) - return WhereItterator::Create(ls, TEnumerator::CreateFromObject(ls, this->parent), callable); - - } - break; + skipCount--; } + return this->parentEnum->MoveNext(ls); + } + TObject GetCurrent(GCList &ls) { return this->parentEnum->GetCurrent(ls); } + void Mark() { + if (this->marked) + return; + this->marked = true; - return TEnumerator::CreateFromObject(ls, this->parent); + if (parentEnum != nullptr) + parentEnum->Mark(); + } +}; +class TakeItterator : public TEnumerator { + private: + TEnumerator *parentEnum; + int64_t takeCount; + TakeItterator(TEnumerator *parentEnum, int64_t takeCount) + : parentEnum(parentEnum), takeCount(takeCount) {} + + public: + static TakeItterator *Create(GCList &ls, TEnumerator *parentEnum, + int64_t takeCount) { + TakeItterator *queryable = new TakeItterator(parentEnum, takeCount); + std::shared_ptr gc = ls.GetGC(); + ls.Add(queryable); + gc->Watch(queryable); + return queryable; + } + bool MoveNext(std::shared_ptr ls) { + if (this->parentEnum == nullptr) + return false; + if (takeCount > 0) { + takeCount--; + return this->parentEnum->MoveNext(ls); + } + return false; + } + TObject GetCurrent(GCList &ls) { return this->parentEnum->GetCurrent(ls); } + void Mark() { + if (this->marked) + return; + this->marked = true; + + if (parentEnum != nullptr) + parentEnum->Mark(); + } +}; +class SkipWhileItterator : public TEnumerator { + private: + TEnumerator *parentEnum; + TCallable *callable; + SkipWhileItterator(TEnumerator *parentEnum, TCallable *callable) + : parentEnum(parentEnum), callable(callable) {} + + public: + static SkipWhileItterator *Create(GCList &ls, TEnumerator *parentEnum, + TCallable *callable) { + SkipWhileItterator *queryable = + new SkipWhileItterator(parentEnum, callable); + std::shared_ptr gc = ls.GetGC(); + ls.Add(queryable); + gc->Watch(queryable); + return queryable; + } + bool MoveNext(std::shared_ptr ls) { + if (this->parentEnum == nullptr) + return false; + ls->BarrierBegin(); + auto callable = this->callable; + ls->BarrierEnd(); + + if (callable != nullptr) { + while (true) { + if (this->parentEnum->MoveNext(ls)) { + GCList ls2(ls); + auto result = callable->Call( + ls2, {this->parentEnum->GetCurrent(ls2)}); + if (!ToBool(result)) { + ls->BarrierBegin(); + this->callable = nullptr; + ls->BarrierEnd(); + return true; + } + + } else { + ls->BarrierBegin(); + this->callable = nullptr; + ls->BarrierEnd(); + return false; + } + } + } else { + return this->parentEnum->MoveNext(ls); + } + return false; + } + TObject GetCurrent(GCList &ls) { return this->parentEnum->GetCurrent(ls); } + void Mark() { + if (this->marked) + return; + this->marked = true; + + if (parentEnum != nullptr) + parentEnum->Mark(); + if (callable != nullptr) + callable->Mark(); + } +}; +class TakeWhileItterator : public TEnumerator { + private: + TEnumerator *parentEnum; + TCallable *callable; + TakeWhileItterator(TEnumerator *parentEnum, TCallable *callable) + : parentEnum(parentEnum), callable(callable) {} + + public: + static TakeWhileItterator *Create(GCList &ls, TEnumerator *parentEnum, + TCallable *callable) { + TakeWhileItterator *queryable = + new TakeWhileItterator(parentEnum, callable); + std::shared_ptr gc = ls.GetGC(); + ls.Add(queryable); + gc->Watch(queryable); + return queryable; + } + bool MoveNext(std::shared_ptr ls) { + if (this->parentEnum == nullptr) + return false; + ls->BarrierBegin(); + auto callable = this->callable; + ls->BarrierEnd(); + if (callable != nullptr) { + if (this->parentEnum->MoveNext(ls)) { + GCList ls2(ls); + auto result = + callable->Call(ls2, {this->parentEnum->GetCurrent(ls2)}); + if (!ToBool(result)) { + ls->BarrierBegin(); + this->callable = nullptr; + ls->BarrierEnd(); + return false; + } + return true; + } + } + return false; + } + TObject GetCurrent(GCList &ls) { return this->parentEnum->GetCurrent(ls); } + void Mark() { + if (this->marked) + return; + this->marked = true; + + if (parentEnum != nullptr) + parentEnum->Mark(); + if (callable != nullptr) + callable->Mark(); + } +}; +class WhereItterator : public TEnumerator { + private: + TEnumerator *parentEnum; + TCallable *callable; + WhereItterator(TEnumerator *parentEnum, TCallable *callable) + : parentEnum(parentEnum), callable(callable) {} + + public: + static WhereItterator *Create(GCList &ls, TEnumerator *parentEnum, + TCallable *callable) { + WhereItterator *queryable = new WhereItterator(parentEnum, callable); + std::shared_ptr gc = ls.GetGC(); + ls.Add(queryable); + gc->Watch(queryable); + return queryable; + } + bool MoveNext(std::shared_ptr ls) { + if (this->parentEnum == nullptr || this->callable == nullptr) + return false; + while (this->parentEnum->MoveNext(ls)) { + GCList ls2(ls); + auto cur = this->parentEnum->GetCurrent(ls2); + if (ToBool(callable->Call(ls2, {cur}))) + return true; + } + return false; + } + TObject GetCurrent(GCList &ls) { return this->parentEnum->GetCurrent(ls); } + void Mark() { + if (this->marked) + return; + this->marked = true; + + if (parentEnum != nullptr) + parentEnum->Mark(); + if (callable != nullptr) + callable->Mark(); + } +}; +class SelectItterator : public TEnumerator { + private: + TEnumerator *parentEnum; + TCallable *callable; + TObject value; + SelectItterator(TEnumerator *parentEnum, TCallable *callable) + : parentEnum(parentEnum), callable(callable) {} + + public: + static SelectItterator *Create(GCList &ls, TEnumerator *parentEnum, + TCallable *callable) { + SelectItterator *queryable = new SelectItterator(parentEnum, callable); + std::shared_ptr gc = ls.GetGC(); + ls.Add(queryable); + gc->Watch(queryable); + return queryable; + } + bool MoveNext(std::shared_ptr ls) { + if (this->parentEnum == nullptr || this->callable == nullptr) + return false; + if (this->parentEnum->MoveNext(ls)) { + GCList ls2(ls); + auto cur = this->parentEnum->GetCurrent(ls2); + auto value = this->callable->Call(ls2, {cur}); + + ls->BarrierBegin(); + this->value = value; + ls->BarrierEnd(); + + return true; + } + return false; + } + TObject GetCurrent(GCList &ls) { + ls.GetGC()->BarrierBegin(); + auto value = this->value; + ls.GetGC()->BarrierEnd(); + return value; + } + void Mark() { + if (this->marked) + return; + this->marked = true; + + if (parentEnum != nullptr) + parentEnum->Mark(); + if (callable != nullptr) + callable->Mark(); + + GC::Mark(this->value); + } +}; + +TEnumerator *TQueryable::GetEnumerator(GCList &ls) { + switch (this->mode) { + case TQueryableMode::Skip: { + int64_t skipCount; + if (GetArgument(args, 0, skipCount)) + return SkipItterator::Create( + ls, TEnumerator::CreateFromObject(ls, this->parent), skipCount); + } break; + case TQueryableMode::Take: { + int64_t takeCount; + if (GetArgument(args, 0, takeCount)) + return TakeItterator::Create( + ls, TEnumerator::CreateFromObject(ls, this->parent), takeCount); + + } break; + case TQueryableMode::SkipWhile: { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) + return SkipWhileItterator::Create( + ls, TEnumerator::CreateFromObject(ls, this->parent), callable); + + } break; + case TQueryableMode::TakeWhile: { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) + return TakeWhileItterator::Create( + ls, TEnumerator::CreateFromObject(ls, this->parent), callable); + + } break; + case TQueryableMode::Select: { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) + return SelectItterator::Create( + ls, TEnumerator::CreateFromObject(ls, this->parent), callable); + + } break; + case TQueryableMode::Where: { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) + return WhereItterator::Create( + ls, TEnumerator::CreateFromObject(ls, this->parent), callable); + + } break; } -} \ No newline at end of file + return TEnumerator::CreateFromObject(ls, this->parent); +} + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/random.cpp b/src/types/random.cpp index de190d6..1dba65f 100644 --- a/src/types/random.cpp +++ b/src/types/random.cpp @@ -1,47 +1,32 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - TRandom::TRandom() : random() - { - - } - TRandom::TRandom(uint64_t seed) : random(seed) - { - - } - std::string TRandom::TypeName() - { - return "Random"; - } - TObject TRandom::CallMethod(GCList& ls,std::string name, std::vector args) - { - if(name == "Next") - { - int64_t first; - int64_t second; - if(GetArgument(args,0,first)) - { - if(GetArgument(args,1,second)) - { - return (int64_t)random.Next((int32_t)first,(int32_t)second); - } - - return (int64_t)random.Next((uint32_t)first); +namespace Tesses::CrossLang { +TRandom::TRandom() : random() {} +TRandom::TRandom(uint64_t seed) : random(seed) {} +std::string TRandom::TypeName() { return "Random"; } +TObject TRandom::CallMethod(GCList &ls, std::string name, + std::vector args) { + if (name == "Next") { + int64_t first; + int64_t second; + if (GetArgument(args, 0, first)) { + if (GetArgument(args, 1, second)) { + return (int64_t)random.Next((int32_t)first, (int32_t)second); } - return random.Next(); - + return (int64_t)random.Next((uint32_t)first); } - if(name == "NextByte") - { - return (int64_t)random.NextByte(); - } - - if(name == "ToString") { - return ""; - } - return Undefined(); + return random.Next(); } -} \ No newline at end of file + + if (name == "NextByte") { + return (int64_t)random.NextByte(); + } + + if (name == "ToString") { + return ""; + } + return Undefined(); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/rootenvironment.cpp b/src/types/rootenvironment.cpp index 063472f..ea3dbf9 100644 --- a/src/types/rootenvironment.cpp +++ b/src/types/rootenvironment.cpp @@ -2,394 +2,377 @@ #include #include namespace Tesses::CrossLang { - void ThrowConstError(std::string key) - { - throw std::runtime_error("Cannot set \"" + key + "\" because it is a const"); - } +void ThrowConstError(std::string key) { + throw std::runtime_error("Cannot set \"" + key + + "\" because it is a const"); +} - void TEnvironment::DeclareConstVariable(std::string key, TObject value) - { - this->DeclareVariable(key,value); - this->consts.push_back(key); - } - bool TEnvironment::HasConstForDeclare(std::string key) - { - for(auto item : this->consts) - if(item == key) - return true; - return false; - } - bool TEnvironment::HasConstForSet(std::string key) - { - return HasConstForDeclare(key); - } - bool TRootEnvironment::TryFindClass(std::vector& name, size_t& index) - { - for(size_t i = 0; i < this->classes.size(); i++) - { - if(classes[i].first->classes.at(classes[i].second).name.size() != name.size()) continue; - for(size_t j = 0; j < name.size(); j++) - if(classes[i].first->classes.at(classes[i].second).name[j] != name[j]) continue; - index=i; +void TEnvironment::DeclareConstVariable(std::string key, TObject value) { + this->DeclareVariable(key, value); + this->consts.push_back(key); +} +bool TEnvironment::HasConstForDeclare(std::string key) { + for (auto item : this->consts) + if (item == key) return true; - } - return false; - } - bool TRootEnvironment::HasVariableOrFieldRecurse(std::string key,bool setting) - { - std::string property=(setting? "set":"get") + key; - if(this->HasVariable(property)) - { - auto res = this->GetVariable(property); - TCallable* callable; - if(GetObjectHeap(res,callable)) return true; - } - - return this->HasVariable(key); - } - TObject TRootEnvironment::GetVariable(GCList& ls, std::string key) - { - ls.GetGC()->BarrierBegin(); - if(this->HasVariable("get" + key)) - { - auto item = this->GetVariable("get"+key); - TCallable* callable; - if(GetObjectHeap(item,callable)) - { - ls.GetGC()->BarrierEnd(); - return callable->Call(ls,{}); + return false; +} +bool TEnvironment::HasConstForSet(std::string key) { + return HasConstForDeclare(key); +} +bool TRootEnvironment::TryFindClass(std::vector &name, + size_t &index) { + for (size_t i = 0; i < this->classes.size(); i++) { + bool conUp = false; + if (classes[i].first->classes.at(classes[i].second).name.size() != + name.size()) + continue; + for (size_t j = 0; j < name.size(); j++) + if (classes[i].first->classes.at(classes[i].second).name[j] != + name[j]) { + conUp = true; + break; } - } - - auto item = this->GetVariable(key); - ls.GetGC()->BarrierEnd(); - - return item; - } - TObject TRootEnvironment::SetVariable(GCList& ls, std::string key, TObject value) - { - ls.GetGC()->BarrierBegin(); - if(this->HasVariable("set" + key)) - { - auto item = this->GetVariable("set"+key); - TCallable* callable; - if(GetObjectHeap(item,callable)) - { - ls.GetGC()->BarrierEnd(); - return callable->Call(ls,{value}); - } - } - - this->SetVariable(key,value); - ls.GetGC()->BarrierEnd(); - - return value; - } - - void TRootEnvironment::LoadDependency(std::shared_ptr gc,std::shared_ptr vfs, std::pair dep) - { - for(auto item : this->dependencies) - if(item.first == dep.first && item.second.CompareTo(dep.second) >= 0) return; - std::string name = {}; - name.append(dep.first); - name.push_back('-'); - name.append(dep.second.ToString()); - name.append(".crvm"); - std::string filename="/" + name; - - if(vfs->RegularFileExists(filename)) - { - auto file = vfs->OpenFile(filename,"rb"); - GCList ls(gc); - TFile* f = TFile::Create(ls); - f->Load(gc, file); - - LoadFileWithDependencies(gc, vfs, f); - } - else throw VMException("Could not open file: \"" + name + "\"."); - } - TObject TEnvironment::Eval(GCList& ls,std::string code) - { - std::stringstream strm(code); - std::vector tokens; - int res =Lex("eval.tcross",strm,tokens); - if(res != 0) - { - throw VMException("Lex error at line: " + std::to_string(res)); - } - Parser parser(tokens); - - SyntaxNode n = parser.ParseRoot(); - CodeGen gen; - gen.GenRoot(n); - auto ms = std::make_shared(true); - gen.Save(ms); - ms->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin); - TFile* f = TFile::Create(ls); - f->Load(ls.GetGC(),ms); - return this->LoadFile(ls.GetGC(), f); - } - TDictionary* TEnvironment::EnsureDictionary(std::shared_ptr gc, std::string key) - { - TObject item = this->GetVariable(key); - TDictionary* dict; - if(GetObjectHeap(item,dict)) return dict; - GCList ls(gc); - dict = TDictionary::Create(ls); - this->DeclareVariable(key, dict); - return dict; - } - void TEnvironment::DeclareVariable(std::shared_ptr gc, std::vector name, TObject o) - { - if(name.size() == 0) - throw VMException("name can't be empty."); - - else if(name.size() == 1) - { - GCList ls(gc); - - gc->BarrierBegin(); - this->DeclareVariable(name[0],o); - gc->BarrierEnd(); - } - else - { - GCList ls(gc); - - TObject v = this->GetVariable(name[0]); - TDictionary* dict=nullptr; - if(std::holds_alternative(v)) - { - dict=dynamic_cast(std::get(v).obj); - if(dict == nullptr) - { - dict = TDictionary::Create(ls); - gc->BarrierBegin(); - this->SetVariable(name[0],dict); - gc->BarrierEnd(); - } - } - else - { - dict = TDictionary::Create(ls); - gc->BarrierBegin(); - this->DeclareVariable(name[0],dict); - gc->BarrierEnd(); - } - - for(size_t i = 1; i < name.size()-1; i++) - { - gc->BarrierBegin(); - auto v = dict->GetValue(name[i]); - gc->BarrierEnd(); - if(std::holds_alternative(v)) - { - auto dict2=dynamic_cast(std::get(v).obj); - if(dict2 == nullptr) - { - dict2 = TDictionary::Create(ls); - gc->BarrierBegin(); - dict->SetValue(name[i],dict2); - gc->BarrierEnd(); - } - dict = dict2; - } - else - { - auto dict2 = TDictionary::Create(ls); - gc->BarrierBegin(); - dict->SetValue(name[i],dict2); - gc->BarrierEnd(); - dict = dict2; - } - } - gc->BarrierBegin(); - dict->SetValue(name[name.size()-1],o); - gc->BarrierEnd(); - } - } - - TObject TEnvironment::LoadFile(std::shared_ptr gc, TFile* file) - { - file->EnsureCanRunInCrossLang(); - for(size_t i = 0; i < file->classes.size(); i++) - { - this->GetRootEnvironment()->classes.push_back(std::pair(file,(uint32_t)i)); - std::vector clsPart={"New"}; - clsPart.insert(clsPart.end(),file->classes[i].name.begin(),file->classes[i].name.end()); - GCList ls(gc); - std::vector name=file->classes[i].name; - auto rootEnv = this->GetRootEnvironment(); - this->DeclareVariable(gc, clsPart, TExternalMethod::Create(ls,"Create instance of the class",{"$$args"},[rootEnv,file,i](GCList& ls, std::vector args)->TObject{ - return TClassObject::Create(ls, file,i,rootEnv,args); - })); - for(auto meth : file->classes[i].entry) - { - - if(meth.isFunction && meth.modifier == TClassModifier::Static) - { - std::vector method=file->classes[i].name; - method.push_back(meth.name); - auto clo = TClosure::Create(ls,this,file,meth.chunkId); - clo->closure->name = JoinPeriod(method); - - - clo->documentation = meth.documentation; - this->DeclareVariable(gc, method, clo); - } - } - - } - for(auto fn : file->functions) - { - - - - if(fn.first.size() < 2) throw VMException("No function name."); - - std::vector items(fn.first.begin()+1, fn.first.end()); - - if(fn.second >= file->chunks.size()) throw VMException("ChunkId out of bounds."); - TFileChunk* chunk = file->chunks[fn.second]; - chunk->name = JoinPeriod(items); - GCList ls(gc); - TClosure* closure=TClosure::Create(ls,this,file,fn.second); - closure->documentation = fn.first[0]; - this->DeclareVariable(gc,items,closure); - - } - if(!file->chunks.empty()) - { - GCList ls(gc); - TClosure* closure=TClosure::Create(ls,this,file,0); - return closure->Call(ls,{}); - } - return nullptr; - } - void TRootEnvironment::LoadFileWithDependencies(std::shared_ptr gc,std::shared_ptr vfs, TFile* file) - { - this->dependencies.push_back(std::pair(file->name,file->version)); - for(auto item : file->dependencies) - { - LoadDependency(gc,vfs,item); - } - LoadFile(gc, file); - - } - void TRootEnvironment::LoadFileWithDependencies(std::shared_ptr gc,std::shared_ptr vfs, Tesses::Framework::Filesystem::VFSPath path) - { - - - if(vfs->RegularFileExists(path)) - { - auto file=vfs->OpenFile(path,"rb"); - GCList ls(gc); - TFile* f = TFile::Create(ls); - f->Load(gc, file); - - auto dir = std::make_shared(vfs,path.GetParent()); - LoadFileWithDependencies(gc,dir,f); - } - else throw VMException("Could not open file: \"" + path.GetFileName() + "\"."); - - } - TDictionary* TRootEnvironment::GetDictionary() - { - return this->dict; - } - TObject TRootEnvironment::GetVariable(std::string key) - { - return this->dict->GetValue(key); - } - void TRootEnvironment::SetVariable(std::string key, TObject value) - { - this->dict->SetValue(key,value); - } - void TRootEnvironment::DeclareVariable(std::string key, TObject value) - { - return this->dict->SetValue(key,value); - } - bool TRootEnvironment::HasVariable(std::string key) - { - return this->dict->HasValue(key); - } - bool TRootEnvironment::HasVariableRecurse(std::string key) - { - return this->dict->HasValue(key); - } - TEnvironment* TRootEnvironment::GetParentEnvironment() - { - return this; - } - TRootEnvironment* TRootEnvironment::GetRootEnvironment() - { - return this; - } - - TRootEnvironment::TRootEnvironment(TDictionary* dict) - { - this->dict = dict; - } - - void TRootEnvironment::Mark() - { - if(this->marked) return; - this->marked = true; - this->dict->Mark(); - if(this->permissions.customConsole != nullptr) this->permissions.customConsole->Mark(); - for(auto defer : this->defers) defer->Mark(); - if(this->error != nullptr) this->error->Mark(); - for(auto cls : this->classes) cls.first->Mark(); - } - TRootEnvironment* TRootEnvironment::Create(GCList* gc,TDictionary* dict) - { - TRootEnvironment* env=new TRootEnvironment(dict); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(env); - _gc->Watch(env); - return env; - } - TRootEnvironment* TRootEnvironment::Create(GCList& gc,TDictionary* dict) - { - TRootEnvironment* env=new TRootEnvironment(dict); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(env); - _gc->Watch(env); - return env; - } - - bool TRootEnvironment::HandleException(std::shared_ptr gc,TEnvironment* env, TObject err) - { - if(error != nullptr) - { - GCList ls(gc); - return ToBool(error->Call(ls, { - TDictionary::Create(ls,{ - TDItem("IsBreakpoint",false), - TDItem("Exception",err), - TDItem("Environment", env) - }) - })); - } - return false; - } - bool TRootEnvironment::HandleBreakpoint(std::shared_ptr gc,TEnvironment* env, TObject err) - { - if(error != nullptr) - { - GCList ls(gc); - return ToBool(error->Call(ls, { - TDictionary::Create(ls,{ - TDItem("IsBreakpoint",true), - TDItem("Breakpoint",err), - TDItem("Environment", env) - }) - })); - } + if (conUp) + continue; + index = i; return true; } - void TRootEnvironment::RegisterOnError(TCallable* call) - { - this->error = call; + return false; +} +TDictionary *TRootEnvironment::GetPrivateFromFile(std::shared_ptr gc, + TFile *file) { + auto index = reinterpret_cast(file); + gc->BarrierBegin(); + TDictionary *obj; + if (this->private_file_data.count(index) > 0) { + obj = this->private_file_data[index]; + } else { + GCList ls(gc); + obj = TDictionary::Create(ls); + this->private_file_data[index] = obj; } -}; + gc->BarrierEnd(); + + return obj; +} +bool TRootEnvironment::HasVariableOrFieldRecurse(std::string key, + bool setting) { + std::string property = (setting ? "set" : "get") + key; + if (this->HasVariable(property)) { + auto res = this->GetVariable(property); + TCallable *callable; + if (GetObjectHeap(res, callable)) + return true; + } + + return this->HasVariable(key); +} +TObject TRootEnvironment::GetVariable(GCList &ls, std::string key) { + ls.GetGC()->BarrierBegin(); + if (this->HasVariable("get" + key)) { + auto item = this->GetVariable("get" + key); + TCallable *callable; + if (GetObjectHeap(item, callable)) { + ls.GetGC()->BarrierEnd(); + return callable->Call(ls, {}); + } + } + + auto item = this->GetVariable(key); + ls.GetGC()->BarrierEnd(); + + return item; +} +TObject TRootEnvironment::SetVariable(GCList &ls, std::string key, + TObject value) { + ls.GetGC()->BarrierBegin(); + if (this->HasVariable("set" + key)) { + auto item = this->GetVariable("set" + key); + TCallable *callable; + if (GetObjectHeap(item, callable)) { + ls.GetGC()->BarrierEnd(); + return callable->Call(ls, {value}); + } + } + + this->SetVariable(key, value); + ls.GetGC()->BarrierEnd(); + + return value; +} + +void TRootEnvironment::LoadDependency( + std::shared_ptr gc, + std::shared_ptr vfs, + std::pair dep) { + for (auto item : this->dependencies) + if (item.first == dep.first && item.second.CompareTo(dep.second) >= 0) + return; + std::string name = {}; + name.append(dep.first); + name.push_back('-'); + name.append(dep.second.ToString()); + name.append(".crvm"); + std::string filename = "/" + name; + + if (vfs->RegularFileExists(filename)) { + auto file = vfs->OpenFile(filename, "rb"); + GCList ls(gc); + TFile *f = TFile::Create(ls); + f->Load(gc, file); + + LoadFileWithDependencies(gc, vfs, f); + } else + throw VMException("Could not open file: \"" + name + "\"."); +} +TObject TEnvironment::Eval(GCList &ls, std::string code) { + std::stringstream strm(code); + std::vector tokens; + int res = Lex("eval.tcross", strm, tokens); + if (res != 0) { + throw VMException("Lex error at line: " + std::to_string(res)); + } + Parser parser(tokens); + + SyntaxNode n = parser.ParseRoot(); + CodeGen gen; + gen.GenRoot(n); + auto ms = std::make_shared(true); + gen.Save(ms); + ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin); + TFile *f = TFile::Create(ls); + f->Load(ls.GetGC(), ms); + return this->LoadFile(ls.GetGC(), f); +} +TDictionary *TEnvironment::EnsureDictionary(std::shared_ptr gc, + std::string key) { + TObject item = this->GetVariable(key); + TDictionary *dict; + if (GetObjectHeap(item, dict)) + return dict; + GCList ls(gc); + dict = TDictionary::Create(ls); + this->DeclareVariable(key, dict); + return dict; +} +void TEnvironment::DeclareVariable(std::shared_ptr gc, + std::vector name, TObject o) { + if (name.size() == 0) + throw VMException("name can't be empty."); + + else if (name.size() == 1) { + GCList ls(gc); + + gc->BarrierBegin(); + this->DeclareVariable(name[0], o); + gc->BarrierEnd(); + } else { + GCList ls(gc); + + TObject v = this->GetVariable(name[0]); + TDictionary *dict = nullptr; + if (std::holds_alternative(v)) { + dict = + dynamic_cast(std::get(v).obj); + if (dict == nullptr) { + dict = TDictionary::Create(ls); + gc->BarrierBegin(); + this->SetVariable(name[0], dict); + gc->BarrierEnd(); + } + } else { + dict = TDictionary::Create(ls); + gc->BarrierBegin(); + this->DeclareVariable(name[0], dict); + gc->BarrierEnd(); + } + + for (size_t i = 1; i < name.size() - 1; i++) { + gc->BarrierBegin(); + auto v = dict->GetValue(name[i]); + gc->BarrierEnd(); + if (std::holds_alternative(v)) { + auto dict2 = dynamic_cast( + std::get(v).obj); + if (dict2 == nullptr) { + dict2 = TDictionary::Create(ls); + gc->BarrierBegin(); + dict->SetValue(name[i], dict2); + gc->BarrierEnd(); + } + dict = dict2; + } else { + auto dict2 = TDictionary::Create(ls); + gc->BarrierBegin(); + dict->SetValue(name[i], dict2); + gc->BarrierEnd(); + dict = dict2; + } + } + gc->BarrierBegin(); + dict->SetValue(name[name.size() - 1], o); + gc->BarrierEnd(); + } +} + +TObject TEnvironment::LoadFile(std::shared_ptr gc, TFile *file) { + file->EnsureCanRunInCrossLang(); + for (size_t i = 0; i < file->classes.size(); i++) { + this->GetRootEnvironment()->classes.push_back( + std::pair(file, (uint32_t)i)); + std::vector clsPart = {"New"}; + clsPart.insert(clsPart.end(), file->classes[i].name.begin(), + file->classes[i].name.end()); + GCList ls(gc); + std::vector name = file->classes[i].name; + auto rootEnv = this->GetRootEnvironment(); + this->DeclareVariable( + gc, clsPart, + TExternalMethod::Create( + ls, "Create instance of the class", {"$$args"}, + [rootEnv, file, i](GCList &ls, + std::vector args) -> TObject { + return TClassObject::Create(ls, file, i, rootEnv, args); + })); + for (auto meth : file->classes[i].entry) { + + if (meth.isFunction && meth.modifier == TClassModifier::Static) { + std::vector method = file->classes[i].name; + method.push_back(meth.name); + auto clo = TClosure::Create(ls, this, file, meth.chunkId); + clo->closure->name = JoinPeriod(method); + + clo->documentation = meth.documentation; + this->DeclareVariable(gc, method, clo); + } + } + } + for (auto fn : file->functions) { + + if (fn.first.size() < 2) + throw VMException("No function name."); + + std::vector items(fn.first.begin() + 1, fn.first.end()); + + if (fn.second >= file->chunks.size()) + throw VMException("ChunkId out of bounds."); + TFileChunk *chunk = file->chunks[fn.second]; + chunk->name = JoinPeriod(items); + GCList ls(gc); + TClosure *closure = TClosure::Create(ls, this, file, fn.second); + closure->documentation = fn.first[0]; + this->DeclareVariable(gc, items, closure); + } + if (!file->chunks.empty()) { + GCList ls(gc); + TClosure *closure = TClosure::Create(ls, this, file, 0); + return closure->Call(ls, {}); + } + return nullptr; +} +void TRootEnvironment::LoadFileWithDependencies( + std::shared_ptr gc, + std::shared_ptr vfs, TFile *file) { + this->dependencies.push_back( + std::pair(file->name, file->version)); + for (auto item : file->dependencies) { + LoadDependency(gc, vfs, item); + } + LoadFile(gc, file); +} +void TRootEnvironment::LoadFileWithDependencies( + std::shared_ptr gc, + std::shared_ptr vfs, + Tesses::Framework::Filesystem::VFSPath path) { + + if (vfs->RegularFileExists(path)) { + auto file = vfs->OpenFile(path, "rb"); + GCList ls(gc); + TFile *f = TFile::Create(ls); + f->Load(gc, file); + + auto dir = + std::make_shared( + vfs, path.GetParent()); + LoadFileWithDependencies(gc, dir, f); + } else + throw VMException("Could not open file: \"" + path.GetFileName() + + "\"."); +} +TDictionary *TRootEnvironment::GetDictionary() { return this->dict; } +TObject TRootEnvironment::GetVariable(std::string key) { + return this->dict->GetValue(key); +} +void TRootEnvironment::SetVariable(std::string key, TObject value) { + this->dict->SetValue(key, value); +} +void TRootEnvironment::DeclareVariable(std::string key, TObject value) { + return this->dict->SetValue(key, value); +} +bool TRootEnvironment::HasVariable(std::string key) { + return this->dict->HasValue(key); +} +bool TRootEnvironment::HasVariableRecurse(std::string key) { + return this->dict->HasValue(key); +} +TEnvironment *TRootEnvironment::GetParentEnvironment() { return this; } +TRootEnvironment *TRootEnvironment::GetRootEnvironment() { return this; } + +TRootEnvironment::TRootEnvironment(TDictionary *dict) { this->dict = dict; } + +void TRootEnvironment::Mark() { + if (this->marked) + return; + this->marked = true; + this->dict->Mark(); + if (this->permissions.customConsole != nullptr) + this->permissions.customConsole->Mark(); + for (auto priv : this->private_file_data) + priv.second->Mark(); + for (auto defer : this->defers) + defer->Mark(); + if (this->error != nullptr) + this->error->Mark(); + for (auto cls : this->classes) + cls.first->Mark(); +} +TRootEnvironment *TRootEnvironment::Create(GCList *gc, TDictionary *dict) { + TRootEnvironment *env = new TRootEnvironment(dict); + std::shared_ptr _gc = gc->GetGC(); + gc->Add(env); + _gc->Watch(env); + return env; +} +TRootEnvironment *TRootEnvironment::Create(GCList &gc, TDictionary *dict) { + TRootEnvironment *env = new TRootEnvironment(dict); + std::shared_ptr _gc = gc.GetGC(); + gc.Add(env); + _gc->Watch(env); + return env; +} + +bool TRootEnvironment::HandleException(std::shared_ptr gc, + TEnvironment *env, TObject err) { + if (error != nullptr) { + GCList ls(gc); + return ToBool(error->Call( + ls, {TDictionary::Create(ls, {TDItem("IsBreakpoint", false), + TDItem("Exception", err), + TDItem("Environment", env)})})); + } + return false; +} +bool TRootEnvironment::HandleBreakpoint(std::shared_ptr gc, + TEnvironment *env, TObject err) { + if (error != nullptr) { + GCList ls(gc); + return ToBool(error->Call( + ls, {TDictionary::Create(ls, {TDItem("IsBreakpoint", true), + TDItem("Breakpoint", err), + TDItem("Environment", env)})})); + } + return true; +} +void TRootEnvironment::RegisterOnError(TCallable *call) { this->error = call; } +}; // namespace Tesses::CrossLang diff --git a/src/types/streamheapobject.cpp b/src/types/streamheapobject.cpp index 3f9f38a..cb09367 100644 --- a/src/types/streamheapobject.cpp +++ b/src/types/streamheapobject.cpp @@ -1,224 +1,217 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - int64_t TObjectStream::_GetPosInternal() - { - return Tesses::Framework::Streams::Stream::GetLength(); - } - TObjectStream::TObjectStream(std::shared_ptr gc, TObject obj) - { - this->ls = new GCList(gc); - this->ls->Add(obj); - this->obj = obj; - TDictionary* dict; - if(GetObjectHeap(obj,dict)) - { - gc->BarrierBegin(); - if(!dict->HasValue("Read")) - { - dict->DeclareFunction(gc,"Read","Read from stream",{"buff","off","len"}, [](GCList& ls, std::vector args)->TObject { +namespace Tesses::CrossLang { +int64_t TObjectStream::_GetPosInternal() { + return Tesses::Framework::Streams::Stream::GetLength(); +} +TObjectStream::TObjectStream(std::shared_ptr gc, TObject obj) { + this->ls = new GCList(gc); + this->ls->Add(obj); + this->obj = obj; + TDictionary *dict; + if (GetObjectHeap(obj, dict)) { + gc->BarrierBegin(); + if (!dict->HasValue("Read")) { + dict->DeclareFunction( + gc, "Read", "Read from stream", {"buff", "off", "len"}, + [](GCList &ls, std::vector args) -> TObject { return (int64_t)0; }); - } - if(!dict->HasValue("Write")) - { - dict->DeclareFunction(gc,"Write","Write to stream",{"buff","off","len"}, [](GCList& ls, std::vector args)->TObject { + } + if (!dict->HasValue("Write")) { + dict->DeclareFunction( + gc, "Write", "Write to stream", {"buff", "off", "len"}, + [](GCList &ls, std::vector args) -> TObject { return (int64_t)0; }); - } - if(!dict->HasValue("getCanRead")) - { - dict->DeclareFunction(gc,"getCanRead","Can read from stream",{}, [](GCList& ls, std::vector args)->TObject { + } + if (!dict->HasValue("getCanRead")) { + dict->DeclareFunction( + gc, "getCanRead", "Can read from stream", {}, + [](GCList &ls, std::vector args) -> TObject { return false; }); - } + } - if(!dict->HasValue("getCanWrite")) - { - dict->DeclareFunction(gc,"getCanWrite","Can write to stream",{}, [](GCList& ls, std::vector args)->TObject { + if (!dict->HasValue("getCanWrite")) { + dict->DeclareFunction( + gc, "getCanWrite", "Can write to stream", {}, + [](GCList &ls, std::vector args) -> TObject { return false; }); - } - if(!dict->HasValue("getCanSeek")) - { - dict->DeclareFunction(gc,"getCanSeek","Can seek in stream",{}, [](GCList& ls, std::vector args)->TObject { + } + if (!dict->HasValue("getCanSeek")) { + dict->DeclareFunction( + gc, "getCanSeek", "Can seek in stream", {}, + [](GCList &ls, std::vector args) -> TObject { return false; }); - } - if(!dict->HasValue("getPosition")) - { - dict->DeclareFunction(gc,"getPosition","Can get position in stream",{}, [](GCList& ls, std::vector args)->TObject { + } + if (!dict->HasValue("getPosition")) { + dict->DeclareFunction( + gc, "getPosition", "Can get position in stream", {}, + [](GCList &ls, std::vector args) -> TObject { return (int64_t)0; }); - } - if(!dict->HasValue("getLength")) - { - dict->DeclareFunction(gc,"getPosition","Can get position in stream",{}, [this](GCList& ls, std::vector args)->TObject { + } + if (!dict->HasValue("getLength")) { + dict->DeclareFunction( + gc, "getPosition", "Can get position in stream", {}, + [this](GCList &ls, std::vector args) -> TObject { return _GetPosInternal(); }); - } - if(!dict->HasValue("getEndOfStream")) - { - dict->DeclareFunction(gc,"getEndOfStream","Is at end of stream",{}, [](GCList& ls, std::vector args)->TObject { + } + if (!dict->HasValue("getEndOfStream")) { + dict->DeclareFunction( + gc, "getEndOfStream", "Is at end of stream", {}, + [](GCList &ls, std::vector args) -> TObject { return false; }); - } - gc->BarrierEnd(); } + gc->BarrierEnd(); } - bool TObjectStream::EndOfStream() - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - auto res = dict->CallMethod(*ls, "getEndOfStream",{}); - bool r; - if(GetObject(res,r)) return r; - } - - return false; - } - size_t TObjectStream::Read(uint8_t* buff, size_t sz) - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - GCList ls2(this->ls->GetGC()); - - TByteArray* arr=TByteArray::Create(ls2); - arr->data.resize(sz); - - auto res = dict->CallMethod(ls2, "Read",{arr, (int64_t)0L, (int64_t)sz}); - - memcpy(buff,arr->data.data(),std::min(sz,arr->data.size())); - - int64_t r; - if(GetObject(res,r)) return r; - } - return 0; - } - size_t TObjectStream::Write(const uint8_t* buff, size_t sz) - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - GCList ls2(this->ls->GetGC()); - - TByteArray* arr=TByteArray::Create(ls2); - arr->data.resize(sz); - memcpy(arr->data.data(), buff, sz); - - auto res = dict->CallMethod(ls2, "Write",{arr, (int64_t)0L, (int64_t)sz}); - int64_t r; - if(GetObject(res,r)) return r; - } - - return 0; - } - bool TObjectStream::CanRead() - { - - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - auto res = dict->CallMethod(*ls, "getCanRead",{}); - bool r; - if(GetObject(res,r)) return r; - } - - return false; - } - bool TObjectStream::CanWrite() - { - - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - auto res = dict->CallMethod(*ls, "getCanWrite",{}); - bool r; - if(GetObject(res,r)) return r; - } - return false; - } - bool TObjectStream::CanSeek() - { - - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - auto res = dict->CallMethod(*ls, "getCanSeek",{}); - bool r; - if(GetObject(res,r)) return r; - } - - return false; - } - int64_t TObjectStream::GetPosition() - { - - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - auto res = dict->CallMethod(*ls, "getPosition",{}); - int64_t r; - if(GetObject(res,r)) return r; - } - - return 0; - } - int64_t TObjectStream::GetLength() - { - - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - auto res = dict->CallMethod(*ls, "getEndOfStream",{}); - bool r; - if(GetObject(res,r)) return r; - } - - return Tesses::Framework::Streams::Stream::GetLength(); - } - void TObjectStream::Flush() - { - - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - dict->CallMethod(*ls, "Flush",{}); - - } - - } - void TObjectStream::Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence) - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - dict->CallMethod(*ls, "Seek",{pos,(int64_t)(whence == Tesses::Framework::Streams::SeekOrigin::Begin ? 0 : whence == Tesses::Framework::Streams::SeekOrigin::Current ? 1 : 2) }); - } - - } - void TObjectStream::Close() - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - dict->CallMethod(*ls,"Dispose",{}); - } - } - TObjectStream::~TObjectStream() - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - dict->CallMethod(*ls,"Dispose",{}); - } - delete this->ls; +} +bool TObjectStream::EndOfStream() { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + auto res = dict->CallMethod(*ls, "getEndOfStream", {}); + bool r; + if (GetObject(res, r)) + return r; } + return false; +} +size_t TObjectStream::Read(uint8_t *buff, size_t sz) { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + GCList ls2(this->ls->GetGC()); - - -} \ No newline at end of file + TByteArray *arr = TByteArray::Create(ls2); + arr->data.resize(sz); + + auto res = + dict->CallMethod(ls2, "Read", {arr, (int64_t)0L, (int64_t)sz}); + + memcpy(buff, arr->data.data(), std::min(sz, arr->data.size())); + + int64_t r; + if (GetObject(res, r)) + return r; + } + return 0; +} +size_t TObjectStream::Write(const uint8_t *buff, size_t sz) { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + GCList ls2(this->ls->GetGC()); + + TByteArray *arr = TByteArray::Create(ls2); + arr->data.resize(sz); + memcpy(arr->data.data(), buff, sz); + + auto res = + dict->CallMethod(ls2, "Write", {arr, (int64_t)0L, (int64_t)sz}); + int64_t r; + if (GetObject(res, r)) + return r; + } + + return 0; +} +bool TObjectStream::CanRead() { + + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + auto res = dict->CallMethod(*ls, "getCanRead", {}); + bool r; + if (GetObject(res, r)) + return r; + } + + return false; +} +bool TObjectStream::CanWrite() { + + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + auto res = dict->CallMethod(*ls, "getCanWrite", {}); + bool r; + if (GetObject(res, r)) + return r; + } + return false; +} +bool TObjectStream::CanSeek() { + + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + auto res = dict->CallMethod(*ls, "getCanSeek", {}); + bool r; + if (GetObject(res, r)) + return r; + } + + return false; +} +int64_t TObjectStream::GetPosition() { + + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + auto res = dict->CallMethod(*ls, "getPosition", {}); + int64_t r; + if (GetObject(res, r)) + return r; + } + + return 0; +} +int64_t TObjectStream::GetLength() { + + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + auto res = dict->CallMethod(*ls, "getEndOfStream", {}); + bool r; + if (GetObject(res, r)) + return r; + } + + return Tesses::Framework::Streams::Stream::GetLength(); +} +void TObjectStream::Flush() { + + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + dict->CallMethod(*ls, "Flush", {}); + } +} +void TObjectStream::Seek(int64_t pos, + Tesses::Framework::Streams::SeekOrigin whence) { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + dict->CallMethod( + *ls, "Seek", + {pos, + (int64_t)(whence == Tesses::Framework::Streams::SeekOrigin::Begin + ? 0 + : whence == + Tesses::Framework::Streams::SeekOrigin::Current + ? 1 + : 2)}); + } +} +void TObjectStream::Close() { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + dict->CallMethod(*ls, "Dispose", {}); + } +} +TObjectStream::~TObjectStream() { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + dict->CallMethod(*ls, "Dispose", {}); + } + delete this->ls; +} + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/subenvironment.cpp b/src/types/subenvironment.cpp index 37c167a..4064ce7 100644 --- a/src/types/subenvironment.cpp +++ b/src/types/subenvironment.cpp @@ -1,246 +1,213 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang { - TDictionary* TSubEnvironment::GetDictionary() - { - return this->dict; +namespace Tesses::CrossLang { +TDictionary *TSubEnvironment::GetDictionary() { return this->dict; } +bool TSubEnvironment::HasVariableOrFieldRecurse(std::string key, bool setting) { + std::string property = (setting ? "set" : "get") + key; + if (this->HasVariable(property)) { + auto res = this->GetVariable(property); + TCallable *callable; + if (GetObjectHeap(res, callable)) + return true; } - bool TSubEnvironment::HasVariableOrFieldRecurse(std::string key,bool setting) - { - std::string property=(setting? "set":"get") + key; - if(this->HasVariable(property)) - { - auto res = this->GetVariable(property); - TCallable* callable; - if(GetObjectHeap(res,callable)) return true; + + if (this->HasVariable(key)) + return true; + + return this->env->HasVariableOrFieldRecurse(key, setting); +} +TObject TSubEnvironment::GetVariable(GCList &ls, std::string key) { + ls.GetGC()->BarrierBegin(); + if (this->HasVariable("get" + key)) { + auto item = this->GetVariable("get" + key); + TCallable *callable; + if (GetObjectHeap(item, callable)) { + ls.GetGC()->BarrierEnd(); + return callable->Call(ls, {}); } - - if(this->HasVariable(key)) return true; - - return this->env->HasVariableOrFieldRecurse(key,setting); } - TObject TSubEnvironment::GetVariable(GCList& ls, std::string key) - { - ls.GetGC()->BarrierBegin(); - if(this->HasVariable("get" + key)) - { - auto item = this->GetVariable("get"+key); - TCallable* callable; - if(GetObjectHeap(item,callable)) - { - ls.GetGC()->BarrierEnd(); - return callable->Call(ls,{}); - } - } - - if(this->HasVariable(key)) - { - auto item = this->GetVariable(key); - ls.GetGC()->BarrierEnd(); - return item; - } - if(this->env->HasVariableOrFieldRecurse(key)) - { - ls.GetGC()->BarrierEnd(); - return this->env->GetVariable(ls,key); - } + + if (this->HasVariable(key)) { + auto item = this->GetVariable(key); ls.GetGC()->BarrierEnd(); - - - - return Undefined(); + return item; } - bool TSubEnvironment::HasConstForSet(std::string key) - { - if(this->dict->HasValue(key)) - { - return this->HasConstForDeclare(key); - } - if(this->env->HasVariableRecurse(key)) - { - return this->env->HasConstForSet(key); - } - return false; - } - TObject TSubEnvironment::SetVariable(GCList& ls, std::string key, TObject value) - { - ls.GetGC()->BarrierBegin(); - if(this->HasVariable("set" + key)) - { - auto item = this->GetVariable("set"+key); - TCallable* callable; - if(GetObjectHeap(item,callable)) - { - ls.GetGC()->BarrierEnd(); - return callable->Call(ls,{value}); - } - } - - if(this->HasVariable(key)) - { - this->SetVariable(key,value); - ls.GetGC()->BarrierEnd(); - return value; - } - if(this->env->HasVariableOrFieldRecurse(key,true)) - { - ls.GetGC()->BarrierEnd(); - return this->env->SetVariable(ls,key,value); - } - else - { - this->env->SetVariable(key,value); - - ls.GetGC()->BarrierEnd(); - return value; - } + if (this->env->HasVariableOrFieldRecurse(key)) { ls.GetGC()->BarrierEnd(); - - + return this->env->GetVariable(ls, key); } - - TObject TSubEnvironment::GetVariable(std::string key) - { - if(this->dict->HasValue(key)) - { - return this->dict->GetValue(key); - } - if(this->env->HasVariableRecurse(key)) - { - return this->env->GetVariable(key); - } - return Undefined(); - } - void TSubEnvironment::DeclareVariable(std::string key,TObject value) - { - this->dict->SetValue(key,value); - } - void TSubEnvironment::SetVariable(std::string key, TObject value) - { - if(this->dict->HasValue(key)) - { - this->dict->SetValue(key,value); - return; - } - if(this->env->HasVariableRecurse(key)) - { - this->env->SetVariable(key,value); - } - else - { - this->dict->SetValue(key,value); - } - } - bool TSubEnvironment::HasVariable(std::string key) - { - return this->dict->HasValue(key); - } - bool TSubEnvironment::HasVariableRecurse(std::string key) - { - if(this->dict->HasValue(key)) return true; - return this->env->HasVariableRecurse(key); - } - TSubEnvironment::TSubEnvironment(TEnvironment* env,TDictionary* dict) - { - this->env = env; - this->dict = dict; - } - TSubEnvironment* TEnvironment::GetSubEnvironment(TDictionary* dict) - { - TSubEnvironment* subEnv = new TSubEnvironment(this,dict); - return subEnv; - } - TObject TEnvironment::CallFunction(GCList& ls, std::string key, std::vector args) - { - ls.GetGC()->BarrierBegin(); - auto res = this->GetVariable(key); - ls.GetGC()->BarrierEnd(); - TCallable* callable; + ls.GetGC()->BarrierEnd(); - if(GetObjectHeap(res,callable)) - { - return callable->Call(ls,args); - } - return Undefined(); + return Undefined(); +} +bool TSubEnvironment::HasConstForSet(std::string key) { + if (this->dict->HasValue(key)) { + return this->HasConstForDeclare(key); + } + if (this->env->HasVariableRecurse(key)) { + return this->env->HasConstForSet(key); + } + return false; +} +TObject TSubEnvironment::SetVariable(GCList &ls, std::string key, + TObject value) { + ls.GetGC()->BarrierBegin(); + if (this->HasVariable("set" + key)) { + auto item = this->GetVariable("set" + key); + TCallable *callable; + if (GetObjectHeap(item, callable)) { + ls.GetGC()->BarrierEnd(); + return callable->Call(ls, {value}); + } } - TObject TEnvironment::CallFunctionWithFatalError(GCList& ls, std::string key, std::vector args) - { - ls.GetGC()->BarrierBegin(); - auto res = this->GetVariable(key); - ls.GetGC()->BarrierEnd(); - TCallable* callable; - if(GetObjectHeap(res,callable)) - { - return callable->CallWithFatalError(ls,args); - } - return Undefined(); + if (this->HasVariable(key)) { + this->SetVariable(key, value); + ls.GetGC()->BarrierEnd(); + return value; } - TSubEnvironment* TEnvironment::GetSubEnvironment(GCList* gc) - { - auto dict=TDictionary::Create(gc); - TSubEnvironment* sEnv = this->GetSubEnvironment(dict); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(sEnv); - _gc->Watch(sEnv); - return sEnv; + if (this->env->HasVariableOrFieldRecurse(key, true)) { + ls.GetGC()->BarrierEnd(); + return this->env->SetVariable(ls, key, value); + } else { + this->env->SetVariable(key, value); + + ls.GetGC()->BarrierEnd(); + return value; } - TSubEnvironment* TEnvironment::GetSubEnvironment(GCList& gc) - { - auto dict=TDictionary::Create(gc); - TSubEnvironment* sEnv = this->GetSubEnvironment(dict); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(sEnv); - _gc->Watch(sEnv); - return sEnv; + ls.GetGC()->BarrierEnd(); +} + +TObject TSubEnvironment::GetVariable(std::string key) { + if (this->dict->HasValue(key)) { + return this->dict->GetValue(key); } - TSubEnvironment* TSubEnvironment::Create(GCList* gc, TEnvironment* env, TDictionary* dict) - { - TSubEnvironment* senv = new TSubEnvironment(env,dict); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(senv); - _gc->Watch(senv); - return senv; + if (this->env->HasVariableRecurse(key)) { + return this->env->GetVariable(key); } - TSubEnvironment* TSubEnvironment::Create(GCList& gc, TEnvironment* env, TDictionary* dict) - { - TSubEnvironment* senv = new TSubEnvironment(env,dict); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(senv); - _gc->Watch(senv); - return senv; + return Undefined(); +} +void TSubEnvironment::DeclareVariable(std::string key, TObject value) { + this->dict->SetValue(key, value); +} +void TSubEnvironment::SetVariable(std::string key, TObject value) { + if (this->dict->HasValue(key)) { + this->dict->SetValue(key, value); + return; } - TEnvironment* TSubEnvironment::GetParentEnvironment() - { - return this->env; + if (this->env->HasVariableRecurse(key)) { + this->env->SetVariable(key, value); + } else { + this->dict->SetValue(key, value); } - TRootEnvironment* TSubEnvironment::GetRootEnvironment() - { - return this->env->GetRootEnvironment(); +} +bool TSubEnvironment::HasVariable(std::string key) { + return this->dict->HasValue(key); +} +bool TSubEnvironment::HasVariableRecurse(std::string key) { + if (this->dict->HasValue(key)) + return true; + return this->env->HasVariableRecurse(key); +} +TSubEnvironment::TSubEnvironment(TEnvironment *env, TDictionary *dict) { + this->env = env; + this->dict = dict; +} +TSubEnvironment *TEnvironment::GetSubEnvironment(TDictionary *dict) { + TSubEnvironment *subEnv = new TSubEnvironment(this, dict); + return subEnv; +} +TObject TEnvironment::CallFunction(GCList &ls, std::string key, + std::vector args) { + ls.GetGC()->BarrierBegin(); + auto res = this->GetVariable(key); + ls.GetGC()->BarrierEnd(); + TCallable *callable; + + if (GetObjectHeap(res, callable)) { + return callable->Call(ls, args); } - - void TSubEnvironment::Mark() - { - if(this->marked) return; - this->marked=true; - this->dict->Mark(); - this->env->Mark(); - for(auto defer : defers) defer->Mark(); + return Undefined(); +} +TObject TEnvironment::CallFunctionWithFatalError(GCList &ls, std::string key, + std::vector args) { + ls.GetGC()->BarrierBegin(); + auto res = this->GetVariable(key); + ls.GetGC()->BarrierEnd(); + TCallable *callable; + + if (GetObjectHeap(res, callable)) { + return callable->CallWithFatalError(ls, args); } - void TEnvironment::DeclareFunction(std::shared_ptr gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb) - { - gc->BarrierBegin(); - GCList ls(gc); - this->DeclareVariable(key, TExternalMethod::Create(ls,documentation,argNames,cb)); - gc->BarrierEnd(); - } - - void TEnvironment::DeclareFunction(std::shared_ptr gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb,std::function destroy) - { - gc->BarrierBegin(); - GCList ls(gc); - this->DeclareVariable(key, TExternalMethod::Create(ls,documentation,argNames,cb,destroy)); - gc->BarrierEnd(); - } - -}; + return Undefined(); +} +TSubEnvironment *TEnvironment::GetSubEnvironment(GCList *gc) { + auto dict = TDictionary::Create(gc); + TSubEnvironment *sEnv = this->GetSubEnvironment(dict); + std::shared_ptr _gc = gc->GetGC(); + gc->Add(sEnv); + _gc->Watch(sEnv); + return sEnv; +} +TSubEnvironment *TEnvironment::GetSubEnvironment(GCList &gc) { + auto dict = TDictionary::Create(gc); + TSubEnvironment *sEnv = this->GetSubEnvironment(dict); + std::shared_ptr _gc = gc.GetGC(); + gc.Add(sEnv); + _gc->Watch(sEnv); + return sEnv; +} +TSubEnvironment *TSubEnvironment::Create(GCList *gc, TEnvironment *env, + TDictionary *dict) { + TSubEnvironment *senv = new TSubEnvironment(env, dict); + std::shared_ptr _gc = gc->GetGC(); + gc->Add(senv); + _gc->Watch(senv); + return senv; +} +TSubEnvironment *TSubEnvironment::Create(GCList &gc, TEnvironment *env, + TDictionary *dict) { + TSubEnvironment *senv = new TSubEnvironment(env, dict); + std::shared_ptr _gc = gc.GetGC(); + gc.Add(senv); + _gc->Watch(senv); + return senv; +} +TEnvironment *TSubEnvironment::GetParentEnvironment() { return this->env; } +TRootEnvironment *TSubEnvironment::GetRootEnvironment() { + return this->env->GetRootEnvironment(); +} + +void TSubEnvironment::Mark() { + if (this->marked) + return; + this->marked = true; + this->dict->Mark(); + this->env->Mark(); + for (auto defer : defers) + defer->Mark(); +} +void TEnvironment::DeclareFunction( + std::shared_ptr gc, std::string key, std::string documentation, + std::vector argNames, + std::function args)> cb) { + gc->BarrierBegin(); + GCList ls(gc); + this->DeclareVariable( + key, TExternalMethod::Create(ls, documentation, argNames, cb)); + gc->BarrierEnd(); +} + +void TEnvironment::DeclareFunction( + std::shared_ptr gc, std::string key, std::string documentation, + std::vector argNames, + std::function args)> cb, + std::function destroy) { + gc->BarrierBegin(); + GCList ls(gc); + this->DeclareVariable( + key, TExternalMethod::Create(ls, documentation, argNames, cb, destroy)); + gc->BarrierEnd(); +} + +}; // namespace Tesses::CrossLang diff --git a/src/types/vfsheapobject.cpp b/src/types/vfsheapobject.cpp index 17907c4..c21b221 100644 --- a/src/types/vfsheapobject.cpp +++ b/src/types/vfsheapobject.cpp @@ -2,402 +2,371 @@ namespace Tesses::CrossLang { - TObjectVFS::TObjectVFS(std::shared_ptr gc, TObject obj) - { - this->ls = new GCList(gc); - this->ls->Add(obj); - this->obj = obj; - - +TObjectVFS::TObjectVFS(std::shared_ptr gc, TObject obj) { + this->ls = new GCList(gc); + this->ls->Add(obj); + this->obj = obj; +} +Tesses::Framework::Filesystem::FIFOCreationResult +TObjectVFS::CreateFIFO(Tesses::Framework::Filesystem::VFSPath path) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + auto res = dict->CallMethod(ls, "CreateFIFO", {path}); + int64_t n = 0; + if (GetObject(res, n)) + return (Tesses::Framework::Filesystem::FIFOCreationResult)n; } - Tesses::Framework::Filesystem::FIFOCreationResult TObjectVFS::CreateFIFO(Tesses::Framework::Filesystem::VFSPath path) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - auto res = dict->CallMethod(ls, "CreateFIFO",{path}); - int64_t n=0; - if(GetObject(res, n)) return (Tesses::Framework::Filesystem::FIFOCreationResult)n; - } - return Tesses::Framework::Filesystem::FIFOCreationResult::UnknownError; - } - - std::shared_ptr TObjectVFS::OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - auto res = dict->CallMethod(ls, "OpenFile",{path,mode}); - std::shared_ptr strm; - if(GetObject(res,strm)) - { - return strm; - } - } - return nullptr; - } - void TObjectVFS::CreateDirectory(Tesses::Framework::Filesystem::VFSPath path) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "CreateDirectory",{path}); - - } - - } - void TObjectVFS::DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path) - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "DeleteDirectory",{path}); - + return Tesses::Framework::Filesystem::FIFOCreationResult::UnknownError; +} + +std::shared_ptr +TObjectVFS::OpenFile(Tesses::Framework::Filesystem::VFSPath path, + std::string mode) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + auto res = dict->CallMethod(ls, "OpenFile", {path, mode}); + std::shared_ptr strm; + if (GetObject(res, strm)) { + return strm; } } - void TObjectVFS::Lock(Tesses::Framework::Filesystem::VFSPath path) - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "Lock",{path}); - - } + return nullptr; +} +void TObjectVFS::CreateDirectory(Tesses::Framework::Filesystem::VFSPath path) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "CreateDirectory", {path}); } - void TObjectVFS::Unlock(Tesses::Framework::Filesystem::VFSPath path) - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "Unlock",{path}); - - } +} +void TObjectVFS::DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path) { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "DeleteDirectory", {path}); } - void TObjectVFS::CreateSymlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath symlinkFile) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "CreateSymlink",{existingFile,symlinkFile}); - - } +} +void TObjectVFS::Lock(Tesses::Framework::Filesystem::VFSPath path) { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "Lock", {path}); } - void TObjectVFS::CreateHardlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath newName) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "CreateHardlink",{existingFile,newName}); - - } +} +void TObjectVFS::Unlock(Tesses::Framework::Filesystem::VFSPath path) { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "Unlock", {path}); } - void TObjectVFS::DeleteFile(Tesses::Framework::Filesystem::VFSPath path) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "DeleteFile",{path}); - - } +} +void TObjectVFS::CreateSymlink( + Tesses::Framework::Filesystem::VFSPath existingFile, + Tesses::Framework::Filesystem::VFSPath symlinkFile) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "CreateSymlink", {existingFile, symlinkFile}); } - void TObjectVFS::DeleteDirectoryRecurse(Tesses::Framework::Filesystem::VFSPath path) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "DeleteDirectoryRecurse",{path}); - - } +} +void TObjectVFS::CreateHardlink( + Tesses::Framework::Filesystem::VFSPath existingFile, + Tesses::Framework::Filesystem::VFSPath newName) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "CreateHardlink", {existingFile, newName}); } - Tesses::Framework::Filesystem::VFSPathEnumerator TObjectVFS::EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList* ls=new GCList(this->ls->GetGC()); - auto res = dict->CallMethod(*ls, "EnumeratePaths",{path}); - auto enumerator = TEnumerator::CreateFromObject(*ls,res); - return Tesses::Framework::Filesystem::VFSPathEnumerator([path,enumerator,ls](Tesses::Framework::Filesystem::VFSPath& path0)->bool{ - if(enumerator == nullptr) return false; - while(enumerator->MoveNext(ls->GetGC())) - { +} +void TObjectVFS::DeleteFile(Tesses::Framework::Filesystem::VFSPath path) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "DeleteFile", {path}); + } +} +void TObjectVFS::DeleteDirectoryRecurse( + Tesses::Framework::Filesystem::VFSPath path) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "DeleteDirectoryRecurse", {path}); + } +} +Tesses::Framework::Filesystem::VFSPathEnumerator +TObjectVFS::EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList *ls = new GCList(this->ls->GetGC()); + auto res = dict->CallMethod(*ls, "EnumeratePaths", {path}); + auto enumerator = TEnumerator::CreateFromObject(*ls, res); + return Tesses::Framework::Filesystem::VFSPathEnumerator( + [path, enumerator, + ls](Tesses::Framework::Filesystem::VFSPath &path0) -> bool { + if (enumerator == nullptr) + return false; + while (enumerator->MoveNext(ls->GetGC())) { auto res = enumerator->GetCurrent(*ls); std::string name; Tesses::Framework::Filesystem::VFSPath path1; - if(GetObject(res,path1)) - { + if (GetObject(res, path1)) { path0 = path1; return true; - } - else if(GetObject(res,name)) - { + } else if (GetObject(res, name)) { path0 = path / name; return true; } } return false; - },[ls]()->void{ - delete ls; - }); - } - return Tesses::Framework::Filesystem::VFSPathEnumerator(); + }, + [ls]() -> void { delete ls; }); } - void TObjectVFS::MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest) - { + return Tesses::Framework::Filesystem::VFSPathEnumerator(); +} +void TObjectVFS::MoveFile(Tesses::Framework::Filesystem::VFSPath src, + Tesses::Framework::Filesystem::VFSPath dest) { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "MoveFile",{src,dest}); - + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "MoveFile", {src, dest}); + } +} +void TObjectVFS::MoveDirectory(Tesses::Framework::Filesystem::VFSPath src, + Tesses::Framework::Filesystem::VFSPath dest) { + + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "MoveDirectory", {src, dest}); + } +} +Tesses::Framework::Filesystem::VFSPath +TObjectVFS::ReadLink(Tesses::Framework::Filesystem::VFSPath path) { + + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + auto res = dict->CallMethod(ls, "ReadLink", {path}); + Tesses::Framework::Filesystem::VFSPath myPath; + if (GetObject(res, myPath)) { + return myPath; } } - void TObjectVFS::MoveDirectory(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest) - { + return Tesses::Framework::Filesystem::VFSPath(); +} +std::string +TObjectVFS::VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path) { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "MoveDirectory",{src,dest}); - + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + auto res = dict->CallMethod(ls, "VFSPathToSystem", {path}); + std::string myPath; + if (GetObject(res, myPath)) { + return myPath; } } - Tesses::Framework::Filesystem::VFSPath TObjectVFS::ReadLink(Tesses::Framework::Filesystem::VFSPath path) - { + return "/"; +} +Tesses::Framework::Filesystem::VFSPath +TObjectVFS::SystemToVFSPath(std::string path) { + TDictionary *dict; - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - auto res = dict->CallMethod(ls, "ReadLink",{path}); - Tesses::Framework::Filesystem::VFSPath myPath; - if(GetObject(res,myPath)) - { - return myPath; - } - } - return Tesses::Framework::Filesystem::VFSPath(); - } - std::string TObjectVFS::VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path) - { - - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - auto res = dict->CallMethod(ls, "VFSPathToSystem",{path}); - std::string myPath; - if(GetObject(res,myPath)) - { - return myPath; - } - } - return "/"; - } - Tesses::Framework::Filesystem::VFSPath TObjectVFS::SystemToVFSPath(std::string path) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - auto res = dict->CallMethod(ls, "SystemToVFSPath",{path}); - Tesses::Framework::Filesystem::VFSPath myPath; - if(GetObject(res,myPath)) - { - return myPath; - } - } - return Tesses::Framework::Filesystem::VFSPath(); - } - void TObjectVFS::SetDate(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Date::DateTime lastWrite, Tesses::Framework::Date::DateTime lastAccess) - { - - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "SetDate",{path,std::make_shared(lastWrite),std::make_shared(lastAccess)}); - + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + auto res = dict->CallMethod(ls, "SystemToVFSPath", {path}); + Tesses::Framework::Filesystem::VFSPath myPath; + if (GetObject(res, myPath)) { + return myPath; } } - void TObjectVFS::Chmod(Tesses::Framework::Filesystem::VFSPath path, uint32_t mode) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "Chmod",{path,(int64_t)mode}); - + return Tesses::Framework::Filesystem::VFSPath(); +} +void TObjectVFS::SetDate(Tesses::Framework::Filesystem::VFSPath path, + Tesses::Framework::Date::DateTime lastWrite, + Tesses::Framework::Date::DateTime lastAccess) { + + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod( + ls, "SetDate", + {path, + std::make_shared(lastWrite), + std::make_shared(lastAccess)}); + } +} +void TObjectVFS::Chmod(Tesses::Framework::Filesystem::VFSPath path, + uint32_t mode) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "Chmod", {path, (int64_t)mode}); + } +} +void TObjectVFS::Chown(Tesses::Framework::Filesystem::VFSPath path, + uint32_t uid, uint32_t gid) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "Chown", {path, (int64_t)uid, (int64_t)gid}); + } +} +bool TObjectVFS::Stat(Tesses::Framework::Filesystem::VFSPath path, + Tesses::Framework::Filesystem::StatData &data) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + auto res = dict->CallMethod(ls, "Stat", {path}); + int64_t _num; + TDictionary *_dict; + TObject _o; + if (GetObjectHeap(res, _dict)) { + this->ls->GetGC()->BarrierBegin(); + _o = _dict->GetValue("BlockSize"); + if (GetObject(_o, _num)) + data.BlockSize = (uint64_t)_num; + + _o = _dict->GetValue("BlockCount"); + if (GetObject(_o, _num)) + data.BlockCount = (uint64_t)_num; + + _o = _dict->GetValue("Device"); + if (GetObject(_o, _num)) + data.Device = (uint64_t)_num; + + _o = _dict->GetValue("DeviceId"); + if (GetObject(_o, _num)) + data.DeviceId = (uint64_t)_num; + + _o = _dict->GetValue("GroupId"); + if (GetObject(_o, _num)) + data.GroupId = (uint32_t)_num; + + _o = _dict->GetValue("HardLinks"); + if (GetObject(_o, _num)) + data.HardLinks = (uint64_t)_num; + std::shared_ptr dt; + _o = _dict->GetValue("LastAccess"); + if (GetObject(_o, dt)) + data.LastAccess = + dt ? *dt : Tesses::Framework::Date::DateTime(0); + + _o = _dict->GetValue("LastModified"); + if (GetObject(_o, dt)) + data.LastModified = + dt ? *dt : Tesses::Framework::Date::DateTime(0); + + _o = _dict->GetValue("LastStatus"); + if (GetObject(_o, dt)) + data.LastStatus = + dt ? *dt : Tesses::Framework::Date::DateTime(0); + + _o = _dict->GetValue("Mode"); + if (GetObject(_o, _num)) + data.Mode = (uint32_t)_num; + + _o = _dict->GetValue("Size"); + if (GetObject(_o, _num)) + data.Size = (uint64_t)_num; + + _o = _dict->GetValue("UserId"); + if (GetObject(_o, _num)) + data.UserId = (uint32_t)_num; + + this->ls->GetGC()->BarrierEnd(); + return true; } } - void TObjectVFS::Chown(Tesses::Framework::Filesystem::VFSPath path, uint32_t uid, uint32_t gid) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls, "Chown",{path,(int64_t)uid, (int64_t)gid}); - + + return false; +} +bool TObjectVFS::StatVFS(Tesses::Framework::Filesystem::VFSPath path, + Tesses::Framework::Filesystem::StatVFSData &data) { + TDictionary *dict; + + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + auto res = dict->CallMethod(ls, "StatVFS", {path}); + int64_t _num; + TDictionary *_dict; + TObject _o; + if (GetObjectHeap(res, _dict)) { + this->ls->GetGC()->BarrierBegin(); + _o = _dict->GetValue("BlockSize"); + if (GetObject(_o, _num)) + data.BlockSize = (uint64_t)_num; + + _o = _dict->GetValue("FragmentSize"); + if (GetObject(_o, _num)) + data.FragmentSize = (uint64_t)_num; + _o = _dict->GetValue("Blocks"); + if (GetObject(_o, _num)) + data.Blocks = (uint64_t)_num; + _o = _dict->GetValue("BlocksFree"); + if (GetObject(_o, _num)) + data.BlocksFree = (uint64_t)_num; + _o = _dict->GetValue("BlocksAvailable"); + if (GetObject(_o, _num)) + data.BlocksAvailable = (uint64_t)_num; + _o = _dict->GetValue("TotalInodes"); + if (GetObject(_o, _num)) + data.TotalInodes = (uint64_t)_num; + _o = _dict->GetValue("FreeInodes"); + if (GetObject(_o, _num)) + data.FreeInodes = (uint64_t)_num; + _o = _dict->GetValue("AvailableInodes"); + if (GetObject(_o, _num)) + data.AvailableInodes = (uint64_t)_num; + _o = _dict->GetValue("Id"); + if (GetObject(_o, _num)) + data.Id = (uint64_t)_num; + _o = _dict->GetValue("Flags"); + if (GetObject(_o, _num)) + data.Flags = (uint64_t)_num; + _o = _dict->GetValue("MaxNameLength"); + if (GetObject(_o, _num)) + data.MaxNameLength = (uint64_t)_num; + + this->ls->GetGC()->BarrierEnd(); + return true; } } - bool TObjectVFS::Stat(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Filesystem::StatData& data) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - auto res = dict->CallMethod(ls, "Stat",{path}); - int64_t _num; - TDictionary* _dict; - TObject _o; - if(GetObjectHeap(res,_dict)) - { - this->ls->GetGC()->BarrierBegin(); - _o = _dict->GetValue("BlockSize"); - if(GetObject(_o,_num)) data.BlockSize = (uint64_t)_num; - _o = _dict->GetValue("BlockCount"); - if(GetObject(_o,_num)) data.BlockCount = (uint64_t)_num; - - _o = _dict->GetValue("Device"); - if(GetObject(_o,_num)) data.Device = (uint64_t)_num; - - _o = _dict->GetValue("DeviceId"); - if(GetObject(_o,_num)) data.DeviceId = (uint64_t)_num; - - _o = _dict->GetValue("GroupId"); - if(GetObject(_o,_num)) data.GroupId = (uint32_t)_num; - - _o = _dict->GetValue("HardLinks"); - if(GetObject(_o,_num)) data.HardLinks = (uint64_t)_num; - std::shared_ptr dt; - _o = _dict->GetValue("LastAccess"); - if(GetObject(_o,dt)) data.LastAccess = dt ? *dt : Tesses::Framework::Date::DateTime(0); - - - _o = _dict->GetValue("LastModified"); - if(GetObject(_o,dt)) data.LastModified = dt ? *dt : Tesses::Framework::Date::DateTime(0); - - - - _o = _dict->GetValue("LastStatus"); - if(GetObject(_o,dt)) data.LastStatus = dt ? *dt : Tesses::Framework::Date::DateTime(0); - - - - _o = _dict->GetValue("Mode"); - if(GetObject(_o,_num)) data.Mode = (uint32_t)_num; - - _o = _dict->GetValue("Size"); - if(GetObject(_o,_num)) data.Size = (uint64_t)_num; - - _o = _dict->GetValue("UserId"); - if(GetObject(_o,_num)) data.UserId = (uint32_t)_num; - - - this->ls->GetGC()->BarrierEnd(); - return true; - } - } - - return false; + return false; +} +void TObjectVFS::Close() { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "Dispose", {}); } - bool TObjectVFS::StatVFS(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Filesystem::StatVFSData& data) - { - TDictionary* dict; - - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - auto res = dict->CallMethod(ls, "StatVFS",{path}); - int64_t _num; - TDictionary* _dict; - TObject _o; - if(GetObjectHeap(res,_dict)) - { - this->ls->GetGC()->BarrierBegin(); - _o = _dict->GetValue("BlockSize"); - if(GetObject(_o,_num)) data.BlockSize = (uint64_t)_num; - - _o = _dict->GetValue("FragmentSize"); - if(GetObject(_o,_num)) data.FragmentSize = (uint64_t)_num; - _o = _dict->GetValue("Blocks"); - if(GetObject(_o,_num)) data.Blocks = (uint64_t)_num; - _o = _dict->GetValue("BlocksFree"); - if(GetObject(_o,_num)) data.BlocksFree = (uint64_t)_num; - _o = _dict->GetValue("BlocksAvailable"); - if(GetObject(_o,_num)) data.BlocksAvailable = (uint64_t)_num; - _o = _dict->GetValue("TotalInodes"); - if(GetObject(_o,_num)) data.TotalInodes = (uint64_t)_num; - _o = _dict->GetValue("FreeInodes"); - if(GetObject(_o,_num)) data.FreeInodes = (uint64_t)_num; - _o = _dict->GetValue("AvailableInodes"); - if(GetObject(_o,_num)) data.AvailableInodes = (uint64_t)_num; - _o = _dict->GetValue("Id"); - if(GetObject(_o,_num)) data.Id = (uint64_t)_num; - _o = _dict->GetValue("Flags"); - if(GetObject(_o,_num)) data.Flags = (uint64_t)_num; - _o = _dict->GetValue("MaxNameLength"); - if(GetObject(_o,_num)) data.MaxNameLength = (uint64_t)_num; - - - - - - - this->ls->GetGC()->BarrierEnd(); - return true; - } - } - - return false; +} +TObjectVFS::~TObjectVFS() { + TDictionary *dict; + if (GetObjectHeap(this->obj, dict)) { + GCList ls(this->ls->GetGC()); + dict->CallMethod(ls, "Dispose", {}); } - void TObjectVFS::Close() - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls,"Dispose",{}); - } - } - TObjectVFS::~TObjectVFS() - { - TDictionary* dict; - if(GetObjectHeap(this->obj, dict)) - { - GCList ls(this->ls->GetGC()); - dict->CallMethod(ls,"Dispose",{}); - } - delete this->ls; - } - -} \ No newline at end of file + delete this->ls; +} + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/add.cpp b/src/vm/bc/add.cpp index 275539c..c7c4c49 100644 --- a/src/vm/bc/add.cpp +++ b/src/vm/bc/add.cpp @@ -2,163 +2,164 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - bool InterperterThread::Add(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); +bool InterperterThread::Add(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, std::get(left) + + std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + (char)(std::get(left) + std::get(right))); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, (char)(std::get(left) + std::get(right))); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, (char)(std::get(left) + std::get(right))); + } else if (std::holds_alternative( + left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, std::get(left) + + std::get(right)); - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,(char)(std::get(left) + std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (char)(std::get(left) + std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (char)(std::get(left) + std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - - } + } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - - } + else if (std::holds_alternative( + left) && + std::holds_alternative( + right)) { + cse.back()->Push( + gc, std::get(left) + + std::get(right)); - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) + (*r))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) + (*r))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) + (*r))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - std::string str={}; - str.append(std::get(left)); - str.append(std::get(right)); - cse.back()->Push(gc,str); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - std::string str={}; - str.push_back(std::get(left)); - str.append(std::get(right)); - cse.back()->Push(gc,str); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - std::string str={}; - str.append(std::get(left)); - str.push_back(std::get(right)); - cse.back()->Push(gc,str); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator+"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator+",{right})); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) + std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) + std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) + std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) + std::get(right)); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push( + gc, + std::make_shared((*l) + (*r))); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push( + gc, + std::make_shared((*l) + (*r))); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push( + gc, + std::make_shared((*l) + (*r))); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + std::string str = {}; + str.append(std::get(left)); + str.append(std::get(right)); + cse.back()->Push(gc, str); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + std::string str = {}; + str.push_back(std::get(left)); + str.append(std::get(right)); + cse.back()->Push(gc, str); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + std::string str = {}; + str.append(std::get(left)); + str.push_back(std::get(right)); + cse.back()->Push(gc, str); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator+"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); return false; } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator+"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator+",{right})); - return false; - } - else - { - cse.back()->Push(gc, Undefined()); - } - - } - else - { + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator+", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator+"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator+", {right})); + return false; + } else { cse.back()->Push(gc, Undefined()); } - return false; + + } else { + cse.back()->Push(gc, Undefined()); } -} \ No newline at end of file + return false; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/equals.cpp b/src/vm/bc/equals.cpp index aa54692..92de359 100644 --- a/src/vm/bc/equals.cpp +++ b/src/vm/bc/equals.cpp @@ -2,235 +2,199 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include - namespace Tesses::CrossLang { - bool Equals(std::shared_ptr gc, TObject left, TObject right) - { - GCList ls(gc); - if(std::holds_alternative(left) && std::holds_alternative(right)) - { +bool Equals(std::shared_ptr gc, TObject left, TObject right) { + GCList ls(gc); + if (std::holds_alternative(left) && + std::holds_alternative(right)) { - return true; - } + return true; + } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return true; - } + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return true; + } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - return std::get>(left)->ToEpoch() == std::get>(right)->ToEpoch(); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - return std::get>(left)->TotalSeconds() == std::get>(right)->TotalSeconds(); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto lver= std::get(left); - auto rver = std::get(right); - auto r = lver.CompareTo(rver); - return r == 0; - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto l= std::get(left); - auto r = std::get(right); - - return l == r; - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + return std::get(left) == std::get(right); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + return std::get>( + left) + ->ToEpoch() == + std::get>( + right) + ->ToEpoch(); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + return std::get>( + left) + ->TotalSeconds() == + std::get>( + right) + ->TotalSeconds(); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto lver = std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + return r == 0; + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto l = std::get(left); + auto r = std::get(right); - auto dynDict = dynamic_cast(obj); - auto native = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue("","operator=="); - gc->BarrierEnd(); - TCallable* callable; - - if(GetObjectHeap(obj,callable)) - { - return ToBool(callable->Call(ls,{right})); - - } - else if(std::holds_alternative(right)) { - return false; - } - else if(std::holds_alternative(right)) - { - return false; - } - else if(std::holds_alternative(right)) - { - return cls == std::get(right).obj; - } + return l == r; + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto native = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = cls->GetValue("", "operator=="); + gc->BarrierEnd(); + TCallable *callable; + + if (GetObjectHeap(obj, callable)) { + return ToBool(callable->Call(ls, {right})); + + } else if (std::holds_alternative(right)) { + return false; + } else if (std::holds_alternative(right)) { + return false; + } else if (std::holds_alternative(right)) { + return cls == std::get(right).obj; } - else - if(natObj != nullptr) - { - return natObj->Equals(gc, right); - } - if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator=="); - gc->BarrierEnd(); - if(!std::holds_alternative(fn)) - { - if(std::holds_alternative(fn)) - { + } else if (natObj != nullptr) { + return natObj->Equals(gc, right); + } + if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator=="); + gc->BarrierEnd(); + if (!std::holds_alternative(fn)) { + if (std::holds_alternative(fn)) { - auto obj = dynamic_cast(std::get(fn).obj); - if(obj != nullptr) - { - auto closure = dynamic_cast(obj); - if(closure != nullptr) - { - - if(!closure->closure->args.empty() && closure->closure->args[0] == "this") - { - return ToBool(obj->Call(ls,{left,right})); - } - else - { - return ToBool(obj->Call(ls,{right})); - } + auto obj = dynamic_cast( + std::get(fn).obj); + if (obj != nullptr) { + auto closure = dynamic_cast(obj); + if (closure != nullptr) { + if (!closure->closure->args.empty() && + closure->closure->args[0] == "this") { + return ToBool(obj->Call(ls, {left, right})); + } else { + return ToBool(obj->Call(ls, {right})); } - else - { - return ToBool(obj->Call(ls,{right})); - } + } else { + return ToBool(obj->Call(ls, {right})); } - else { - - - return dict == std::get(right).obj; - } - } else { - return dict == std::get(right).obj; - } + return dict == std::get(right).obj; + } - } - else { + } else { return dict == std::get(right).obj; } - return false; + } else { + + return dict == std::get(right).obj; } - - else if(dynDict != nullptr) - { - auto res = dynDict->CallMethod(ls,"operator==",{right}); - if(!std::holds_alternative(res) && std::holds_alternative(res)) - { - return ToBool(res); - } - } - else if(native != nullptr && std::holds_alternative(right)) - { - return native->GetDestroyed(); - - } - - if(std::holds_alternative(right)) - { - return obj == std::get(right).obj; - - } - - else if(std::holds_alternative(right)) - { - return false; - } - else if(std::holds_alternative(right)) - { - - return false; - } - else - { - return false; - } - - } - - else if(std::holds_alternative(right)) - { - return false; - } - else if(std::holds_alternative(right)) - { - return false; - } - else - { return false; } - return false; + else if (dynDict != nullptr) { + auto res = dynDict->CallMethod(ls, "operator==", {right}); + if (!std::holds_alternative(res) && + std::holds_alternative(res)) { + return ToBool(res); + } + } else if (native != nullptr && + std::holds_alternative(right)) { + return native->GetDestroyed(); + } + + if (std::holds_alternative(right)) { + return obj == std::get(right).obj; + + } + + else if (std::holds_alternative(right)) { + return false; + } else if (std::holds_alternative(right)) { + + return false; + } else { + return false; + } } -} \ No newline at end of file + + else if (std::holds_alternative(right)) { + return false; + } else if (std::holds_alternative(right)) { + return false; + } else { + return false; + } + + return false; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/executemethod2.cpp b/src/vm/bc/executemethod2.cpp index c433467..983a27c 100644 --- a/src/vm/bc/executemethod2.cpp +++ b/src/vm/bc/executemethod2.cpp @@ -3,3986 +3,3692 @@ #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Streams/ByteWriter.hpp" #include "TessesFramework/Uuid.hpp" +#include #include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - extern bool IHttpServer_Handle(std::shared_ptr svr,std::vector& args); - - bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, std::string key, std::vector args) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - GCList ls(gc); - std::regex regex; - TVMVersion version; - if(std::holds_alternative(instance)) - { - if(key == "ToString") - { - cse.back()->Push(gc,"null"); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - }else if(std::holds_alternative(instance)) - { - if(key == "ToString") - { - cse.back()->Push(gc,"undefined"); - return false; - } - cse.back()->Push(gc,Undefined()); +extern bool +IHttpServer_Handle(std::shared_ptr svr, + std::vector &args); + +bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, + std::string key, + std::vector args) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + GCList ls(gc); + std::regex regex; + TVMVersion version; + if (std::holds_alternative(instance)) { + if (key == "ToString") { + cse.back()->Push(gc, "null"); return false; } - else - if(GetObject(instance, version)) - { - if(key == "ToString") - { - cse.back()->Push(gc, version.ToString()); - return false; - } - if(key == "ToByteArray") - { - TByteArray* ba = TByteArray::Create(ls); - ba->data.resize(5); - version.ToArray(ba->data.data()); - cse.back()->Push(gc,ba); - return false; - } - cse.back()->Push(gc, Undefined()); + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative(instance)) { + if (key == "ToString") { + cse.back()->Push(gc, "undefined"); return false; } - else if(GetObject(instance,regex)) - { - if(key == "Search") - { - std::string str; - if(GetArgument(args,0,str)) - { - std::smatch m; - if(std::regex_search(str,m,regex)) - { - auto myLs = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : m) - { - auto itm = TDictionary::Create(ls); - itm->SetValue("Offset", (int64_t)(item.first-str.begin())); - itm->SetValue("Length",(int64_t)item.length()); - itm->SetValue("Matched",item.matched); - itm->SetValue("Text",item.str()); - myLs->Add(itm); - } - - - cse.back()->Push(gc, myLs); - gc->BarrierEnd(); - return false; + cse.back()->Push(gc, Undefined()); + return false; + } else if (GetObject(instance, version)) { + if (key == "ToString") { + cse.back()->Push(gc, version.ToString()); + return false; + } + if (key == "ToByteArray") { + TByteArray *ba = TByteArray::Create(ls); + ba->data.resize(5); + version.ToArray(ba->data.data()); + cse.back()->Push(gc, ba); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (GetObject(instance, regex)) { + if (key == "Search") { + std::string str; + if (GetArgument(args, 0, str)) { + std::smatch m; + if (std::regex_search(str, m, regex)) { + auto myLs = TList::Create(ls); + gc->BarrierBegin(); + for (auto item : m) { + auto itm = TDictionary::Create(ls); + itm->SetValue("Offset", + (int64_t)(item.first - str.begin())); + itm->SetValue("Length", (int64_t)item.length()); + itm->SetValue("Matched", item.matched); + itm->SetValue("Text", item.str()); + myLs->Add(itm); } - + + cse.back()->Push(gc, myLs); + gc->BarrierEnd(); + return false; } } + } - cse.back()->Push(gc, nullptr); + cse.back()->Push(gc, nullptr); + return false; + } else if (std::holds_alternative(instance)) { + bool flag = std::get(instance); + if (key == "ToString") { + cse.back()->Push(gc, flag ? "true" : "false"); + return false; + } else if (key == "ToLong") { + cse.back()->Push(gc, flag ? (int64_t)1 : (int64_t)0); return false; } - else if(std::holds_alternative(instance)) - { - bool flag = std::get(instance); - if(key == "ToString") - { - cse.back()->Push(gc, flag ? "true" : "false"); - return false; - } - else if(key == "ToLong") - { - cse.back()->Push(gc, flag ? (int64_t)1 : (int64_t)0); - return false; - } - cse.back()->Push(gc, Undefined()); + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative(instance)) { + char c = std::get(instance); + if (key == "ToString") { + cse.back()->Push(gc, std::string{c}); + return false; + } else if (key == "ToLong") { + uint8_t uc = (uint8_t)c; + cse.back()->Push(gc, (int64_t)uc); + return false; + } else if (key == "IsAscii") { + bool isAscii = c >= 0; + cse.back()->Push(gc, isAscii); return false; } - else if(std::holds_alternative(instance)) - { - char c = std::get(instance); - if(key == "ToString") - { - cse.back()->Push(gc, std::string{c}); - return false; - } - else if(key == "ToLong") - { - uint8_t uc = (uint8_t)c; - cse.back()->Push(gc, (int64_t)uc); - return false; - } - else if(key == "IsAscii") - { - bool isAscii = c >= 0; - cse.back()->Push(gc, isAscii); - return false; - } - if(key == "IsLetter") - { - bool isLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); - cse.back()->Push(gc, isLetter); - return false; - } - if(key == "IsDigit") - { - bool isDigit = (c >= '0' && c <= '9'); - cse.back()->Push(gc, isDigit); - return false; - } - if(key == "IsLetterOrDigit") - { - bool isDigit = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); - cse.back()->Push(gc, isDigit); - return false; - } - if(key == "ToLower") - { - if(c >= 'A' && c <= 'Z') - cse.back()->Push(gc, (char)tolower(c)); - else - cse.back()->Push(gc, c); + if (key == "IsLetter") { + bool isLetter = + (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); + cse.back()->Push(gc, isLetter); + return false; + } + if (key == "IsDigit") { + bool isDigit = (c >= '0' && c <= '9'); + cse.back()->Push(gc, isDigit); + return false; + } + if (key == "IsLetterOrDigit") { + bool isDigit = (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); + cse.back()->Push(gc, isDigit); + return false; + } + if (key == "ToLower") { + if (c >= 'A' && c <= 'Z') + cse.back()->Push(gc, (char)tolower(c)); + else + cse.back()->Push(gc, c); - return false; - } - if(key == "ToUpper") - { - if(c >= 'a' && c <= 'z') - cse.back()->Push(gc, (char)toupper(c)); - else - cse.back()->Push(gc, c); - - return false; - } - cse.back()->Push(gc, Undefined()); return false; } - else if(std::holds_alternative(instance)) - { - double number = std::get(instance); - if(key == "ToString") - { - cse.back()->Push(gc, std::to_string(number)); - return false; - } - if(key == "ToLong") - { - cse.back()->Push(gc, (int64_t)number); - return false; - } - if(key == "ToLongBits") - { - cse.back()->Push(gc, *(int64_t*)&number); - return false; - } - if(key == "Floor") - { - cse.back()->Push(gc,floor(number)); - return false; - } - if(key == "Ceiling") - { - cse.back()->Push(gc,ceil(number)); - return false; - } - if(key == "Abs") - { - cse.back()->Push(gc,fabs(number)); - return false; - } - if(key == "Pow") - { - if(args.size() != 1) - { - throw VMException("Double.Pow must only accept one argument"); - } - if(!std::holds_alternative(args[0])) - { - throw VMException("Double.Pow must only accept a double"); - } - cse.back()->Push(gc,pow(number, std::get(args[0]))); - return false; - } - if(key == "Atan2") - { - if(args.size() != 1) - { - throw VMException("Double.Atan2 must only accept one argument"); - } - if(!std::holds_alternative(args[0])) - { - throw VMException("Double.Atan2 must only accept a double"); - } - cse.back()->Push(gc,atan2(number, std::get(args[0]))); - return false; - } - if(key == "Atan") - { - cse.back()->Push(gc,tan(number)); - return false; - } - if(key == "Tan") - { - cse.back()->Push(gc,tan(number)); - return false; - } - if(key == "Tanh") - { - cse.back()->Push(gc,tanh(number)); - return false; - } - if(key == "Asin") - { - cse.back()->Push(gc,asin(number)); - return false; - } - if(key == "Sin") - { - cse.back()->Push(gc,sin(number)); - return false; - } - if(key == "Sinh") - { - cse.back()->Push(gc,sinh(number)); - return false; - } - if(key == "Acos") - { - cse.back()->Push(gc,acos(number)); - return false; - } - if(key == "Cos") - { - cse.back()->Push(gc,cos(number)); - return false; - } - if(key == "Cosh") - { - cse.back()->Push(gc,cosh(number)); - return false; - } - if(key == "Log") - { - cse.back()->Push(gc,log(number)); - return false; - } - if(key == "Log10") - { - cse.back()->Push(gc,log10(number)); - return false; - } - if(key == "Sqrt") - { - cse.back()->Push(gc,sqrt(number)); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative(instance)) - { - int64_t number = std::get(instance); - if(key == "ToHexString") - { - int64_t width = 1; + if (key == "ToUpper") { + if (c >= 'a' && c <= 'z') + cse.back()->Push(gc, (char)toupper(c)); + else + cse.back()->Push(gc, c); - if(!GetArgument(args,0,width)) width=1; - size_t _width = (size_t)width; - - std::stringstream strm; - if(_width > 1) - strm << std::setfill('0') << std::setw((int)_width) << std::hex << number; - else + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative(instance)) { + double number = std::get(instance); + if (key == "ToString") { + cse.back()->Push(gc, std::to_string(number)); + return false; + } + if (key == "ToLong") { + cse.back()->Push(gc, (int64_t)number); + return false; + } + if (key == "ToLongBits") { + cse.back()->Push(gc, *(int64_t *)&number); + return false; + } + if (key == "Floor") { + cse.back()->Push(gc, floor(number)); + return false; + } + if (key == "Ceiling") { + cse.back()->Push(gc, ceil(number)); + return false; + } + if (key == "Abs") { + cse.back()->Push(gc, fabs(number)); + return false; + } + if (key == "Pow") { + if (args.size() != 1) { + throw VMException( + "Double.Pow must only accept one argument"); + } + if (!std::holds_alternative(args[0])) { + throw VMException("Double.Pow must only accept a double"); + } + cse.back()->Push(gc, pow(number, std::get(args[0]))); + return false; + } + if (key == "Atan2") { + if (args.size() != 1) { + throw VMException( + "Double.Atan2 must only accept one argument"); + } + if (!std::holds_alternative(args[0])) { + throw VMException("Double.Atan2 must only accept a double"); + } + cse.back()->Push(gc, atan2(number, std::get(args[0]))); + return false; + } + if (key == "Atan") { + cse.back()->Push(gc, tan(number)); + return false; + } + if (key == "Tan") { + cse.back()->Push(gc, tan(number)); + return false; + } + if (key == "Tanh") { + cse.back()->Push(gc, tanh(number)); + return false; + } + if (key == "Asin") { + cse.back()->Push(gc, asin(number)); + return false; + } + if (key == "Sin") { + cse.back()->Push(gc, sin(number)); + return false; + } + if (key == "Sinh") { + cse.back()->Push(gc, sinh(number)); + return false; + } + if (key == "Acos") { + cse.back()->Push(gc, acos(number)); + return false; + } + if (key == "Cos") { + cse.back()->Push(gc, cos(number)); + return false; + } + if (key == "Cosh") { + cse.back()->Push(gc, cosh(number)); + return false; + } + if (key == "Log") { + cse.back()->Push(gc, log(number)); + return false; + } + if (key == "Log10") { + cse.back()->Push(gc, log10(number)); + return false; + } + if (key == "Sqrt") { + cse.back()->Push(gc, sqrt(number)); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative(instance)) { + int64_t number = std::get(instance); + if (key == "ToHexString") { + int64_t width = 1; + + if (!GetArgument(args, 0, width)) + width = 1; + size_t _width = (size_t)width; + + std::stringstream strm; + if (_width > 1) + strm << std::setfill('0') << std::setw((int)_width) + << std::hex << number; + else strm << std::hex << number; - cse.back()->Push(gc,strm.str()); - return false; - } - if(key == "ToString") - { - cse.back()->Push(gc, std::to_string(number)); - return false; - } - if(key == "ToChar") - { - uint8_t c = (uint8_t)number; - cse.back()->Push(gc, (char)c); - return false; - } - if(key == "Abs") - { - if(number < 0) - cse.back()->Push(gc, -number); - else - cse.back()->Push(gc, number); - return false; - } - if(key == "ToDouble") - { - cse.back()->Push(gc,(double)number); - return false; - } - if(key == "ToDoubleBits") - { - cse.back()->Push(gc,*(double*)&number); - return false; - } - - cse.back()->Push(gc, Undefined()); + cse.back()->Push(gc, strm.str()); return false; - } - else if(std::holds_alternative(instance)) - { - auto path = std::get(instance); - if(key == "GetEnumerator") - { + } + if (key == "ToString") { + cse.back()->Push(gc, std::to_string(number)); + return false; + } + if (key == "ToChar") { + uint8_t c = (uint8_t)number; + cse.back()->Push(gc, (char)c); + return false; + } + if (key == "Abs") { + if (number < 0) + cse.back()->Push(gc, -number); + else + cse.back()->Push(gc, number); + return false; + } + if (key == "ToDouble") { + cse.back()->Push(gc, (double)number); + return false; + } + if (key == "ToDoubleBits") { + cse.back()->Push(gc, *(double *)&number); + return false; + } - TList* _ls = TList::Create(ls); - for(auto item : path.path) - { - _ls->Add(item); - } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative< + Tesses::Framework::Filesystem::VFSPath>(instance)) { + auto path = + std::get(instance); + if (key == "GetEnumerator") { - cse.back()->Push(gc, TListEnumerator::Create(ls,_ls)); - return false; + TList *_ls = TList::Create(ls); + for (auto item : path.path) { + _ls->Add(item); } - if(key == "ToString") - { - cse.back()->Push(gc, path.ToString()); - return false; - } - if(key == "GetAt") - { - int64_t index; - if(GetArgument(args,0,index)) - { - size_t idx = (size_t)idx; - if(idx < path.path.size()) - cse.back()->Push(gc, path.path[idx]); - else - cse.back()->Push(gc, nullptr); - return false; - } - } - if(key == "Count" || key == "Length") - { - cse.back()->Push(gc, (int64_t)path.path.size()); - return false; - } - if(key == "GetParent") - { - cse.back()->Push(gc, path.GetParent()); - return false; - } - if(key == "GetFileName") - { - cse.back()->Push(gc, path.GetFileName()); - return false; - } - if(key == "GetExtension") - { - cse.back()->Push(gc, path.GetExtension()); - return false; - } - if(cse.back()->env->GetRootEnvironment()->permissions.localfs && key == "MakeAbsolute") - { - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgumentAsPath(args,0,p)) - { - cse.back()->Push(gc,path.MakeAbsolute(p)); - return false; - } + + cse.back()->Push(gc, TListEnumerator::Create(ls, _ls)); + return false; + } + if (key == "ToString") { + cse.back()->Push(gc, path.ToString()); + return false; + } + if (key == "GetAt") { + int64_t index; + if (GetArgument(args, 0, index)) { + size_t idx = (size_t)idx; + if (idx < path.path.size()) + cse.back()->Push(gc, path.path[idx]); else - { - cse.back()->Push(gc,path.MakeAbsolute(cse.back()->env->GetRootEnvironment()->permissions.localfs->GetWorking())); - return false; - } - } - if(cse.back()->env->GetRootEnvironment()->permissions.localfs && key == "MakeRelative") - { - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgumentAsPath(args,0,p)) - { - cse.back()->Push(gc,path.MakeRelative(p)); - return false; - } - else - { - cse.back()->Push(gc,path.MakeRelative(cse.back()->env->GetRootEnvironment()->permissions.localfs->GetWorking())); - return false; - } - } - if(key == "ChangeExtension") - { - Tesses::Framework::Filesystem::VFSPath newPath = path; - std::string ext; - if(GetArgument(args,0, ext)) - { - newPath.ChangeExtension(ext); - } - else - { - newPath.RemoveExtension(); - } - cse.back()->Push(gc, newPath); + cse.back()->Push(gc, nullptr); return false; } - if(key == "CollapseRelativeParents") - { - cse.back()->Push(gc, path.CollapseRelativeParents()); - return false; - } - if(key == "IsRelative") - { - cse.back()->Push(gc, path.relative); - return false; - //Path.FromString(); - } } - else if(std::holds_alternative(instance)) - { - std::string str = std::get(instance); - if(key == "ToLower") - { - for(size_t i = 0; i < str.size(); i++) - { - if(str[i] >= 'A' && str[i] <= 'Z') - { - str[i] = 'a' + (str[i] - 'A'); - } - } - cse.back()->Push(gc, str); + if (key == "Count" || key == "Length") { + cse.back()->Push(gc, (int64_t)path.path.size()); + return false; + } + if (key == "GetParent") { + cse.back()->Push(gc, path.GetParent()); + return false; + } + if (key == "GetFileName") { + cse.back()->Push(gc, path.GetFileName()); + return false; + } + if (key == "GetExtension") { + cse.back()->Push(gc, path.GetExtension()); + return false; + } + if (cse.back()->env->GetRootEnvironment()->permissions.localfs && + key == "MakeAbsolute") { + Tesses::Framework::Filesystem::VFSPath p; + if (GetArgumentAsPath(args, 0, p)) { + cse.back()->Push(gc, path.MakeAbsolute(p)); + return false; + } else { + cse.back()->Push( + gc, path.MakeAbsolute( + cse.back() + ->env->GetRootEnvironment() + ->permissions.localfs->GetWorking())); return false; } - if(key == "ToUpper") - { - - for(size_t i = 0; i < str.size(); i++) - { - if(str[i] >= 'a' && str[i] <= 'z') - { - str[i] = 'A' + (str[i] - 'a'); - } - } - cse.back()->Push(gc, str); + } + if (cse.back()->env->GetRootEnvironment()->permissions.localfs && + key == "MakeRelative") { + Tesses::Framework::Filesystem::VFSPath p; + if (GetArgumentAsPath(args, 0, p)) { + cse.back()->Push(gc, path.MakeRelative(p)); + return false; + } else { + cse.back()->Push( + gc, path.MakeRelative( + cse.back() + ->env->GetRootEnvironment() + ->permissions.localfs->GetWorking())); return false; } - if(key == "PadLeft") - { - int64_t pad; - char padChar=' '; - - if(args.size() == 0 || args.size() > 2) - { - throw VMException("String.PadLeft must only accept 1 or 2 arguments"); - + } + if (key == "ChangeExtension") { + Tesses::Framework::Filesystem::VFSPath newPath = path; + std::string ext; + if (GetArgument(args, 0, ext)) { + newPath.ChangeExtension(ext); + } else { + newPath.RemoveExtension(); + } + cse.back()->Push(gc, newPath); + return false; + } + if (key == "CollapseRelativeParents") { + cse.back()->Push(gc, path.CollapseRelativeParents()); + return false; + } + if (key == "IsRelative") { + cse.back()->Push(gc, path.relative); + return false; + // Path.FromString(); + } + } else if (std::holds_alternative(instance)) { + std::string str = std::get(instance); + if (key == "ToLower") { + for (size_t i = 0; i < str.size(); i++) { + if (str[i] >= 'A' && str[i] <= 'Z') { + str[i] = 'a' + (str[i] - 'A'); } + } + cse.back()->Push(gc, str); + return false; + } + if (key == "ToUpper") { - if(GetArgument(args,0, pad)) - { - if((size_t)pad < str.size()) { - cse.back()->Push(gc, str); - return false; - } - GetArgument(args,1, padChar); - size_t diff = (size_t)pad - str.size(); - str.insert(str.begin(),diff, padChar); + for (size_t i = 0; i < str.size(); i++) { + if (str[i] >= 'a' && str[i] <= 'z') { + str[i] = 'A' + (str[i] - 'a'); + } + } + cse.back()->Push(gc, str); + return false; + } + if (key == "PadLeft") { + int64_t pad; + char padChar = ' '; + + if (args.size() == 0 || args.size() > 2) { + throw VMException( + "String.PadLeft must only accept 1 or 2 arguments"); + } + + if (GetArgument(args, 0, pad)) { + if ((size_t)pad < str.size()) { cse.back()->Push(gc, str); return false; } - else throw VMException("String.PadLeft must have a long for width"); + GetArgument(args, 1, padChar); + size_t diff = (size_t)pad - str.size(); + str.insert(str.begin(), diff, padChar); + cse.back()->Push(gc, str); + return false; + } else + throw VMException( + "String.PadLeft must have a long for width"); + } + if (key == "PadRight") { + int64_t pad; + char padChar = ' '; + + if (args.size() == 0 || args.size() > 2) { + throw VMException( + "String.PadRight must only accept 1 or 2 arguments"); } - if(key == "PadRight") - { - int64_t pad; - char padChar=' '; - if(args.size() == 0 || args.size() > 2) - { - throw VMException("String.PadRight must only accept 1 or 2 arguments"); - - } - - if(GetArgument(args,0, pad)) - { - if((size_t)pad < str.size()) { - cse.back()->Push(gc, str); - return false; - } - GetArgument(args,1, padChar); - size_t diff = (size_t)pad - str.size(); - str.insert(str.end(),diff, padChar); + if (GetArgument(args, 0, pad)) { + if ((size_t)pad < str.size()) { cse.back()->Push(gc, str); return false; } - else throw VMException("String.PadRight must have a long for width"); - } - if(key == "Contains") - { - std::string str2; - char c; - if(GetArgument(args,0,str2)) - { - - int64_t index = 0; - GetArgument(args,1,index); - - auto res = str.find(str2,(std::size_t)index); - - cse.back()->Push(gc, res != std::string::npos); - return false; - } - - else if(GetArgument(args,0,c)) - { - int64_t index = 0; - GetArgument(args,1,index); - - auto res = str.find_first_of(c,(std::size_t)index); - - cse.back()->Push(gc, res != std::string::npos); - return false; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "IndexOf") - { - std::string str2; - char c; - if(GetArgument(args,0,str2)) - { - - int64_t index = 0; - GetArgument(args,1,index); - - auto res = str.find(str2,(std::size_t)index); - if(res == std::string::npos) - cse.back()->Push(gc, (int64_t)-1); - else - cse.back()->Push(gc, (int64_t)res); - return false; - } - - else if(GetArgument(args,0,c)) - { - int64_t index = 0; - GetArgument(args,1,index); - - auto res = str.find_first_of(c,(std::size_t)index); - if(res == std::string::npos) - cse.back()->Push(gc, (int64_t)-1); - else - cse.back()->Push(gc, (int64_t)res); - return false; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "LastIndexOf") - { - std::string str2; - char c; - if(GetArgument(args,0,str2)) - { - - int64_t index = str.size(); - GetArgument(args,1,index); - - auto res = str.rfind(str2,(std::size_t)index); - if(res == std::string::npos) - cse.back()->Push(gc, (int64_t)-1); - else - cse.back()->Push(gc, (int64_t)res); - return false; - } - else if(GetArgument(args,0,c)) - { - int64_t index = str.size(); - GetArgument(args,1,index); - - auto res = str.find_last_of(c,(std::size_t)index); - if(res == std::string::npos) - cse.back()->Push(gc, (int64_t)-1); - else - cse.back()->Push(gc, (int64_t)res); - return false; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "GetEnumerator") - { - cse.back()->Push(gc, TStringEnumerator::Create(ls,str)); - return false; - } - if(key == "Substring") - { - if(args.size() >=1 && std::holds_alternative(args[0])) - { - size_t offset = (size_t)std::get(args[0]); - size_t count = std::string::npos; - if(args.size() == 2 && std::holds_alternative(args[1])) - { - count = (size_t)std::get(args[1]); - } - cse.back()->Push(gc, str.substr(offset,count)); - return false; - } - - } - if(key == "Remove") - { - if(args.size() >=1 && std::holds_alternative(args[0])) - { - size_t offset = (size_t)std::get(args[0]); - size_t count = std::string::npos; - if(args.size() == 2 && std::holds_alternative(args[1])) - { - count = (size_t)std::get(args[1]); - } - cse.back()->Push(gc, str.erase(offset,count)); - return false; - } - - } - if(key == "TrimStart") - { - if(args.size() >= 0) - { - char c = (args.size() == 1 && std::holds_alternative(args[0])) ? std::get(args[0]) : ' '; - - size_t i = 0; - for(; i < str.size();i++) - { - if(str[i] != c) break; - } - - cse.back()->Push(gc,(!str.empty() && i < str.size()) ? str.substr(i) : ""); - return false; - } - } - if(key == "TrimEnd") - { - if(args.size() >= 0) - { - char c = (args.size() == 1 && std::holds_alternative(args[0])) ? std::get(args[0]) : ' '; - size_t i = str.size()-1; - for(; i >= 0;i--) - { - if(str[i] != c) break; - } - - cse.back()->Push(gc, (!str.empty() && i < str.size()) ? str.substr(0,i+1) : ""); - return false; - } - } - if(key == "EndsWith") - { - std::string v; - if(GetArgument(args,0,v)) - { - if(str.size() < v.size()) { - cse.back()->Push(gc,false); - return false; - } - - size_t _end = str.size()-v.size(); - for(size_t i = 0; i < v.size(); i++) - { - if(v[i] != str[i+_end]) - { - cse.back()->Push(gc,false); - return false; - } - } - cse.back()->Push(gc,true); - return false; - } - cse.back()->Push(gc,false); - return false; - } - if(key == "StartsWith") - { - std::string v; - if(GetArgument(args,0,v)) - { - if(str.size() < v.size()) { - cse.back()->Push(gc,false); - return false; - } - for(size_t i = 0; i < v.size(); i++) - { - if(v[i] != str[i]) - { - cse.back()->Push(gc,false); - return false; - } - } - cse.back()->Push(gc,true); - return false; - } - cse.back()->Push(gc,false); - return false; - } - if(key == "Escape") - { - bool quote; - if(!GetArgument(args,0,quote)) quote=false; - cse.back()->Push(gc, EscapeString(str, quote)); - return false; - } - if(key == "Replace") - { - std::string oldStr; - std::string newStr; - - std::string _str={}; - if(GetArgument(args,0,oldStr) && GetArgument(args,1,newStr)) - { - _str = Tesses::Framework::Http::HttpUtils::Replace(str, oldStr,newStr); - - - } - cse.back()->Push(gc,_str); - - return false; - } - if(key == "Split") - { - std::string delimiter; - bool removeEmpty=false; - size_t count=std::string::npos; - - if(args.size() < 1 || args.size() > 3) throw VMException("String.Split must only accept 1-3 arguments"); - if(!std::holds_alternative(args[0])) throw VMException("String.Split first arg must be a string"); - else - delimiter = std::get(args[0]); - - if(args.size() > 1 && !std::holds_alternative(args[1])) throw VMException("String.Split second arg must be a bool"); - else if(args.size() > 1) - removeEmpty = std::get(args[1]); - if(args.size() > 2 && !std::holds_alternative(args[2])) throw VMException("String.Split third arg must be a int64_t"); - else if(args.size() > 2) - count = (size_t)std::get(args[2]); - - auto res = Tesses::Framework::Http::HttpUtils::SplitString(str, delimiter,count); - TList* mls = TList::Create(ls); - for(auto item : res) - { - if(!removeEmpty || !item.empty()) mls->Add(item); - } - cse.back()->Push(gc,mls); - return false; - // SplitString() - } - if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("String.GetAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("String.GetAt must only accept a long"); - } - - size_t index = (size_t)std::get(args[0]); - size_t sz = str.size(); - if(index >= 0 && index < sz) - { - cse.back()->Push(gc, str[index]); - return false; - } - - } - if(key == "Count" || key == "Length") - { - int64_t len = (int64_t)str.size(); - if(len < 0) len = 0; - - cse.back()->Push(gc, len); - return false; - } - if(key == "ToString") - { + GetArgument(args, 1, padChar); + size_t diff = (size_t)pad - str.size(); + str.insert(str.end(), diff, padChar); cse.back()->Push(gc, str); return false; - } - cse.back()->Push(gc, Undefined()); - return false; + } else + throw VMException( + "String.PadRight must have a long for width"); } - else if(std::holds_alternative>(instance)) - { - auto& time = std::get>(instance); - if(key == "ToString") - { - bool slim = false; - GetArgument(args,0,slim); - - cse.back()->Push(gc, time->ToString(slim)); + if (key == "Contains") { + std::string str2; + char c; + if (GetArgument(args, 0, str2)) { + int64_t index = 0; + GetArgument(args, 1, index); + + auto res = str.find(str2, (std::size_t)index); + + cse.back()->Push(gc, res != std::string::npos); return false; } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative>(instance)) - { - auto& date = std::get>(instance); - - - if(key == "ToString") - { - std::string fmt; - if(GetArgument(args,0,fmt)) - { - cse.back()->Push(gc, date->ToString(fmt)); - } - else - { - cse.back()->Push(gc, date->ToString()); - } - return false; - } - if(key == "ToHttpDate") - { - cse.back()->Push(gc, date->ToHttpDate()); - return false; - } - if(key == "ToEpoch") - { - cse.back()->Push(gc, date->ToEpoch()); - return false; - } - if(key == "ToLocal") - { - cse.back()->Push(gc, std::make_shared(date->ToLocal())); - return false; - } - if(key == "ToUTC") - { - cse.back()->Push(gc, std::make_shared(date->ToUTC())); + + else if (GetArgument(args, 0, c)) { + int64_t index = 0; + GetArgument(args, 1, index); + + auto res = str.find_first_of(c, (std::size_t)index); + + cse.back()->Push(gc, res != std::string::npos); return false; } cse.back()->Push(gc, nullptr); return false; - } - else if(std::holds_alternative>(instance)) - { - auto textReader = std::get>(instance); - if(key == "Rewind") - { - cse.back()->Push(gc,textReader->Rewind()); + if (key == "IndexOf") { + std::string str2; + char c; + if (GetArgument(args, 0, str2)) { + + int64_t index = 0; + GetArgument(args, 1, index); + + auto res = str.find(str2, (std::size_t)index); + if (res == std::string::npos) + cse.back()->Push(gc, (int64_t)-1); + else + cse.back()->Push(gc, (int64_t)res); return false; } - if(key == "ReadBlock") - { - int64_t sz; - if(GetArgument(args,0,sz)) - { - std::string block; - if(textReader->ReadBlock(block,(size_t)sz)) - { - cse.back()->Push(gc, block); + + else if (GetArgument(args, 0, c)) { + int64_t index = 0; + GetArgument(args, 1, index); + + auto res = str.find_first_of(c, (std::size_t)index); + if (res == std::string::npos) + cse.back()->Push(gc, (int64_t)-1); + else + cse.back()->Push(gc, (int64_t)res); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "LastIndexOf") { + std::string str2; + char c; + if (GetArgument(args, 0, str2)) { + + int64_t index = str.size(); + GetArgument(args, 1, index); + + auto res = str.rfind(str2, (std::size_t)index); + if (res == std::string::npos) + cse.back()->Push(gc, (int64_t)-1); + else + cse.back()->Push(gc, (int64_t)res); + return false; + } else if (GetArgument(args, 0, c)) { + int64_t index = str.size(); + GetArgument(args, 1, index); + + auto res = str.find_last_of(c, (std::size_t)index); + if (res == std::string::npos) + cse.back()->Push(gc, (int64_t)-1); + else + cse.back()->Push(gc, (int64_t)res); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "GetEnumerator") { + cse.back()->Push(gc, TStringEnumerator::Create(ls, str)); + return false; + } + if (key == "Substring") { + if (args.size() >= 1 && + std::holds_alternative(args[0])) { + size_t offset = (size_t)std::get(args[0]); + size_t count = std::string::npos; + if (args.size() == 2 && + std::holds_alternative(args[1])) { + count = (size_t)std::get(args[1]); + } + cse.back()->Push(gc, str.substr(offset, count)); + return false; + } + } + if (key == "Remove") { + if (args.size() >= 1 && + std::holds_alternative(args[0])) { + size_t offset = (size_t)std::get(args[0]); + size_t count = std::string::npos; + if (args.size() == 2 && + std::holds_alternative(args[1])) { + count = (size_t)std::get(args[1]); + } + cse.back()->Push(gc, str.erase(offset, count)); + return false; + } + } + if (key == "TrimStart") { + if (args.size() >= 0) { + char c = (args.size() == 1 && + std::holds_alternative(args[0])) + ? std::get(args[0]) + : ' '; + + size_t i = 0; + for (; i < str.size(); i++) { + if (str[i] != c) + break; + } + + cse.back()->Push(gc, (!str.empty() && i < str.size()) + ? str.substr(i) + : ""); + return false; + } + } + if (key == "TrimEnd") { + if (args.size() >= 0) { + char c = (args.size() == 1 && + std::holds_alternative(args[0])) + ? std::get(args[0]) + : ' '; + size_t i = str.size() - 1; + for (; i >= 0; i--) { + if (str[i] != c) + break; + } + + cse.back()->Push(gc, (!str.empty() && i < str.size()) + ? str.substr(0, i + 1) + : ""); + return false; + } + } + if (key == "EndsWith") { + std::string v; + if (GetArgument(args, 0, v)) { + if (str.size() < v.size()) { + cse.back()->Push(gc, false); + return false; + } + + size_t _end = str.size() - v.size(); + for (size_t i = 0; i < v.size(); i++) { + if (v[i] != str[i + _end]) { + cse.back()->Push(gc, false); return false; } } - cse.back()->Push(gc, nullptr); + cse.back()->Push(gc, true); return false; } - if(key == "ReadChar") - { - cse.back()->Push(gc,(int64_t)textReader->ReadChar()); - return false; - } - if(key == "ReadLine") - { - std::string line; - if(textReader->ReadLine(line)) - { - cse.back()->Push(gc, line); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadLineHttp") - { - std::string line; - if(textReader->ReadLineHttp(line)) - { - cse.back()->Push(gc, line); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadAllLines") - { - std::vector lines; - textReader->ReadAllLines(lines); - gc->BarrierBegin(); - TList* list = TList::Create(ls); - for(auto& item : lines) list->Add(item); - gc->BarrierEnd(); - return list; - } - if(key == "ReadToEnd") - { - std::string text; - textReader->ReadToEnd(text); - cse.back()->Push(gc,text); - return false; - } - if(key == "CopyTo") - { - std::shared_ptr writer; - if(GetArgument(args,0,writer)) - { - textReader->CopyTo(*writer); - } - } - cse.back()->Push(gc, Undefined()); + cse.back()->Push(gc, false); return false; } - else if(std::holds_alternative>(instance)) - { - auto textWriter=std::get>(instance); - if(key == "Write") - { - if(args.size()>0) - textWriter->Write(ToString(gc,args[0])); + if (key == "StartsWith") { + std::string v; + if (GetArgument(args, 0, v)) { + if (str.size() < v.size()) { + cse.back()->Push(gc, false); + return false; + } + for (size_t i = 0; i < v.size(); i++) { + if (v[i] != str[i]) { + cse.back()->Push(gc, false); + return false; + } + } + cse.back()->Push(gc, true); + return false; } - if(key == "WriteLine") - { - if(args.size()>0) - textWriter->WriteLine(ToString(gc,args[0])); + cse.back()->Push(gc, false); + return false; + } + if (key == "Escape") { + bool quote; + if (!GetArgument(args, 0, quote)) + quote = false; + cse.back()->Push(gc, EscapeString(str, quote)); + return false; + } + if (key == "Replace") { + std::string oldStr; + std::string newStr; + + std::string _str = {}; + if (GetArgument(args, 0, oldStr) && + GetArgument(args, 1, newStr)) { + _str = Tesses::Framework::Http::HttpUtils::Replace( + str, oldStr, newStr); } - if(key == "WriteData") - { - if(args.size()>0) - { - auto s=ToString(gc,args[0]); - textWriter->WriteData(s.c_str(),s.size()); + cse.back()->Push(gc, _str); + + return false; + } + if (key == "Split") { + std::string delimiter; + bool removeEmpty = false; + size_t count = std::string::npos; + + if (args.size() < 1 || args.size() > 3) + throw VMException( + "String.Split must only accept 1-3 arguments"); + if (!std::holds_alternative(args[0])) + throw VMException( + "String.Split first arg must be a string"); + else + delimiter = std::get(args[0]); + + if (args.size() > 1 && !std::holds_alternative(args[1])) + throw VMException("String.Split second arg must be a bool"); + else if (args.size() > 1) + removeEmpty = std::get(args[1]); + if (args.size() > 2 && + !std::holds_alternative(args[2])) + throw VMException( + "String.Split third arg must be a int64_t"); + else if (args.size() > 2) + count = (size_t)std::get(args[2]); + + auto res = Tesses::Framework::Http::HttpUtils::SplitString( + str, delimiter, count); + TList *mls = TList::Create(ls); + for (auto item : res) { + if (!removeEmpty || !item.empty()) + mls->Add(item); + } + cse.back()->Push(gc, mls); + return false; + // SplitString() + } + if (key == "GetAt") { + if (args.size() != 1) { + throw VMException( + "String.GetAt must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("String.GetAt must only accept a long"); + } + + size_t index = (size_t)std::get(args[0]); + size_t sz = str.size(); + if (index >= 0 && index < sz) { + cse.back()->Push(gc, str[index]); + return false; + } + } + if (key == "Count" || key == "Length") { + int64_t len = (int64_t)str.size(); + if (len < 0) + len = 0; + + cse.back()->Push(gc, len); + return false; + } + if (key == "ToString") { + cse.back()->Push(gc, str); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto &time = + std::get>( + instance); + if (key == "ToString") { + bool slim = false; + GetArgument(args, 0, slim); + + cse.back()->Push(gc, time->ToString(slim)); + + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto &date = + std::get>( + instance); + + if (key == "ToString") { + std::string fmt; + if (GetArgument(args, 0, fmt)) { + cse.back()->Push(gc, date->ToString(fmt)); + } else { + cse.back()->Push(gc, date->ToString()); + } + return false; + } + if (key == "ToHttpDate") { + cse.back()->Push(gc, date->ToHttpDate()); + return false; + } + if (key == "ToEpoch") { + cse.back()->Push(gc, date->ToEpoch()); + return false; + } + if (key == "ToLocal") { + cse.back()->Push( + gc, std::make_shared( + date->ToLocal())); + return false; + } + if (key == "ToUTC") { + cse.back()->Push( + gc, std::make_shared( + date->ToUTC())); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + + } else if (std::holds_alternative>(instance)) { + auto textReader = std::get< + std::shared_ptr>( + instance); + if (key == "Rewind") { + cse.back()->Push(gc, textReader->Rewind()); + return false; + } + if (key == "ReadBlock") { + int64_t sz; + if (GetArgument(args, 0, sz)) { + std::string block; + if (textReader->ReadBlock(block, (size_t)sz)) { + cse.back()->Push(gc, block); + return false; } } cse.back()->Push(gc, nullptr); return false; } - else if(std::holds_alternative>(instance)) - { - auto& br = std::get>(instance); - if(key == "ReadS8") - { - cse.back()->Push(gc,(int64_t)br->ReadI8()); - return false; - } - if(key == "ReadU8") - { - cse.back()->Push(gc,(int64_t)br->ReadU8()); - return false; - } - if(key == "ReadS16BE") - { - cse.back()->Push(gc,(int64_t)br->ReadI16BE()); - return false; - } - if(key == "ReadS16LE") - { - cse.back()->Push(gc,(int64_t)br->ReadI16LE()); - return false; - } - if(key == "ReadU16BE") - { - cse.back()->Push(gc,(int64_t)br->ReadU16BE()); - return false; - } - if(key == "ReadU16LE") - { - cse.back()->Push(gc,(int64_t)br->ReadU16LE()); - return false; - } - if(key == "ReadS32BE") - { - cse.back()->Push(gc,(int64_t)br->ReadI32BE()); - return false; - } - if(key == "ReadS32LE") - { - cse.back()->Push(gc,(int64_t)br->ReadI32LE()); - return false; - } - if(key == "ReadU32BE") - { - cse.back()->Push(gc,(int64_t)br->ReadU32BE()); - return false; - } - if(key == "ReadU32LE") - { - cse.back()->Push(gc,(int64_t)br->ReadU32LE()); - return false; - } - if(key == "ReadS64BE") - { - cse.back()->Push(gc,br->ReadI64BE()); - return false; - } - if(key == "ReadS64LE") - { - cse.back()->Push(gc,br->ReadI64LE()); - return false; - } - if(key == "ReadU16BE") - { - uint64_t value = br->ReadU64BE(); - int64_t value2 = 0; - memcpy(&value2,&value,sizeof(uint64_t)); - cse.back()->Push(gc,value2); - return false; - } - if(key == "ReadU64LE") - { - uint64_t value = br->ReadU64LE(); - int64_t value2 = 0; - memcpy(&value2,&value,sizeof(uint64_t)); - cse.back()->Push(gc,value2); - return false; - } - - if(key == "ReadF32BE") - { - cse.back()->Push(gc,(double)br->ReadF32BE()); - return false; - } - if(key == "ReadF32LE") - { - cse.back()->Push(gc,(double)br->ReadF32LE()); - return false; - } - - if(key == "ReadF64BE") - { - cse.back()->Push(gc,br->ReadF64BE()); - return false; - } - if(key == "ReadF64LE") - { - cse.back()->Push(gc,br->ReadF64LE()); - return false; - } - - if(key == "ReadUuid") - { - cse.back()->Push(gc, br->ReadUuid()); - return false; - } - cse.back()->Push(gc, Undefined()); + if (key == "ReadChar") { + cse.back()->Push(gc, (int64_t)textReader->ReadChar()); return false; } - else if(std::holds_alternative>(instance)) - { - auto& bw = std::get>(instance); - int64_t number; - - double numberDbl; - - Tesses::Framework::Uuid uuid; - if(GetArgument(args,0,number)) - { - if(key == "WriteS8") - { - bw->WriteI8((int8_t)number); - } - else if(key == "WriteU8") - { - bw->WriteI8((uint8_t)number); - } - - - else if(key == "WriteS16BE") - { - bw->WriteI16BE((int16_t)number); - } - else if(key == "WriteS16LE") - { - bw->WriteI16LE((int16_t)number); - } - else if(key == "WriteU16BE") - { - bw->WriteU16BE((uint16_t)number); - } - else if(key == "WriteU16LE") - { - bw->WriteU16LE((uint16_t)number); - } - - - else if(key == "WriteS32BE") - { - bw->WriteI32BE((int32_t)number); - } - else if(key == "WriteS32LE") - { - bw->WriteI32LE((int32_t)number); - } - else if(key == "WriteU32BE") - { - bw->WriteU32BE((uint32_t)number); - } - else if(key == "WriteU32LE") - { - bw->WriteU32LE((uint32_t)number); - } - - else if(key == "WriteS64BE") - { - bw->WriteI64BE(number); - } - else if(key == "WriteS64LE") - { - bw->WriteI64LE(number); - } - else if(key == "WriteU64BE") - { - uint64_t number2 = 0; - memcpy(&number2,&number, sizeof(uint64_t)); - bw->WriteU64BE(number2); - } - else if(key == "WriteU64LE") - { - - uint64_t number2 = 0; - memcpy(&number2,&number, sizeof(uint64_t)); - bw->WriteU64LE(number2); - } - - + if (key == "ReadLine") { + std::string line; + if (textReader->ReadLine(line)) { + cse.back()->Push(gc, line); + return false; } - else if(GetArgument(args,0,numberDbl)) - { - if(key == "WriteF32BE") - { - bw->WriteF32BE((float)numberDbl); - } - else if(key == "WriteF32LE") - { - bw->WriteF32LE((float)numberDbl); - } - else if(key == "WriteF64BE") - { - bw->WriteF64BE(numberDbl); - } - else if(key == "WriteF64LE") - { - bw->WriteF64LE(numberDbl); - } - } - else if(GetArgument(args,0,uuid)) - { - if(key == "WriteUuid") - { - bw->WriteUuid(uuid); - } - } - cse.back()->Push(gc,Undefined()); + cse.back()->Push(gc, nullptr); return false; } - else if(std::holds_alternative>(instance)) - { - auto& sse = std::get>(instance); - if(sse != nullptr) - { - std::string text; - std::string text2; - if(key == "SendComment" && GetArgument(args, 0, text)) - { - sse->SendComment(text); - } - else if(key == "SendCustomEvent" && GetArgument(args, 0, text) && GetArgument(args,1,text2)) { - sse->SendCustomEvent(text,text2); - } - else if(key == "SendCustomEvent" && GetArgument(args, 0, text)) { - if(GetArgument(args,1,text2)) - sse->SendData(text,text2); - else + if (key == "ReadLineHttp") { + std::string line; + if (textReader->ReadLineHttp(line)) { + cse.back()->Push(gc, line); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "ReadAllLines") { + std::vector lines; + textReader->ReadAllLines(lines); + gc->BarrierBegin(); + TList *list = TList::Create(ls); + for (auto &item : lines) + list->Add(item); + gc->BarrierEnd(); + return list; + } + if (key == "ReadToEnd") { + std::string text; + textReader->ReadToEnd(text); + cse.back()->Push(gc, text); + return false; + } + if (key == "CopyTo") { + std::shared_ptr + writer; + if (GetArgument(args, 0, writer)) { + textReader->CopyTo(*writer); + } + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative>(instance)) { + auto textWriter = std::get< + std::shared_ptr>( + instance); + if (key == "Write") { + if (args.size() > 0) + textWriter->Write(ToString(gc, args[0])); + } + if (key == "WriteLine") { + if (args.size() > 0) + textWriter->WriteLine(ToString(gc, args[0])); + } + if (key == "WriteData") { + if (args.size() > 0) { + auto s = ToString(gc, args[0]); + textWriter->WriteData(s.c_str(), s.size()); + } + } + cse.back()->Push(gc, nullptr); + return false; + } else if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto &br = std::get< + std::shared_ptr>( + instance); + if (key == "ReadS8") { + cse.back()->Push(gc, (int64_t)br->ReadI8()); + return false; + } + if (key == "ReadU8") { + cse.back()->Push(gc, (int64_t)br->ReadU8()); + return false; + } + if (key == "ReadS16BE") { + cse.back()->Push(gc, (int64_t)br->ReadI16BE()); + return false; + } + if (key == "ReadS16LE") { + cse.back()->Push(gc, (int64_t)br->ReadI16LE()); + return false; + } + if (key == "ReadU16BE") { + cse.back()->Push(gc, (int64_t)br->ReadU16BE()); + return false; + } + if (key == "ReadU16LE") { + cse.back()->Push(gc, (int64_t)br->ReadU16LE()); + return false; + } + if (key == "ReadS32BE") { + cse.back()->Push(gc, (int64_t)br->ReadI32BE()); + return false; + } + if (key == "ReadS32LE") { + cse.back()->Push(gc, (int64_t)br->ReadI32LE()); + return false; + } + if (key == "ReadU32BE") { + cse.back()->Push(gc, (int64_t)br->ReadU32BE()); + return false; + } + if (key == "ReadU32LE") { + cse.back()->Push(gc, (int64_t)br->ReadU32LE()); + return false; + } + if (key == "ReadS64BE") { + cse.back()->Push(gc, br->ReadI64BE()); + return false; + } + if (key == "ReadS64LE") { + cse.back()->Push(gc, br->ReadI64LE()); + return false; + } + if (key == "ReadU16BE") { + uint64_t value = br->ReadU64BE(); + int64_t value2 = 0; + memcpy(&value2, &value, sizeof(uint64_t)); + cse.back()->Push(gc, value2); + return false; + } + if (key == "ReadU64LE") { + uint64_t value = br->ReadU64LE(); + int64_t value2 = 0; + memcpy(&value2, &value, sizeof(uint64_t)); + cse.back()->Push(gc, value2); + return false; + } + + if (key == "ReadF32BE") { + cse.back()->Push(gc, (double)br->ReadF32BE()); + return false; + } + if (key == "ReadF32LE") { + cse.back()->Push(gc, (double)br->ReadF32LE()); + return false; + } + + if (key == "ReadF64BE") { + cse.back()->Push(gc, br->ReadF64BE()); + return false; + } + if (key == "ReadF64LE") { + cse.back()->Push(gc, br->ReadF64LE()); + return false; + } + + if (key == "ReadUuid") { + cse.back()->Push(gc, br->ReadUuid()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto &bw = std::get< + std::shared_ptr>( + instance); + int64_t number; + + double numberDbl; + + Tesses::Framework::Uuid uuid; + if (GetArgument(args, 0, number)) { + if (key == "WriteS8") { + bw->WriteI8((int8_t)number); + } else if (key == "WriteU8") { + bw->WriteI8((uint8_t)number); + } + + else if (key == "WriteS16BE") { + bw->WriteI16BE((int16_t)number); + } else if (key == "WriteS16LE") { + bw->WriteI16LE((int16_t)number); + } else if (key == "WriteU16BE") { + bw->WriteU16BE((uint16_t)number); + } else if (key == "WriteU16LE") { + bw->WriteU16LE((uint16_t)number); + } + + else if (key == "WriteS32BE") { + bw->WriteI32BE((int32_t)number); + } else if (key == "WriteS32LE") { + bw->WriteI32LE((int32_t)number); + } else if (key == "WriteU32BE") { + bw->WriteU32BE((uint32_t)number); + } else if (key == "WriteU32LE") { + bw->WriteU32LE((uint32_t)number); + } + + else if (key == "WriteS64BE") { + bw->WriteI64BE(number); + } else if (key == "WriteS64LE") { + bw->WriteI64LE(number); + } else if (key == "WriteU64BE") { + uint64_t number2 = 0; + memcpy(&number2, &number, sizeof(uint64_t)); + bw->WriteU64BE(number2); + } else if (key == "WriteU64LE") { + + uint64_t number2 = 0; + memcpy(&number2, &number, sizeof(uint64_t)); + bw->WriteU64LE(number2); + } + + } else if (GetArgument(args, 0, numberDbl)) { + if (key == "WriteF32BE") { + bw->WriteF32BE((float)numberDbl); + } else if (key == "WriteF32LE") { + bw->WriteF32LE((float)numberDbl); + } else if (key == "WriteF64BE") { + bw->WriteF64BE(numberDbl); + } else if (key == "WriteF64LE") { + bw->WriteF64LE(numberDbl); + } + } else if (GetArgument(args, 0, uuid)) { + if (key == "WriteUuid") { + bw->WriteUuid(uuid); + } + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative>(instance)) { + auto &sse = std::get< + std::shared_ptr>( + instance); + if (sse != nullptr) { + std::string text; + std::string text2; + if (key == "SendComment" && GetArgument(args, 0, text)) { + sse->SendComment(text); + } else if (key == "SendCustomEvent" && + GetArgument(args, 0, text) && + GetArgument(args, 1, text2)) { + sse->SendCustomEvent(text, text2); + } else if (key == "SendCustomEvent" && + GetArgument(args, 0, text)) { + if (GetArgument(args, 1, text2)) + sse->SendData(text, text2); + else sse->SendData(text); - } - else if(key == "SendId" && GetArgument(args, 0, text)) - { - sse->SendId(text); - } - else if(key == "SendRetry") - { - std::shared_ptr ts; - int64_t num; - if(GetArgument(args,0,ts) && ts) - { - sse->SendRetry(*ts); - } - else if(GetArgument(args,0,num)) - { - sse->SendRetry((uint32_t)num); - } + } else if (key == "SendId" && GetArgument(args, 0, text)) { + sse->SendId(text); + } else if (key == "SendRetry") { + std::shared_ptr ts; + int64_t num; + if (GetArgument(args, 0, ts) && ts) { + sse->SendRetry(*ts); + } else if (GetArgument(args, 0, num)) { + sse->SendRetry((uint32_t)num); } } - - cse.back()->Push(gc, Undefined()); - return false; } - else if(std::holds_alternative>(instance)) - { - auto& strm = std::get>(instance); - if(strm != nullptr) - { - auto memStrm = std::dynamic_pointer_cast(strm); - auto netStrm = std::dynamic_pointer_cast(strm); - - auto mystrm = std::dynamic_pointer_cast(strm); - if(mystrm != nullptr) - { - TDictionary* dict2; - if(GetObjectHeap(mystrm->obj, dict2)) - { + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto &strm = + std::get>( + instance); + if (strm != nullptr) { + auto memStrm = std::dynamic_pointer_cast< + Tesses::Framework::Streams::MemoryStream>(strm); + auto netStrm = std::dynamic_pointer_cast< + Tesses::Framework::Streams::NetworkStream>(strm); - gc->BarrierBegin(); - auto o = dict2->GetValue(key); - gc->BarrierEnd(); + auto mystrm = std::dynamic_pointer_cast(strm); - return InvokeMethod(ls,o,dict2,args); - } + if (mystrm != nullptr) { + TDictionary *dict2; + if (GetObjectHeap(mystrm->obj, dict2)) { + + gc->BarrierBegin(); + auto o = dict2->GetValue(key); + gc->BarrierEnd(); + + return InvokeMethod(ls, o, dict2, args); } - if(memStrm != nullptr) - { - if(key == "GetBytes") - { - auto res = TByteArray::Create(ls); - res->data = memStrm->GetBuffer(); - cse.back()->Push(gc, res); - return false; - } + } + if (memStrm != nullptr) { + if (key == "GetBytes") { + auto res = TByteArray::Create(ls); + res->data = memStrm->GetBuffer(); + cse.back()->Push(gc, res); + return false; } - if(netStrm != nullptr) - { - if(key == "SetMulticastMembership") - { - std::string ma; - std::string ifaceIP = "0.0.0.0"; - if(GetArgument(args,0,ma)) - { - GetArgument(args,1,ifaceIP); - netStrm->SetMulticastMembership(ma,ifaceIP); - } - cse.back()->Push(gc, Undefined()); - return false; + } + if (netStrm != nullptr) { + if (key == "SetMulticastMembership") { + std::string ma; + std::string ifaceIP = "0.0.0.0"; + if (GetArgument(args, 0, ma)) { + GetArgument(args, 1, ifaceIP); + netStrm->SetMulticastMembership(ma, ifaceIP); } - if(key == "GetPort") - { - cse.back()->Push(gc, (int64_t)netStrm->GetPort()); - return false; - } - if(key == "Bind") - { - std::string ip; - int64_t port; - if(GetArgument(args,0,ip) && GetArgument(args,1,port)) - netStrm->Bind(ip,(uint16_t)port); - - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Accept") - { - std::string ip; - uint16_t port; - auto strm = netStrm->Accept(ip,port); - TDictionary* dict = TDictionary::Create(ls); - gc->BarrierBegin(); - dict->SetValue("IP",ip); - dict->SetValue("Port",(int64_t)port); - dict->SetValue("Stream", strm); - - gc->BarrierEnd(); - cse.back()->Push(gc, dict); - return false; - } - if(key == "Listen") - { - int64_t backlog; - if(GetArgument(args,0,backlog)) - { - netStrm->Listen((int32_t)backlog); - } - else - { - netStrm->Listen(10); - } + cse.back()->Push(gc, Undefined()); + return false; + } + if (key == "GetPort") { + cse.back()->Push(gc, (int64_t)netStrm->GetPort()); + return false; + } + if (key == "Bind") { + std::string ip; + int64_t port; + if (GetArgument(args, 0, ip) && + GetArgument(args, 1, port)) + netStrm->Bind(ip, (uint16_t)port); - cse.back()->Push(gc, nullptr); - return false; + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "Accept") { + std::string ip; + uint16_t port; + auto strm = netStrm->Accept(ip, port); + TDictionary *dict = TDictionary::Create(ls); + gc->BarrierBegin(); + dict->SetValue("IP", ip); + dict->SetValue("Port", (int64_t)port); + dict->SetValue("Stream", strm); + + gc->BarrierEnd(); + cse.back()->Push(gc, dict); + return false; + } + if (key == "Listen") { + int64_t backlog; + if (GetArgument(args, 0, backlog)) { + netStrm->Listen((int32_t)backlog); + } else { + netStrm->Listen(10); } - if(key == "ReadFrom") - { - TByteArray* data; + + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "ReadFrom") { + TByteArray *data; int64_t offset; int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { + if (GetArgumentHeap(args, 0, data) && + GetArgument(args, 1, offset) && + GetArgument(args, 2, length)) { size_t off = (size_t)offset; size_t len = (size_t)length; - std::string ip={}; - uint16_t port=0; + std::string ip = {}; + uint16_t port = 0; + + if (off < len) + + len = netStrm->ReadFrom( + data->data.data() + off, + std::min(len, + std::min(data->data.size() - off, + data->data.size())), + ip, port); - if(off < len) - - len = netStrm->ReadFrom(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size())),ip,port); - else len = 0; - TDictionary* dict = TDictionary::Create(ls); + TDictionary *dict = TDictionary::Create(ls); gc->BarrierBegin(); - dict->SetValue("IP",ip); - dict->SetValue("Port",(int64_t)port); + dict->SetValue("IP", ip); + dict->SetValue("Port", (int64_t)port); dict->SetValue("Read", (int64_t)len); - + gc->BarrierEnd(); cse.back()->Push(gc, dict); - + return false; } cse.back()->Push(gc, nullptr); return false; - } - if(key == "WriteTo") - { - TByteArray* data; + } + if (key == "WriteTo") { + TByteArray *data; int64_t offset; int64_t length; std::string ip; int64_t port; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length) && GetArgument(args,3,ip) && GetArgument(args,4,port)) - { + if (GetArgumentHeap(args, 0, data) && + GetArgument(args, 1, offset) && + GetArgument(args, 2, length) && + GetArgument(args, 3, ip) && + GetArgument(args, 4, port)) { size_t off = (size_t)offset; size_t len = (size_t)length; - if(off < len) - - len = netStrm->WriteTo(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size())), ip, (int64_t)port); - + if (off < len) + + len = netStrm->WriteTo( + data->data.data() + off, + std::min(len, + std::min(data->data.size() - off, + data->data.size())), + ip, (int64_t)port); + else len = 0; - - cse.back()->Push(gc, (int64_t)len); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - } - if(key == "Read") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; - - if(off < len) - - len = strm->Read(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size()))); - - else - len = 0; - cse.back()->Push(gc, (int64_t)len); return false; } cse.back()->Push(gc, nullptr); return false; } - if(key == "Write") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; + } - if(off < len) - - len = strm->Write(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size()))); - - else - len = 0; - - cse.back()->Push(gc, (int64_t)len); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadBlock") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; + if (key == "Read") { + TByteArray *data; + int64_t offset; + int64_t length; + if (GetArgumentHeap(args, 0, data) && + GetArgument(args, 1, offset) && + GetArgument(args, 2, length)) { + size_t off = (size_t)offset; + size_t len = (size_t)length; - if(off < len) - - len = strm->ReadBlock(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size()))); - - else - len = 0; - - cse.back()->Push(gc, (int64_t)len); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "WriteText") - { - std::string text; + if (off < len) - if(GetArgument(args,0,text)) - { - strm->WriteBlock((const uint8_t*)text.data(), text.size()); - } + len = strm->Read( + data->data.data() + off, + std::min(len, std::min(data->data.size() - off, + data->data.size()))); - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "WriteBlock") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; + else + len = 0; - if(off < len) - - strm->WriteBlock(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size()))); - - - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CopyTo") - { - std::shared_ptr data; - int64_t buffSize; - if(GetArgument(args,0,data)) - { - if(!GetArgument(args,1,buffSize)) buffSize=1024; - strm->CopyTo(data,(size_t)buffSize); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CopyToLimit") - { - std::shared_ptr data; - int64_t cnt; - int64_t buffSize; - if(GetArgument(args,0,data) && GetArgument(args,1,cnt)) - { - if(!GetArgument(args,2,buffSize)) buffSize=1024; - strm->CopyToLimit(data,(uint64_t)cnt,(size_t)buffSize); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Flush") - { - strm->Flush(); - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Close") - { - strm->Close(); - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Seek") - { - int64_t pos,whence; - if(!GetArgument(args,0,pos)) pos=0; - - if(!GetArgument(args,1,whence)) whence=0; - - - strm->Seek(pos, whence == 0 ? Tesses::Framework::Streams::SeekOrigin::Begin : whence == 1 ? Tesses::Framework::Streams::SeekOrigin::Current : Tesses::Framework::Streams::SeekOrigin::End); - - cse.back()->Push(gc, nullptr); + cse.back()->Push(gc, (int64_t)len); return false; } cse.back()->Push(gc, nullptr); return false; } - } - else if(std::holds_alternative>(instance)) - { - auto svr = std::get>(instance); - if(svr != nullptr) - { - auto mountable = std::dynamic_pointer_cast(svr); - auto routable = std::dynamic_pointer_cast(svr); - - if(mountable != nullptr) - { - if(key == "Mount") - { - Tesses::Framework::Filesystem::VFSPath p; - - if(args.size() > 1 && GetArgumentAsPath(args,0,p)) - { - std::shared_ptr svr2=ToHttpServer(gc,args[1]); - - if(svr2) - mountable->Mount(p.ToString(), svr2); - - cse.back()->Push(gc,nullptr); - return false; - } - } - if(key == "Unmount") - { - Tesses::Framework::Filesystem::VFSPath p; - - if(GetArgumentAsPath(args,0,p)) - { - mountable->Unmount(p.ToString()); - cse.back()->Push(gc,nullptr); - return false; - } - } - } - if(routable != nullptr) - { - if(key == "Add") - { - std::string method; - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,method) && GetArgument(args,1,pattern) && GetArgumentHeap(args,2,callable)) - { - routable->Add(method,pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Delete") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Delete(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Get") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Get(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Options") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Options(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Patch") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Patch(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Post") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Post(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Put") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Put(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Trace") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Trace(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - } - if(key == "Handle") - { - cse.back()->Push(gc,IHttpServer_Handle(svr,args)); + if (key == "Write") { + TByteArray *data; + int64_t offset; + int64_t length; + if (GetArgumentHeap(args, 0, data) && + GetArgument(args, 1, offset) && + GetArgument(args, 2, length)) { + size_t off = (size_t)offset; + size_t len = (size_t)length; + + if (off < len) + + len = strm->Write( + data->data.data() + off, + std::min(len, std::min(data->data.size() - off, + data->data.size()))); + + else + len = 0; + + cse.back()->Push(gc, (int64_t)len); return false; } - cse.back()->Push(gc,Undefined()); + cse.back()->Push(gc, nullptr); return false; } - } - else if(std::holds_alternative>(instance)) - { - auto vfs = std::get>(instance); - if(vfs != nullptr) - { - auto myvfs = std::dynamic_pointer_cast(vfs); + if (key == "ReadBlock") { + TByteArray *data; + int64_t offset; + int64_t length; + if (GetArgumentHeap(args, 0, data) && + GetArgument(args, 1, offset) && + GetArgument(args, 2, length)) { + size_t off = (size_t)offset; + size_t len = (size_t)length; - auto mountable = std::dynamic_pointer_cast(vfs); + if (off < len) - - if(myvfs != nullptr) - { - TDictionary* dict2; - if(GetObjectHeap(myvfs->obj, dict2)) - { + len = strm->ReadBlock( + data->data.data() + off, + std::min(len, std::min(data->data.size() - off, + data->data.size()))); - gc->BarrierBegin(); - auto o = dict2->GetValue(key); - gc->BarrierEnd(); + else + len = 0; - return InvokeMethod(ls,o,dict2,args); - } - } - if(mountable != nullptr) - { - if(key == "Unmount") - { - Tesses::Framework::Filesystem::VFSPath path; - - if(GetArgumentAsPath(args,0,path)) - { - mountable->Unmount(path); - } - - cse.back()->Push(gc, nullptr); + cse.back()->Push(gc, (int64_t)len); return false; - } - if(key == "Mount") - { - Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr vfs2; - if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,vfs2)) - { - - //mountable->Mount(path, , true); - mountable->Mount(path, vfs2); - } + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "WriteText") { + std::string text; + + if (GetArgument(args, 0, text)) { + strm->WriteBlock((const uint8_t *)text.data(), + text.size()); + } + + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "WriteBlock") { + TByteArray *data; + int64_t offset; + int64_t length; + if (GetArgumentHeap(args, 0, data) && + GetArgument(args, 1, offset) && + GetArgument(args, 2, length)) { + size_t off = (size_t)offset; + size_t len = (size_t)length; + + if (off < len) + + strm->WriteBlock( + data->data.data() + off, + std::min(len, std::min(data->data.size() - off, + data->data.size()))); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "CopyTo") { + std::shared_ptr data; + int64_t buffSize; + if (GetArgument(args, 0, data)) { + if (!GetArgument(args, 1, buffSize)) + buffSize = 1024; + strm->CopyTo(data, (size_t)buffSize); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "CopyToLimit") { + std::shared_ptr data; + int64_t cnt; + int64_t buffSize; + if (GetArgument(args, 0, data) && + GetArgument(args, 1, cnt)) { + if (!GetArgument(args, 2, buffSize)) + buffSize = 1024; + strm->CopyToLimit(data, (uint64_t)cnt, + (size_t)buffSize); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "Flush") { + strm->Flush(); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "Close") { + strm->Close(); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "Seek") { + int64_t pos, whence; + if (!GetArgument(args, 0, pos)) + pos = 0; + + if (!GetArgument(args, 1, whence)) + whence = 0; + + strm->Seek( + pos, + whence == 0 + ? Tesses::Framework::Streams::SeekOrigin::Begin + : whence == 1 + ? Tesses::Framework::Streams::SeekOrigin::Current + : Tesses::Framework::Streams::SeekOrigin::End); + + cse.back()->Push(gc, nullptr); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + } else if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto svr = + std::get>( + instance); + if (svr != nullptr) { + auto mountable = std::dynamic_pointer_cast< + Tesses::Framework::Http::MountableServer>(svr); + auto routable = std::dynamic_pointer_cast< + Tesses::Framework::Http::RouteServer>(svr); + + if (mountable != nullptr) { + if (key == "Mount") { + Tesses::Framework::Filesystem::VFSPath p; + + if (args.size() > 1 && GetArgumentAsPath(args, 0, p)) { + std::shared_ptr< + Tesses::Framework::Http::IHttpServer> + svr2 = ToHttpServer(gc, args[1]); + + if (svr2) + mountable->Mount(p.ToString(), svr2); cse.back()->Push(gc, nullptr); return false; } } - if(key == "Close") - { - vfs->Close(); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "EnumeratePaths") - { - Tesses::Framework::Filesystem::VFSPath dir; - if(GetArgumentAsPath(args,0,dir)) - { - auto tem = TExternalMethod::Create(ls,"Get the enumerator",{},[vfs,dir](GCList& ls, std::vector args)->TObject{ - return TVFSPathEnumerator::Create(ls,vfs->EnumeratePaths(dir)); - }); - auto d1=TDictionary::Create(ls); - gc->BarrierBegin(); - tem->watch.push_back(vfs); - d1->SetValue("GetEnumerator", tem); - gc->BarrierEnd(); - - cse.back()->Push(gc,d1); - return false; - } + if (key == "Unmount") { + Tesses::Framework::Filesystem::VFSPath p; - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "MoveDirectory") - { - Tesses::Framework::Filesystem::VFSPath existingFile; - - Tesses::Framework::Filesystem::VFSPath symlinkFile; - if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) - { - vfs->MoveDirectory(existingFile,symlinkFile); + if (GetArgumentAsPath(args, 0, p)) { + mountable->Unmount(p.ToString()); + cse.back()->Push(gc, nullptr); return false; } - cse.back()->Push(gc, nullptr); - return false; } - if(key == "SetDate") - { - Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr lastWrite; - std::shared_ptr lastAccess; - if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,lastWrite) && GetArgument(args,2,lastAccess)) - { - vfs->SetDate(path,*lastWrite, *lastAccess); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "GetDate") - { - Tesses::Framework::Filesystem::VFSPath path; - if(GetArgumentAsPath(args,0,path)) - { - Tesses::Framework::Date::DateTime lastWrite; - Tesses::Framework::Date::DateTime lastAccess; - vfs->GetDate(path,lastWrite,lastAccess); - - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - - dict->SetValue("LastWrite", std::make_shared(lastWrite)); - dict->SetValue("LastAccess", std::make_shared(lastAccess)); - ls.GetGC()->BarrierEnd(); - - cse.back()->Push(gc, dict); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "MoveFile") - { - Tesses::Framework::Filesystem::VFSPath existingFile; - - Tesses::Framework::Filesystem::VFSPath symlinkFile; - if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) - { - vfs->MoveFile(existingFile,symlinkFile); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CreateHardlink") - { - Tesses::Framework::Filesystem::VFSPath existingFile; - - Tesses::Framework::Filesystem::VFSPath symlinkFile; - if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) - { - vfs->CreateHardlink(existingFile,symlinkFile); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CreateSymlink") - { - Tesses::Framework::Filesystem::VFSPath existingFile; - - Tesses::Framework::Filesystem::VFSPath symlinkFile; - if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) - { - vfs->CreateSymlink(existingFile,symlinkFile); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "RegularFileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->RegularFileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SpecialFileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->SpecialFileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "FIFOFileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->FIFOFileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SocketFileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->SocketFileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "BlockDeviceExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->BlockDeviceExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CharacterDeviceExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->CharacterDeviceExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SymlinkExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->SymlinkExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "DirectoryExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->DirectoryExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "FileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->FileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadLink") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->ReadLink(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "VFSPathToSystem") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->VFSPathToSystem(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SystemToVFSPath") - { - std::string filename; - if(GetArgument(args,0,filename)) - { - cse.back()->Push(gc,vfs->SystemToVFSPath(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "DeleteFile") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - vfs->DeleteFile(filename); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Lock") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - vfs->Lock(filename); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Unlock") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - vfs->Unlock(filename); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "DeleteDirectoryRecurse") - { - Tesses::Framework::Filesystem::VFSPath dirname; - if(GetArgumentAsPath(args,0,dirname)) - { - vfs->DeleteDirectoryRecurse(dirname); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "DeleteDirectory") - { - Tesses::Framework::Filesystem::VFSPath dirname; - if(GetArgumentAsPath(args,0,dirname)) - { - vfs->DeleteDirectory(dirname); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CreateDirectory") - { - - Tesses::Framework::Filesystem::VFSPath dirname; - if(GetArgumentAsPath(args,0,dirname)) - { - vfs->CreateDirectory(dirname); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "OpenFile") - { - - Tesses::Framework::Filesystem::VFSPath path; - std::string mode; - if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,mode)) - { - auto res = vfs->OpenFile(path,mode); - cse.back()->Push(gc, res); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Chmod") - { - Tesses::Framework::Filesystem::VFSPath path; - int64_t mode; - if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,mode)) - { - vfs->Chmod(path,(uint32_t)mode); - } - - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Stat") - { - Tesses::Framework::Filesystem::VFSPath path; - - if(GetArgumentAsPath(args,0,path)) - { - Tesses::Framework::Filesystem::StatData data; - if(vfs->Stat(path,data)) - { - cse.back()->Push(gc, TDictionary::Create(ls,{ - TDItem("BlockCount", (int64_t)data.BlockCount), - TDItem("BlockSize", (int64_t)data.BlockSize), - TDItem("Device", (int64_t)data.Device), - TDItem("DeviceId", (int64_t)data.DeviceId), - TDItem("GroupId", (int64_t)data.GroupId), - TDItem("HardLinks", (int64_t)data.HardLinks), - TDItem("Inode", (int64_t)data.Inode), - TDItem("LastAccess", std::make_shared(data.LastAccess)), - TDItem("LastModified", std::make_shared(data.LastModified)), - TDItem("LastStatus", std::make_shared(data.LastStatus)), - TDItem("Mode", (int64_t)data.Mode), - TDItem("Size", (int64_t)data.Size), - TDItem("UserId", (int64_t)data.UserId) - })); - return false; - } - } - - cse.back()->Push(gc, nullptr); - return false; - } - - if(key == "StatVFS") - { - Tesses::Framework::Filesystem::VFSPath path; - - if(GetArgumentAsPath(args,0,path)) - { - Tesses::Framework::Filesystem::StatVFSData data; - if(vfs->StatVFS(path,data)) - { - cse.back()->Push(gc, TDictionary::Create(ls,{ - TDItem("BlockSize", (int64_t)data.BlockSize), - TDItem("FragmentSize",(int64_t)data.FragmentSize), - TDItem("Blocks",(int64_t)data.Blocks), - TDItem("BlocksFree",(int64_t)data.BlocksFree), - TDItem("BlocksAvailable", (int64_t)data.BlocksAvailable), - TDItem("TotalInodes", (int64_t)data.TotalInodes), - TDItem("FreeInodes",(int64_t)data.FreeInodes), - TDItem("AvailableInodes",(int64_t)data.AvailableInodes), - TDItem("Id",(int64_t)data.Id), - TDItem("Flags",(int64_t)data.Flags), - TDItem("MaxNameLength",(int64_t)data.MaxNameLength) - })); - return false; - } - } - - cse.back()->Push(gc, nullptr); - return false; - } - cse.back()->Push(gc, nullptr); - return false; } - - } - else if(std::holds_alternative(instance)) - { - auto& obj = std::get(instance); - if(key == "ToBytes") - { - TByteArray* ba = TByteArray::Create(ls); - ba->data.resize(16); - Tesses::Framework::Serialization::BitConverter::FromUuid(ba->data[0], obj); - cse.back()->Push(gc, ba); - return false; - } - if(key == "ToString") - { - int64_t arg; - if(GetArgument(args,0,arg)) - { - cse.back()->Push(gc, obj.ToString((Framework::UuidStringifyConfig)arg)); - return false; + if (routable != nullptr) { + if (key == "Add") { + std::string method; + std::string pattern; + TCallable *callable; + if (GetArgument(args, 0, method) && + GetArgument(args, 1, pattern) && + GetArgumentHeap(args, 2, callable)) { + routable->Add( + method, pattern, + callable->ToRouteServerRequestHandler(gc)); + } + } else if (key == "Delete") { + std::string pattern; + TCallable *callable; + if (GetArgument(args, 0, pattern) && + GetArgumentHeap(args, 1, callable)) { + routable->Delete( + pattern, + callable->ToRouteServerRequestHandler(gc)); + } + } else if (key == "Get") { + std::string pattern; + TCallable *callable; + if (GetArgument(args, 0, pattern) && + GetArgumentHeap(args, 1, callable)) { + routable->Get( + pattern, + callable->ToRouteServerRequestHandler(gc)); + } + } else if (key == "Options") { + std::string pattern; + TCallable *callable; + if (GetArgument(args, 0, pattern) && + GetArgumentHeap(args, 1, callable)) { + routable->Options( + pattern, + callable->ToRouteServerRequestHandler(gc)); + } + } else if (key == "Patch") { + std::string pattern; + TCallable *callable; + if (GetArgument(args, 0, pattern) && + GetArgumentHeap(args, 1, callable)) { + routable->Patch( + pattern, + callable->ToRouteServerRequestHandler(gc)); + } + } else if (key == "Post") { + std::string pattern; + TCallable *callable; + if (GetArgument(args, 0, pattern) && + GetArgumentHeap(args, 1, callable)) { + routable->Post( + pattern, + callable->ToRouteServerRequestHandler(gc)); + } + } else if (key == "Put") { + std::string pattern; + TCallable *callable; + if (GetArgument(args, 0, pattern) && + GetArgumentHeap(args, 1, callable)) { + routable->Put( + pattern, + callable->ToRouteServerRequestHandler(gc)); + } + } else if (key == "Trace") { + std::string pattern; + TCallable *callable; + if (GetArgument(args, 0, pattern) && + GetArgumentHeap(args, 1, callable)) { + routable->Trace( + pattern, + callable->ToRouteServerRequestHandler(gc)); + } } - cse.back()->Push(gc, obj.ToString(Framework::UuidStringifyConfig::LowercaseNoCurly)); + } + if (key == "Handle") { + cse.back()->Push(gc, IHttpServer_Handle(svr, args)); return false; } cse.back()->Push(gc, Undefined()); return false; } - else if(std::holds_alternative(instance)) - { - auto obj = std::get(instance).obj; - auto list = dynamic_cast(obj); - auto dynList = dynamic_cast(obj); - auto bArray = dynamic_cast(obj); - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto ittr = dynamic_cast(obj); - - auto env = dynamic_cast(obj); + } else if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto vfs = + std::get>( + instance); + if (vfs != nullptr) { + auto myvfs = std::dynamic_pointer_cast(vfs); - auto subEnv = dynamic_cast(obj); - auto rootEnv = dynamic_cast(obj); - auto callable = dynamic_cast(obj); - auto callstackEntry = dynamic_cast(obj); - - - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - auto aArray=dynamic_cast(obj); - auto ttask = dynamic_cast(obj); - auto file = dynamic_cast(obj); + auto mountable = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::MountableFilesystem>(vfs); - auto queryable = dynamic_cast(obj); + if (myvfs != nullptr) { + TDictionary *dict2; + if (GetObjectHeap(myvfs->obj, dict2)) { - if(queryable != nullptr) - { - if(key == "Skip") - { - int64_t count; - if(GetArgument(args,0,count)) - { - cse.back()->Push(gc, queryable->Skip(ls,count)); - return false; - } + gc->BarrierBegin(); + auto o = dict2->GetValue(key); + gc->BarrierEnd(); + + return InvokeMethod(ls, o, dict2, args); } - if(key == "Take") - { - int64_t count; - if(GetArgument(args,0,count)) - { - cse.back()->Push(gc, queryable->Take(ls,count)); - return false; + } + if (mountable != nullptr) { + if (key == "Unmount") { + Tesses::Framework::Filesystem::VFSPath path; + + if (GetArgumentAsPath(args, 0, path)) { + mountable->Unmount(path); } - } - if(key == "SkipWhile") - { - TCallable* callable; - if(GetArgumentHeap(args, 0, callable)) - { - cse.back()->Push(gc, queryable->SkipWhile(ls,callable)); - return false; - } - } - if(key == "TakeWhile") - { - TCallable* callable; - if(GetArgumentHeap(args, 0, callable)) - { - cse.back()->Push(gc, queryable->TakeWhile(ls,callable)); - return false; - } - } - if(key == "Select") - { - TCallable* callable; - if(GetArgumentHeap(args, 0, callable)) - { - cse.back()->Push(gc, queryable->Select(ls,callable)); - return false; - } - } - if(key == "Where") - { - TCallable* callable; - if(GetArgumentHeap(args, 0, callable)) - { - cse.back()->Push(gc, queryable->Where(ls,callable)); - return false; - } - } - if(key == "ToList") - { - cse.back()->Push(gc, queryable->ToList(ls)); + + cse.back()->Push(gc, nullptr); return false; } + if (key == "Mount") { + Tesses::Framework::Filesystem::VFSPath path; + std::shared_ptr + vfs2; + if (GetArgumentAsPath(args, 0, path) && + GetArgument(args, 1, vfs2)) { - - - if(key == "ForEach") - { - TCallable* call; - if(GetArgumentHeap(args,0,call)) - { - queryable->ForEach(gc, call); + // mountable->Mount(path, , true); + mountable->Mount(path, vfs2); } - cse.back()->Push(gc, Undefined()); + cse.back()->Push(gc, nullptr); return false; } - - - - if(key == "Count") - { - TCallable* call; - if(GetArgumentHeap(args,0,call)) - { - cse.back()->Push(gc, queryable->Count(gc, call)); - return false; - } - else { - cse.back()->Push(gc, queryable->Count(gc)); - return false; - } - } - if(key == "Contains") - { - if(!args.empty()) - { - cse.back()->Push(gc, queryable->Contains(gc, args[0])); - return false; - } - } - if(key == "All") - { - TCallable* call; - if(GetArgumentHeap(args,0,call)) - { - cse.back()->Push(gc, queryable->All(gc, call)); - return false; - } - } - if(key == "Any") - { - TCallable* call; - if(GetArgumentHeap(args,0,call)) - { - cse.back()->Push(gc, queryable->Any(gc, call)); - return false; - } - } - - if(key == "GetEnumerator") - { - cse.back()->Push(gc, queryable->GetEnumerator(ls)); - return false; - } - - cse.back()->Push(gc, Undefined()); + } + if (key == "Close") { + vfs->Close(); + cse.back()->Push(gc, nullptr); return false; } + if (key == "EnumeratePaths") { + Tesses::Framework::Filesystem::VFSPath dir; + if (GetArgumentAsPath(args, 0, dir)) { + auto tem = TExternalMethod::Create( + ls, "Get the enumerator", {}, + [vfs, dir](GCList &ls, + std::vector args) -> TObject { + return TVFSPathEnumerator::Create( + ls, vfs->EnumeratePaths(dir)); + }); + auto d1 = TDictionary::Create(ls); + gc->BarrierBegin(); + tem->watch.push_back(vfs); + d1->SetValue("GetEnumerator", tem); + gc->BarrierEnd(); - if(file != nullptr) - { - if(key == "MetadataDecode") - { - int64_t index; - if(GetArgument(args,0, index) && (size_t)index < file->metadata.size()) - { - cse.back()->Push(gc,file->MetadataDecode(ls,(size_t)index)); - return false; - } + cse.back()->Push(gc, d1); + return false; } - if(key == "MetadataName") - { - int64_t index; - if(GetArgument(args,0, index) && (size_t)index < file->metadata.size()) - { - cse.back()->Push(gc,file->metadata.at((size_t)index).first); - return false; - } - } - cse.back()->Push(gc,Undefined()); - return false; - } - if(ttask != nullptr) - { - if(key == "ContinueWith") - { - TCallable* callable2; - if(GetArgumentHeap(args,0,callable2)) - { - cse.back()->Push(gc,ttask->ContinueWith(ls,callable2)); - return false; - } - } - if(key == "Wait") - { - - cse.back()->Push(gc,ttask->Wait()); - return false; - } - cse.back()->Push(gc,Undefined()); + + cse.back()->Push(gc, nullptr); return false; } + if (key == "MoveDirectory") { + Tesses::Framework::Filesystem::VFSPath existingFile; - if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,key,args)); - return false; - } - - if(callstackEntry != nullptr) - { - if(key == "Resume") - { - gc->BarrierBegin(); - cse.push_back(callstackEntry); - gc->BarrierEnd(); - return true; - } - if(key == "Push") - { - if(!args.empty()) - callstackEntry->Push(gc, args[0]); - else - callstackEntry->Push(gc,Undefined()); - return false; - } - if(key == "Pop") - { - cse.back()->Push(gc, callstackEntry->Pop(ls)); - return false; - } - } - - - if(rootEnv != nullptr) - { - //TStd::RegisterCrypto - //TStd::RegisterDictionary - //TStd::RegisterEnv - //TStd::RegisterIO - //TStd::RegisterJson - //TStd::RegisterNet - //TStd::RegisterOGC - //TStd::RegisterPath - //TStd::RegisterRoot - //TStd::RegisterSqlite - //TStd::RegisterVM - auto myEnv = cse.back()->env->GetRootEnvironment(); - - if(key == "RegisterOnError") - { - TCallable* callable; - if(!rootEnv->permissions.locked && GetArgumentHeap(args,0,callable)) - { - gc->BarrierBegin(); - rootEnv->RegisterOnError(callable); - gc->BarrierEnd(); - } - } - if(key == "SetCustomConsole") - { - TDictionary* dict; - if(!rootEnv->permissions.locked && GetArgumentHeap(args,0, dict)) - { - gc->BarrierBegin(); - rootEnv->permissions.customConsole = dict; - gc->BarrierEnd(); - } - else if(!rootEnv->permissions.locked && myEnv->permissions.customConsole == nullptr) - { - gc->BarrierBegin(); - rootEnv->permissions.customConsole=nullptr; - gc->BarrierEnd(); - } - } - if(key == "RegisterEverything") - { - if(rootEnv->permissions.locked) - { - cse.back()->Push(gc,nullptr); - return false; - } - - if(myEnv->permissions.canRegisterEverything) - { - std::shared_ptr vfs; - if(GetArgument(args,0, vfs)) - { - - auto rfs = std::dynamic_pointer_cast(vfs); - if(rfs) - { - TStd::RegisterStd(gc,rootEnv, rfs); - cse.back()->Push(gc,nullptr); - return false; - } - } - - if(myEnv->permissions.localfs) - TStd::RegisterStd(gc, rootEnv, std::make_shared(myEnv->permissions.localfs->GetVFS(),myEnv->permissions.localfs->GetWorking())); - else - TStd::RegisterStd(gc, rootEnv, nullptr); - - - - cse.back()->Push(gc,nullptr); - return false; - } - else - { - if(myEnv->permissions.canRegisterConsole && !rootEnv->permissions.locked) - TStd::RegisterConsole(gc, rootEnv); - - if(myEnv->permissions.canRegisterCrypto && !rootEnv->permissions.locked) - TStd::RegisterCrypto(gc, rootEnv); - - if(myEnv->permissions.canRegisterDictionary && !rootEnv->permissions.locked) - TStd::RegisterDictionary(gc, rootEnv); - - if(myEnv->permissions.canRegisterEnv && !rootEnv->permissions.locked) - TStd::RegisterEnv(gc, rootEnv); - - - if(myEnv->permissions.canRegisterIO && !rootEnv->permissions.locked) - { - if(myEnv->permissions.localfs) - { - TStd::RegisterIO(gc, rootEnv, std::make_shared(myEnv->permissions.localfs->GetVFS(),myEnv->permissions.localfs->GetWorking())); - } - else { - TStd::RegisterIO(gc, rootEnv, nullptr); - } - } - - if(myEnv->permissions.canRegisterJSON && !rootEnv->permissions.locked) - TStd::RegisterJson(gc, rootEnv); - - if(myEnv->permissions.canRegisterNet && !rootEnv->permissions.locked) - TStd::RegisterNet(gc, rootEnv); - - if(myEnv->permissions.canRegisterOGC && !rootEnv->permissions.locked) - TStd::RegisterOGC(gc, rootEnv); - - if(myEnv->permissions.canRegisterPath && !rootEnv->permissions.locked) - TStd::RegisterPath(gc, rootEnv); - - if(myEnv->permissions.canRegisterRoot && !rootEnv->permissions.locked) - TStd::RegisterRoot(gc, rootEnv); - - - if(myEnv->permissions.canRegisterSqlite && !rootEnv->permissions.locked) - TStd::RegisterSqlite(gc, rootEnv); - - if(myEnv->permissions.canRegisterVM && !rootEnv->permissions.locked) - TStd::RegisterVM(gc, rootEnv); - if(myEnv->permissions.canRegisterProcess && !rootEnv->permissions.locked) - TStd::RegisterProcess(gc, rootEnv); - } - - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterClass") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterClass) && !rootEnv->permissions.locked) - TStd::RegisterClass(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - - if(key == "RegisterConsole") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterConsole) && !rootEnv->permissions.locked) - TStd::RegisterConsole(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterProcess") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterProcess) && !rootEnv->permissions.locked) - TStd::RegisterProcess(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterCrypto") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterCrypto) && !rootEnv->permissions.locked) - TStd::RegisterCrypto(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterDictionary") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterDictionary) && !rootEnv->permissions.locked) - TStd::RegisterDictionary(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterEnv") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterEnv) && !rootEnv->permissions.locked) - TStd::RegisterDictionary(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterIO") - { - std::shared_ptr vfs; - - bool r; - if(GetArgument(args,0,r)) - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterIO) && !rootEnv->permissions.locked) - { - if(myEnv->permissions.localfs) - { - TStd::RegisterIO(gc, rootEnv, std::make_shared(myEnv->permissions.localfs->GetVFS(),myEnv->permissions.localfs->GetWorking())); - } - else { - TStd::RegisterIO(gc, rootEnv, nullptr); - } - } - } - if(GetArgument(args,0,vfs)) - { - auto rfs = std::dynamic_pointer_cast(vfs); - if(rfs && (myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterIO) && !rootEnv->permissions.locked) - { - TStd::RegisterIO(gc, rootEnv, rfs); - } - } - cse.back()->Push(gc,nullptr); - return false; - - } - if(key == "RegisterJson") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterJSON) && !rootEnv->permissions.locked) - TStd::RegisterJson(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterNet") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterNet) && !rootEnv->permissions.locked) - TStd::RegisterNet(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterOGC") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterOGC) && !rootEnv->permissions.locked) - TStd::RegisterOGC(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterPath") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterPath) && !rootEnv->permissions.locked) - TStd::RegisterPath(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterRoot") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterRoot) && !rootEnv->permissions.locked) - TStd::RegisterRoot(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - - if(key == "RegisterSqlite") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterSqlite) && !rootEnv->permissions.locked) - TStd::RegisterSqlite(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - - if(key == "SetSqliteRoot") - { - Tesses::Framework::Filesystem::VFSPath p; - if(!rootEnv->permissions.locked) - { - if(GetArgumentAsPath(args,0,p)) - { - if(myEnv->permissions.sqlite3Scoped) - { - rootEnv->permissions.sqliteOffsetPath = myEnv->permissions.sqliteOffsetPath / p.CollapseRelativeParents(); - rootEnv->permissions.sqlite3Scoped = true; - } - else - { - rootEnv->permissions.sqliteOffsetPath = p; - rootEnv->permissions.sqlite3Scoped = true; - } - } - else { - if(myEnv->permissions.sqlite3Scoped) - { - rootEnv->permissions.sqliteOffsetPath = myEnv->permissions.sqliteOffsetPath; - rootEnv->permissions.sqlite3Scoped = true; - } - else - { - rootEnv->permissions.sqlite3Scoped = false; - } - } - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterVM") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterVM) && !rootEnv->permissions.locked) - TStd::RegisterVM(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "LockRegister") - { - if(!rootEnv->permissions.locked) - { - rootEnv->permissions.locked=true; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "GetDictionary") - { - - cse.back()->Push(gc,rootEnv->GetDictionary()); - return false; - } - if(key == "LoadFileWithDependencies") - { - std::shared_ptr vfs0; - TFile* f; - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgument(args,0,vfs0) ) - { - if(GetArgumentHeap(args,1,f)) - { - rootEnv->LoadFileWithDependencies(gc,vfs0,f); - } - else if(GetArgumentAsPath(args,1,p)) - { - rootEnv->LoadFileWithDependencies(gc,vfs0,p); - } - } - cse.back()->Push(gc,nullptr); - return false; - } - } - if(subEnv != nullptr) - { - if(key == "GetDictionary") - { - cse.back()->Push(gc,subEnv->GetDictionary()); - return false; - } - } - - if(env != nullptr) - { - if(key == "Eval") - { - std::string str; - if(GetArgument(args,0,str)) - { - - - cse.back()->Push(gc,env->Eval(ls,str)); - return false; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "GetRootEnvironment") - { - cse.back()->Push(gc,env->GetRootEnvironment()); - return false; - } - - if(key == "GetSubEnvironment") - { - cse.back()->Push(gc,env->GetSubEnvironment(ls)); - return false; - } - if(key == "GetParentEnvironment") - { - cse.back()->Push(gc,env->GetParentEnvironment()); - return false; - } - if(key == "GetVariable") - { - std::string key; - gc->BarrierBegin(); - if(GetArgument(args,0,key)) - cse.back()->Push(gc,env->GetVariable(key)); - gc->BarrierEnd(); - return false; - } - if(key == "SetVariable") - { - std::string key; - - gc->BarrierBegin(); - if(args.size() > 1 && GetArgument(args,0,key)) - { - if(env->HasConstForSet(key)) - { - gc->BarrierEnd(); - ThrowConstError(key); - } - - env->SetVariable(key,args[1]); - - } - gc->BarrierEnd(); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "DeclareVariable") - { - std::string key; - - gc->BarrierBegin(); - if(args.size() > 1 && GetArgument(args,0,key)) - { - if(env->HasConstForDeclare(key)) - { - gc->BarrierEnd(); - ThrowConstError(key); - } - env->DeclareVariable(key,args[1]); - - } - gc->BarrierEnd(); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "DeclareConstVariable") - { - std::string key; - - gc->BarrierBegin(); - if(args.size() > 1 && GetArgument(args,0,key)) - { - if(env->HasConstForDeclare(key)) - { - gc->BarrierEnd(); - ThrowConstError(key); - } - env->DeclareConstVariable(key,args[1]); - } - gc->BarrierEnd(); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "LoadFile") - { - TFile* f; - if(GetArgumentHeap(args,0,f)) - { - env->LoadFile(gc,f); - } - cse.back()->Push(gc,nullptr); - return false; - } - - cse.back()->Push(gc,nullptr); - return false; - } - - - - if(ittr != nullptr) - { - if(key == "MoveNext") - { - cse.back()->Push(gc, ittr->MoveNext(gc)); + Tesses::Framework::Filesystem::VFSPath symlinkFile; + if (GetArgumentAsPath(args, 0, existingFile) && + GetArgumentAsPath(args, 1, symlinkFile)) { + vfs->MoveDirectory(existingFile, symlinkFile); return false; } cse.back()->Push(gc, nullptr); return false; } - - else if(bArray != nullptr) - { - if(key == "Count" || key == "Length") - { - int64_t len = (int64_t)bArray->data.size(); - if(len < 0) len = 0; - - cse.back()->Push(gc, len); - return false; - + if (key == "SetDate") { + Tesses::Framework::Filesystem::VFSPath path; + std::shared_ptr + lastWrite; + std::shared_ptr + lastAccess; + if (GetArgumentAsPath(args, 0, path) && + GetArgument(args, 1, lastWrite) && + GetArgument(args, 2, lastAccess)) { + vfs->SetDate(path, *lastWrite, *lastAccess); } - if(key == "ToString") - { - cse.back()->Push(gc,std::string(bArray->data.begin(),bArray->data.end())); - return false; - } - if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("ByteArray.GetAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("ByteArray.GetAt must only accept a long"); - } - - size_t index = (size_t)std::get(args[0]); - size_t sz = bArray->data.size(); - if(index >= 0 && index < sz) - { - cse.back()->Push(gc, (int64_t)bArray->data[index]); - return false; - } - - } - - if(key == "SetAt") - { - if(args.size() != 2) - { - throw VMException("ByteArray.SetAt must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("ByteArray.SetAt first argument must only accept a long"); - } - - uint8_t v = 0; - - if(std::holds_alternative(args[1])) - { - v = (uint8_t)(std::get(args[1]) & 0xFF); - } - - size_t index = (size_t)std::get(args[0]); - size_t sz = bArray->data.size(); - if(index >= 0 && index < sz) - { - bArray->data[index]=v; - return false; - } - - } - if(key == "ToCHeaderFile") - { - std::string name = "NONAME"; - GetArgument(args,0,name); - - cse.back()->Push(gc, Tesses::Framework::Text::GenerateCHeaderFile(bArray->data,name)); - return false; - } - if(key == "CopyTo") - { - //CopyTo(destBuff, offsetSrc, offsetDest, length) - - if(args.size() != 4) - { - throw VMException("ByteArray.CopyTo must only accept 4 arguments"); - } - - TByteArray* bArray2; - int64_t offsetSrc; - int64_t offsetDest; - int64_t count; - if(!GetArgumentHeap(args,0,bArray2)) - { - throw VMException("ByteArray.CopyTo first argument must be a ByteArray"); - } - if(!GetArgument(args,1, offsetSrc)) - { - throw VMException("ByteArray.CopyTo second argument must be a Long (offsetSrc)"); - } - if(!GetArgument(args,2, offsetDest)) - { - throw VMException("ByteArray.CopyTo third argument must be a Long (offsetDest)"); - } - if(!GetArgument(args,3,count)) - { - throw VMException("ByteArray.CopyTo fourth argument must be a Long (length)"); - } - size_t offsrc = (size_t)offsetSrc; - size_t offdest = (size_t)offsetDest; - size_t len = (size_t)count; - - if(offsrc > bArray->data.size()) - { - offsrc = bArray->data.size(); - } - - if(offdest > bArray2->data.size()) - { - offdest = bArray2->data.size(); - } - - len = std::min(std::min(bArray->data.size()-offsrc,bArray2->data.size()-offdest),len); - - if(len > 0) - memcpy(bArray2->data.data()+offdest,bArray->data.data()+offsrc,len); - cse.back()->Push(gc,bArray2); - return false; - } - if(key == "Insert") - { - if(args.size() != 4) - { - throw VMException("ByteArray.Insert must only accept 4 arguments"); - } - //Insert(offsetDest, buffer, offsetSrc, length) - TByteArray* bArray2; - int64_t offsetSrc; - int64_t offsetDest; - int64_t count; - if(!GetArgumentHeap(args,1,bArray2)) - { - throw VMException("ByteArray.Insert second argument must be a ByteArray"); - } - if(!GetArgument(args,0, offsetSrc)) - { - throw VMException("ByteArray.Insert first argument must be a Long (offsetSrc)"); - } - if(!GetArgument(args,2, offsetDest)) - { - throw VMException("ByteArray.Insert third argument must be a Long (offsetDest)"); - } - if(!GetArgument(args,3,count)) - { - throw VMException("ByteArray.Insert fourth argument must be a Long (length)"); - } - - size_t offsrc = (size_t)offsetSrc; - size_t offdest = (size_t)offsetDest; - size_t len = (size_t)count; - - if(offsrc > bArray->data.size()) - { - offsrc = bArray->data.size(); - } - if(offdest > bArray->data.size()) - { - offdest = bArray->data.size(); - } - - len = std::min(len,bArray2->data.size()-offsrc); - - - bArray->data.insert(bArray->data.begin()+offdest,bArray2->data.begin()+offsrc,bArray2->data.begin()+offsrc+len); - cse.back()->Push(gc, bArray); - return false; - } - if(key == "Append") - { - if(args.size() != 3) - { - throw VMException("ByteArray.Append must only accept 3 arguments"); - } - TByteArray* bArray2; - int64_t offset; - int64_t count; - if(!GetArgumentHeap(args,0,bArray2)) - { - throw VMException("ByteArray.Append first argument must be a ByteArray"); - } - if(!GetArgument(args,1, offset)) - { - throw VMException("ByteArray.Append second argument must be a Long (offset)"); - } - if(!GetArgument(args,2,count)) - { - throw VMException("ByteArray.Append third argument must be a Long (length)"); - } - size_t off = (size_t)offset; - size_t len = (size_t)count; - - if(off > bArray->data.size()) - { - off = bArray->data.size(); - } - - len = std::min(bArray->data.size() - off,len); - bArray->data.insert(bArray->data.end(),bArray2->data.begin()+off,bArray2->data.begin()+off+len); - cse.back()->Push(gc,bArray); - return false; - } - - if(key == "Resize") - { - if(args.size() != 1) - { - throw VMException("ByteArray.Resize must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("ByteArray.Resize must only accept a long"); - } - - size_t len = (size_t)std::get(args[0]); - if(len >= 0) - { - bArray->data.resize(len); - } - cse.back()->Push(gc, bArray); - return false; - } - if(key == "SetU16BE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) - { - uint16_t number = (uint16_t)value; - BitConverter::FromUint16BE(bArray->data[(size_t)index],number); - cse.back()->Push(gc, (int64_t)value); - return false; - } - } - if(key == "SetU32BE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - uint32_t number = (uint32_t)value; - BitConverter::FromUint32BE(bArray->data[(size_t)index],number); - cse.back()->Push(gc, (int64_t)value); - return false; - } - } - if(key == "SetU64BE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - uint64_t number=0; - memcpy(&number, &value,sizeof(int64_t)); - BitConverter::FromUint64BE(bArray->data[(size_t)index],number); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "SetU16LE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) - { - uint16_t number = (uint16_t)value; - BitConverter::FromUint16LE(bArray->data[(size_t)index],number); - cse.back()->Push(gc, (int64_t)value); - return false; - } - } - if(key == "SetU32LE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - uint32_t number = (uint32_t)value; - BitConverter::FromUint32LE(bArray->data[(size_t)index],number); - cse.back()->Push(gc, (int64_t)value); - return false; - } - } - if(key == "SetU64LE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - uint64_t number=0; - memcpy(&number, &value,sizeof(int64_t)); - BitConverter::FromUint64LE(bArray->data[(size_t)index],number); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "SetU16BE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) - { - BitConverter::FromSint16BE(bArray->data[(size_t)index],(int16_t)value); - cse.back()->Push(gc, (int64_t)(int16_t)value); - return false; - } - } - if(key == "SetS32BE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - BitConverter::FromSint32BE(bArray->data[(size_t)index],(int32_t)value); - cse.back()->Push(gc,(int64_t)(int32_t) value); - return false; - } - } - if(key == "SetS64BE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - BitConverter::FromSint64BE(bArray->data[(size_t)index],value); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "SetS16LE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) - { - BitConverter::FromSint16LE(bArray->data[(size_t)index],(int16_t)value); - cse.back()->Push(gc,(int64_t)(int16_t) value); - return false; - } - } - if(key == "SetS32LE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - BitConverter::FromSint32LE(bArray->data[(size_t)index],(int32_t)value); - cse.back()->Push(gc, (int64_t)(int32_t)value); - return false; - } - } - if(key == "SetS64LE") - { - int64_t index; - int64_t value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - BitConverter::FromSint64LE(bArray->data[(size_t)index],value); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "SetF32LE") - { - int64_t index; - double value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - BitConverter::FromFloatLE(bArray->data[(size_t)index],(float)value); - cse.back()->Push(gc, (double)(float)value); - return false; - } - } - if(key == "SetF64LE") - { - int64_t index; - double value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - BitConverter::FromDoubleLE(bArray->data[(size_t)index],value); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "SetF32BE") - { - int64_t index; - double value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - BitConverter::FromFloatBE(bArray->data[(size_t)index],(float)value); - cse.back()->Push(gc, (double)(float)value); - return false; - } - } - if(key == "SetF64BE") - { - int64_t index; - double value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - BitConverter::FromDoubleBE(bArray->data[(size_t)index],value); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "SetUuid") - { - int64_t index; - Tesses::Framework::Uuid value; - if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 16 <= bArray->data.size()) - { - BitConverter::FromUuid(bArray->data[(size_t)index],value); - cse.back()->Push(gc, value); - return false; - } - } - - if(key == "GetU16BE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) - { - int64_t value = (int64_t)BitConverter::ToUint16BE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetU32BE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - int64_t value = (int64_t)BitConverter::ToUint32BE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetU64BE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - uint64_t value = BitConverter::ToUint64BE(bArray->data[(size_t)index]); - int64_t value2 = 0; - memcpy(&value2, &value, sizeof(uint64_t)); - cse.back()->Push(gc, value2); - return false; - } - } - if(key == "GetU16LE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) - { - int64_t value = (int64_t)BitConverter::ToUint16LE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetU32LE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - int64_t value = (int64_t)BitConverter::ToUint32LE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetU64LE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - uint64_t value = BitConverter::ToUint64LE(bArray->data[(size_t)index]); - int64_t value2 = 0; - memcpy(&value2, &value, sizeof(uint64_t)); - cse.back()->Push(gc, value2); - return false; - } - } - - if(key == "GetS16BE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) - { - int64_t value = (int64_t)BitConverter::ToSint16BE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetS32BE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - int64_t value = (int64_t)BitConverter::ToSint32BE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetS64BE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - int64_t value = BitConverter::ToSint64BE(bArray->data[(size_t)index]); - - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetS16LE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) - { - int64_t value = (int64_t)BitConverter::ToSint16LE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetS32LE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - int64_t value = (int64_t)BitConverter::ToSint32LE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetS64LE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - int64_t value = BitConverter::ToSint64LE(bArray->data[(size_t)index]); - - cse.back()->Push(gc, value); - return false; - } - } - - if(key == "GetF32LE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - double value = (double)BitConverter::ToFloatLE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetF64LE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - uint64_t value = BitConverter::ToDoubleLE(bArray->data[(size_t)index]); - - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetF32BE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) - { - double value = (double)BitConverter::ToFloatBE(bArray->data[(size_t)index]); - cse.back()->Push(gc, value); - return false; - } - } - if(key == "GetF64BE") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) - { - uint64_t value = BitConverter::ToDoubleBE(bArray->data[(size_t)index]); - - cse.back()->Push(gc, value); - return false; - } - } - - if(key == "GetUuid") - { - int64_t index; - if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 16 <= bArray->data.size()) - { - auto value = BitConverter::ToUuid(bArray->data[(size_t)index]); - - cse.back()->Push(gc, value); - return false; - } - } - cse.back()->Push(gc, Undefined()); + cse.back()->Push(gc, nullptr); return false; } - else if(aArray != nullptr) - { - if(key == "ToString") - { - cse.back()->Push(gc,ToString(gc,aArray)); - return false; - } - else if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("AArray.GetAt must only accept one argument"); - } - cse.back()->Push(gc, aArray->Get(gc,args[0])); - return false; - } - else if(key == "SetAt") - { - if(args.size() != 2) - { - throw VMException("AArray.SetAt must only accept two arguments"); - } - aArray->Set(gc,args[0],args[1]); - cse.back()->Push(gc, args[1]); - return false; - } - else if(key == "GetKey") - { - if(args.size() != 1) - { - throw VMException("AArray.GetKey must only accept one argument"); - } + if (key == "GetDate") { + Tesses::Framework::Filesystem::VFSPath path; + if (GetArgumentAsPath(args, 0, path)) { + Tesses::Framework::Date::DateTime lastWrite; + Tesses::Framework::Date::DateTime lastAccess; + vfs->GetDate(path, lastWrite, lastAccess); - if(!std::holds_alternative(args[0])) - { - throw VMException("AArray.GetKey must only accept a long"); - } + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); - gc->BarrierBegin(); - auto res = aArray->GetKey(std::get(args[0])); - gc->BarrierEnd(); + dict->SetValue( + "LastWrite", + std::make_shared( + lastWrite)); + dict->SetValue( + "LastAccess", + std::make_shared( + lastAccess)); + ls.GetGC()->BarrierEnd(); + + cse.back()->Push(gc, dict); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "MoveFile") { + Tesses::Framework::Filesystem::VFSPath existingFile; + + Tesses::Framework::Filesystem::VFSPath symlinkFile; + if (GetArgumentAsPath(args, 0, existingFile) && + GetArgumentAsPath(args, 1, symlinkFile)) { + vfs->MoveFile(existingFile, symlinkFile); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "CreateHardlink") { + Tesses::Framework::Filesystem::VFSPath existingFile; + + Tesses::Framework::Filesystem::VFSPath symlinkFile; + if (GetArgumentAsPath(args, 0, existingFile) && + GetArgumentAsPath(args, 1, symlinkFile)) { + vfs->CreateHardlink(existingFile, symlinkFile); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "CreateSymlink") { + Tesses::Framework::Filesystem::VFSPath existingFile; + + Tesses::Framework::Filesystem::VFSPath symlinkFile; + if (GetArgumentAsPath(args, 0, existingFile) && + GetArgumentAsPath(args, 1, symlinkFile)) { + vfs->CreateSymlink(existingFile, symlinkFile); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegularFileExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->RegularFileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "SpecialFileExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->SpecialFileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "FIFOFileExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->FIFOFileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "SocketFileExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->SocketFileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "BlockDeviceExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->BlockDeviceExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "CharacterDeviceExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, + vfs->CharacterDeviceExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "SymlinkExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->SymlinkExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "DirectoryExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->DirectoryExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "FileExists") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->FileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "ReadLink") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->ReadLink(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "VFSPathToSystem") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + cse.back()->Push(gc, vfs->VFSPathToSystem(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "SystemToVFSPath") { + std::string filename; + if (GetArgument(args, 0, filename)) { + cse.back()->Push(gc, vfs->SystemToVFSPath(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "DeleteFile") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + vfs->DeleteFile(filename); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "Lock") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + vfs->Lock(filename); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "Unlock") { + Tesses::Framework::Filesystem::VFSPath filename; + if (GetArgumentAsPath(args, 0, filename)) { + vfs->Unlock(filename); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "DeleteDirectoryRecurse") { + Tesses::Framework::Filesystem::VFSPath dirname; + if (GetArgumentAsPath(args, 0, dirname)) { + vfs->DeleteDirectoryRecurse(dirname); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "DeleteDirectory") { + Tesses::Framework::Filesystem::VFSPath dirname; + if (GetArgumentAsPath(args, 0, dirname)) { + vfs->DeleteDirectory(dirname); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "CreateDirectory") { + + Tesses::Framework::Filesystem::VFSPath dirname; + if (GetArgumentAsPath(args, 0, dirname)) { + vfs->CreateDirectory(dirname); + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "OpenFile") { + + Tesses::Framework::Filesystem::VFSPath path; + std::string mode; + if (GetArgumentAsPath(args, 0, path) && + GetArgument(args, 1, mode)) { + auto res = vfs->OpenFile(path, mode); cse.back()->Push(gc, res); return false; } - else if(key == "GetValue") - { - if(args.size() != 1) - { - throw VMException("AArray.GetValue must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("AArray.GetValue must only accept a long"); - } - - gc->BarrierBegin(); - auto res = aArray->GetValue(std::get(args[0])); - gc->BarrierEnd(); - cse.back()->Push(gc, res); - return false; - } - else if(key == "SetKey") - { - if(args.size() != 2) - { - throw VMException("AArray.SetKey must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("AArray.SetKey first argument must only accept a long"); - } - - gc->BarrierBegin(); - aArray->SetKey(std::get(args[0]),args[1]); - gc->BarrierEnd(); - cse.back()->Push(gc, args[1]); - return false; - } - else if(key == "SetValue") - { - if(args.size() != 2) - { - throw VMException("AArray.SetValue must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("AArray.SetValue first argument must only accept a long"); - } - - gc->BarrierBegin(); - aArray->SetValue(std::get(args[0]),args[1]); - gc->BarrierEnd(); - cse.back()->Push(gc, args[1]); - return false; - } - else if(key == "Count" || key == "Length") - { - gc->BarrierBegin(); - cse.back()->Push(gc, aArray->Count()); - gc->BarrierEnd(); - return false; - } - else if(key == "GetEnumerator") - { - - cse.back()->Push(gc,TAssociativeArrayEnumerator::Create(ls,aArray)); - return false; - } - cse.back()->Push(gc,Undefined()); + cse.back()->Push(gc, nullptr); return false; } - else if(list != nullptr) - { - - if(key == "GetEnumerator") - { - cse.back()->Push(gc, TListEnumerator::Create(ls,list)); - return false; + if (key == "Chmod") { + Tesses::Framework::Filesystem::VFSPath path; + int64_t mode; + if (GetArgumentAsPath(args, 0, path) && + GetArgument(args, 1, mode)) { + vfs->Chmod(path, (uint32_t)mode); } - else if(key == "ToString") - { - - cse.back()->Push(gc,Json_Encode(list)); - return false; - - } - else if(key == "Insert") - { - if(args.size() != 2) - { - throw VMException("List.Insert must only accept two arguments"); - } - int64_t index; - if(!GetArgument(args,0,index)) - { - throw VMException("List.Insert first argument must be Long"); - } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "Stat") { + Tesses::Framework::Filesystem::VFSPath path; - gc->BarrierBegin(); - list->Insert(index,args[1]); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "Add") - { - if(args.size() != 1) - { - throw VMException("List.Add must only accept one argument"); - } - gc->BarrierBegin(); - list->Add(args[0]); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "Contains") - { - if(args.size() != 1) - { - throw VMException("List.Contains must only accept one argument"); - } - gc->BarrierBegin(); - for(int64_t i = 0; i < list->Count(); i++) - { - auto item = list->Get(i); - gc->BarrierEnd(); - if(Equals(gc,args[0],item)) - { - cse.back()->Push(gc, true); - return false; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, false); - return false; - } - else if(key == "IndexOf") - { - //IndexOf(obj, $idx) - if(args.size() < 1 || args.size() > 2) - { - throw VMException("List.IndexOf must either have one or two arguments"); - } - - int64_t i=0; - - GetArgument(args,1,i); - gc->BarrierBegin(); - for(; i < list->Count(); i++) - { - auto item = list->Get(i); - gc->BarrierEnd(); - if(Equals(gc,args[0],item)) - { - - cse.back()->Push(gc,i); - return false; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc,(int64_t)-1); - return false; - } - else if(key == "RemoveAllEqual") - { - if(args.size() != 1) - { - throw VMException("List.RemoveAllEqual must only accept one argument"); - } - - - gc->BarrierBegin(); - for(int64_t i = 0; i < list->Count(); i++) - { - auto item = list->Get(i); - gc->BarrierEnd(); - if(Equals(gc,args[0],item)) - { - gc->BarrierBegin(); - list->RemoveAt(i); - i--; - }else gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "Remove") - { - if(args.size() != 1) - { - throw VMException("List.Remove must only accept one argument"); - } - - - gc->BarrierBegin(); - for(int64_t i = 0; i < list->Count(); i++) - { - auto item = list->Get(i); - gc->BarrierEnd(); - if(Equals(gc,args[0],item)) - { - gc->BarrierBegin(); - list->RemoveAt(i); - gc->BarrierEnd(); - break; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "RemoveAt") - { - if(args.size() != 1) - { - throw VMException("List.RemoveAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.RemoveAt must only accept a long"); - } - gc->BarrierBegin(); - list->RemoveAt(std::get(args[0])); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "Clear") - { - gc->BarrierBegin(); - list->Clear(); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("List.GetAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.GetAt must only accept a long"); - } - - int64_t index = std::get(args[0]); - if(index >= 0 && index < list->Count()) - { - cse.back()->Push(gc, list->Get(index)); + if (GetArgumentAsPath(args, 0, path)) { + Tesses::Framework::Filesystem::StatData data; + if (vfs->Stat(path, data)) { + cse.back()->Push( + gc, + TDictionary::Create( + ls, + {TDItem("BlockCount", + (int64_t)data.BlockCount), + TDItem("BlockSize", + (int64_t)data.BlockSize), + TDItem("Device", (int64_t)data.Device), + TDItem("DeviceId", (int64_t)data.DeviceId), + TDItem("GroupId", (int64_t)data.GroupId), + TDItem("HardLinks", + (int64_t)data.HardLinks), + TDItem("Inode", (int64_t)data.Inode), + TDItem( + "LastAccess", + std::make_shared< + Tesses::Framework::Date::DateTime>( + data.LastAccess)), + TDItem( + "LastModified", + std::make_shared< + Tesses::Framework::Date::DateTime>( + data.LastModified)), + TDItem( + "LastStatus", + std::make_shared< + Tesses::Framework::Date::DateTime>( + data.LastStatus)), + TDItem("Mode", (int64_t)data.Mode), + TDItem("Size", (int64_t)data.Size), + TDItem("UserId", (int64_t)data.UserId)})); return false; } - } - else if(key == "SetAt") - { - if(args.size() != 2) - { - throw VMException("List.SetAt must only accept two arguments"); - } - if(!std::holds_alternative(args[0])) - { - throw VMException("List.SetAt first argument must only accept a long"); - } + cse.back()->Push(gc, nullptr); + return false; + } - int64_t index = std::get(args[0]); - if(index >= 0 && index < list->Count()) - { - list->Set(index,args[1]); + if (key == "StatVFS") { + Tesses::Framework::Filesystem::VFSPath path; + + if (GetArgumentAsPath(args, 0, path)) { + Tesses::Framework::Filesystem::StatVFSData data; + if (vfs->StatVFS(path, data)) { + cse.back()->Push( + gc, + TDictionary::Create( + ls, {TDItem("BlockSize", + (int64_t)data.BlockSize), + TDItem("FragmentSize", + (int64_t)data.FragmentSize), + TDItem("Blocks", (int64_t)data.Blocks), + TDItem("BlocksFree", + (int64_t)data.BlocksFree), + TDItem("BlocksAvailable", + (int64_t)data.BlocksAvailable), + TDItem("TotalInodes", + (int64_t)data.TotalInodes), + TDItem("FreeInodes", + (int64_t)data.FreeInodes), + TDItem("AvailableInodes", + (int64_t)data.AvailableInodes), + TDItem("Id", (int64_t)data.Id), + TDItem("Flags", (int64_t)data.Flags), + TDItem("MaxNameLength", + (int64_t)data.MaxNameLength)})); return false; } - } - - else if(key == "Count" || key == "Length") - { - gc->BarrierBegin(); - cse.back()->Push(gc, list->Count()); - gc->BarrierEnd(); + + cse.back()->Push(gc, nullptr); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + + } else if (std::holds_alternative(instance)) { + auto &obj = std::get(instance); + if (key == "ToBytes") { + TByteArray *ba = TByteArray::Create(ls); + ba->data.resize(16); + Tesses::Framework::Serialization::BitConverter::FromUuid( + ba->data[0], obj); + cse.back()->Push(gc, ba); + return false; + } + if (key == "ToString") { + int64_t arg; + if (GetArgument(args, 0, arg)) { + cse.back()->Push( + gc, obj.ToString((Framework::UuidStringifyConfig)arg)); + return false; + } + cse.back()->Push( + gc, obj.ToString( + Framework::UuidStringifyConfig::LowercaseNoCurly)); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (std::holds_alternative(instance)) { + auto obj = std::get(instance).obj; + auto list = dynamic_cast(obj); + auto dynList = dynamic_cast(obj); + auto bArray = dynamic_cast(obj); + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto ittr = dynamic_cast(obj); + + auto env = dynamic_cast(obj); + + auto subEnv = dynamic_cast(obj); + auto rootEnv = dynamic_cast(obj); + auto callable = dynamic_cast(obj); + auto callstackEntry = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + auto aArray = dynamic_cast(obj); + auto ttask = dynamic_cast(obj); + auto file = dynamic_cast(obj); + + auto queryable = dynamic_cast(obj); + + if (queryable != nullptr) { + if (key == "Skip") { + int64_t count; + if (GetArgument(args, 0, count)) { + cse.back()->Push(gc, queryable->Skip(ls, count)); return false; } + } + if (key == "Take") { + int64_t count; + if (GetArgument(args, 0, count)) { + cse.back()->Push(gc, queryable->Take(ls, count)); + return false; + } + } + if (key == "SkipWhile") { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) { + cse.back()->Push(gc, + queryable->SkipWhile(ls, callable)); + return false; + } + } + if (key == "TakeWhile") { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) { + cse.back()->Push(gc, + queryable->TakeWhile(ls, callable)); + return false; + } + } + if (key == "Select") { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) { + cse.back()->Push(gc, queryable->Select(ls, callable)); + return false; + } + } + if (key == "Where") { + TCallable *callable; + if (GetArgumentHeap(args, 0, callable)) { + cse.back()->Push(gc, queryable->Where(ls, callable)); + return false; + } + } + if (key == "ToList") { + cse.back()->Push(gc, queryable->ToList(ls)); + return false; + } + + if (key == "ForEach") { + TCallable *call; + if (GetArgumentHeap(args, 0, call)) { + queryable->ForEach(gc, call); + } + cse.back()->Push(gc, Undefined()); return false; } - else if(dynList != nullptr) - { - if(key == "GetEnumerator") - { - cse.back()->Push(gc, TDynamicListEnumerator::Create(ls, dynList)); + if (key == "Count") { + TCallable *call; + if (GetArgumentHeap(args, 0, call)) { + cse.back()->Push(gc, queryable->Count(gc, call)); + return false; + } else { + cse.back()->Push(gc, queryable->Count(gc)); return false; } - else if(key == "ToString") - { - cse.back()->Push(gc, dynList->ToString(ls)); + } + if (key == "Contains") { + if (!args.empty()) { + cse.back()->Push(gc, queryable->Contains(gc, args[0])); return false; } - else if(key == "Insert") - { - if(args.size() != 2) - { - throw VMException("List.Insert must only accept two arguments"); - } - int64_t index; - - if(!GetArgument(args,0,index)) - { - throw VMException("List.Insert first argument must be Long"); - } - - cse.back()->Push(gc, dynList->Insert(ls,index,args[0])); + } + if (key == "All") { + TCallable *call; + if (GetArgumentHeap(args, 0, call)) { + cse.back()->Push(gc, queryable->All(gc, call)); return false; } - if(key == "Add") - { - if(args.size() != 1) - { - throw VMException("List.Add must only accept one argument"); - } - - cse.back()->Push(gc,dynList->Add(ls,args[0])); + } + if (key == "Any") { + TCallable *call; + if (GetArgumentHeap(args, 0, call)) { + cse.back()->Push(gc, queryable->Any(gc, call)); return false; } - if(key == "RemoveAllEqual") - { - if(args.size() != 1) - { - throw VMException("List.RemoveAllEqual must only accept one argument"); - } + } - cse.back()->Push(gc,dynList->RemoveAllEqual(ls, args[0])); - return false; - } - if(key == "Remove") - { - if(args.size() != 1) - { - throw VMException("List.Remove must only accept one argument"); - } - - - - cse.back()->Push(gc,dynList->Remove(ls, args[0])); - return false; - } - if(key == "RemoveAt") - { - if(args.size() != 1) - { - throw VMException("List.RemoveAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.RemoveAt must only accept a long"); - } - cse.back()->Push(gc,dynList->RemoveAt(ls,std::get(args[0]))); - - return false; - } - if(key == "Clear") - { - - - cse.back()->Push(gc, dynList->Clear(ls)); - return false; - } - if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("List.GetAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.GetAt must only accept a long"); - } - - int64_t index = std::get(args[0]); - if(index >= 0) - { - cse.back()->Push(gc, dynList->GetAt(ls,index)); - return false; - } - - } - if(key == "SetAt") - { - if(args.size() != 2) - { - throw VMException("List.SetAt must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.SetAt first argument must only accept a long"); - } - - int64_t index = std::get(args[0]); - if(index >= 0) - { - cse.back()->Push(gc,dynList->SetAt(ls,index,args[1])); - return false; - } - - } - - if(key == "Count" || key == "Length") - { - cse.back()->Push(gc, dynList->Count(ls)); - - return false; - } - cse.back()->Push(gc, Undefined()); + if (key == "GetEnumerator") { + cse.back()->Push(gc, queryable->GetEnumerator(ls)); return false; } - else if(cls != nullptr) - { + + cse.back()->Push(gc, Undefined()); + return false; + } + + if (file != nullptr) { + if (key == "MetadataDecode") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < file->metadata.size()) { + cse.back()->Push( + gc, file->MetadataDecode(ls, (size_t)index)); + return false; + } + } + if (key == "MetadataName") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < file->metadata.size()) { + cse.back()->Push( + gc, file->metadata.at((size_t)index).first); + return false; + } + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (ttask != nullptr) { + if (key == "ContinueWith") { + TCallable *callable2; + if (GetArgumentHeap(args, 0, callable2)) { + cse.back()->Push(gc, + ttask->ContinueWith(ls, callable2)); + return false; + } + } + if (key == "Wait") { + + cse.back()->Push(gc, ttask->Wait()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + + if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, key, args)); + return false; + } + + if (callstackEntry != nullptr) { + if (key == "Resume") { gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,key); + cse.push_back(callstackEntry); gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,args); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,args)); - return false; - } - cse.back()->Push(gc,Undefined()); + return true; + } + if (key == "Push") { + if (!args.empty()) + callstackEntry->Push(gc, args[0]); + else + callstackEntry->Push(gc, Undefined()); return false; } - else if(dict != nullptr) - { - if(key == "ToString" && !dict->MethodExists(ls, key) && args.empty()) - { - cse.back()->Push(gc,Json_Encode(dict)); - return false; - } - gc->BarrierBegin(); - auto o = dict->GetValue(key); - gc->BarrierEnd(); - - - return InvokeMethod(ls,o,dict,args); - } - else if(dynDict != nullptr) - { - - - cse.back()->Push(gc,dynDict->CallMethod(ls, key, args)); - + if (key == "Pop") { + cse.back()->Push(gc, callstackEntry->Pop(ls)); return false; } - else if(callable != nullptr) - { - if(key == "Call") - { - TList* argls; - if(GetArgumentHeap(args,0,argls)) - { - TClosure* clo = dynamic_cast(callable); - if(clo != nullptr) - { - AddCallStackEntry(ls,clo,argls->items); - return true; - } - else - { - cse.back()->Push(gc,callable->Call(ls, argls->items)); - return false; - } - } - } - cse.back()->Push(gc,nullptr); - return false; - } - else - { - cse.back()->Push(gc, Undefined()); - } } - else - { - cse.back()->Push(gc,Undefined()); + + if (rootEnv != nullptr) { + // TStd::RegisterCrypto + // TStd::RegisterDictionary + // TStd::RegisterEnv + // TStd::RegisterIO + // TStd::RegisterJson + // TStd::RegisterNet + // TStd::RegisterOGC + // TStd::RegisterPath + // TStd::RegisterRoot + // TStd::RegisterSqlite + // TStd::RegisterVM + auto myEnv = cse.back()->env->GetRootEnvironment(); + + if (key == "RegisterOnError") { + TCallable *callable; + if (!rootEnv->permissions.locked && + GetArgumentHeap(args, 0, callable)) { + gc->BarrierBegin(); + rootEnv->RegisterOnError(callable); + gc->BarrierEnd(); + } + } + if (key == "SetCustomConsole") { + TDictionary *dict; + if (!rootEnv->permissions.locked && + GetArgumentHeap(args, 0, dict)) { + gc->BarrierBegin(); + rootEnv->permissions.customConsole = dict; + gc->BarrierEnd(); + } else if (!rootEnv->permissions.locked && + myEnv->permissions.customConsole == nullptr) { + gc->BarrierBegin(); + rootEnv->permissions.customConsole = nullptr; + gc->BarrierEnd(); + } + } + if (key == "RegisterEverything") { + if (rootEnv->permissions.locked) { + cse.back()->Push(gc, nullptr); + return false; + } + + if (myEnv->permissions.canRegisterEverything) { + std::shared_ptr vfs; + if (GetArgument(args, 0, vfs)) { + + auto rfs = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem:: + RelativeFilesystem>(vfs); + if (rfs) { + TStd::RegisterStd(gc, rootEnv, rfs); + cse.back()->Push(gc, nullptr); + return false; + } + } + + if (myEnv->permissions.localfs) + TStd::RegisterStd( + gc, rootEnv, + std::make_shared( + myEnv->permissions.localfs->GetVFS(), + myEnv->permissions.localfs->GetWorking())); + else + TStd::RegisterStd(gc, rootEnv, nullptr); + + cse.back()->Push(gc, nullptr); + return false; + } else { + if (myEnv->permissions.canRegisterConsole && + !rootEnv->permissions.locked) + TStd::RegisterConsole(gc, rootEnv); + + if (myEnv->permissions.canRegisterCrypto && + !rootEnv->permissions.locked) + TStd::RegisterCrypto(gc, rootEnv); + + if (myEnv->permissions.canRegisterDictionary && + !rootEnv->permissions.locked) + TStd::RegisterDictionary(gc, rootEnv); + + if (myEnv->permissions.canRegisterEnv && + !rootEnv->permissions.locked) + TStd::RegisterEnv(gc, rootEnv); + + if (myEnv->permissions.canRegisterIO && + !rootEnv->permissions.locked) { + if (myEnv->permissions.localfs) { + TStd::RegisterIO( + gc, rootEnv, + std::make_shared< + Tesses::Framework::Filesystem:: + RelativeFilesystem>( + myEnv->permissions.localfs->GetVFS(), + myEnv->permissions.localfs + ->GetWorking())); + } else { + TStd::RegisterIO(gc, rootEnv, nullptr); + } + } + + if (myEnv->permissions.canRegisterJSON && + !rootEnv->permissions.locked) + TStd::RegisterJson(gc, rootEnv); + + if (myEnv->permissions.canRegisterNet && + !rootEnv->permissions.locked) + TStd::RegisterNet(gc, rootEnv); + + if (myEnv->permissions.canRegisterOGC && + !rootEnv->permissions.locked) + TStd::RegisterOGC(gc, rootEnv); + + if (myEnv->permissions.canRegisterPath && + !rootEnv->permissions.locked) + TStd::RegisterPath(gc, rootEnv); + + if (myEnv->permissions.canRegisterRoot && + !rootEnv->permissions.locked) + TStd::RegisterRoot(gc, rootEnv); + + if (myEnv->permissions.canRegisterSqlite && + !rootEnv->permissions.locked) + TStd::RegisterSqlite(gc, rootEnv); + + if (myEnv->permissions.canRegisterVM && + !rootEnv->permissions.locked) + TStd::RegisterVM(gc, rootEnv); + if (myEnv->permissions.canRegisterProcess && + !rootEnv->permissions.locked) + TStd::RegisterProcess(gc, rootEnv); + } + + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterClass") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterClass) && + !rootEnv->permissions.locked) + TStd::RegisterClass(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + + if (key == "RegisterConsole") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterConsole) && + !rootEnv->permissions.locked) + TStd::RegisterConsole(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterProcess") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterProcess) && + !rootEnv->permissions.locked) + TStd::RegisterProcess(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterCrypto") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterCrypto) && + !rootEnv->permissions.locked) + TStd::RegisterCrypto(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterDictionary") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterDictionary) && + !rootEnv->permissions.locked) + TStd::RegisterDictionary(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterEnv") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterEnv) && + !rootEnv->permissions.locked) + TStd::RegisterDictionary(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterIO") { + std::shared_ptr vfs; + + bool r; + if (GetArgument(args, 0, r)) { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterIO) && + !rootEnv->permissions.locked) { + if (myEnv->permissions.localfs) { + TStd::RegisterIO( + gc, rootEnv, + std::make_shared< + Tesses::Framework::Filesystem:: + RelativeFilesystem>( + myEnv->permissions.localfs->GetVFS(), + myEnv->permissions.localfs + ->GetWorking())); + } else { + TStd::RegisterIO(gc, rootEnv, nullptr); + } + } + } + if (GetArgument(args, 0, vfs)) { + auto rfs = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::RelativeFilesystem>( + vfs); + if (rfs && + (myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterIO) && + !rootEnv->permissions.locked) { + TStd::RegisterIO(gc, rootEnv, rfs); + } + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterJson") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterJSON) && + !rootEnv->permissions.locked) + TStd::RegisterJson(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterNet") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterNet) && + !rootEnv->permissions.locked) + TStd::RegisterNet(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterOGC") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterOGC) && + !rootEnv->permissions.locked) + TStd::RegisterOGC(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterPath") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterPath) && + !rootEnv->permissions.locked) + TStd::RegisterPath(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterRoot") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterRoot) && + !rootEnv->permissions.locked) + TStd::RegisterRoot(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + + if (key == "RegisterSqlite") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterSqlite) && + !rootEnv->permissions.locked) + TStd::RegisterSqlite(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + + if (key == "SetSqliteRoot") { + Tesses::Framework::Filesystem::VFSPath p; + if (!rootEnv->permissions.locked) { + if (GetArgumentAsPath(args, 0, p)) { + if (myEnv->permissions.sqlite3Scoped) { + rootEnv->permissions.sqliteOffsetPath = + myEnv->permissions.sqliteOffsetPath / + p.CollapseRelativeParents(); + rootEnv->permissions.sqlite3Scoped = true; + } else { + rootEnv->permissions.sqliteOffsetPath = p; + rootEnv->permissions.sqlite3Scoped = true; + } + } else { + if (myEnv->permissions.sqlite3Scoped) { + rootEnv->permissions.sqliteOffsetPath = + myEnv->permissions.sqliteOffsetPath; + rootEnv->permissions.sqlite3Scoped = true; + } else { + rootEnv->permissions.sqlite3Scoped = false; + } + } + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "RegisterVM") { + if ((myEnv->permissions.canRegisterEverything || + myEnv->permissions.canRegisterVM) && + !rootEnv->permissions.locked) + TStd::RegisterVM(gc, rootEnv); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "LockRegister") { + if (!rootEnv->permissions.locked) { + rootEnv->permissions.locked = true; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "GetDictionary") { + + cse.back()->Push(gc, rootEnv->GetDictionary()); + return false; + } + if (key == "LoadFileWithDependencies") { + std::shared_ptr vfs0; + TFile *f; + Tesses::Framework::Filesystem::VFSPath p; + if (GetArgument(args, 0, vfs0)) { + if (GetArgumentHeap(args, 1, f)) { + rootEnv->LoadFileWithDependencies(gc, vfs0, f); + } else if (GetArgumentAsPath(args, 1, p)) { + rootEnv->LoadFileWithDependencies(gc, vfs0, p); + } + } + cse.back()->Push(gc, nullptr); + return false; + } } + if (subEnv != nullptr) { + if (key == "GetDictionary") { + cse.back()->Push(gc, subEnv->GetDictionary()); + return false; + } + } + + if (env != nullptr) { + if (key == "Eval") { + std::string str; + if (GetArgument(args, 0, str)) { + + cse.back()->Push(gc, env->Eval(ls, str)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "GetRootEnvironment") { + cse.back()->Push(gc, env->GetRootEnvironment()); + return false; + } + + if (key == "GetSubEnvironment") { + cse.back()->Push(gc, env->GetSubEnvironment(ls)); + return false; + } + if (key == "GetParentEnvironment") { + cse.back()->Push(gc, env->GetParentEnvironment()); + return false; + } + if (key == "GetVariable") { + std::string key; + gc->BarrierBegin(); + if (GetArgument(args, 0, key)) + cse.back()->Push(gc, env->GetVariable(key)); + gc->BarrierEnd(); + return false; + } + if (key == "SetVariable") { + std::string key; + + gc->BarrierBegin(); + if (args.size() > 1 && GetArgument(args, 0, key)) { + if (env->HasConstForSet(key)) { + gc->BarrierEnd(); + ThrowConstError(key); + } + + env->SetVariable(key, args[1]); + } + gc->BarrierEnd(); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "DeclareVariable") { + std::string key; + + gc->BarrierBegin(); + if (args.size() > 1 && GetArgument(args, 0, key)) { + if (env->HasConstForDeclare(key)) { + gc->BarrierEnd(); + ThrowConstError(key); + } + env->DeclareVariable(key, args[1]); + } + gc->BarrierEnd(); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "DeclareConstVariable") { + std::string key; + + gc->BarrierBegin(); + if (args.size() > 1 && GetArgument(args, 0, key)) { + if (env->HasConstForDeclare(key)) { + gc->BarrierEnd(); + ThrowConstError(key); + } + env->DeclareConstVariable(key, args[1]); + } + gc->BarrierEnd(); + cse.back()->Push(gc, nullptr); + return false; + } + if (key == "LoadFile") { + TFile *f; + if (GetArgumentHeap(args, 0, f)) { + env->LoadFile(gc, f); + } + cse.back()->Push(gc, nullptr); + return false; + } + + cse.back()->Push(gc, nullptr); + return false; + } + + if (ittr != nullptr) { + if (key == "MoveNext") { + cse.back()->Push(gc, ittr->MoveNext(gc)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + + else if (bArray != nullptr) { + if (key == "Count" || key == "Length") { + int64_t len = (int64_t)bArray->data.size(); + if (len < 0) + len = 0; + + cse.back()->Push(gc, len); + return false; + } + if (key == "ToString") { + cse.back()->Push(gc, std::string(bArray->data.begin(), + bArray->data.end())); + return false; + } + if (key == "GetAt") { + if (args.size() != 1) { + throw VMException( + "ByteArray.GetAt must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException( + "ByteArray.GetAt must only accept a long"); + } + + size_t index = (size_t)std::get(args[0]); + size_t sz = bArray->data.size(); + if (index >= 0 && index < sz) { + cse.back()->Push(gc, (int64_t)bArray->data[index]); + return false; + } + } + + if (key == "SetAt") { + if (args.size() != 2) { + throw VMException( + "ByteArray.SetAt must only accept two arguments"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("ByteArray.SetAt first argument must " + "only accept a long"); + } + + uint8_t v = 0; + + if (std::holds_alternative(args[1])) { + v = (uint8_t)(std::get(args[1]) & 0xFF); + } + + size_t index = (size_t)std::get(args[0]); + size_t sz = bArray->data.size(); + if (index >= 0 && index < sz) { + bArray->data[index] = v; + return false; + } + } + if (key == "ToCHeaderFile") { + std::string name = "NONAME"; + GetArgument(args, 0, name); + + cse.back()->Push( + gc, Tesses::Framework::Text::GenerateCHeaderFile( + bArray->data, name)); + return false; + } + if (key == "CopyTo") { + // CopyTo(destBuff, offsetSrc, offsetDest, length) + + if (args.size() != 4) { + throw VMException( + "ByteArray.CopyTo must only accept 4 arguments"); + } + + TByteArray *bArray2; + int64_t offsetSrc; + int64_t offsetDest; + int64_t count; + if (!GetArgumentHeap(args, 0, bArray2)) { + throw VMException("ByteArray.CopyTo first argument " + "must be a ByteArray"); + } + if (!GetArgument(args, 1, offsetSrc)) { + throw VMException("ByteArray.CopyTo second argument " + "must be a Long (offsetSrc)"); + } + if (!GetArgument(args, 2, offsetDest)) { + throw VMException("ByteArray.CopyTo third argument " + "must be a Long (offsetDest)"); + } + if (!GetArgument(args, 3, count)) { + throw VMException("ByteArray.CopyTo fourth argument " + "must be a Long (length)"); + } + size_t offsrc = (size_t)offsetSrc; + size_t offdest = (size_t)offsetDest; + size_t len = (size_t)count; + + if (offsrc > bArray->data.size()) { + offsrc = bArray->data.size(); + } + + if (offdest > bArray2->data.size()) { + offdest = bArray2->data.size(); + } + + len = std::min( + std::min(bArray->data.size() - offsrc, + bArray2->data.size() - offdest), + len); + + if (len > 0) + memcpy(bArray2->data.data() + offdest, + bArray->data.data() + offsrc, len); + cse.back()->Push(gc, bArray2); + return false; + } + if (key == "Insert") { + if (args.size() != 4) { + throw VMException( + "ByteArray.Insert must only accept 4 arguments"); + } + // Insert(offsetDest, buffer, offsetSrc, length) + TByteArray *bArray2; + int64_t offsetSrc; + int64_t offsetDest; + int64_t count; + if (!GetArgumentHeap(args, 1, bArray2)) { + throw VMException("ByteArray.Insert second argument " + "must be a ByteArray"); + } + if (!GetArgument(args, 0, offsetSrc)) { + throw VMException("ByteArray.Insert first argument " + "must be a Long (offsetSrc)"); + } + if (!GetArgument(args, 2, offsetDest)) { + throw VMException("ByteArray.Insert third argument " + "must be a Long (offsetDest)"); + } + if (!GetArgument(args, 3, count)) { + throw VMException("ByteArray.Insert fourth argument " + "must be a Long (length)"); + } + + size_t offsrc = (size_t)offsetSrc; + size_t offdest = (size_t)offsetDest; + size_t len = (size_t)count; + + if (offsrc > bArray->data.size()) { + offsrc = bArray->data.size(); + } + if (offdest > bArray->data.size()) { + offdest = bArray->data.size(); + } + + len = std::min(len, bArray2->data.size() - offsrc); + + bArray->data.insert(bArray->data.begin() + offdest, + bArray2->data.begin() + offsrc, + bArray2->data.begin() + offsrc + len); + cse.back()->Push(gc, bArray); + return false; + } + if (key == "Append") { + if (args.size() != 3) { + throw VMException( + "ByteArray.Append must only accept 3 arguments"); + } + TByteArray *bArray2; + int64_t offset; + int64_t count; + if (!GetArgumentHeap(args, 0, bArray2)) { + throw VMException("ByteArray.Append first argument " + "must be a ByteArray"); + } + if (!GetArgument(args, 1, offset)) { + throw VMException("ByteArray.Append second argument " + "must be a Long (offset)"); + } + if (!GetArgument(args, 2, count)) { + throw VMException("ByteArray.Append third argument " + "must be a Long (length)"); + } + size_t off = (size_t)offset; + size_t len = (size_t)count; + + if (off > bArray->data.size()) { + off = bArray->data.size(); + } + + len = std::min(bArray->data.size() - off, len); + bArray->data.insert(bArray->data.end(), + bArray2->data.begin() + off, + bArray2->data.begin() + off + len); + cse.back()->Push(gc, bArray); + return false; + } + + if (key == "Resize") { + if (args.size() != 1) { + throw VMException( + "ByteArray.Resize must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException( + "ByteArray.Resize must only accept a long"); + } + + size_t len = (size_t)std::get(args[0]); + if (len >= 0) { + bArray->data.resize(len); + } + cse.back()->Push(gc, bArray); + return false; + } + if (key == "SetU16BE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 2 <= bArray->data.size()) { + uint16_t number = (uint16_t)value; + BitConverter::FromUint16BE(bArray->data[(size_t)index], + number); + cse.back()->Push(gc, (int64_t)value); + return false; + } + } + if (key == "SetU32BE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + uint32_t number = (uint32_t)value; + BitConverter::FromUint32BE(bArray->data[(size_t)index], + number); + cse.back()->Push(gc, (int64_t)value); + return false; + } + } + if (key == "SetU64BE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + uint64_t number = 0; + memcpy(&number, &value, sizeof(int64_t)); + BitConverter::FromUint64BE(bArray->data[(size_t)index], + number); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "SetU16LE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 2 <= bArray->data.size()) { + uint16_t number = (uint16_t)value; + BitConverter::FromUint16LE(bArray->data[(size_t)index], + number); + cse.back()->Push(gc, (int64_t)value); + return false; + } + } + if (key == "SetU32LE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + uint32_t number = (uint32_t)value; + BitConverter::FromUint32LE(bArray->data[(size_t)index], + number); + cse.back()->Push(gc, (int64_t)value); + return false; + } + } + if (key == "SetU64LE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + uint64_t number = 0; + memcpy(&number, &value, sizeof(int64_t)); + BitConverter::FromUint64LE(bArray->data[(size_t)index], + number); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "SetU16BE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 2 <= bArray->data.size()) { + BitConverter::FromSint16BE(bArray->data[(size_t)index], + (int16_t)value); + cse.back()->Push(gc, (int64_t)(int16_t)value); + return false; + } + } + if (key == "SetS32BE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + BitConverter::FromSint32BE(bArray->data[(size_t)index], + (int32_t)value); + cse.back()->Push(gc, (int64_t)(int32_t)value); + return false; + } + } + if (key == "SetS64BE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + BitConverter::FromSint64BE(bArray->data[(size_t)index], + value); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "SetS16LE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 2 <= bArray->data.size()) { + BitConverter::FromSint16LE(bArray->data[(size_t)index], + (int16_t)value); + cse.back()->Push(gc, (int64_t)(int16_t)value); + return false; + } + } + if (key == "SetS32LE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + BitConverter::FromSint32LE(bArray->data[(size_t)index], + (int32_t)value); + cse.back()->Push(gc, (int64_t)(int32_t)value); + return false; + } + } + if (key == "SetS64LE") { + int64_t index; + int64_t value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + BitConverter::FromSint64LE(bArray->data[(size_t)index], + value); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "SetF32LE") { + int64_t index; + double value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + BitConverter::FromFloatLE(bArray->data[(size_t)index], + (float)value); + cse.back()->Push(gc, (double)(float)value); + return false; + } + } + if (key == "SetF64LE") { + int64_t index; + double value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + BitConverter::FromDoubleLE(bArray->data[(size_t)index], + value); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "SetF32BE") { + int64_t index; + double value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + BitConverter::FromFloatBE(bArray->data[(size_t)index], + (float)value); + cse.back()->Push(gc, (double)(float)value); + return false; + } + } + if (key == "SetF64BE") { + int64_t index; + double value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + BitConverter::FromDoubleBE(bArray->data[(size_t)index], + value); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "SetUuid") { + int64_t index; + Tesses::Framework::Uuid value; + if (GetArgument(args, 0, index) && + GetArgument(args, 1, value) && + (size_t)index < bArray->data.size() && + (size_t)index + 16 <= bArray->data.size()) { + BitConverter::FromUuid(bArray->data[(size_t)index], + value); + cse.back()->Push(gc, value); + return false; + } + } + + if (key == "GetU16BE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 2 <= bArray->data.size()) { + int64_t value = (int64_t)BitConverter::ToUint16BE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetU32BE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + int64_t value = (int64_t)BitConverter::ToUint32BE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetU64BE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + uint64_t value = BitConverter::ToUint64BE( + bArray->data[(size_t)index]); + int64_t value2 = 0; + memcpy(&value2, &value, sizeof(uint64_t)); + cse.back()->Push(gc, value2); + return false; + } + } + if (key == "GetU16LE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 2 <= bArray->data.size()) { + int64_t value = (int64_t)BitConverter::ToUint16LE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetU32LE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + int64_t value = (int64_t)BitConverter::ToUint32LE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetU64LE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + uint64_t value = BitConverter::ToUint64LE( + bArray->data[(size_t)index]); + int64_t value2 = 0; + memcpy(&value2, &value, sizeof(uint64_t)); + cse.back()->Push(gc, value2); + return false; + } + } + + if (key == "GetS16BE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 2 <= bArray->data.size()) { + int64_t value = (int64_t)BitConverter::ToSint16BE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetS32BE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + int64_t value = (int64_t)BitConverter::ToSint32BE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetS64BE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + int64_t value = BitConverter::ToSint64BE( + bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetS16LE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 2 <= bArray->data.size()) { + int64_t value = (int64_t)BitConverter::ToSint16LE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetS32LE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + int64_t value = (int64_t)BitConverter::ToSint32LE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetS64LE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + int64_t value = BitConverter::ToSint64LE( + bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + + if (key == "GetF32LE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + double value = (double)BitConverter::ToFloatLE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetF64LE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + uint64_t value = BitConverter::ToDoubleLE( + bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetF32BE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 4 <= bArray->data.size()) { + double value = (double)BitConverter::ToFloatBE( + bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if (key == "GetF64BE") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 8 <= bArray->data.size()) { + uint64_t value = BitConverter::ToDoubleBE( + bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + + if (key == "GetUuid") { + int64_t index; + if (GetArgument(args, 0, index) && + (size_t)index < bArray->data.size() && + (size_t)index + 16 <= bArray->data.size()) { + auto value = + BitConverter::ToUuid(bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (aArray != nullptr) { + if (key == "ToString") { + cse.back()->Push(gc, ToString(gc, aArray)); + return false; + } else if (key == "GetAt") { + if (args.size() != 1) { + throw VMException( + "AArray.GetAt must only accept one argument"); + } + cse.back()->Push(gc, aArray->Get(gc, args[0])); + return false; + } else if (key == "SetAt") { + if (args.size() != 2) { + throw VMException( + "AArray.SetAt must only accept two arguments"); + } + aArray->Set(gc, args[0], args[1]); + cse.back()->Push(gc, args[1]); + return false; + } else if (key == "GetKey") { + if (args.size() != 1) { + throw VMException( + "AArray.GetKey must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException( + "AArray.GetKey must only accept a long"); + } + + gc->BarrierBegin(); + auto res = aArray->GetKey(std::get(args[0])); + gc->BarrierEnd(); + cse.back()->Push(gc, res); + return false; + } else if (key == "GetValue") { + if (args.size() != 1) { + throw VMException( + "AArray.GetValue must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException( + "AArray.GetValue must only accept a long"); + } + + gc->BarrierBegin(); + auto res = aArray->GetValue(std::get(args[0])); + gc->BarrierEnd(); + cse.back()->Push(gc, res); + return false; + } else if (key == "SetKey") { + if (args.size() != 2) { + throw VMException( + "AArray.SetKey must only accept two arguments"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("AArray.SetKey first argument must " + "only accept a long"); + } + + gc->BarrierBegin(); + aArray->SetKey(std::get(args[0]), args[1]); + gc->BarrierEnd(); + cse.back()->Push(gc, args[1]); + return false; + } else if (key == "SetValue") { + if (args.size() != 2) { + throw VMException( + "AArray.SetValue must only accept two arguments"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("AArray.SetValue first argument must " + "only accept a long"); + } + + gc->BarrierBegin(); + aArray->SetValue(std::get(args[0]), args[1]); + gc->BarrierEnd(); + cse.back()->Push(gc, args[1]); + return false; + } else if (key == "Count" || key == "Length") { + gc->BarrierBegin(); + cse.back()->Push(gc, aArray->Count()); + gc->BarrierEnd(); + return false; + } else if (key == "GetEnumerator") { + + cse.back()->Push( + gc, TAssociativeArrayEnumerator::Create(ls, aArray)); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (list != nullptr) { + + if (key == "GetEnumerator") { + cse.back()->Push(gc, TListEnumerator::Create(ls, list)); + return false; + } else if (key == "ToString") { + + cse.back()->Push(gc, Json_Encode(list)); + return false; + + } else if (key == "Insert") { + if (args.size() != 2) { + throw VMException( + "List.Insert must only accept two arguments"); + } + int64_t index; + + if (!GetArgument(args, 0, index)) { + throw VMException( + "List.Insert first argument must be Long"); + } + + gc->BarrierBegin(); + list->Insert(index, args[1]); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (key == "Add") { + if (args.size() != 1) { + throw VMException( + "List.Add must only accept one argument"); + } + gc->BarrierBegin(); + list->Add(args[0]); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (key == "Contains") { + if (args.size() != 1) { + throw VMException( + "List.Contains must only accept one argument"); + } + gc->BarrierBegin(); + for (int64_t i = 0; i < list->Count(); i++) { + auto item = list->Get(i); + gc->BarrierEnd(); + if (Equals(gc, args[0], item)) { + cse.back()->Push(gc, true); + return false; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, false); + return false; + } else if (key == "IndexOf") { + // IndexOf(obj, $idx) + if (args.size() < 1 || args.size() > 2) { + throw VMException("List.IndexOf must either have one " + "or two arguments"); + } + + int64_t i = 0; + + GetArgument(args, 1, i); + gc->BarrierBegin(); + for (; i < list->Count(); i++) { + auto item = list->Get(i); + gc->BarrierEnd(); + if (Equals(gc, args[0], item)) { + + cse.back()->Push(gc, i); + return false; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, (int64_t)-1); + return false; + } else if (key == "RemoveAllEqual") { + if (args.size() != 1) { + throw VMException("List.RemoveAllEqual must only " + "accept one argument"); + } + + gc->BarrierBegin(); + for (int64_t i = 0; i < list->Count(); i++) { + auto item = list->Get(i); + gc->BarrierEnd(); + if (Equals(gc, args[0], item)) { + gc->BarrierBegin(); + list->RemoveAt(i); + i--; + } else + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (key == "Remove") { + if (args.size() != 1) { + throw VMException( + "List.Remove must only accept one argument"); + } + + gc->BarrierBegin(); + for (int64_t i = 0; i < list->Count(); i++) { + auto item = list->Get(i); + gc->BarrierEnd(); + if (Equals(gc, args[0], item)) { + gc->BarrierBegin(); + list->RemoveAt(i); + gc->BarrierEnd(); + break; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (key == "RemoveAt") { + if (args.size() != 1) { + throw VMException( + "List.RemoveAt must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException( + "List.RemoveAt must only accept a long"); + } + gc->BarrierBegin(); + list->RemoveAt(std::get(args[0])); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (key == "Clear") { + gc->BarrierBegin(); + list->Clear(); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (key == "GetAt") { + if (args.size() != 1) { + throw VMException( + "List.GetAt must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("List.GetAt must only accept a long"); + } + + int64_t index = std::get(args[0]); + if (index >= 0 && index < list->Count()) { + cse.back()->Push(gc, list->Get(index)); + return false; + } + + } else if (key == "SetAt") { + if (args.size() != 2) { + throw VMException( + "List.SetAt must only accept two arguments"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("List.SetAt first argument must only " + "accept a long"); + } + + int64_t index = std::get(args[0]); + if (index >= 0 && index < list->Count()) { + list->Set(index, args[1]); + return false; + } + + } + + else if (key == "Count" || key == "Length") { + gc->BarrierBegin(); + cse.back()->Push(gc, list->Count()); + gc->BarrierEnd(); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (dynList != nullptr) { + + if (key == "GetEnumerator") { + cse.back()->Push( + gc, TDynamicListEnumerator::Create(ls, dynList)); + return false; + } else if (key == "ToString") { + cse.back()->Push(gc, dynList->ToString(ls)); + return false; + } else if (key == "Insert") { + if (args.size() != 2) { + throw VMException( + "List.Insert must only accept two arguments"); + } + int64_t index; + + if (!GetArgument(args, 0, index)) { + throw VMException( + "List.Insert first argument must be Long"); + } + + cse.back()->Push(gc, dynList->Insert(ls, index, args[0])); + return false; + } + if (key == "Add") { + if (args.size() != 1) { + throw VMException( + "List.Add must only accept one argument"); + } + + cse.back()->Push(gc, dynList->Add(ls, args[0])); + return false; + } + if (key == "RemoveAllEqual") { + if (args.size() != 1) { + throw VMException("List.RemoveAllEqual must only " + "accept one argument"); + } + + cse.back()->Push(gc, dynList->RemoveAllEqual(ls, args[0])); + return false; + } + if (key == "Remove") { + if (args.size() != 1) { + throw VMException( + "List.Remove must only accept one argument"); + } + + cse.back()->Push(gc, dynList->Remove(ls, args[0])); + return false; + } + if (key == "RemoveAt") { + if (args.size() != 1) { + throw VMException( + "List.RemoveAt must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException( + "List.RemoveAt must only accept a long"); + } + cse.back()->Push( + gc, dynList->RemoveAt(ls, std::get(args[0]))); + + return false; + } + if (key == "Clear") { + + cse.back()->Push(gc, dynList->Clear(ls)); + return false; + } + if (key == "GetAt") { + if (args.size() != 1) { + throw VMException( + "List.GetAt must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("List.GetAt must only accept a long"); + } + + int64_t index = std::get(args[0]); + if (index >= 0) { + cse.back()->Push(gc, dynList->GetAt(ls, index)); + return false; + } + } + if (key == "SetAt") { + if (args.size() != 2) { + throw VMException( + "List.SetAt must only accept two arguments"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("List.SetAt first argument must only " + "accept a long"); + } + + int64_t index = std::get(args[0]); + if (index >= 0) { + cse.back()->Push(gc, + dynList->SetAt(ls, index, args[1])); + return false; + } + } + + if (key == "Count" || key == "Length") { + cse.back()->Push(gc, dynList->Count(ls)); + + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = cls->GetValue(cse.back()->callable->className, key); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, args); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, args)); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (dict != nullptr) { + if (key == "ToString" && !dict->MethodExists(ls, key) && + args.empty()) { + cse.back()->Push(gc, Json_Encode(dict)); + return false; + } + gc->BarrierBegin(); + auto o = dict->GetValue(key); + gc->BarrierEnd(); + + return InvokeMethod(ls, o, dict, args); + } else if (dynDict != nullptr) { + + cse.back()->Push(gc, dynDict->CallMethod(ls, key, args)); + + return false; + } else if (callable != nullptr) { + if (key == "Call") { + TList *argls; + if (GetArgumentHeap(args, 0, argls)) { + TClosure *clo = dynamic_cast(callable); + if (clo != nullptr) { + AddCallStackEntry(ls, clo, argls->items); + return true; + } else { + cse.back()->Push(gc, + callable->Call(ls, argls->items)); + return false; + } + } + } + cse.back()->Push(gc, nullptr); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + } else { + cse.back()->Push(gc, Undefined()); } - - - return false; } -} \ No newline at end of file + + return false; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/getfield.cpp b/src/vm/bc/getfield.cpp index 02e8cdd..fe4a1ff 100644 --- a/src/vm/bc/getfield.cpp +++ b/src/vm/bc/getfield.cpp @@ -2,810 +2,690 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - bool InterperterThread::GetField(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; +bool InterperterThread::GetField(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - GCList ls(gc); - TObject _key = stk->Pop(ls); - - - TObject instance = stk->Pop(ls); - - if(!std::holds_alternative(_key)) - { - stk->Push(gc,Undefined()); + if (!cse.empty()) { + auto stk = cse.back(); + GCList ls(gc); + TObject _key = stk->Pop(ls); + + TObject instance = stk->Pop(ls); + + if (!std::holds_alternative(_key)) { + stk->Push(gc, Undefined()); + return false; + } + + std::string key = std::get(_key); + + if (std::holds_alternative(instance)) { + std::string str = std::get(instance); + + if (key == "Count" || key == "Length") { + int64_t len = (int64_t)str.size(); + if (len < 0) + len = 0; + + cse.back()->Push(gc, len); return false; } - - std::string key = std::get(_key); - - - if(std::holds_alternative(instance)) - { - std::string str = std::get(instance); - - if(key == "Count" || key == "Length") - { - int64_t len = (int64_t)str.size(); - if(len < 0) len = 0; - - cse.back()->Push(gc, len); + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto timer = + std::get>( + instance); + if (timer) { + if (key == "Interval") { + cse.back()->Push(gc, timer->GetIntervalMilliseconds()); return false; } + if (key == "Enabled") { + cse.back()->Push(gc, timer->GetEnabled()); + return false; + } + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto vfs = + std::get>( + instance); + auto tmpFS = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::TempFS>(vfs); + auto relative = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::RelativeFilesystem>(vfs); + auto myFS = std::dynamic_pointer_cast(vfs); + if (relative) { + if (key == "Working") { + cse.back()->Push(gc, relative->GetWorking()); + return false; + } + if (key == "Filesystem") { + cse.back()->Push(gc, relative->GetVFS()); + return false; + } + } + if (myFS) { + if (key == "Inner") { + cse.back()->Push(gc, myFS->obj); + return false; + } + } + if (tmpFS) { + if (key == "TempDirectoryName") { + + cse.back()->Push(gc, tmpFS->TempDirectoryName()); + return false; + } + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto writer = std::get< + std::shared_ptr>( + instance); + auto stringWriter = std::dynamic_pointer_cast< + Tesses::Framework::TextStreams::StringWriter>(writer); + if (stringWriter != nullptr) { + if (key == "Text") { + cse.back()->Push(gc, stringWriter->GetString()); + return false; + } + } + if (key == "NewLine") { + cse.back()->Push(gc, writer->newline); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto br = std::get< + std::shared_ptr>( + instance); + if (key == "Stream") { + cse.back()->Push(gc, br->GetStream()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto bw = std::get< + std::shared_ptr>( + instance); + if (key == "Stream") { + + cse.back()->Push(gc, bw->GetStream()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto strm = + std::get>( + instance); + if (strm != nullptr) { + auto netStrm = std::dynamic_pointer_cast< + Tesses::Framework::Streams::NetworkStream>(strm); + + if (key == "CanRead") { + + cse.back()->Push(gc, strm->CanRead()); + return false; + } + if (key == "CanWrite") { + + cse.back()->Push(gc, strm->CanWrite()); + return false; + } + if (key == "CanSeek") { + + cse.back()->Push(gc, strm->CanSeek()); + return false; + } + if (key == "EndOfStream") { + + cse.back()->Push(gc, strm->EndOfStream()); + return false; + } + if (key == "Length") { + + cse.back()->Push(gc, strm->GetLength()); + return false; + } + if (key == "Position") { + + cse.back()->Push(gc, strm->GetPosition()); + return false; + } + + if (netStrm != nullptr) { + if (key == "Port") { + cse.back()->Push(gc, netStrm->GetPort()); + return false; + } + } + cse.back()->Push(gc, Undefined()); + return false; } - if(std::holds_alternative>(instance)) - { - auto timer = std::get>(instance); - if(timer) - { - if(key == "Interval") - { - cse.back()->Push(gc, timer->GetIntervalMilliseconds()); - return false; - } - if(key == "Enabled") - { - cse.back()->Push(gc, timer->GetEnabled()); - return false; - } - } - cse.back()->Push(gc, Undefined()); + } + if (std::holds_alternative(instance)) { + TVMVersion &version = std::get(instance); + if (key == "Major") { + stk->Push(gc, (int64_t)version.Major()); return false; } - if(std::holds_alternative>(instance)) - { - auto vfs = std::get>(instance); - auto tmpFS=std::dynamic_pointer_cast(vfs); - auto relative = std::dynamic_pointer_cast(vfs); - auto myFS = std::dynamic_pointer_cast(vfs); - if(relative) - { - if(key == "Working") - { - cse.back()->Push(gc, relative->GetWorking()); - return false; - } - if(key == "Filesystem") - { - cse.back()->Push(gc, relative->GetVFS()); - return false; - } - } - if(myFS) - { - if(key == "Inner") - { - cse.back()->Push(gc, myFS->obj); - return false; - } - } - if(tmpFS) - { - if(key == "TempDirectoryName") - { - - cse.back()->Push(gc,tmpFS->TempDirectoryName()); - return false; - } - } - cse.back()->Push(gc,Undefined()); + if (key == "Minor") { + stk->Push(gc, (int64_t)version.Minor()); return false; } - if(std::holds_alternative>(instance)) - { - auto writer = std::get>(instance); - auto stringWriter = std::dynamic_pointer_cast(writer); - if(stringWriter != nullptr) - { - if(key == "Text") - { - cse.back()->Push(gc, stringWriter->GetString()); - return false; - } - } - if(key == "NewLine") - { - cse.back()->Push(gc,writer->newline); - return false; - } - cse.back()->Push(gc,Undefined()); + if (key == "Patch") { + stk->Push(gc, (int64_t)version.Patch()); return false; } - if(std::holds_alternative>(instance)) - { - auto br = std::get>(instance); - if(key == "Stream") - { - cse.back()->Push(gc,br->GetStream()); - return false; - } - cse.back()->Push(gc,Undefined()); + if (key == "Build") { + stk->Push(gc, (int64_t)version.Build()); return false; } - if(std::holds_alternative>(instance)) - { - auto bw = std::get>(instance); - if(key == "Stream") - { - - cse.back()->Push(gc,bw->GetStream()); - return false; - } - cse.back()->Push(gc,Undefined()); + if (key == "VersionInt") { + stk->Push(gc, (int64_t)version.AsLong()); return false; } - if(std::holds_alternative>(instance)) - { - auto strm = std::get>(instance); - if(strm != nullptr) - { - auto netStrm = std::dynamic_pointer_cast(strm); - - if(key == "CanRead") - { - - - cse.back()->Push(gc, strm->CanRead()); - return false; - } - if(key == "CanWrite") - { - - cse.back()->Push(gc, strm->CanWrite()); - return false; - } - if(key == "CanSeek") - { - - - cse.back()->Push(gc, strm->CanSeek()); - return false; - } - if(key == "EndOfStream") - { - - cse.back()->Push(gc, strm->EndOfStream()); - return false; - } - if(key == "Length") - { - - cse.back()->Push(gc, strm->GetLength()); - return false; - } - if(key == "Position") - { - - cse.back()->Push(gc, strm->GetPosition()); - return false; - } - - if(netStrm != nullptr) - { - if(key == "Port") - { - cse.back()->Push(gc, netStrm->GetPort()); - return false; - } - } - - cse.back()->Push(gc, Undefined()); - - return false; - + if (key == "Stage") { + switch (version.VersionStage()) { + case TVMVersionStage::DevVersion: + stk->Push(gc, "dev"); + break; + case TVMVersionStage::AlphaVersion: + stk->Push(gc, "alpha"); + break; + case TVMVersionStage::BetaVersion: + stk->Push(gc, "beta"); + break; + case TVMVersionStage::ProductionVersion: + stk->Push(gc, "prod"); + break; } - } - if(std::holds_alternative(instance)) - { - TVMVersion& version = std::get(instance); - if(key == "Major") - { - stk->Push(gc, (int64_t)version.Major()); - return false; - } - if(key == "Minor") - { - stk->Push(gc, (int64_t)version.Minor()); - return false; - } - if(key == "Patch") - { - stk->Push(gc, (int64_t)version.Patch()); - return false; - } - if(key == "Build") - { - stk->Push(gc, (int64_t)version.Build()); - return false; - } - if(key == "VersionInt") - { - stk->Push(gc,(int64_t)version.AsLong()); - return false; - } - if(key == "Stage") - { - switch(version.VersionStage()) - { - case TVMVersionStage::DevVersion: - stk->Push(gc,"dev"); - break; - case TVMVersionStage::AlphaVersion: - stk->Push(gc,"alpha"); - break; - case TVMVersionStage::BetaVersion: - stk->Push(gc,"beta"); - break; - case TVMVersionStage::ProductionVersion: - stk->Push(gc,"prod"); - break; - } - return false; - } - - stk->Push(gc, Undefined()); return false; } - if(std::holds_alternative>(instance)) - { - auto time = std::get>(instance); - if(key == "Days") - { - stk->Push(gc, (int64_t)time->Days()); - return false; - } - if(key == "Hours") - { - stk->Push(gc, (int64_t)time->Hours()); - return false; - } - - if(key == "Minutes") - { - stk->Push(gc, (int64_t)time->Minutes()); - return false; - } - if(key == "Seconds") - { - stk->Push(gc, (int64_t)time->Seconds()); - return false; - } - - if(key == "TotalHours") - { - stk->Push(gc, time->TotalHours()); - return false; - } - - if(key == "TotalMinutes") - { - stk->Push(gc, time->TotalMinutes()); - return false; - } - - if(key == "TotalSeconds") - { - stk->Push(gc, time->TotalSeconds()); - return false; - } - - stk->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto& date = std::get>(instance); - if(key == "IsLocal") - { - stk->Push(gc, date->IsLocal()); - return false; - } - if(key == "Year") - { - stk->Push(gc, (int64_t)date->Year()); - return false; - } - if(key == "Month") - { - stk->Push(gc, (int64_t)date->Month()); - return false; - } - if(key == "Day") - { - stk->Push(gc, (int64_t)date->Day()); - return false; - } - if(key == "Hour") - { - stk->Push(gc, (int64_t)date->Hour()); - return false; - } - if(key == "Minute") - { - stk->Push(gc, (int64_t)date->Minute()); - return false; - } - if(key == "Second") - { - stk->Push(gc, (int64_t)date->Second()); - return false; - } - if(key == "DayOfWeek") - { - stk->Push(gc, (int64_t)date->DayOfWeek()); - return false; - } - - stk->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative(instance)) - { - auto obj = std::get(instance).obj; - auto bA = dynamic_cast(obj); - auto list = dynamic_cast(obj); - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto dynList = dynamic_cast(obj); - auto tcallable = dynamic_cast(obj); - auto closure = dynamic_cast(obj); - auto externalMethod = dynamic_cast(obj); - auto ittr = dynamic_cast(obj); - - auto callstackEntry = dynamic_cast(obj); - auto file = dynamic_cast(obj); - auto chunk = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - auto aarray = dynamic_cast(obj); - auto task = dynamic_cast(obj); - if(task != nullptr) - { - if(key == "IsCompleted") - { - cse.back()->Push(gc,task->IsCompleted()); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - if(aarray != nullptr) - { - if(key == "Count" || key == "Length") - { - cse.back()->Push(gc,aarray->Count()); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"get"+key); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{})); - return false; - } - cse.back()->Push(gc,cls->GetValue(cse.back()->callable->className,key)); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc,natObj->CallMethod(ls,"get"+key,{})); - return false; - } - - if(file != nullptr) - { - if(key == "Version") - { - cse.back()->Push(gc,file->version); - return false; - } - else if(key == "Name") - { - cse.back()->Push(gc,file->name); - return false; - } - else if(key == "Info") - { - cse.back()->Push(gc, file->info); - return false; - } - else if(key == "Dependencies") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : file->dependencies) - { - auto res = TDictionary::Create(ls); - res->SetValue("Name", item.first); - res->SetValue("Version", item.second); - list->Add(res); - } - gc->BarrierEnd(); - cse.back()->Push(gc, list); - return false; - } - else if(key == "Tools") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : file->tools) - { - auto res = TDictionary::Create(ls); - res->SetValue("Name", item.first); - res->SetValue("Version", item.second); - list->Add(res); - } - gc->BarrierEnd(); - cse.back()->Push(gc, list); - return false; - } - else if(key == "Strings") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : file->name) - { - list->Add(item); - } - gc->BarrierEnd(); - - cse.back()->Push(gc, list); - return false; - } - else if(key == "MetadataCount") - { - - cse.back()->Push(gc, (int64_t)file->metadata.size()); - return false; - } - else if(key == "Metadata") - { - TList* meta = TList::Create(ls); - gc->BarrierBegin(); - for(size_t i = 0; i < file->metadata.size(); i++) - { - meta->Add( - TDictionary::Create(ls, - { - TDItem("Name", file->metadata[i].first), - TDItem("Index",(int64_t)i) - } - ) - ); - } - gc->BarrierEnd(); - - cse.back()->Push(gc, meta); - return false; - } - else if(key == "Sections") - { - TList* sections = TList::Create(ls); - gc->BarrierBegin(); - for(auto& item : file->sections) - { - TByteArray* ba = TByteArray::Create(ls); - ba->data = item.second; - sections->Add(TDictionary::Create(ls,{ - TDItem("Name", item.first), - TDItem("Data", ba) - })); - } - gc->BarrierEnd(); - - cse.back()->Push(gc, sections); - return false; - } - else if(key == "SupportedVMs") - { - TList* supported = TList::Create(ls); - gc->BarrierBegin(); - if(file->vms.empty()) - { - supported->Add(TDictionary::Create(ls,{ - TDItem("Name",std::string(VMName)), - TDItem("HowToGet",std::string(VMHowToGet)) - })); - } - else { - for(auto item : file->vms) - supported->Add(TDictionary::Create(ls,{ - TDItem("Name",item.first), - TDItem("HowToGet",item.second) - })); - } - gc->BarrierEnd(); - cse.back()->Push(gc, supported); - return false; - } - else if(key == "Chunks") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : file->chunks) - { - list->Add(item); - } - - gc->BarrierEnd(); - - cse.back()->Push(gc, list); - return false; - } - else if(key == "Classes") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - - for(uint32_t i = 0; i < (uint32_t)file->classes.size(); i++) - { - list->Add(GetClassInfo(ls,file,i)); - } - - cse.back()->Push(gc, list); - gc->BarrierEnd(); - return false; - } - else if(key == "Functions") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto& item : file->functions) - { - TDictionary* dict = TDictionary::Create(ls); - if(!item.first.empty()) - dict->SetValue("Documentation", item.first[0]); - TList* nameParts = TList::Create(ls); - for(size_t i = 1; i < item.first.size(); i++) - { - nameParts->Add(item.first[i]); - } - dict->SetValue("NameParts", nameParts); - dict->SetValue("ChunkId", (int64_t)item.second); - - list->Add(dict); - } - - cse.back()->Push(gc, list); - gc->BarrierEnd(); - return false; - } - else if(key == "Icon") - { - if(file->icon >= 0 && file->icon < file->resources.size()) - { - TByteArray* ba = TByteArray::Create(ls); - ba->data = file->resources[file->icon]; - cse.back()->Push(gc, ba); - return false; - } - else { - cse.back()->Push(gc, nullptr); - return false; - } - } - cse.back()->Push(gc, Undefined()); - return false; - } - if(chunk != nullptr) - { - if(key == "Arguments") - { - auto myargs = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : chunk->args) - { - myargs->Add(item); - } - gc->BarrierEnd(); - cse.back()->Push(gc, myargs); - return false; - } - if(key == "Code") - { - auto ba = TByteArray::Create(ls); - ba->data = chunk->code; - cse.back()->Push(gc, ba); - return false; - } - if(key == "File") - { - cse.back()->Push(gc, chunk->file); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - if(callstackEntry != nullptr) - { - if(key == "IP") - { - cse.back()->Push(gc, (int64_t)callstackEntry->ip); - return false; - } - if(key == "IsDone") - { - cse.back()->Push(gc, callstackEntry->ip >= callstackEntry->callable->closure->code.size()); - return false; - } - if(key == "Closure") - { - cse.back()->Push(gc, callstackEntry->callable); - return false; - } - if(key == "StackEmpty") - { - cse.back()->Push(gc, callstackEntry->stack.empty()); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - - - - - if(ittr != nullptr) - { - if(key == "Current") - { - cse.back()->Push(gc, ittr->GetCurrent(ls)); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - if(closure != nullptr) - { - if(key == "Arguments") - { - GCList ls2(gc); - TList* ls = TList::Create(ls2); - for(auto arg : closure->closure->args) - { - ls->Add(arg); - } - cse.back()->Push(gc,ls); - return false; - } - if(key == "File") - { - cse.back()->Push(gc,closure->file); - return false; - } - } - if(externalMethod != nullptr) - { - if(key == "Arguments") - { - GCList ls2(gc); - TList* ls = TList::Create(ls2); - for(auto arg : externalMethod->args) - { - ls->Add(arg); - } - cse.back()->Push(gc,ls); - return false; - } - } - - if(tcallable != nullptr) - { - if(key == "Documentation") - { - cse.back()->Push(gc, tcallable->documentation); - return false; - } - if(key == "Tag") - { - gc->BarrierBegin(); - cse.back()->Push(gc, tcallable->tag); - gc->BarrierEnd(); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - - if(bA != nullptr) - { - if(key == "Count" || key == "Length") - { - int64_t len = (int64_t)bA->data.size(); - if(len < 0) len = 0; - - stk->Push(gc, len); - return false; - } - } - if(list != nullptr) - { - if(key == "Count" || key == "Length") - { - int64_t len = list->Count(); - if(len < 0) len = 0; - - stk->Push(gc, len); - return false; - } - } - if(dynList != nullptr) - { - if(key == "Count" || key == "Length") - { - int64_t len = dynList->Count(ls); - if(len < 0) len = 0; - - stk->Push(gc, len); - return false; - } - } - if(dynDict != nullptr) - { - if(dynDict->MethodExists(ls,"get" + key)) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"get" + key, {})); - } - else - { - cse.back()->Push(gc, dynDict->GetField(ls,key)); - } - return false; - } - - if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("get" + key); - gc->BarrierEnd(); - if(std::holds_alternative(fn) && dynamic_cast(std::get(fn).obj) != nullptr) - { - return InvokeOne(ls,fn, dict); - } - else - { - gc->BarrierBegin(); - fn = dict->GetValue(key); - stk->Push(gc, fn); - gc->BarrierEnd(); - return false; - } - } - - } stk->Push(gc, Undefined()); + return false; } - - return false; + if (std::holds_alternative< + std::shared_ptr>(instance)) { + auto time = + std::get>( + instance); + if (key == "Days") { + stk->Push(gc, (int64_t)time->Days()); + return false; + } + if (key == "Hours") { + stk->Push(gc, (int64_t)time->Hours()); + return false; + } + + if (key == "Minutes") { + stk->Push(gc, (int64_t)time->Minutes()); + return false; + } + if (key == "Seconds") { + stk->Push(gc, (int64_t)time->Seconds()); + return false; + } + + if (key == "TotalHours") { + stk->Push(gc, time->TotalHours()); + return false; + } + + if (key == "TotalMinutes") { + stk->Push(gc, time->TotalMinutes()); + return false; + } + + if (key == "TotalSeconds") { + stk->Push(gc, time->TotalSeconds()); + return false; + } + + stk->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>(instance)) { + auto &date = + std::get>( + instance); + if (key == "IsLocal") { + stk->Push(gc, date->IsLocal()); + return false; + } + if (key == "Year") { + stk->Push(gc, (int64_t)date->Year()); + return false; + } + if (key == "Month") { + stk->Push(gc, (int64_t)date->Month()); + return false; + } + if (key == "Day") { + stk->Push(gc, (int64_t)date->Day()); + return false; + } + if (key == "Hour") { + stk->Push(gc, (int64_t)date->Hour()); + return false; + } + if (key == "Minute") { + stk->Push(gc, (int64_t)date->Minute()); + return false; + } + if (key == "Second") { + stk->Push(gc, (int64_t)date->Second()); + return false; + } + if (key == "DayOfWeek") { + stk->Push(gc, (int64_t)date->DayOfWeek()); + return false; + } + + stk->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative(instance)) { + auto obj = std::get(instance).obj; + auto bA = dynamic_cast(obj); + auto list = dynamic_cast(obj); + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto dynList = dynamic_cast(obj); + auto tcallable = dynamic_cast(obj); + auto closure = dynamic_cast(obj); + auto externalMethod = dynamic_cast(obj); + auto ittr = dynamic_cast(obj); + + auto callstackEntry = dynamic_cast(obj); + auto file = dynamic_cast(obj); + auto chunk = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + auto aarray = dynamic_cast(obj); + auto task = dynamic_cast(obj); + if (task != nullptr) { + if (key == "IsCompleted") { + cse.back()->Push(gc, task->IsCompleted()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (aarray != nullptr) { + if (key == "Count" || key == "Length") { + cse.back()->Push(gc, aarray->Count()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } else if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "get" + key); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {})); + return false; + } + cse.back()->Push( + gc, cls->GetValue(cse.back()->callable->className, key)); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "get" + key, {})); + return false; + } + + if (file != nullptr) { + if (key == "Version") { + cse.back()->Push(gc, file->version); + return false; + } else if (key == "Name") { + cse.back()->Push(gc, file->name); + return false; + } else if (key == "Info") { + cse.back()->Push(gc, file->info); + return false; + } else if (key == "Dependencies") { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for (auto item : file->dependencies) { + auto res = TDictionary::Create(ls); + res->SetValue("Name", item.first); + res->SetValue("Version", item.second); + list->Add(res); + } + gc->BarrierEnd(); + cse.back()->Push(gc, list); + return false; + } else if (key == "Tools") { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for (auto item : file->tools) { + auto res = TDictionary::Create(ls); + res->SetValue("Name", item.first); + res->SetValue("Version", item.second); + list->Add(res); + } + gc->BarrierEnd(); + cse.back()->Push(gc, list); + return false; + } else if (key == "Strings") { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for (auto item : file->name) { + list->Add(item); + } + gc->BarrierEnd(); + + cse.back()->Push(gc, list); + return false; + } else if (key == "MetadataCount") { + + cse.back()->Push(gc, (int64_t)file->metadata.size()); + return false; + } else if (key == "Metadata") { + TList *meta = TList::Create(ls); + gc->BarrierBegin(); + for (size_t i = 0; i < file->metadata.size(); i++) { + meta->Add(TDictionary::Create( + ls, {TDItem("Name", file->metadata[i].first), + TDItem("Index", (int64_t)i)})); + } + gc->BarrierEnd(); + + cse.back()->Push(gc, meta); + return false; + } else if (key == "Sections") { + TList *sections = TList::Create(ls); + gc->BarrierBegin(); + for (auto &item : file->sections) { + TByteArray *ba = TByteArray::Create(ls); + ba->data = item.second; + sections->Add( + TDictionary::Create(ls, {TDItem("Name", item.first), + TDItem("Data", ba)})); + } + gc->BarrierEnd(); + + cse.back()->Push(gc, sections); + return false; + } else if (key == "SupportedVMs") { + TList *supported = TList::Create(ls); + gc->BarrierBegin(); + if (file->vms.empty()) { + supported->Add(TDictionary::Create( + ls, {TDItem("Name", std::string(VMName)), + TDItem("HowToGet", std::string(VMHowToGet))})); + } else { + for (auto item : file->vms) + supported->Add(TDictionary::Create( + ls, {TDItem("Name", item.first), + TDItem("HowToGet", item.second)})); + } + gc->BarrierEnd(); + cse.back()->Push(gc, supported); + return false; + } else if (key == "Chunks") { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for (auto item : file->chunks) { + list->Add(item); + } + + gc->BarrierEnd(); + + cse.back()->Push(gc, list); + return false; + } else if (key == "Classes") { + auto list = TList::Create(ls); + gc->BarrierBegin(); + + for (uint32_t i = 0; i < (uint32_t)file->classes.size(); + i++) { + list->Add(GetClassInfo(ls, file, i)); + } + + cse.back()->Push(gc, list); + gc->BarrierEnd(); + return false; + } else if (key == "Functions") { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for (auto &item : file->functions) { + TDictionary *dict = TDictionary::Create(ls); + if (!item.first.empty()) + dict->SetValue("Documentation", item.first[0]); + TList *nameParts = TList::Create(ls); + for (size_t i = 1; i < item.first.size(); i++) { + nameParts->Add(item.first[i]); + } + dict->SetValue("NameParts", nameParts); + dict->SetValue("ChunkId", (int64_t)item.second); + + list->Add(dict); + } + + cse.back()->Push(gc, list); + gc->BarrierEnd(); + return false; + } else if (key == "Icon") { + if (file->icon >= 0 && + file->icon < file->resources.size()) { + TByteArray *ba = TByteArray::Create(ls); + ba->data = file->resources[file->icon]; + cse.back()->Push(gc, ba); + return false; + } else { + cse.back()->Push(gc, nullptr); + return false; + } + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (chunk != nullptr) { + if (key == "Arguments") { + auto myargs = TList::Create(ls); + gc->BarrierBegin(); + for (auto item : chunk->args) { + myargs->Add(item); + } + gc->BarrierEnd(); + cse.back()->Push(gc, myargs); + return false; + } + if (key == "Code") { + auto ba = TByteArray::Create(ls); + ba->data = chunk->code; + cse.back()->Push(gc, ba); + return false; + } + if (key == "File") { + cse.back()->Push(gc, chunk->file); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (callstackEntry != nullptr) { + if (key == "IP") { + cse.back()->Push(gc, (int64_t)callstackEntry->ip); + return false; + } + if (key == "IsDone") { + cse.back()->Push( + gc, callstackEntry->ip >= + callstackEntry->callable->closure->code.size()); + return false; + } + if (key == "Closure") { + cse.back()->Push(gc, callstackEntry->callable); + return false; + } + if (key == "StackEmpty") { + cse.back()->Push(gc, callstackEntry->stack.empty()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + + if (ittr != nullptr) { + if (key == "Current") { + cse.back()->Push(gc, ittr->GetCurrent(ls)); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (closure != nullptr) { + if (key == "Arguments") { + GCList ls2(gc); + TList *ls = TList::Create(ls2); + for (auto arg : closure->closure->args) { + ls->Add(arg); + } + cse.back()->Push(gc, ls); + return false; + } + if (key == "File") { + cse.back()->Push(gc, closure->file); + return false; + } + } + if (externalMethod != nullptr) { + if (key == "Arguments") { + GCList ls2(gc); + TList *ls = TList::Create(ls2); + for (auto arg : externalMethod->args) { + ls->Add(arg); + } + cse.back()->Push(gc, ls); + return false; + } + } + + if (tcallable != nullptr) { + if (key == "Documentation") { + cse.back()->Push(gc, tcallable->documentation); + return false; + } + if (key == "Tag") { + gc->BarrierBegin(); + cse.back()->Push(gc, tcallable->tag); + gc->BarrierEnd(); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + + if (bA != nullptr) { + if (key == "Count" || key == "Length") { + int64_t len = (int64_t)bA->data.size(); + if (len < 0) + len = 0; + + stk->Push(gc, len); + return false; + } + } + if (list != nullptr) { + if (key == "Count" || key == "Length") { + int64_t len = list->Count(); + if (len < 0) + len = 0; + + stk->Push(gc, len); + return false; + } + } + if (dynList != nullptr) { + if (key == "Count" || key == "Length") { + int64_t len = dynList->Count(ls); + if (len < 0) + len = 0; + + stk->Push(gc, len); + return false; + } + } + if (dynDict != nullptr) { + if (dynDict->MethodExists(ls, "get" + key)) { + cse.back()->Push(gc, + dynDict->CallMethod(ls, "get" + key, {})); + } else { + cse.back()->Push(gc, dynDict->GetField(ls, key)); + } + return false; + } + + if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("get" + key); + gc->BarrierEnd(); + if (std::holds_alternative(fn) && + dynamic_cast( + std::get(fn).obj) != nullptr) { + return InvokeOne(ls, fn, dict); + } else { + gc->BarrierBegin(); + fn = dict->GetValue(key); + stk->Push(gc, fn); + gc->BarrierEnd(); + return false; + } + } + } + + stk->Push(gc, Undefined()); } -} \ No newline at end of file + + return false; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/invokemethod.cpp b/src/vm/bc/invokemethod.cpp index 46b726f..26c9777 100644 --- a/src/vm/bc/invokemethod.cpp +++ b/src/vm/bc/invokemethod.cpp @@ -2,53 +2,46 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - bool InterperterThread::InvokeMethod(GCList& ls, TObject fn, TObject instance, std::vector args) - { - - if(std::holds_alternative(fn)) - { - - auto obj = dynamic_cast(std::get(fn).obj); - if(obj != nullptr) - { - auto closure = dynamic_cast(obj); - if(closure != nullptr) - { - - if(!closure->closure->args.empty() && closure->closure->args[0] == "this") - { - std::vector args2; - args2.push_back(instance); - args2.insert(args2.end(), args.begin(),args.end()); - this->AddCallStackEntry(ls,closure,args2); - } - else - { - this->AddCallStackEntry(ls,closure,args); - } - +bool InterperterThread::InvokeMethod(GCList &ls, TObject fn, TObject instance, + std::vector args) { + + if (std::holds_alternative(fn)) { + + auto obj = + dynamic_cast(std::get(fn).obj); + if (obj != nullptr) { + auto closure = dynamic_cast(obj); + if (closure != nullptr) { + + if (!closure->closure->args.empty() && + closure->closure->args[0] == "this") { + std::vector args2; + args2.push_back(instance); + args2.insert(args2.end(), args.begin(), args.end()); + this->AddCallStackEntry(ls, closure, args2); + } else { + this->AddCallStackEntry(ls, closure, args); } - else - { - auto val = obj->Call(ls,args); - this->call_stack_entries.back()->Push(ls.GetGC(), val); - return false; - } - return true; + + } else { + auto val = obj->Call(ls, args); + this->call_stack_entries.back()->Push(ls.GetGC(), val); + return false; } - + return true; } - this->call_stack_entries.back()->Push(ls.GetGC(),Undefined()); - return false; } -} \ No newline at end of file + this->call_stack_entries.back()->Push(ls.GetGC(), Undefined()); + return false; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/invoketwo.cpp b/src/vm/bc/invoketwo.cpp index 8f97d5b..54b5c32 100644 --- a/src/vm/bc/invoketwo.cpp +++ b/src/vm/bc/invoketwo.cpp @@ -2,46 +2,40 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - bool InterperterThread::InvokeTwo(GCList& ls, TObject fn, TObject left, TObject right) - { - if(std::holds_alternative(fn)) - { - - auto obj = dynamic_cast(std::get(fn).obj); - if(obj != nullptr) - { - auto closure = dynamic_cast(obj); - if(closure != nullptr) - { - - if(!closure->closure->args.empty() && closure->closure->args[0] == "this") - { - this->AddCallStackEntry(ls,closure,{left,right}); - } - else - { - this->AddCallStackEntry(ls,closure,{right}); - } - +bool InterperterThread::InvokeTwo(GCList &ls, TObject fn, TObject left, + TObject right) { + if (std::holds_alternative(fn)) { + + auto obj = + dynamic_cast(std::get(fn).obj); + if (obj != nullptr) { + auto closure = dynamic_cast(obj); + if (closure != nullptr) { + + if (!closure->closure->args.empty() && + closure->closure->args[0] == "this") { + this->AddCallStackEntry(ls, closure, {left, right}); + } else { + this->AddCallStackEntry(ls, closure, {right}); } - else - { - this->call_stack_entries[this->call_stack_entries.size()-1]->Push(ls.GetGC(), obj->Call(ls,{right})); - - return false; - } - return true; + + } else { + this->call_stack_entries[this->call_stack_entries.size() - 1] + ->Push(ls.GetGC(), obj->Call(ls, {right})); + + return false; } - + return true; } - return false; } -} \ No newline at end of file + return false; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/setfield.cpp b/src/vm/bc/setfield.cpp index ef2bb21..b4e5cf1 100644 --- a/src/vm/bc/setfield.cpp +++ b/src/vm/bc/setfield.cpp @@ -2,371 +2,333 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - - static void empty() - { - } - bool InterperterThread::SetField(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; +static void empty() {} +bool InterperterThread::SetField(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - GCList ls(gc); - TObject value = stk->Pop(ls); - TObject _key = stk->Pop(ls); - TObject instance = stk->Pop(ls); - - if(!std::holds_alternative(_key)) - { - stk->Push(gc,Undefined()); - return false; - } + if (!cse.empty()) { + auto stk = cse.back(); + GCList ls(gc); + TObject value = stk->Pop(ls); + TObject _key = stk->Pop(ls); + TObject instance = stk->Pop(ls); - std::string key = std::get(_key); - if(std::holds_alternative>(instance)) - { - auto handle = std::get>(instance); - if(handle) - { - int64_t ms; - bool b; - if(key == "Enabled" && GetObject(value,b)) - { + if (!std::holds_alternative(_key)) { + stk->Push(gc, Undefined()); + return false; + } - handle->SetEnabled(b); + std::string key = std::get(_key); + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto handle = + std::get>( + instance); + if (handle) { + int64_t ms; + bool b; + if (key == "Enabled" && GetObject(value, b)) { - cse.back()->Push(gc,b); - return false; - } + handle->SetEnabled(b); - if(key == "Interval" && GetObject(value, ms)) - { - handle->SetIntervalFromMilliseconds(ms); - - cse.back()->Push(gc,ms); - return false; - } - if(key == "Callback") - { - TCallable* callable; - if(GetObjectHeap(value,callable)) - { - - auto obj = CreateMarkedTObject(ls.GetGC(), callable); - handle->SetCallback([obj]()->void { - TCallable* callable; - if(GetObjectHeap(obj->GetObject(), callable)) - { - GCList ls(obj->GetGC()); - callable->Call(ls,{}); - } - }); - cse.back()->Push(gc, callable); - return false; - } - else - { - handle->SetCallback(empty); - cse.back()->Push(gc, nullptr); - return false; - } - } - - } - - cse.back()->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto writer = std::get>(instance); - auto stringWriter = std::dynamic_pointer_cast(writer); - if(stringWriter != nullptr) - { - if(key == "Text") - { - if(std::holds_alternative(value)) - { - stringWriter->GetString() = std::get(value); - } - cse.back()->Push(gc, stringWriter->GetString()); - return false; - } - } - if(key == "NewLine") - { - if(std::holds_alternative(value)) - { - writer->newline = std::get(value); - } - cse.back()->Push(gc,writer->newline); + cse.back()->Push(gc, b); return false; } - cse.back()->Push(gc,Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto vfs = std::get>(instance); - auto relative = std::dynamic_pointer_cast(vfs); - - if(relative) - { - if(key == "Working") - { - Tesses::Framework::Filesystem::VFSPath path; - if(GetObjectAsPath(value,path)) - { - if(path.relative) - { - relative->SetWorking(path.MakeAbsolute(relative->GetWorking())); + if (key == "Interval" && GetObject(value, ms)) { + handle->SetIntervalFromMilliseconds(ms); + + cse.back()->Push(gc, ms); + return false; + } + if (key == "Callback") { + TCallable *callable; + if (GetObjectHeap(value, callable)) { + + auto obj = CreateMarkedTObject(ls.GetGC(), callable); + handle->SetCallback([obj]() -> void { + TCallable *callable; + if (GetObjectHeap(obj->GetObject(), callable)) { + GCList ls(obj->GetGC()); + callable->Call(ls, {}); } - else { - relative->SetWorking(path); + }); + cse.back()->Push(gc, callable); + return false; + } else { + handle->SetCallback(empty); + cse.back()->Push(gc, nullptr); + return false; + } + } + } + + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto writer = std::get< + std::shared_ptr>( + instance); + auto stringWriter = std::dynamic_pointer_cast< + Tesses::Framework::TextStreams::StringWriter>(writer); + if (stringWriter != nullptr) { + if (key == "Text") { + if (std::holds_alternative(value)) { + stringWriter->GetString() = + std::get(value); + } + cse.back()->Push(gc, stringWriter->GetString()); + return false; + } + } + if (key == "NewLine") { + if (std::holds_alternative(value)) { + writer->newline = std::get(value); + } + cse.back()->Push(gc, writer->newline); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + + auto vfs = + std::get>( + instance); + auto relative = std::dynamic_pointer_cast< + Tesses::Framework::Filesystem::RelativeFilesystem>(vfs); + + if (relative) { + if (key == "Working") { + Tesses::Framework::Filesystem::VFSPath path; + if (GetObjectAsPath(value, path)) { + if (path.relative) { + relative->SetWorking( + path.MakeAbsolute(relative->GetWorking())); + } else { + relative->SetWorking(path); + } + } + } + } + + cse.back()->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto svr = + std::get>( + instance); + auto bas = std::dynamic_pointer_cast< + Tesses::Framework::Http::BasicAuthServer>(svr); + auto cgi = + std::dynamic_pointer_cast( + svr); + auto changable = std::dynamic_pointer_cast< + Tesses::Framework::Http::ChangeableServer>(svr); + if (changable != nullptr) { + if (key == "Server") { + bas->server = ToHttpServer(gc, value); + stk->Push(gc, value); + return false; + } + } + + if (bas != nullptr) { + if (key == "Realm") { + bool val; + if (GetObject(value, val)) { + bas->realm = val; + stk->Push(gc, val); + + return false; + } + } + if (key == "Server") { + bas->server = ToHttpServer(gc, value); + stk->Push(gc, value); + return false; + } + if (key == "Authorization") { + TCallable *val; + if (GetObjectHeap(value, val)) { + auto marked = CreateMarkedTObject(ls, val); + bas->authorization = + [marked](std::string user, + std::string password) -> bool { + GCList ls(marked->GetGC()); + TCallable *callable; + if (GetObjectHeap(marked->GetObject(), callable)) { + return ToBool( + callable->Call(ls, {user, password})); } - } + return false; + }; + stk->Push(gc, val); + + return false; } } - - - cse.back()->Push(gc,Undefined()); - return false; } - if(std::holds_alternative>(instance)) - { - auto svr = std::get>(instance); - auto bas = std::dynamic_pointer_cast(svr); - auto cgi = std::dynamic_pointer_cast(svr); - auto changable = std::dynamic_pointer_cast(svr); - if(changable != nullptr) - { - if(key == "Server") - { - bas->server = ToHttpServer(gc,value); - stk->Push(gc,value); + + if (cgi != nullptr) { + if (key == "WorkingDirectory") { + Tesses::Framework::Filesystem::VFSPath path; + if (GetObjectAsPath(value, path)) { + cgi->workingDirectory = path; + stk->Push(gc, path); + return false; + } else { + cgi->workingDirectory = std::nullopt; + stk->Push(gc, nullptr); return false; } } - - if(bas != nullptr) - { - if(key == "Realm") - { - bool val; - if(GetObject(value,val)) - { - bas->realm = val; - stk->Push(gc,val ); - - return false; - } - } - if(key == "Server") - { - bas->server = ToHttpServer(gc,value); - stk->Push(gc,value); + if (key == "DocumentRoot") { + Tesses::Framework::Filesystem::VFSPath path; + if (GetObjectAsPath(value, path)) { + cgi->document_root = path; + stk->Push(gc, path); + return false; + } else { + cgi->document_root = std::nullopt; + stk->Push(gc, nullptr); return false; } - if(key == "Authorization") - { - TCallable* val; - if(GetObjectHeap(value,val)) - { - auto marked= CreateMarkedTObject(ls, val); - bas->authorization = [marked](std::string user,std::string password)->bool { - GCList ls(marked->GetGC()); - TCallable* callable; - if(GetObjectHeap(marked->GetObject(), callable)) - { - return ToBool(callable->Call(ls,{user,password})); - } - return false; - }; - stk->Push(gc,val); - - return false; - } + } + if (key == "AdminEmail") { + std::string str; + if (GetObject(value, str)) { + cgi->adminEmail = str; + stk->Push(gc, str); + return false; + } else { + cgi->adminEmail = std::nullopt; + stk->Push(gc, nullptr); + return false; } } - - if(cgi != nullptr) - { - if(key == "WorkingDirectory") - { - Tesses::Framework::Filesystem::VFSPath path; - if(GetObjectAsPath(value,path)) - { - cgi->workingDirectory = path; - stk->Push(gc,path); - return false; - } - else { - cgi->workingDirectory = std::nullopt; - stk->Push(gc,nullptr); - return false; - } - - } - if(key == "DocumentRoot") - { - Tesses::Framework::Filesystem::VFSPath path; - if(GetObjectAsPath(value,path)) - { - cgi->document_root= path; - stk->Push(gc,path); - return false; - } - else { - cgi->document_root= std::nullopt; - stk->Push(gc,nullptr); - return false; - } - - } - if(key == "AdminEmail") - { - std::string str; - if(GetObject(value,str)) - { - cgi->adminEmail = str; - stk->Push(gc,str); - return false; - } - else { - cgi->adminEmail= std::nullopt; - stk->Push(gc,nullptr); - return false; - } - - } - } - - stk->Push(gc, Undefined()); - return false; } - if(std::holds_alternative>(instance)) - { - auto strm = std::get>(instance); - auto netStrm = std::dynamic_pointer_cast(strm); - if(netStrm != nullptr) - { - int64_t n0; - bool bc; - if(key == "Broadcast" && GetObject(value,bc)) - netStrm->SetBroadcast(bc); - if(key == "NoDelay" && GetObject(value,bc)) - netStrm->SetNoDelay(bc); - if(key == "ReuseAddress" && GetObject(value,bc)) - netStrm->SetReuseAddress(bc); - if(key == "ReusePort" && GetObject(value,bc)) - netStrm->SetReusePort(bc); - if(key == "MulticastTTL" && GetObject(value,n0)) - netStrm->SetMulticastTTL((uint8_t)n0); - - } - stk->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative(instance)) - { - auto obj = std::get(instance).obj; - - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"set"+key); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{value}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{value})); - return false; - } - gc->BarrierBegin(); - cls->SetValue(cse.back()->callable->className,key,value); - gc->BarrierEnd(); - cse.back()->Push(gc,value); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc,natObj->CallMethod(ls,"set"+key,{value})); - return false; - } - auto tcallable = dynamic_cast(obj); - if(tcallable != nullptr) - { - if(key == "Tag") - { - gc->BarrierBegin(); - tcallable->tag = value; - gc->BarrierEnd(); - cse.back()->Push(gc,nullptr); - return false; - } - } - if(dynDict != nullptr) - { - if(dynDict->MethodExists(ls,"set" + key)) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"set" + key, {value})); - } - else - { - dynDict->SetField(ls,key,value); - cse.back()->Push(gc,value); - } - return false; - } - if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("set" + key); - gc->BarrierEnd(); - if(std::holds_alternative(fn) && dynamic_cast(std::get(fn).obj) != nullptr) - { - return InvokeTwo(ls,fn, dict, value); - } - else - { - gc->BarrierBegin(); - dict->SetValue(key, value); - stk->Push(gc, value); - gc->BarrierEnd(); - return false; - } - } - + stk->Push(gc, Undefined()); + return false; + } + if (std::holds_alternative< + std::shared_ptr>( + instance)) { + auto strm = + std::get>( + instance); + + auto netStrm = std::dynamic_pointer_cast< + Tesses::Framework::Streams::NetworkStream>(strm); + if (netStrm != nullptr) { + int64_t n0; + bool bc; + if (key == "Broadcast" && GetObject(value, bc)) + netStrm->SetBroadcast(bc); + if (key == "NoDelay" && GetObject(value, bc)) + netStrm->SetNoDelay(bc); + if (key == "ReuseAddress" && GetObject(value, bc)) + netStrm->SetReuseAddress(bc); + if (key == "ReusePort" && GetObject(value, bc)) + netStrm->SetReusePort(bc); + if (key == "MulticastTTL" && GetObject(value, n0)) + netStrm->SetMulticastTTL((uint8_t)n0); } stk->Push(gc, Undefined()); - + return false; } - return false; - } + if (std::holds_alternative(instance)) { + auto obj = std::get(instance).obj; -} \ No newline at end of file + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "set" + key); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {value}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {value})); + return false; + } + gc->BarrierBegin(); + cls->SetValue(cse.back()->callable->className, key, value); + gc->BarrierEnd(); + cse.back()->Push(gc, value); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, + natObj->CallMethod(ls, "set" + key, {value})); + return false; + } + auto tcallable = dynamic_cast(obj); + if (tcallable != nullptr) { + if (key == "Tag") { + gc->BarrierBegin(); + tcallable->tag = value; + gc->BarrierEnd(); + cse.back()->Push(gc, nullptr); + return false; + } + } + if (dynDict != nullptr) { + if (dynDict->MethodExists(ls, "set" + key)) { + cse.back()->Push( + gc, dynDict->CallMethod(ls, "set" + key, {value})); + } else { + dynDict->SetField(ls, key, value); + cse.back()->Push(gc, value); + } + return false; + } + if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("set" + key); + gc->BarrierEnd(); + if (std::holds_alternative(fn) && + dynamic_cast( + std::get(fn).obj) != nullptr) { + return InvokeTwo(ls, fn, dict, value); + } else { + gc->BarrierBegin(); + dict->SetValue(key, value); + stk->Push(gc, value); + gc->BarrierEnd(); + return false; + } + } + } + stk->Push(gc, Undefined()); + } + return false; +} + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/sub.cpp b/src/vm/bc/sub.cpp index f2f1b55..2874072 100644 --- a/src/vm/bc/sub.cpp +++ b/src/vm/bc/sub.cpp @@ -2,120 +2,112 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - bool InterperterThread::Sub(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); +bool InterperterThread::Sub(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) - std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) - std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) - std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) - std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) - (*r))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) - (*r))); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) - std::get(right)); + } - auto natObj = dynamic_cast(obj); - - - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator-"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator-",{right})); + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) - std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) - std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) - std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, (int64_t)(std::get(left) - std::get(right))); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, (int64_t)(std::get(left) - std::get(right))); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, (int64_t)(std::get(left) - std::get(right))); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push( + gc, + std::make_shared((*l) - (*r))); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push( + gc, + std::make_shared((*l) - (*r))); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator-"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); return false; } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator-"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator-",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator-", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator-"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator-", {right})); + return false; + } else { cse.back()->Push(gc, Undefined()); } - return false; + + } else { + cse.back()->Push(gc, Undefined()); } -} \ No newline at end of file + return false; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/tobool.cpp b/src/vm/bc/tobool.cpp index 574f83c..f3ef224 100644 --- a/src/vm/bc/tobool.cpp +++ b/src/vm/bc/tobool.cpp @@ -2,105 +2,84 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - bool ToBool(TObject obj) - { - if(std::holds_alternative(obj)) - { - return true; - } - if(std::holds_alternative(obj)) - { - auto v = std::get(obj); - return v.AsLong() != 0; - } - if(std::holds_alternative(obj)) - { - return !std::get(obj).empty(); - } - else if(std::holds_alternative(obj)) - { - return std::get(obj) != 0; - } - else if(std::holds_alternative(obj)) - { - return std::get(obj); - } - else if(std::holds_alternative(obj)) - { - return std::get(obj); - } - else if(std::holds_alternative(obj)) - { - return std::get(obj) != 0; - } - else if(std::holds_alternative>(obj)) - { - auto& dt = std::get>(obj); - return !(dt->Year() == 1970 && dt->Month() == 1 && dt->Day() == 1 && dt->Hour() == 0 && dt->Minute() == 0 && dt->Second() == 0 && !dt->IsLocal()); - - } - else if(std::holds_alternative>(obj)) - { - return std::get>(obj)->TotalSeconds() != 0; - } - else if(std::holds_alternative(obj)) - { - auto& uuid = std::get(obj); - return !uuid.IsEmpty(); - } - else if(std::holds_alternative(obj)) - { - auto o = std::get(obj).obj; - auto ls = dynamic_cast(o); - auto aarray = dynamic_cast(o); - auto dict = dynamic_cast(o); - auto ba = dynamic_cast(o); - auto nat = dynamic_cast(o); - auto thrd = dynamic_cast(o); - auto natObj = dynamic_cast(o); - - auto any = dynamic_cast(o); - auto cls = dynamic_cast(o); - if(cls!=nullptr) return true; - if(natObj != nullptr) return natObj->ToBool(); - if(any != nullptr) return any->any.has_value(); - - if(ls != nullptr) - { - return ls->Count() != 0; - } - if(aarray != nullptr) - { - return aarray->Count() != 0; - } - else if(dict != nullptr) - { - return !dict->items.empty(); - } - else if(ba != nullptr) - { - return !ba->data.empty(); - } - else if(nat != nullptr) - { - return !nat->GetDestroyed(); - } - else if(thrd != nullptr) - { - return !thrd->hasReturned; - } - return true; - } - - return false; +bool ToBool(TObject obj) { + if (std::holds_alternative(obj)) { + return true; } -} \ No newline at end of file + if (std::holds_alternative(obj)) { + auto v = std::get(obj); + return v.AsLong() != 0; + } + if (std::holds_alternative(obj)) { + return !std::get(obj).empty(); + } else if (std::holds_alternative(obj)) { + return std::get(obj) != 0; + } else if (std::holds_alternative(obj)) { + return std::get(obj); + } else if (std::holds_alternative(obj)) { + return std::get(obj); + } else if (std::holds_alternative(obj)) { + return std::get(obj) != 0; + } else if (std::holds_alternative< + std::shared_ptr>(obj)) { + auto &dt = + std::get>(obj); + return !(dt->Year() == 1970 && dt->Month() == 1 && dt->Day() == 1 && + dt->Hour() == 0 && dt->Minute() == 0 && dt->Second() == 0 && + !dt->IsLocal()); + + } else if (std::holds_alternative< + std::shared_ptr>(obj)) { + return std::get>(obj) + ->TotalSeconds() != 0; + } else if (std::holds_alternative(obj)) { + auto &uuid = std::get(obj); + return !uuid.IsEmpty(); + } else if (std::holds_alternative(obj)) { + auto o = std::get(obj).obj; + auto ls = dynamic_cast(o); + auto aarray = dynamic_cast(o); + auto dict = dynamic_cast(o); + auto ba = dynamic_cast(o); + auto nat = dynamic_cast(o); + auto thrd = dynamic_cast(o); + auto natObj = dynamic_cast(o); + + auto any = dynamic_cast(o); + auto cls = dynamic_cast(o); + if (cls != nullptr) + return true; + if (natObj != nullptr) + return natObj->ToBool(); + if (any != nullptr) + return any->any.has_value(); + + if (ls != nullptr) { + return ls->Count() != 0; + } + if (aarray != nullptr) { + return aarray->Count() != 0; + } else if (dict != nullptr) { + return !dict->items.empty(); + } else if (ba != nullptr) { + return !ba->data.empty(); + } else if (nat != nullptr) { + return !nat->GetDestroyed(); + } else if (thrd != nullptr) { + return !thrd->hasReturned; + } + return true; + } + + return false; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/tostring.cpp b/src/vm/bc/tostring.cpp index 121ade6..d8003de 100644 --- a/src/vm/bc/tostring.cpp +++ b/src/vm/bc/tostring.cpp @@ -2,132 +2,114 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include namespace Tesses::CrossLang { - std::string ToString(std::shared_ptr gc, TObject o) - { - if(std::holds_alternative(o)) - { - return std::get(o).ToString(); - } - if(std::holds_alternative(o)) - { - return std::get(o); - } - if(std::holds_alternative(o)) - { - return std::get(o).ToString(); - } - if(std::holds_alternative(o)) - { - return std::to_string(std::get(o)); - } - - if(std::holds_alternative(o)) - { - return std::to_string(std::get(o)); - } - - if(std::holds_alternative(o)) - { - return std::string{std::get(o)}; - } - if(std::holds_alternative(o)) - { - return "null"; - } - if(std::holds_alternative(o)) - { - return "undefined"; - } - if(std::holds_alternative(o)) - { - return std::get(o) ? "true" : "false"; - } - if(std::holds_alternative>(o)) - { - return std::get>(o)->ToString(); - } - if(std::holds_alternative>(o)) - { - return std::get>(o)->ToString(false); - } - if(std::holds_alternative(o)) - { - return std::get(o).ToString(Framework::UuidStringifyConfig::LowercaseNoCurly); - } - if(std::holds_alternative(o)) - { - auto obj = std::get(o).obj; - auto dict = dynamic_cast(obj); - auto list = dynamic_cast(obj); - auto bArray = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - auto aArray = dynamic_cast(obj); - if(aArray != nullptr) - { - - std::string str={}; - - gc->BarrierBegin(); - bool first=true; - for(auto item : aArray->items) - { - if(!first) str.push_back('\n'); - first=false; - str.push_back('['); - str.append(Json_Encode(item.first)); - str.append("] = "); - str.append(Json_Encode(item.second)); - str.append(";"); - } - gc->BarrierEnd(); - return str; - } - if(cls != nullptr) - { - auto res = cls->GetValue("","ToString"); - TCallable* call; - GCList ls(gc); - if(GetObjectHeap(res,call)) return ToString(gc, call->Call(ls,{})); - return cls->TypeName(); - } - if(natObj != nullptr) - { - GCList ls(gc); - TObject o=natObj->CallMethod(ls,"ToString",{}); - - - return ToString(gc, o); - } - - if(dict != nullptr) - { - GCList ls(gc); - if(dict->MethodExists(ls,"ToString")) - return ToString(gc,dict->CallMethod(ls,"ToString",{})); - else - { - return Json_Encode(dict); - } - } - else if(bArray != nullptr) - { - return std::string(bArray->data.begin(),bArray->data.end()); - } - else if(list != nullptr) - { - return Json_Encode(list); - } - } - - return ""; +std::string ToString(std::shared_ptr gc, TObject o) { + if (std::holds_alternative(o)) { + return std::get(o).ToString(); } -} \ No newline at end of file + if (std::holds_alternative(o)) { + return std::get(o); + } + if (std::holds_alternative(o)) { + return std::get(o).ToString(); + } + if (std::holds_alternative(o)) { + return std::to_string(std::get(o)); + } + + if (std::holds_alternative(o)) { + return std::to_string(std::get(o)); + } + + if (std::holds_alternative(o)) { + return std::string{std::get(o)}; + } + if (std::holds_alternative(o)) { + return "null"; + } + if (std::holds_alternative(o)) { + return "undefined"; + } + if (std::holds_alternative(o)) { + return std::get(o) ? "true" : "false"; + } + if (std::holds_alternative< + std::shared_ptr>(o)) { + return std::get>(o) + ->ToString(); + } + if (std::holds_alternative< + std::shared_ptr>(o)) { + return std::get>(o) + ->ToString(false); + } + if (std::holds_alternative(o)) { + return std::get(o).ToString( + Framework::UuidStringifyConfig::LowercaseNoCurly); + } + if (std::holds_alternative(o)) { + auto obj = std::get(o).obj; + auto dict = dynamic_cast(obj); + auto list = dynamic_cast(obj); + auto bArray = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + auto aArray = dynamic_cast(obj); + if (aArray != nullptr) { + + std::string str = {}; + + gc->BarrierBegin(); + bool first = true; + for (auto item : aArray->items) { + if (!first) + str.push_back('\n'); + first = false; + str.push_back('['); + str.append(Json_Encode(item.first)); + str.append("] = "); + str.append(Json_Encode(item.second)); + str.append(";"); + } + gc->BarrierEnd(); + return str; + } + if (cls != nullptr) { + auto res = cls->GetValue("", "ToString"); + TCallable *call; + GCList ls(gc); + if (GetObjectHeap(res, call)) + return ToString(gc, call->Call(ls, {})); + return cls->TypeName(); + } + if (natObj != nullptr) { + GCList ls(gc); + TObject o = natObj->CallMethod(ls, "ToString", {}); + + return ToString(gc, o); + } + + if (dict != nullptr) { + GCList ls(gc); + if (dict->MethodExists(ls, "ToString")) + return ToString(gc, dict->CallMethod(ls, "ToString", {})); + else { + return Json_Encode(dict); + } + } else if (bArray != nullptr) { + return std::string(bArray->data.begin(), bArray->data.end()); + } else if (list != nullptr) { + return Json_Encode(list); + } + } + + return ""; +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/exception.cpp b/src/vm/exception.cpp index 16446d4..48ad2bc 100644 --- a/src/vm/exception.cpp +++ b/src/vm/exception.cpp @@ -1,107 +1,93 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { - TObject TCallable::CallWithFatalError(GCList& ls, std::vector args) - { - try { - return Call(ls,args); - } - catch(VMByteCodeException& ex) - { - ThrowFatalError(ex); - } - catch(VMException& ex) - { - ThrowFatalError(ex); - } - catch(SyntaxException& ex) - { - ThrowFatalError(ex); - } - catch(std::runtime_error& ex) - { - ThrowFatalError(ex); - } - catch(std::exception& ex) - { - ThrowFatalError(ex); - } - return (int64_t)1; +TObject TCallable::CallWithFatalError(GCList &ls, std::vector args) { + try { + return Call(ls, args); + } catch (VMByteCodeException &ex) { + ThrowFatalError(ex); + } catch (VMException &ex) { + ThrowFatalError(ex); + } catch (SyntaxException &ex) { + ThrowFatalError(ex); + } catch (std::runtime_error &ex) { + ThrowFatalError(ex); + } catch (std::exception &ex) { + ThrowFatalError(ex); } - void ThrowFatalError(std::exception& ex) - { - using namespace Tesses::Framework::TextStreams; - std::exception* ex2 = &ex; - auto clexcept = dynamic_cast(ex2); - auto clrtexcept = dynamic_cast(ex2); - auto compiler = dynamic_cast(ex2); - Tesses::Framework::TextStreams::ConsoleWriter error(true); - - if(clexcept != nullptr) - { - error.WriteLine("CrossLang has encountered a fatal exception"); - error.WriteLine(); - - error.WriteLine(ToString(clexcept->GetGCList()->GetGC(),clexcept->exception)); - error.WriteLine(); - error.WriteLine("STACKTRACE:"); - - for(auto ittr = clexcept->stack_trace.crbegin(); ittr != clexcept->stack_trace.crend(); ittr++) - { - auto item = *ittr; - std::string text = "\t"; - text += item->callable->closure->name.value_or((std::string)""); - text += "("; - bool first=true; - for(auto& arg : item->callable->closure->args) - { - if(!first) text += ", "; - text += arg; - first=false; - } - text += ")"; - if(item->srcline >= 1) - { - text += " at "; - text += item->srcfile; - text += ":"; - text += std::to_string(item->srcline); - } - error.WriteLine(text); - } + return (int64_t)1; +} +void ThrowFatalError(std::exception &ex) { + using namespace Tesses::Framework::TextStreams; + std::exception *ex2 = &ex; + auto clexcept = dynamic_cast(ex2); + auto clrtexcept = dynamic_cast(ex2); + auto compiler = dynamic_cast(ex2); + Tesses::Framework::TextStreams::ConsoleWriter error(true); - exit(1); - } - if(clrtexcept != nullptr) - { - error.WriteLine("CrossLang has encountered a fatal runtime exception"); - error.WriteLine(); - error.WriteLine(clrtexcept->what()); - exit(1); - } - if(compiler != nullptr) - { - error.WriteLine("CrossLang has encountered a compiler error"); - error.WriteLine(); - error.WriteLine(compiler->Message()); - error.WriteLine(); - auto li = compiler->LineInfo(); - error.Write("in file: "); - error.Write(li.filename); - error.Write(":"); - error.Write((int64_t)li.line); - error.Write(":"); - error.Write((int64_t)li.column); - error.Write(":"); - error.WriteLine((int64_t)li.offset); - - exit(1); - } - - error.WriteLine("CrossLang has encountered a fatal C++ exception"); + if (clexcept != nullptr) { + error.WriteLine("CrossLang has encountered a fatal exception"); error.WriteLine(); - error.Write("what(): "); - error.WriteLine(ex2->what()); + + error.WriteLine( + ToString(clexcept->GetGCList()->GetGC(), clexcept->exception)); + error.WriteLine(); + error.WriteLine("STACKTRACE:"); + + for (auto ittr = clexcept->stack_trace.crbegin(); + ittr != clexcept->stack_trace.crend(); ittr++) { + auto item = *ittr; + std::string text = "\t"; + text += item->callable->closure->name.value_or( + (std::string) ""); + text += "("; + bool first = true; + for (auto &arg : item->callable->closure->args) { + if (!first) + text += ", "; + text += arg; + first = false; + } + text += ")"; + if (item->srcline >= 1) { + text += " at "; + text += item->srcfile; + text += ":"; + text += std::to_string(item->srcline); + } + error.WriteLine(text); + } + exit(1); } -} \ No newline at end of file + if (clrtexcept != nullptr) { + error.WriteLine("CrossLang has encountered a fatal runtime exception"); + error.WriteLine(); + error.WriteLine(clrtexcept->what()); + exit(1); + } + if (compiler != nullptr) { + error.WriteLine("CrossLang has encountered a compiler error"); + error.WriteLine(); + error.WriteLine(compiler->Message()); + error.WriteLine(); + auto li = compiler->LineInfo(); + error.Write("in file: "); + error.Write(li.filename); + error.Write(":"); + error.Write((int64_t)li.line); + error.Write(":"); + error.Write((int64_t)li.column); + error.Write(":"); + error.WriteLine((int64_t)li.offset); + + exit(1); + } + + error.WriteLine("CrossLang has encountered a fatal C++ exception"); + error.WriteLine(); + error.Write("what(): "); + error.WriteLine(ex2->what()); + exit(1); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/filereader.cpp b/src/vm/filereader.cpp index c34f201..1d224e0 100644 --- a/src/vm/filereader.cpp +++ b/src/vm/filereader.cpp @@ -1,453 +1,413 @@ #include "CrossLang.hpp" - #include #include #include -namespace Tesses::CrossLang -{ +namespace Tesses::CrossLang { - TFile* TFile::Create(GCList& ls) - { - TFile* f = new TFile(); - f->icon = -1; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(f); - _gc->Watch(f); - return f; - } - TFile* TFile::Create(GCList* ls) - { - TFile* f = new TFile(); - f->icon=-1; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(f); - _gc->Watch(f); - return f; - } - void TFileChunk::Mark() - { - if(this->marked) return; - this->marked=true; - this->file->Mark(); - } - - TFileChunk* TFileChunk::Create(GCList& ls) - { - TFileChunk* chk = new TFileChunk(); - std::shared_ptr _gc = ls.GetGC(); - ls.Add(chk); - _gc->Watch(chk); - return chk; - } - TFileChunk* TFileChunk::Create(GCList* ls) - { - TFileChunk* chk = new TFileChunk(); - std::shared_ptr _gc = ls->GetGC(); - ls->Add(chk); - _gc->Watch(chk); - return chk; - } - void TFile::Mark() - { - if(this->marked) return; - this->marked=true; - - for(auto item : this->chunks) - item->Mark(); - - } - void TFile::Skip(std::shared_ptr stream,size_t len) - { - if(stream->CanSeek()) - { - stream->Seek((int64_t)len,Tesses::Framework::Streams::SeekOrigin::Current); - } - else{ - uint8_t* buffer=new uint8_t[len]; - Ensure(stream,buffer,len); - delete[] buffer; - } - } - void TFile::Ensure(std::shared_ptr stream, uint8_t* buffer,size_t len) - { - size_t read = stream->ReadBlock(buffer, len); - if(read < len) throw VMException("End of file, could not read " + std::to_string((int64_t)len) + " byte(s)., offset=" + std::to_string(stream->GetLength())); - } - std::string TFile::EnsureString(std::shared_ptr stream) - { - auto len = EnsureInt(stream); - if(len == 0) return {}; - std::string str={}; - str.resize((size_t)len); - Ensure(stream,(uint8_t*)str.data(),str.size()); - return str; - } - - uint32_t TFile::EnsureInt(std::shared_ptr stream) - { - uint8_t buffer[4]; - Ensure(stream,buffer,4); - return BitConverter::ToUint32BE(buffer[0]); - } - std::string TFile::GetString(std::shared_ptr stream) - { - uint32_t index=EnsureInt(stream); - if(index >= this->strings.size()) throw VMException("String does not exist in TCrossVM file, expected string index: " + std::to_string(index) + ", total strings: " + std::to_string(this->strings.size())); - return this->strings[index]; - } - void TFile::EnsureCanRunInCrossLang() - { - if(this->vms.empty()) return; - - for(auto item : this->vms) - { - if(item.first == VMName) - { - return; - } - } - - - std::string errorMessage="The virtual machines supported are:\n"; - - for(auto item : this->vms) - { - errorMessage += item.first + "\n\t" + item.second + "\n"; - } - throw VMException(errorMessage); - } - - TDictionary* TFile::MetadataDecode(GCList& ls, size_t midx) - { - if(midx >= this->metadata.size()) return nullptr; - if(this->metadata[midx].second.empty()) return nullptr; - if(this->metadata[midx].second[0] != 8) return nullptr; - size_t index = 0; - auto& bytes = this->metadata[midx].second; - - std::function parseEnt; - parseEnt = [&]()->TObject { - if(index >= bytes.size()) throw std::out_of_range("Abrupt end of metadata"); - switch(bytes[index++]) - { - case 0: - return false; - case 1: - return true; - case 2: - return nullptr; - case 3: - { - if(index + 8 <= bytes.size()) - { - auto val= BitConverter::ToUint64BE(bytes[index]); - index+=8; - int64_t val2; - memcpy(&val2,&val,sizeof(val)); - return val2; - } - else throw std::out_of_range("Abrupt end of metadata"); - } - break; - case 4: - { - if(index + 8 <= bytes.size()) - { - auto val= BitConverter::ToDoubleBE(bytes[index]); - index+=8; - return val; - } - else throw std::out_of_range("Abrupt end of metadata"); - } - break; - case 5: - - if(index + 1 <= bytes.size()) - { - return (char)bytes[index++]; - } - else throw std::out_of_range("Abrupt end of metadata"); - break; - case 6: - { - if(index + 4 <= bytes.size()) - { - auto val= BitConverter::ToUint32BE(bytes[index]); - index+=4; - return this->strings.at((size_t)val); - } else throw std::out_of_range("Abrupt end of metadata"); - - } - break; - case 7: - { - if(index + 4 <= bytes.size()) - { - auto val= BitConverter::ToUint32BE(bytes[index]); - index+=4; - std::vector items; - for(uint32_t i = 0; i < val; i++) - { - items.push_back(parseEnt()); - } - - return TList::Create(ls,items.begin(),items.end()); - } else throw std::out_of_range("Abrupt end of metadata"); - } - break; - case 8: - if(index + 4 <= bytes.size()) - { - auto val= BitConverter::ToUint32BE(bytes[index]); - index+=4; - std::vector items; - - for(uint32_t i = 0; i < val; i++) - { - if(index + 4 <= bytes.size()) - { - auto val2= BitConverter::ToUint32BE(bytes[index]); - index+=4; - std::string& text=this->strings.at((size_t)val2); - items.emplace_back(text,parseEnt()); - } else throw std::out_of_range("Abrupt end of metadata"); - - } - - return TDictionary::Create(ls, items.begin(),items.end()); - }else throw std::out_of_range("Abrupt end of metadata"); - break; - case 9: - { - if(index + 4 <= bytes.size()) - { - auto val= BitConverter::ToUint32BE(bytes[index]); - index+=4; - auto ba = TByteArray::Create(ls); - ba->data = this->resources.at((size_t)val); - return ba; - } else throw std::out_of_range("Abrupt end of metadata"); - } - break; - case 10: - { - if(index + 4 <= bytes.size()) - { - auto val= BitConverter::ToUint32BE(bytes[index]); - index+=4; - return std::make_shared(ls.GetGC(),this,val); - } else throw std::out_of_range("Abrupt end of metadata"); - } - break; - case 11: - { - - auto data = parseEnt(); - TDictionary* dict; - if(GetObjectHeap(data,dict)) - { - return std::make_shared(ls.GetGC(),dict); - } - else return Undefined(); - } - break; - case 12: - { - if(index + 4 <= bytes.size()) - { - auto val= BitConverter::ToUint32BE(bytes[index]); - index+=4; - ls.GetGC()->BarrierBegin(); - auto em = TExternalMethod::Create(ls,"",{},[val,this](GCList& ls, std::vector args)->TObject { - return std::make_shared(ls.GetGC(),this,val); - }); - em->watch.push_back(this); - ls.GetGC()->BarrierEnd(); - - return em; - } else throw std::out_of_range("Abrupt end of metadata"); - } - break; - default: - throw std::runtime_error("Invalid metadata opcode"); - } - }; - - TDictionary* dict_res; - TObject ent = parseEnt(); - if(GetObjectHeap(ent, dict_res)) return dict_res; - return nullptr; - } - - void TFile::Load(std::shared_ptr gc, std::shared_ptr stream) - { - - uint8_t main_header[18]; - Ensure(stream,main_header,sizeof(main_header)); - if(strncmp((const char*)main_header,"TCROSSVM",8) != 0) throw VMException("Invalid TCrossVM image."); - TVMVersion version(main_header+8); - if(version.CompareToRuntime() == 1) - { - throw VMException("Runtime is too old."); - } - TVMVersion v2(main_header+13); - this->version = v2; - - size_t _len = (size_t)EnsureInt(stream); - - char table_name[4]; - - for(size_t i = 0;i < _len; i++) - { - Ensure(stream,(uint8_t*)table_name,sizeof(table_name)); - size_t tableLen = (size_t)EnsureInt(stream); - if(strncmp(table_name,"NAME",4) == 0) - { - this->name = GetString(stream); - } - else if(strncmp(table_name,"INFO",4) == 0) - { - this->info = GetString(stream); - } - else if(strncmp(table_name,"DEPS",4) == 0) //dependencies - { - std::string name = GetString(stream); - uint8_t version_bytes[5]; - Ensure(stream,version_bytes,sizeof(version_bytes)); - TVMVersion depVersion(version_bytes); - this->dependencies.push_back(std::pair(name, depVersion)); - } - else if(strncmp(table_name,"TOOL",4) == 0) //compile tools (for package manager) - { - std::string name = GetString(stream); - uint8_t version_bytes[5]; - Ensure(stream,version_bytes,sizeof(version_bytes)); - TVMVersion depVersion(version_bytes); - this->tools.push_back(std::pair(name, depVersion)); - } - else if(strncmp(table_name,"RESO",4) == 0) //resources (using embed) - { - auto& data = this->resources.emplace_back(tableLen); - Ensure(stream,data.data(), data.size()); - } - else if(strncmp(table_name,"CHKS",4) == 0 && gc != nullptr) //chunks - { - GCList ls(gc); - size_t chunkCount = (size_t)EnsureInt(stream); - for(size_t j = 0; j < chunkCount; j++) - { - - auto chunk = TFileChunk::Create(ls); - chunk->file = this; - size_t argCount = (size_t)EnsureInt(stream); - for(size_t k = 0; k < argCount; k++) - { - chunk->args.push_back(GetString(stream)); - } - size_t len = (size_t)EnsureInt(stream); - chunk->code.resize(len); - Ensure(stream,chunk->code.data(),len); - //reader.ReadIntoBuffer(chunk->code); - - this->chunks.push_back(chunk); - } - - } - else if(strncmp(table_name,"FUNS",4) == 0) //functions - { - size_t funLength = (size_t)EnsureInt(stream); - - for(size_t j = 0; j < funLength;j++) - { - std::vector fnParts; - uint32_t fnPartsC = EnsureInt(stream); - for(uint32_t k = 0; k < fnPartsC; k++) - { - fnParts.push_back(GetString(stream)); - } - - uint32_t fnNumber = EnsureInt(stream); - this->functions.push_back(std::pair,uint32_t>(fnParts,fnNumber)); - - } - - } - else if(strncmp(table_name,"STRS",4) == 0) //strings - { - size_t strsLen = (size_t)EnsureInt(stream); - for(size_t j = 0;j < strsLen;j++) - { - this->strings.push_back(EnsureString(stream)); - } - } - else if(strncmp(table_name,"ICON",4) == 0) //icon - { - this->icon = (int32_t)EnsureInt(stream); - } - else if(strncmp(table_name,"MACH",4) == 0) //machine - { - std::string name = GetString(stream); - std::string howToGet = GetString(stream); - this->vms.push_back(std::pair(name,howToGet)); - } - else if(strncmp(table_name,"CLSS",4) == 0) //classes - { - uint32_t clsCnt = EnsureInt(stream); - for(uint32_t j = 0; j < clsCnt; j++) - { - TClass cls; - cls.documentation= GetString(stream); - uint32_t name_cnt = EnsureInt(stream); - for(uint32_t k = 0; k < name_cnt; k++) - { - cls.name.push_back(GetString(stream)); - } - name_cnt = EnsureInt(stream); - for(uint32_t k = 0; k < name_cnt; k++) - { - cls.inherits.push_back(GetString(stream)); - } - name_cnt = EnsureInt(stream); - for(uint32_t k = 0; k < name_cnt; k++) - { - TClassEntry ent; - Ensure(stream,main_header,1); - uint8_t sig = main_header[0]; - ent.isAbstract = (sig & 0b00001000) != 0; - ent.isFunction = (sig & 0b00000100) == 0; - ent.modifier = (TClassModifier)(sig & 3); - ent.documentation = GetString(stream); - ent.name = GetString(stream); - uint32_t arglen = EnsureInt(stream); - for(uint32_t l = 0; l < arglen; l++) - ent.args.push_back(GetString(stream)); - ent.chunkId = EnsureInt(stream); - cls.entry.push_back(ent); - } - this->classes.push_back(cls); - } - } - else if(strncmp(table_name,"META",4) == 0) //structured metadata - { - if(tableLen > 4) - { - auto name = this->GetString(stream); - auto& data = this->metadata.emplace_back(name, std::vector(tableLen-4)); - Ensure(stream,data.second.data(), tableLen-4); - } - else throw VMException("meta tag is not valid"); - - } - else - { - auto& data = this->sections.emplace_back(std::string(table_name, 4), std::vector(tableLen)); - Ensure(stream,data.second.data(), tableLen); - - } - } - - } - - +TFile *TFile::Create(GCList &ls) { + TFile *f = new TFile(); + f->icon = -1; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(f); + _gc->Watch(f); + return f; } +TFile *TFile::Create(GCList *ls) { + TFile *f = new TFile(); + f->icon = -1; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(f); + _gc->Watch(f); + return f; +} +void TFileChunk::Mark() { + if (this->marked) + return; + this->marked = true; + this->file->Mark(); +} + +TFileChunk *TFileChunk::Create(GCList &ls) { + TFileChunk *chk = new TFileChunk(); + std::shared_ptr _gc = ls.GetGC(); + ls.Add(chk); + _gc->Watch(chk); + return chk; +} +TFileChunk *TFileChunk::Create(GCList *ls) { + TFileChunk *chk = new TFileChunk(); + std::shared_ptr _gc = ls->GetGC(); + ls->Add(chk); + _gc->Watch(chk); + return chk; +} +void TFile::Mark() { + if (this->marked) + return; + this->marked = true; + + for (auto item : this->chunks) + item->Mark(); +} +void TFile::Skip(std::shared_ptr stream, + size_t len) { + if (stream->CanSeek()) { + stream->Seek((int64_t)len, + Tesses::Framework::Streams::SeekOrigin::Current); + } else { + uint8_t *buffer = new uint8_t[len]; + Ensure(stream, buffer, len); + delete[] buffer; + } +} +void TFile::Ensure(std::shared_ptr stream, + uint8_t *buffer, size_t len) { + size_t read = stream->ReadBlock(buffer, len); + if (read < len) + throw VMException( + "End of file, could not read " + std::to_string((int64_t)len) + + " byte(s)., offset=" + std::to_string(stream->GetLength())); +} +std::string TFile::EnsureString( + std::shared_ptr stream) { + auto len = EnsureInt(stream); + if (len == 0) + return {}; + std::string str = {}; + str.resize((size_t)len); + Ensure(stream, (uint8_t *)str.data(), str.size()); + return str; +} + +uint32_t +TFile::EnsureInt(std::shared_ptr stream) { + uint8_t buffer[4]; + Ensure(stream, buffer, 4); + return BitConverter::ToUint32BE(buffer[0]); +} +std::string +TFile::GetString(std::shared_ptr stream) { + uint32_t index = EnsureInt(stream); + if (index >= this->strings.size()) + throw VMException( + "String does not exist in TCrossVM file, expected string index: " + + std::to_string(index) + + ", total strings: " + std::to_string(this->strings.size())); + return this->strings[index]; +} +void TFile::EnsureCanRunInCrossLang() { + if (this->vms.empty()) + return; + + for (auto item : this->vms) { + if (item.first == VMName) { + return; + } + } + + std::string errorMessage = "The virtual machines supported are:\n"; + + for (auto item : this->vms) { + errorMessage += item.first + "\n\t" + item.second + "\n"; + } + throw VMException(errorMessage); +} + +TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) { + if (midx >= this->metadata.size()) + return nullptr; + if (this->metadata[midx].second.empty()) + return nullptr; + if (this->metadata[midx].second[0] != 8) + return nullptr; + size_t index = 0; + auto &bytes = this->metadata[midx].second; + + std::function parseEnt; + parseEnt = [&]() -> TObject { + if (index >= bytes.size()) + throw std::out_of_range("Abrupt end of metadata"); + switch (bytes[index++]) { + case 0: + return false; + case 1: + return true; + case 2: + return nullptr; + case 3: { + if (index + 8 <= bytes.size()) { + auto val = BitConverter::ToUint64BE(bytes[index]); + index += 8; + int64_t val2; + memcpy(&val2, &val, sizeof(val)); + return val2; + } else + throw std::out_of_range("Abrupt end of metadata"); + } break; + case 4: { + if (index + 8 <= bytes.size()) { + auto val = BitConverter::ToDoubleBE(bytes[index]); + index += 8; + return val; + } else + throw std::out_of_range("Abrupt end of metadata"); + } break; + case 5: + + if (index + 1 <= bytes.size()) { + return (char)bytes[index++]; + } else + throw std::out_of_range("Abrupt end of metadata"); + break; + case 6: { + if (index + 4 <= bytes.size()) { + auto val = BitConverter::ToUint32BE(bytes[index]); + index += 4; + return this->strings.at((size_t)val); + } else + throw std::out_of_range("Abrupt end of metadata"); + + } break; + case 7: { + if (index + 4 <= bytes.size()) { + auto val = BitConverter::ToUint32BE(bytes[index]); + index += 4; + std::vector items; + for (uint32_t i = 0; i < val; i++) { + items.push_back(parseEnt()); + } + + return TList::Create(ls, items.begin(), items.end()); + } else + throw std::out_of_range("Abrupt end of metadata"); + } break; + case 8: + if (index + 4 <= bytes.size()) { + auto val = BitConverter::ToUint32BE(bytes[index]); + index += 4; + std::vector items; + + for (uint32_t i = 0; i < val; i++) { + if (index + 4 <= bytes.size()) { + auto val2 = BitConverter::ToUint32BE(bytes[index]); + index += 4; + std::string &text = this->strings.at((size_t)val2); + items.emplace_back(text, parseEnt()); + } else + throw std::out_of_range("Abrupt end of metadata"); + } + + return TDictionary::Create(ls, items.begin(), items.end()); + } else + throw std::out_of_range("Abrupt end of metadata"); + break; + case 9: { + if (index + 4 <= bytes.size()) { + auto val = BitConverter::ToUint32BE(bytes[index]); + index += 4; + auto ba = TByteArray::Create(ls); + ba->data = this->resources.at((size_t)val); + return ba; + } else + throw std::out_of_range("Abrupt end of metadata"); + } break; + case 10: { + if (index + 4 <= bytes.size()) { + auto val = BitConverter::ToUint32BE(bytes[index]); + index += 4; + return std::make_shared(ls.GetGC(), this, val); + } else + throw std::out_of_range("Abrupt end of metadata"); + } break; + case 11: { + + auto data = parseEnt(); + TDictionary *dict; + if (GetObjectHeap(data, dict)) { + return std::make_shared(ls.GetGC(), dict); + } else + return Undefined(); + } break; + case 12: { + if (index + 4 <= bytes.size()) { + auto val = BitConverter::ToUint32BE(bytes[index]); + index += 4; + ls.GetGC()->BarrierBegin(); + auto em = TExternalMethod::Create( + ls, "", {}, + [val, this](GCList &ls, + std::vector args) -> TObject { + return std::make_shared(ls.GetGC(), this, + val); + }); + em->watch.push_back(this); + ls.GetGC()->BarrierEnd(); + + return em; + } else + throw std::out_of_range("Abrupt end of metadata"); + } break; + default: + throw std::runtime_error("Invalid metadata opcode"); + } + }; + + TDictionary *dict_res; + TObject ent = parseEnt(); + if (GetObjectHeap(ent, dict_res)) + return dict_res; + return nullptr; +} + +void TFile::Load(std::shared_ptr gc, + std::shared_ptr stream) { + + uint8_t main_header[18]; + Ensure(stream, main_header, sizeof(main_header)); + if (strncmp((const char *)main_header, "TCROSSVM", 8) != 0) + throw VMException("Invalid TCrossVM image."); + TVMVersion version(main_header + 8); + if (version.CompareToRuntime() == 1) { + throw VMException("Runtime is too old."); + } + TVMVersion v2(main_header + 13); + this->version = v2; + + size_t _len = (size_t)EnsureInt(stream); + + char table_name[4]; + + for (size_t i = 0; i < _len; i++) { + Ensure(stream, (uint8_t *)table_name, sizeof(table_name)); + size_t tableLen = (size_t)EnsureInt(stream); + if (strncmp(table_name, "NAME", 4) == 0) { + this->name = GetString(stream); + } else if (strncmp(table_name, "INFO", 4) == 0) { + this->info = GetString(stream); + } else if (strncmp(table_name, "DEPS", 4) == 0) // dependencies + { + std::string name = GetString(stream); + uint8_t version_bytes[5]; + Ensure(stream, version_bytes, sizeof(version_bytes)); + TVMVersion depVersion(version_bytes); + this->dependencies.push_back( + std::pair(name, depVersion)); + } else if (strncmp(table_name, "TOOL", 4) == + 0) // compile tools (for package manager) + { + std::string name = GetString(stream); + uint8_t version_bytes[5]; + Ensure(stream, version_bytes, sizeof(version_bytes)); + TVMVersion depVersion(version_bytes); + this->tools.push_back( + std::pair(name, depVersion)); + } else if (strncmp(table_name, "RESO", 4) == + 0) // resources (using embed) + { + auto &data = this->resources.emplace_back(tableLen); + Ensure(stream, data.data(), data.size()); + } else if (strncmp(table_name, "CHKS", 4) == 0 && + gc != nullptr) // chunks + { + GCList ls(gc); + size_t chunkCount = (size_t)EnsureInt(stream); + for (size_t j = 0; j < chunkCount; j++) { + + auto chunk = TFileChunk::Create(ls); + chunk->file = this; + size_t argCount = (size_t)EnsureInt(stream); + for (size_t k = 0; k < argCount; k++) { + chunk->args.push_back(GetString(stream)); + } + size_t len = (size_t)EnsureInt(stream); + chunk->code.resize(len); + Ensure(stream, chunk->code.data(), len); + // reader.ReadIntoBuffer(chunk->code); + + this->chunks.push_back(chunk); + } + + } else if (strncmp(table_name, "FUNS", 4) == 0) // functions + { + size_t funLength = (size_t)EnsureInt(stream); + + for (size_t j = 0; j < funLength; j++) { + std::vector fnParts; + uint32_t fnPartsC = EnsureInt(stream); + for (uint32_t k = 0; k < fnPartsC; k++) { + fnParts.push_back(GetString(stream)); + } + + uint32_t fnNumber = EnsureInt(stream); + this->functions.push_back( + std::pair, uint32_t>(fnParts, + fnNumber)); + } + + } else if (strncmp(table_name, "STRS", 4) == 0) // strings + { + size_t strsLen = (size_t)EnsureInt(stream); + for (size_t j = 0; j < strsLen; j++) { + this->strings.push_back(EnsureString(stream)); + } + } else if (strncmp(table_name, "ICON", 4) == 0) // icon + { + this->icon = (int32_t)EnsureInt(stream); + } else if (strncmp(table_name, "MACH", 4) == 0) // machine + { + std::string name = GetString(stream); + std::string howToGet = GetString(stream); + this->vms.push_back( + std::pair(name, howToGet)); + } else if (strncmp(table_name, "CLSS", 4) == 0) // classes + { + uint32_t clsCnt = EnsureInt(stream); + for (uint32_t j = 0; j < clsCnt; j++) { + TClass cls; + cls.documentation = GetString(stream); + uint32_t name_cnt = EnsureInt(stream); + for (uint32_t k = 0; k < name_cnt; k++) { + cls.name.push_back(GetString(stream)); + } + name_cnt = EnsureInt(stream); + for (uint32_t k = 0; k < name_cnt; k++) { + cls.inherits.push_back(GetString(stream)); + } + name_cnt = EnsureInt(stream); + for (uint32_t k = 0; k < name_cnt; k++) { + TClassEntry ent; + Ensure(stream, main_header, 1); + uint8_t sig = main_header[0]; + ent.isAbstract = (sig & 0b00001000) != 0; + ent.isFunction = (sig & 0b00000100) == 0; + ent.modifier = (TClassModifier)(sig & 3); + ent.documentation = GetString(stream); + ent.name = GetString(stream); + uint32_t arglen = EnsureInt(stream); + for (uint32_t l = 0; l < arglen; l++) + ent.args.push_back(GetString(stream)); + ent.chunkId = EnsureInt(stream); + cls.entry.push_back(ent); + } + this->classes.push_back(cls); + } + } else if (strncmp(table_name, "META", 4) == 0) // structured metadata + { + if (tableLen > 4) { + auto name = this->GetString(stream); + auto &data = this->metadata.emplace_back( + name, std::vector(tableLen - 4)); + Ensure(stream, data.second.data(), tableLen - 4); + } else + throw VMException("meta tag is not valid"); + + } else { + auto &data = this->sections.emplace_back( + std::string(table_name, 4), std::vector(tableLen)); + Ensure(stream, data.second.data(), tableLen); + } + } +} + +} // namespace Tesses::CrossLang diff --git a/src/vm/gc.cpp b/src/vm/gc.cpp index 6463ac6..6767cf5 100644 --- a/src/vm/gc.cpp +++ b/src/vm/gc.cpp @@ -8,270 +8,233 @@ #include #endif - using namespace Tesses::Framework::Threading; using namespace std::chrono; -namespace Tesses::CrossLang -{ +namespace Tesses::CrossLang { - bool GC::IsRunning() - { +bool GC::IsRunning() { - bool run = this->running; + bool run = this->running; - return run; - } - GC::GC() - { + return run; +} +GC::GC() {} +TDictionary *CreateThread(GCList &ls, TCallable *callable, bool detached) { - } - TDictionary* CreateThread(GCList& ls, TCallable* callable,bool detached) - { + TDictionary *dict = TDictionary::Create(ls); - TDictionary* dict = TDictionary::Create(ls); - - ThreadHandle* th = new ThreadHandle(); - th->gc = ls.GetGC(); - th->callable = callable; - th->hasInit=false; - th->hasReturned = false; - th->detached=detached; - ls.Add(th); - ls.GetGC()->Watch(th); - - ls.GetGC()->BarrierBegin(); - dict->SetValue("_internal", th); - - dict->DeclareFunction(ls.GetGC(),"Join","Join thread",{},[th](GCList& _ls, std::vector _args)-> TObject{ + ThreadHandle *th = new ThreadHandle(); + th->gc = ls.GetGC(); + th->callable = callable; + th->hasInit = false; + th->hasReturned = false; + th->detached = detached; + ls.Add(th); + ls.GetGC()->Watch(th); + ls.GetGC()->BarrierBegin(); + dict->SetValue("_internal", th); + dict->DeclareFunction( + ls.GetGC(), "Join", "Join thread", {}, + [th](GCList &_ls, std::vector _args) -> TObject { th->thrd->Join(); delete th->thrd; - if(th->hasReturned) - { + if (th->hasReturned) { _ls.GetGC()->BarrierBegin(); auto v = th->returnValue; _ls.Add(v); _ls.GetGC()->BarrierEnd(); - return v; + return v; } return Undefined(); }); - dict->DeclareFunction(ls.GetGC(), "Detach","Detach thread",{},[th](GCList& _ls, std::vector _args)-> TObject{ + dict->DeclareFunction( + ls.GetGC(), "Detach", "Detach thread", {}, + [th](GCList &_ls, std::vector _args) -> TObject { _ls.GetGC()->BarrierBegin(); - th->detached=true; + th->detached = true; _ls.GetGC()->BarrierEnd(); return Undefined(); }); - dict->DeclareFunction(ls.GetGC(),"getFinished","Get whether thread has finished",{},[th](GCList& _ls, std::vector _args)-> TObject{ - return (bool)(th->hasReturned==true); + dict->DeclareFunction( + ls.GetGC(), "getFinished", "Get whether thread has finished", {}, + [th](GCList &_ls, std::vector _args) -> TObject { + return (bool)(th->hasReturned == true); }); - ls.GetGC()->BarrierEnd(); - th->thrd =new Thread([th]()->void { - std::shared_ptr gc=th->gc; - GCList ls(gc); - ls.Add(th); - th->hasInit=true; - TObject cb = th->callable->Call(ls,{}); - gc->BarrierBegin(); - th->returnValue=cb; - gc->BarrierEnd(); - th->hasReturned=true; - }); - while(!th->hasInit); - return dict; - } - void GC::Start() - { + ls.GetGC()->BarrierEnd(); + th->thrd = new Thread([th]() -> void { + std::shared_ptr gc = th->gc; + GCList ls(gc); + ls.Add(th); + th->hasInit = true; + TObject cb = th->callable->Call(ls, {}); + gc->BarrierBegin(); + th->returnValue = cb; + gc->BarrierEnd(); + th->hasReturned = true; + }); + while (!th->hasInit) + ; + return dict; +} +void GC::Start() { - this->tpool=new Tesses::Framework::Lazy([]()->Tesses::Framework::Threading::ThreadPool*{ - auto threads = Tesses::Framework::Threading::ThreadPool::GetNumberOfCores(); - if(threads < 4) threads=4; + this->tpool = new Tesses::Framework::Lazy< + Tesses::Framework::Threading::ThreadPool *>( + []() -> Tesses::Framework::Threading::ThreadPool * { + auto threads = + Tesses::Framework::Threading::ThreadPool::GetNumberOfCores(); + if (threads < 4) + threads = 4; return new Tesses::Framework::Threading::ThreadPool(threads); - },[](Tesses::Framework::Threading::ThreadPool* p)->void{delete p;}); - this->mtx=new Mutex(); - this->running = true; - this->thrd = new Thread([this]()->void { - std::chrono::time_point last_frame, this_frame; + }, + [](Tesses::Framework::Threading::ThreadPool *p) -> void { delete p; }); + this->mtx = new Mutex(); + this->running = true; + this->thrd = new Thread([this]() -> void { + std::chrono::time_point last_frame, + this_frame; this_frame = system_clock::now(); last_frame = this_frame; - while(this->IsRunning()) - { + while (this->IsRunning()) { this_frame = system_clock::now(); - if((this_frame - last_frame) > 10s) - { - + if ((this_frame - last_frame) > 10s) { last_frame = this_frame; this->Collect(); - - } - #if defined(_WIN32) +#if defined(_WIN32) Sleep(100); - #else +#else usleep(100000); - #endif +#endif } GC::Collect(); - }); - } + }); +} - bool GC::UsingNullThreads() - { - return false; - } +bool GC::UsingNullThreads() { return false; } - void GC::BarrierBegin() - { - - this->mtx->Lock(); - } - void GC::BarrierEnd() - { - - this->mtx->Unlock(); - - } - void GC::Watch(TObject obj) - { - if(std::holds_alternative(obj)) - { - auto _item=std::get(obj).obj; - this->BarrierBegin(); - - for(auto item : this->objects) - { - if(item == _item) { - this->BarrierEnd(); - return; - } - } - this->objects.push_back(_item); - this->BarrierEnd(); - } - } - void GC::Mark(TObject obj) - { - if(std::holds_alternative(obj)) - { - auto _item=std::get(obj).obj; - _item->Mark(); - } - } - void GC::Unwatch(TObject obj) - { - if(std::holds_alternative(obj)) - { - auto _item=std::get(obj).obj; - this->BarrierBegin(); - for(auto index = this->objects.begin();indexobjects.end();index++) - { - if(*index == _item) - { - this->objects.erase(index); - continue; - } - } - this->BarrierEnd(); - } - } - void GC::SetRoot(TObject obj) - { - if(std::holds_alternative(obj)) - { - auto _item=std::get(obj).obj; - this->BarrierBegin(); - - for(auto item : this->roots) - { - if(item == _item) { - this->BarrierEnd(); - return; - } - } - this->roots.push_back(_item); - this->BarrierEnd(); - } - } - Tesses::Framework::Threading::ThreadPool* GC::GetPool() - { - return this->tpool->GetValue(); - } - - void GC::UnsetRoot(TObject obj) - { - if(std::holds_alternative(obj)) - { - auto _item=std::get(obj).obj; - this->BarrierBegin(); - for(auto index = this->roots.begin();indexroots.end();index++) - { - if(*index == _item) - { - this->roots.erase(index); - continue; - } - } - this->BarrierEnd(); - } - } - - GC::~GC() - { - GC::BarrierBegin(); - - this->roots.clear(); - GC::BarrierEnd(); - - - - this->running=false; - this->thrd->Join(); - delete this->thrd; - for(auto item : objects) delete item; - - delete this->tpool; - delete this->mtx; - } - - void GC::RegisterEverythingCallback(std::function gc, TRootEnvironment* env)> cb) - { - this->register_everything.push_back(cb); - } - void GC::RegisterEverything(TRootEnvironment* env) - { - for(auto item : this->register_everything) - item(this->shared_from_this(),env); - } - void GC::Collect() - { +void GC::BarrierBegin() { this->mtx->Lock(); } +void GC::BarrierEnd() { this->mtx->Unlock(); } +void GC::Watch(TObject obj) { + if (std::holds_alternative(obj)) { + auto _item = std::get(obj).obj; this->BarrierBegin(); - for(auto item : this->objects) - { - item->marked=false; - } - for(auto item : this->roots) - { - item->Mark(); - } - for(auto index = this->objects.begin();index < this->objects.end();index++) - { - THeapObject* o = *index; - if(!o->marked) - { - delete o; - this->objects.erase(index); - index--; + + for (auto item : this->objects) { + if (item == _item) { + this->BarrierEnd(); + return; } } + this->objects.push_back(_item); + this->BarrierEnd(); + } +} +void GC::Mark(TObject obj) { + if (std::holds_alternative(obj)) { + auto _item = std::get(obj).obj; + _item->Mark(); + } +} +void GC::Unwatch(TObject obj) { + if (std::holds_alternative(obj)) { + auto _item = std::get(obj).obj; + this->BarrierBegin(); + for (auto index = this->objects.begin(); + index != this->objects.end();) { + if (*index == _item) { + index = this->objects.erase(index); + continue; + } + index++; + } this->BarrierEnd(); - } -}; +} +void GC::SetRoot(TObject obj) { + if (std::holds_alternative(obj)) { + auto _item = std::get(obj).obj; + this->BarrierBegin(); + + for (auto item : this->roots) { + if (item == _item) { + this->BarrierEnd(); + return; + } + } + this->roots.push_back(_item); + this->BarrierEnd(); + } +} +Tesses::Framework::Threading::ThreadPool *GC::GetPool() { + return this->tpool->GetValue(); +} + +void GC::UnsetRoot(TObject obj) { + if (std::holds_alternative(obj)) { + auto _item = std::get(obj).obj; + this->BarrierBegin(); + for (auto index = this->roots.begin(); index != this->roots.end();) { + if (*index == _item) { + index = this->roots.erase(index); + continue; + } + index++; + } + this->BarrierEnd(); + } +} + +GC::~GC() { + GC::BarrierBegin(); + + this->roots.clear(); + GC::BarrierEnd(); + + this->running = false; + this->thrd->Join(); + delete this->thrd; + for (auto item : objects) + delete item; + + delete this->tpool; + delete this->mtx; +} + +void GC::RegisterEverythingCallback( + std::function gc, TRootEnvironment *env)> cb) { + this->register_everything.push_back(cb); +} +void GC::RegisterEverything(TRootEnvironment *env) { + for (auto item : this->register_everything) + item(this->shared_from_this(), env); +} +void GC::Collect() { + this->BarrierBegin(); + for (auto item : this->objects) { + item->marked = false; + } + for (auto item : this->roots) { + item->Mark(); + } + for (auto index = this->objects.begin(); index != this->objects.end(); + index++) { + THeapObject *o = *index; + if (!o->marked) { + delete o; + this->objects.erase(index); + index--; + } + } + this->BarrierEnd(); +} +}; // namespace Tesses::CrossLang diff --git a/src/vm/gclist.cpp b/src/vm/gclist.cpp index 8ddbf03..b087cbd 100644 --- a/src/vm/gclist.cpp +++ b/src/vm/gclist.cpp @@ -1,67 +1,53 @@ #include "CrossLang.hpp" -namespace Tesses::CrossLang -{ - GCList::GCList(std::shared_ptr gc) - { - gc->BarrierBegin(); - this->gc = gc; - gc->SetRoot(this); - gc->BarrierEnd(); - } - - std::shared_ptr GCList::GetGC() - { - return this->gc; - } - void GCList::Remove(TObject obj) - { - if(std::holds_alternative(obj)) - { - auto _item=std::get(obj).obj; - this->gc->BarrierBegin(); - for(auto index = this->items.begin();indexitems.end();index++) - { - if(*index == _item) - { - this->items.erase(index); - continue; - } - } - this->gc->BarrierEnd(); - } - } - void GCList::Add(TObject obj) - { +namespace Tesses::CrossLang { +GCList::GCList(std::shared_ptr gc) { + gc->BarrierBegin(); + this->gc = gc; + gc->SetRoot(this); + gc->BarrierEnd(); +} - if(std::holds_alternative(obj)) - { - auto _item=std::get(obj).obj; - this->gc->BarrierBegin(); - - for(auto item : this->items) - { - if(item == _item) { - this->gc->BarrierEnd(); - return; - } +std::shared_ptr GCList::GetGC() { return this->gc; } +void GCList::Remove(TObject obj) { + if (std::holds_alternative(obj)) { + auto _item = std::get(obj).obj; + this->gc->BarrierBegin(); + for (auto index = this->items.begin(); index != this->items.end(); + index++) { + if (*index == _item) { + this->items.erase(index); + continue; } - this->items.push_back(_item); - this->gc->BarrierEnd(); } - } - void GCList::Mark() - { - this->marked=true; - for(auto item : this->items) - { - item->Mark(); - } - } - GCList::~GCList() - { - gc->BarrierBegin(); - this->gc->UnsetRoot(this); - gc->BarrierEnd(); + this->gc->BarrierEnd(); } } +void GCList::Add(TObject obj) { + + if (std::holds_alternative(obj)) { + auto _item = std::get(obj).obj; + this->gc->BarrierBegin(); + + for (auto item : this->items) { + if (item == _item) { + this->gc->BarrierEnd(); + return; + } + } + this->items.push_back(_item); + this->gc->BarrierEnd(); + } +} +void GCList::Mark() { + this->marked = true; + for (auto item : this->items) { + item->Mark(); + } +} +GCList::~GCList() { + gc->BarrierBegin(); + this->gc->UnsetRoot(this); + gc->BarrierEnd(); +} +} // namespace Tesses::CrossLang diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 01372c4..f3ed6db 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -2,3498 +2,2987 @@ #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" +#include #include +#include #include #include -#include -#include #include #include - namespace Tesses::CrossLang { - - thread_local CallStackEntry* current_function=nullptr; +thread_local CallStackEntry *current_function = nullptr; - +TObject ExecuteFunction(GCList &ls, TCallable *callable, + std::vector args) { + return callable->Call(ls, args); +} - - TObject ExecuteFunction(GCList& ls,TCallable* callable, std::vector args) - { - return callable->Call(ls,args); +void InterperterThread::Mark() { + if (this->marked) + return; + this->marked = true; + for (auto item : this->call_stack_entries) { + item->Mark(); } - - void InterperterThread::Mark() - { - if(this->marked) return; - this->marked=true; - for(auto item : this->call_stack_entries) - { - item->Mark(); - } +} + +#define TVM_HANDLER(hndl) \ + if (hndl(gc)) \ + goto execute + +typedef bool (InterperterThread::*opcode)(std::shared_ptr gc); + +bool InterperterThread::InterperterThread::Breakpoint(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto res = cse.back()->Pop(ls); + + auto env = cse.back()->env; + if (!env->GetRootEnvironment()->HandleBreakpoint(gc, env, res)) { + throw std::runtime_error("Breakpoint unhandled"); } - #define TVM_HANDLER(hndl) if(hndl(gc)) goto execute + return false; +} - typedef bool (InterperterThread::*opcode)(std::shared_ptr gc); +bool InterperterThread::PushPrivateExpression(std::shared_ptr gc) { - bool InterperterThread::InterperterThread::Breakpoint(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto res = cse.back()->Pop(ls); - - auto env = cse.back()->env; - if(!env->GetRootEnvironment()->HandleBreakpoint(gc, env, res)) - { - throw std::runtime_error("Breakpoint unhandled"); - } - - return false; + std::vector &cse = this->call_stack_entries; + auto fn = cse.back(); + auto re = fn->env->GetRootEnvironment(); + if (re) { + fn->Push(gc, re->GetPrivateFromFile(gc, fn->callable->file)); + } else { + throw VMException("No root environment for private expression"); } - - bool InterperterThread::Times(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); + return false; +} - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) * std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) * std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) * std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) * std::get(right)); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); +bool InterperterThread::Times(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - - - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator*"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator*",{right})); + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) * std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) * std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) * std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) * std::get(right)); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator*"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); return false; } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator*"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator*",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator*", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator*"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator*", {right})); + return false; + } else { cse.back()->Push(gc, Undefined()); } - - return false; + + } else { + cse.back()->Push(gc, Undefined()); } - bool InterperterThread::Divide(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,Tesses::Framework::Filesystem::VFSPath(std::get(left)) / std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) / std::get(right)); - - } + return false; +} +bool InterperterThread::Divide(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, Tesses::Framework::Filesystem::VFSPath( + std::get(left)) / + std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative( + right)) { + cse.back()->Push( + gc, std::get(left) / + std::get(right)); - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) / std::get(right)); - - } + } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) / std::get(right)); - - } + else if (std::holds_alternative( + left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, std::get(left) / + std::get(right)); - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) / std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) / std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) / std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) / std::get(right)); - } + } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); + else if (std::holds_alternative( + left) && + std::holds_alternative( + right)) { + cse.back()->Push( + gc, std::get(left) / + std::get(right)); - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator/"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator/",{right})); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) / std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) / std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) / std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) / std::get(right)); + } + + else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator/"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); return false; } - else - - - if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator/",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator/"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator/",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator/", {right})); + return false; + } else + + if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator/", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator/"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator/", {right})); + return false; + } else { cse.back()->Push(gc, Undefined()); } - return false; + + } else { + cse.back()->Push(gc, Undefined()); } - bool InterperterThread::Mod(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); + return false; +} +bool InterperterThread::Mod(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) % std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,fmod(std::get(left), std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,fmod(std::get(left), std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,fmod(std::get(left), std::get(right))); - } + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) % std::get(right)); + } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + fmod(std::get(left), std::get(right))); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, fmod(std::get(left), std::get(right))); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push( + gc, fmod(std::get(left), std::get(right))); + } - auto dynDict = dynamic_cast(obj); + else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - - - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator%"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator%",{right})); + auto dynDict = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator%"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); return false; } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator%"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator%",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator%", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator%"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator%", {right})); + return false; + } else { cse.back()->Push(gc, Undefined()); } - - return false; + + } else { + cse.back()->Push(gc, Undefined()); } - bool InterperterThread::Neg(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto left = cse.back()->Pop(ls); - if(std::holds_alternative(left)) - { - cse.back()->Push(gc,-std::get(left)); - } - else if(std::holds_alternative(left)) - { - cse.back()->Push(gc,-std::get(left)); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - - auto natObj = dynamic_cast(obj); - - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator-"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator-",{})); + return false; +} +bool InterperterThread::Neg(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left)) { + cse.back()->Push(gc, -std::get(left)); + } else if (std::holds_alternative(left)) { + cse.back()->Push(gc, -std::get(left)); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator-"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {})); return false; } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject negfn = dict->GetValue("operator-"); - gc->BarrierEnd(); - return InvokeOne(ls,negfn,left); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator-",{})); - return false; - } - else - { - cse.back()->Push(gc,nullptr); - } - + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator-", {})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject negfn = dict->GetValue("operator-"); + gc->BarrierEnd(); + return InvokeOne(ls, negfn, left); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator-", {})); + return false; + } else { + cse.back()->Push(gc, nullptr); } - else - { - cse.back()->Push(gc,nullptr); - } - - return false; + + } else { + cse.back()->Push(gc, nullptr); } - bool InterperterThread::LNot(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto left = cse.back()->Pop(ls); - if(std::holds_alternative(left)) - { - cse.back()->Push(gc,true); - } - else if(std::holds_alternative(left)) - { - cse.back()->Push(gc,true); + return false; +} +bool InterperterThread::LNot(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left)) { + cse.back()->Push(gc, true); + } else if (std::holds_alternative(left)) { + cse.back()->Push(gc, true); + } + + else if (std::holds_alternative(left)) { + cse.back()->Push(gc, !std::get(left)); + } + + else if (std::holds_alternative(left)) { + cse.back()->Push(gc, !std::get(left)); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator!"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, !natObj->ToBool()); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject negfn = dict->GetValue("operator!"); + gc->BarrierEnd(); + return InvokeOne(ls, negfn, left); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator!", {})); + return false; } - else if(std::holds_alternative(left)) - { - cse.back()->Push(gc,!std::get(left)); - } - - else if(std::holds_alternative(left)) - { - cse.back()->Push(gc,!std::get(left)); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator!"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc, !natObj->ToBool()); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject negfn = dict->GetValue("operator!"); - gc->BarrierEnd(); - return InvokeOne(ls,negfn,left); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator!",{})); - return false; - } - - else - { - cse.back()->Push(gc, !ToBool(left)); - } - - } - else - { + else { cse.back()->Push(gc, !ToBool(left)); } - - return false; + + } else { + cse.back()->Push(gc, !ToBool(left)); } - bool InterperterThread::BNot(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto left = cse.back()->Pop(ls); - if(std::holds_alternative(left)) - { - cse.back()->Push(gc,~std::get(left)); - } - + return false; +} +bool InterperterThread::BNot(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto left = cse.back()->Pop(ls); - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator~"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator~",{})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject negfn = dict->GetValue("operator~"); - gc->BarrierEnd(); - return InvokeOne(ls,negfn,left); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator~",{})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; + if (std::holds_alternative(left)) { + cse.back()->Push(gc, ~std::get(left)); } - bool InterperterThread::Lt(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) < std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) < std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) < std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) < std::get(right)); - } + else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) < std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) < std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) < std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto lver= std::get(left); - auto rver = std::get(right); - auto r = lver.CompareTo(rver); - cse.back()->Push(gc, r < 0); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, std::get(left) < std::get(right)); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->ToEpoch() < r->ToEpoch()); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->TotalSeconds() < r->TotalSeconds()); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator<"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator<",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator<"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator<",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::Gt(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) > std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) > std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) > std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) > std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) > std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) > std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) > std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto lver= std::get(left); - auto rver = std::get(right); - auto r = lver.CompareTo(rver); - cse.back()->Push(gc, r > 0); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, std::get(left) > std::get(right)); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->ToEpoch() > r->ToEpoch()); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->TotalSeconds() > r->TotalSeconds()); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator>"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator>",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator>"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator>",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::Lte(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) <= std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) <= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) <= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) <= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) <= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) <= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) <= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto lver= std::get(left); - auto rver = std::get(right); - auto r = lver.CompareTo(rver); - cse.back()->Push(gc, r <= 0); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, std::get(left) <= std::get(right)); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->ToEpoch() <= r->ToEpoch()); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->TotalSeconds() <= r->TotalSeconds()); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator<="); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator<=",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator<="); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator<=",{right})); - return false; - } - - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::Gte(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) >= std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) >= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) >= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) >= std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) >= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) >= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) >= std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto lver= std::get(left); - auto rver = std::get(right); - auto r = lver.CompareTo(rver); - cse.back()->Push(gc, r >= 0); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, std::get(left) >= std::get(right)); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->ToEpoch() >= r->ToEpoch()); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->TotalSeconds() >= r->TotalSeconds()); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator>="); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator>=",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator>="); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator>=",{right})); - return false; - } - - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::Eq(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,true); - return false; - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,true); - return false; - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) == std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto lver= std::get(left); - auto rver = std::get(right); - auto r = lver.CompareTo(rver); - cse.back()->Push(gc, r == 0); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto l= std::get(left); - auto r = std::get(right); - - return l == r; - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,(l->ToEpoch() == r->ToEpoch()) && (l->IsLocal() == r->IsLocal())); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->TotalSeconds() == r->TotalSeconds()); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto native = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator=="); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->Equals(gc,right)); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator=="); - gc->BarrierEnd(); - if(!std::holds_alternative(fn)) - return InvokeTwo(ls,fn,left,right); - - } - - else if(dynDict != nullptr) - { - auto res = dynDict->CallMethod(ls,"operator==",{right}); - if(!std::holds_alternative(res) && std::holds_alternative(res)) - { - cse.back()->Push(gc,res); - return false; - } - } - - else if(native != nullptr && std::holds_alternative(right)){ - cse.back()->Push(gc, native->GetDestroyed()); - return false; - } - - if(std::holds_alternative(right)) - { - cse.back()->Push(gc,obj == std::get(right).obj); - return false; - } - - else if(std::holds_alternative(right)) - { - cse.back()->Push(gc, false); - return false; - } - else if(std::holds_alternative(right)) - { - cse.back()->Push(gc, false); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - - else if(std::holds_alternative(right)) - { - cse.back()->Push(gc, false); - return false; - } - else if(std::holds_alternative(right)) - { - cse.back()->Push(gc, false); - return false; - } - else - { - cse.back()->Push(gc, Undefined()); - - } - - return false; - } - bool InterperterThread::NEq(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,false); - return false; - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,false); - return false; - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) != std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto lver= std::get(left); - auto rver = std::get(right); - auto r = lver.CompareTo(rver); - cse.back()->Push(gc, r != 0); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto l= std::get(left); - auto r = std::get(right); - - return l != r; - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,!((l->ToEpoch() == r->ToEpoch()) && (l->IsLocal() == r->IsLocal()))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,l->TotalSeconds() != r->TotalSeconds()); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - auto native = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator!="); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc, !natObj->Equals(gc,right)); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator!="); - gc->BarrierEnd(); - if(!std::holds_alternative(fn)) - return InvokeTwo(ls,fn,left,right); - } - - else if(dynDict != nullptr) - { - - auto res = dynDict->CallMethod(ls,"operator!=",{right}); - if(!std::holds_alternative(res) && std::holds_alternative(res)) - { - cse.back()->Push(gc,res); - return false; - } - } - - else if(native != nullptr && std::holds_alternative(right)){ - cse.back()->Push(gc, !native->GetDestroyed()); - return false; - } - if(std::holds_alternative(right)) - { - cse.back()->Push(gc,obj != std::get(right).obj); - return false; - } - else if(std::holds_alternative(right)) - { - cse.back()->Push(gc, true); - return false; - } - else if(std::holds_alternative(right)) - { - cse.back()->Push(gc, true); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - - } - - } - else if(std::holds_alternative(right)) - { - cse.back()->Push(gc, true); - return false; - } - else if(std::holds_alternative(right)) - { - cse.back()->Push(gc, true); - return false; - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::LShift(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) << (int)std::get(right)); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator<<"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator<<",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator<<"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator<<",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::RShift(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) >> (int)std::get(right)); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator>>"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator>>",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator>>"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator>>",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::BOr(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) | std::get(right)); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator|"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator|",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator|"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator|",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::XOr(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) ^ std::get(right)); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator^"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator^",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator^"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator^",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::BAnd(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) & std::get(right)); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator&"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator&",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator&"); - gc->BarrierEnd(); - return InvokeTwo(ls,fn,left,right); - } - else if(dynDict != nullptr) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"operator&",{right})); - return false; - } - else - { - cse.back()->Push(gc,Undefined()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::InvokeOne(GCList& ls, TObject fn, TObject arg) - { - if(std::holds_alternative(fn)) - { - - auto obj = dynamic_cast(std::get(fn).obj); - if(obj != nullptr) - { - auto closure = dynamic_cast(obj); - if(closure != nullptr) - { - - if(!closure->closure->args.empty() && closure->closure->args[0] == "this") - { - this->AddCallStackEntry(ls,closure,{arg}); - } - else - { - this->AddCallStackEntry(ls,closure,{}); - } - - } - else - { - auto val = obj->Call(ls,{}); - this->call_stack_entries.back()->Push(ls.GetGC(), val); - return false; - } - return true; - } - - } - return false; - } - - bool InterperterThread::ExecuteFunction(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - GCList ls(gc); - auto res = stk->Pop(ls); - - - if(std::holds_alternative(res)) - { - uint32_t n=(uint32_t)std::get(res); - - - std::vector args; - - for(size_t i = 0;iPop(ls)}); - } - - - - TObject fn = stk->Pop(ls); - if(std::holds_alternative(fn)) - { - if(args.size() == 3) - { - - if(std::holds_alternative(args[1]) && std::holds_alternative(args[2])) - { - std::string key = std::get(args[1]); - TList* ls = dynamic_cast(std::get(args[2]).obj); - if(ls != nullptr) - return ExecuteMethod2(gc,args[0],key,ls->items); - } - } - stk->Push(gc, Undefined()); - return false; - } - - if(std::holds_alternative(fn)) - { - - auto obj = dynamic_cast(std::get(fn).obj); - if(obj != nullptr) - { - auto closure = dynamic_cast(obj); - if(closure != nullptr) - { - - this->AddCallStackEntry(ls,closure,args); - return true; - } - else - { - - auto val = obj->Call(ls,args); - this->call_stack_entries.back()->Push(ls.GetGC(), val); - - return false; - } - return true; - } - stk->Push(gc,Undefined()); - return false; - } - stk->Push(gc, Undefined()); - } - else - stk->Push(gc, Undefined()); - } - return false; - } - - bool InterperterThread::Yield(std::shared_ptr gc) - { - GCList ls(gc); - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { + if (cls != nullptr) { gc->BarrierBegin(); - cse.back()->mustReturn=true; - cse.back()->Push(gc, cse.back()); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator~"); gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator~", {})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject negfn = dict->GetValue("operator~"); + gc->BarrierEnd(); + return InvokeOne(ls, negfn, left); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator~", {})); + return false; + } else { + cse.back()->Push(gc, Undefined()); } - return false; - } - bool InterperterThread::ExecuteMethod(std::shared_ptr gc) - { - GCList ls(gc); - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - - auto cnt = stk->Pop(ls); - if(std::holds_alternative(cnt)) - { - uint32_t n=(uint32_t)std::get(cnt); - - std::vector args; - - for(size_t i = 0;iPop(ls)}); - } - - - TObject key = stk->Pop(ls); - TObject instance = stk->Pop(ls); - - if(std::holds_alternative(key)) - { - return ExecuteMethod2(gc,instance,std::get(key),args); - } - stk->Push(gc, Undefined()); - return false; - } - } - return false; - } - - bool InterperterThread::GetVariable(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - GCList ls(gc); - auto key = stk->Pop(ls); - if(std::holds_alternative(key)) - { - gc->BarrierBegin(); - stk->Push(gc, - stk->env->GetVariable(ls,std::get(key))); - gc->BarrierEnd(); - } - else - { - throw VMException("[GETVARIABLE] Can't pop string."); - } - } - return false; - } - bool InterperterThread::SetVariable(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - GCList ls(gc); - auto value = stk->Pop(ls); - auto key = stk->Pop(ls); - TList* mls; - if(std::holds_alternative(key)) - { - gc->BarrierBegin(); - - if(stk->env->HasConstForSet(std::get(key))) - { - gc->BarrierEnd(); - ThrowConstError(std::get(key)); - } - stk->Push(gc,stk->env->SetVariable(ls,std::get(key),value)); - - gc->BarrierEnd(); - } - else if(GetObjectHeap(key,mls)) - { - gc->BarrierBegin(); - - TList* valueLs; - TDynamicList* valueDynList; - TDictionary* valueDict; - TDynamicDictionary* valueDynDict; - if(GetObjectHeap(value, valueLs)) - { - TDictionary* result = TDictionary::Create(ls); - int64_t len = std::min(valueLs->Count(), mls->Count()); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - auto val = valueLs->Get(i); - result->SetValue(mkey, val); - - if(stk->env->HasConstForSet(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->SetVariable(ls,mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDynList)) - { - TDictionary* result = TDictionary::Create(ls); - gc->BarrierEnd(); - int64_t len = std::min(valueDynList->Count(ls), mls->Count()); - gc->BarrierBegin(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - gc->BarrierEnd(); - auto val = valueDynList->GetAt(ls,i); - gc->BarrierBegin(); - result->SetValue(mkey, val); - - if(stk->env->HasConstForSet(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->SetVariable(ls,mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDict)) - { - - TDictionary* result = TDictionary::Create(ls); - int64_t len = mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - auto val = valueDict->GetValue(mkey); - result->SetValue(mkey, val); - - if(stk->env->HasConstForSet(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->SetVariable(ls,mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDynDict)) - { - TDictionary* result = TDictionary::Create(ls); - int64_t len =mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - gc->BarrierEnd(); - auto val = valueDynDict->GetField(ls,mkey); - gc->BarrierBegin(); - - result->SetValue(mkey, val); - - if(stk->env->HasConstForSet(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->SetVariable(ls,mkey,val); - } - } - stk->Push(gc,result); - } - else { - int64_t len =mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - if(stk->env->HasConstForSet(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - - stk->env->SetVariable(ls,mkey, value); - } - } - stk->Push(gc, value); - } - gc->BarrierEnd(); - } - else - { - throw VMException("[SETVARIABLE] Can't pop string."); - } - } - return false; - } - bool InterperterThread::DeclareVariable(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - GCList ls(gc); - - auto value = stk->Pop(ls); - auto key = stk->Pop(ls); - - TList* mls; - - if(std::holds_alternative(key)) - { - gc->BarrierBegin(); - if(stk->env->HasConstForDeclare(std::get(key))) - { - gc->BarrierEnd(); - ThrowConstError(std::get(key)); - } - stk->env->DeclareVariable(std::get(key),value); - stk->Push(gc, value); - gc->BarrierEnd(); - } - else if(GetObjectHeap(key,mls)) - { - gc->BarrierBegin(); - - TList* valueLs; - TDynamicList* valueDynList; - TDictionary* valueDict; - TDynamicDictionary* valueDynDict; - if(GetObjectHeap(value, valueLs)) - { - TDictionary* result = TDictionary::Create(ls); - int64_t len = std::min(valueLs->Count(), mls->Count()); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - auto val = valueLs->Get(i); - result->SetValue(mkey, val); - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareVariable(mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDynList)) - { - TDictionary* result = TDictionary::Create(ls); - gc->BarrierEnd(); - int64_t len = std::min(valueDynList->Count(ls), mls->Count()); - gc->BarrierBegin(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - gc->BarrierEnd(); - auto val = valueDynList->GetAt(ls,i); - gc->BarrierBegin(); - result->SetValue(mkey, val); - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareVariable(mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDict)) - { - - TDictionary* result = TDictionary::Create(ls); - int64_t len = mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - auto val = valueDict->GetValue(mkey); - result->SetValue(mkey, val); - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareVariable(mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDynDict)) - { - TDictionary* result = TDictionary::Create(ls); - int64_t len =mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - gc->BarrierEnd(); - auto val = valueDynDict->GetField(ls,mkey); - gc->BarrierBegin(); - - result->SetValue(mkey, val); - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareVariable(mkey,val); - } - } - stk->Push(gc,result); - } - else { - int64_t len =mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareVariable(mkey, value); - } - } - stk->Push(gc, value); - } - gc->BarrierEnd(); - } - else - { - - throw VMException("[DECLAREVARIABLE] Can't pop string, got type " + GetObjectTypeString(key) + " = " + ToString(gc,key) + "."); - } - } - return false; - } - - - bool InterperterThread::DeclareConstVariable(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - GCList ls(gc); - - auto value = stk->Pop(ls); - auto key = stk->Pop(ls); - - TList* mls; - - if(std::holds_alternative(key)) - { - gc->BarrierBegin(); - if(stk->env->HasConstForDeclare(std::get(key))) - { - gc->BarrierEnd(); - ThrowConstError(std::get(key)); - } - stk->env->DeclareConstVariable(std::get(key),value); - stk->Push(gc, value); - gc->BarrierEnd(); - } - else if(GetObjectHeap(key,mls)) - { - gc->BarrierBegin(); - - TList* valueLs; - TDynamicList* valueDynList; - TDictionary* valueDict; - TDynamicDictionary* valueDynDict; - if(GetObjectHeap(value, valueLs)) - { - TDictionary* result = TDictionary::Create(ls); - int64_t len = std::min(valueLs->Count(), mls->Count()); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - auto val = valueLs->Get(i); - result->SetValue(mkey, val); - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareConstVariable(mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDynList)) - { - TDictionary* result = TDictionary::Create(ls); - gc->BarrierEnd(); - int64_t len = std::min(valueDynList->Count(ls), mls->Count()); - gc->BarrierBegin(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - gc->BarrierEnd(); - auto val = valueDynList->GetAt(ls,i); - gc->BarrierBegin(); - result->SetValue(mkey, val); - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareConstVariable(mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDict)) - { - - TDictionary* result = TDictionary::Create(ls); - int64_t len = mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - auto val = valueDict->GetValue(mkey); - result->SetValue(mkey, val); - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareConstVariable(mkey,val); - } - } - stk->Push(gc,result); - } - else if(GetObjectHeap(value, valueDynDict)) - { - TDictionary* result = TDictionary::Create(ls); - int64_t len =mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - gc->BarrierEnd(); - auto val = valueDynDict->GetField(ls,mkey); - gc->BarrierBegin(); - - result->SetValue(mkey, val); - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareConstVariable(mkey,val); - } - } - stk->Push(gc,result); - } - else { - int64_t len =mls->Count(); - for(int64_t i = 0; i < len; i++) - { - std::string mkey; - auto item = mls->Get(i); - if(GetObject(item,mkey)) - { - if(stk->env->HasConstForDeclare(mkey)) - { - gc->BarrierEnd(); - ThrowConstError(mkey); - } - stk->env->DeclareConstVariable(mkey, value); - } - } - stk->Push(gc, value); - } - gc->BarrierEnd(); - } - else - { - - throw VMException("[DECLARECONSTVARIABLE] Can't pop string, got type " + GetObjectTypeString(key) + " = " + ToString(gc,key) + "."); - } - } - return false; - } - bool InterperterThread::PushResourceStream(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - if(stk->ip + 4 <= code.size()) - { - uint32_t n=BitConverter::ToUint32BE(code[stk->ip]); - if(n >= stk->callable->file->resources.size()) - throw VMException("Can't read resource."); - stk->ip = stk->ip + 4; - - gc->BarrierBegin(); - GCList ls(gc); - // TByteArray* arr = TByteArray::Create(ls); -// arr->data = stk->callable->file->resources[n]; - stk->Push(gc, std::make_shared(gc,stk->callable->file,n)); - - gc->BarrierEnd(); - } - else - { - throw VMException("Can't read chunk."); - } - } - return false; + } else { + cse.back()->Push(gc, Undefined()); } - bool InterperterThread::PushResource(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - if(stk->ip + 4 <= code.size()) - { - uint32_t n=BitConverter::ToUint32BE(code[stk->ip]); - if(n >= stk->callable->file->resources.size()) - throw VMException("Can't read resource."); - stk->ip = stk->ip + 4; + return false; +} +bool InterperterThread::Lt(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); - gc->BarrierBegin(); - GCList ls(gc); - TByteArray* arr = TByteArray::Create(ls); - arr->data = stk->callable->file->resources[n]; - stk->Push(gc, arr); - - gc->BarrierEnd(); - } - else - { - throw VMException("Can't read chunk."); - } - } - return false; + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) < std::get(right)); } - bool InterperterThread::Throw(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto _res2 = cse.back()->Pop(ls); - if(!std::holds_alternative(_res2)) - { - auto env = cse.back()->env; - if(!env->GetRootEnvironment()->HandleException(gc,env, _res2)) - throw VMByteCodeException(gc,_res2,cse.back()); - } - return false; + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) < std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) < std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) < std::get(right)); } - bool InterperterThread::PushResourceDirectory(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto _res2 = cse.back()->Pop(ls); - TDictionary* dict; - if(GetObjectHeap(_res2, dict)) - { - cse.back()->Push(gc, std::make_shared(gc,dict)); + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) < std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) < std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) < std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto lver = std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + cse.back()->Push(gc, r < 0); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) < + std::get(right)); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->ToEpoch() < r->ToEpoch()); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->TotalSeconds() < r->TotalSeconds()); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator<"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator<", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator<"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator<", {right})); + return false; + } else { + cse.back()->Push(gc, Undefined()); } + + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::Gt(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) > std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) > std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) > std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) > std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) > std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) > std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) > std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto lver = std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + cse.back()->Push(gc, r > 0); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) > + std::get(right)); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->ToEpoch() > r->ToEpoch()); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->TotalSeconds() > r->TotalSeconds()); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator>"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator>", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator>"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator>", {right})); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::Lte(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) <= std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) <= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) <= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) <= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) <= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) <= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) <= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto lver = std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + cse.back()->Push(gc, r <= 0); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) <= + std::get(right)); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->ToEpoch() <= r->ToEpoch()); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->TotalSeconds() <= r->TotalSeconds()); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator<="); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator<=", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator<="); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, + dynDict->CallMethod(ls, "operator<=", {right})); + return false; + } + else { cse.back()->Push(gc, Undefined()); } - return false; - } - bool InterperterThread::JumpIfDefined(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - if(stk->ip + 4 <= stk->callable->closure->code.size()) - { - uint32_t n=BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); - - GCList ls(gc); - auto _res2 = stk->Pop(ls); - - stk->ip = stk->ip + 4; - if(!std::holds_alternative(_res2) && !std::holds_alternative(_res2)) - { - stk->ip = n; - stk->Push(gc,_res2); + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::Gte(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) >= std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) >= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) >= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) >= std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) >= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) >= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) >= std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto lver = std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + cse.back()->Push(gc, r >= 0); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) >= + std::get(right)); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->ToEpoch() >= r->ToEpoch()); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->TotalSeconds() >= r->TotalSeconds()); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator>="); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; } - - - } - else - throw VMException("Can't read jmpifdefined pc."); - return false; - } - bool InterperterThread::JumpIfBreak(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - if(stk->ip + 4 <= stk->callable->closure->code.size()) - { - uint32_t n=BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); - - GCList ls(gc); - auto _res2 = stk->Pop(ls); - - stk->ip = stk->ip + 4; - if(std::holds_alternative(_res2)) - stk->ip = n; - else - stk->Push(gc,_res2); - - - } - else - throw VMException("Can't read jmpifbreak pc."); - return false; - } - - bool InterperterThread::JumpIfContinue(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - if(stk->ip + 4 <= stk->callable->closure->code.size()) - { - uint32_t n=BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); - - GCList ls(gc); - auto _res2 = stk->Pop(ls); - - stk->ip = stk->ip + 4; - if(std::holds_alternative(_res2)) - stk->ip = n; - else - stk->Push(gc,_res2); - - - } - else - throw VMException("Can't read jmpifcontinue pc."); - return false; - } - bool InterperterThread::JumpUndefined(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - if(stk->ip + 4 <= stk->callable->closure->code.size()) - { - uint32_t n=BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); - - GCList ls(gc); - auto _res2 = stk->Pop(ls); - - stk->ip = stk->ip + 4; - if(std::holds_alternative(_res2)) - stk->ip = n; - else - stk->Push(gc,_res2); - - - } - else - throw VMException("Can't read jmpundefined pc."); - return false; - } - bool InterperterThread::Jump(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - if(stk->ip + 4 <= stk->callable->closure->code.size()) - { - uint32_t n=BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); - stk->ip = n; - } - else - throw VMException("Can't read jmp pc."); - return false; - } - bool InterperterThread::PushNull(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - stk->Push(gc,nullptr); - return false; - } - bool InterperterThread::PushBreak(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - stk->Push(gc,TBreak()); - return false; - } - bool InterperterThread::PushContinue(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - stk->Push(gc,TContinue()); - return false; - } - bool InterperterThread::PushUndefined(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - stk->Push(gc,Undefined()); - return false; - } - bool InterperterThread::LineInfo(std::shared_ptr gc) - { - GCList ls(gc); - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - auto file = stk->Pop(ls); - auto line = stk->Pop(ls); - - //Set the fields in this cse - GetObject(file,stk->srcfile); - GetObject(line,stk->srcline); - - //TODO: implement lines (this will make the language work until we get it rigged up) - - - - return false; - } - bool InterperterThread::PushFalse(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - stk->Push(gc,false); - return false; - } - bool InterperterThread::PushTrue(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - stk->Push(gc,true); - return false; - } - bool InterperterThread::CreateDictionary(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - GCList ls(gc); - TDictionary* dict = TDictionary::Create(ls); - stk->Push(gc,dict); - return false; - } - bool InterperterThread::Nop(std::shared_ptr gc) - { - return false; - } - bool InterperterThread::AppendList(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - GCList ls(gc); - gc->BarrierBegin(); - auto obj = stk->Pop(ls); - auto objhold= stk->Pop(ls); - if(std::holds_alternative(objhold)) - { - auto list= dynamic_cast(std::get(objhold).obj); - if(list != nullptr) - { - list->Add(obj); - } - /* - if(dict != nullptr) - { - auto potential_str = stk->Pop(ls); - if(std::holds_alternative(potential_str)) - { - dict->SetValue(std::get(potential_str), stk->Pop(ls)); - } - }*/ - } - - stk->Push(gc, objhold); - - gc->BarrierEnd(); - return false; - } - bool InterperterThread::AppendDictionary(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - GCList ls(gc); - gc->BarrierBegin(); - auto value = stk->Pop(ls); - auto k = stk->Pop(ls); - auto objhold= stk->Pop(ls); - if(std::holds_alternative(objhold) && std::holds_alternative(k)) - { - auto dict= dynamic_cast(std::get(objhold).obj); - auto cls = dynamic_cast(std::get(objhold).obj); - - if(dict != nullptr) - { - dict->SetValue(std::get(k), value); - } - else if(cls != nullptr) - { - auto obj=cls->GetValue(cse.back()->callable->className,"set"+std::get(k)); - TCallable* callable; - if(GetObjectHeap(obj,callable)) - { - gc->BarrierEnd(); - - callable->Call(ls,{value}); - gc->BarrierBegin(); - }else { - cls->SetValue(cse.back()->callable->className,std::get(k),value); - } - } - } - - stk->Push(gc, objhold); - - gc->BarrierEnd(); - return false; - } - bool InterperterThread::CreateArray(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - GCList ls(gc); - TList* dict = TList::Create(ls); - stk->Push(gc,dict); - return false; - } - bool InterperterThread::Pop(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - GCList ls(gc); - stk->Pop(ls); - return false; - } - bool InterperterThread::TryCatch(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - GCList ls(gc); - auto catchFn = stk->Pop(ls); - auto tryFn = stk->Pop(ls); - - TCallable* tryC; - TCallable* catchC; - - if(GetObjectHeap(tryFn,tryC) && GetObjectHeap(catchFn,catchC)) - { - try - { - stk->Push(gc, tryC->Call(ls,{})); - } - - catch(std::exception& ex) - { - TDictionary* dict = TDictionary::Create(ls); - auto gc = ls.GetGC(); - auto myEx = dynamic_cast(&ex); - if(myEx != nullptr) - { - stk->Push(gc, catchC->Call(ls,{myEx->exception})); - } else { - gc->BarrierBegin(); - - dict->SetValue("Type","NativeException"); - dict->SetValue("Text",ex.what()); - gc->BarrierEnd(); - - stk->Push(gc, catchC->Call(ls,{dict})); - } - } - - - } - return false; - } - bool InterperterThread::JumpConditional(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - if(stk->ip + 4 <= stk->callable->closure->code.size()) - { - uint32_t n=BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); - - GCList ls2(gc); - auto _res2 = stk->Pop(ls2); - auto _res = ToBool(_res2); - stk->ip = stk->ip + 4; - if(_res) - stk->ip = n; - - - - } - else - throw VMException("Can't read jmpc pc."); - return false; - } - bool InterperterThread::PushClosure(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - if(stk->ip + 4 <= code.size()) - { - uint32_t n=BitConverter::ToUint32BE(code[stk->ip]); - if(n >= stk->callable->file->chunks.size()) - throw VMException("Can't read chunk."); - stk->ip = stk->ip + 4; - - gc->BarrierBegin(); - GCList ls(gc); - TClosure* closure = TClosure::Create(ls,stk->env,stk->callable->file,n,true); - closure->className = cse.back()->callable->className; - stk->Push(gc,closure); - gc->BarrierEnd(); - } - else - { - throw VMException("Can't read chunk."); - } - } - return false; - } - bool InterperterThread::PushScopelessClosure(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - if(stk->ip + 4 <= code.size()) - { - uint32_t n=BitConverter::ToUint32BE(code[stk->ip]); - if(n >= stk->callable->file->chunks.size()) - throw VMException("Can't read chunk."); - stk->ip = stk->ip + 4; - - gc->BarrierBegin(); - GCList ls(gc); - TClosure* closure = TClosure::Create(ls,stk->env,stk->callable->file,n,false); - closure->className = stk->callable->className; - stk->Push(gc,closure); - gc->BarrierEnd(); - } - else - { - throw VMException("Can't read chunk."); - } - } - return false; - } - - bool InterperterThread::PushString(std::shared_ptr gc) - { - - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - if(stk->ip + 4 <= code.size()) - { - uint32_t n=BitConverter::ToUint32BE(code[stk->ip]); - if(n < stk->callable->file->strings.size()) - stk->Push(gc,stk->callable->file->strings[n]); - else - throw VMException("Can't read string."); - stk->ip = stk->ip + 4; - } - } - return false; - } - - bool InterperterThread::PushLong(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - if(stk->ip + 8 <= code.size()) - { - uint64_t n=BitConverter::ToUint64BE(code[stk->ip]); - stk->Push(gc,(int64_t)n); - stk->ip = stk->ip + 8; - } - } - return false; - } - bool InterperterThread::PushChar(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - if(stk->ip + 1 <= code.size()) - { - char c = (char)code[stk->ip]; - stk->Push(gc,c); - stk->ip = stk->ip + 1; - } - } - return false; - } - bool InterperterThread::PushDouble(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - auto stk = cse.back(); - std::vector& code = stk->callable->closure->code; - if(stk->ip + 8 <= code.size()) - { - double dbl = BitConverter::ToDoubleBE(code[stk->ip]); - stk->Push(gc,dbl); - stk->ip = stk->ip + 8; - } - } - return false; - } - bool InterperterThread::Return(std::shared_ptr gc) - { - - - std::vector& cse=this->call_stack_entries; - - auto stk = cse.back(); - stk->ip = (uint32_t)stk->callable->closure->code.size(); + cse.back()->Push(gc, Undefined()); return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator>=", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator>="); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, + dynDict->CallMethod(ls, "operator>=", {right})); + return false; + } + + else { + cse.back()->Push(gc, Undefined()); + } + + } else { + cse.back()->Push(gc, Undefined()); } - bool InterperterThread::ScopeBegin(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - gc->BarrierBegin(); - GCList ls(gc); - stk->env = stk->env->GetSubEnvironment(ls); - stk->scopes++; - gc->BarrierEnd(); - + return false; +} +bool InterperterThread::Eq(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, true); return false; } - bool InterperterThread::Defer(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - auto stk = cse.back(); - - gc->BarrierBegin(); - GCList ls(gc); - auto item = stk->Pop(ls); - TCallable* call; - if(GetObjectHeap(item,call)) - cse.back()->env->defers.insert(cse.back()->env->defers.begin(), {call}); - gc->BarrierEnd(); - + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, true); return false; } - bool InterperterThread::Dup(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) == std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) == std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) == std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) == std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) == + std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) == std::get(right)); + } + + else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) == std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) == std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) == std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto lver = std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + cse.back()->Push(gc, r == 0); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto l = std::get(left); + auto r = std::get(right); + + return l == r; + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, (l->ToEpoch() == r->ToEpoch()) && + (l->IsLocal() == r->IsLocal())); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->TotalSeconds() == r->TotalSeconds()); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto native = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator=="); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->Equals(gc, right)); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator=="); + gc->BarrierEnd(); + if (!std::holds_alternative(fn)) + return InvokeTwo(ls, fn, left, right); + + } + + else if (dynDict != nullptr) { + auto res = dynDict->CallMethod(ls, "operator==", {right}); + if (!std::holds_alternative(res) && + std::holds_alternative(res)) { + cse.back()->Push(gc, res); + return false; + } + } + + else if (native != nullptr && + std::holds_alternative(right)) { + cse.back()->Push(gc, native->GetDestroyed()); + return false; + } + + if (std::holds_alternative(right)) { + cse.back()->Push(gc, obj == std::get(right).obj); + return false; + } + + else if (std::holds_alternative(right)) { + cse.back()->Push(gc, false); + return false; + } else if (std::holds_alternative(right)) { + cse.back()->Push(gc, false); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + } + + else if (std::holds_alternative(right)) { + cse.back()->Push(gc, false); + return false; + } else if (std::holds_alternative(right)) { + cse.back()->Push(gc, false); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::NEq(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, false); + return false; + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, false); + return false; + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) != std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) != std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) != std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) != std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) != + std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) != std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) != std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) != std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) != std::get(right)); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto lver = std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + cse.back()->Push(gc, r != 0); + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + auto l = std::get(left); + auto r = std::get(right); + + return l != r; + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, !((l->ToEpoch() == r->ToEpoch()) && + (l->IsLocal() == r->IsLocal()))); + } else if (std::holds_alternative< + std::shared_ptr>(left) && + std::holds_alternative< + std::shared_ptr>(right)) { + auto &l = + std::get>(left); + auto &r = + std::get>(right); + cse.back()->Push(gc, l->TotalSeconds() != r->TotalSeconds()); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + auto native = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator!="); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, !natObj->Equals(gc, right)); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator!="); + gc->BarrierEnd(); + if (!std::holds_alternative(fn)) + return InvokeTwo(ls, fn, left, right); + } + + else if (dynDict != nullptr) { + + auto res = dynDict->CallMethod(ls, "operator!=", {right}); + if (!std::holds_alternative(res) && + std::holds_alternative(res)) { + cse.back()->Push(gc, res); + return false; + } + } + + else if (native != nullptr && + std::holds_alternative(right)) { + cse.back()->Push(gc, !native->GetDestroyed()); + return false; + } + if (std::holds_alternative(right)) { + cse.back()->Push(gc, obj != std::get(right).obj); + return false; + } else if (std::holds_alternative(right)) { + cse.back()->Push(gc, true); + return false; + } else if (std::holds_alternative(right)) { + cse.back()->Push(gc, true); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + } else if (std::holds_alternative(right)) { + cse.back()->Push(gc, true); + return false; + } else if (std::holds_alternative(right)) { + cse.back()->Push(gc, true); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::LShift(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) + << (int)std::get(right)); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator<<"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator<<", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator<<"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } + + else if (dynDict != nullptr) { + cse.back()->Push(gc, + dynDict->CallMethod(ls, "operator<<", {right})); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::RShift(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, std::get(left) >> + (int)std::get(right)); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator>>"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator>>", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator>>"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } + + else if (dynDict != nullptr) { + cse.back()->Push(gc, + dynDict->CallMethod(ls, "operator>>", {right})); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::BOr(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) | std::get(right)); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator|"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator|", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator|"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } + + else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator|", {right})); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::XOr(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) ^ std::get(right)); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator^"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator^", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator^"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } + + else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator^", {right})); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::BAnd(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + cse.back()->Push(gc, + std::get(left) & std::get(right)); + } else if (std::holds_alternative(left)) { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if (cls != nullptr) { + gc->BarrierBegin(); + auto obj = + cls->GetValue(cse.back()->callable->className, "operator&"); + gc->BarrierEnd(); + TClosure *clos; + TCallable *callable; + if (GetObjectHeap(obj, clos)) { + this->AddCallStackEntry(ls, clos, {right}); + return true; + } else if (GetObjectHeap(obj, callable)) { + cse.back()->Push(gc, callable->Call(ls, {right})); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + + } else if (natObj != nullptr) { + cse.back()->Push(gc, natObj->CallMethod(ls, "operator&", {right})); + return false; + } else if (dict != nullptr) { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator&"); + gc->BarrierEnd(); + return InvokeTwo(ls, fn, left, right); + } else if (dynDict != nullptr) { + cse.back()->Push(gc, dynDict->CallMethod(ls, "operator&", {right})); + return false; + } else { + cse.back()->Push(gc, Undefined()); + } + + } else { + cse.back()->Push(gc, Undefined()); + } + + return false; +} +bool InterperterThread::InvokeOne(GCList &ls, TObject fn, TObject arg) { + if (std::holds_alternative(fn)) { + + auto obj = + dynamic_cast(std::get(fn).obj); + if (obj != nullptr) { + auto closure = dynamic_cast(obj); + if (closure != nullptr) { + + if (!closure->closure->args.empty() && + closure->closure->args[0] == "this") { + this->AddCallStackEntry(ls, closure, {arg}); + } else { + this->AddCallStackEntry(ls, closure, {}); + } + + } else { + auto val = obj->Call(ls, {}); + this->call_stack_entries.back()->Push(ls.GetGC(), val); + return false; + } + return true; + } + } + return false; +} + +bool InterperterThread::ExecuteFunction(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; GCList ls(gc); auto res = stk->Pop(ls); - stk->Push(gc,res); - stk->Push(gc,res); - return false; + if (std::holds_alternative(res)) { + uint32_t n = (uint32_t)std::get(res); + + std::vector args; + + for (size_t i = 0; i < n; i++) { + args.insert(args.begin(), {stk->Pop(ls)}); + } + + TObject fn = stk->Pop(ls); + if (std::holds_alternative(fn)) { + if (args.size() == 3) { + + if (std::holds_alternative(args[1]) && + std::holds_alternative(args[2])) { + std::string key = std::get(args[1]); + TList *ls = dynamic_cast( + std::get(args[2]).obj); + if (ls != nullptr) + return ExecuteMethod2(gc, args[0], key, ls->items); + } + } + stk->Push(gc, Undefined()); + return false; + } + + if (std::holds_alternative(fn)) { + + auto obj = dynamic_cast( + std::get(fn).obj); + if (obj != nullptr) { + auto closure = dynamic_cast(obj); + if (closure != nullptr) { + + this->AddCallStackEntry(ls, closure, args); + return true; + } else { + + auto val = obj->Call(ls, args); + this->call_stack_entries.back()->Push(ls.GetGC(), val); + + return false; + } + return true; + } + stk->Push(gc, Undefined()); + return false; + } + stk->Push(gc, Undefined()); + } else + stk->Push(gc, Undefined()); } - bool InterperterThread::ScopeEndTimes(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - - auto stk = cse.back(); + return false; +} +bool InterperterThread::Yield(std::shared_ptr gc) { + GCList ls(gc); + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { gc->BarrierBegin(); - GCList ls(gc); - std::vector callable; - std::vector& code = stk->callable->closure->code; - if(stk->ip + 4 <= code.size()) - { - uint32_t n=BitConverter::ToUint32BE(code[stk->ip]); - stk->ip += 4; - for(uint32_t i = 0; i < n;i++) - { - if(!stk->env->defers.empty()) - { - ls.Add(stk->env); - callable.insert(callable.end(), stk->env->defers.begin(),stk->env->defers.end()); - } - stk->scopes--; - stk->env = stk->env->GetParentEnvironment(); - } - } - - gc->BarrierEnd(); - for(auto item : callable) - { - GCList ls2(gc); - item->Call(ls2,{}); - } - - return false; + cse.back()->mustReturn = true; + cse.back()->Push(gc, cse.back()); + gc->BarrierEnd(); } - bool InterperterThread::ScopeEnd(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; - + return false; +} +bool InterperterThread::ExecuteMethod(std::shared_ptr gc) { + GCList ls(gc); + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; - + auto cnt = stk->Pop(ls); + if (std::holds_alternative(cnt)) { + uint32_t n = (uint32_t)std::get(cnt); + + std::vector args; + + for (size_t i = 0; i < n; i++) { + args.insert(args.begin(), {stk->Pop(ls)}); + } + + TObject key = stk->Pop(ls); + TObject instance = stk->Pop(ls); + + if (std::holds_alternative(key)) { + return ExecuteMethod2(gc, instance, std::get(key), + args); + } + stk->Push(gc, Undefined()); + return false; + } + } + return false; +} + +bool InterperterThread::GetVariable(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + GCList ls(gc); + auto key = stk->Pop(ls); + if (std::holds_alternative(key)) { + gc->BarrierBegin(); + stk->Push(gc, + stk->env->GetVariable(ls, std::get(key))); + gc->BarrierEnd(); + } else { + throw VMException("[GETVARIABLE] Can't pop string."); + } + } + return false; +} +bool InterperterThread::SetVariable(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + GCList ls(gc); + auto value = stk->Pop(ls); + auto key = stk->Pop(ls); + TList *mls; + if (std::holds_alternative(key)) { + gc->BarrierBegin(); + + if (stk->env->HasConstForSet(std::get(key))) { + gc->BarrierEnd(); + ThrowConstError(std::get(key)); + } + stk->Push(gc, stk->env->SetVariable(ls, std::get(key), + value)); + + gc->BarrierEnd(); + } else if (GetObjectHeap(key, mls)) { + gc->BarrierBegin(); + + TList *valueLs; + TDynamicList *valueDynList; + TDictionary *valueDict; + TDynamicDictionary *valueDynDict; + if (GetObjectHeap(value, valueLs)) { + TDictionary *result = TDictionary::Create(ls); + int64_t len = std::min(valueLs->Count(), mls->Count()); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + auto val = valueLs->Get(i); + result->SetValue(mkey, val); + + if (stk->env->HasConstForSet(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->SetVariable(ls, mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDynList)) { + TDictionary *result = TDictionary::Create(ls); + gc->BarrierEnd(); + int64_t len = std::min(valueDynList->Count(ls), mls->Count()); + gc->BarrierBegin(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + gc->BarrierEnd(); + auto val = valueDynList->GetAt(ls, i); gc->BarrierBegin(); - GCList ls(gc); - std::vector callable; - - if(!stk->env->defers.empty()) - { - ls.Add(stk->env); - callable.insert(callable.end(), stk->env->defers.begin(),stk->env->defers.end()); + result->SetValue(mkey, val); + + if (stk->env->HasConstForSet(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); } - - stk->scopes--; - stk->env = stk->env->GetParentEnvironment(); + stk->env->SetVariable(ls, mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDict)) { + + TDictionary *result = TDictionary::Create(ls); + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + auto val = valueDict->GetValue(mkey); + result->SetValue(mkey, val); + + if (stk->env->HasConstForSet(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->SetVariable(ls, mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDynDict)) { + TDictionary *result = TDictionary::Create(ls); + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { gc->BarrierEnd(); + auto val = valueDynDict->GetField(ls, mkey); + gc->BarrierBegin(); + result->SetValue(mkey, val); - for(auto item : callable) - { - GCList ls2(gc); - item->Call(ls2,{}); + if (stk->env->HasConstForSet(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->SetVariable(ls, mkey, val); + } + } + stk->Push(gc, result); + } else { + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + if (stk->env->HasConstForSet(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); } - - return false; - } - bool InterperterThread::PushRelativePath(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; + stk->env->SetVariable(ls, mkey, value); + } + } + stk->Push(gc, value); + } + gc->BarrierEnd(); + } else { + throw VMException("[SETVARIABLE] Can't pop string."); + } + } + return false; +} +bool InterperterThread::DeclareVariable(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { auto stk = cse.back(); - auto p = Framework::Filesystem::VFSPath(); - p.relative=true; - p.path={}; - stk->Push(gc, p); - return false; - } - bool InterperterThread::PushRootPath(std::shared_ptr gc) - { - std::vector& cse=this->call_stack_entries; + GCList ls(gc); + auto value = stk->Pop(ls); + auto key = stk->Pop(ls); + + TList *mls; + + if (std::holds_alternative(key)) { + gc->BarrierBegin(); + if (stk->env->HasConstForDeclare(std::get(key))) { + gc->BarrierEnd(); + ThrowConstError(std::get(key)); + } + stk->env->DeclareVariable(std::get(key), value); + stk->Push(gc, value); + gc->BarrierEnd(); + } else if (GetObjectHeap(key, mls)) { + gc->BarrierBegin(); + + TList *valueLs; + TDynamicList *valueDynList; + TDictionary *valueDict; + TDynamicDictionary *valueDynDict; + if (GetObjectHeap(value, valueLs)) { + TDictionary *result = TDictionary::Create(ls); + int64_t len = std::min(valueLs->Count(), mls->Count()); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + auto val = valueLs->Get(i); + result->SetValue(mkey, val); + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareVariable(mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDynList)) { + TDictionary *result = TDictionary::Create(ls); + gc->BarrierEnd(); + int64_t len = std::min(valueDynList->Count(ls), mls->Count()); + gc->BarrierBegin(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + gc->BarrierEnd(); + auto val = valueDynList->GetAt(ls, i); + gc->BarrierBegin(); + result->SetValue(mkey, val); + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareVariable(mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDict)) { + + TDictionary *result = TDictionary::Create(ls); + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + auto val = valueDict->GetValue(mkey); + result->SetValue(mkey, val); + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareVariable(mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDynDict)) { + TDictionary *result = TDictionary::Create(ls); + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + gc->BarrierEnd(); + auto val = valueDynDict->GetField(ls, mkey); + gc->BarrierBegin(); + + result->SetValue(mkey, val); + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareVariable(mkey, val); + } + } + stk->Push(gc, result); + } else { + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareVariable(mkey, value); + } + } + stk->Push(gc, value); + } + gc->BarrierEnd(); + } else { + + throw VMException("[DECLAREVARIABLE] Can't pop string, got type " + + GetObjectTypeString(key) + " = " + + ToString(gc, key) + "."); + } + } + return false; +} + +bool InterperterThread::DeclareConstVariable(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { auto stk = cse.back(); - auto p = Framework::Filesystem::VFSPath(); - p.relative=false; - p.path={}; - stk->Push(gc, p); - return false; + GCList ls(gc); + + auto value = stk->Pop(ls); + auto key = stk->Pop(ls); + + TList *mls; + + if (std::holds_alternative(key)) { + gc->BarrierBegin(); + if (stk->env->HasConstForDeclare(std::get(key))) { + gc->BarrierEnd(); + ThrowConstError(std::get(key)); + } + stk->env->DeclareConstVariable(std::get(key), value); + stk->Push(gc, value); + gc->BarrierEnd(); + } else if (GetObjectHeap(key, mls)) { + gc->BarrierBegin(); + + TList *valueLs; + TDynamicList *valueDynList; + TDictionary *valueDict; + TDynamicDictionary *valueDynDict; + if (GetObjectHeap(value, valueLs)) { + TDictionary *result = TDictionary::Create(ls); + int64_t len = std::min(valueLs->Count(), mls->Count()); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + auto val = valueLs->Get(i); + result->SetValue(mkey, val); + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareConstVariable(mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDynList)) { + TDictionary *result = TDictionary::Create(ls); + gc->BarrierEnd(); + int64_t len = std::min(valueDynList->Count(ls), mls->Count()); + gc->BarrierBegin(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + gc->BarrierEnd(); + auto val = valueDynList->GetAt(ls, i); + gc->BarrierBegin(); + result->SetValue(mkey, val); + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareConstVariable(mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDict)) { + + TDictionary *result = TDictionary::Create(ls); + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + auto val = valueDict->GetValue(mkey); + result->SetValue(mkey, val); + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareConstVariable(mkey, val); + } + } + stk->Push(gc, result); + } else if (GetObjectHeap(value, valueDynDict)) { + TDictionary *result = TDictionary::Create(ls); + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + gc->BarrierEnd(); + auto val = valueDynDict->GetField(ls, mkey); + gc->BarrierBegin(); + + result->SetValue(mkey, val); + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareConstVariable(mkey, val); + } + } + stk->Push(gc, result); + } else { + int64_t len = mls->Count(); + for (int64_t i = 0; i < len; i++) { + std::string mkey; + auto item = mls->Get(i); + if (GetObject(item, mkey)) { + if (stk->env->HasConstForDeclare(mkey)) { + gc->BarrierEnd(); + ThrowConstError(mkey); + } + stk->env->DeclareConstVariable(mkey, value); + } + } + stk->Push(gc, value); + } + gc->BarrierEnd(); + } else { + + throw VMException( + "[DECLARECONSTVARIABLE] Can't pop string, got type " + + GetObjectTypeString(key) + " = " + ToString(gc, key) + "."); + } } - bool InterperterThread::Illegal(std::shared_ptr gc) - { + return false; +} +bool InterperterThread::PushResourceStream(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; + if (stk->ip + 4 <= code.size()) { + uint32_t n = BitConverter::ToUint32BE(code[stk->ip]); + if (n >= stk->callable->file->resources.size()) + throw VMException("Can't read resource."); + stk->ip = stk->ip + 4; + gc->BarrierBegin(); + GCList ls(gc); + // TByteArray* arr = TByteArray::Create(ls); + // arr->data = stk->callable->file->resources[n]; + stk->Push( + gc, std::make_shared(gc, stk->callable->file, n)); - std::vector& cse=this->call_stack_entries; - - auto stk = cse.back(); - char chr[3]; - snprintf(chr,3,"%02X",stk->callable->closure->code[stk->ip-1]); - throw VMException("Illegal instruction: 0x" + std::string(chr) + "."); - + gc->BarrierEnd(); + } else { + throw VMException("Can't read chunk."); + } } + return false; +} - void InterperterThread::Execute(std::shared_ptr gc) - { +bool InterperterThread::PushResource(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; + if (stk->ip + 4 <= code.size()) { + uint32_t n = BitConverter::ToUint32BE(code[stk->ip]); + if (n >= stk->callable->file->resources.size()) + throw VMException("Can't read resource."); + stk->ip = stk->ip + 4; - std::vector& cse=this->call_stack_entries; - #define VM_OPCODE_TABLE_INLINE - #include "vm_opcode_table.h" - #undef VM_OPCODE_TABLE_INLINE - - execute: + gc->BarrierBegin(); + GCList ls(gc); + TByteArray *arr = TByteArray::Create(ls); + arr->data = stk->callable->file->resources[n]; + stk->Push(gc, arr); - if(!cse.empty()) + gc->BarrierEnd(); + } else { + throw VMException("Can't read chunk."); + } + } + return false; +} +bool InterperterThread::Throw(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto _res2 = cse.back()->Pop(ls); + + if (!std::holds_alternative(_res2)) { + auto env = cse.back()->env; + if (!env->GetRootEnvironment()->HandleException(gc, env, _res2)) + throw VMByteCodeException(gc, _res2, cse.back()); + } + return false; +} +bool InterperterThread::PushResourceDirectory(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + GCList ls(gc); + auto _res2 = cse.back()->Pop(ls); + TDictionary *dict; + if (GetObjectHeap(_res2, dict)) { + cse.back()->Push(gc, std::make_shared(gc, dict)); + } else { + cse.back()->Push(gc, Undefined()); + } + return false; +} +bool InterperterThread::JumpIfDefined(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + if (stk->ip + 4 <= stk->callable->closure->code.size()) { + uint32_t n = + BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); + + GCList ls(gc); + auto _res2 = stk->Pop(ls); + + stk->ip = stk->ip + 4; + if (!std::holds_alternative(_res2) && + !std::holds_alternative(_res2)) { + stk->ip = n; + stk->Push(gc, _res2); + } + + } else + throw VMException("Can't read jmpifdefined pc."); + return false; +} +bool InterperterThread::JumpIfBreak(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + if (stk->ip + 4 <= stk->callable->closure->code.size()) { + uint32_t n = + BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); + + GCList ls(gc); + auto _res2 = stk->Pop(ls); + + stk->ip = stk->ip + 4; + if (std::holds_alternative(_res2)) + stk->ip = n; + else + stk->Push(gc, _res2); + + } else + throw VMException("Can't read jmpifbreak pc."); + return false; +} + +bool InterperterThread::JumpIfContinue(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + if (stk->ip + 4 <= stk->callable->closure->code.size()) { + uint32_t n = + BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); + + GCList ls(gc); + auto _res2 = stk->Pop(ls); + + stk->ip = stk->ip + 4; + if (std::holds_alternative(_res2)) + stk->ip = n; + else + stk->Push(gc, _res2); + + } else + throw VMException("Can't read jmpifcontinue pc."); + return false; +} +bool InterperterThread::JumpUndefined(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + if (stk->ip + 4 <= stk->callable->closure->code.size()) { + uint32_t n = + BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); + + GCList ls(gc); + auto _res2 = stk->Pop(ls); + + stk->ip = stk->ip + 4; + if (std::holds_alternative(_res2)) + stk->ip = n; + else + stk->Push(gc, _res2); + + } else + throw VMException("Can't read jmpundefined pc."); + return false; +} +bool InterperterThread::Jump(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + if (stk->ip + 4 <= stk->callable->closure->code.size()) { + uint32_t n = + BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); + stk->ip = n; + } else + throw VMException("Can't read jmp pc."); + return false; +} +bool InterperterThread::PushNull(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + stk->Push(gc, nullptr); + return false; +} +bool InterperterThread::PushBreak(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + stk->Push(gc, TBreak()); + return false; +} +bool InterperterThread::PushContinue(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + stk->Push(gc, TContinue()); + return false; +} +bool InterperterThread::PushUndefined(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + stk->Push(gc, Undefined()); + return false; +} +bool InterperterThread::LineInfo(std::shared_ptr gc) { + GCList ls(gc); + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + auto file = stk->Pop(ls); + auto line = stk->Pop(ls); + + // Set the fields in this cse + GetObject(file, stk->srcfile); + GetObject(line, stk->srcline); + + // TODO: implement lines (this will make the language work until we get it + // rigged up) + + return false; +} +bool InterperterThread::PushFalse(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + stk->Push(gc, false); + return false; +} +bool InterperterThread::PushTrue(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + stk->Push(gc, true); + return false; +} +bool InterperterThread::CreateDictionary(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + GCList ls(gc); + TDictionary *dict = TDictionary::Create(ls); + stk->Push(gc, dict); + return false; +} +bool InterperterThread::Nop(std::shared_ptr gc) { return false; } +bool InterperterThread::AppendList(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + + GCList ls(gc); + gc->BarrierBegin(); + auto obj = stk->Pop(ls); + auto objhold = stk->Pop(ls); + if (std::holds_alternative(objhold)) { + auto list = + dynamic_cast(std::get(objhold).obj); + if (list != nullptr) { + list->Add(obj); + } + /* + if(dict != nullptr) { - auto stk = cse.back(); - current_function = stk; - - - - try{ - while(stk->ip < 0xFFFFFFFF && stk->ip < stk->callable->closure->code.size()) + auto potential_str = stk->Pop(ls); + if(std::holds_alternative(potential_str)) { - + dict->SetValue(std::get(potential_str), + stk->Pop(ls)); + } + }*/ + } + + stk->Push(gc, objhold); + + gc->BarrierEnd(); + return false; +} +bool InterperterThread::AppendDictionary(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + GCList ls(gc); + gc->BarrierBegin(); + auto value = stk->Pop(ls); + auto k = stk->Pop(ls); + auto objhold = stk->Pop(ls); + if (std::holds_alternative(objhold) && + std::holds_alternative(k)) { + auto dict = dynamic_cast( + std::get(objhold).obj); + auto cls = dynamic_cast( + std::get(objhold).obj); + + if (dict != nullptr) { + dict->SetValue(std::get(k), value); + } else if (cls != nullptr) { + auto obj = cls->GetValue(cse.back()->callable->className, + "set" + std::get(k)); + TCallable *callable; + if (GetObjectHeap(obj, callable)) { + gc->BarrierEnd(); + + callable->Call(ls, {value}); + gc->BarrierBegin(); + } else { + cls->SetValue(cse.back()->callable->className, + std::get(k), value); + } + } + } + + stk->Push(gc, objhold); + + gc->BarrierEnd(); + return false; +} +bool InterperterThread::CreateArray(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + GCList ls(gc); + TList *dict = TList::Create(ls); + stk->Push(gc, dict); + return false; +} +bool InterperterThread::Pop(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + GCList ls(gc); + stk->Pop(ls); + return false; +} +bool InterperterThread::TryCatch(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + GCList ls(gc); + auto catchFn = stk->Pop(ls); + auto tryFn = stk->Pop(ls); + + TCallable *tryC; + TCallable *catchC; + + if (GetObjectHeap(tryFn, tryC) && GetObjectHeap(catchFn, catchC)) { + try { + stk->Push(gc, tryC->Call(ls, {})); + } + + catch (std::exception &ex) { + TDictionary *dict = TDictionary::Create(ls); + auto gc = ls.GetGC(); + auto myEx = dynamic_cast(&ex); + if (myEx != nullptr) { + stk->Push(gc, catchC->Call(ls, {myEx->exception})); + } else { + gc->BarrierBegin(); + + dict->SetValue("Type", "NativeException"); + dict->SetValue("Text", ex.what()); + gc->BarrierEnd(); + + stk->Push(gc, catchC->Call(ls, {dict})); + } + } + } + return false; +} +bool InterperterThread::JumpConditional(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); + if (stk->ip + 4 <= stk->callable->closure->code.size()) { + uint32_t n = + BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]); + + GCList ls2(gc); + auto _res2 = stk->Pop(ls2); + auto _res = ToBool(_res2); + stk->ip = stk->ip + 4; + if (_res) + stk->ip = n; + + } else + throw VMException("Can't read jmpc pc."); + return false; +} +bool InterperterThread::PushClosure(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; + if (stk->ip + 4 <= code.size()) { + uint32_t n = BitConverter::ToUint32BE(code[stk->ip]); + if (n >= stk->callable->file->chunks.size()) + throw VMException("Can't read chunk."); + stk->ip = stk->ip + 4; + + gc->BarrierBegin(); + GCList ls(gc); + TClosure *closure = + TClosure::Create(ls, stk->env, stk->callable->file, n, true); + closure->className = cse.back()->callable->className; + stk->Push(gc, closure); + gc->BarrierEnd(); + } else { + throw VMException("Can't read chunk."); + } + } + return false; +} +bool InterperterThread::PushScopelessClosure(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; + if (stk->ip + 4 <= code.size()) { + uint32_t n = BitConverter::ToUint32BE(code[stk->ip]); + if (n >= stk->callable->file->chunks.size()) + throw VMException("Can't read chunk."); + stk->ip = stk->ip + 4; + + gc->BarrierBegin(); + GCList ls(gc); + TClosure *closure = + TClosure::Create(ls, stk->env, stk->callable->file, n, false); + closure->className = stk->callable->className; + stk->Push(gc, closure); + gc->BarrierEnd(); + } else { + throw VMException("Can't read chunk."); + } + } + return false; +} + +bool InterperterThread::PushString(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; + if (stk->ip + 4 <= code.size()) { + uint32_t n = BitConverter::ToUint32BE(code[stk->ip]); + if (n < stk->callable->file->strings.size()) + stk->Push(gc, stk->callable->file->strings[n]); + else + throw VMException("Can't read string."); + stk->ip = stk->ip + 4; + } + } + return false; +} + +bool InterperterThread::PushLong(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; + if (stk->ip + 8 <= code.size()) { + uint64_t n = BitConverter::ToUint64BE(code[stk->ip]); + stk->Push(gc, (int64_t)n); + stk->ip = stk->ip + 8; + } + } + return false; +} +bool InterperterThread::PushChar(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; + if (stk->ip + 1 <= code.size()) { + char c = (char)code[stk->ip]; + stk->Push(gc, c); + stk->ip = stk->ip + 1; + } + } + return false; +} +bool InterperterThread::PushDouble(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + if (!cse.empty()) { + auto stk = cse.back(); + std::vector &code = stk->callable->closure->code; + if (stk->ip + 8 <= code.size()) { + double dbl = BitConverter::ToDoubleBE(code[stk->ip]); + stk->Push(gc, dbl); + stk->ip = stk->ip + 8; + } + } + return false; +} +bool InterperterThread::Return(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + stk->ip = (uint32_t)stk->callable->closure->code.size(); + return false; +} +bool InterperterThread::ScopeBegin(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + + gc->BarrierBegin(); + GCList ls(gc); + stk->env = stk->env->GetSubEnvironment(ls); + stk->scopes++; + gc->BarrierEnd(); + + return false; +} +bool InterperterThread::Defer(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + + gc->BarrierBegin(); + GCList ls(gc); + auto item = stk->Pop(ls); + TCallable *call; + if (GetObjectHeap(item, call)) + cse.back()->env->defers.insert(cse.back()->env->defers.begin(), {call}); + gc->BarrierEnd(); + + return false; +} +bool InterperterThread::Dup(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + GCList ls(gc); + auto res = stk->Pop(ls); + stk->Push(gc, res); + stk->Push(gc, res); + + return false; +} +bool InterperterThread::ScopeEndTimes(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + + gc->BarrierBegin(); + GCList ls(gc); + std::vector callable; + std::vector &code = stk->callable->closure->code; + if (stk->ip + 4 <= code.size()) { + uint32_t n = BitConverter::ToUint32BE(code[stk->ip]); + stk->ip += 4; + for (uint32_t i = 0; i < n; i++) { + if (!stk->env->defers.empty()) { + ls.Add(stk->env); + callable.insert(callable.end(), stk->env->defers.begin(), + stk->env->defers.end()); + } + stk->scopes--; + stk->env = stk->env->GetParentEnvironment(); + } + } + + gc->BarrierEnd(); + for (auto item : callable) { + GCList ls2(gc); + item->Call(ls2, {}); + } + + return false; +} +bool InterperterThread::ScopeEnd(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + + gc->BarrierBegin(); + GCList ls(gc); + std::vector callable; + + if (!stk->env->defers.empty()) { + ls.Add(stk->env); + callable.insert(callable.end(), stk->env->defers.begin(), + stk->env->defers.end()); + } + + stk->scopes--; + stk->env = stk->env->GetParentEnvironment(); + gc->BarrierEnd(); + + for (auto item : callable) { + GCList ls2(gc); + item->Call(ls2, {}); + } + + return false; +} +bool InterperterThread::PushRelativePath(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + auto p = Framework::Filesystem::VFSPath(); + p.relative = true; + p.path = {}; + stk->Push(gc, p); + return false; +} +bool InterperterThread::PushRootPath(std::shared_ptr gc) { + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + auto p = Framework::Filesystem::VFSPath(); + p.relative = false; + p.path = {}; + stk->Push(gc, p); + return false; +} +bool InterperterThread::Illegal(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; + + auto stk = cse.back(); + char chr[3]; + snprintf(chr, 3, "%02X", stk->callable->closure->code[stk->ip - 1]); + throw VMException("Illegal instruction: 0x" + std::string(chr) + "."); +} + +void InterperterThread::Execute(std::shared_ptr gc) { + + std::vector &cse = this->call_stack_entries; +#define VM_OPCODE_TABLE_INLINE +#include "vm_opcode_table.h" +#undef VM_OPCODE_TABLE_INLINE + +execute: + + if (!cse.empty()) { + auto stk = cse.back(); + current_function = stk; + + try { + while (stk->ip < 0xFFFFFFFF && + stk->ip < stk->callable->closure->code.size()) { + uint32_t ip = stk->ip; stk->ip = ip + 1; - if(((*this).*(opcodes[stk->callable->closure->code[ip]]))(gc)) + if (((*this).*(opcodes[stk->callable->closure->code[ip]]))(gc)) goto execute; - if(stk->mustReturn) { + if (stk->mustReturn) { - stk->mustReturn=false; - if(cse.size() > 1) - { + stk->mustReturn = false; + if (cse.size() > 1) { GCList ls(gc); - TObject o = cse[cse.size()-1]->Pop(ls); - cse[cse.size()-2]->Push(gc,o); - - cse.erase(cse.end()-1); - current_function = cse.back(); - gc->BarrierEnd(); - goto execute; + TObject o = cse[cse.size() - 1]->Pop(ls); + cse[cse.size() - 2]->Push(gc, o); + + cse.erase(cse.end() - 1); + current_function = cse.back(); + gc->BarrierEnd(); + goto execute; } else { return; } } - - if(gc->UsingNullThreads()) gc->Collect(); - + if (gc->UsingNullThreads()) + gc->Collect(); } - stk->mustReturn=false; - } - catch(...) + stk->mustReturn = false; + } catch (...) { + { - - { - gc->BarrierBegin(); - GCList ls(gc); - std::vector callable; - while(!cse.empty()) - { - auto r= cse.back(); - auto e = r->env; - for(uint32_t i = 0; i < r->scopes; i++) - { - if(!e->defers.empty()) - { - ls.Add(e); - callable.insert(callable.end(), e->defers.begin(),e->defers.end()); - } - e = e->GetParentEnvironment(); - } - cse.erase(cse.end()-1); - } - gc->BarrierEnd(); - - for(auto item : callable) - { - GCList ls2(gc); - item->Call(ls2,{}); - } - } - std::rethrow_exception(std::current_exception()); - } - if(cse.size()==1) - { - - - current_function=nullptr; - { - gc->BarrierBegin(); - - - - GCList ls(gc); - - - - std::vector callable; - - auto r= cse.back(); - auto e = r->env; - for(uint32_t i = 0; i < r->scopes; i++) - { - if(!e->defers.empty()) - { - ls.Add(e); - callable.insert(callable.end(), e->defers.begin(),e->defers.end()); - } - e = e->GetParentEnvironment(); + GCList ls(gc); + std::vector callable; + while (!cse.empty()) { + auto r = cse.back(); + auto e = r->env; + for (uint32_t i = 0; i < r->scopes; i++) { + if (!e->defers.empty()) { + ls.Add(e); + callable.insert(callable.end(), e->defers.begin(), + e->defers.end()); } - + e = e->GetParentEnvironment(); + } + cse.erase(cse.end() - 1); + } gc->BarrierEnd(); - for(auto item : callable) - { + for (auto item : callable) { GCList ls2(gc); - item->Call(ls2,{}); + item->Call(ls2, {}); } - } - - return; } - else + std::rethrow_exception(std::current_exception()); + } + if (cse.size() == 1) { + + current_function = nullptr; { - - { + gc->BarrierBegin(); - - GCList ls(gc); + GCList ls(gc); - - std::vector callable; - - auto r= cse.back(); - auto e = r->env; - for(uint32_t i = 0; i < r->scopes; i++) - { - if(!e->defers.empty()) - { - ls.Add(e); - callable.insert(callable.end(), e->defers.begin(),e->defers.end()); - } - e = e->GetParentEnvironment(); - } - + std::vector callable; + auto r = cse.back(); + auto e = r->env; + for (uint32_t i = 0; i < r->scopes; i++) { + if (!e->defers.empty()) { + ls.Add(e); + callable.insert(callable.end(), e->defers.begin(), + e->defers.end()); + } + e = e->GetParentEnvironment(); + } - TObject o = cse[cse.size()-1]->Pop(ls); - cse[cse.size()-2]->Push(gc,o); - - cse.erase(cse.end()-1); + gc->BarrierEnd(); + + for (auto item : callable) { + GCList ls2(gc); + item->Call(ls2, {}); + } + } + + return; + } else { + + { + gc->BarrierBegin(); + + GCList ls(gc); + + std::vector callable; + + auto r = cse.back(); + auto e = r->env; + for (uint32_t i = 0; i < r->scopes; i++) { + if (!e->defers.empty()) { + ls.Add(e); + callable.insert(callable.end(), e->defers.begin(), + e->defers.end()); + } + e = e->GetParentEnvironment(); + } + + TObject o = cse[cse.size() - 1]->Pop(ls); + cse[cse.size() - 2]->Push(gc, o); + + cse.erase(cse.end() - 1); current_function = cse.back(); gc->BarrierEnd(); - for(auto item : callable) - { + for (auto item : callable) { GCList ls2(gc); - item->Call(ls2,{}); + item->Call(ls2, {}); } - - } - - goto execute; } + + goto execute; } - } - - - void CallStackEntry::Mark() - { - if(this->marked) return; - this->marked=true; - this->env->Mark(); - this->callable->Mark(); - for(auto item : this->stack) GC::Mark(item); - } - void CallStackEntry::Push(std::shared_ptr gc,TObject o) - { - gc->BarrierBegin(); - this->stack.push_back(o); - gc->BarrierEnd(); - } - TObject CallStackEntry::Resume(GCList& ls) - { - auto cse = current_function; - InterperterThread* thrd=InterperterThread::Create(ls); - ls.GetGC()->BarrierBegin(); - thrd->call_stack_entries.push_back(this); - ls.GetGC()->BarrierEnd(); - - thrd->Execute(ls.GetGC()); - - TObject v= thrd->call_stack_entries[0]->Pop(ls); - current_function = cse; - return v; - } - TObject CallStackEntry::Pop(GCList& gc) - { - if(this->stack.empty()) return Undefined(); - gc.GetGC()->BarrierBegin(); - TObject o = this->stack[this->stack.size()-1]; - gc.Add(o); - this->stack.erase(this->stack.begin()+this->stack.size()-1); - gc.GetGC()->BarrierEnd(); - return o; - } - - InterperterThread* InterperterThread::Create(GCList& ls) - { - InterperterThread* it = new InterperterThread(); - std::shared_ptr _gc = ls.GetGC(); - ls.Add(it); - _gc->Watch(it); - return it; - } - InterperterThread* InterperterThread::Create(GCList* ls) - { - InterperterThread* it = new InterperterThread(); - std::shared_ptr _gc = ls->GetGC(); - ls->Add(it); - _gc->Watch(it); - return it; - } - CallStackEntry* CallStackEntry::Create(GCList& ls) - { - CallStackEntry* cse = new CallStackEntry(); - cse->mustReturn=false; - cse->srcline = -1; - cse->srcfile = ""; - cse->thread=nullptr; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(cse); - _gc->Watch(cse); - return cse; - } - - CallStackEntry* CallStackEntry::Create(GCList* ls) - { - CallStackEntry* cse = new CallStackEntry(); - cse->mustReturn=false; - cse->srcline = -1; - cse->srcfile = ""; - cse->thread=nullptr; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(cse); - _gc->Watch(cse); - return cse; - } - void InterperterThread::AddCallStackEntry(GCList& ls, TClosure* closure, std::vector args) - { - ls.GetGC()->BarrierBegin(); - CallStackEntry* cse = CallStackEntry::Create(ls); - cse->thread = this; - cse->callable = closure; - cse->env = closure->chunkId == 0 ? closure->env : closure->ownScope ? closure->env->GetSubEnvironment(ls) : closure->env; - cse->ip = 0; - if(closure->closure->args.empty() && closure->chunkId != 0) - { - TList* list = TList::Create(ls); - list->items = args; - cse->env->DeclareVariable("arguments", list); - - } - else - { - auto requiredArguments = [closure]()->size_t - { - for(size_t i =0;iclosure->args.size();i++) - { - if(closure->closure->args[i].find("$") == 0) - { - return i; - } - } - return closure->closure->args.size(); - }; - auto optionalArguments = [closure](size_t argLen)->size_t - { - for(size_t i =0;iclosure->args.size();i++) - { - if(closure->closure->args[i].find("$$") == 0) - { - - return std::min(argLen,i); - - } - } - - return std::min(argLen,closure->closure->args.size()); - }; - auto trimStart = [](std::string txt)->std::string { - if(txt.empty()) return {}; - if(txt[0] != '$') return txt; - auto idx = txt.find_first_not_of('$'); - if(idx == std::string::npos) return {}; - return txt.substr(idx); - }; - size_t required = requiredArguments(); - - if(args.size() < required) - { - throw VMException("Called a function that expected at least " + std::to_string(required) + " args but got " + std::to_string(args.size())); - } - - size_t i; - for( i = 0; i < optionalArguments(args.size()); i++) - { - cse->env->DeclareVariable(trimStart(closure->closure->args[i]), args[i]); - } - std::string back = closure->closure->args.empty() ? std::string() : closure->closure->args.back(); - if(i == closure->closure->args.size()-1 && back.size() > 2 && back[0] == '$' && back[1] == '$') - { - auto argName = closure->closure->args[i]; - auto lsArgs = TList::Create(ls); - for(;iAdd(args[i]); - cse->env->DeclareVariable(trimStart(argName), lsArgs); - i = args.size(); - } - if(icall_stack_entries.push_back(cse); - ls.GetGC()->BarrierEnd(); - } - - } + +void CallStackEntry::Mark() { + if (this->marked) + return; + this->marked = true; + this->env->Mark(); + this->callable->Mark(); + for (auto item : this->stack) + GC::Mark(item); +} +void CallStackEntry::Push(std::shared_ptr gc, TObject o) { + gc->BarrierBegin(); + this->stack.push_back(o); + gc->BarrierEnd(); +} +TObject CallStackEntry::Resume(GCList &ls) { + auto cse = current_function; + InterperterThread *thrd = InterperterThread::Create(ls); + ls.GetGC()->BarrierBegin(); + thrd->call_stack_entries.push_back(this); + ls.GetGC()->BarrierEnd(); + + thrd->Execute(ls.GetGC()); + + TObject v = thrd->call_stack_entries[0]->Pop(ls); + current_function = cse; + return v; +} +TObject CallStackEntry::Pop(GCList &gc) { + if (this->stack.empty()) + return Undefined(); + gc.GetGC()->BarrierBegin(); + TObject o = this->stack[this->stack.size() - 1]; + gc.Add(o); + this->stack.erase(this->stack.begin() + this->stack.size() - 1); + gc.GetGC()->BarrierEnd(); + return o; +} + +InterperterThread *InterperterThread::Create(GCList &ls) { + InterperterThread *it = new InterperterThread(); + std::shared_ptr _gc = ls.GetGC(); + ls.Add(it); + _gc->Watch(it); + return it; +} +InterperterThread *InterperterThread::Create(GCList *ls) { + InterperterThread *it = new InterperterThread(); + std::shared_ptr _gc = ls->GetGC(); + ls->Add(it); + _gc->Watch(it); + return it; +} +CallStackEntry *CallStackEntry::Create(GCList &ls) { + CallStackEntry *cse = new CallStackEntry(); + cse->mustReturn = false; + cse->srcline = -1; + cse->srcfile = ""; + cse->thread = nullptr; + std::shared_ptr _gc = ls.GetGC(); + ls.Add(cse); + _gc->Watch(cse); + return cse; +} + +CallStackEntry *CallStackEntry::Create(GCList *ls) { + CallStackEntry *cse = new CallStackEntry(); + cse->mustReturn = false; + cse->srcline = -1; + cse->srcfile = ""; + cse->thread = nullptr; + std::shared_ptr _gc = ls->GetGC(); + ls->Add(cse); + _gc->Watch(cse); + return cse; +} +void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure, + std::vector args) { + ls.GetGC()->BarrierBegin(); + CallStackEntry *cse = CallStackEntry::Create(ls); + cse->thread = this; + cse->callable = closure; + cse->env = closure->chunkId == 0 ? closure->env + : closure->ownScope ? closure->env->GetSubEnvironment(ls) + : closure->env; + cse->ip = 0; + if (closure->closure->args.empty() && closure->chunkId != 0) { + TList *list = TList::Create(ls); + list->items = args; + cse->env->DeclareVariable("arguments", list); + + } else { + auto requiredArguments = [closure]() -> size_t { + for (size_t i = 0; i < closure->closure->args.size(); i++) { + if (closure->closure->args[i].find("$") == 0) { + return i; + } + } + return closure->closure->args.size(); + }; + auto optionalArguments = [closure](size_t argLen) -> size_t { + for (size_t i = 0; i < closure->closure->args.size(); i++) { + if (closure->closure->args[i].find("$$") == 0) { + + return std::min(argLen, i); + } + } + + return std::min(argLen, closure->closure->args.size()); + }; + auto trimStart = [](std::string txt) -> std::string { + if (txt.empty()) + return {}; + if (txt[0] != '$') + return txt; + auto idx = txt.find_first_not_of('$'); + if (idx == std::string::npos) + return {}; + return txt.substr(idx); + }; + size_t required = requiredArguments(); + + if (args.size() < required) { + throw VMException("Called a function that expected at least " + + std::to_string(required) + " args but got " + + std::to_string(args.size())); + } + + size_t i; + for (i = 0; i < optionalArguments(args.size()); i++) { + cse->env->DeclareVariable(trimStart(closure->closure->args[i]), + args[i]); + } + std::string back = closure->closure->args.empty() + ? std::string() + : closure->closure->args.back(); + if (i == closure->closure->args.size() - 1 && back.size() > 2 && + back[0] == '$' && back[1] == '$') { + auto argName = closure->closure->args[i]; + auto lsArgs = TList::Create(ls); + for (; i < args.size(); i++) + lsArgs->Add(args[i]); + cse->env->DeclareVariable(trimStart(argName), lsArgs); + i = args.size(); + } + if (i < args.size()) + throw VMException("Too many arguments"); + } + + current_function = cse; + + this->call_stack_entries.push_back(cse); + ls.GetGC()->BarrierEnd(); +} + +} // namespace Tesses::CrossLang diff --git a/src/vm/vm_opcode_table.h b/src/vm/vm_opcode_table.h index 2bc176d..97a4267 100644 --- a/src/vm/vm_opcode_table.h +++ b/src/vm/vm_opcode_table.h @@ -1,260 +1,258 @@ #if defined(VM_OPCODE_TABLE_INLINE) -static opcode opcodes[256]={ - &InterperterThread::Add, - &InterperterThread::Sub, - &InterperterThread::Times, - &InterperterThread::Divide, - &InterperterThread::Mod, - &InterperterThread::LShift, - &InterperterThread::RShift, - &InterperterThread::BOr, - &InterperterThread::BAnd, - &InterperterThread::BNot, - &InterperterThread::Lt, - &InterperterThread::Gt, - &InterperterThread::Lte, - &InterperterThread::Gte, - &InterperterThread::Eq, - &InterperterThread::NEq, - &InterperterThread::LNot, - &InterperterThread::Neg, - &InterperterThread::XOr, - &InterperterThread::Pop, - &InterperterThread::Dup, - &InterperterThread::Nop, - &InterperterThread::PushClosure, - &InterperterThread::CreateDictionary, - &InterperterThread::CreateArray, - &InterperterThread::AppendList, - &InterperterThread::AppendDictionary, - &InterperterThread::PushResource, - &InterperterThread::PushLong, - &InterperterThread::PushChar, - &InterperterThread::PushDouble, - &InterperterThread::PushString, - &InterperterThread::PushNull, - &InterperterThread::PushUndefined, - &InterperterThread::ScopeBegin, - &InterperterThread::ScopeEnd, - &InterperterThread::ScopeEndTimes, - &InterperterThread::PushFalse, - &InterperterThread::PushTrue, - &InterperterThread::SetVariable, - &InterperterThread::GetVariable, - &InterperterThread::DeclareVariable, - &InterperterThread::SetField, - &InterperterThread::GetField, - &InterperterThread::ExecuteFunction, - &InterperterThread::ExecuteMethod, - &InterperterThread::Return, - &InterperterThread::JumpConditional, - &InterperterThread::Jump, - &InterperterThread::JumpUndefined, - &InterperterThread::Defer, - &InterperterThread::TryCatch, - &InterperterThread::Throw, - &InterperterThread::PushScopelessClosure, - &InterperterThread::Yield, - &InterperterThread::PushRootPath, - &InterperterThread::PushRelativePath, - &InterperterThread::Breakpoint, - &InterperterThread::PushBreak, - &InterperterThread::PushContinue, - &InterperterThread::JumpIfBreak, - &InterperterThread::JumpIfContinue, - &InterperterThread::JumpIfDefined, - &InterperterThread::DeclareConstVariable, - &InterperterThread::LineInfo, - &InterperterThread::PushResourceStream, - &InterperterThread::PushResourceDirectory, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal, - &InterperterThread::Illegal -}; +static opcode opcodes[256] = {&InterperterThread::Add, + &InterperterThread::Sub, + &InterperterThread::Times, + &InterperterThread::Divide, + &InterperterThread::Mod, + &InterperterThread::LShift, + &InterperterThread::RShift, + &InterperterThread::BOr, + &InterperterThread::BAnd, + &InterperterThread::BNot, + &InterperterThread::Lt, + &InterperterThread::Gt, + &InterperterThread::Lte, + &InterperterThread::Gte, + &InterperterThread::Eq, + &InterperterThread::NEq, + &InterperterThread::LNot, + &InterperterThread::Neg, + &InterperterThread::XOr, + &InterperterThread::Pop, + &InterperterThread::Dup, + &InterperterThread::Nop, + &InterperterThread::PushClosure, + &InterperterThread::CreateDictionary, + &InterperterThread::CreateArray, + &InterperterThread::AppendList, + &InterperterThread::AppendDictionary, + &InterperterThread::PushResource, + &InterperterThread::PushLong, + &InterperterThread::PushChar, + &InterperterThread::PushDouble, + &InterperterThread::PushString, + &InterperterThread::PushNull, + &InterperterThread::PushUndefined, + &InterperterThread::ScopeBegin, + &InterperterThread::ScopeEnd, + &InterperterThread::ScopeEndTimes, + &InterperterThread::PushFalse, + &InterperterThread::PushTrue, + &InterperterThread::SetVariable, + &InterperterThread::GetVariable, + &InterperterThread::DeclareVariable, + &InterperterThread::SetField, + &InterperterThread::GetField, + &InterperterThread::ExecuteFunction, + &InterperterThread::ExecuteMethod, + &InterperterThread::Return, + &InterperterThread::JumpConditional, + &InterperterThread::Jump, + &InterperterThread::JumpUndefined, + &InterperterThread::Defer, + &InterperterThread::TryCatch, + &InterperterThread::Throw, + &InterperterThread::PushScopelessClosure, + &InterperterThread::Yield, + &InterperterThread::PushRootPath, + &InterperterThread::PushRelativePath, + &InterperterThread::Breakpoint, + &InterperterThread::PushBreak, + &InterperterThread::PushContinue, + &InterperterThread::JumpIfBreak, + &InterperterThread::JumpIfContinue, + &InterperterThread::JumpIfDefined, + &InterperterThread::DeclareConstVariable, + &InterperterThread::LineInfo, + &InterperterThread::PushResourceStream, + &InterperterThread::PushResourceDirectory, + &InterperterThread::PushPrivateExpression, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal, + &InterperterThread::Illegal}; #endif