mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-04-16 07:37:03 +00:00
Compare commits
6 Commits
b3c92707b9
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| 5be9d96b54 | |||
| 46850e8edf | |||
| 86c7d85f0e | |||
| 45dcd9e7c5 | |||
| 447e9e6d37 | |||
| cc62377919 |
2
.clangd
2
.clangd
@@ -1,2 +0,0 @@
|
||||
CompileFlags: # Tweak the parse settings, example directory given to show format
|
||||
Add: ["-Iinclude","-std=gnu++17"]
|
||||
70
.gitea/workflows/tag.yaml
Normal file
70
.gitea/workflows/tag.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
name: Build and Deploy on Tag
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
env:
|
||||
GITEA_AUTH: ${{ secrets.MY_GITEA_AUTH }}
|
||||
|
||||
jobs:
|
||||
build-arch:
|
||||
runs-on: arch-builder
|
||||
steps:
|
||||
- run: pacman --noconfirm -Sy nodejs npm
|
||||
- uses: actions/checkout@v4
|
||||
- run: wget -O /root/repository.key https://git.tesseslanguage.com/api/packages/tesses50/arch/repository.key
|
||||
- run: pacman-key --add /root/repository.key
|
||||
- run: pacman-key --config /opt/cross/ppc/pacman.conf --add /root/repository.key
|
||||
- run: printf "[tesses50.git.tesseslanguage.com]\nSigLevel = Optional TrustAll\nServer = https://git.tesseslanguage.com/api/packages/tesses50/arch/core/\$arch\n" >> /etc/pacman.conf
|
||||
- run: printf "[tesses50.git.tesseslanguage.com]\nSigLevel = Optional TrustAll\nServer = https://git.tesseslanguage.com/api/packages/tesses50/arch/core/\$arch\n" >> /opt/cross/ppc/pacman.conf
|
||||
- run: pacman --noconfirm -Sy mbedtls curl tesses-framework
|
||||
- run: pacman --config /opt/cross/ppc/pacman.conf --noconfirm -Sy mbedtls tesses-framework
|
||||
- run: cp Packaging/Linux/PKGBUILD /home/build/PKGBUILD
|
||||
- run: cp Packaging/Linux/build-arch.sh /home/build/build-arch.sh
|
||||
- run: chmod 755 /home/build/build-arch.sh
|
||||
- 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
|
||||
build-jammy:
|
||||
runs-on: deb-builder-jammy
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build for jammy, noble
|
||||
run: |
|
||||
mkdir ../../artifacts
|
||||
apt update -y
|
||||
apt install -y pkg-config git
|
||||
bash build-ubuntu-jammy.sh
|
||||
bash push-ubuntu-jammy.sh
|
||||
bash build-tars.sh
|
||||
working-directory: ./Packaging/Linux
|
||||
- uses: akkuman/gitea-release-action@v1
|
||||
env:
|
||||
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18
|
||||
with:
|
||||
files: |-
|
||||
artifacts/**
|
||||
build-plucky:
|
||||
runs-on: deb-builder-plucky
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build for plucky, resolute
|
||||
run: |
|
||||
mkdir ../../artifacts
|
||||
apt update -y
|
||||
apt install -y pkg-config git gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 gcc-mingw-w64-i686 g++-mingw-w64-i686 nsis
|
||||
bash build-ubuntu-plucky.sh
|
||||
bash push-ubuntu-plucky.sh
|
||||
working-directory: ./Packaging/Linux
|
||||
|
||||
- name: Build for windows
|
||||
run: bash build.sh
|
||||
|
||||
working-directory: ./Packaging/Windows
|
||||
- uses: akkuman/gitea-release-action@v1
|
||||
env:
|
||||
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18
|
||||
with:
|
||||
files: |-
|
||||
artifacts/**
|
||||
@@ -1,18 +1,21 @@
|
||||
version: 39
|
||||
version: 43
|
||||
jobs:
|
||||
- name: Build for x86_64
|
||||
steps:
|
||||
- !CheckoutStep
|
||||
- type: CheckoutStep
|
||||
name: Checkout
|
||||
cloneCredential: !DefaultCredential {}
|
||||
cloneCredential:
|
||||
type: DefaultCredential
|
||||
withLfs: true
|
||||
withSubmodules: false
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
- !CommandStep
|
||||
condition: SUCCESSFUL
|
||||
optional: false
|
||||
- type: CommandStep
|
||||
name: Execute build
|
||||
runInContainer: true
|
||||
image: onedev.site.tesses.net/tesses-framework/tesses-framework:latest
|
||||
interpreter: !DefaultInterpreter
|
||||
interpreter:
|
||||
type: DefaultInterpreter
|
||||
commands: |
|
||||
mkdir build
|
||||
cd build
|
||||
@@ -20,127 +23,32 @@ jobs:
|
||||
make -j12
|
||||
make install DESTDIR=../out
|
||||
useTTY: true
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
- !BuildImageStep
|
||||
condition: SUCCESSFUL
|
||||
optional: false
|
||||
- type: BuildImageStep
|
||||
name: Build Docker Image
|
||||
dockerfile: Dockerfile.run
|
||||
output: !RegistryOutput
|
||||
output:
|
||||
type: RegistryOutput
|
||||
tags: onedev.site.tesses.net/crosslang/crosslang:latest onedev.site.tesses.net/crosslang/crosslang:@commit_hash@
|
||||
registryLogins:
|
||||
- registryUrl: '@server_url@'
|
||||
userName: '@job_token@'
|
||||
passwordSecret: dockersecret
|
||||
platforms: linux/amd64
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
- !CommandStep
|
||||
name: Wii Build
|
||||
runInContainer: true
|
||||
image: onedev.site.tesses.net/dependencies/wiidev:latest
|
||||
interpreter: !DefaultInterpreter
|
||||
commands: |
|
||||
cd Packaging/CPKG
|
||||
bash wiibuild.sh
|
||||
useTTY: true
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
- !CommandStep
|
||||
name: Build archlinux
|
||||
runInContainer: true
|
||||
image: git.tesseslanguage.com/tesses50/arch-builds:2025-11-11
|
||||
interpreter: !DefaultInterpreter
|
||||
commands: |
|
||||
wget -O /root/repository.key https://git.tesseslanguage.com/api/packages/tesses50/arch/repository.key
|
||||
pacman-key --add /root/repository.key
|
||||
pacman-key --config /opt/cross/ppc/pacman.conf --add /root/repository.key
|
||||
printf "[tesses50.git.tesseslanguage.com]\nSigLevel = Optional TrustAll\nServer = https://git.tesseslanguage.com/api/packages/tesses50/arch/core/\$arch\n" >> /etc/pacman.conf
|
||||
printf "[tesses50.git.tesseslanguage.com]\nSigLevel = Optional TrustAll\nServer = https://git.tesseslanguage.com/api/packages/tesses50/arch/core/\$arch\n" >> /opt/cross/ppc/pacman.conf
|
||||
|
||||
pacman --noconfirm -Sy mbedtls curl tesses-framework
|
||||
pacman --config /opt/cross/ppc/pacman.conf --noconfirm -Sy mbedtls tesses-framework
|
||||
cp Packaging/Linux/PKGBUILD /home/build/PKGBUILD
|
||||
cp Packaging/Linux/build-arch.sh /home/build/build-arch.sh
|
||||
chmod 755 /home/build/build-arch.sh
|
||||
chown build:build /home/build/PKGBUILD
|
||||
chown build:build /home/build/build-arch.sh
|
||||
su build -c /home/build/build-arch.sh
|
||||
envVars:
|
||||
- name: GITEA_AUTH
|
||||
value: '@secret:GITEA_AUTH@'
|
||||
useTTY: true
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
- !CommandStep
|
||||
name: Build and Publish Deb Package (Plucky)
|
||||
runInContainer: true
|
||||
image: onedev.site.tesses.net/dependencies/debbuilder/plucky:latest
|
||||
interpreter: !DefaultInterpreter
|
||||
commands: |
|
||||
mkdir artifacts
|
||||
apt update -y
|
||||
apt install -y pkg-config git gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 gcc-mingw-w64-i686 g++-mingw-w64-i686 nsis
|
||||
cd Packaging/Linux
|
||||
bash build-ubuntu-plucky.sh
|
||||
bash push-ubuntu-plucky.sh
|
||||
cd ../CPKG
|
||||
bash winbuild.sh
|
||||
cd ../Windows
|
||||
bash build.sh
|
||||
envVars:
|
||||
- name: GITEA_AUTH
|
||||
value: '@secret:GITEA_AUTH@'
|
||||
- name: BUILD_NO
|
||||
value: '@build_number@'
|
||||
useTTY: true
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
- !CommandStep
|
||||
name: Build and Publish Deb Package
|
||||
runInContainer: true
|
||||
image: onedev.site.tesses.net/dependencies/debbuilder/jammy:latest
|
||||
interpreter: !DefaultInterpreter
|
||||
commands: |
|
||||
apt update -y
|
||||
apt install -y pkg-config git
|
||||
cd Packaging/Linux
|
||||
bash build-ubuntu-jammy.sh
|
||||
bash push-ubuntu-jammy.sh
|
||||
bash build-tars.sh
|
||||
apt update -y
|
||||
apt install -y crosslang
|
||||
cd ../CPKG
|
||||
bash pack_and_publish.sh
|
||||
envVars:
|
||||
- name: GITEA_AUTH
|
||||
value: '@secret:GITEA_AUTH@'
|
||||
- name: CPKG_KEY
|
||||
value: '@secret:CPKG_KEY@'
|
||||
- name: BUILD_NO
|
||||
value: '@build_number@'
|
||||
useTTY: true
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
- !SCPCommandStep
|
||||
name: Copy Files
|
||||
privateKeySecret: TRUENAS_SSH
|
||||
source: artifacts
|
||||
target: mike@@10.137.42.30:/mnt/storage24tb/Files/Public/CrossLang/@build_number@
|
||||
options: -r
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
- !SSHCommandStep
|
||||
name: Link latest
|
||||
remoteMachine: 10.137.42.30
|
||||
userName: mike
|
||||
privateKeySecret: TRUENAS_SSH
|
||||
commands: |
|
||||
cd /mnt/storage24tb/Files/Public/CrossLang
|
||||
rm -f latest
|
||||
ln -s @build_number@ latest
|
||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||
condition: SUCCESSFUL
|
||||
optional: false
|
||||
triggers:
|
||||
- !DependencyFinishedTrigger
|
||||
- type: DependencyFinishedTrigger
|
||||
projects: tesses-framework
|
||||
- !BranchUpdateTrigger
|
||||
- type: BranchUpdateTrigger
|
||||
branches: master
|
||||
userMatch: anyone
|
||||
projects: crosslang
|
||||
projectDependencies:
|
||||
- projectPath: tesses-framework
|
||||
buildProvider: !LastFinishedBuild
|
||||
buildProvider:
|
||||
type: LastFinishedBuild
|
||||
jobName: Build for x86_64
|
||||
artifacts: '*'
|
||||
retryCondition: never
|
||||
|
||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -84,7 +84,11 @@
|
||||
"stack": "cpp",
|
||||
"stdfloat": "cpp"
|
||||
},
|
||||
|
||||
"clangd.fallbackFlags": [
|
||||
"-Iinclude"
|
||||
"-I${workspaceFolder}/include",
|
||||
"-I/home/mike/tmp-crosslang/usr/local/include/"
|
||||
]
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(TessesCrossLang VERSION 1.0)
|
||||
set(CROSSLANG_MAJOR_VERSION 0)
|
||||
set(CROSSLANG_MINOR_VERSION 0)
|
||||
set(CROSSLANG_PATCH_VERSION 2)
|
||||
|
||||
project(TessesCrossLang VERSION ${CROSSLANG_MAJOR_VERSION}.${CROSSLANG_MINOR_VERSION}.${CROSSLANG_PATCH_VERSION})
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
@@ -78,6 +82,11 @@ if(CROSSLANG_ENABLE_FFI AND CROSSLANG_ENABLE_SHARED)
|
||||
pkg_check_modules(LIBFFI REQUIRED IMPORTED_TARGET libffi)
|
||||
endif()
|
||||
function(CROSSLANG_LINK_DEPS CROSSLANG_TARGET_NAME)
|
||||
target_include_directories(${CROSSLANG_TARGET_NAME}
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
)
|
||||
if(CROSSLANG_ENABLE_FFI AND CROSSLANG_ENABLE_SHARED)
|
||||
|
||||
target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_FFI)
|
||||
@@ -132,6 +141,16 @@ target_include_directories(${CROSSLANG_TARGET_NAME}
|
||||
endfunction()
|
||||
|
||||
list(APPEND CROSSLANG_SOURCE
|
||||
src/vm/bc/add.cpp
|
||||
src/vm/bc/sub.cpp
|
||||
src/vm/bc/getfield.cpp
|
||||
src/vm/bc/setfield.cpp
|
||||
src/vm/bc/tostring.cpp
|
||||
src/vm/bc/equals.cpp
|
||||
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
|
||||
@@ -139,6 +158,7 @@ src/compiler/codegen.cpp
|
||||
src/compiler/lexer.cpp
|
||||
src/compiler/parser.cpp
|
||||
src/compiler/ast.cpp
|
||||
src/runtime_methods/uuid.cpp
|
||||
src/runtime_methods/class.cpp
|
||||
src/runtime_methods/console.cpp
|
||||
src/runtime_methods/io.cpp
|
||||
@@ -236,7 +256,7 @@ install(TARGETS ${TessesCrossLangLibs}
|
||||
)
|
||||
|
||||
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
|
||||
FILE TessesCrossLangTargets.cmake
|
||||
NAMESPACE TessesCrossLang::
|
||||
@@ -245,6 +265,8 @@ install(EXPORT TessesCrossLangTargets
|
||||
|
||||
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/TessesCrossLangConfig.cmake"
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesCrossLang)
|
||||
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)
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/TessesCrossLangConfig.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesCrossLang)
|
||||
|
||||
5
CrossLangVersion.h.in
Normal file
5
CrossLangVersion.h.in
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define CROSSLANG_MAJOR @CROSSLANG_MAJOR_VERSION@
|
||||
#define CROSSLANG_MINOR @CROSSLANG_MINOR_VERSION@
|
||||
#define CROSSLANG_PATCH @CROSSLANG_PATCH_VERSION@
|
||||
@@ -1,55 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(CrossLangPublish)
|
||||
|
||||
option(CROSSAPPPUBLISH_STATIC "Build static version" OFF)
|
||||
|
||||
if(CROSSAPPPUBLISH_STATIC)
|
||||
set(TESSESFRAMEWORK_ENABLE_RPATH OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_STATIC ON CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_APPS OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_SHARED OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_FETCHCONTENT ON CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(CROSSLANG_ENABLE_BINARIES OFF CACHE INTERNAL "For CrossLang" FORCE)
|
||||
else()
|
||||
set(TESSESFRAMEWORK_ENABLE_RPATH OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_STATIC OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_APPS OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_SHARED ON CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_FETCHCONTENT ON CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(CROSSLANG_ENABLE_BINARIES OFF CACHE INTERNAL "For CrossLang" FORCE)
|
||||
set(CMAKE_INSTALL_BINDIR "." CACHE INTERNAL "For CrossLang" FORCE)
|
||||
set(CMAKE_INSTALL_LIBDIR "." CACHE INTERNAL "For CrossLang" FORCE)
|
||||
set(CMAKE_INSTALL_PREFIX "/dir" CACHE INTERNAL "For CrossLang" FORCE)
|
||||
set(CMAKE_PLATFORM_NO_VERSIONED_SONAME ON CACHE INTERNAL "For CrossLang" FORCE)
|
||||
set(CMAKE_MACOSX_RPATH 1)
|
||||
set(CMAKE_BUILD_RPATH_USE_ORIGIN ON CACHE INTERNAL "For CrossLang" FORCE)
|
||||
if (APPLE)
|
||||
set(CMAKE_INSTALL_RPATH "@executable_path/" CACHE INTERNAL "For CrossLang" FORCE)
|
||||
else()
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/" CACHE INTERNAL "For CrossLang" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
TessesCrossLang
|
||||
GIT_REPOSITORY https://onedev.site.tesses.net/crosslang.git
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(TessesCrossLang)
|
||||
|
||||
|
||||
|
||||
add_executable(crossapp main.cpp)
|
||||
if(CROSSAPPPUBLISH_STATIC)
|
||||
target_link_libraries(crossapp PUBLIC crosslang_static)
|
||||
else()
|
||||
install(TARGETS crossapp DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
|
||||
target_link_libraries(crossapp PUBLIC crosslang_shared)
|
||||
|
||||
endif()
|
||||
@@ -1,76 +0,0 @@
|
||||
#include <CrossLang.hpp>
|
||||
using namespace Tesses::Framework;
|
||||
using namespace Tesses::CrossLang;
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
TF_InitWithConsole();
|
||||
if(argc > 0)
|
||||
TF_AllowPortable(argv[0]);
|
||||
std::string name = argv[0];
|
||||
Tesses::Framework::Filesystem::VFSPath exePath=Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(name);
|
||||
exePath.MakeAbsolute();
|
||||
exePath.ChangeExtension(".crvm");
|
||||
|
||||
|
||||
|
||||
|
||||
GC gc;
|
||||
gc.Start();
|
||||
GCList ls(gc);
|
||||
TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls));
|
||||
|
||||
TStd::RegisterStd(&gc,env);
|
||||
env->LoadFileWithDependencies(&gc, Tesses::Framework::Filesystem::LocalFS, exePath);
|
||||
|
||||
|
||||
|
||||
if(env->HasVariable("WebAppMain"))
|
||||
{
|
||||
Args args(argc, argv);
|
||||
int port = 4206;
|
||||
for(auto& item : args.options)
|
||||
{
|
||||
if(item.first == "port")
|
||||
{
|
||||
port = std::stoi(item.second);
|
||||
}
|
||||
}
|
||||
|
||||
env->EnsureDictionary(&gc,"Net")->SetValue("WebServerPort", (int64_t)port);
|
||||
TList* args2 = TList::Create(ls);
|
||||
args2->Add(exePath.ToString());
|
||||
for(auto& item : args.positional)
|
||||
{
|
||||
args2->Add(item);
|
||||
}
|
||||
|
||||
auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2});
|
||||
auto svr2 = Tesses::CrossLang::ToHttpServer(&gc,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();
|
||||
}
|
||||
else {
|
||||
TList* args = TList::Create(ls);
|
||||
args->Add(exePath.ToString());
|
||||
for(int arg=1;arg<argc;arg++)
|
||||
args->Add(argv[arg]);
|
||||
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||
int64_t iresult;
|
||||
if(GetObject(res,iresult))
|
||||
return (int)iresult;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(CrossLangWii)
|
||||
|
||||
|
||||
set(TESSESFRAMEWORK_FETCHCONTENT OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_RPATH OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_STATIC ON CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_APPS OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(TESSESFRAMEWORK_ENABLE_SHARED OFF CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
set(CROSSLANG_ENABLE_BINARIES OFF CACHE INTERNAL "For CrossLang" FORCE)
|
||||
set(MBEDTLS_DIR "/opt/devkitpro/portlibs/wii" CACHE INTERNAL "For TessesFramework" FORCE)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
TessesCrossLang
|
||||
GIT_REPOSITORY https://onedev.site.tesses.net/crosslang.git
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(TessesCrossLang)
|
||||
|
||||
|
||||
|
||||
add_executable(boot main.cpp)
|
||||
target_link_libraries(boot PUBLIC crosslang_static)
|
||||
ogc_create_dol(boot)
|
||||
@@ -1,80 +0,0 @@
|
||||
#include <CrossLang.hpp>
|
||||
using namespace Tesses::Framework;
|
||||
using namespace Tesses::CrossLang;
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
TF_InitWithConsole();
|
||||
std::string name = "boot.dol";
|
||||
Tesses::Framework::Filesystem::VFSPath exePath=Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(name);
|
||||
exePath.MakeAbsolute();
|
||||
exePath.ChangeExtension(".crvm");
|
||||
|
||||
|
||||
|
||||
|
||||
GC gc;
|
||||
gc.Start();
|
||||
GCList ls(gc);
|
||||
TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls));
|
||||
|
||||
TStd::RegisterStd(&gc,env);
|
||||
env->LoadFileWithDependencies(&gc, Tesses::Framework::Filesystem::LocalFS, exePath);
|
||||
|
||||
|
||||
|
||||
if(env->HasVariable("WebAppMain"))
|
||||
{
|
||||
std::vector<std::string> argsls={"boot.dol"};
|
||||
for(int i = 0; i < argc; i++)
|
||||
{
|
||||
argsls.push_back(argv[i]);
|
||||
}
|
||||
|
||||
Args args(argsls);
|
||||
int port = 4206;
|
||||
for(auto& item : args.options)
|
||||
{
|
||||
if(item.first == "port")
|
||||
{
|
||||
port = std::stoi(item.second);
|
||||
}
|
||||
}
|
||||
|
||||
env->EnsureDictionary(&gc,"Net")->SetValue("WebServerPort", (int64_t)port);
|
||||
TList* args2 = TList::Create(ls);
|
||||
args2->Add(exePath.ToString());
|
||||
for(auto& item : args.positional)
|
||||
{
|
||||
args2->Add(item);
|
||||
}
|
||||
|
||||
auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2});
|
||||
auto svr2 = Tesses::CrossLang::ToHttpServer(&gc,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();
|
||||
}
|
||||
else {
|
||||
TList* args = TList::Create(ls);
|
||||
args->Add(exePath.ToString());
|
||||
for(int arg=0;arg<argc;arg++)
|
||||
args->Add(argv[arg]);
|
||||
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||
int64_t iresult;
|
||||
if(GetObject(res,iresult))
|
||||
return (int)iresult;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
set(CMAKE_C_COMPILER "/usr/bin/x86_64-w64-mingw32-gcc")
|
||||
set(CMAKE_CXX_COMPILER "/usr/bin/x86_64-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_SYSTEM_NAME Windows)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
@@ -1,7 +0,0 @@
|
||||
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_SYSTEM_NAME Windows)
|
||||
set(CMAKE_SYSTEM_PROCESSOR i686)
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
rm -r compilers
|
||||
mkdir -p compilers
|
||||
cd compilers
|
||||
wget https://downloads.tesses.net/cache/compilers/$1-cross.tgz
|
||||
tar xvzf $1-cross.tgz
|
||||
mv $1-cross/* .
|
||||
rmdir $1-cross
|
||||
rm $1-cross.tgz
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
mkdir compilers
|
||||
crossint pack.tcross
|
||||
@@ -1,282 +0,0 @@
|
||||
var VERSION="1.0.0.0-dev";
|
||||
var statics = [
|
||||
{
|
||||
target="powerpc-linux-musl",
|
||||
cpu = "powerpc"
|
||||
},
|
||||
{
|
||||
target="powerpc64-linux-musl",
|
||||
cpu = "powerpc64"
|
||||
},
|
||||
{
|
||||
target="i686-linux-musl",
|
||||
cpu = "i686"
|
||||
},
|
||||
{
|
||||
target="arm-linux-musleabihf",
|
||||
cpu="armv7l"
|
||||
},
|
||||
{
|
||||
target="riscv32-linux-musl",
|
||||
cpu="riscv32"
|
||||
},
|
||||
{
|
||||
target="riscv64-linux-musl",
|
||||
cpu="riscv64"
|
||||
},
|
||||
{
|
||||
target="x86_64-linux-musl",
|
||||
cpu="x86_64"
|
||||
},
|
||||
{
|
||||
target="mips-linux-musl",
|
||||
cpu="mips"
|
||||
},
|
||||
{
|
||||
target="mips64-linux-musl",
|
||||
cpu="mips64"
|
||||
},
|
||||
{
|
||||
target="aarch64-linux-musl",
|
||||
cpu="aarch64"
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
func CPUS()
|
||||
{
|
||||
var p = Process.Start({
|
||||
FileName = Env.GetRealExecutablePath("nproc").ToString(),
|
||||
RedirectStandardOutput=true
|
||||
});
|
||||
var ms = new MemoryStream(true);
|
||||
p.StandardOutput.CopyTo(ms);
|
||||
return ParseLong(ms.GetBytes().ToString().Replace("\n","").Replace("\r",""));
|
||||
}
|
||||
var nproc = CPUS();
|
||||
func BuildConsoleOrServerWindowsStatic(arch)
|
||||
{
|
||||
Console.WriteLine($"Building Windows Static {arch}");
|
||||
var build_dir = "builds" / $"win-{arch}";
|
||||
var publish_dir = "publish" / $"win-{arch}";
|
||||
FS.Local.CreateDirectory(build_dir);
|
||||
FS.Local.CreateDirectory(publish_dir);
|
||||
|
||||
var args = ["-S","ConsoleOrServer","-B",build_dir.ToString(),"-DCROSSAPPPUBLISH_STATIC=ON"];
|
||||
|
||||
var file= ("WindowsToolchains"/$"{arch}.cmake").MakeAbsolute().ToString();
|
||||
|
||||
args.Add($"-DCMAKE_TOOLCHAIN_FILE={file}");
|
||||
|
||||
Process.Start({
|
||||
FileName = Env.GetRealExecutablePath("cmake").ToString(),
|
||||
Arguments = args
|
||||
}).Join();
|
||||
|
||||
|
||||
var p = new Process();
|
||||
p.FileName = Env.GetRealExecutablePath("make").ToString();
|
||||
p.WorkingDirectory = build_dir.MakeAbsolute().ToString();
|
||||
p.Arguments = [$"-j{nproc}"];
|
||||
if(p.Start())
|
||||
p.Join();
|
||||
|
||||
|
||||
|
||||
}
|
||||
func BuildConsoleOrServerLinuxStatic(dir,cmake_toolchain)
|
||||
{
|
||||
Console.WriteLine($"Building Linux Static {dir}");
|
||||
var build_dir = "builds" / $"linux-{dir}-static";
|
||||
var publish_dir = "publish" / $"linux-{dir}-static";
|
||||
FS.Local.CreateDirectory(build_dir);
|
||||
FS.Local.CreateDirectory(publish_dir);
|
||||
|
||||
var args = ["-S","ConsoleOrServer","-B",build_dir.ToString(),"-DCROSSAPPPUBLISH_STATIC=ON"];
|
||||
if(TypeOf(cmake_toolchain) == "String")
|
||||
{
|
||||
args.Add($"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain}");
|
||||
}
|
||||
Process.Start({
|
||||
FileName = Env.GetRealExecutablePath("cmake").ToString(),
|
||||
Arguments = args
|
||||
}).Join();
|
||||
|
||||
|
||||
var p = new Process();
|
||||
p.FileName = Env.GetRealExecutablePath("make").ToString();
|
||||
p.WorkingDirectory = build_dir.MakeAbsolute().ToString();
|
||||
p.Arguments = [$"-j{nproc}"];
|
||||
if(p.Start())
|
||||
p.Join();
|
||||
|
||||
|
||||
mvFile(build_dir/"crossapp", publish_dir / "crossapp");
|
||||
var info = {
|
||||
type = "archive",
|
||||
maintainer = "Mike Nolan",
|
||||
repo = "https://onedev.site.tesses.net/crosslang",
|
||||
homepage = "https://crosslang.tesseslanguage.com/",
|
||||
executable_name = "crossapp",
|
||||
executable_can_be_renamed = true,
|
||||
executable_runtime = $"linux-{dir}-static",
|
||||
description = $"Runtime files for linux-{dir}-static",
|
||||
};
|
||||
|
||||
var name = $"Tesses.CrossLang.Runtime.linux-{dir}-static";
|
||||
|
||||
var subDir = new SubdirFilesystem(FS.Local,publish_dir);
|
||||
var pkgStrm = FS.Local.OpenFile("publish"/$"{name}-{VERSION}.crvm","wb");
|
||||
FS.CreateArchive(subDir,pkgStrm, name ,VERSION, Json.Encode(info));
|
||||
pkgStrm.Close();
|
||||
}
|
||||
func BuildConsoleOrServerLinuxStaticBasedOnTarget(target,cpu)
|
||||
{
|
||||
var compiler = ("compilers"/"bin"/target).MakeAbsolute().ToString();
|
||||
var p = new Process();
|
||||
p.FileName = Env.GetRealExecutablePath("bash").ToString();
|
||||
p.Arguments = ["extract_compiler.sh",target];
|
||||
if(p.Start())
|
||||
p.Join();
|
||||
|
||||
var toolchain = $"
|
||||
set(CMAKE_C_COMPILER \"{compiler}-gcc\")
|
||||
set(CMAKE_CXX_COMPILER \"{compiler}-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_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR {cpu})
|
||||
";
|
||||
if(target == "riscv32-linux-musl" || target == "riscv64-linux-musl")
|
||||
{
|
||||
toolchain += "set(CMAKE_POSITION_INDEPENDENT_CODE ON)\n";
|
||||
}
|
||||
FS.WriteAllText(FS.Local,"compilers"/$"{target}.cmake", toolchain);
|
||||
BuildConsoleOrServerLinuxStatic(cpu,("compilers"/$"{target}.cmake").MakeAbsolute().ToString());
|
||||
}
|
||||
func BuildConsoleOrServerLinuxShared(dir,$cmake_toolchain)
|
||||
{
|
||||
Console.WriteLine($"Building Linux Shared {dir}");
|
||||
var build_dir = "builds" / $"linux-{dir}";
|
||||
var publish_dir = "publish" / $"linux-{dir}";
|
||||
FS.Local.CreateDirectory(build_dir);
|
||||
FS.Local.CreateDirectory(publish_dir);
|
||||
|
||||
var args = ["-S","ConsoleOrServer","-B",build_dir.ToString()];
|
||||
if(TypeOf(cmake_toolchain) == "String")
|
||||
{
|
||||
args.Add($"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain}");
|
||||
}
|
||||
Process.Start({
|
||||
FileName = Env.GetRealExecutablePath("cmake").ToString(),
|
||||
Arguments = args
|
||||
}).Join();
|
||||
|
||||
|
||||
var p = new Process();
|
||||
p.FileName = Env.GetRealExecutablePath("make").ToString();
|
||||
p.WorkingDirectory = build_dir.MakeAbsolute().ToString();
|
||||
p.Arguments = [$"-j{nproc}"];
|
||||
if(p.Start())
|
||||
p.Join();
|
||||
p = new Process();
|
||||
p.FileName = Env.GetRealExecutablePath("make").ToString();
|
||||
p.WorkingDirectory = build_dir.MakeAbsolute().ToString();
|
||||
p.Arguments = ["install","DESTDIR=."];
|
||||
if(p.Start())
|
||||
p.Join();
|
||||
|
||||
mvFile(build_dir/"dir"/"crossapp", publish_dir / "crossapp");
|
||||
each(var lib : FS.Local.EnumeratePaths(build_dir/"dir"))
|
||||
{
|
||||
if(lib.GetExtension() == ".so")
|
||||
{
|
||||
mvFile(lib,publish_dir / lib.GetFileName());
|
||||
}
|
||||
}
|
||||
var info = {
|
||||
type = "archive",
|
||||
maintainer = "Mike Nolan",
|
||||
repo = "https://onedev.site.tesses.net/crosslang",
|
||||
homepage = "https://crosslang.tesseslanguage.com/",
|
||||
description = $"Runtime files for linux-{dir}",
|
||||
executable_name = "crossapp",
|
||||
executable_can_be_renamed = true,
|
||||
executable_runtime = $"linux-{dir}"
|
||||
};
|
||||
|
||||
var name = $"Tesses.CrossLang.Runtime.linux-{dir}";
|
||||
|
||||
var subDir = new SubdirFilesystem(FS.Local,publish_dir);
|
||||
var pkgStrm = FS.Local.OpenFile("publish"/$"{name}-{VERSION}.crvm","wb");
|
||||
FS.CreateArchive(subDir,pkgStrm, name ,VERSION, Json.Encode(info));
|
||||
pkgStrm.Close();
|
||||
}
|
||||
func mvFile(src,dest)
|
||||
{
|
||||
Process.Start({
|
||||
FileName = Env.GetRealExecutablePath("mv").ToString(),
|
||||
Arguments = [src.MakeAbsolute().ToString(),dest.MakeAbsolute().ToString()]
|
||||
}).Join();
|
||||
}
|
||||
func main(args)
|
||||
{
|
||||
Console.WriteLine($"Got {nproc} cpus");
|
||||
each(var arch : ["x86","x64"])
|
||||
{
|
||||
var build_dir = "build" / $"win-{arch}";
|
||||
var publish_dir = "publish" / $"win-{arch}";
|
||||
FS.Local.CreateDirectory(publish_dir);
|
||||
mvFile(build_dir/"crossapp.exe", publish_dir / "crossapp.exe");
|
||||
var info = {
|
||||
type = "archive",
|
||||
maintainer = "Mike Nolan",
|
||||
repo = "https://onedev.site.tesses.net/crosslang",
|
||||
homepage = "https://crosslang.tesseslanguage.com/",
|
||||
executable_name = "crossapp.exe",
|
||||
executable_can_be_renamed = true,
|
||||
executable_runtime = $"win-{arch}",
|
||||
description = $"Runtime files for win-{arch}",
|
||||
};
|
||||
|
||||
var name = $"Tesses.CrossLang.Runtime.win-{arch}";
|
||||
|
||||
var subDir = new SubdirFilesystem(FS.Local,publish_dir);
|
||||
var pkgStrm = FS.Local.OpenFile("publish"/$"{name}-{VERSION}.crvm","wb");
|
||||
FS.CreateArchive(subDir,pkgStrm, name ,VERSION, Json.Encode(info));
|
||||
pkgStrm.Close();
|
||||
}
|
||||
|
||||
BuildConsoleOrServerLinuxShared("x86_64");
|
||||
BuildConsoleOrServerLinuxShared("aarch64", "/opt/toolchains/arm64.cmake");
|
||||
BuildConsoleOrServerLinuxShared("armv7l", "/opt/toolchains/armhf.cmake");
|
||||
BuildConsoleOrServerLinuxShared("riscv64", "/opt/toolchains/riscv64.cmake");
|
||||
|
||||
|
||||
each(var static : statics)
|
||||
{
|
||||
BuildConsoleOrServerLinuxStaticBasedOnTarget(static.target,static.cpu);
|
||||
}
|
||||
|
||||
var info = {
|
||||
type = "archive",
|
||||
maintainer = "Mike Nolan",
|
||||
repo = "https://onedev.site.tesses.net/crosslang",
|
||||
homepage = "https://crosslang.tesseslanguage.com/",
|
||||
executable_name = "boot.dol",
|
||||
executable_can_be_renamed = false,
|
||||
executable_runtime = "wii",
|
||||
description = $"Runtime files for wii",
|
||||
};
|
||||
|
||||
var name = $"Tesses.CrossLang.Runtime.wii";
|
||||
|
||||
var subDir = new SubdirFilesystem(FS.Local,"publish"/"wii");
|
||||
var pkgStrm = FS.Local.OpenFile("publish"/$"{name}-{VERSION}.crvm","wb");
|
||||
FS.CreateArchive(subDir,pkgStrm, name ,VERSION, Json.Encode(info));
|
||||
pkgStrm.Close();
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
bash ./pack.sh
|
||||
bash ./publish.sh
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
find publish -name "*.crvm" -exec crosslang upload-package --token="$CPKG_KEY" --host="https://cpkg.tesseslanguage.com/" "{}" \;
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
mkdir -p publish/wii
|
||||
cd Wii
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -S .. -B . -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Wii.cmake
|
||||
make -j`nproc`
|
||||
mv boot.dol ../../publish/wii/boot.dol
|
||||
@@ -1,10 +0,0 @@
|
||||
echo "Building Windows Static x86"
|
||||
cmake -S "ConsoleOrServer" -B build/win-x86 -DCROSSAPPPUBLISH_STATIC=ON -DCMAKE_TOOLCHAIN_FILE=`pwd`/WindowsToolchains/x86.cmake
|
||||
cd build/win-x86
|
||||
make -j`nproc`
|
||||
cd ../..
|
||||
echo "Building Windows Static x64"
|
||||
cmake -S "ConsoleOrServer" -B build/win-x64 -DCROSSAPPPUBLISH_STATIC=ON -DCMAKE_TOOLCHAIN_FILE=`pwd`/WindowsToolchains/x64.cmake
|
||||
cd build/win-x64
|
||||
make -j`nproc`
|
||||
cd ../..
|
||||
@@ -1,6 +1,6 @@
|
||||
# Maintainer: Mike Nolan <tesses@tesses.net>
|
||||
pkgname=crosslang # '-bzr', '-git', '-hg' or '-svn'
|
||||
pkgver=1.0.0
|
||||
pkgver=0.0.2
|
||||
pkgrel=1
|
||||
pkgdesc=""
|
||||
arch=('x86_64' 'powerpc')
|
||||
@@ -21,18 +21,7 @@ fi
|
||||
# Please refer to the 'USING VCS SOURCES' section of the PKGBUILD man page for
|
||||
# a description of each element in the source array.
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname}"
|
||||
|
||||
# The examples below are not absolute and need to be adapted to each repo. The
|
||||
# primary goal is to generate version numbers that will increase according to
|
||||
# pacman's version comparisons with later commits to the repo. The format
|
||||
# VERSION='VER_NUM.rREV_NUM.HASH', or a relevant subset in case VER_NUM or HASH
|
||||
# are not available, is recommended.
|
||||
|
||||
# Git, no tags available
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "$srcdir/${pkgname}"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export BUILD=$(($BUILD_NO-142))
|
||||
export DEB_VERSION=1.0.0-$BUILD
|
||||
|
||||
export DEB_VERSION=0.0.2
|
||||
7
changelog.md
Normal file
7
changelog.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Changelog
|
||||
|
||||
## 0.0.2
|
||||
Add uuids and bytestreams
|
||||
|
||||
## 0.0.1
|
||||
Start versioning
|
||||
@@ -1 +0,0 @@
|
||||
# C++ Layer
|
||||
@@ -1,232 +0,0 @@
|
||||
Extending the runtime
|
||||
=====================
|
||||
|
||||
See [this](CPP_LAYER.md)
|
||||
|
||||
There are a couple ways of doing this
|
||||
|
||||
- Creating a shared library (only works if using shared libs)
|
||||
- Embeding the runtime
|
||||
- Forking crosslang and adding functionality (I don't support pull requests at this time)
|
||||
|
||||
### Shared Library
|
||||
|
||||
This assumes you are on linux, if on windows use MyPlugin.dll on mac libMyPlugin.dylib in crosslang project (it would be a good idea to check Env.Platform)
|
||||
|
||||
CMakeLists.txt:
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(MyPlugin)
|
||||
|
||||
find_package(TessesCrossLang REQUIRED)
|
||||
|
||||
add_library(MyPlugin SHARED lib.cpp)
|
||||
|
||||
target_link_libraries(MyPlugin PUBLIC TessesCrossLang::crosslang_shared)
|
||||
```
|
||||
|
||||
lib.cpp:
|
||||
```c++
|
||||
#include <CrossLang.hpp>
|
||||
|
||||
using namespace Tesses::CrossLang;
|
||||
|
||||
void MyPlugin(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls,{
|
||||
TDItem("MyFunction", TExternalMethod::Create(ls, "A description for function",{"myLong","$optionalList"},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
int64_t n;
|
||||
if(GetArgument(args,0,n))
|
||||
{
|
||||
TList* myLs;
|
||||
if(GetArgumentHeap(args,1,myLs))
|
||||
{
|
||||
//do something with the list
|
||||
myLs->Add(n);
|
||||
return TList::Create(ls, {n,myLs});
|
||||
}
|
||||
|
||||
|
||||
return TList::Create(ls, {n});
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}))
|
||||
});
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->SetVariable("MyPlugin",dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
|
||||
CROSSLANG_PLUGIN(MyPlugin);
|
||||
|
||||
```
|
||||
|
||||
main.tcross:
|
||||
```go
|
||||
func main(args)
|
||||
{
|
||||
Reflection.LoadNativePlugin(FS.MakeFull("libMyPlugin.so"));
|
||||
|
||||
var res = MyPlugin.MyFunction(42);
|
||||
if(TypeOf(res) == "List")
|
||||
{
|
||||
Console.WriteLine(res);
|
||||
}
|
||||
|
||||
var res = MyPlugin.MyFunction(42,["Hello","John"]);
|
||||
if(TypeOf(res) == "List")
|
||||
{
|
||||
Console.WriteLine(res);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Embeding the runtime
|
||||
|
||||
CMakeLists.txt:
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(MyCrossLangBinary)
|
||||
|
||||
find_package(TessesCrossLang REQUIRED)
|
||||
|
||||
add_executable(MyCrossLangBinary SHARED app.cpp)
|
||||
|
||||
target_link_libraries(MyCrossLangBinary PUBLIC TessesCrossLang::crosslang_shared) # or crosslang_static for static linking
|
||||
|
||||
|
||||
```
|
||||
|
||||
app.cpp:
|
||||
```c++
|
||||
#include <CrossLang.hpp>
|
||||
|
||||
using namespace Tesses::CrossLang;
|
||||
using namespace Tesses::Framework;
|
||||
|
||||
void MyPlugin(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls,{
|
||||
TDItem("MyFunction", TExternalMethod::Create(ls, "A description for function",{"myLong","$optionalList"},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
int64_t n;
|
||||
if(GetArgument(args,0,n))
|
||||
{
|
||||
TList* myLs;
|
||||
if(GetArgumentHeap(args,1,myLs))
|
||||
{
|
||||
//do something with the list
|
||||
myLs->Add(n);
|
||||
return TList::Create(ls, {n,myLs});
|
||||
}
|
||||
|
||||
|
||||
return TList::Create(ls, {n});
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}))
|
||||
});
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->SetVariable("MyPlugin",dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
TF_Init();
|
||||
if(argc < 2)
|
||||
{
|
||||
printf("USAGE: %s <filename.crvm> <args...>\n",argv[0]);
|
||||
return 1;
|
||||
}
|
||||
GC gc;
|
||||
gc.RegisterEverythingCallback(MyPlugin);
|
||||
gc.Start();
|
||||
GCList ls(gc);
|
||||
TRootEnvironment* env = TRootEnvironment::Create(ls,TDictionary::Create(ls));
|
||||
Tesses::Framework::Filesystem::LocalFilesystem fs;
|
||||
TStd::RegisterStd(&gc,env);
|
||||
env->LoadFileWithDependencies(&gc, &fs, fs.SystemToVFSPath(argv[1]));
|
||||
|
||||
TList* args = TList::Create(ls);
|
||||
for(int arg=1;arg<argc;arg++)
|
||||
args->Add(std::string(argv[arg]));
|
||||
|
||||
auto res = env->CallFunction(ls,"main",{args});
|
||||
int64_t iresult;
|
||||
if(GetObject(res,iresult))
|
||||
return (int)iresult;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
main.tcross (needs to be compiled with crossc):
|
||||
```go
|
||||
func main(args)
|
||||
{
|
||||
//no reflection necessary
|
||||
|
||||
var res = MyPlugin.MyFunction(42);
|
||||
if(TypeOf(res) == "List")
|
||||
{
|
||||
Console.WriteLine(res);
|
||||
}
|
||||
|
||||
var res = MyPlugin.MyFunction(42,["Hello","John"]);
|
||||
if(TypeOf(res) == "List")
|
||||
{
|
||||
Console.WriteLine(res);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Forking (implementing it in runtime library itself)
|
||||
- edit include/CrossLang.hpp
|
||||
- in TStd class insert, static void RegisterMyPlugin(GC* gc, TRootEnvironment* env); where MyPlugin is whatever you want
|
||||
- edit src/runtime_methods/std.cpp
|
||||
- in TStd::RegisterStd before register everything call TStd::RegisterMyPlugin(gc, env);
|
||||
- in CMakeLists.txt within list(APPEND CROSSLANG_SOURCE **Many Source Files**) you must add src/runtime_methods/myplugin.cpp
|
||||
|
||||
src/runtime_methods/myplugin.cpp:
|
||||
```c++
|
||||
#include <CrossLang.hpp>
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
void TStd::RegisterMyPlugin(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls,{
|
||||
TDItem("MyFunction", TExternalMethod::Create(ls, "A description for function",{"myLong","$optionalList"},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
int64_t n;
|
||||
if(GetArgument(args,0,n))
|
||||
{
|
||||
TList* myLs;
|
||||
if(GetArgumentHeap(args,1,myLs))
|
||||
{
|
||||
//do something with the list
|
||||
myLs->Add(n);
|
||||
return TList::Create(ls, {n,myLs});
|
||||
}
|
||||
|
||||
|
||||
return TList::Create(ls, {n});
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}))
|
||||
});
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->SetVariable("MyPlugin",dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
```
|
||||
598
docs/HANDBOOK.md
598
docs/HANDBOOK.md
@@ -1,598 +0,0 @@
|
||||
## CrossLang Handbook
|
||||
|
||||
This is a book for my language found [here](https://crosslang.tesseslanguage.com/)
|
||||
|
||||
## Statements and loops
|
||||
|
||||
|
||||
|
||||
#### Declare a variable (it is an expression)
|
||||
|
||||
You can (the var is optional but should be used if the root environment has the same variable and you don't want to set it)
|
||||
|
||||
```js
|
||||
var myVariable = 42;
|
||||
```
|
||||
|
||||
#### Set a variable (it is an expression)
|
||||
|
||||
```js
|
||||
myVariable = "I have set the variable to a string";
|
||||
```
|
||||
|
||||
#### Reflective variables
|
||||
|
||||
```js
|
||||
var nameOfVariable = "Var 1";
|
||||
.[nameOfVariable] = 42; //the variable name in this instance will be Var 1
|
||||
Console.WriteLine(.[nameOfVariable]); //prints 42
|
||||
|
||||
|
||||
var nameOfVariable2 = "Var 2";
|
||||
var nameOfField = "This field has spaces and \n New Lines";
|
||||
.[nameOfVariable2] = {
|
||||
.[nameOfField] = "Hello, world"
|
||||
};
|
||||
|
||||
Console.WriteLine(.[nameOfVariable2].[nameOfField]); //should print Hello, world
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### If statements
|
||||
|
||||
The {} are optional if you only need one statement
|
||||
|
||||
```js
|
||||
var myExpression = 0;
|
||||
var myOtherExpression = {
|
||||
mol = 42
|
||||
};
|
||||
|
||||
if(myExpression)
|
||||
{
|
||||
Console.WriteLine("myExpression is truthy");
|
||||
}
|
||||
else if(myOtherExpression)
|
||||
{
|
||||
//this will run based on the condition
|
||||
Console.WriteLine("myExpression is falsey but myOtherExpression is truthy");
|
||||
}
|
||||
else {
|
||||
Console.WriteLine("both myExpression and myOtherExpression are falsey");
|
||||
}
|
||||
```
|
||||
|
||||
#### For loop
|
||||
|
||||
Note: i will leak, also you can use curly brackets like if
|
||||
|
||||
```js
|
||||
for(var i = 0; i < 42; i++)
|
||||
Console.WriteLine(i);
|
||||
```
|
||||
|
||||
#### Each loop
|
||||
|
||||
```js
|
||||
enumerable MyItterator()
|
||||
{
|
||||
yield 42;
|
||||
yield 100;
|
||||
yield 88;
|
||||
}
|
||||
each(var item : MyItterator())
|
||||
{
|
||||
Console.WriteLine(item);
|
||||
}
|
||||
|
||||
|
||||
each(var item : [3,7,12])
|
||||
{
|
||||
Console.WriteLine(item);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This should output
|
||||
42
|
||||
100
|
||||
88
|
||||
3
|
||||
7
|
||||
12
|
||||
*/
|
||||
```
|
||||
|
||||
#### While loop
|
||||
|
||||
```js
|
||||
while(conditionLikeIf)
|
||||
{
|
||||
Console.WriteLine("Hi");
|
||||
}
|
||||
|
||||
//If conditionLikeIf is falsey we never print Hi
|
||||
//If conditionLikeIf is truthy we print Hi until it is falsey
|
||||
```
|
||||
|
||||
#### Do loop
|
||||
|
||||
```js
|
||||
do(conditionLikeIf)
|
||||
{
|
||||
Console.WriteLine("Hi");
|
||||
}
|
||||
|
||||
//If conditionLikeIf is falsey we print Hi once
|
||||
//If conditionLikeIf is truthy we print Hi until it is falsey
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### Try statement
|
||||
|
||||
NOTE: you can't return undefined (but you can return other types) (It will just return from try and will still execute the body past the try statement) due to the try statement being a closure (you can still break and continue due to special TObjects being returned)
|
||||
|
||||
```js
|
||||
try {
|
||||
Console.WriteLine("God is good.");
|
||||
throw "my error";
|
||||
Console.WriteLine("I am lonely, I am never called.");
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
Console.WriteLine($"I got an error {ex}.");
|
||||
}
|
||||
finally {
|
||||
Console.WriteLine("For God so loved the world that he gave his only begotten Son, that whoever believes in him should not perish but have eternal life.");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This should print
|
||||
God is good.
|
||||
I got an error my error.
|
||||
For God so loved the world that he gave his only begotten Son, that whoever believes in him should not perish but have eternal life.
|
||||
*/
|
||||
```
|
||||
|
||||
#### Switch statement
|
||||
|
||||
NOTE: you can use dictionaries with overloaded equals operator (we will pass the switch's expression as the argument)
|
||||
|
||||
```js
|
||||
o = {
|
||||
operator== = (this,v) => {
|
||||
//this is implicitly passed by runtime, but you must declare it if you want it
|
||||
return (v * 7) == 42;
|
||||
}
|
||||
};
|
||||
|
||||
var val = 6;
|
||||
|
||||
switch(val)
|
||||
{
|
||||
case 4:
|
||||
Console.WriteLine("I am four");
|
||||
break;
|
||||
case 5:
|
||||
Console.WriteLine("I am five");
|
||||
break;
|
||||
case o:
|
||||
Console.WriteLine("Hitchhiker's guide to the galaxy meaning of life");
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("We don't support it we are sorry");
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### Function declaration
|
||||
|
||||
```go
|
||||
//you can create functions on dictionaries so long as they are on root environment (they are declared there before root scope is evaluated so this is possible)
|
||||
My.Func.Joel = 59; //Because My.Func.Is.A.Few.Deep creates the dictionaries via runtime
|
||||
|
||||
func My.Func.Is.A.Few.Deep(a, b)
|
||||
{
|
||||
return a * b;
|
||||
}
|
||||
func main(args)
|
||||
{
|
||||
Console.WriteLine(My.Func.Is.A.Few.Deep(6,7));
|
||||
}
|
||||
```
|
||||
|
||||
#### Function inside a function
|
||||
|
||||
Oh yeah functions can have exclusively a expression as a body which does not need a return keyword
|
||||
|
||||
```go
|
||||
func main(args)
|
||||
{
|
||||
func MyOther(a,b) a * b;
|
||||
Console.WriteLine(MyOther(a,b));
|
||||
}
|
||||
```
|
||||
|
||||
#### Document a function
|
||||
|
||||
```go
|
||||
/^
|
||||
This function returns 42
|
||||
^/
|
||||
func MyFunction() 42;
|
||||
```
|
||||
|
||||
#### Return statement
|
||||
|
||||
You can also return nothing
|
||||
|
||||
```js
|
||||
return 42;
|
||||
return;
|
||||
```
|
||||
|
||||
#### Yield statement
|
||||
|
||||
This will halt the function's execution and return the running function object (were you can pop the item and resume it)
|
||||
|
||||
To automaticly make a function enumerable (with each statement) you must use ``enumerable`` instead of func when declaring your function
|
||||
|
||||
```js
|
||||
yield 42;
|
||||
```
|
||||
|
||||
#### Throw statement
|
||||
|
||||
You can catch this with ``try statement`` with ``catch`` clause
|
||||
|
||||
```js
|
||||
throw "You can replace me with another string or any other object";
|
||||
```
|
||||
|
||||
#### Defer statement
|
||||
|
||||
Your code will be called when your scope is destroyed
|
||||
|
||||
```go
|
||||
{
|
||||
defer {
|
||||
Console.WriteLine("In defer");
|
||||
}
|
||||
Console.WriteLine("About to leave scope");
|
||||
}
|
||||
Console.WriteLine("Left scope");
|
||||
|
||||
|
||||
/*
|
||||
The output should be
|
||||
|
||||
About to leave scope
|
||||
In defer
|
||||
Left scope
|
||||
*/
|
||||
```
|
||||
|
||||
## Expressions
|
||||
|
||||
We will place it as a parameter to a function ``doThing`` but these will work anywhere like setting a variable or another expression
|
||||
|
||||
#### Undefined
|
||||
|
||||
```js
|
||||
doThing(undefined);
|
||||
```
|
||||
|
||||
#### Null
|
||||
|
||||
```js
|
||||
doThing(null);
|
||||
```
|
||||
|
||||
#### Boolean
|
||||
|
||||
```js
|
||||
doThing(false);
|
||||
doThing(true);
|
||||
```
|
||||
|
||||
#### Long
|
||||
|
||||
A signed 64 bit number
|
||||
|
||||
```js
|
||||
doThing(94);
|
||||
doThing(599929022);
|
||||
```
|
||||
|
||||
#### Double
|
||||
|
||||
A 64 bit floating pointer number
|
||||
|
||||
```js
|
||||
doThing(5.25);
|
||||
doThing(942.90204);
|
||||
```
|
||||
|
||||
#### Char
|
||||
|
||||
Yes we support single character strings (this escapes a double quote)
|
||||
|
||||
```csharp
|
||||
doThing('\"');
|
||||
```
|
||||
|
||||
#### String
|
||||
|
||||
Second is an interopolated string
|
||||
|
||||
```csharp
|
||||
doThing("Hi");
|
||||
doThing($"My name is {name}");
|
||||
```
|
||||
|
||||
#### List
|
||||
|
||||
```js
|
||||
doThing(
|
||||
[4,5,9,42,true,"Hi",'\n']
|
||||
);
|
||||
```
|
||||
|
||||
#### Dictionary
|
||||
|
||||
```js
|
||||
doThing(
|
||||
{
|
||||
a = "This is an option",
|
||||
b = 42,
|
||||
c = 9
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
###### Enumerating a dictionary
|
||||
|
||||
```js
|
||||
var dict = { a = 5, b = 42};
|
||||
each(var item : Dictionary.Items(dict))
|
||||
{
|
||||
Console.WriteLine($"Key: {item.Key}");
|
||||
Console.WriteLine($"Value: {item.Value}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
/*
|
||||
This prints
|
||||
Key: a
|
||||
Value: 5
|
||||
|
||||
Key: b
|
||||
Value: 42
|
||||
|
||||
*/
|
||||
```
|
||||
|
||||
|
||||
|
||||
###### Getting a value from dictionary
|
||||
|
||||
```go
|
||||
func doThing(data)
|
||||
{
|
||||
Console.WriteLine(data.b); //will print 42
|
||||
}
|
||||
```
|
||||
|
||||
###### Setting a value to dictionary
|
||||
|
||||
```go
|
||||
func doThing(data)
|
||||
{
|
||||
data.a = true; //replace a with a different value
|
||||
data.someFieldThatDoesNotExist = 9; //define a new field entirely
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
###### Methods
|
||||
|
||||
Note that this is optional but if you do have it it must be the first argument, the this argument points to the dictionary
|
||||
|
||||
```go
|
||||
var item = {
|
||||
myMethod = (this, a, b) => {
|
||||
return a * b;
|
||||
}
|
||||
};
|
||||
|
||||
Console.WriteLine(item.myMethod(6,7)); //prints 42
|
||||
```
|
||||
|
||||
Or
|
||||
|
||||
```go
|
||||
var item = {};
|
||||
func item.myMethod(this, a, b)
|
||||
{
|
||||
return a * b;
|
||||
}
|
||||
Console.WriteLine(item.myMethod(6,7)); //prints 42
|
||||
```
|
||||
|
||||
###### Properties
|
||||
|
||||
They are declared like every other method except they are prefixed with ``get`` or ``set``
|
||||
|
||||
```go
|
||||
var item = {
|
||||
getProp = (this)=>{
|
||||
return 42;
|
||||
},
|
||||
setProp = (this,v)=>{
|
||||
//do something with v
|
||||
}
|
||||
};
|
||||
|
||||
Console.WriteLine(item.Prop); //equivalent to Console.WriteLine(item.getProp());
|
||||
|
||||
item.Prop = 100; //equivalent to item.setProp(100); will do nothing in this example
|
||||
|
||||
```
|
||||
|
||||
###### Operator overloading
|
||||
|
||||
```js
|
||||
var item = {
|
||||
operator+ = (this,right) => {
|
||||
return 4 + a;
|
||||
}
|
||||
operator- = (this,right) => {
|
||||
return 4 - right; //be careful right may be undefined if the negate operator is used
|
||||
}
|
||||
};
|
||||
|
||||
Console.WriteLine(item + 5); //prints 9
|
||||
```
|
||||
|
||||
###### Array operator overloading
|
||||
|
||||
```js
|
||||
var item = {
|
||||
GetAt = (index)=>{
|
||||
return index * 2; //we multiply index by two and return
|
||||
},
|
||||
SetAt => (index,value)=>{
|
||||
Console.WriteLine($"The index was {index} and value was {value}");
|
||||
}
|
||||
};
|
||||
|
||||
Console.WriteLine(item[21]); //prints 42
|
||||
item["Hi"] = "John"; //prints The index was Hi and value was John
|
||||
```
|
||||
|
||||
#### ByteArray
|
||||
|
||||
```js
|
||||
var bA = new ByteArray(1);
|
||||
ba[0] = 42;
|
||||
Console.WriteLine(ba.ToString()); //prints *
|
||||
```
|
||||
|
||||
###### ByteArray from string
|
||||
|
||||
```js
|
||||
var bA = new ByteArray("Hi");
|
||||
//we can get bytes like this bA[0] which will be 72
|
||||
//we can get length by bA.Count or bA.Length
|
||||
```
|
||||
|
||||
#### Embedding files (you can't do this easily in C/C++ and C# not as easy as this)
|
||||
|
||||
```js
|
||||
var bA = embed("myFile.png"); //will embed the file res/myFile.png
|
||||
//it is stored as a RESO in the crvm file and bA is a ByteArray
|
||||
//note the argument MUST be a constant string
|
||||
//note you can access a subdirectory of res as well just use dir/file.bin
|
||||
```
|
||||
|
||||
#### Streams
|
||||
|
||||
|
||||
|
||||
###### From an existing file
|
||||
|
||||
```js
|
||||
var strm = FS.Local.OpenFile("file.bin","rb");
|
||||
|
||||
var data = new ByteArray(1024);
|
||||
var read = strm.Read(data,0,data.Count);
|
||||
//use ReadBlock to ensure you have 1024 bytes if not near end of stream
|
||||
|
||||
//use WriteBlock to ensure you write the amount you say you need
|
||||
|
||||
strm.Close();
|
||||
```
|
||||
|
||||
#### VFS
|
||||
|
||||
```js
|
||||
var myVFS = FS.Local; //FS.Local is the local filesystem
|
||||
|
||||
|
||||
myVFS.CreateDirectory("myDir"); //creates directory in current dir (only local)
|
||||
|
||||
myVFS.DeleteDirectory("myDir"); //now we delete it
|
||||
|
||||
|
||||
myVFS.CreateDirectory(Path.FromString(Env.Downloads) / "Folder in Downloads"); //Create a folder in downloads
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### Path
|
||||
|
||||
```js
|
||||
var path = / "Path" / "To" / "Directory";
|
||||
var relativePath = ./"another"/"path";
|
||||
var combined = path / relativePath;
|
||||
var someString = "joel";
|
||||
var combinedAndStr = combined / someString;
|
||||
var combinedWithExtension = combined + ".mp4";
|
||||
Console.WriteLine(combined); // outputs /Path/To/Directory/another/path
|
||||
Console.WriteLine(combined); // outputs /Path/To/Directory/another/path/joel
|
||||
Console.WriteLine(combinedWithExtension); //outputs /Path/To/Directory/another/path.mp4
|
||||
//these paths are used with vfs
|
||||
|
||||
|
||||
//to get parent directory use combined.GetParent();
|
||||
//to get filename use combined.GetFileName();
|
||||
//to get extension use combinedWithExtension.GetExtension();, it will be the extension including .
|
||||
//to change the extension use combinedWithExtension.ChangeExtension(".mkv");
|
||||
//to remove the extension use combinedWithExtension.ChangeExtension(null); or combinedWithExtension.ChangeExtension();
|
||||
```
|
||||
|
||||
#### Html Litterals
|
||||
```go
|
||||
//comments are just crosslang ones
|
||||
|
||||
//we will be setting to myHtml for the html (returns a string) (it is already html escaped)
|
||||
myHtml = <h1>{someStringExpression}</h1>;
|
||||
|
||||
//a link, in this example we have a dictionary named node with string fields href and text
|
||||
//lets say node.text equaled List<int> and href contained ./mypage?name=Joel&file=steve.bin myHtml would be equal to "<a target=\"_blank\" href=\"./mypage?name=Joel&file=steve.bin\">List<int></a>" (the \ are just there to make this a valid string for demonstration purposes, there aren't really backslashes)
|
||||
myHtml = <a target="_blank" href={node.href}>{node.text}</a>;
|
||||
|
||||
|
||||
//for (works like for loop but is in html form, the for part is not rendered in the final string)
|
||||
myHtml = <for(var i = 0; i < 42; i++)>
|
||||
<h6>{i}</h6>
|
||||
</for>;
|
||||
|
||||
//each
|
||||
myHtml = <each(var item : list)></each>;
|
||||
|
||||
//do
|
||||
myHtml = <do(expr == 42)></do>;
|
||||
|
||||
//while
|
||||
myHtml = <while(expr == 42)></while>;
|
||||
|
||||
//if
|
||||
|
||||
myHtml = <if(expr == 42)>
|
||||
<true>
|
||||
//if expr is 42
|
||||
</true>
|
||||
<false>
|
||||
//if expr is not 42
|
||||
//you would use another if here instead of else if
|
||||
</false>
|
||||
</if>;
|
||||
|
||||
myHtml = <null>Hello</null>; //would just be Hello (useful for templating as it works just like div but the null part is not emited into string)
|
||||
|
||||
myHtml = <raw(stringExpr)>; //allowing you to emit unescaped html from string into html litteral (useful for templating)
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
# Tesses CrossLang
|
||||
|
||||
This is the docs for my language
|
||||
|
||||
- [Handbook](HANDBOOK.md)
|
||||
- [C++ Layer](CPP_LAYER.md)
|
||||
- [Extend the runtime](EXTENDING_RUNTIME.md)
|
||||
@@ -1,16 +0,0 @@
|
||||
What is TObject
|
||||
===============
|
||||
|
||||
It is a std::variant that can be (not in that order)
|
||||
|
||||
- Undefined (std::monostate)
|
||||
- Null (std::nullptr_t)
|
||||
- Long (int64_t)
|
||||
- Double (double)
|
||||
- Char (char)
|
||||
- String (std::string)
|
||||
- Version (Tesses::CrossLang::TVMVersion)
|
||||
- Regex (std::regex)
|
||||
- Path (Tesses::Framework::Filesystem::VFSPath)
|
||||
- MethodInvoker (Tesses::CrossLang::MethodInvoker)
|
||||
- HeapObjects (Tesses::CrossLang::THeapObjectHolder)
|
||||
@@ -19,31 +19,14 @@
|
||||
#include <time.h>
|
||||
#include <any>
|
||||
|
||||
/**
|
||||
* @brief CrossLang Runtime Major version
|
||||
*
|
||||
*/
|
||||
#define TVM_MAJOR 1
|
||||
/**
|
||||
* @brief CrossLang Runtime Minor version
|
||||
*
|
||||
*/
|
||||
#define TVM_MINOR 0
|
||||
/**
|
||||
* @brief CrossLang Runtime Patch version
|
||||
*
|
||||
*/
|
||||
#define TVM_PATCH 0
|
||||
/**
|
||||
* @brief CrossLang Runtime Build version
|
||||
*
|
||||
*/
|
||||
#define TVM_BUILD 0
|
||||
/**
|
||||
* @brief CrossLang Runtime Stage version
|
||||
*
|
||||
*/
|
||||
#define TVM_VERSIONSTAGE DevVersion
|
||||
#include "CrossLangVersion.h"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
|
||||
#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_VERSIONSTAGE DevVersion
|
||||
|
||||
#if defined(_WIN32)
|
||||
#undef Yield
|
||||
@@ -341,13 +324,13 @@ namespace Tesses::CrossLang {
|
||||
return v;
|
||||
}
|
||||
/**
|
||||
* @brief Compares this to the runtime version
|
||||
* @brief Compares this to the runtime version (for Bytecode)
|
||||
*
|
||||
* @return int CompareTo(RuntimeVersion) where RuntimeVersion is the runtime version
|
||||
*/
|
||||
int CompareToRuntime()
|
||||
{
|
||||
TVMVersion version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
TVMVersion version(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE);
|
||||
return CompareTo(version);
|
||||
}
|
||||
/**
|
||||
@@ -1422,7 +1405,7 @@ class TContinue {
|
||||
*
|
||||
*/
|
||||
|
||||
using TObject = std::variant<int64_t,double,char,bool,std::string,std::regex,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder,TVMVersion,std::shared_ptr<Tesses::Framework::Date::DateTime>,std::shared_ptr<Tesses::Framework::Date::TimeSpan>,TBreak,TContinue,std::shared_ptr<Tesses::Framework::Streams::Stream>,std::shared_ptr<Tesses::Framework::Filesystem::VFS>,std::shared_ptr<Tesses::Framework::Http::IHttpServer>,std::shared_ptr<Tesses::Framework::Http::HttpRequestBody>,std::shared_ptr<Tesses::Framework::TextStreams::TextReader>,std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>;
|
||||
using TObject = std::variant<int64_t,double,char,bool,std::string,std::regex,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder,TVMVersion,std::shared_ptr<Tesses::Framework::Date::DateTime>,std::shared_ptr<Tesses::Framework::Date::TimeSpan>,TBreak,TContinue,std::shared_ptr<Tesses::Framework::Streams::Stream>,std::shared_ptr<Tesses::Framework::Filesystem::VFS>,std::shared_ptr<Tesses::Framework::Http::IHttpServer>,std::shared_ptr<Tesses::Framework::Http::HttpRequestBody>,std::shared_ptr<Tesses::Framework::TextStreams::TextReader>,std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>,std::shared_ptr<Tesses::Framework::Streams::ByteReader>,std::shared_ptr<Tesses::Framework::Streams::ByteWriter>, Tesses::Framework::Uuid>;
|
||||
|
||||
class TRootEnvironment;
|
||||
class GC;
|
||||
@@ -1859,6 +1842,7 @@ class GC {
|
||||
class TStd {
|
||||
private:
|
||||
static void RegisterHelpers(GC* gc, TRootEnvironment* env);
|
||||
static void RegisterUuid(GC* gc, TRootEnvironment* env);
|
||||
public:
|
||||
static void RegisterStd(GC* gc, TRootEnvironment* env);
|
||||
static void RegisterConsole(GC* gc,TRootEnvironment* env);
|
||||
@@ -1875,6 +1859,7 @@ class GC {
|
||||
static void RegisterEnv(GC* gc, TRootEnvironment* env);
|
||||
static void RegisterProcess(GC* gc, TRootEnvironment* env);
|
||||
static void RegisterClass(GC* gc, TRootEnvironment* env);
|
||||
|
||||
};
|
||||
|
||||
class TSubEnvironment : public TEnvironment
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Tesses::CrossLang
|
||||
|
||||
uint8_t main_header[18];
|
||||
memcpy(main_header,"TCROSSVM",8);
|
||||
TVMVersion rtVersion(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
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));
|
||||
|
||||
@@ -773,7 +773,7 @@ namespace Tesses::CrossLang {
|
||||
void Save(std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs, std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
|
||||
TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
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);
|
||||
|
||||
@@ -380,7 +380,7 @@ namespace Tesses::CrossLang
|
||||
|
||||
void CodeGen::Save(std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
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);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
@@ -131,6 +132,10 @@ namespace Tesses::CrossLang
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return list;
|
||||
}
|
||||
static TObject Env_getLittleEndian(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return Tesses::Framework::Serialization::BitConverter::IsLittleEndian();
|
||||
}
|
||||
void TStd::RegisterEnv(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
|
||||
@@ -155,6 +160,7 @@ namespace Tesses::CrossLang
|
||||
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);
|
||||
|
||||
@@ -172,15 +172,157 @@ namespace Tesses::CrossLang
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class FS_Watcher : public TNativeObject {
|
||||
public:
|
||||
std::shared_ptr<Tesses::Framework::Filesystem::FSWatcher> watcher;
|
||||
|
||||
FS_Watcher(std::shared_ptr<Tesses::Framework::Filesystem::FSWatcher> watcher): watcher(watcher)
|
||||
{}
|
||||
|
||||
TObject CallMethod(GCList& ls, std::string name, std::vector<TObject> 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<TObject> args)->TObject
|
||||
{
|
||||
int64_t n;
|
||||
if(GetArgument(args,0,n))
|
||||
{
|
||||
auto myevt = evt;
|
||||
return myevt.IsEvent((Tesses::Framework::Filesystem::FSWatcherEventType)n);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
auto toString = TExternalMethod::Create(ls,"",{},[evt](GCList& ls, std::vector<TObject> 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});
|
||||
}
|
||||
};
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
std::string TypeName() {
|
||||
return "FSWatcher";
|
||||
}
|
||||
};
|
||||
|
||||
TObject New_FSWatcher(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
|
||||
Tesses::Framework::Filesystem::VFSPath path;
|
||||
if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path))
|
||||
{
|
||||
return TNativeObject::Create<FS_Watcher>(ls,Tesses::Framework::Filesystem::FSWatcher::Create(vfs,path));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TStd::RegisterIO(GC* gc,TRootEnvironment* env,bool enableLocalFilesystem)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterIO=true;
|
||||
env->permissions.canRegisterLocalFS = enableLocalFilesystem;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
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(enableLocalFilesystem)
|
||||
{
|
||||
|
||||
@@ -202,7 +344,7 @@ namespace Tesses::CrossLang
|
||||
|
||||
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);
|
||||
env->DeclareVariable("FS", dict);
|
||||
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,11 @@
|
||||
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Streams/Stream.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#if defined(CROSSLANG_ENABLE_SHARED)
|
||||
#if defined(CROSSLANG_ENABLE_FFI)
|
||||
#include <ffi.h>
|
||||
@@ -568,6 +574,23 @@ namespace Tesses::CrossLang
|
||||
std::shared_ptr<Tesses::Framework::TextStreams::TextWriter> strm;
|
||||
return GetArgument(args,0,strm);
|
||||
}
|
||||
static TObject TypeIsByteReader(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
std::shared_ptr<Tesses::Framework::Streams::ByteReader> strm;
|
||||
return GetArgument(args,0,strm);
|
||||
}
|
||||
static TObject TypeIsByteWriter(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
std::shared_ptr<Tesses::Framework::Streams::ByteWriter> strm;
|
||||
return GetArgument(args,0,strm);
|
||||
}
|
||||
static TObject TypeIsUuid(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
return std::holds_alternative<Tesses::Framework::Uuid>(args[0]);
|
||||
}
|
||||
static TObject TypeIsVFS(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
@@ -741,6 +764,11 @@ namespace Tesses::CrossLang
|
||||
if(std::holds_alternative<TVMVersion>(_obj)) return "Version";
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(_obj)) return "DateTime";
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(_obj)) return "TimeSpan";
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::ByteReader>>(_obj)) return "ByteReader";
|
||||
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::ByteWriter>>(_obj)) return "ByteWriter";
|
||||
|
||||
if(std::holds_alternative<Tesses::Framework::Uuid>(_obj)) return "Uuid";
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::Stream>>(_obj))
|
||||
{
|
||||
auto strm = std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(_obj);
|
||||
@@ -1222,6 +1250,21 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject New_ByteReader(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||
if(GetArgument(args, 0, strm))
|
||||
return std::make_shared<Tesses::Framework::Streams::ByteReader>(strm);
|
||||
return nullptr;
|
||||
}
|
||||
static TObject New_ByteWriter(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||
if(GetArgument(args, 0, strm))
|
||||
return std::make_shared<Tesses::Framework::Streams::ByteWriter>(strm);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TStd::RegisterRoot(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
GCList ls(gc);
|
||||
@@ -1230,6 +1273,8 @@ namespace Tesses::CrossLang
|
||||
|
||||
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);
|
||||
@@ -1269,6 +1314,10 @@ namespace Tesses::CrossLang
|
||||
task->DeclareFunction(gc, "FromResult", "async from result", {"result"}, Task_FromResult);
|
||||
|
||||
TDictionary* newTypes = env->EnsureDictionary(gc, "New");
|
||||
|
||||
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);
|
||||
@@ -1339,6 +1388,9 @@ namespace Tesses::CrossLang
|
||||
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);
|
||||
|
||||
|
||||
newTypes->DeclareFunction(gc, "Regex", "Create regex object",{"regex"},[](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
|
||||
40
src/runtime_methods/uuid.cpp
Normal file
40
src/runtime_methods/uuid.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
static TObject Uuid_NewUuid(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return Tesses::Framework::Uuid::Generate();
|
||||
}
|
||||
static TObject Uuid_TryParse(GCList& ls, std::vector<TObject> 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<TObject> 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(GC* 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();
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,7 @@ namespace Tesses::CrossLang
|
||||
|
||||
std::string name = "Out";
|
||||
std::vector<std::pair<std::string,std::string>> sources;
|
||||
TVMVersion version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
TVMVersion version(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE);
|
||||
std::vector<std::pair<std::string,TVMVersion>> dependencies;
|
||||
std::vector<std::pair<std::string,TVMVersion>> tools;
|
||||
std::string info;
|
||||
@@ -359,7 +359,10 @@ namespace Tesses::CrossLang
|
||||
|
||||
dict->DeclareFunction(gc, "SourceToAst", "Convert source to ast", {"source"}, VM_SourceToAst);
|
||||
dict->DeclareFunction(gc, "getRuntimeVersion","Get the runtime version",{},[](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
return TVMVersion(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
return TVMVersion(CROSSLANG_MAJOR,CROSSLANG_MINOR,CROSSLANG_PATCH,0,TVMVersionStage::DevVersion);
|
||||
});
|
||||
dict->DeclareFunction(gc, "getBytecodeVersion","Get the bytecode version",{},[](GCList& ls,std::vector<TObject> 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<TObject> args)->TObject {
|
||||
return Tesses::Framework::TF_IsRunning();
|
||||
|
||||
164
src/vm/bc/add.cpp
Normal file
164
src/vm/bc/add.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::Add(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||
GCList ls(gc);
|
||||
auto right = cse.back()->Pop(ls);
|
||||
auto left = cse.back()->Pop(ls);
|
||||
|
||||
|
||||
|
||||
if(std::holds_alternative<std::string>(left) && std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<std::string>(left) + std::get<Tesses::Framework::Filesystem::VFSPath>(right));
|
||||
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
cse.back()->Push(gc,(char)(std::get<char>(left) + std::get<char>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (char)(std::get<int64_t>(left) + std::get<char>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (char)(std::get<char>(left) + std::get<int64_t>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(left) && std::holds_alternative<std::string>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<Tesses::Framework::Filesystem::VFSPath>(left) + std::get<std::string>(right));
|
||||
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(left) && std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<Tesses::Framework::Filesystem::VFSPath>(left) + std::get<Tesses::Framework::Filesystem::VFSPath>(right));
|
||||
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<int64_t>(left) + std::get<int64_t>(right));
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<double>(left) + std::get<double>(right));
|
||||
}
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<double>(left) + std::get<int64_t>(right));
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<int64_t>(left) + std::get<double>(right));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::TimeSpan>((*l) + (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::DateTime>((*l) + (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::DateTime>((*l) + (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
|
||||
{
|
||||
std::string str={};
|
||||
str.append(std::get<std::string>(left));
|
||||
str.append(std::get<std::string>(right));
|
||||
cse.back()->Push(gc,str);
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<std::string>(right))
|
||||
{
|
||||
std::string str={};
|
||||
str.push_back(std::get<char>(left));
|
||||
str.append(std::get<std::string>(right));
|
||||
cse.back()->Push(gc,str);
|
||||
}
|
||||
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
std::string str={};
|
||||
str.append(std::get<std::string>(left));
|
||||
str.push_back(std::get<char>(right));
|
||||
cse.back()->Push(gc,str);
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(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;
|
||||
}
|
||||
}
|
||||
236
src/vm/bc/equals.cpp
Normal file
236
src/vm/bc/equals.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
bool Equals(GC* gc, TObject left, TObject right)
|
||||
{
|
||||
GCList ls(gc);
|
||||
if(std::holds_alternative<std::nullptr_t>(left) && std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<Undefined>(left) && std::holds_alternative<Undefined>(right))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
return std::get<int64_t>(left) == std::get<int64_t>(right);
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
return std::get<double>(left) == std::get<double>(right);
|
||||
}
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
return std::get<double>(left) == std::get<int64_t>(right);
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
return std::get<int64_t>(left) == std::get<double>(right);
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
|
||||
{
|
||||
return std::get<std::string>(left) == std::get<std::string>(right);
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<bool>(left) && std::holds_alternative<bool>(right))
|
||||
{
|
||||
return std::get<bool>(left) == std::get<bool>(right);
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
return std::get<char>(left) == std::get<char>(right);
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
return std::get<char>(left) == std::get<int64_t>(right);
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
return std::get<int64_t>(left) == std::get<char>(right);
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left)->ToEpoch() == std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right)->ToEpoch();
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left)->TotalSeconds() == std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right)->TotalSeconds();
|
||||
}
|
||||
else if(std::holds_alternative<TVMVersion>(left) && std::holds_alternative<TVMVersion>(right))
|
||||
{
|
||||
auto lver= std::get<TVMVersion>(left);
|
||||
auto rver = std::get<TVMVersion>(right);
|
||||
auto r = lver.CompareTo(rver);
|
||||
return r == 0;
|
||||
}
|
||||
else if(std::holds_alternative<Tesses::Framework::Uuid>(left) && std::holds_alternative<Tesses::Framework::Uuid>(right))
|
||||
{
|
||||
auto l= std::get<Tesses::Framework::Uuid>(left);
|
||||
auto r = std::get<Tesses::Framework::Uuid>(right);
|
||||
|
||||
return l == r;
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto native = dynamic_cast<TNative*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(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<std::nullptr_t>(right)) {
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<Undefined>(right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(right))
|
||||
{
|
||||
return cls == std::get<THeapObjectHolder>(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<Undefined>(fn))
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(fn))
|
||||
{
|
||||
|
||||
auto obj = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(fn).obj);
|
||||
if(obj != nullptr)
|
||||
{
|
||||
auto closure = dynamic_cast<TClosure*>(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 dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
else if(dynDict != nullptr)
|
||||
{
|
||||
auto res = dynDict->CallMethod(ls,"operator==",{right});
|
||||
if(!std::holds_alternative<std::nullptr_t>(res) && std::holds_alternative<Undefined>(res))
|
||||
{
|
||||
return ToBool(res);
|
||||
}
|
||||
}
|
||||
else if(native != nullptr && std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
return native->GetDestroyed();
|
||||
|
||||
}
|
||||
|
||||
if(std::holds_alternative<THeapObjectHolder>(right))
|
||||
{
|
||||
return obj == std::get<THeapObjectHolder>(right).obj;
|
||||
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<Undefined>(right))
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<Undefined>(right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
3715
src/vm/bc/executemethod2.cpp
Normal file
3715
src/vm/bc/executemethod2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
769
src/vm/bc/getfield.cpp
Normal file
769
src/vm/bc/getfield.cpp
Normal file
@@ -0,0 +1,769 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::GetField(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& 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<std::string>(_key))
|
||||
{
|
||||
stk->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string key = std::get<std::string>(_key);
|
||||
|
||||
|
||||
if(std::holds_alternative<std::string>(instance))
|
||||
{
|
||||
std::string str = std::get<std::string>(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;
|
||||
}
|
||||
cse.back()->Push(gc, Undefined());
|
||||
return false;
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(instance))
|
||||
{
|
||||
auto vfs = std::get<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(instance);
|
||||
auto tmpFS=std::dynamic_pointer_cast<Tesses::Framework::Filesystem::TempFS>(vfs);
|
||||
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<Tesses::Framework::TextStreams::TextWriter>>(instance))
|
||||
{
|
||||
auto writer = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(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<Tesses::Framework::Streams::ByteReader>>(instance))
|
||||
{
|
||||
auto br = std::get<std::shared_ptr<Tesses::Framework::Streams::ByteReader>>(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<Tesses::Framework::Streams::ByteWriter>>(instance))
|
||||
{
|
||||
auto bw = std::get<std::shared_ptr<Tesses::Framework::Streams::ByteWriter>>(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<Tesses::Framework::Streams::Stream>>(instance))
|
||||
{
|
||||
auto strm = std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(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<TVMVersion>(instance))
|
||||
{
|
||||
TVMVersion& version = std::get<TVMVersion>(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<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(instance))
|
||||
{
|
||||
auto time = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(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<Tesses::Framework::Date::DateTime>>(instance))
|
||||
{
|
||||
auto& date = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(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<THeapObjectHolder>(instance))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
||||
auto bA = dynamic_cast<TByteArray*>(obj);
|
||||
auto list = dynamic_cast<TList*>(obj);
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto dynList = dynamic_cast<TDynamicList*>(obj);
|
||||
auto tcallable = dynamic_cast<TCallable*>(obj);
|
||||
auto closure = dynamic_cast<TClosure*>(obj);
|
||||
auto externalMethod = dynamic_cast<TExternalMethod*>(obj);
|
||||
auto ittr = dynamic_cast<TEnumerator*>(obj);
|
||||
|
||||
auto callstackEntry = dynamic_cast<CallStackEntry*>(obj);
|
||||
auto file = dynamic_cast<TFile*>(obj);
|
||||
auto chunk = dynamic_cast<TFileChunk*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(obj);
|
||||
auto aarray = dynamic_cast<TAssociativeArray*>(obj);
|
||||
auto task = dynamic_cast<TTask*>(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<THeapObjectHolder>(fn) && dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(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;
|
||||
}
|
||||
}
|
||||
54
src/vm/bc/invokemethod.cpp
Normal file
54
src/vm/bc/invokemethod.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
bool InterperterThread::InvokeMethod(GCList& ls, TObject fn, TObject instance, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
if(std::holds_alternative<THeapObjectHolder>(fn))
|
||||
{
|
||||
|
||||
auto obj = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(fn).obj);
|
||||
if(obj != nullptr)
|
||||
{
|
||||
auto closure = dynamic_cast<TClosure*>(obj);
|
||||
if(closure != nullptr)
|
||||
{
|
||||
|
||||
if(!closure->closure->args.empty() && closure->closure->args[0] == "this")
|
||||
{
|
||||
std::vector<TObject> 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;
|
||||
}
|
||||
|
||||
}
|
||||
this->call_stack_entries.back()->Push(ls.GetGC(),Undefined());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
47
src/vm/bc/invoketwo.cpp
Normal file
47
src/vm/bc/invoketwo.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::InvokeTwo(GCList& ls, TObject fn, TObject left, TObject right)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(fn))
|
||||
{
|
||||
|
||||
auto obj = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(fn).obj);
|
||||
if(obj != nullptr)
|
||||
{
|
||||
auto closure = dynamic_cast<TClosure*>(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;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
278
src/vm/bc/setfield.cpp
Normal file
278
src/vm/bc/setfield.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
bool InterperterThread::SetField(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& 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<std::string>(_key))
|
||||
{
|
||||
stk->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string key = std::get<std::string>(_key);
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance))
|
||||
{
|
||||
auto writer = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance);
|
||||
auto stringWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringWriter>(writer);
|
||||
if(stringWriter != nullptr)
|
||||
{
|
||||
if(key == "Text")
|
||||
{
|
||||
if(std::holds_alternative<std::string>(value))
|
||||
{
|
||||
stringWriter->GetString() = std::get<std::string>(value);
|
||||
}
|
||||
cse.back()->Push(gc, stringWriter->GetString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(key == "NewLine")
|
||||
{
|
||||
if(std::holds_alternative<std::string>(value))
|
||||
{
|
||||
writer->newline = std::get<std::string>(value);
|
||||
}
|
||||
cse.back()->Push(gc,writer->newline);
|
||||
return false;
|
||||
}
|
||||
cse.back()->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Http::IHttpServer>>(instance))
|
||||
{
|
||||
auto svr = std::get<std::shared_ptr<Tesses::Framework::Http::IHttpServer>>(instance);
|
||||
auto bas = std::dynamic_pointer_cast<Tesses::Framework::Http::BasicAuthServer>(svr);
|
||||
auto cgi = std::dynamic_pointer_cast<Tesses::Framework::Http::CGIServer>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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<std::shared_ptr<Tesses::Framework::Streams::Stream>>(instance))
|
||||
{
|
||||
auto strm = std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(instance);
|
||||
|
||||
auto netStrm = std::dynamic_pointer_cast<Tesses::Framework::Streams::NetworkStream>(strm);
|
||||
if(netStrm != nullptr)
|
||||
{
|
||||
bool bc;
|
||||
if(key == "Broadcast" && GetObject(value,bc))
|
||||
netStrm->SetBroadcast(bc);
|
||||
if(key == "NoDelay" && GetObject(value,bc))
|
||||
netStrm->SetNoDelay(bc);
|
||||
}
|
||||
stk->Push(gc, Undefined());
|
||||
return false;
|
||||
}
|
||||
if(std::holds_alternative<THeapObjectHolder>(instance))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
||||
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(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<TCallable*>(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<THeapObjectHolder>(fn) && dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(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;
|
||||
}
|
||||
|
||||
}
|
||||
121
src/vm/bc/sub.cpp
Normal file
121
src/vm/bc/sub.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::Sub(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||
GCList ls(gc);
|
||||
auto right = cse.back()->Pop(ls);
|
||||
auto left = cse.back()->Pop(ls);
|
||||
|
||||
if(std::holds_alternative<int64_t>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<int64_t>(left) - std::get<int64_t>(right));
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<double>(left) - std::get<double>(right));
|
||||
}
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<double>(left) - std::get<int64_t>(right));
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<int64_t>(left) - std::get<double>(right));
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (int64_t)(std::get<char>(left) - std::get<char>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (int64_t)(std::get<char>(left) - std::get<int64_t>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (int64_t)(std::get<int64_t>(left) - std::get<char>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::TimeSpan>((*l) - (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::DateTime>((*l) - (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
|
||||
|
||||
auto cls = dynamic_cast<TClassObject*>(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;
|
||||
}
|
||||
}
|
||||
106
src/vm/bc/tobool.cpp
Normal file
106
src/vm/bc/tobool.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
bool ToBool(TObject obj)
|
||||
{
|
||||
if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(obj))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(std::holds_alternative<TVMVersion>(obj))
|
||||
{
|
||||
auto v = std::get<TVMVersion>(obj);
|
||||
return v.AsLong() != 0;
|
||||
}
|
||||
if(std::holds_alternative<std::string>(obj))
|
||||
{
|
||||
return !std::get<std::string>(obj).empty();
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(obj))
|
||||
{
|
||||
return std::get<int64_t>(obj) != 0;
|
||||
}
|
||||
else if(std::holds_alternative<double>(obj))
|
||||
{
|
||||
return std::get<double>(obj);
|
||||
}
|
||||
else if(std::holds_alternative<bool>(obj))
|
||||
{
|
||||
return std::get<bool>(obj);
|
||||
}
|
||||
else if(std::holds_alternative<char>(obj))
|
||||
{
|
||||
return std::get<char>(obj) != 0;
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(obj))
|
||||
{
|
||||
auto& dt = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(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<Tesses::Framework::Date::TimeSpan>>(obj))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(obj)->TotalSeconds() != 0;
|
||||
}
|
||||
else if(std::holds_alternative<Tesses::Framework::Uuid>(obj))
|
||||
{
|
||||
auto& uuid = std::get<Tesses::Framework::Uuid>(obj);
|
||||
return !uuid.IsEmpty();
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto o = std::get<THeapObjectHolder>(obj).obj;
|
||||
auto ls = dynamic_cast<TList*>(o);
|
||||
auto aarray = dynamic_cast<TAssociativeArray*>(o);
|
||||
auto dict = dynamic_cast<TDictionary*>(o);
|
||||
auto ba = dynamic_cast<TByteArray*>(o);
|
||||
auto nat = dynamic_cast<TNative*>(o);
|
||||
auto thrd = dynamic_cast<ThreadHandle*>(o);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(o);
|
||||
|
||||
auto any = dynamic_cast<TAny*>(o);
|
||||
auto cls = dynamic_cast<TClassObject*>(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;
|
||||
}
|
||||
}
|
||||
133
src/vm/bc/tostring.cpp
Normal file
133
src/vm/bc/tostring.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
std::string ToString(GC* gc, TObject o)
|
||||
{
|
||||
if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(o))
|
||||
{
|
||||
return std::get<Tesses::Framework::Filesystem::VFSPath>(o).ToString();
|
||||
}
|
||||
if(std::holds_alternative<std::string>(o))
|
||||
{
|
||||
return std::get<std::string>(o);
|
||||
}
|
||||
if(std::holds_alternative<TVMVersion>(o))
|
||||
{
|
||||
return std::get<TVMVersion>(o).ToString();
|
||||
}
|
||||
if(std::holds_alternative<int64_t>(o))
|
||||
{
|
||||
return std::to_string(std::get<int64_t>(o));
|
||||
}
|
||||
|
||||
if(std::holds_alternative<double>(o))
|
||||
{
|
||||
return std::to_string(std::get<double>(o));
|
||||
}
|
||||
|
||||
if(std::holds_alternative<char>(o))
|
||||
{
|
||||
return std::string{std::get<char>(o)};
|
||||
}
|
||||
if(std::holds_alternative<std::nullptr_t>(o))
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
if(std::holds_alternative<Undefined>(o))
|
||||
{
|
||||
return "undefined";
|
||||
}
|
||||
if(std::holds_alternative<bool>(o))
|
||||
{
|
||||
return std::get<bool>(o) ? "true" : "false";
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(o))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(o)->ToString();
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(o))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(o)->ToString(false);
|
||||
}
|
||||
if(std::holds_alternative<Tesses::Framework::Uuid>(o))
|
||||
{
|
||||
return std::get<Tesses::Framework::Uuid>(o).ToString(Framework::UuidStringifyConfig::LowercaseNoCurly);
|
||||
}
|
||||
if(std::holds_alternative<THeapObjectHolder>(o))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(o).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto list = dynamic_cast<TList*>(obj);
|
||||
auto bArray = dynamic_cast<TByteArray*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(obj);
|
||||
auto aArray = dynamic_cast<TAssociativeArray*>(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 "";
|
||||
}
|
||||
}
|
||||
@@ -242,6 +242,7 @@ namespace Tesses::CrossLang
|
||||
break;
|
||||
case 11:
|
||||
{
|
||||
|
||||
auto data = parseEnt();
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(data,dict))
|
||||
|
||||
4854
src/vm/vm.cpp
4854
src/vm/vm.cpp
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user