mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-04-18 15:47:02 +00:00
Compare commits
13 Commits
bbf122a7eb
...
v0.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 46850e8edf | |||
| 86c7d85f0e | |||
| 45dcd9e7c5 | |||
| 447e9e6d37 | |||
| cc62377919 | |||
| b3c92707b9 | |||
| ba7213e184 | |||
| 23df4838ff | |||
| e6ce053c2e | |||
| a49b61c532 | |||
| 40205a928d | |||
| c37b26af14 | |||
| deb492b8c4 |
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:
|
jobs:
|
||||||
- name: Build for x86_64
|
- name: Build for x86_64
|
||||||
steps:
|
steps:
|
||||||
- !CheckoutStep
|
- type: CheckoutStep
|
||||||
name: Checkout
|
name: Checkout
|
||||||
cloneCredential: !DefaultCredential {}
|
cloneCredential:
|
||||||
|
type: DefaultCredential
|
||||||
withLfs: true
|
withLfs: true
|
||||||
withSubmodules: false
|
withSubmodules: false
|
||||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
condition: SUCCESSFUL
|
||||||
- !CommandStep
|
optional: false
|
||||||
|
- type: CommandStep
|
||||||
name: Execute build
|
name: Execute build
|
||||||
runInContainer: true
|
runInContainer: true
|
||||||
image: onedev.site.tesses.net/tesses-framework/tesses-framework:latest
|
image: onedev.site.tesses.net/tesses-framework/tesses-framework:latest
|
||||||
interpreter: !DefaultInterpreter
|
interpreter:
|
||||||
|
type: DefaultInterpreter
|
||||||
commands: |
|
commands: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
@@ -20,127 +23,32 @@ jobs:
|
|||||||
make -j12
|
make -j12
|
||||||
make install DESTDIR=../out
|
make install DESTDIR=../out
|
||||||
useTTY: true
|
useTTY: true
|
||||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
condition: SUCCESSFUL
|
||||||
- !BuildImageStep
|
optional: false
|
||||||
|
- type: BuildImageStep
|
||||||
name: Build Docker Image
|
name: Build Docker Image
|
||||||
dockerfile: Dockerfile.run
|
dockerfile: Dockerfile.run
|
||||||
output: !RegistryOutput
|
output:
|
||||||
|
type: RegistryOutput
|
||||||
tags: onedev.site.tesses.net/crosslang/crosslang:latest onedev.site.tesses.net/crosslang/crosslang:@commit_hash@
|
tags: onedev.site.tesses.net/crosslang/crosslang:latest onedev.site.tesses.net/crosslang/crosslang:@commit_hash@
|
||||||
registryLogins:
|
registryLogins:
|
||||||
- registryUrl: '@server_url@'
|
- registryUrl: '@server_url@'
|
||||||
userName: '@job_token@'
|
userName: '@job_token@'
|
||||||
passwordSecret: dockersecret
|
passwordSecret: dockersecret
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
condition: SUCCESSFUL
|
||||||
- !CommandStep
|
optional: false
|
||||||
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
|
|
||||||
triggers:
|
triggers:
|
||||||
- !DependencyFinishedTrigger
|
- type: DependencyFinishedTrigger
|
||||||
projects: tesses-framework
|
projects: tesses-framework
|
||||||
- !BranchUpdateTrigger
|
- type: BranchUpdateTrigger
|
||||||
branches: master
|
branches: master
|
||||||
|
userMatch: anyone
|
||||||
projects: crosslang
|
projects: crosslang
|
||||||
projectDependencies:
|
projectDependencies:
|
||||||
- projectPath: tesses-framework
|
- projectPath: tesses-framework
|
||||||
buildProvider: !LastFinishedBuild
|
buildProvider:
|
||||||
|
type: LastFinishedBuild
|
||||||
jobName: Build for x86_64
|
jobName: Build for x86_64
|
||||||
artifacts: '*'
|
artifacts: '*'
|
||||||
retryCondition: never
|
retryCondition: never
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
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 1)
|
||||||
|
|
||||||
|
project(TessesCrossLang VERSION ${CROSSLANG_MAJOR_VERSION}.${CROSSLANG_MINOR_VERSION}.${CROSSLANG_PATCH_VERSION})
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
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)
|
pkg_check_modules(LIBFFI REQUIRED IMPORTED_TARGET libffi)
|
||||||
endif()
|
endif()
|
||||||
function(CROSSLANG_LINK_DEPS CROSSLANG_TARGET_NAME)
|
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)
|
if(CROSSLANG_ENABLE_FFI AND CROSSLANG_ENABLE_SHARED)
|
||||||
|
|
||||||
target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_FFI)
|
target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_FFI)
|
||||||
@@ -154,6 +163,7 @@ src/runtime_methods/path.cpp
|
|||||||
src/runtime_methods/env.cpp
|
src/runtime_methods/env.cpp
|
||||||
src/runtime_methods/process.cpp
|
src/runtime_methods/process.cpp
|
||||||
src/runtime_methods/helpers.cpp
|
src/runtime_methods/helpers.cpp
|
||||||
|
src/types/embed.cpp
|
||||||
src/types/async.cpp
|
src/types/async.cpp
|
||||||
src/types/associativearray.cpp
|
src/types/associativearray.cpp
|
||||||
src/types/any.cpp
|
src/types/any.cpp
|
||||||
@@ -169,10 +179,12 @@ src/types/vfsheapobject.cpp
|
|||||||
src/types/streamheapobject.cpp
|
src/types/streamheapobject.cpp
|
||||||
src/types/class.cpp
|
src/types/class.cpp
|
||||||
src/types/classenvironment.cpp
|
src/types/classenvironment.cpp
|
||||||
|
src/types/random.cpp
|
||||||
src/vm/filereader.cpp
|
src/vm/filereader.cpp
|
||||||
src/vm/gc.cpp
|
src/vm/gc.cpp
|
||||||
src/vm/gclist.cpp
|
src/vm/gclist.cpp
|
||||||
src/vm/vm.cpp
|
src/vm/vm.cpp
|
||||||
|
src/vm/exception.cpp
|
||||||
src/archive.cpp
|
src/archive.cpp
|
||||||
src/markedtobject.cpp
|
src/markedtobject.cpp
|
||||||
)
|
)
|
||||||
@@ -233,7 +245,7 @@ install(TARGETS ${TessesCrossLangLibs}
|
|||||||
)
|
)
|
||||||
|
|
||||||
install(FILES include/CrossLang.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
install(FILES include/CrossLang.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/CrossLangVersion.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
install(EXPORT TessesCrossLangTargets
|
install(EXPORT TessesCrossLangTargets
|
||||||
FILE TessesCrossLangTargets.cmake
|
FILE TessesCrossLangTargets.cmake
|
||||||
NAMESPACE TessesCrossLang::
|
NAMESPACE TessesCrossLang::
|
||||||
@@ -242,6 +254,8 @@ install(EXPORT TessesCrossLangTargets
|
|||||||
|
|
||||||
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/TessesCrossLangConfig.cmake"
|
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/TessesCrossLangConfig.cmake"
|
||||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesCrossLang)
|
INSTALL_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"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/TessesCrossLangConfig.cmake"
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesCrossLang)
|
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,72 +0,0 @@
|
|||||||
#include <CrossLang.hpp>
|
|
||||||
using namespace Tesses::Framework;
|
|
||||||
using namespace Tesses::CrossLang;
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
TF_InitWithConsole();
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TList* args2 = TList::Create(ls);
|
|
||||||
args2->Add(exePath.ToString());
|
|
||||||
for(auto& item : args.positional)
|
|
||||||
{
|
|
||||||
args2->Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto res = env->CallFunction(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->CallFunction(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,78 +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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TList* args2 = TList::Create(ls);
|
|
||||||
args2->Add(exePath.ToString());
|
|
||||||
for(auto& item : args.positional)
|
|
||||||
{
|
|
||||||
args2->Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto res = env->CallFunction(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->CallFunction(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>
|
# Maintainer: Mike Nolan <tesses@tesses.net>
|
||||||
pkgname=crosslang # '-bzr', '-git', '-hg' or '-svn'
|
pkgname=crosslang # '-bzr', '-git', '-hg' or '-svn'
|
||||||
pkgver=1.0.0
|
pkgver=0.0.1
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc=""
|
pkgdesc=""
|
||||||
arch=('x86_64' 'powerpc')
|
arch=('x86_64' 'powerpc')
|
||||||
@@ -21,18 +21,7 @@ fi
|
|||||||
# Please refer to the 'USING VCS SOURCES' section of the PKGBUILD man page for
|
# Please refer to the 'USING VCS SOURCES' section of the PKGBUILD man page for
|
||||||
# a description of each element in the source array.
|
# 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() {
|
prepare() {
|
||||||
cd "$srcdir/${pkgname}"
|
cd "$srcdir/${pkgname}"
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ mkdir build-x86_64-tar
|
|||||||
cd build-x86_64-tar
|
cd build-x86_64-tar
|
||||||
cmake -S ../../.. -B . -DTESSESFRAMEWORK_ENABLE_SHARED=ON -DTESSESFRAMEWORK_ENABLE_STATIC=OFF -DTESSESFRAMEWORK_FETCHCONTENT=ON
|
cmake -S ../../.. -B . -DTESSESFRAMEWORK_ENABLE_SHARED=ON -DTESSESFRAMEWORK_ENABLE_STATIC=OFF -DTESSESFRAMEWORK_FETCHCONTENT=ON
|
||||||
make -j`nproc`
|
make -j`nproc`
|
||||||
make install DESTDIR=./crosslang
|
make install DESTDIR=./crosslang-x86_64
|
||||||
mkdir -p crosslang/share/Tesses/CrossLang
|
mkdir -p crosslang-x86_64/share/Tesses/CrossLang
|
||||||
cp ../build/jammy/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm crosslang/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm
|
cp ../build/jammy/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm crosslang-x86_64/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm
|
||||||
tar cvzf ../../../artifacts/crosslang-linux-x86_64.tar.gz crosslang
|
tar cvzf ../../../artifacts/crosslang-linux-x86_64.tar.gz crosslang-x86_64
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
foreign() {
|
foreign() {
|
||||||
@@ -14,10 +14,10 @@ mkdir build-$1\-tar
|
|||||||
cd build-$1\-tar
|
cd build-$1\-tar
|
||||||
cmake -S ../../.. -B . -DTESSESFRAMEWORK_ENABLE_SHARED=ON -DTESSESFRAMEWORK_ENABLE_STATIC=OFF -DTESSESFRAMEWORK_FETCHCONTENT=ON -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/$1\.cmake
|
cmake -S ../../.. -B . -DTESSESFRAMEWORK_ENABLE_SHARED=ON -DTESSESFRAMEWORK_ENABLE_STATIC=OFF -DTESSESFRAMEWORK_FETCHCONTENT=ON -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/$1\.cmake
|
||||||
make -j`nproc`
|
make -j`nproc`
|
||||||
make install DESTDIR=./crosslang
|
make install DESTDIR=./crosslang-$1
|
||||||
mkdir -p crosslang/share/Tesses/CrossLang
|
mkdir -p crosslang-$1\/share/Tesses/CrossLang
|
||||||
cp ../build/jammy/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm crosslang/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm
|
cp ../build/jammy/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm crosslang-$1\/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm
|
||||||
tar cvzf ../../../artifacts/crosslang-linux-$1\.tar.gz crosslang
|
tar cvzf ../../../artifacts/crosslang-linux-$1\.tar.gz crosslang-$1
|
||||||
cd ..
|
cd ..
|
||||||
}
|
}
|
||||||
foreign arm64
|
foreign arm64
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export BUILD=$(($BUILD_NO-142))
|
|
||||||
export DEB_VERSION=1.0.0-$BUILD
|
export DEB_VERSION=0.0.1
|
||||||
@@ -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 (Tesses::CrossLang::Undefined)
|
|
||||||
- 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,13 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <any>
|
#include <any>
|
||||||
|
|
||||||
/**
|
#include "CrossLangVersion.h"
|
||||||
* @brief CrossLang Runtime Major version
|
|
||||||
*
|
#define CROSSLANG_BYTECODE_MAJOR 1
|
||||||
*/
|
#define CROSSLANG_BYTECODE_MINOR 0
|
||||||
#define TVM_MAJOR 1
|
#define CROSSLANG_BYTECODE_PATCH 0
|
||||||
/**
|
#define CROSSLANG_BYTECODE_BUILD 0 //SHOULD ALWAYS BE 0
|
||||||
* @brief CrossLang Runtime Minor version
|
#define CROSSLANG_BYTECODE_VERSIONSTAGE DevVersion
|
||||||
*
|
|
||||||
*/
|
|
||||||
#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
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#undef Yield
|
#undef Yield
|
||||||
@@ -341,13 +323,13 @@ namespace Tesses::CrossLang {
|
|||||||
return v;
|
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
|
* @return int CompareTo(RuntimeVersion) where RuntimeVersion is the runtime version
|
||||||
*/
|
*/
|
||||||
int CompareToRuntime()
|
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);
|
return CompareTo(version);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -661,7 +643,10 @@ typedef enum {
|
|||||||
JMPIFBREAK,
|
JMPIFBREAK,
|
||||||
JMPIFCONTINUE,
|
JMPIFCONTINUE,
|
||||||
JMPIFDEFINED,
|
JMPIFDEFINED,
|
||||||
DECLARECONSTVARIABLE
|
DECLARECONSTVARIABLE,
|
||||||
|
LINEINFO,
|
||||||
|
PUSHRESOURCESTREAM,
|
||||||
|
PUSHRESOUURCEDIR
|
||||||
} Instruction;
|
} Instruction;
|
||||||
/**
|
/**
|
||||||
* @brief Base type for bytecode instruction
|
* @brief Base type for bytecode instruction
|
||||||
@@ -761,6 +746,13 @@ class EmbedInstruction : public ByteCodeInstruction {
|
|||||||
size_t Size();
|
size_t Size();
|
||||||
void Write(std::vector<uint8_t>& data);
|
void Write(std::vector<uint8_t>& data);
|
||||||
};
|
};
|
||||||
|
class EmbedStreamInstruction : public ByteCodeInstruction {
|
||||||
|
public:
|
||||||
|
uint32_t n;
|
||||||
|
EmbedStreamInstruction(uint32_t n);
|
||||||
|
size_t Size();
|
||||||
|
void Write(std::vector<uint8_t>& data);
|
||||||
|
};
|
||||||
|
|
||||||
class ClosureInstruction : public ByteCodeInstruction {
|
class ClosureInstruction : public ByteCodeInstruction {
|
||||||
public:
|
public:
|
||||||
@@ -861,11 +853,14 @@ class CodeGen {
|
|||||||
std::vector<std::pair<std::vector<uint32_t>, std::vector<ByteCodeInstruction*>>> chunks;
|
std::vector<std::pair<std::vector<uint32_t>, std::vector<ByteCodeInstruction*>>> chunks;
|
||||||
std::vector<std::pair<std::vector<uint32_t>,uint32_t>> funcs;
|
std::vector<std::pair<std::vector<uint32_t>,uint32_t>> funcs;
|
||||||
std::vector<CodeGenClass> classes;
|
std::vector<CodeGenClass> classes;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::vector<uint8_t>> meta;
|
||||||
|
SyntaxNode OptimizeNode(SyntaxNode n);
|
||||||
|
void WriteMetadataObject(std::vector<uint8_t>& bytes, SyntaxNode n);
|
||||||
void GenNode(std::vector<ByteCodeInstruction*>& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI);
|
void GenNode(std::vector<ByteCodeInstruction*>& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI);
|
||||||
void GenPop(std::vector<ByteCodeInstruction*>& instrs,SyntaxNode n);
|
void GenPop(std::vector<ByteCodeInstruction*>& instrs,SyntaxNode n);
|
||||||
public:
|
public:
|
||||||
|
std::shared_ptr<Tesses::Framework::Filesystem::VFS> embedFS;
|
||||||
std::vector<std::pair<std::string, TVMVersion>> dependencies;
|
std::vector<std::pair<std::string, TVMVersion>> dependencies;
|
||||||
std::vector<std::pair<std::string, TVMVersion>> tools;
|
std::vector<std::pair<std::string, TVMVersion>> tools;
|
||||||
TVMVersion version;
|
TVMVersion version;
|
||||||
@@ -873,7 +868,7 @@ class CodeGen {
|
|||||||
std::string info;
|
std::string info;
|
||||||
std::string icon;
|
std::string icon;
|
||||||
void GenRoot(SyntaxNode n);
|
void GenRoot(SyntaxNode n);
|
||||||
void Save(std::shared_ptr<Tesses::Framework::Filesystem::VFS> embedFS,std::shared_ptr<Tesses::Framework::Streams::Stream> output);
|
void Save(std::shared_ptr<Tesses::Framework::Streams::Stream> output);
|
||||||
~CodeGen();
|
~CodeGen();
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@@ -882,10 +877,20 @@ class CodeGen {
|
|||||||
*/
|
*/
|
||||||
constexpr std::string_view HtmlRootExpression = "htmlRootExpression";
|
constexpr std::string_view HtmlRootExpression = "htmlRootExpression";
|
||||||
/**
|
/**
|
||||||
* @brief an intrinsic function that embeads a resource from the filename based on the constant string argument
|
* @brief an intrinsic function that embeds a resource from the filename based on the constant string argument
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
constexpr std::string_view EmbedExpression = "embedExpression";
|
constexpr std::string_view EmbedExpression = "embedExpression";
|
||||||
|
/**
|
||||||
|
* @brief an intrinsic function that embeds a resource as a stream from the filename based on the constant string argument
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constexpr std::string_view EmbedStreamExpression = "embedStreamExpression";
|
||||||
|
/**
|
||||||
|
* @brief an intrinsic function that embeds a resource directory from the directory name based on the constant string argument
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constexpr std::string_view EmbedDirectoryExpression = "embedDirectoryExpression";
|
||||||
/**
|
/**
|
||||||
* @brief Negative operator -EXPR
|
* @brief Negative operator -EXPR
|
||||||
*
|
*
|
||||||
@@ -1239,6 +1244,15 @@ constexpr std::string_view AwaitExpression = "awaitExpression";
|
|||||||
* @brief ?? operator
|
* @brief ?? operator
|
||||||
*/
|
*/
|
||||||
constexpr std::string_view NullCoalescingExpression = "nullCoalescingExpression";
|
constexpr std::string_view NullCoalescingExpression = "nullCoalescingExpression";
|
||||||
|
/**
|
||||||
|
* @brief For debugging (store line info and filename)
|
||||||
|
*/
|
||||||
|
constexpr std::string_view LineNode="lineNode";
|
||||||
|
/**
|
||||||
|
* @brief For storing generic metadata
|
||||||
|
*/
|
||||||
|
constexpr std::string_view MetadataStatement = "MetadataStatement";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Advanced AST node
|
* @brief Advanced AST node
|
||||||
*
|
*
|
||||||
@@ -1315,8 +1329,11 @@ class Parser {
|
|||||||
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
|
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
|
||||||
GC* gc;
|
GC* gc;
|
||||||
TRootEnvironment* env;
|
TRootEnvironment* env;
|
||||||
|
int lastLine=-1;
|
||||||
|
std::string lastFile="";
|
||||||
|
bool CanEmit(LexTokenLineInfo& token);
|
||||||
public:
|
public:
|
||||||
|
bool debug=true;
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new Parser object
|
* @brief Construct a new Parser object
|
||||||
*
|
*
|
||||||
@@ -1455,6 +1472,7 @@ class GC {
|
|||||||
TFile* file;
|
TFile* file;
|
||||||
std::vector<uint8_t> code;
|
std::vector<uint8_t> code;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
std::optional<std::string> name;
|
||||||
void Mark();
|
void Mark();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1503,7 +1521,7 @@ class GC {
|
|||||||
TObject value;
|
TObject value;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
class TDictionary;
|
||||||
class TFile : public THeapObject
|
class TFile : public THeapObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1518,6 +1536,7 @@ class GC {
|
|||||||
std::vector<std::pair<std::string,TVMVersion>> dependencies;
|
std::vector<std::pair<std::string,TVMVersion>> dependencies;
|
||||||
std::vector<std::pair<std::string,TVMVersion>> tools;
|
std::vector<std::pair<std::string,TVMVersion>> tools;
|
||||||
std::vector<std::pair<std::string,std::vector<uint8_t>>> sections;
|
std::vector<std::pair<std::string,std::vector<uint8_t>>> sections;
|
||||||
|
std::vector<std::pair<std::string,std::vector<uint8_t>>> metadata;
|
||||||
std::vector<std::vector<uint8_t>> resources;
|
std::vector<std::vector<uint8_t>> resources;
|
||||||
std::vector<TClass> classes;
|
std::vector<TClass> classes;
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -1535,6 +1554,8 @@ class GC {
|
|||||||
void Mark();
|
void Mark();
|
||||||
|
|
||||||
void EnsureCanRunInCrossLang();
|
void EnsureCanRunInCrossLang();
|
||||||
|
|
||||||
|
TDictionary* MetadataDecode(GCList& ls, size_t index);
|
||||||
};
|
};
|
||||||
class TAssociativeArray : public THeapObject
|
class TAssociativeArray : public THeapObject
|
||||||
{
|
{
|
||||||
@@ -1642,6 +1663,7 @@ class GC {
|
|||||||
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
||||||
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
||||||
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args);
|
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args);
|
||||||
|
TObject CallMethodWithFatalError(GCList& ls, std::string key, std::vector<TObject> args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1655,9 +1677,14 @@ class GC {
|
|||||||
TObject tag;
|
TObject tag;
|
||||||
std::string documentation;
|
std::string documentation;
|
||||||
virtual TObject Call(GCList& ls,std::vector<TObject> args)=0;
|
virtual TObject Call(GCList& ls,std::vector<TObject> args)=0;
|
||||||
|
TObject CallWithFatalError(GCList& ls, std::vector<TObject> args);
|
||||||
virtual void Mark();
|
virtual void Mark();
|
||||||
|
|
||||||
|
Tesses::Framework::Http::ServerRequestHandler ToRouteServerRequestHandler(GC* gc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ThrowFatalError(std::exception& ex);
|
||||||
|
|
||||||
void ThrowConstError(std::string key);
|
void ThrowConstError(std::string key);
|
||||||
|
|
||||||
class TEnvironment : public THeapObject {
|
class TEnvironment : public THeapObject {
|
||||||
@@ -1694,7 +1721,7 @@ class GC {
|
|||||||
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
||||||
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
||||||
TObject CallFunction(GCList& ls, std::string key, std::vector<TObject> args);
|
TObject CallFunction(GCList& ls, std::string key, std::vector<TObject> args);
|
||||||
|
TObject CallFunctionWithFatalError(GCList& ls, std::string key, std::vector<TObject> args);
|
||||||
};
|
};
|
||||||
class TClassEnvironment;
|
class TClassEnvironment;
|
||||||
class TClassObject : public THeapObject
|
class TClassObject : public THeapObject
|
||||||
@@ -2012,6 +2039,9 @@ class GC {
|
|||||||
void CreateHardlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath newName);
|
void CreateHardlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath newName);
|
||||||
bool DirectoryExists(Tesses::Framework::Filesystem::VFSPath path);
|
bool DirectoryExists(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
void DeleteFile(Tesses::Framework::Filesystem::VFSPath path);
|
void DeleteFile(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
void Lock(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
void Unlock(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
|
||||||
void DeleteDirectoryRecurse(Tesses::Framework::Filesystem::VFSPath path);
|
void DeleteDirectoryRecurse(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path);
|
Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
void MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest);
|
void MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest);
|
||||||
@@ -2048,6 +2078,8 @@ class GC {
|
|||||||
~TObjectStream();
|
~TObjectStream();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer
|
class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -2134,18 +2166,21 @@ class GC {
|
|||||||
|
|
||||||
~TDynamicDictionary();
|
~TDynamicDictionary();
|
||||||
};
|
};
|
||||||
|
class InterperterThread;
|
||||||
|
|
||||||
class CallStackEntry : public THeapObject
|
class CallStackEntry : public THeapObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static CallStackEntry* Create(GCList* ls);
|
static CallStackEntry* Create(GCList* ls);
|
||||||
static CallStackEntry* Create(GCList& ls);
|
static CallStackEntry* Create(GCList& ls);
|
||||||
|
InterperterThread* thread;
|
||||||
std::vector<TObject> stack;
|
std::vector<TObject> stack;
|
||||||
TEnvironment* env;
|
TEnvironment* env;
|
||||||
TClosure* callable;
|
TClosure* callable;
|
||||||
uint32_t ip;
|
uint32_t ip;
|
||||||
uint32_t scopes;
|
uint32_t scopes;
|
||||||
|
int64_t srcline;
|
||||||
|
std::string srcfile;
|
||||||
bool mustReturn;
|
bool mustReturn;
|
||||||
|
|
||||||
void Mark();
|
void Mark();
|
||||||
@@ -2262,6 +2297,9 @@ class GC {
|
|||||||
bool PushContinue(GC* gc);
|
bool PushContinue(GC* gc);
|
||||||
bool JumpIfBreak(GC* gc);
|
bool JumpIfBreak(GC* gc);
|
||||||
bool JumpIfContinue(GC* gc);
|
bool JumpIfContinue(GC* gc);
|
||||||
|
bool LineInfo(GC* gc);
|
||||||
|
bool PushResourceStream(GC* gc);
|
||||||
|
bool PushResourceDirectory(GC* gc);
|
||||||
public:
|
public:
|
||||||
static InterperterThread* Create(GCList* ls);
|
static InterperterThread* Create(GCList* ls);
|
||||||
static InterperterThread* Create(GCList& ls);
|
static InterperterThread* Create(GCList& ls);
|
||||||
@@ -2329,6 +2367,16 @@ class GC {
|
|||||||
virtual bool Equals(GC* gc, TObject right);
|
virtual bool Equals(GC* gc, TObject right);
|
||||||
virtual ~TNativeObject();
|
virtual ~TNativeObject();
|
||||||
};
|
};
|
||||||
|
class TRandom : public TNativeObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Tesses::Framework::Random random;
|
||||||
|
TRandom();
|
||||||
|
TRandom(uint64_t seed);
|
||||||
|
std::string TypeName();
|
||||||
|
TObject CallMethod(GCList& ls,std::string name, std::vector<TObject> args);
|
||||||
|
|
||||||
|
};
|
||||||
class TNative : public THeapObject
|
class TNative : public THeapObject
|
||||||
{
|
{
|
||||||
std::atomic<bool> destroyed;
|
std::atomic<bool> destroyed;
|
||||||
@@ -2346,7 +2394,7 @@ class GC {
|
|||||||
~TNative();
|
~TNative();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ThreadHandle : public THeapObject {
|
class ThreadHandle : public THeapObject {
|
||||||
public:
|
public:
|
||||||
@@ -2387,22 +2435,30 @@ class GC {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
TObject exception;
|
TObject exception;
|
||||||
|
std::vector<CallStackEntry*> stack_trace;
|
||||||
|
|
||||||
|
|
||||||
VMByteCodeException()
|
VMByteCodeException()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
VMByteCodeException(GC* gc,TObject obj)
|
VMByteCodeException(GC* gc,TObject obj, CallStackEntry* ent)
|
||||||
{
|
{
|
||||||
gcList = std::make_shared<GCList>(gc);
|
gcList = std::make_shared<GCList>(gc);
|
||||||
gcList.get()->Add(obj);
|
gcList->Add(obj);
|
||||||
|
if(ent != nullptr && ent->thread != nullptr)
|
||||||
|
{
|
||||||
|
this->stack_trace = ent->thread->call_stack_entries;
|
||||||
|
for(auto item : this->stack_trace)
|
||||||
|
gcList->Add(item);
|
||||||
|
}
|
||||||
this->exception = obj;
|
this->exception = obj;
|
||||||
UpdateError();
|
UpdateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateError()
|
void UpdateError()
|
||||||
{
|
{
|
||||||
lastErrorText = ToString(gcList.get()->GetGC(),exception);
|
lastErrorText = ToString(gcList->GetGC(),exception);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2410,14 +2466,19 @@ class GC {
|
|||||||
{
|
{
|
||||||
return lastErrorText.c_str();
|
return lastErrorText.c_str();
|
||||||
}
|
}
|
||||||
|
std::shared_ptr<GCList> GetGCList() {
|
||||||
|
return this->gcList;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SyntaxException : public std::exception
|
class SyntaxException : public std::exception
|
||||||
{
|
{
|
||||||
std::string msg={};
|
std::string msg={};
|
||||||
|
LexTokenLineInfo line;
|
||||||
|
std::string message;
|
||||||
public:
|
public:
|
||||||
SyntaxException(LexTokenLineInfo lineInfo, std::string message)
|
SyntaxException(LexTokenLineInfo lineInfo, std::string message) : line(lineInfo), message(message)
|
||||||
{
|
{
|
||||||
msg.append("in file: ");
|
msg.append("in file: ");
|
||||||
msg.append(lineInfo.filename);
|
msg.append(lineInfo.filename);
|
||||||
@@ -2434,6 +2495,9 @@ class GC {
|
|||||||
{
|
{
|
||||||
return msg.c_str();
|
return msg.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Message() { return message;}
|
||||||
|
LexTokenLineInfo LineInfo() { return line;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -2483,6 +2547,8 @@ class GC {
|
|||||||
void LoadPlugin(GC* gc, TRootEnvironment* env, Tesses::Framework::Filesystem::VFSPath sharedObjectPath);
|
void LoadPlugin(GC* gc, TRootEnvironment* env, Tesses::Framework::Filesystem::VFSPath sharedObjectPath);
|
||||||
std::string Json_Encode(TObject o,bool indent=false);
|
std::string Json_Encode(TObject o,bool indent=false);
|
||||||
TObject Json_Decode(GCList ls,std::string str);
|
TObject Json_Decode(GCList ls,std::string str);
|
||||||
|
std::string Json_DocEncode(TObject o,bool indent);
|
||||||
|
TObject Json_DocDecode(GCList ls,std::string str);
|
||||||
//DO NOT USE DIRECTLY
|
//DO NOT USE DIRECTLY
|
||||||
class SharedPtrTObject {
|
class SharedPtrTObject {
|
||||||
GCList* ls;
|
GCList* ls;
|
||||||
@@ -2510,4 +2576,41 @@ class GC {
|
|||||||
|
|
||||||
|
|
||||||
std::shared_ptr<Tesses::Framework::Http::IHttpServer> ToHttpServer(GC* gc,TObject obj);
|
std::shared_ptr<Tesses::Framework::Http::IHttpServer> ToHttpServer(GC* gc,TObject obj);
|
||||||
|
|
||||||
|
class EmbedStream : public Tesses::Framework::Streams::Stream
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
MarkedTObject file;
|
||||||
|
uint32_t resource;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EmbedStream(GC* gc, TFile* file, uint32_t resource);
|
||||||
|
bool CanRead();
|
||||||
|
bool CanSeek();
|
||||||
|
bool EndOfStream();
|
||||||
|
size_t Read(uint8_t* buff, size_t len);
|
||||||
|
int64_t GetPosition();
|
||||||
|
int64_t GetLength();
|
||||||
|
void Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence);
|
||||||
|
};
|
||||||
|
|
||||||
|
class EmbedDirectory : public Tesses::Framework::Filesystem::VFS
|
||||||
|
{
|
||||||
|
MarkedTObject dir;
|
||||||
|
TObject getEntry(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
public:
|
||||||
|
EmbedDirectory(GC* gc, TDictionary* dict);
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode);
|
||||||
|
void CreateDirectory(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
void DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
bool RegularFileExists(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
bool DirectoryExists(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
void DeleteFile(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
void MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest);
|
||||||
|
std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path);
|
||||||
|
Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
uint8_t main_header[18];
|
uint8_t main_header[18];
|
||||||
memcpy(main_header,"TCROSSVM",8);
|
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);
|
rtVersion.ToArray(main_header+8);
|
||||||
version.ToArray(main_header+13);
|
version.ToArray(main_header+13);
|
||||||
strm->WriteBlock(main_header,sizeof(main_header));
|
strm->WriteBlock(main_header,sizeof(main_header));
|
||||||
@@ -151,6 +151,12 @@ namespace Tesses::CrossLang
|
|||||||
strm->WriteBlock((const uint8_t*)"INFO",4);
|
strm->WriteBlock((const uint8_t*)"INFO",4);
|
||||||
writeInt(strm,4);
|
writeInt(strm,4);
|
||||||
writeInt(strm,1);
|
writeInt(strm,1);
|
||||||
|
if(!icon.empty())
|
||||||
|
{
|
||||||
|
strm->WriteBlock((const uint8_t*)"ICON",4);
|
||||||
|
writeInt(strm,4);
|
||||||
|
writeInt(strm,ensureResource(icon));
|
||||||
|
}
|
||||||
strm->WriteBlock((const uint8_t*)"CHKS",4);
|
strm->WriteBlock((const uint8_t*)"CHKS",4);
|
||||||
writeInt(strm,(uint32_t)(12+error_message_byte_code.size()));
|
writeInt(strm,(uint32_t)(12+error_message_byte_code.size()));
|
||||||
writeInt(strm,1);
|
writeInt(strm,1);
|
||||||
|
|||||||
@@ -83,6 +83,18 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PushResourceStreamChunkInstruction : public ChunkInstruction {
|
||||||
|
public:
|
||||||
|
PushResourceStreamChunkInstruction(std::string v) : value(v)
|
||||||
|
{}
|
||||||
|
std::string value;
|
||||||
|
size_t Size()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LabelChunkInstruction : public ChunkInstruction {
|
class LabelChunkInstruction : public ChunkInstruction {
|
||||||
public:
|
public:
|
||||||
LabelChunkInstruction(std::string lbl) : lbl(lbl)
|
LabelChunkInstruction(std::string lbl) : lbl(lbl)
|
||||||
@@ -281,6 +293,14 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
instrs.push_back(std::make_shared<SimpleChunkInstruction>(NOP));
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(NOP));
|
||||||
}
|
}
|
||||||
|
else if(name == "lineinfo")
|
||||||
|
{
|
||||||
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(LINEINFO));
|
||||||
|
}
|
||||||
|
else if(name == "embeddir")
|
||||||
|
{
|
||||||
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(PUSHRESOUURCEDIR));
|
||||||
|
}
|
||||||
else if(name == "pushclosure")
|
else if(name == "pushclosure")
|
||||||
{
|
{
|
||||||
auto closure = std::make_shared<ClosureChunkInstruction>(true);
|
auto closure = std::make_shared<ClosureChunkInstruction>(true);
|
||||||
@@ -321,6 +341,14 @@ namespace Tesses::CrossLang {
|
|||||||
instrs.push_back(std::make_shared<PushResourceChunkInstruction>(str));
|
instrs.push_back(std::make_shared<PushResourceChunkInstruction>(str));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(name == "embedstrm")
|
||||||
|
{
|
||||||
|
if(i < tokens.size() && tokens[i].type == LexTokenType::String)
|
||||||
|
{
|
||||||
|
std::string str = tokens[i++].text;
|
||||||
|
instrs.push_back(std::make_shared<PushResourceStreamChunkInstruction>(str));
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(name == "push")
|
else if(name == "push")
|
||||||
{
|
{
|
||||||
if(IsSym("."))
|
if(IsSym("."))
|
||||||
@@ -745,7 +773,7 @@ namespace Tesses::CrossLang {
|
|||||||
void Save(std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs, std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
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];
|
uint8_t buffer[18];
|
||||||
memcpy(buffer,"TCROSSVM",8);
|
memcpy(buffer,"TCROSSVM",8);
|
||||||
runtime_version.ToArray(buffer+8);
|
runtime_version.ToArray(buffer+8);
|
||||||
@@ -1027,6 +1055,7 @@ namespace Tesses::CrossLang {
|
|||||||
auto chr = std::dynamic_pointer_cast<PushCharChunkInstruction>(item);
|
auto chr = std::dynamic_pointer_cast<PushCharChunkInstruction>(item);
|
||||||
auto chk = std::dynamic_pointer_cast<ClosureChunkInstruction>(item);
|
auto chk = std::dynamic_pointer_cast<ClosureChunkInstruction>(item);
|
||||||
auto reso = std::dynamic_pointer_cast<PushResourceChunkInstruction>(item);
|
auto reso = std::dynamic_pointer_cast<PushResourceChunkInstruction>(item);
|
||||||
|
auto resos = std::dynamic_pointer_cast<PushResourceStreamChunkInstruction>(item);
|
||||||
auto jmp = std::dynamic_pointer_cast<JumpStyleChunkInstruction>(item);
|
auto jmp = std::dynamic_pointer_cast<JumpStyleChunkInstruction>(item);
|
||||||
auto scopeend = std::dynamic_pointer_cast<ScopeEndTimesChunkInstruction>(item);
|
auto scopeend = std::dynamic_pointer_cast<ScopeEndTimesChunkInstruction>(item);
|
||||||
if(lbl)
|
if(lbl)
|
||||||
@@ -1062,6 +1091,10 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
chunks[chunkId].second.push_back(std::make_shared<EmbedInstruction>(GetResource(reso->value)));
|
chunks[chunkId].second.push_back(std::make_shared<EmbedInstruction>(GetResource(reso->value)));
|
||||||
}
|
}
|
||||||
|
if(resos)
|
||||||
|
{
|
||||||
|
chunks[chunkId].second.push_back(std::make_shared<EmbedStreamInstruction>(GetResource(reso->value)));
|
||||||
|
}
|
||||||
if(jmp)
|
if(jmp)
|
||||||
{
|
{
|
||||||
chunks[chunkId].second.push_back(std::make_shared<JumpStyleInstruction>(jmp->instr,jmp->lbl));
|
chunks[chunkId].second.push_back(std::make_shared<JumpStyleInstruction>(jmp->instr,jmp->lbl));
|
||||||
|
|||||||
@@ -223,6 +223,7 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
switch(code[i++])
|
switch(code[i++])
|
||||||
{
|
{
|
||||||
|
case PUSHRESOURCESTREAM:
|
||||||
case PUSHRESOURCE:
|
case PUSHRESOURCE:
|
||||||
case PUSHSTRING:
|
case PUSHSTRING:
|
||||||
case SCOPEENDTIMES:
|
case SCOPEENDTIMES:
|
||||||
@@ -381,6 +382,9 @@ namespace Tesses::CrossLang {
|
|||||||
case APPENDDICT:
|
case APPENDDICT:
|
||||||
buffer.append("appenddict");
|
buffer.append("appenddict");
|
||||||
break;
|
break;
|
||||||
|
case PUSHRESOUURCEDIR:
|
||||||
|
buffer.append("embeddir");
|
||||||
|
break;
|
||||||
case PUSHRESOURCE:
|
case PUSHRESOURCE:
|
||||||
{
|
{
|
||||||
uint32_t clId = (uint32_t)code[i++] << 24;
|
uint32_t clId = (uint32_t)code[i++] << 24;
|
||||||
@@ -391,6 +395,16 @@ namespace Tesses::CrossLang {
|
|||||||
buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true));
|
buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PUSHRESOURCESTREAM:
|
||||||
|
{
|
||||||
|
uint32_t clId = (uint32_t)code[i++] << 24;
|
||||||
|
clId |= (uint32_t)code[i++] << 16;
|
||||||
|
clId |= (uint32_t)code[i++] << 8;
|
||||||
|
clId |= (uint32_t)code[i++];
|
||||||
|
buffer.append("embedstrm ");
|
||||||
|
buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PUSHLONG:
|
case PUSHLONG:
|
||||||
{
|
{
|
||||||
uint64_t number = (uint64_t)code[i++] << 56;
|
uint64_t number = (uint64_t)code[i++] << 56;
|
||||||
@@ -571,6 +585,9 @@ namespace Tesses::CrossLang {
|
|||||||
case BREAKPOINT:
|
case BREAKPOINT:
|
||||||
buffer.append("breakpoint");
|
buffer.append("breakpoint");
|
||||||
break;
|
break;
|
||||||
|
case LINEINFO:
|
||||||
|
buffer.append("lineinfo");
|
||||||
|
break;
|
||||||
case PUSHBREAK:
|
case PUSHBREAK:
|
||||||
buffer.append("push break");
|
buffer.append("push break");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -33,10 +33,354 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyntaxNode CodeGen::OptimizeNode(SyntaxNode n)
|
||||||
void CodeGen::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);
|
if(std::holds_alternative<AdvancedSyntaxNode>(n))
|
||||||
|
{
|
||||||
|
auto& asn = std::get<AdvancedSyntaxNode>(n);
|
||||||
|
if(asn.nodeName == AddExpression && asn.nodes.size() == 2)
|
||||||
|
{
|
||||||
|
auto leftNode = OptimizeNode(asn.nodes[0]);
|
||||||
|
auto rightNode = OptimizeNode(asn.nodes[1]);
|
||||||
|
|
||||||
|
|
||||||
|
if(std::holds_alternative<int64_t>(leftNode) && std::holds_alternative<int64_t>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<int64_t>(leftNode) + std::get<int64_t>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<double>(leftNode) && std::holds_alternative<double>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<double>(leftNode) + std::get<double>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<int64_t>(leftNode) && std::holds_alternative<double>(rightNode))
|
||||||
|
{
|
||||||
|
return (double)std::get<int64_t>(leftNode) + std::get<double>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<double>(leftNode) && std::holds_alternative<int64_t>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<double>(leftNode) + (double)std::get<int64_t>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<std::string>(leftNode) && std::holds_alternative<std::string>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<std::string>(leftNode) + std::get<std::string>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<std::string>(leftNode) && std::holds_alternative<char>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<std::string>(leftNode) + std::get<char>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<char>(leftNode) && std::holds_alternative<std::string>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<char>(leftNode) + std::get<std::string>(rightNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(asn.nodeName == SubExpression && asn.nodes.size() == 2)
|
||||||
|
{
|
||||||
|
auto leftNode = OptimizeNode(asn.nodes[0]);
|
||||||
|
auto rightNode = OptimizeNode(asn.nodes[1]);
|
||||||
|
|
||||||
|
|
||||||
|
if(std::holds_alternative<int64_t>(leftNode) && std::holds_alternative<int64_t>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<int64_t>(leftNode) - std::get<int64_t>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<double>(leftNode) && std::holds_alternative<double>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<double>(leftNode) - std::get<double>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<int64_t>(leftNode) && std::holds_alternative<double>(rightNode))
|
||||||
|
{
|
||||||
|
return (double)std::get<int64_t>(leftNode) - std::get<double>(rightNode);
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<double>(leftNode) && std::holds_alternative<int64_t>(rightNode))
|
||||||
|
{
|
||||||
|
return std::get<double>(leftNode) - (double)std::get<int64_t>(rightNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(asn.nodeName == CommaExpression && asn.nodes.size() == 2)
|
||||||
|
{
|
||||||
|
return AdvancedSyntaxNode::Create(CommaExpression,true, {
|
||||||
|
OptimizeNode(asn.nodes[0]),
|
||||||
|
OptimizeNode(asn.nodes[1])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(asn.nodeName == ScopeNode)
|
||||||
|
{
|
||||||
|
if(asn.nodes.empty())
|
||||||
|
{
|
||||||
|
asn.nodeName = NodeList;
|
||||||
|
return asn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(auto& item : asn.nodes)
|
||||||
|
{
|
||||||
|
item = OptimizeNode(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
0: false,
|
||||||
|
1: true,
|
||||||
|
2: null,
|
||||||
|
3: Long,
|
||||||
|
4: Double,
|
||||||
|
5: Char
|
||||||
|
6: String,
|
||||||
|
7: List,
|
||||||
|
8: Dictionary,
|
||||||
|
9: ByteArray (embed),
|
||||||
|
10: Stream (embedstrm),
|
||||||
|
11: VFS (embeddir),
|
||||||
|
12: ClosureOfEmbedStream (used by embeddir)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void CodeGen::WriteMetadataObject(std::vector<uint8_t>& bytes, SyntaxNode n)
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<bool>(n))
|
||||||
|
{
|
||||||
|
bytes.push_back(std::get<bool>(n) ? 1 : 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<std::nullptr_t>(n))
|
||||||
|
{
|
||||||
|
bytes.push_back(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<int64_t>(n))
|
||||||
|
{
|
||||||
|
auto num = std::get<int64_t>(n);
|
||||||
|
bytes.push_back(3);
|
||||||
|
size_t offset = bytes.size();
|
||||||
|
bytes.resize(offset+8);
|
||||||
|
BitConverter::FromUint64BE(bytes[offset],num);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<double>(n))
|
||||||
|
{
|
||||||
|
auto num = std::get<double>(n);
|
||||||
|
bytes.push_back(4);
|
||||||
|
size_t offset = bytes.size();
|
||||||
|
bytes.resize(offset+8);
|
||||||
|
BitConverter::FromDoubleBE(bytes[offset],num);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<char>(n))
|
||||||
|
{
|
||||||
|
auto chr = std::get<char>(n);
|
||||||
|
bytes.push_back(5);
|
||||||
|
bytes.push_back((uint8_t)chr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<std::string>(n))
|
||||||
|
{
|
||||||
|
auto& str = std::get<std::string>(n);
|
||||||
|
bytes.push_back(6);
|
||||||
|
size_t offset = bytes.size();
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset], GetString(str));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<AdvancedSyntaxNode>(n))
|
||||||
|
{
|
||||||
|
auto& asn = std::get<AdvancedSyntaxNode>(n);
|
||||||
|
if(asn.nodeName == ArrayExpression)
|
||||||
|
{
|
||||||
|
std::vector<SyntaxNode> itms;
|
||||||
|
if(asn.nodes.size() > 0)
|
||||||
|
|
||||||
|
GetFunctionArgs(itms,asn.nodes[0]);
|
||||||
|
bytes.push_back(7);
|
||||||
|
size_t offset = bytes.size();
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size());
|
||||||
|
for(auto& item : itms)
|
||||||
|
{
|
||||||
|
WriteMetadataObject(bytes,item);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(asn.nodeName == DictionaryExpression)
|
||||||
|
{
|
||||||
|
std::vector<SyntaxNode> itms;
|
||||||
|
if(asn.nodes.size() > 0)
|
||||||
|
|
||||||
|
GetFunctionArgs(itms,asn.nodes[0]);
|
||||||
|
bytes.push_back(8);
|
||||||
|
size_t offset = bytes.size();
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size());
|
||||||
|
for(auto& item : itms)
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<AdvancedSyntaxNode>(item))
|
||||||
|
{
|
||||||
|
auto tkn = std::get<AdvancedSyntaxNode>(item);
|
||||||
|
if(tkn.nodeName == GetVariableExpression && !tkn.nodes.empty())
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<std::string>(tkn.nodes[0]))
|
||||||
|
{
|
||||||
|
size_t offset2 = bytes.size();
|
||||||
|
bytes.resize(offset2+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset2], GetString(std::get<std::string>(tkn.nodes[0])));
|
||||||
|
bytes.push_back(2);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t offset2 = bytes.size();
|
||||||
|
bytes.resize(offset2+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown"));
|
||||||
|
bytes.push_back(2);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(tkn.nodeName == AssignExpression && tkn.nodes.size()==2 && std::holds_alternative<AdvancedSyntaxNode>(tkn.nodes[0]))
|
||||||
|
{
|
||||||
|
auto myTn = std::get<AdvancedSyntaxNode>(tkn.nodes[0]);
|
||||||
|
if(myTn.nodeName == GetVariableExpression && !myTn.nodes.empty())
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<std::string>(myTn.nodes[0]))
|
||||||
|
{
|
||||||
|
size_t offset2 = bytes.size();
|
||||||
|
bytes.resize(offset2+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset2], GetString(std::get<std::string>(myTn.nodes[0])));
|
||||||
|
WriteMetadataObject(bytes,tkn.nodes[1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t offset2 = bytes.size();
|
||||||
|
bytes.resize(offset2+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown"));
|
||||||
|
bytes.push_back(2);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t offset2 = bytes.size();
|
||||||
|
bytes.resize(offset2+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown"));
|
||||||
|
bytes.push_back(2);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t offset2 = bytes.size();
|
||||||
|
bytes.resize(offset2+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown"));
|
||||||
|
bytes.push_back(2);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(asn.nodeName == EmbedExpression)
|
||||||
|
{
|
||||||
|
if(!asn.nodes.empty() && std::holds_alternative<std::string>(asn.nodes[0]))
|
||||||
|
{
|
||||||
|
auto& filename = std::get<std::string>(asn.nodes[0]);
|
||||||
|
bytes.push_back(9);
|
||||||
|
size_t offset = bytes.size();
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset], GetResource(std::make_shared<ResourceFile>(filename)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(asn.nodeName == EmbedStreamExpression)
|
||||||
|
{
|
||||||
|
if(!asn.nodes.empty() && std::holds_alternative<std::string>(asn.nodes[0]))
|
||||||
|
{
|
||||||
|
auto& filename = std::get<std::string>(asn.nodes[0]);
|
||||||
|
bytes.push_back(10);
|
||||||
|
size_t offset = bytes.size();
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset], GetResource(std::make_shared<ResourceFile>(filename)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(asn.nodeName == EmbedDirectoryExpression)
|
||||||
|
{
|
||||||
|
if(!asn.nodes.empty() && std::holds_alternative<std::string>(asn.nodes[0]))
|
||||||
|
{
|
||||||
|
auto& filename = std::get<std::string>(asn.nodes[0]);
|
||||||
|
bytes.push_back(11);
|
||||||
|
|
||||||
|
|
||||||
|
std::function<void(Tesses::Framework::Filesystem::VFSPath path)> embedDir;
|
||||||
|
embedDir = [&](Tesses::Framework::Filesystem::VFSPath path)-> void {
|
||||||
|
bytes.push_back(8);
|
||||||
|
std::vector<std::pair<Tesses::Framework::Filesystem::VFSPath, bool>> entries;
|
||||||
|
if(embedFS != nullptr && embedFS->DirectoryExists(path))
|
||||||
|
for(auto& item : embedFS->EnumeratePaths(path))
|
||||||
|
{
|
||||||
|
if(embedFS->DirectoryExists(item))
|
||||||
|
entries.emplace_back(item,true);
|
||||||
|
else if(embedFS->FileExists(item))
|
||||||
|
entries.emplace_back(item,false);
|
||||||
|
|
||||||
|
|
||||||
|
/*GenNode(instructions,item.GetFileName(),scope,contscope,brkscope,contI,brkI);
|
||||||
|
if(embedFS->DirectoryExists(item))
|
||||||
|
{
|
||||||
|
embedDir(item);
|
||||||
|
}
|
||||||
|
else if(embedFS->RegularFileExists(item))
|
||||||
|
{
|
||||||
|
auto ce = AdvancedSyntaxNode::Create(ClosureExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(EmbedStreamExpression,true,{item.ToString()})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
GenNode(instructions,ce,scope,contscope,brkscope,contI,brkI);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
instructions.push_back(new SimpleInstruction(PUSHUNDEFINED));
|
||||||
|
}
|
||||||
|
|
||||||
|
instructions.push_back(new SimpleInstruction(APPENDDICT));*/
|
||||||
|
}
|
||||||
|
size_t offset = bytes.size();
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset], (uint32_t)entries.size());
|
||||||
|
for(auto& item : entries)
|
||||||
|
{
|
||||||
|
offset = bytes.size();
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset],GetString(item.first.GetFileName()));
|
||||||
|
if(item.second)
|
||||||
|
embedDir(item.first);
|
||||||
|
else {
|
||||||
|
bytes.push_back(12);
|
||||||
|
offset = bytes.size();
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
bytes.resize(offset+4);
|
||||||
|
BitConverter::FromUint32BE(bytes[offset],GetResource(std::make_shared<ResourceFile>(item.first.ToString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
embedDir(filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes.push_back(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeGen::Save(std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||||
|
{
|
||||||
|
TVMVersion runtime_version(CROSSLANG_BYTECODE_MAJOR,CROSSLANG_BYTECODE_MINOR,CROSSLANG_BYTECODE_PATCH,CROSSLANG_BYTECODE_BUILD,CROSSLANG_BYTECODE_VERSIONSTAGE);
|
||||||
uint8_t buffer[18];
|
uint8_t buffer[18];
|
||||||
memcpy(buffer,"TCROSSVM",8);
|
memcpy(buffer,"TCROSSVM",8);
|
||||||
runtime_version.ToArray(buffer+8);
|
runtime_version.ToArray(buffer+8);
|
||||||
@@ -56,6 +400,10 @@ namespace Tesses::CrossLang
|
|||||||
GetString(tool.first);
|
GetString(tool.first);
|
||||||
sections++;
|
sections++;
|
||||||
}
|
}
|
||||||
|
for(auto& meta : this->meta)
|
||||||
|
{
|
||||||
|
sections++;
|
||||||
|
}
|
||||||
if(!this->icon.empty())
|
if(!this->icon.empty())
|
||||||
{
|
{
|
||||||
this->GetResource(std::make_shared<ResourceFile>(this->icon));
|
this->GetResource(std::make_shared<ResourceFile>(this->icon));
|
||||||
@@ -235,7 +583,7 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
memcpy(buffer,"RESO",4);
|
memcpy(buffer,"RESO",4);
|
||||||
Write(stream,buffer,4);
|
Write(stream,buffer,4);
|
||||||
WriteInt(stream,reso->GetLength(vfs));
|
WriteInt(stream,reso->GetLength(embedFS));
|
||||||
reso->Write(stream);
|
reso->Write(stream);
|
||||||
}
|
}
|
||||||
if(!this->icon.empty())
|
if(!this->icon.empty())
|
||||||
@@ -246,6 +594,13 @@ namespace Tesses::CrossLang
|
|||||||
WriteInt(stream,this->GetResource(std::make_shared<ResourceFile>(this->icon)));
|
WriteInt(stream,this->GetResource(std::make_shared<ResourceFile>(this->icon)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
for(auto& meta : this->meta)
|
||||||
|
{
|
||||||
|
memcpy(buffer,"META", 4);
|
||||||
|
Write(stream,buffer,4);
|
||||||
|
WriteInt(stream,(uint32_t)meta.size());
|
||||||
|
Write(stream,meta.data(),meta.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -354,6 +709,21 @@ namespace Tesses::CrossLang
|
|||||||
BitConverter::FromUint32BE(buff[0],this->n);
|
BitConverter::FromUint32BE(buff[0],this->n);
|
||||||
instr.insert(instr.end(),buff.begin(),buff.end());
|
instr.insert(instr.end(),buff.begin(),buff.end());
|
||||||
}
|
}
|
||||||
|
EmbedStreamInstruction::EmbedStreamInstruction(uint32_t s)
|
||||||
|
{
|
||||||
|
this->n = s;
|
||||||
|
}
|
||||||
|
size_t EmbedStreamInstruction::Size()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
void EmbedStreamInstruction::Write(std::vector<uint8_t>& instr)
|
||||||
|
{
|
||||||
|
instr.push_back(PUSHRESOURCESTREAM);
|
||||||
|
std::array<uint8_t,4> buff;
|
||||||
|
BitConverter::FromUint32BE(buff[0],this->n);
|
||||||
|
instr.insert(instr.end(),buff.begin(),buff.end());
|
||||||
|
}
|
||||||
ClosureInstruction::ClosureInstruction(uint32_t s,bool hasScope)
|
ClosureInstruction::ClosureInstruction(uint32_t s,bool hasScope)
|
||||||
{
|
{
|
||||||
this->n = s;
|
this->n = s;
|
||||||
@@ -522,7 +892,14 @@ namespace Tesses::CrossLang
|
|||||||
TWO_EXPR(NotEqualsExpression, NEQ)
|
TWO_EXPR(NotEqualsExpression, NEQ)
|
||||||
TWO_EXPR(EqualsExpression, EQ)
|
TWO_EXPR(EqualsExpression, EQ)
|
||||||
TWO_EXPR(XOrExpression, XOR)
|
TWO_EXPR(XOrExpression, XOR)
|
||||||
if(adv.nodeName == NullCoalescingExpression && adv.nodes.size() == 2)
|
if(adv.nodeName == LineNode && adv.nodes.size() == 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||||
|
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||||
|
instructions.push_back(new SimpleInstruction(LINEINFO));
|
||||||
|
}
|
||||||
|
else if(adv.nodeName == NullCoalescingExpression && adv.nodes.size() == 2)
|
||||||
{
|
{
|
||||||
uint32_t ifId = NewId();
|
uint32_t ifId = NewId();
|
||||||
std::string ifIdTrue = "__compGenTrue";
|
std::string ifIdTrue = "__compGenTrue";
|
||||||
@@ -1358,6 +1735,60 @@ namespace Tesses::CrossLang
|
|||||||
instructions.push_back(new EmbedInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
instructions.push_back(new EmbedInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if(adv.nodeName == MetadataStatement && adv.nodes.size() == 2 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||||
|
{
|
||||||
|
auto& name = std::get<std::string>(adv.nodes[0]);
|
||||||
|
|
||||||
|
|
||||||
|
auto& metabytes= this->meta.emplace_back();
|
||||||
|
metabytes.resize(4);
|
||||||
|
BitConverter::FromUint32BE(metabytes[0],GetString(name));
|
||||||
|
|
||||||
|
WriteMetadataObject(metabytes, adv.nodes[1]);
|
||||||
|
}
|
||||||
|
else if(adv.nodeName == EmbedStreamExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||||
|
{
|
||||||
|
std::string filename = std::get<std::string>(adv.nodes[0]);
|
||||||
|
instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(adv.nodeName == EmbedDirectoryExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||||
|
{
|
||||||
|
std::string filename = std::get<std::string>(adv.nodes[0]);
|
||||||
|
std::function<void(Tesses::Framework::Filesystem::VFSPath path)> embedDir;
|
||||||
|
embedDir = [&](Tesses::Framework::Filesystem::VFSPath path)-> void {
|
||||||
|
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
|
||||||
|
|
||||||
|
if(embedFS != nullptr && embedFS->DirectoryExists(path))
|
||||||
|
for(auto& item : embedFS->EnumeratePaths(path))
|
||||||
|
{
|
||||||
|
GenNode(instructions,item.GetFileName(),scope,contscope,brkscope,contI,brkI);
|
||||||
|
if(embedFS->DirectoryExists(item))
|
||||||
|
{
|
||||||
|
embedDir(item);
|
||||||
|
}
|
||||||
|
else if(embedFS->RegularFileExists(item))
|
||||||
|
{
|
||||||
|
auto ce = AdvancedSyntaxNode::Create(ClosureExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(EmbedStreamExpression,true,{item.ToString()})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
GenNode(instructions,ce,scope,contscope,brkscope,contI,brkI);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
instructions.push_back(new SimpleInstruction(PUSHUNDEFINED));
|
||||||
|
}
|
||||||
|
|
||||||
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
embedDir(filename);
|
||||||
|
//
|
||||||
|
//instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||||
|
instructions.push_back(new SimpleInstruction(PUSHRESOUURCEDIR));
|
||||||
|
}
|
||||||
else if(adv.nodeName == HtmlRootExpression)
|
else if(adv.nodeName == HtmlRootExpression)
|
||||||
{
|
{
|
||||||
scope++;
|
scope++;
|
||||||
@@ -1381,6 +1812,7 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
else if(adv.nodeName == ScopeNode)
|
else if(adv.nodeName == ScopeNode)
|
||||||
{
|
{
|
||||||
|
|
||||||
scope++;
|
scope++;
|
||||||
instructions.push_back(new SimpleInstruction(SCOPEBEGIN));
|
instructions.push_back(new SimpleInstruction(SCOPEBEGIN));
|
||||||
for(size_t i = 0; i < adv.nodes.size(); i++)
|
for(size_t i = 0; i < adv.nodes.size(); i++)
|
||||||
|
|||||||
@@ -922,7 +922,7 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||||
|
|
||||||
gen.Save(nullptr,ms);
|
gen.Save(ms);
|
||||||
|
|
||||||
ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin);
|
ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||||
|
|
||||||
@@ -962,7 +962,27 @@ namespace Tesses::CrossLang
|
|||||||
if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\"");
|
if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\"");
|
||||||
EnsureSymbol(")");
|
EnsureSymbol(")");
|
||||||
node = AdvancedSyntaxNode::Create(EmbedExpression, true,{embed.text});
|
node = AdvancedSyntaxNode::Create(EmbedExpression, true,{embed.text});
|
||||||
}
|
}
|
||||||
|
else if(IsIdentifier("embedstrm"))
|
||||||
|
{
|
||||||
|
EnsureSymbol("(");
|
||||||
|
if(i >= tokens.size()) throw std::out_of_range("End of file");
|
||||||
|
auto embed = tokens[i];
|
||||||
|
i++;
|
||||||
|
if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\"");
|
||||||
|
EnsureSymbol(")");
|
||||||
|
node = AdvancedSyntaxNode::Create(EmbedStreamExpression, true,{embed.text});
|
||||||
|
}
|
||||||
|
else if(IsIdentifier("embeddir"))
|
||||||
|
{
|
||||||
|
EnsureSymbol("(");
|
||||||
|
if(i >= tokens.size()) throw std::out_of_range("End of file");
|
||||||
|
auto embed = tokens[i];
|
||||||
|
i++;
|
||||||
|
if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\"");
|
||||||
|
EnsureSymbol(")");
|
||||||
|
node = AdvancedSyntaxNode::Create(EmbedDirectoryExpression, true,{embed.text});
|
||||||
|
}
|
||||||
else if(tokens[i].type == LexTokenType::Identifier)
|
else if(tokens[i].type == LexTokenType::Identifier)
|
||||||
{
|
{
|
||||||
auto token=tokens[i];
|
auto token=tokens[i];
|
||||||
@@ -1304,6 +1324,15 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
bool Parser::CanEmit(LexTokenLineInfo& ifo)
|
||||||
|
{
|
||||||
|
if(!this->debug) return false;
|
||||||
|
bool same = ifo.line == this->lastLine && ifo.filename == this->lastFile;
|
||||||
|
this->lastFile = ifo.filename;
|
||||||
|
this->lastLine = ifo.line;
|
||||||
|
|
||||||
|
return !same;
|
||||||
|
}
|
||||||
SyntaxNode Parser::ParseNode(bool isRoot)
|
SyntaxNode Parser::ParseNode(bool isRoot)
|
||||||
{
|
{
|
||||||
std::string documentation="";
|
std::string documentation="";
|
||||||
@@ -1324,6 +1353,8 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
while(i < tokens.size() && (isRoot || !IsSymbol("}",false)))
|
while(i < tokens.size() && (isRoot || !IsSymbol("}",false)))
|
||||||
{
|
{
|
||||||
|
auto token = tokens[i];
|
||||||
|
if(CanEmit(token.lineInfo)) aSN.nodes.push_back(AdvancedSyntaxNode::Create(LineNode,false, {(int64_t)tokens[i].lineInfo.line,tokens[i].lineInfo.filename}));
|
||||||
aSN.nodes.push_back(ParseNode());
|
aSN.nodes.push_back(ParseNode());
|
||||||
IsSymbol(";");
|
IsSymbol(";");
|
||||||
}
|
}
|
||||||
@@ -1425,7 +1456,7 @@ namespace Tesses::CrossLang
|
|||||||
EnsureSymbol("(");
|
EnsureSymbol("(");
|
||||||
SyntaxNode list = ParseExpression();
|
SyntaxNode list = ParseExpression();
|
||||||
SyntaxNode body = nullptr;
|
SyntaxNode body = nullptr;
|
||||||
if(IsSymbol(":"))
|
if(IsSymbol(":") || IsIdentifier("in"))
|
||||||
{
|
{
|
||||||
item = list;
|
item = list;
|
||||||
list = ParseExpression();
|
list = ParseExpression();
|
||||||
@@ -1436,6 +1467,11 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
body = ParseNode();
|
body = ParseNode();
|
||||||
}
|
}
|
||||||
|
if(std::holds_alternative<std::nullptr_t>(item))
|
||||||
|
item = AdvancedSyntaxNode::Create(DeclareExpression,true, {
|
||||||
|
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"item"})
|
||||||
|
});
|
||||||
|
|
||||||
return AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body});
|
return AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body});
|
||||||
}
|
}
|
||||||
if(IsIdentifier("class"))
|
if(IsIdentifier("class"))
|
||||||
@@ -1650,6 +1686,25 @@ namespace Tesses::CrossLang
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(IsIdentifier("meta"))
|
||||||
|
{
|
||||||
|
if(i >= tokens.size() || tokens[i].type != LexTokenType::String)
|
||||||
|
{
|
||||||
|
std::cout << "WARN: meta is a conditional keyword,\nif you suffix it with a string, it will be assumed to be a metadata tag" << std::endl;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string name = tokens[i++].text;
|
||||||
|
EnsureSymbol("{");
|
||||||
|
auto expr = ParseExpression();
|
||||||
|
|
||||||
|
|
||||||
|
EnsureSymbol("}");
|
||||||
|
|
||||||
|
return AdvancedSyntaxNode::Create(MetadataStatement,false,{name, AdvancedSyntaxNode::Create(DictionaryExpression,true,{expr})});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if(IsIdentifier("func"))
|
if(IsIdentifier("func"))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ bool Download(Tesses::Framework::Filesystem::VFSPath filename,std::shared_ptr<Te
|
|||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
TF_InitWithConsole();
|
TF_InitWithConsole();
|
||||||
|
if(argc > 0)
|
||||||
|
TF_AllowPortable(argv[0]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -58,7 +60,11 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
|
|
||||||
auto p = Tesses::Framework::Platform::Environment::GetRealExecutablePath(Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(argv[0])).GetParent().GetParent() / "share" / "Tesses" / "CrossLang" / "Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm";
|
auto p = Tesses::Framework::Platform::Environment::GetRealExecutablePath(Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(argv[0])).GetParent().GetParent() / "share" / "Tesses" / "CrossLang" / "Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm";
|
||||||
|
if(argc == 2 && strcmp(argv[1],"configdir") == 0)
|
||||||
|
{
|
||||||
|
std::cout << dir.ToString() << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if(argc > 1 && strcmp(argv[1],"update-shell") == 0)
|
if(argc > 1 && strcmp(argv[1],"update-shell") == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -127,7 +133,7 @@ int main(int argc, char** argv)
|
|||||||
for(int arg=1;arg<argc;arg++)
|
for(int arg=1;arg<argc;arg++)
|
||||||
args->Add(std::string(argv[arg]));
|
args->Add(std::string(argv[arg]));
|
||||||
|
|
||||||
auto res = env->CallFunction(ls,"main",{args});
|
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||||
int64_t iresult;
|
int64_t iresult;
|
||||||
if(GetObject(res,iresult))
|
if(GetObject(res,iresult))
|
||||||
return (int)iresult;
|
return (int)iresult;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ void Help(const char* filename)
|
|||||||
printf(" -I: Set icon resource name (in the resource folder), should be a 128x128 png\n");
|
printf(" -I: Set icon resource name (in the resource folder), should be a 128x128 png\n");
|
||||||
printf(" -v: Set version (1.0.0.0-prod defaults to 1.0.0.0-dev)\n");
|
printf(" -v: Set version (1.0.0.0-prod defaults to 1.0.0.0-dev)\n");
|
||||||
printf(" -d: Add dependency (DependencyName-1.0.0.0-prod)\n");
|
printf(" -d: Add dependency (DependencyName-1.0.0.0-prod)\n");
|
||||||
|
printf(" -D: enable debug)\n");
|
||||||
printf(" -t: Declare a tool (ToolName-1.0.0.0-prod)\n");
|
printf(" -t: Declare a tool (ToolName-1.0.0.0-prod)\n");
|
||||||
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
||||||
printf(" -r: Set resource directory (RESDIR defaults to res)\n");
|
printf(" -r: Set resource directory (RESDIR defaults to res)\n");
|
||||||
@@ -46,7 +47,7 @@ int main(int argc, char** argv)
|
|||||||
std::string icon="";
|
std::string icon="";
|
||||||
std::string comptime="none";
|
std::string comptime="none";
|
||||||
TVMVersion version;
|
TVMVersion version;
|
||||||
|
bool debug=false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
Help(argv[0]);
|
Help(argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(strcmp(argv[i], "-o") == 0)
|
else if(strcmp(argv[i], "-o") == 0)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
@@ -187,6 +189,10 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(strcmp(argv[i],"-D") == 0)
|
||||||
|
{
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
source.push_back(argv[i]);
|
source.push_back(argv[i]);
|
||||||
}
|
}
|
||||||
@@ -202,7 +208,7 @@ int main(int argc, char** argv)
|
|||||||
for(auto src : source)
|
for(auto src : source)
|
||||||
{
|
{
|
||||||
std::ifstream strm(src,std::ios_base::in|std::ios_base::binary);
|
std::ifstream strm(src,std::ios_base::in|std::ios_base::binary);
|
||||||
int res = Lex(argv[1],strm,tokens);
|
int res = Lex(std::filesystem::absolute(src).string(),strm,tokens);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,8 +254,12 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Parser parser(tokens,gc,env);
|
Parser parser(tokens,gc,env);
|
||||||
|
parser.debug = debug;
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
|
|
||||||
|
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string()));
|
||||||
|
gen.embedFS = sfs;
|
||||||
|
|
||||||
gen.GenRoot(parser.ParseRoot());
|
gen.GenRoot(parser.ParseRoot());
|
||||||
gen.name = name;
|
gen.name = name;
|
||||||
gen.version = version;
|
gen.version = version;
|
||||||
@@ -269,9 +279,7 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
auto strm = std::make_shared<Tesses::Framework::Streams::FileStream>(outputDir / (name + "-" + version.ToString() + ".crvm"),"wb");
|
auto strm = std::make_shared<Tesses::Framework::Streams::FileStream>(outputDir / (name + "-" + version.ToString() + ".crvm"),"wb");
|
||||||
|
|
||||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string()));
|
gen.Save(strm);
|
||||||
|
|
||||||
gen.Save(sfs,strm);
|
|
||||||
}
|
}
|
||||||
if(gc != nullptr)
|
if(gc != nullptr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ using namespace Tesses::Framework::Filesystem;
|
|||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
TF_InitWithConsole();
|
TF_InitWithConsole();
|
||||||
|
if(argc > 0)
|
||||||
|
TF_AllowPortable(argv[0]);
|
||||||
GC gc;
|
GC gc;
|
||||||
gc.Start();
|
gc.Start();
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
@@ -24,13 +26,14 @@ int main(int argc, char** argv)
|
|||||||
Parser parser(tokens);
|
Parser parser(tokens);
|
||||||
|
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
|
|
||||||
|
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||||
|
gen.embedFS = sfs;
|
||||||
gen.GenRoot(parser.ParseRoot());
|
gen.GenRoot(parser.ParseRoot());
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
{
|
{
|
||||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
|
||||||
|
|
||||||
auto strm2 = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
auto strm2 = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||||
gen.Save(sfs,strm2);
|
gen.Save(strm2);
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -49,7 +52,7 @@ int main(int argc, char** argv)
|
|||||||
for(int arg=1;arg<argc;arg++)
|
for(int arg=1;arg<argc;arg++)
|
||||||
args->Add(std::string(argv[arg]));
|
args->Add(std::string(argv[arg]));
|
||||||
|
|
||||||
auto res = env->CallFunction(ls,"main",{args});
|
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||||
int64_t iresult;
|
int64_t iresult;
|
||||||
if(GetObject(res,iresult))
|
if(GetObject(res,iresult))
|
||||||
return (int)iresult;
|
return (int)iresult;
|
||||||
@@ -78,11 +81,12 @@ int main(int argc, char** argv)
|
|||||||
Parser parser(tokens);
|
Parser parser(tokens);
|
||||||
|
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
|
|
||||||
|
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||||
|
gen.embedFS = sfs;
|
||||||
gen.GenRoot(parser.ParseRoot());
|
gen.GenRoot(parser.ParseRoot());
|
||||||
|
|
||||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
gen.Save(strm2);
|
||||||
|
|
||||||
gen.Save(sfs, strm2);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(source == "exit")
|
else if(source == "exit")
|
||||||
@@ -98,11 +102,13 @@ int main(int argc, char** argv)
|
|||||||
Parser parser(tokens);
|
Parser parser(tokens);
|
||||||
|
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
|
|
||||||
|
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||||
|
gen.embedFS = sfs;
|
||||||
|
|
||||||
gen.GenRoot(parser.ParseRoot());
|
gen.GenRoot(parser.ParseRoot());
|
||||||
|
|
||||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
gen.Save(strm2);
|
||||||
|
|
||||||
gen.Save(sfs,strm2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ using namespace Tesses::CrossLang;
|
|||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
TF_InitWithConsole();
|
TF_InitWithConsole();
|
||||||
|
|
||||||
if(argc < 2)
|
if(argc < 2)
|
||||||
{
|
{
|
||||||
printf("USAGE: %s <filename.crvm> <args...>\n",argv[0]);
|
printf("USAGE: %s <filename.crvm> <args...>\n",argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if(argc > 0)
|
||||||
|
TF_AllowPortable(argv[0]);
|
||||||
|
|
||||||
GC gc;
|
GC gc;
|
||||||
gc.Start();
|
gc.Start();
|
||||||
@@ -29,13 +32,15 @@ int main(int argc, char** argv)
|
|||||||
port = std::stoi(item.second);
|
port = std::stoi(item.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env->EnsureDictionary(&gc,"Net")->SetValue("WebServerPort", (int64_t)port);
|
||||||
TList* args2 = TList::Create(ls);
|
TList* args2 = TList::Create(ls);
|
||||||
for(auto& item : args.positional)
|
for(auto& item : args.positional)
|
||||||
{
|
{
|
||||||
args2->Add(item);
|
args2->Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = env->CallFunction(ls, "WebAppMain", {args2});
|
auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2});
|
||||||
auto svr2 = Tesses::CrossLang::ToHttpServer(&gc,res);
|
auto svr2 = Tesses::CrossLang::ToHttpServer(&gc,res);
|
||||||
if(svr2 == nullptr) return 1;
|
if(svr2 == nullptr) return 1;
|
||||||
Tesses::Framework::Http::HttpServer svr(port,svr2);
|
Tesses::Framework::Http::HttpServer svr(port,svr2);
|
||||||
@@ -58,7 +63,7 @@ int main(int argc, char** argv)
|
|||||||
for(int arg=1;arg<argc;arg++)
|
for(int arg=1;arg<argc;arg++)
|
||||||
args->Add(std::string(argv[arg]));
|
args->Add(std::string(argv[arg]));
|
||||||
|
|
||||||
auto res = env->CallFunction(ls,"main",{args});
|
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||||
int64_t iresult;
|
int64_t iresult;
|
||||||
if(GetObject(res,iresult))
|
if(GetObject(res,iresult))
|
||||||
return (int)iresult;
|
return (int)iresult;
|
||||||
|
|||||||
@@ -320,6 +320,15 @@ namespace Tesses::CrossLang {
|
|||||||
dict->DeclareFunction(gc, "getSize", "Get console size",{},Console_getSize);
|
dict->DeclareFunction(gc, "getSize", "Get console size",{},Console_getSize);
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
env->DeclareVariable("Console", dict);
|
env->DeclareVariable("Console", dict);
|
||||||
|
auto _new = env->EnsureDictionary(gc,"New");
|
||||||
|
_new->DeclareFunction(gc,"ConsoleReader","Read from console",{},[](GCList& ls,std::vector<TObject> args)->TObject {
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::ConsoleReader>();
|
||||||
|
});
|
||||||
|
_new->DeclareFunction(gc,"ConsoleWriter","Write to console",{"$isStderr"},[](GCList& ls,std::vector<TObject> args)->TObject {
|
||||||
|
bool err;
|
||||||
|
if(GetArgument(args,0,err)) return std::make_shared<Tesses::Framework::TextStreams::ConsoleWriter>(err);
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::ConsoleWriter>();
|
||||||
|
});
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,19 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
return Tesses::Framework::Filesystem::VFSPath();
|
return Tesses::Framework::Filesystem::VFSPath();
|
||||||
}
|
}
|
||||||
|
static TObject Env_GetAll(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
TList* list = TList::Create(ls);
|
||||||
|
std::vector<std::pair<std::string, std::string>> env;
|
||||||
|
Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env);
|
||||||
|
for(auto& item : env)
|
||||||
|
{
|
||||||
|
list->Add(TDictionary::Create(ls,{TDItem("Key",item.first),TDItem("Value",item.second)}));
|
||||||
|
}
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
void TStd::RegisterEnv(GC* gc, TRootEnvironment* env)
|
void TStd::RegisterEnv(GC* gc, TRootEnvironment* env)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -126,8 +139,9 @@ namespace Tesses::CrossLang
|
|||||||
TDictionary* dict = TDictionary::Create(ls);
|
TDictionary* dict = TDictionary::Create(ls);
|
||||||
dict->DeclareFunction(gc,"GetAt","Get environment variable", {"key"}, Env_GetAt);
|
dict->DeclareFunction(gc,"GetAt","Get environment variable", {"key"}, Env_GetAt);
|
||||||
dict->DeclareFunction(gc,"SetAt","Set environment variable", {"key","value"}, Env_SetAt);
|
dict->DeclareFunction(gc,"SetAt","Set environment variable", {"key","value"}, Env_SetAt);
|
||||||
|
dict->DeclareFunction(gc,"GetAll","Get all of the environment variables",{},Env_GetAll);
|
||||||
|
|
||||||
dict->DeclareFunction(gc,"getDesktop","Get downloads folder",{},Env_getDownloads);
|
dict->DeclareFunction(gc,"getDesktop","Get desktop folder",{},Env_getDesktop);
|
||||||
dict->DeclareFunction(gc,"getDownloads","Get downloads folder",{},Env_getDownloads);
|
dict->DeclareFunction(gc,"getDownloads","Get downloads folder",{},Env_getDownloads);
|
||||||
dict->DeclareFunction(gc,"getDocuments","Get documents folder",{},Env_getDocuments);
|
dict->DeclareFunction(gc,"getDocuments","Get documents folder",{},Env_getDocuments);
|
||||||
dict->DeclareFunction(gc,"getMusic","Get music folder",{},Env_getMusic);
|
dict->DeclareFunction(gc,"getMusic","Get music folder",{},Env_getMusic);
|
||||||
|
|||||||
@@ -172,15 +172,157 @@ namespace Tesses::CrossLang
|
|||||||
return nullptr;
|
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)
|
void TStd::RegisterIO(GC* gc,TRootEnvironment* env,bool enableLocalFilesystem)
|
||||||
{
|
{
|
||||||
|
|
||||||
env->permissions.canRegisterIO=true;
|
env->permissions.canRegisterIO=true;
|
||||||
env->permissions.canRegisterLocalFS = enableLocalFilesystem;
|
env->permissions.canRegisterLocalFS = enableLocalFilesystem;
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
TDictionary* dict = TDictionary::Create(ls);
|
|
||||||
|
|
||||||
gc->BarrierBegin();
|
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)
|
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, "CreateArchive", "Create a crvm archive",{"fs","strm","name","version","info"},FS_CreateArchive);
|
||||||
dict->DeclareFunction(gc,"ExtractArchive", "Extract a crvm archive",{"strm","vfs"},FS_ExtractArchive);
|
dict->DeclareFunction(gc,"ExtractArchive", "Extract a crvm archive",{"strm","vfs"},FS_ExtractArchive);
|
||||||
env->DeclareVariable("FS", dict);
|
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,6 +81,21 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
|
static TObject JsonDocEncode(GCList& ls2, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(args.size() >= 1)
|
||||||
|
{
|
||||||
|
bool indent = (args.size() == 2 && std::holds_alternative<bool>(args[1]) && std::get<bool>(args[1]));
|
||||||
|
|
||||||
|
auto json = JsonSerialize(args[0]);
|
||||||
|
JArray ar;
|
||||||
|
if(TryGetJToken(json,ar))
|
||||||
|
return Json::DocEncode(ar,indent);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
static TObject JsonDeserialize(GCList& ls2,JToken json)
|
static TObject JsonDeserialize(GCList& ls2,JToken json)
|
||||||
{
|
{
|
||||||
if(std::holds_alternative<JUndefined>(json)) return nullptr;
|
if(std::holds_alternative<JUndefined>(json)) return nullptr;
|
||||||
@@ -138,6 +153,19 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
static TObject JsonDocDecode(GCList& ls2,std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(args.size() > 0 && std::holds_alternative<std::string>(args[0]))
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
return JsonDeserialize(ls2, Json::DocDecode(std::get<std::string>(args[0])));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
std::string Json_Encode(TObject o,bool indent)
|
std::string Json_Encode(TObject o,bool indent)
|
||||||
{
|
{
|
||||||
return Json::Encode(JsonSerialize(o),indent);
|
return Json::Encode(JsonSerialize(o),indent);
|
||||||
@@ -146,14 +174,29 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
return JsonDeserialize(ls,Json::Decode(str));
|
return JsonDeserialize(ls,Json::Decode(str));
|
||||||
}
|
}
|
||||||
|
std::string Json_DocEncode(TObject o,bool indent)
|
||||||
|
{
|
||||||
|
auto obj = JsonSerialize(o);
|
||||||
|
JArray ls;
|
||||||
|
if(TryGetJToken(obj,ls))
|
||||||
|
return Json::DocEncode(ls,indent);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
TObject Json_DocDecode(GCList ls,std::string str)
|
||||||
|
{
|
||||||
|
return JsonDeserialize(ls,Json::DocDecode(str));
|
||||||
|
}
|
||||||
void TStd::RegisterJson(GC* gc,TRootEnvironment* env)
|
void TStd::RegisterJson(GC* gc,TRootEnvironment* env)
|
||||||
{
|
{
|
||||||
|
|
||||||
env->permissions.canRegisterJSON=true;
|
env->permissions.canRegisterJSON=true;
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
TDictionary* dict = TDictionary::Create(ls);
|
TDictionary* dict = TDictionary::Create(ls);
|
||||||
dict->DeclareFunction(gc, "Decode","Deserialize Json",{"Json string"},JsonDecode);
|
dict->DeclareFunction(gc, "Decode","Deserialize Json",{"jsonString"},JsonDecode);
|
||||||
dict->DeclareFunction(gc, "Encode","Serialize Json",{"any","$indent"},JsonEncode);
|
dict->DeclareFunction(gc, "Encode","Serialize Json",{"any","$indent"},JsonEncode);
|
||||||
|
dict->DeclareFunction(gc, "DocDecode", "Deserialize JsonDoc", {"jsonDocString"},JsonDocDecode);
|
||||||
|
dict->DeclareFunction(gc, "DocEncode", "Serialize JsonDoc", {"ls","$indent"},JsonDocEncode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
|||||||
@@ -295,6 +295,7 @@ namespace Tesses::CrossLang
|
|||||||
else if(key == "getQueryParams") return TNativeObject::Create<THttpDictionary>(ls, &ctx->queryParams,this);
|
else if(key == "getQueryParams") return TNativeObject::Create<THttpDictionary>(ls, &ctx->queryParams,this);
|
||||||
else if(key == "getRequestHeaders") return TNativeObject::Create<THttpDictionary>(ls, &ctx->requestHeaders,this);
|
else if(key == "getRequestHeaders") return TNativeObject::Create<THttpDictionary>(ls, &ctx->requestHeaders,this);
|
||||||
else if(key == "getResponseHeaders") return TNativeObject::Create<THttpDictionary>(ls, &ctx->responseHeaders,this);
|
else if(key == "getResponseHeaders") return TNativeObject::Create<THttpDictionary>(ls, &ctx->responseHeaders,this);
|
||||||
|
else if(key == "getPathArguments") return TNativeObject::Create<THttpDictionary>(ls,&ctx->pathArguments, this);
|
||||||
else if(key == "GetStream") return ctx->GetStream();
|
else if(key == "GetStream") return ctx->GetStream();
|
||||||
else if(key == "OpenRequestStream") return ctx->OpenRequestStream();
|
else if(key == "OpenRequestStream") return ctx->OpenRequestStream();
|
||||||
else if(key == "OpenResponseStream") return ctx->OpenResponseStream();
|
else if(key == "OpenResponseStream") return ctx->OpenResponseStream();
|
||||||
@@ -578,6 +579,7 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,7 +899,8 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
~THttpResponse()
|
~THttpResponse()
|
||||||
{
|
{
|
||||||
Close();
|
delete this->response;
|
||||||
|
this->response = nullptr;
|
||||||
}
|
}
|
||||||
std::string TypeName()
|
std::string TypeName()
|
||||||
{
|
{
|
||||||
@@ -1478,9 +1481,14 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
static TObject New_MountableServer(GCList& ls, std::vector<TObject> args)
|
static TObject New_MountableServer(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
if(args.empty()) return Undefined();
|
if(args.empty()) return std::make_shared<MountableServer>();
|
||||||
return std::make_shared<MountableServer>(ToHttpServer(ls.GetGC(),args[0]));
|
return std::make_shared<MountableServer>(ToHttpServer(ls.GetGC(),args[0]));
|
||||||
}
|
}
|
||||||
|
static TObject New_RouteServer(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(args.empty()) return std::make_shared<RouteServer>();
|
||||||
|
return std::make_shared<RouteServer>(ToHttpServer(ls.GetGC(),args[0]));
|
||||||
|
}
|
||||||
static TObject New_StreamHttpRequestBody(GCList& ls, std::vector<TObject> args)
|
static TObject New_StreamHttpRequestBody(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Stream> strm;
|
std::shared_ptr<Stream> strm;
|
||||||
@@ -1530,6 +1538,8 @@ namespace Tesses::CrossLang
|
|||||||
_new->DeclareFunction(gc, "HttpServer", "Create a http server (allows multiple)",{"server","portOrUnixPath","$printIPs"},[env](GCList& ls, std::vector<TObject> args)->TObject{
|
_new->DeclareFunction(gc, "HttpServer", "Create a http server (allows multiple)",{"server","portOrUnixPath","$printIPs"},[env](GCList& ls, std::vector<TObject> args)->TObject{
|
||||||
return New_HttpServer(ls,args,env);
|
return New_HttpServer(ls,args,env);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_new->DeclareFunction(gc, "RouteServer","Create a routeserver",{"$root"}, New_RouteServer);
|
||||||
_new->DeclareFunction(gc, "FileServer","Create a file server",{"vfs","allowlisting","spa"}, New_FileServer);
|
_new->DeclareFunction(gc, "FileServer","Create a file server",{"vfs","allowlisting","spa"}, New_FileServer);
|
||||||
_new->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", {"$server","$auth","$realm"},New_BasicAuthServer);
|
_new->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", {"$server","$auth","$realm"},New_BasicAuthServer);
|
||||||
_new->DeclareFunction(gc, "MountableServer","Create a server you can mount to, must mount parents before child",{"root"}, New_MountableServer);
|
_new->DeclareFunction(gc, "MountableServer","Create a server you can mount to, must mount parents before child",{"root"}, New_MountableServer);
|
||||||
@@ -1564,6 +1574,8 @@ namespace Tesses::CrossLang
|
|||||||
http->DeclareFunction(gc, "ListenSimpleWithLoop", "Listen (creates application loop)", {"server","port"},Net_Http_ListenSimpleWithLoop);
|
http->DeclareFunction(gc, "ListenSimpleWithLoop", "Listen (creates application loop)", {"server","port"},Net_Http_ListenSimpleWithLoop);
|
||||||
http->DeclareFunction(gc, "ListenOnUnusedPort","Listen on unused localhost port and print Port: theport",{"server"},Net_Http_ListenOnUnusedPort);
|
http->DeclareFunction(gc, "ListenOnUnusedPort","Listen on unused localhost port and print Port: theport",{"server"},Net_Http_ListenOnUnusedPort);
|
||||||
//FileServer svr()
|
//FileServer svr()
|
||||||
|
|
||||||
|
http->DeclareFunction(gc, "RouteServer","Create a routeserver",{"$root"}, New_RouteServer);
|
||||||
http->DeclareFunction(gc, "FileServer","Create a file server",{"vfs","allowlisting","spa"}, New_FileServer);
|
http->DeclareFunction(gc, "FileServer","Create a file server",{"vfs","allowlisting","spa"}, New_FileServer);
|
||||||
http->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", {"$server","$auth","$realm"},New_BasicAuthServer);
|
http->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", {"$server","$auth","$realm"},New_BasicAuthServer);
|
||||||
http->DeclareFunction(gc, "BasicAuthGetCreds","Get creds from str",{"ctx"},[](GCList& ls, std::vector<TObject> args)->TObject {
|
http->DeclareFunction(gc, "BasicAuthGetCreds","Get creds from str",{"ctx"},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||||
@@ -1604,4 +1616,25 @@ namespace Tesses::CrossLang
|
|||||||
dict->SetValue("Smtp", smtp);
|
dict->SetValue("Smtp", smtp);
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tesses::Framework::Http::ServerRequestHandler TCallable::ToRouteServerRequestHandler(GC* gc)
|
||||||
|
{
|
||||||
|
auto value = CreateMarkedTObject(gc,this);
|
||||||
|
return [value,this](ServerContext& ctx)->bool {
|
||||||
|
auto v=value;
|
||||||
|
auto gc = v->GetGC();
|
||||||
|
GCList ls(gc);
|
||||||
|
auto res = TNativeObject::Create<TServerContext>(ls, &ctx);
|
||||||
|
bool result;
|
||||||
|
auto out = this->Call(ls,{res});
|
||||||
|
if(GetObject(out,result))
|
||||||
|
{
|
||||||
|
res->Finish();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
res->Finish();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -556,6 +556,18 @@ namespace Tesses::CrossLang
|
|||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||||
return GetArgument(args,0,strm);
|
return GetArgument(args,0,strm);
|
||||||
}
|
}
|
||||||
|
static TObject TypeIsTextReader(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(args.empty()) return nullptr;
|
||||||
|
std::shared_ptr<Tesses::Framework::TextStreams::TextReader> strm;
|
||||||
|
return GetArgument(args,0,strm);
|
||||||
|
}
|
||||||
|
static TObject TypeIsTextWriter(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(args.empty()) return nullptr;
|
||||||
|
std::shared_ptr<Tesses::Framework::TextStreams::TextWriter> strm;
|
||||||
|
return GetArgument(args,0,strm);
|
||||||
|
}
|
||||||
static TObject TypeIsVFS(GCList& ls, std::vector<TObject> args)
|
static TObject TypeIsVFS(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
if(args.empty()) return nullptr;
|
if(args.empty()) return nullptr;
|
||||||
@@ -752,6 +764,7 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
auto fileServer = std::dynamic_pointer_cast<Tesses::Framework::Http::FileServer>(svr);
|
auto fileServer = std::dynamic_pointer_cast<Tesses::Framework::Http::FileServer>(svr);
|
||||||
auto mountableServer = std::dynamic_pointer_cast<Tesses::Framework::Http::MountableServer>(svr);
|
auto mountableServer = std::dynamic_pointer_cast<Tesses::Framework::Http::MountableServer>(svr);
|
||||||
|
auto routableServer = std::dynamic_pointer_cast<Tesses::Framework::Http::RouteServer>(svr);
|
||||||
if(fileServer != nullptr)
|
if(fileServer != nullptr)
|
||||||
{
|
{
|
||||||
return "FileServer";
|
return "FileServer";
|
||||||
@@ -760,10 +773,63 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
return "MountableServer";
|
return "MountableServer";
|
||||||
}
|
}
|
||||||
|
if(routableServer != nullptr)
|
||||||
|
{
|
||||||
|
return "RoutableServer";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return "HttpServer";
|
return "HttpServer";
|
||||||
|
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextReader>>(_obj))
|
||||||
|
{
|
||||||
|
auto textReader = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextReader>>(_obj);
|
||||||
|
if(textReader != nullptr)
|
||||||
|
{
|
||||||
|
auto stringReader = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringReader>(textReader);
|
||||||
|
auto streamReader = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StreamReader>(textReader);
|
||||||
|
auto consoleReader = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::ConsoleReader>(textReader);
|
||||||
|
if(stringReader != nullptr)
|
||||||
|
{
|
||||||
|
return "StringReader";
|
||||||
|
}
|
||||||
|
if(streamReader != nullptr)
|
||||||
|
{
|
||||||
|
return "StreamReader";
|
||||||
|
}
|
||||||
|
if(consoleReader != nullptr)
|
||||||
|
{
|
||||||
|
return "ConsoleReader";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "TextReader";
|
||||||
|
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(_obj))
|
||||||
|
{
|
||||||
|
auto textWriter = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(_obj);
|
||||||
|
if(textWriter != nullptr)
|
||||||
|
{
|
||||||
|
auto stringWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringWriter>(textWriter);
|
||||||
|
auto streamWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StreamWriter>(textWriter);
|
||||||
|
auto consoleWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::ConsoleReader>(textWriter);
|
||||||
|
if(stringWriter != nullptr)
|
||||||
|
{
|
||||||
|
return "StringWriter";
|
||||||
|
}
|
||||||
|
if(streamWriter != nullptr)
|
||||||
|
{
|
||||||
|
return "StreamWriter";
|
||||||
|
}
|
||||||
|
if(consoleWriter != nullptr)
|
||||||
|
{
|
||||||
|
return "ConsoleWriter";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "TextReader";
|
||||||
|
|
||||||
}
|
}
|
||||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(_obj))
|
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(_obj))
|
||||||
{
|
{
|
||||||
@@ -997,9 +1063,48 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
static TObject New_Task(GCList& ls, std::vector<TObject> args)
|
static TObject New_Promise(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
return TTask::Create(ls);
|
TCallable* call;
|
||||||
|
|
||||||
|
if(GetArgumentHeap(args,0,call))
|
||||||
|
{
|
||||||
|
|
||||||
|
TTask* task = TTask::Create(ls);
|
||||||
|
|
||||||
|
TExternalMethod* resolve = TExternalMethod::Create(ls, "fulfill the promise",{"arg"},[task](GCList& ls,std::vector<TObject> args)->TObject {
|
||||||
|
if(!args.empty())
|
||||||
|
{
|
||||||
|
task->SetSucceeded(args[0]);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
});
|
||||||
|
resolve->watch.push_back(task);
|
||||||
|
TExternalMethod* reject = TExternalMethod::Create(ls, "reject the promise",{"arg"},[task](GCList& ls,std::vector<TObject> args)->TObject {
|
||||||
|
if(!args.empty())
|
||||||
|
{
|
||||||
|
auto item = args[0];
|
||||||
|
if(!std::holds_alternative<Undefined>(item))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
VMByteCodeException ex(ls.GetGC(),item,nullptr);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
task->SetFailed(std::current_exception());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
});
|
||||||
|
reject->watch.push_back(task);
|
||||||
|
|
||||||
|
call->Call(ls,{resolve,reject});
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
static TObject TimeSpan_Parse(GCList& ls, std::vector<TObject> args)
|
static TObject TimeSpan_Parse(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
@@ -1051,6 +1156,72 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
static TObject New_StreamReader(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||||
|
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
|
||||||
|
Tesses::Framework::Filesystem::VFSPath path;
|
||||||
|
|
||||||
|
if(GetArgument(args,0,strm))
|
||||||
|
{
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::StreamReader>(strm);
|
||||||
|
}
|
||||||
|
else if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path))
|
||||||
|
{
|
||||||
|
strm = vfs->OpenFile(path,"rb");
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::StreamReader>(strm);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TObject New_StreamWriter(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||||
|
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
|
||||||
|
Tesses::Framework::Filesystem::VFSPath path;
|
||||||
|
|
||||||
|
if(GetArgument(args,0,strm))
|
||||||
|
{
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::StreamWriter>(strm);
|
||||||
|
}
|
||||||
|
else if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path))
|
||||||
|
{
|
||||||
|
bool append=false;
|
||||||
|
GetArgument(args,2,append);
|
||||||
|
|
||||||
|
strm = vfs->OpenFile(path,append ? "ab" : "wb");
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::StreamWriter>(strm);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
static TObject New_StringReader(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
if(GetArgument(args,0,str))
|
||||||
|
{
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::StringReader>(str);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
static TObject New_StringWriter(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
if(GetArgument(args,0,str))
|
||||||
|
{
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::StringWriter>(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_shared<Tesses::Framework::TextStreams::StringWriter>();
|
||||||
|
}
|
||||||
|
static TObject Task_FromResult(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(!args.empty())
|
||||||
|
{
|
||||||
|
return TTask::FromResult(ls,args[0]);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
void TStd::RegisterRoot(GC* gc, TRootEnvironment* env)
|
void TStd::RegisterRoot(GC* gc, TRootEnvironment* env)
|
||||||
{
|
{
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
@@ -1095,10 +1266,11 @@ namespace Tesses::CrossLang
|
|||||||
return TTask::Run(ls,closure);
|
return TTask::Run(ls,closure);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
});
|
});
|
||||||
|
task->DeclareFunction(gc, "FromResult", "async from result", {"result"}, Task_FromResult);
|
||||||
|
|
||||||
TDictionary* newTypes = env->EnsureDictionary(gc, "New");
|
TDictionary* newTypes = env->EnsureDictionary(gc, "New");
|
||||||
|
//newTypes->DeclareFunction(gc,)
|
||||||
|
newTypes->DeclareFunction(gc, "Promise", "Create an async object",{"resolve","reject"},New_Promise);
|
||||||
newTypes->DeclareFunction(gc, "DateTime","Create a DateTime object, if only one arg is provided year is epoch, isLocal defaults to true unless epoch",{"year","$month","$day","$hour","$minute","$second","$isLocal"},New_DateTime);
|
newTypes->DeclareFunction(gc, "DateTime","Create a DateTime object, if only one arg is provided year is epoch, isLocal defaults to true unless epoch",{"year","$month","$day","$hour","$minute","$second","$isLocal"},New_DateTime);
|
||||||
newTypes->DeclareFunction(gc, "TimeSpan","Create a DateTime object, if only one arg is provided days is totalSeconds, if there are only three arguments days will be hours, hours will be minutes, minutes will be seconds (according to the argument documentation)",{"days","$hours","$minutes","$seconds"},New_TimeSpan);
|
newTypes->DeclareFunction(gc, "TimeSpan","Create a DateTime object, if only one arg is provided days is totalSeconds, if there are only three arguments days will be hours, hours will be minutes, minutes will be seconds (according to the argument documentation)",{"days","$hours","$minutes","$seconds"},New_TimeSpan);
|
||||||
|
|
||||||
@@ -1133,7 +1305,18 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
return TVMVersion((uint8_t)major,(uint8_t)minor,(uint8_t)patch,(uint16_t)build,stage);
|
return TVMVersion((uint8_t)major,(uint8_t)minor,(uint8_t)patch,(uint16_t)build,stage);
|
||||||
});
|
});
|
||||||
|
newTypes->DeclareFunction(gc,"Random","Create random number generator",{"$seed"}, [](GCList& ls,std::vector<TObject> args)->TObject{
|
||||||
|
int64_t seed;
|
||||||
|
if(GetArgument(args,0,seed))
|
||||||
|
{
|
||||||
|
return TNativeObject::Create<TRandom>(ls, (uint64_t)seed);
|
||||||
|
}
|
||||||
|
return TNativeObject::Create<TRandom>(ls);
|
||||||
|
});
|
||||||
|
newTypes->DeclareFunction(gc, "StreamReader","Create a StreamReader", {"strmOrVFS","$pathIfVFS"},New_StreamReader);
|
||||||
|
newTypes->DeclareFunction(gc, "StreamWriter","Create a StreamWriter", {"strmOrVFS","$pathIfVFS","$appendIfVFS"},New_StreamWriter);
|
||||||
|
newTypes->DeclareFunction(gc, "StringReader","Create a StringReader", {"str"},New_StringReader);
|
||||||
|
newTypes->DeclareFunction(gc, "StringWriter","Create a StringWriter", {"$str"},New_StringWriter);
|
||||||
|
|
||||||
env->DeclareFunction(gc, "ParseLong","Parse Long from String",{"arg","$base"},ParseLong);
|
env->DeclareFunction(gc, "ParseLong","Parse Long from String",{"arg","$base"},ParseLong);
|
||||||
env->DeclareFunction(gc, "ParseDouble","Parse Double from String",{"arg"},ParseDouble);
|
env->DeclareFunction(gc, "ParseDouble","Parse Double from String",{"arg"},ParseDouble);
|
||||||
@@ -1154,6 +1337,8 @@ namespace Tesses::CrossLang
|
|||||||
env->DeclareFunction(gc, "TypeIsVFS","Get whether object is a virtual filesystem",{"object"},TypeIsVFS);
|
env->DeclareFunction(gc, "TypeIsVFS","Get whether object is a virtual filesystem",{"object"},TypeIsVFS);
|
||||||
env->DeclareFunction(gc, "TypeIsDateTime","Get whether object is a DateTime",{"object"},TypeIsDateTime);
|
env->DeclareFunction(gc, "TypeIsDateTime","Get whether object is a DateTime",{"object"},TypeIsDateTime);
|
||||||
env->DeclareFunction(gc, "TypeIsTimeSpan","Get whether object is a TimeSpan",{"object"},TypeIsTimeSpan);
|
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);
|
||||||
|
|
||||||
|
|
||||||
newTypes->DeclareFunction(gc, "Regex", "Create regex object",{"regex"},[](GCList& ls,std::vector<TObject> args)->TObject {
|
newTypes->DeclareFunction(gc, "Regex", "Create regex object",{"regex"},[](GCList& ls,std::vector<TObject> args)->TObject {
|
||||||
@@ -1200,7 +1385,6 @@ namespace Tesses::CrossLang
|
|||||||
return TAssociativeArray::Create(ls);
|
return TAssociativeArray::Create(ls);
|
||||||
});
|
});
|
||||||
newTypes->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray);
|
newTypes->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray);
|
||||||
newTypes->DeclareFunction(gc,"Task","Create a task for async, to manually create an async object",{},New_Task);
|
|
||||||
|
|
||||||
env->DeclareVariable("Version", TDictionary::Create(ls,{
|
env->DeclareVariable("Version", TDictionary::Create(ls,{
|
||||||
TDItem("Parse",TExternalMethod::Create(ls,"Parse version from string",{"versionStr"},[](GCList& ls, std::vector<TObject> args)->TObject{
|
TDItem("Parse",TExternalMethod::Create(ls,"Parse version from string",{"versionStr"},[](GCList& ls, std::vector<TObject> args)->TObject{
|
||||||
|
|||||||
@@ -133,11 +133,12 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
std::string name = "Out";
|
std::string name = "Out";
|
||||||
std::vector<std::pair<std::string,std::string>> sources;
|
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>> dependencies;
|
||||||
std::vector<std::pair<std::string,TVMVersion>> tools;
|
std::vector<std::pair<std::string,TVMVersion>> tools;
|
||||||
std::string info;
|
std::string info;
|
||||||
std::string icon;
|
std::string icon;
|
||||||
|
bool debug=false;
|
||||||
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
|
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
|
||||||
|
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
@@ -152,6 +153,7 @@ namespace Tesses::CrossLang
|
|||||||
TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem");
|
TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem");
|
||||||
|
|
||||||
TObject _out = dict->GetValue("Output");
|
TObject _out = dict->GetValue("Output");
|
||||||
|
TObject _dbg = dict->GetValue("Debug");
|
||||||
TList* _toolList;
|
TList* _toolList;
|
||||||
TList* _depList; TList* srcLst;
|
TList* _depList; TList* srcLst;
|
||||||
TRootEnvironment* comptimeEnv=nullptr;
|
TRootEnvironment* comptimeEnv=nullptr;
|
||||||
@@ -160,6 +162,7 @@ namespace Tesses::CrossLang
|
|||||||
GetObject<std::string>(_icon,icon);
|
GetObject<std::string>(_icon,icon);
|
||||||
GetObject(_resourceFileSystem, vfs);
|
GetObject(_resourceFileSystem, vfs);
|
||||||
GetObjectHeap(_comptime,comptimeEnv);
|
GetObjectHeap(_comptime,comptimeEnv);
|
||||||
|
GetObject(_dbg,debug);
|
||||||
std::string v2;
|
std::string v2;
|
||||||
if(GetObject<std::string>(_version,v2))
|
if(GetObject<std::string>(_version,v2))
|
||||||
TVMVersion::TryParse(v2, version);
|
TVMVersion::TryParse(v2, version);
|
||||||
@@ -258,8 +261,10 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Parser parser(tokens,ls.GetGC(),comptimeEnv);
|
Parser parser(tokens,ls.GetGC(),comptimeEnv);
|
||||||
|
parser.debug = debug;
|
||||||
SyntaxNode n = parser.ParseRoot();
|
SyntaxNode n = parser.ParseRoot();
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
|
gen.embedFS = vfs;
|
||||||
gen.GenRoot(n);
|
gen.GenRoot(n);
|
||||||
gen.dependencies = dependencies;
|
gen.dependencies = dependencies;
|
||||||
gen.tools = tools;
|
gen.tools = tools;
|
||||||
@@ -271,7 +276,7 @@ namespace Tesses::CrossLang
|
|||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> stream;
|
std::shared_ptr<Tesses::Framework::Streams::Stream> stream;
|
||||||
if(GetObject(_out, stream))
|
if(GetObject(_out, stream))
|
||||||
{
|
{
|
||||||
gen.Save(vfs, stream);
|
gen.Save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -282,11 +287,43 @@ namespace Tesses::CrossLang
|
|||||||
return Failure(ls, ex.what());
|
return Failure(ls, ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static TObject VM_GetStacktrace(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(current_function != nullptr)
|
||||||
|
{
|
||||||
|
if(current_function->thread != nullptr)
|
||||||
|
{
|
||||||
|
TList* list = TList::Create(ls);
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
for(auto item : current_function->thread->call_stack_entries)
|
||||||
|
{
|
||||||
|
auto dict = TDictionary::Create(ls);
|
||||||
|
if(item->callable->closure->name)
|
||||||
|
dict->SetValue("Name", *item->callable->closure->name);
|
||||||
|
|
||||||
|
dict->SetValue("Closure", item->callable->closure);
|
||||||
|
dict->SetValue("FileName", item->callable->file->name + "-" + item->callable->file->version.ToString() + ".crvm");
|
||||||
|
dict->SetValue("IP",(int64_t)item->ip);
|
||||||
|
if(item->srcline >= 1)
|
||||||
|
{
|
||||||
|
dict->SetValue("SourceFile", item->srcfile);
|
||||||
|
dict->SetValue("SourceLine",item->srcline);
|
||||||
|
}
|
||||||
|
list->Add(dict);
|
||||||
|
}
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
void TStd::RegisterVM(GC* gc,TRootEnvironment* env)
|
void TStd::RegisterVM(GC* gc,TRootEnvironment* env)
|
||||||
{
|
{
|
||||||
env->permissions.canRegisterVM=true;
|
env->permissions.canRegisterVM=true;
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
|
|
||||||
TDictionary* dict = TDictionary::Create(ls);
|
TDictionary* dict = TDictionary::Create(ls);
|
||||||
|
dict->DeclareFunction(gc, "GetStacktrace","Get the current stack trace", {}, VM_GetStacktrace);
|
||||||
dict->DeclareFunction(gc, "getRootEnvironmentAsDictionary","Get root environment as a dictionary",{},[env](GCList& ls, std::vector<TObject> args)-> TObject{
|
dict->DeclareFunction(gc, "getRootEnvironmentAsDictionary","Get root environment as a dictionary",{},[env](GCList& ls, std::vector<TObject> args)-> TObject{
|
||||||
return env->GetDictionary();
|
return env->GetDictionary();
|
||||||
});
|
});
|
||||||
@@ -322,7 +359,10 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
dict->DeclareFunction(gc, "SourceToAst", "Convert source to ast", {"source"}, VM_SourceToAst);
|
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 {
|
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 {
|
dict->DeclareFunction(gc, "getIsRunning","Is the program still running",{},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||||
return Tesses::Framework::TF_IsRunning();
|
return Tesses::Framework::TF_IsRunning();
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ namespace Tesses::CrossLang
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
||||||
|
clos->closure->name = obj->name + "::" + ent.name;
|
||||||
clos->className = ownerNow;
|
clos->className = ownerNow;
|
||||||
clos->documentation = entry.documentation;
|
clos->documentation = entry.documentation;
|
||||||
ent.value = clos;
|
ent.value = clos;
|
||||||
@@ -163,6 +164,7 @@ namespace Tesses::CrossLang
|
|||||||
if(entry.isAbstract) ent.value = Undefined();
|
if(entry.isAbstract) ent.value = Undefined();
|
||||||
else {
|
else {
|
||||||
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
||||||
|
clos->closure->name = obj->name + "::" + ent.name;
|
||||||
clos->className = ownerNow;
|
clos->className = ownerNow;
|
||||||
ent.value = clos->Call(*ls,{});
|
ent.value = clos->Call(*ls,{});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,33 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
TObject TDictionary::CallMethodWithFatalError(GCList& ls, std::string key, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
auto res = this->GetValue(key);
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
TCallable* callable;
|
||||||
|
|
||||||
|
if(GetObjectHeap(res,callable))
|
||||||
|
{
|
||||||
|
auto closure = dynamic_cast<TClosure*>(callable);
|
||||||
|
if(closure != nullptr && !closure->closure->args.empty() && closure->closure->args.front() == "this")
|
||||||
|
{
|
||||||
|
std::vector<TObject> args2;
|
||||||
|
args2.push_back(this);
|
||||||
|
args2.insert(args2.end(), args.begin(),args.end());
|
||||||
|
return closure->CallWithFatalError(ls,args2);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return callable->CallWithFatalError(ls,args);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
void TDictionary::DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb)
|
void TDictionary::DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb)
|
||||||
{
|
{
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
@@ -204,4 +231,5 @@ namespace Tesses::CrossLang {
|
|||||||
_gc->Watch(dict);
|
_gc->Watch(dict);
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
228
src/types/embed.cpp
Normal file
228
src/types/embed.cpp
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
|
||||||
|
EmbedStream::EmbedStream(GC* gc, TFile* file, uint32_t resource)
|
||||||
|
{
|
||||||
|
this->offset = 0;
|
||||||
|
this->resource = resource;
|
||||||
|
this->file = CreateMarkedTObject(gc,file);
|
||||||
|
}
|
||||||
|
bool EmbedStream::CanRead()
|
||||||
|
{
|
||||||
|
TFile* file;
|
||||||
|
if(GetObjectHeap(this->file->GetObject(),file))
|
||||||
|
{
|
||||||
|
if(this->resource >= file->resources.size()) return false;
|
||||||
|
if(this->offset >= file->resources[this->resource].size()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool EmbedStream::CanSeek()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool EmbedStream::EndOfStream()
|
||||||
|
{
|
||||||
|
return !CanRead();
|
||||||
|
}
|
||||||
|
size_t EmbedStream::Read(uint8_t* buff, size_t len)
|
||||||
|
{
|
||||||
|
TFile* file;
|
||||||
|
|
||||||
|
if(GetObjectHeap(this->file->GetObject(),file))
|
||||||
|
{
|
||||||
|
if(this->resource >= file->resources.size()) return 0;
|
||||||
|
auto flen = file->resources[this->resource].size();
|
||||||
|
if(this->offset >= flen) return 0;
|
||||||
|
|
||||||
|
len = std::min(len, std::min(
|
||||||
|
flen,
|
||||||
|
flen - this->offset
|
||||||
|
));
|
||||||
|
|
||||||
|
memcpy(buff,file->resources[this->resource].data() + this->offset,len);
|
||||||
|
this->offset += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int64_t EmbedStream::GetPosition()
|
||||||
|
{
|
||||||
|
return (int64_t)this->offset;
|
||||||
|
}
|
||||||
|
int64_t EmbedStream::GetLength()
|
||||||
|
{
|
||||||
|
TFile* file;
|
||||||
|
|
||||||
|
if(GetObjectHeap(this->file->GetObject(),file))
|
||||||
|
{
|
||||||
|
if(this->resource >= file->resources.size()) return 0;
|
||||||
|
return (int64_t)file->resources[this->resource].size();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void EmbedStream::Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence)
|
||||||
|
{
|
||||||
|
switch(whence)
|
||||||
|
{
|
||||||
|
case Tesses::Framework::Streams::SeekOrigin::Begin:
|
||||||
|
this->offset = (uint32_t)pos;
|
||||||
|
break;
|
||||||
|
case Tesses::Framework::Streams::SeekOrigin::Current:
|
||||||
|
{
|
||||||
|
int64_t cur = this->offset;
|
||||||
|
cur += pos;
|
||||||
|
this->offset = (uint32_t)cur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Tesses::Framework::Streams::SeekOrigin::End:
|
||||||
|
{
|
||||||
|
TFile* file;
|
||||||
|
|
||||||
|
if(GetObjectHeap(this->file->GetObject(),file))
|
||||||
|
{
|
||||||
|
if(this->resource >= file->resources.size()) return;
|
||||||
|
int64_t cur = (int64_t)file->resources[this->resource].size();
|
||||||
|
cur += pos;
|
||||||
|
this->offset = (uint32_t)cur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TObject EmbedDirectory::getEntry(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
path = path.CollapseRelativeParents();
|
||||||
|
auto curEntry = this->dir->GetObject();
|
||||||
|
for(auto item : path.path)
|
||||||
|
{
|
||||||
|
TDictionary* dict;
|
||||||
|
if(GetObjectHeap(curEntry,dict) && dict->HasValue(item))
|
||||||
|
{
|
||||||
|
curEntry = dict->GetValue(item);
|
||||||
|
continue; //don't want to return undefined now do we
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
return curEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> EmbedDirectory::OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode)
|
||||||
|
{
|
||||||
|
if(mode != "r" && mode != "rb") return nullptr;
|
||||||
|
|
||||||
|
auto ent = getEntry(path);
|
||||||
|
TCallable* call;
|
||||||
|
if(GetObjectHeap(ent,call))
|
||||||
|
{
|
||||||
|
GCList ls(this->dir->GetGC());
|
||||||
|
auto fileO = call->Call(ls,{});
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||||
|
if(GetObject(fileO,strm)) return strm;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bool EmbedDirectory::RegularFileExists(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
auto ent = getEntry(path);
|
||||||
|
TCallable* call;
|
||||||
|
return GetObjectHeap(ent,call);
|
||||||
|
}
|
||||||
|
bool EmbedDirectory::DirectoryExists(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
auto ent = getEntry(path);
|
||||||
|
TDictionary* dict;
|
||||||
|
return GetObjectHeap(ent,dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DICT_DIRENUM
|
||||||
|
{
|
||||||
|
GCList ls;
|
||||||
|
TDictionary* dict;
|
||||||
|
std::map<std::string, Tesses::CrossLang::TObject>::iterator current;
|
||||||
|
bool hasStarted = false;
|
||||||
|
public:
|
||||||
|
std::string GetCurrent()
|
||||||
|
{
|
||||||
|
return this->current->first;
|
||||||
|
}
|
||||||
|
DICT_DIRENUM(GC* gc, TDictionary* dict) : ls(gc), dict(dict)
|
||||||
|
{
|
||||||
|
ls.Add(dict);
|
||||||
|
}
|
||||||
|
bool MoveNext()
|
||||||
|
{
|
||||||
|
if(!this->hasStarted)
|
||||||
|
{
|
||||||
|
this->hasStarted=true;
|
||||||
|
this->current = this->dict->items.begin();
|
||||||
|
return !this->dict->items.empty();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->current++;
|
||||||
|
return this->current != this->dict->items.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Tesses::Framework::Filesystem::VFSPathEnumerator EmbedDirectory::EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
auto ent = getEntry(path);
|
||||||
|
TDictionary* dict;
|
||||||
|
if(GetObjectHeap(ent,dict))
|
||||||
|
{
|
||||||
|
DICT_DIRENUM* dir2 = new DICT_DIRENUM(this->dir->GetGC(), dict);
|
||||||
|
|
||||||
|
Tesses::Framework::Filesystem::VFSPathEnumerator er(
|
||||||
|
[dir2,path](Tesses::Framework::Filesystem::VFSPath& path2)->bool {
|
||||||
|
if(dir2->MoveNext())
|
||||||
|
{
|
||||||
|
path2 = path / dir2->GetCurrent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
[dir2]()->void {
|
||||||
|
delete dir2;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return er;
|
||||||
|
}
|
||||||
|
return Tesses::Framework::Filesystem::VFSPathEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbedDirectory::EmbedDirectory(GC* gc, TDictionary* dict)
|
||||||
|
{
|
||||||
|
this->dir = CreateMarkedTObject(gc, dict);
|
||||||
|
}
|
||||||
|
void EmbedDirectory::CreateDirectory(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
void EmbedDirectory::DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void EmbedDirectory::DeleteFile(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void EmbedDirectory::MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
std::string EmbedDirectory::VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
return path.ToString();
|
||||||
|
}
|
||||||
|
Tesses::Framework::Filesystem::VFSPath EmbedDirectory::SystemToVFSPath(std::string path)
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/types/random.cpp
Normal file
47
src/types/random.cpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang
|
||||||
|
{
|
||||||
|
TRandom::TRandom() : random()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
TRandom::TRandom(uint64_t seed) : random(seed)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
std::string TRandom::TypeName()
|
||||||
|
{
|
||||||
|
return "Random";
|
||||||
|
}
|
||||||
|
TObject TRandom::CallMethod(GCList& ls,std::string name, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(name == "Next")
|
||||||
|
{
|
||||||
|
int64_t first;
|
||||||
|
int64_t second;
|
||||||
|
if(GetArgument(args,0,first))
|
||||||
|
{
|
||||||
|
if(GetArgument(args,1,second))
|
||||||
|
{
|
||||||
|
return (int64_t)random.Next((int32_t)first,(int32_t)second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int64_t)random.Next((uint32_t)first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return random.Next();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(name == "NextByte")
|
||||||
|
{
|
||||||
|
return (int64_t)random.NextByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(name == "ToString") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,11 +118,12 @@ namespace Tesses::CrossLang {
|
|||||||
throw VMException("Lex error at line: " + std::to_string(res));
|
throw VMException("Lex error at line: " + std::to_string(res));
|
||||||
}
|
}
|
||||||
Parser parser(tokens);
|
Parser parser(tokens);
|
||||||
|
|
||||||
SyntaxNode n = parser.ParseRoot();
|
SyntaxNode n = parser.ParseRoot();
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
gen.GenRoot(n);
|
gen.GenRoot(n);
|
||||||
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||||
gen.Save(nullptr, ms);
|
gen.Save(ms);
|
||||||
ms->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin);
|
ms->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||||
TFile* f = TFile::Create(ls);
|
TFile* f = TFile::Create(ls);
|
||||||
f->Load(ls.GetGC(),ms);
|
f->Load(ls.GetGC(),ms);
|
||||||
@@ -230,6 +231,9 @@ namespace Tesses::CrossLang {
|
|||||||
std::vector<std::string> method=file->classes[i].name;
|
std::vector<std::string> method=file->classes[i].name;
|
||||||
method.push_back(meth.name);
|
method.push_back(meth.name);
|
||||||
auto clo = TClosure::Create(ls,this,file,meth.chunkId);
|
auto clo = TClosure::Create(ls,this,file,meth.chunkId);
|
||||||
|
clo->closure->name = JoinPeriod(method);
|
||||||
|
|
||||||
|
|
||||||
clo->documentation = meth.documentation;
|
clo->documentation = meth.documentation;
|
||||||
this->DeclareVariable(gc, method, clo);
|
this->DeclareVariable(gc, method, clo);
|
||||||
}
|
}
|
||||||
@@ -239,7 +243,6 @@ namespace Tesses::CrossLang {
|
|||||||
for(auto fn : file->functions)
|
for(auto fn : file->functions)
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
|
|
||||||
if(fn.first.size() < 2) throw VMException("No function name.");
|
if(fn.first.size() < 2) throw VMException("No function name.");
|
||||||
@@ -248,6 +251,7 @@ namespace Tesses::CrossLang {
|
|||||||
|
|
||||||
if(fn.second >= file->chunks.size()) throw VMException("ChunkId out of bounds.");
|
if(fn.second >= file->chunks.size()) throw VMException("ChunkId out of bounds.");
|
||||||
TFileChunk* chunk = file->chunks[fn.second];
|
TFileChunk* chunk = file->chunks[fn.second];
|
||||||
|
chunk->name = JoinPeriod(items);
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
TClosure* closure=TClosure::Create(ls,this,file,fn.second);
|
TClosure* closure=TClosure::Create(ls,this,file,fn.second);
|
||||||
closure->documentation = fn.first[0];
|
closure->documentation = fn.first[0];
|
||||||
|
|||||||
@@ -210,7 +210,11 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
TObjectStream::~TObjectStream()
|
TObjectStream::~TObjectStream()
|
||||||
{
|
{
|
||||||
Close();
|
TDictionary* dict;
|
||||||
|
if(GetObjectHeap(this->obj, dict))
|
||||||
|
{
|
||||||
|
dict->CallMethod(*ls,"Close",{});
|
||||||
|
}
|
||||||
delete this->ls;
|
delete this->ls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,6 +163,19 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
TObject TEnvironment::CallFunctionWithFatalError(GCList& ls, std::string key, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
auto res = this->GetVariable(key);
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
TCallable* callable;
|
||||||
|
|
||||||
|
if(GetObjectHeap(res,callable))
|
||||||
|
{
|
||||||
|
return callable->CallWithFatalError(ls,args);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
TSubEnvironment* TEnvironment::GetSubEnvironment(GCList* gc)
|
TSubEnvironment* TEnvironment::GetSubEnvironment(GCList* gc)
|
||||||
{
|
{
|
||||||
auto dict=TDictionary::Create(gc);
|
auto dict=TDictionary::Create(gc);
|
||||||
|
|||||||
@@ -169,6 +169,26 @@ namespace Tesses::CrossLang {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void TObjectVFS::Lock(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
TDictionary* dict;
|
||||||
|
if(GetObjectHeap(this->obj, dict))
|
||||||
|
{
|
||||||
|
GCList ls(this->ls->GetGC());
|
||||||
|
dict->CallMethod(ls, "Lock",{path});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void TObjectVFS::Unlock(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
|
{
|
||||||
|
TDictionary* dict;
|
||||||
|
if(GetObjectHeap(this->obj, dict))
|
||||||
|
{
|
||||||
|
GCList ls(this->ls->GetGC());
|
||||||
|
dict->CallMethod(ls, "Unlock",{path});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
bool TObjectVFS::RegularFileExists(Tesses::Framework::Filesystem::VFSPath path)
|
bool TObjectVFS::RegularFileExists(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -573,8 +593,12 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
TObjectVFS::~TObjectVFS()
|
TObjectVFS::~TObjectVFS()
|
||||||
{
|
{
|
||||||
|
TDictionary* dict;
|
||||||
Close();
|
if(GetObjectHeap(this->obj, dict))
|
||||||
|
{
|
||||||
|
GCList ls(this->ls->GetGC());
|
||||||
|
dict->CallMethod(ls,"Close",{});
|
||||||
|
}
|
||||||
delete this->ls;
|
delete this->ls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
107
src/vm/exception.cpp
Normal file
107
src/vm/exception.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
TObject TCallable::CallWithFatalError(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return Call(ls,args);
|
||||||
|
}
|
||||||
|
catch(VMByteCodeException& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
catch(VMException& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
catch(SyntaxException& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
catch(std::runtime_error& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
catch(std::exception& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
return (int64_t)1;
|
||||||
|
}
|
||||||
|
void ThrowFatalError(std::exception& ex)
|
||||||
|
{
|
||||||
|
using namespace Tesses::Framework::TextStreams;
|
||||||
|
std::exception* ex2 = &ex;
|
||||||
|
auto clexcept = dynamic_cast<VMByteCodeException*>(ex2);
|
||||||
|
auto clrtexcept = dynamic_cast<VMException*>(ex2);
|
||||||
|
auto compiler = dynamic_cast<SyntaxException*>(ex2);
|
||||||
|
Tesses::Framework::TextStreams::ConsoleWriter error(true);
|
||||||
|
|
||||||
|
if(clexcept != nullptr)
|
||||||
|
{
|
||||||
|
error.WriteLine("CrossLang has encountered a fatal exception");
|
||||||
|
error.WriteLine();
|
||||||
|
|
||||||
|
error.WriteLine(ToString(clexcept->GetGCList()->GetGC(),clexcept->exception));
|
||||||
|
error.WriteLine();
|
||||||
|
error.WriteLine("STACKTRACE:");
|
||||||
|
|
||||||
|
for(auto ittr = clexcept->stack_trace.crbegin(); ittr != clexcept->stack_trace.crend(); ittr++)
|
||||||
|
{
|
||||||
|
auto item = *ittr;
|
||||||
|
std::string text = "\t";
|
||||||
|
text += item->callable->closure->name.value_or((std::string)"<Closure>");
|
||||||
|
text += "(";
|
||||||
|
bool first=true;
|
||||||
|
for(auto& arg : item->callable->closure->args)
|
||||||
|
{
|
||||||
|
if(!first) text += ", ";
|
||||||
|
text += arg;
|
||||||
|
first=false;
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
if(item->srcline >= 1)
|
||||||
|
{
|
||||||
|
text += " at ";
|
||||||
|
text += item->srcfile;
|
||||||
|
text += ":";
|
||||||
|
text += std::to_string(item->srcline);
|
||||||
|
}
|
||||||
|
error.WriteLine(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(clrtexcept != nullptr)
|
||||||
|
{
|
||||||
|
error.WriteLine("CrossLang has encountered a fatal runtime exception");
|
||||||
|
error.WriteLine();
|
||||||
|
error.WriteLine(clrtexcept->what());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(compiler != nullptr)
|
||||||
|
{
|
||||||
|
error.WriteLine("CrossLang has encountered a compiler error");
|
||||||
|
error.WriteLine();
|
||||||
|
error.WriteLine(compiler->Message());
|
||||||
|
error.WriteLine();
|
||||||
|
auto li = compiler->LineInfo();
|
||||||
|
error.Write("in file: ");
|
||||||
|
error.Write(li.filename);
|
||||||
|
error.Write(":");
|
||||||
|
error.Write((int64_t)li.line);
|
||||||
|
error.Write(":");
|
||||||
|
error.Write((int64_t)li.column);
|
||||||
|
error.Write(":");
|
||||||
|
error.WriteLine((int64_t)li.offset);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
error.WriteLine("CrossLang has encountered a fatal C++ exception");
|
||||||
|
error.WriteLine();
|
||||||
|
error.Write("what(): ");
|
||||||
|
error.WriteLine(ex2->what());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,6 +118,168 @@ namespace Tesses::CrossLang
|
|||||||
throw VMException(errorMessage);
|
throw VMException(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TDictionary* TFile::MetadataDecode(GCList& ls, size_t midx)
|
||||||
|
{
|
||||||
|
if(midx >= this->metadata.size()) return nullptr;
|
||||||
|
if(this->metadata[midx].second.empty()) return nullptr;
|
||||||
|
if(this->metadata[midx].second[0] != 8) return nullptr;
|
||||||
|
size_t index = 0;
|
||||||
|
auto& bytes = this->metadata[midx].second;
|
||||||
|
|
||||||
|
std::function<TObject()> parseEnt;
|
||||||
|
parseEnt = [&]()->TObject {
|
||||||
|
if(index >= bytes.size()) throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
switch(bytes[index++])
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return false;
|
||||||
|
case 1:
|
||||||
|
return true;
|
||||||
|
case 2:
|
||||||
|
return nullptr;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if(index + 8 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val= BitConverter::ToUint64BE(bytes[index]);
|
||||||
|
index+=8;
|
||||||
|
int64_t val2;
|
||||||
|
memcpy(&val2,&val,sizeof(val));
|
||||||
|
return val2;
|
||||||
|
}
|
||||||
|
else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if(index + 8 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val= BitConverter::ToDoubleBE(bytes[index]);
|
||||||
|
index+=8;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
|
||||||
|
if(index + 1 <= bytes.size())
|
||||||
|
{
|
||||||
|
return (char)bytes[index++];
|
||||||
|
}
|
||||||
|
else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
if(index + 4 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||||
|
index+=4;
|
||||||
|
return this->strings.at((size_t)val);
|
||||||
|
} else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
{
|
||||||
|
if(index + 4 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||||
|
index+=4;
|
||||||
|
std::vector<TObject> items;
|
||||||
|
for(uint32_t i = 0; i < val; i++)
|
||||||
|
{
|
||||||
|
items.push_back(parseEnt());
|
||||||
|
}
|
||||||
|
|
||||||
|
return TList::Create(ls,items.begin(),items.end());
|
||||||
|
} else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
if(index + 4 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||||
|
index+=4;
|
||||||
|
std::vector<TDItem> items;
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < val; i++)
|
||||||
|
{
|
||||||
|
if(index + 4 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val2= BitConverter::ToUint32BE(bytes[index]);
|
||||||
|
index+=4;
|
||||||
|
std::string& text=this->strings.at((size_t)val2);
|
||||||
|
items.emplace_back(text,parseEnt());
|
||||||
|
} else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return TDictionary::Create(ls, items.begin(),items.end());
|
||||||
|
}else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
{
|
||||||
|
if(index + 4 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||||
|
index+=4;
|
||||||
|
auto ba = TByteArray::Create(ls);
|
||||||
|
ba->data = this->resources.at((size_t)val);
|
||||||
|
return ba;
|
||||||
|
} else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
{
|
||||||
|
if(index + 4 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||||
|
index+=4;
|
||||||
|
return std::make_shared<EmbedStream>(ls.GetGC(),this,val);
|
||||||
|
} else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
{
|
||||||
|
|
||||||
|
auto data = parseEnt();
|
||||||
|
TDictionary* dict;
|
||||||
|
if(GetObjectHeap(data,dict))
|
||||||
|
{
|
||||||
|
return std::make_shared<EmbedDirectory>(ls.GetGC(),dict);
|
||||||
|
}
|
||||||
|
else return Undefined();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
{
|
||||||
|
if(index + 4 <= bytes.size())
|
||||||
|
{
|
||||||
|
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||||
|
index+=4;
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
auto em = TExternalMethod::Create(ls,"",{},[val,this](GCList& ls, std::vector<TObject> args)->TObject {
|
||||||
|
return std::make_shared<EmbedStream>(ls.GetGC(),this,val);
|
||||||
|
});
|
||||||
|
em->watch.push_back(this);
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
|
||||||
|
return em;
|
||||||
|
} else throw std::out_of_range("Abrupt end of metadata");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Invalid metadata opcode");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TDictionary* dict_res;
|
||||||
|
TObject ent = parseEnt();
|
||||||
|
if(GetObjectHeap(ent, dict_res)) return dict_res;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void TFile::Load(GC* gc, std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
void TFile::Load(GC* gc, std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -166,10 +328,8 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
else if(strncmp(table_name,"RESO",4) == 0) //resources (using embed)
|
else if(strncmp(table_name,"RESO",4) == 0) //resources (using embed)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> data;
|
auto& data = this->resources.emplace_back(tableLen);
|
||||||
data.resize(tableLen);
|
Ensure(stream,data.data(), data.size());
|
||||||
Ensure(stream,data.data(), tableLen);
|
|
||||||
this->resources.push_back(data);
|
|
||||||
}
|
}
|
||||||
else if(strncmp(table_name,"CHKS",4) == 0 && gc != nullptr) //chunks
|
else if(strncmp(table_name,"CHKS",4) == 0 && gc != nullptr) //chunks
|
||||||
{
|
{
|
||||||
@@ -268,13 +428,22 @@ namespace Tesses::CrossLang
|
|||||||
this->classes.push_back(cls);
|
this->classes.push_back(cls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(strncmp(table_name,"META",4) == 0) //structured metadata
|
||||||
|
{
|
||||||
|
if(tableLen > 4)
|
||||||
|
{
|
||||||
|
auto name = this->GetString(stream);
|
||||||
|
auto& data = this->metadata.emplace_back(name, std::vector<uint8_t>(tableLen-4));
|
||||||
|
Ensure(stream,data.second.data(), tableLen-4);
|
||||||
|
}
|
||||||
|
else throw VMException("meta tag is not valid");
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> data;
|
auto& data = this->sections.emplace_back(std::string(table_name, 4), std::vector<uint8_t>(tableLen));
|
||||||
data.resize(tableLen);
|
Ensure(stream,data.second.data(), tableLen);
|
||||||
Ensure(stream,data.data(), tableLen);
|
|
||||||
std::string key(std::string(table_name), 4);
|
|
||||||
this->sections.push_back(std::pair<std::string,std::vector<uint8_t>>(key,data));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
274
src/vm/vm.cpp
274
src/vm/vm.cpp
@@ -3411,6 +3411,17 @@ namespace Tesses::CrossLang {
|
|||||||
cse.back()->Push(gc, nullptr);
|
cse.back()->Push(gc, nullptr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if(key == "ReadLineHttp")
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
if(textReader->ReadLineHttp(line))
|
||||||
|
{
|
||||||
|
cse.back()->Push(gc, line);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cse.back()->Push(gc, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if(key == "ReadAllLines")
|
if(key == "ReadAllLines")
|
||||||
{
|
{
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
@@ -3763,6 +3774,7 @@ namespace Tesses::CrossLang {
|
|||||||
if(svr != nullptr)
|
if(svr != nullptr)
|
||||||
{
|
{
|
||||||
auto mountable = std::dynamic_pointer_cast<Tesses::Framework::Http::MountableServer>(svr);
|
auto mountable = std::dynamic_pointer_cast<Tesses::Framework::Http::MountableServer>(svr);
|
||||||
|
auto routable = std::dynamic_pointer_cast<Tesses::Framework::Http::RouteServer>(svr);
|
||||||
|
|
||||||
if(mountable != nullptr)
|
if(mountable != nullptr)
|
||||||
{
|
{
|
||||||
@@ -3793,6 +3805,82 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(routable != nullptr)
|
||||||
|
{
|
||||||
|
if(key == "Add")
|
||||||
|
{
|
||||||
|
std::string method;
|
||||||
|
std::string pattern;
|
||||||
|
TCallable* callable;
|
||||||
|
if(GetArgument(args,0,method) && GetArgument(args,1,pattern) && GetArgumentHeap(args,2,callable))
|
||||||
|
{
|
||||||
|
routable->Add(method,pattern, callable->ToRouteServerRequestHandler(gc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(key == "Delete")
|
||||||
|
{
|
||||||
|
std::string pattern;
|
||||||
|
TCallable* callable;
|
||||||
|
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
|
||||||
|
{
|
||||||
|
routable->Delete(pattern, callable->ToRouteServerRequestHandler(gc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(key == "Get")
|
||||||
|
{
|
||||||
|
std::string pattern;
|
||||||
|
TCallable* callable;
|
||||||
|
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
|
||||||
|
{
|
||||||
|
routable->Get(pattern, callable->ToRouteServerRequestHandler(gc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(key == "Options")
|
||||||
|
{
|
||||||
|
std::string pattern;
|
||||||
|
TCallable* callable;
|
||||||
|
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
|
||||||
|
{
|
||||||
|
routable->Options(pattern, callable->ToRouteServerRequestHandler(gc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(key == "Patch")
|
||||||
|
{
|
||||||
|
std::string pattern;
|
||||||
|
TCallable* callable;
|
||||||
|
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
|
||||||
|
{
|
||||||
|
routable->Patch(pattern, callable->ToRouteServerRequestHandler(gc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(key == "Post")
|
||||||
|
{
|
||||||
|
std::string pattern;
|
||||||
|
TCallable* callable;
|
||||||
|
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
|
||||||
|
{
|
||||||
|
routable->Post(pattern, callable->ToRouteServerRequestHandler(gc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(key == "Put")
|
||||||
|
{
|
||||||
|
std::string pattern;
|
||||||
|
TCallable* callable;
|
||||||
|
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
|
||||||
|
{
|
||||||
|
routable->Put(pattern, callable->ToRouteServerRequestHandler(gc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(key == "Trace")
|
||||||
|
{
|
||||||
|
std::string pattern;
|
||||||
|
TCallable* callable;
|
||||||
|
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
|
||||||
|
{
|
||||||
|
routable->Trace(pattern, callable->ToRouteServerRequestHandler(gc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if(key == "Handle")
|
if(key == "Handle")
|
||||||
{
|
{
|
||||||
cse.back()->Push(gc,IHttpServer_Handle(svr,args));
|
cse.back()->Push(gc,IHttpServer_Handle(svr,args));
|
||||||
@@ -4107,6 +4195,26 @@ namespace Tesses::CrossLang {
|
|||||||
cse.back()->Push(gc, nullptr);
|
cse.back()->Push(gc, nullptr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if(key == "Lock")
|
||||||
|
{
|
||||||
|
Tesses::Framework::Filesystem::VFSPath filename;
|
||||||
|
if(GetArgumentAsPath(args,0,filename))
|
||||||
|
{
|
||||||
|
vfs->Lock(filename);
|
||||||
|
}
|
||||||
|
cse.back()->Push(gc, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(key == "Unlock")
|
||||||
|
{
|
||||||
|
Tesses::Framework::Filesystem::VFSPath filename;
|
||||||
|
if(GetArgumentAsPath(args,0,filename))
|
||||||
|
{
|
||||||
|
vfs->Unlock(filename);
|
||||||
|
}
|
||||||
|
cse.back()->Push(gc, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if(key == "DeleteDirectoryRecurse")
|
if(key == "DeleteDirectoryRecurse")
|
||||||
{
|
{
|
||||||
Tesses::Framework::Filesystem::VFSPath dirname;
|
Tesses::Framework::Filesystem::VFSPath dirname;
|
||||||
@@ -4220,31 +4328,33 @@ namespace Tesses::CrossLang {
|
|||||||
auto cls = dynamic_cast<TClassObject*>(obj);
|
auto cls = dynamic_cast<TClassObject*>(obj);
|
||||||
auto aArray=dynamic_cast<TAssociativeArray*>(obj);
|
auto aArray=dynamic_cast<TAssociativeArray*>(obj);
|
||||||
auto ttask = dynamic_cast<TTask*>(obj);
|
auto ttask = dynamic_cast<TTask*>(obj);
|
||||||
|
auto file = dynamic_cast<TFile*>(obj);
|
||||||
|
|
||||||
|
if(file != nullptr)
|
||||||
|
{
|
||||||
|
if(key == "MetadataDecode")
|
||||||
|
{
|
||||||
|
int64_t index;
|
||||||
|
if(GetArgument(args,0, index) && (size_t)index < file->metadata.size())
|
||||||
|
{
|
||||||
|
cse.back()->Push(gc,file->MetadataDecode(ls,(size_t)index));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(key == "MetadataName")
|
||||||
|
{
|
||||||
|
int64_t index;
|
||||||
|
if(GetArgument(args,0, index) && (size_t)index < file->metadata.size())
|
||||||
|
{
|
||||||
|
cse.back()->Push(gc,file->metadata.at((size_t)index).first);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cse.back()->Push(gc,Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if(ttask != nullptr)
|
if(ttask != nullptr)
|
||||||
{
|
{
|
||||||
if(key == "SetSucceeded")
|
|
||||||
{
|
|
||||||
if(args.size() > 0)
|
|
||||||
{
|
|
||||||
ttask->SetSucceeded(args[0]);
|
|
||||||
}
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(key == "SetFailed")
|
|
||||||
{
|
|
||||||
if(args.size() > 0)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
throw VMByteCodeException(gc,args[0]);
|
|
||||||
} catch(...) {
|
|
||||||
ttask->SetFailed(std::current_exception());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(key == "ContinueWith")
|
if(key == "ContinueWith")
|
||||||
{
|
{
|
||||||
TCallable* callable2;
|
TCallable* callable2;
|
||||||
@@ -5581,6 +5691,15 @@ namespace Tesses::CrossLang {
|
|||||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance))
|
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 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")
|
if(key == "NewLine")
|
||||||
{
|
{
|
||||||
cse.back()->Push(gc,writer->newline);
|
cse.back()->Push(gc,writer->newline);
|
||||||
@@ -5922,6 +6041,32 @@ namespace Tesses::CrossLang {
|
|||||||
cse.back()->Push(gc, list);
|
cse.back()->Push(gc, list);
|
||||||
return false;
|
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")
|
else if(key == "Sections")
|
||||||
{
|
{
|
||||||
TList* sections = TList::Create(ls);
|
TList* sections = TList::Create(ls);
|
||||||
@@ -6245,6 +6390,19 @@ namespace Tesses::CrossLang {
|
|||||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance))
|
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 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(key == "NewLine")
|
||||||
{
|
{
|
||||||
if(std::holds_alternative<std::string>(value))
|
if(std::holds_alternative<std::string>(value))
|
||||||
@@ -6971,7 +7129,35 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool InterperterThread::PushResourceStream(GC* gc)
|
||||||
|
{
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
if(!cse.empty())
|
||||||
|
{
|
||||||
|
auto stk = cse.back();
|
||||||
|
std::vector<uint8_t>& code = stk->callable->closure->code;
|
||||||
|
if(stk->ip + 4 <= code.size())
|
||||||
|
{
|
||||||
|
uint32_t n=BitConverter::ToUint32BE(code[stk->ip]);
|
||||||
|
if(n >= stk->callable->file->resources.size())
|
||||||
|
throw VMException("Can't read resource.");
|
||||||
|
stk->ip = stk->ip + 4;
|
||||||
|
|
||||||
|
gc->BarrierBegin();
|
||||||
|
GCList ls(gc);
|
||||||
|
// TByteArray* arr = TByteArray::Create(ls);
|
||||||
|
// arr->data = stk->callable->file->resources[n];
|
||||||
|
stk->Push(gc, std::make_shared<EmbedStream>(gc,stk->callable->file,n));
|
||||||
|
|
||||||
|
gc->BarrierEnd();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw VMException("Can't read chunk.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool InterperterThread::PushResource(GC* gc)
|
bool InterperterThread::PushResource(GC* gc)
|
||||||
{
|
{
|
||||||
@@ -7012,7 +7198,22 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
auto env = cse.back()->env;
|
auto env = cse.back()->env;
|
||||||
if(!env->GetRootEnvironment()->HandleException(gc,env, _res2))
|
if(!env->GetRootEnvironment()->HandleException(gc,env, _res2))
|
||||||
throw VMByteCodeException(gc,_res2);
|
throw VMByteCodeException(gc,_res2,cse.back());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool InterperterThread::PushResourceDirectory(GC* gc)
|
||||||
|
{
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
GCList ls(gc);
|
||||||
|
auto _res2 = cse.back()->Pop(ls);
|
||||||
|
TDictionary* dict;
|
||||||
|
if(GetObjectHeap(_res2, dict))
|
||||||
|
{
|
||||||
|
cse.back()->Push(gc, std::make_shared<EmbedDirectory>(gc,dict));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -7167,6 +7368,24 @@ namespace Tesses::CrossLang {
|
|||||||
auto stk = cse.back();
|
auto stk = cse.back();
|
||||||
|
|
||||||
stk->Push(gc,Undefined());
|
stk->Push(gc,Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool InterperterThread::LineInfo(GC* gc)
|
||||||
|
{
|
||||||
|
GCList ls(gc);
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
auto stk = cse.back();
|
||||||
|
auto file = stk->Pop(ls);
|
||||||
|
auto line = stk->Pop(ls);
|
||||||
|
|
||||||
|
//Set the fields in this cse
|
||||||
|
GetObject(file,stk->srcfile);
|
||||||
|
GetObject(line,stk->srcline);
|
||||||
|
|
||||||
|
//TODO: implement lines (this will make the language work until we get it rigged up)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool InterperterThread::PushFalse(GC* gc)
|
bool InterperterThread::PushFalse(GC* gc)
|
||||||
@@ -7867,6 +8086,9 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
CallStackEntry* cse = new CallStackEntry();
|
CallStackEntry* cse = new CallStackEntry();
|
||||||
cse->mustReturn=false;
|
cse->mustReturn=false;
|
||||||
|
cse->srcline = -1;
|
||||||
|
cse->srcfile = "";
|
||||||
|
cse->thread=nullptr;
|
||||||
GC* _gc = ls.GetGC();
|
GC* _gc = ls.GetGC();
|
||||||
ls.Add(cse);
|
ls.Add(cse);
|
||||||
_gc->Watch(cse);
|
_gc->Watch(cse);
|
||||||
@@ -7877,6 +8099,9 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
CallStackEntry* cse = new CallStackEntry();
|
CallStackEntry* cse = new CallStackEntry();
|
||||||
cse->mustReturn=false;
|
cse->mustReturn=false;
|
||||||
|
cse->srcline = -1;
|
||||||
|
cse->srcfile = "";
|
||||||
|
cse->thread=nullptr;
|
||||||
GC* _gc = ls->GetGC();
|
GC* _gc = ls->GetGC();
|
||||||
ls->Add(cse);
|
ls->Add(cse);
|
||||||
_gc->Watch(cse);
|
_gc->Watch(cse);
|
||||||
@@ -7886,6 +8111,7 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
CallStackEntry* cse = CallStackEntry::Create(ls);
|
CallStackEntry* cse = CallStackEntry::Create(ls);
|
||||||
|
cse->thread = this;
|
||||||
cse->callable = closure;
|
cse->callable = closure;
|
||||||
cse->env = closure->chunkId == 0 ? closure->env : closure->ownScope ? closure->env->GetSubEnvironment(ls) : closure->env;
|
cse->env = closure->chunkId == 0 ? closure->env : closure->ownScope ? closure->env->GetSubEnvironment(ls) : closure->env;
|
||||||
cse->ip = 0;
|
cse->ip = 0;
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ static opcode opcodes[256]={
|
|||||||
&InterperterThread::JumpIfContinue,
|
&InterperterThread::JumpIfContinue,
|
||||||
&InterperterThread::JumpIfDefined,
|
&InterperterThread::JumpIfDefined,
|
||||||
&InterperterThread::DeclareConstVariable,
|
&InterperterThread::DeclareConstVariable,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::LineInfo,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::PushResourceStream,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::PushResourceDirectory,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
|
|||||||
Reference in New Issue
Block a user