13 Commits
75 changed files with 2838 additions and 1690 deletions
+44 -15
View File
@@ -5,6 +5,7 @@ on:
- 'v*' - 'v*'
env: env:
TF_VERSION: 0.0.7
PACKAGE_AND_BREW: ${{ secrets.PACKAGE_AND_BREW }} PACKAGE_AND_BREW: ${{ secrets.PACKAGE_AND_BREW }}
VERSION: ${{ gitea.ref_name }} VERSION: ${{ gitea.ref_name }}
RESULT_IMAGE_NAME: tesses50/crosslang RESULT_IMAGE_NAME: tesses50/crosslang
@@ -12,23 +13,14 @@ env:
GITEA_REGISTRY_USER: tesses50 GITEA_REGISTRY_USER: tesses50
jobs: jobs:
build-arch: build-ppc:
runs-on: arch-builder name: "🔨 Build for PowerPC"
runs-on: ubuntu-latest
container:
image: git.tesses.org/tesses50/linux-ppc:latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- run: wget -O /root/repository.key https://git.tesses.org/api/packages/tesses50/arch/repository.key - run: bash build-for-ppc.sh
- run: pacman-key --add /root/repository.key
- run: pacman-key --config /opt/cross/ppc/pacman.conf --add /root/repository.key
- run: printf "[tesses50.git.tesses.org]\nSigLevel = Optional TrustAll\nServer = https://git.tesses.org/api/packages/tesses50/arch/core/\$arch\n" >> /etc/pacman.conf
- run: printf "[tesses50.git.tesses.org]\nSigLevel = Optional TrustAll\nServer = https://git.tesses.org/api/packages/tesses50/arch/core/\$arch\n" >> /opt/cross/ppc/pacman.conf
- run: pacman --noconfirm -Sy mbedtls tessesframework zip zig ninja
- run: pacman --config /opt/cross/ppc/pacman.conf --noconfirm -Sy mbedtls tessesframework
- 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
- uses: akkuman/gitea-release-action@v1 - uses: akkuman/gitea-release-action@v1
env: env:
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18 NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18
@@ -36,6 +28,43 @@ jobs:
prerelease: true prerelease: true
files: |- files: |-
artifacts/** artifacts/**
build-packages:
name: "🔨 Build for everything else"
runs-on: fw13-ubuntu-latest
strategy:
fail-fast: true
matrix:
include:
- container: "git.tesses.org/tesses50/linux-x64:latest"
nfpmName: "amd64"
debianName: "x86_64-linux-gnu"
- container: "git.tesses.org/tesses50/linux-x86:latest"
nfpmName: "386"
debianName: "i386-linux-gnu"
- container: "git.tesses.org/tesses50/linux-arm:latest"
nfpmName: "arm7"
debianName: "arm-linux-gnueabihf"
- container: "git.tesses.org/tesses50/linux-arm64:latest"
nfpmName: "arm64"
debianName: "aarch64-linux-gnu"
- container: "git.tesses.org/tesses50/linux-riscv64:latest"
nfpmName: "riscv64"
debianName: "riscv64-linux-gnu"
container:
image: ${{ matrix.container }}
steps:
- uses: actions/checkout@v4
- run: bash build-for-nfpm.sh ${{ matrix.nfpmName }} ${{ matrix.debianName }}
- uses: akkuman/gitea-release-action@v1
env:
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18
with:
prerelease: true
files: |-
artifacts/**
update-tap: update-tap:
runs-on: global-container-mingw runs-on: global-container-mingw
+9
View File
@@ -32,4 +32,13 @@ include(cmake/app.cmake)
if(CROSSLANG_INSTALL_DEVELOPMENT) if(CROSSLANG_INSTALL_DEVELOPMENT)
add_subdirectory(pkgconfig) add_subdirectory(pkgconfig)
endif()
if(NOT CROSSLANG_TF_VERSION STREQUAL "")
if(NOT CROSSLANG_NFPM_ARCH STREQUAL "")
configure_file(nfpm.yaml.in nfpm.yaml @ONLY)
endif()
configure_file(ppc-pkgbuild.in ppc-pkgbuild @ONLY)
endif() endif()
-51
View File
@@ -1,51 +0,0 @@
# Maintainer: Mike Nolan <tesses@tesses.net>
pkgname=crosslang # '-bzr', '-git', '-hg' or '-svn'
pkgver=0.0.6
pkgrel=1
pkgdesc=""
arch=('x86_64' 'powerpc')
url="https://git.tesses.org/tesses50/crosslang"
license=('GPLv3')
groups=()
depends=('mbedtls' 'tessesframework=0.0.4')
makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion'
install=
source=('crosslang::git+https://git.tesses.org/tesses50/crosslang')
noextract=()
sha256sums=('SKIP')
if [[ -z "$CMAKE_TOOLCHAIN" ]]; then
options=(!strip)
else
options=(!buildflags !strip)
fi
# Please refer to the 'USING VCS SOURCES' section of the PKGBUILD man page for
# a description of each element in the source array.
prepare() {
cd "$srcdir/${pkgname}"
}
build() {
cd "$srcdir/${pkgname}"
mkdir build
cd build
if [[ -z "$CMAKE_TOOLCHAIN" ]]; then
cmake -S .. -B . -DCMAKE_INSTALL_PREFIX=/usr -DCROSSLANG_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=Release
else
cmake -S .. -B . -DCMAKE_INSTALL_PREFIX=/usr -DCROSSLANG_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN"
fi
make -j`nproc`
}
package() {
cd "$srcdir/${pkgname}/build"
make install DESTDIR="$pkgdir/"
}
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
cd /home/build
mkdir x86_64
cd x86_64
cp ../PKGBUILD .
makepkg
curl --user tesses50:$PACKAGE_AND_BREW \
--upload-file *.pkg.tar.zst \
https://git.tesses.org/api/packages/tesses50/arch/core
cd ..
mkdir powerpc
cd powerpc
cp ../PKGBUILD .
CARCH=powerpc CMAKE_TOOLCHAIN=/opt/cross/ppc/toolchain.cmake makepkg
curl --user tesses50:$PACKAGE_AND_BREW \
--upload-file *.pkg.tar.zst \
https://git.tesses.org/api/packages/tesses50/arch/core
+41
View File
@@ -0,0 +1,41 @@
if [ $# -lt 2 ]
then
echo "Not enough args, pass nfpm arch and debian tripple as argument"
echo "This script requires our docker container: git.tesses.org/tesses50/linux-*:latest"
else
curl https://git.tesses.org/tesses50/tessesframework/releases/download/v$TF_VERSION/tessesframework-v$TF_VERSION-$1.tar.gz | tar xz -C /opt/cross/staging
mkdir -p build
cd build
cmake-cross -S .. -B . -DCROSSLANG_NFPM_ARCH=$1 -DCMAKE_INSTALL_LIBDIR=lib/$2 -DCMAKE_BUILD_TYPE=Release -DCROSSLANG_FETCHCONTENT=OFF -DCROSSLANG_TF_VERSION=$TF_VERSION
make -j`nproc`
make install DESTDIR=debian
cd debian
nfpm package -f ../nfpm.yaml -p deb
curl --user tesses50:$PACKAGE_AND_BREW \
--upload-file *.deb \
https://git.tesses.org/api/packages/tesses50/debian/pool/universal/main/upload
#debian/pool/bionic
cd ..
if [ "$1" = "386" ] || [ "$1" = "arm7" ]
then
cmake-cross -S .. -B . -DCROSSLANG_NFPM_ARCH=$1 -DCMAKE_INSTALL_LIBDIR=lib32
else
cmake-cross -S .. -B . -DCROSSLANG_NFPM_ARCH=$1 -DCMAKE_INSTALL_LIBDIR=lib64
fi
make install DESTDIR=fedora
cd fedora
nfpm package -f ../nfpm.yaml -p rpm
curl --user tesses50:$PACKAGE_AND_BREW \
--upload-file *.rpm \
https://git.tesses.org/api/packages/tesses50/rpm/upload
cd ..
cmake-cross -S .. -B . -DCROSSLANG_NFPM_ARCH=$1 -DCMAKE_INSTALL_LIBDIR=lib
make install DESTDIR=arch
cd arch
nfpm package -f ../nfpm.yaml -p archlinux
curl --user tesses50:$PACKAGE_AND_BREW \
--upload-file *.pkg.tar.zst \
https://git.tesses.org/api/packages/tesses50/arch/core
mkdir -p ../../artifacts
tar czf ../../artifacts/crosslang-$VERSION\-$1\.tar.gz --owner=1000 --group=1000 -C usr/ . -C /opt/cross/staging/ .
fi
+21
View File
@@ -0,0 +1,21 @@
curl https://git.tesses.org/tesses50/tessesframework/releases/download/v$TF_VERSION/tessesframework-v$TF_VERSION-powerpc.tar.gz | tar xz -C /opt/cross/staging
mkdir -p build
pushd build
cmake-cross -S .. -B . -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_BUILD_TYPE=Release -DCROSSLANG_FETCHCONTENT=OFF -DCROSSLANG_TF_VERSION=$TF_VERSION
make -j`nproc`
mkdir -p /home/build/cl
chown build:build -R /home/build
make install DESTDIR=/home/build/cl/src
cp ppc-pkgbuild /home/build/cl/PKGBUILD
chmod 644 /home/build/cl/PKGBUILD
chown build:build -R /home/build/cl
pushd /home/build/cl
su build -c 'CARCH=powerpc makepkg -d'
curl --user tesses50:$PACKAGE_AND_BREW \
--upload-file *.pkg.tar.zst \
https://git.tesses.org/api/packages/tesses50/arch/core
popd
popd
mkdir -p artifacts
tar czf artifacts/crosslang-$VERSION\-powerpc.tar.gz --owner=1000 --group=1000 -C /home/build/cl/src/usr . -C /opt/cross/staging/ .
+12
View File
@@ -1,5 +1,17 @@
# Changelog # Changelog
## 0.0.10
Replace time-based GC with allocation-count trigger, migrate all Create factories to GCList::Create(), fix VFSPath root path, reorder TObject variant
## 0.0.9
Fixed Process.ShellFileOrUrl was broken New.ShellFileOrUrl
## 0.0.8
Use new build setup
## 0.0.7
Fix a security vulerability in crossdump that is supposed to use uint32_t but accidently used uint8_t, set to tessesframework=0.0.5
## 0.0.6 ## 0.0.6
Fix bug with classes, use slim exclusively, add package private data and change rehaul cmake configs Fix bug with classes, use slim exclusively, add package private data and change rehaul cmake configs
+2 -3
View File
@@ -32,8 +32,7 @@ set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/winicon.ico") set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/winicon.ico")
set(CPACK_NSIS_MODIFY_PATH ON) set(CPACK_NSIS_MODIFY_PATH ON)
set(CPACK_PACKAGE_VENDOR "Tesses") set(CPACK_PACKAGE_VENDOR "Tesses")
set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$DESKTOP\\\\CrossLang Interperter.lnk' '$INSTDIR\\\\bin\\\\crossint.exe'") set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$DESKTOP\\\\CrossLang Menu.lnk' '$INSTDIR\\\\bin\\\\crosslang.exe' 'interactive'")
set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\CrossLang Interperter.lnk' '$INSTDIR\\\\bin\\\\crossint.exe'") set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\CrossLang Menu.lnk' '$INSTDIR\\\\bin\\\\crosslang.exe' 'interactive'")
include(CPack) include(CPack)
+2 -2
View File
@@ -5,10 +5,10 @@ set(CROSSLANG_STATIC ${TESSESFRAMEWORK_STATIC} CACHE INTERNAL "For CrossLang" FO
FetchContent_Declare( FetchContent_Declare(
TessesFramework TessesFramework
GIT_REPOSITORY https://git.tesses.org/tesses50/tessesframework.git GIT_REPOSITORY https://git.tesses.org/tesses50/tessesframework.git
GIT_TAG 25d67053ccebf209f50e6928fad8827164eb4c28 GIT_TAG 5b54af1728907559999e446e56497055297a3696
) )
set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF) set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF)
FetchContent_MakeAvailable(TessesFramework) FetchContent_MakeAvailable(TessesFramework)
else() else()
find_package(TessesFramework REQUIRED) find_package(TessesFramework REQUIRED)
endif() endif()
+2
View File
@@ -5,3 +5,5 @@ option(CROSSLANG_ENABLE_FFI "Enable libffi" OFF)
option(CROSSLANG_ENABLE_RPATH "Enable RPATH" ON) option(CROSSLANG_ENABLE_RPATH "Enable RPATH" ON)
option(CROSSLANG_CUSTOM_CONSOLE "Enable custom Console" OFF) option(CROSSLANG_CUSTOM_CONSOLE "Enable custom Console" OFF)
option(CROSSLANG_STATIC "Build with static libraries instead of shared" OFF) option(CROSSLANG_STATIC "Build with static libraries instead of shared" OFF)
option(CROSSLANG_NFPM_ARCH "Architecture for NFPM" "")
option(CROSSLANG_TF_VERSION "TessesFramework Version for nfpm and pkgbuild" "")
+1
View File
@@ -47,6 +47,7 @@ src/types/class.cpp
src/types/classenvironment.cpp src/types/classenvironment.cpp
src/types/random.cpp src/types/random.cpp
src/types/queryable.cpp src/types/queryable.cpp
src/types/exception.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
+1 -1
View File
@@ -1,3 +1,3 @@
set(CROSSLANG_MAJOR_VERSION 0) set(CROSSLANG_MAJOR_VERSION 0)
set(CROSSLANG_MINOR_VERSION 0) set(CROSSLANG_MINOR_VERSION 0)
set(CROSSLANG_PATCH_VERSION 6) set(CROSSLANG_PATCH_VERSION 10)
+550 -140
View File
File diff suppressed because it is too large Load Diff
+183
View File
@@ -0,0 +1,183 @@
# Name. (required)
name: crosslang
# Architecture. (required)
# This will expand any env var you set in the field, e.g. arch: ${GOARCH}
# The architecture is specified using Go nomenclature (GOARCH) and translated
# to the platform specific equivalent. In order to manually set the architecture
# to a platform specific value, set `{format}.arch`.
# Examples: `all`, `amd64`, `386`, `arm5`, `arm6`, `arm7`, `arm64`, `mips`,
# `mipsle`, `mips64le`, `ppc64le`, `s390`, `riscv64`
arch: @CROSSLANG_NFPM_ARCH@
# Platform.
# This will expand any env var you set in the field, e.g. platform: ${GOOS}
# This is only used by the rpm and deb packagers.
# Examples: `linux` (default), `darwin`
platform: linux
# Version. (required)
# This will expand any env var you set in the field, e.g. version: ${SEMVER}
# Some package managers, like deb, require the version to start with a digit.
# Hence, you should not prefix the version with 'v'.
version: @CROSSLANG_MAJOR_VERSION@.@CROSSLANG_MINOR_VERSION@.@CROSSLANG_PATCH_VERSION@
# Version Schema allows you to specify how to parse the version string.
# Default is `semver`
# `semver` attempt to parse the version string as a valid semver version.
# The parser is lenient; it will strip a `v` prefix and will accept
# versions with fewer than 3 components, like `v1.2`.
# If parsing succeeds, then the version will be molded into a format
# compatible with the specific packager used.
# If parsing fails, then the version is used as-is.
# `none` skip trying to parse the version string and just use what is passed in
version_schema: semver
# Version Epoch.
# A package with a higher version epoch will always be considered newer.
# See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#epochs-should-be-used-sparingly
#epoch: 1
# Version Prerelease.
# Default is extracted from `version` if it is semver compatible.
# This is appended to the `version`, e.g. `1.2.3+beta1`. If the `version` is
# semver compatible, then this replaces the prerelease component of the semver.
#prerelease: alpha
# Version Metadata (previously deb.metadata).
# Default is extracted from `version` if it is semver compatible.
# Setting metadata might interfere with version comparisons depending on the
# packager. If the `version` is semver compatible, then this replaces the
# version metadata component of the semver.
# version_metadata: git
# Version Release, aka revision.
# This will expand any env var you set in the field, e.g. release: ${VERSION_RELEASE}
# This is appended to the `version` after `prerelease`. This should be
# incremented if you release an updated package of the same upstream version,
# and it should reset to 1 when bumping the version.
release: 1
# Section.
# This is only used by the deb packager.
# See: https://www.debian.org/doc/debian-policy/ch-archive.html#sections
section: default
# Priority.
# Defaults to `optional` on deb
# Defaults to empty on rpm and apk
# See: https://www.debian.org/doc/debian-policy/ch-archive.html#priorities
priority: extra
# Maintainer. (required)
# This will expand any env var you set in the field, e.g. maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}>
# Defaults to empty on rpm and apk
# Leaving the 'maintainer' field unset will not be allowed in a future version
maintainer: Mike Nolan <tesses@tesses.net>
# Description.
# This will expand any env var you set in the field, e.g. description: ${DESCRIPTION}
# Defaults to `no description given`.
# Most packagers call for a one-line synopsis of the package. Some (like deb)
# also call for a multi-line description starting on the second line.
description: TessesFramework a library to make C++ easier for me, used in CrossLang
# Vendor.
# This will expand any env var you set in the field, e.g. vendor: ${VENDOR}
# This is only used by the rpm packager.
vendor: Tesses
# Package's homepage.
# This will expand any env var you set in the field, e.g. homepage: ${CI_PROJECT_URL}
homepage: https://git.tesses.org/tesses50/crosslang
# License.
license: GPLv3
# Date to be used as mtime on internal files.
#
# Default is the value of $SOURCE_DATE_EPOCH (which should be an Unix time),
# or the current time.
# Read more about SOURCE_DATE_EPOCH at https://reproducible-builds.org/docs/source-date-epoch/
#mtime: "2009-11-10T23:00:00Z"
# Changelog YAML file, see: https://github.com/goreleaser/chglog
# changelog: "changelog.yaml"
# Disables globbing for files, config_files, etc.
# disable_globbing: false
# Packages it replaces. (overridable)
# This will expand any env var you set in the field, e.g. ${REPLACE_BLA}
# the env var approach can be used to account for differences in platforms
#replaces:
# - foobar
# - ${REPLACE_BLA}
# Packages it provides. (overridable)
# This will expand any env var you set in the field, e.g. ${PROVIDES_BLA}
# the env var approach can be used to account for differences in platforms
#provides:
# - bar
# - ${PROVIDES_BLA}
# Dependencies. (overridable)
# This will expand any env var you set in the field, e.g. ${DEPENDS_NGINX}
# the env var approach can be used to account for differences in platforms
# e.g. rhel needs nginx >= 1:1.18 and deb needs nginx (>= 1.18.0)
#depends:
# - git
# - ${DEPENDS_NGINX}
# Recommended packages. (overridable)
# This will expand any env var you set in the field, e.g. ${RECOMMENDS_BLA}
# the env var approach can be used to account for differences in platforms
#recommends:
# - golang
# - ${RECOMMENDS_BLA}
# Suggested packages. (overridable)
# This will expand any env var you set in the field, e.g. ${SUGGESTS_BLA}
# the env var approach can be used to account for differences in platforms
#suggests:
# - bzr
# Packages it conflicts with. (overridable)
# This will expand any env var you set in the field, e.g. ${CONFLICTS_BLA}
# the env var approach can be used to account for differences in platforms
#conflicts:
# - mercurial
# - ${CONFLICTS_BLA}
# Contents to add to the package
# This can be binaries or any other files.
contents:
- src: usr/
dst: /usr/
type: tree
# Umask to be used on files without explicit mode set.
#
# By default, nFPM will inherit the mode of the original file that's being
# added.
# This may lead to issues if these files are checkout out in Git, for example,
# as it won't keep all the permissions on fresh checkouts, or if the local
# system has a problematic umask setting.
#
# This setting allows to set the umask for all files that are added to the
# package without a specific file_info.mode set.
#
# Default: 0o002 (will remove world-writable permissions)
umask: 0o002
overrides:
deb:
depends:
- "tessesframework (= @CROSSLANG_TF_VERSION@-1)"
rpm:
depends:
- "tessesframework = @CROSSLANG_TF_VERSION@-1"
archlinux:
depends:
- "tessesframework=@CROSSLANG_TF_VERSION@-1"
+21
View File
@@ -0,0 +1,21 @@
# Maintainer: Mike Nolan <tesses@tesses.net>
pkgname=crosslang # '-bzr', '-git', '-hg' or '-svn'
pkgver=@CROSSLANG_MAJOR_VERSION@.@CROSSLANG_MINOR_VERSION@.@CROSSLANG_PATCH_VERSION@
pkgrel=1
pkgdesc=""
arch=('powerpc')
url="https://git.tesses.org/tesses50/crosslang"
license=('GPLv3')
groups=()
depends=('tessesframework=@CROSSLANG_TF_VERSION@-1')
makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion'
install=
source=()
noextract=()
sha256sums=()
options=(!buildflags !strip)
package() {
cp -r "${srcdir}/"* "${pkgdir}/"
}
+1 -1
View File
@@ -44,7 +44,7 @@ void CrossArchiveCreate(
strs.push_back("Console"); strs.push_back("Console");
strs.push_back("WriteLine"); strs.push_back("WriteLine");
strs.push_back("You are trying to run a crvm archive, stop it you won't " strs.push_back("You are trying to run a crvm archive, stop it you won't "
"get anywhere!\nUse crossarchiveextract instead."); "get anywhere!\nUse crosslang archiveextract instead.");
std::vector<std::string> resources; std::vector<std::string> resources;
+1 -1
View File
@@ -75,7 +75,7 @@ SyntaxNode Deserialize(std::string astData) {
} }
#if defined(CROSSLANG_ENABLE_JSON) #if defined(CROSSLANG_ENABLE_JSON)
static json_t *Serialize2(SyntaxNode node) { static json_t *Serialize2(SyntaxNode node) {
if (std::holds_alternative<std::nullptr_t>(node)) if (IsNull(node))
return json_null(); return json_null();
if (std::holds_alternative<int64_t>(node)) { if (std::holds_alternative<int64_t>(node)) {
return json_integer(std::get<int64_t>(node)); return json_integer(std::get<int64_t>(node));
+118 -34
View File
@@ -175,7 +175,7 @@ void CodeGen::WriteMetadataObject(std::vector<uint8_t> &bytes, SyntaxNode n) {
std::vector<SyntaxNode> itms; std::vector<SyntaxNode> itms;
if (asn.nodes.size() > 0) if (asn.nodes.size() > 0)
GetFunctionArgs(itms, asn.nodes[0]); FlattenCommas(itms, asn.nodes[0]);
bytes.push_back(7); bytes.push_back(7);
size_t offset = bytes.size(); size_t offset = bytes.size();
bytes.resize(offset + 4); bytes.resize(offset + 4);
@@ -189,7 +189,7 @@ void CodeGen::WriteMetadataObject(std::vector<uint8_t> &bytes, SyntaxNode n) {
std::vector<SyntaxNode> itms; std::vector<SyntaxNode> itms;
if (asn.nodes.size() > 0) if (asn.nodes.size() > 0)
GetFunctionArgs(itms, asn.nodes[0]); FlattenCommas(itms, asn.nodes[0]);
bytes.push_back(8); bytes.push_back(8);
size_t offset = bytes.size(); size_t offset = bytes.size();
bytes.resize(offset + 4); bytes.resize(offset + 4);
@@ -827,6 +827,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
size_t fnindex = this->chunks.size(); size_t fnindex = this->chunks.size();
ent.closure = (uint32_t)fnindex; ent.closure = (uint32_t)fnindex;
this->chunks.resize(fnindex + 1); this->chunks.resize(fnindex + 1);
std::vector<ByteCodeInstruction *> fnInstructions;
auto &nameAndArgs = auto &nameAndArgs =
std::get<AdvancedSyntaxNode>(adv2.nodes[2]); std::get<AdvancedSyntaxNode>(adv2.nodes[2]);
if (nameAndArgs.nodeName == FunctionCallExpression && if (nameAndArgs.nodeName == FunctionCallExpression &&
@@ -844,14 +846,13 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
std::get<std::string>(getvar.nodes[0])); std::get<std::string>(getvar.nodes[0]));
if (nameAndArgs.nodes.size() > 1) { if (nameAndArgs.nodes.size() > 1) {
GetFunctionArgs(ent.arguments, GetFunctionArgs(ent.arguments,
fnInstructions,
nameAndArgs.nodes[1]); nameAndArgs.nodes[1]);
} }
} else } else
continue; continue;
} }
std::vector<ByteCodeInstruction *> fnInstructions;
GenNode(fnInstructions, adv2.nodes[3], 0, -1, -1, -1, GenNode(fnInstructions, adv2.nodes[3], 0, -1, -1, -1,
-1); -1);
@@ -881,8 +882,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
ent.name = GetString( ent.name = GetString(
std::get<std::string>(getvar.nodes[0])); std::get<std::string>(getvar.nodes[0]));
if (nameAndArgs.nodes.size() > 1) { if (nameAndArgs.nodes.size() > 1) {
GetFunctionArgs(ent.arguments, FlattenCommas(ent.arguments,
nameAndArgs.nodes[1]); nameAndArgs.nodes[1]);
} }
} else } else
continue; continue;
@@ -1041,13 +1042,13 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
} }
if (item.first.second.nodeName == DefaultStatement) { if (item.first.second.nodeName == DefaultStatement) {
if (!defaultJmp.empty()) if (!defaultJmp.empty())
std::cout << "ERROR: multiple default in " Tesses::Framework::Console::WriteLine(
"switch statement will cause " "ERROR: multiple default in "
"undefined behaviour, this is not " "switch statement will cause "
"an exception due to not allowing " "undefined behaviour, this is not "
"exceptions in codegen stage (the " "an exception due to not allowing "
"compilation shouldn't fail)" "exceptions in codegen stage (the "
<< std::endl; "compilation shouldn't fail)");
defaultJmp = item.first.first; defaultJmp = item.first.first;
} }
} }
@@ -1223,7 +1224,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
std::vector<SyntaxNode> itms; std::vector<SyntaxNode> itms;
if (adv.nodes.size() > 0) if (adv.nodes.size() > 0)
GetFunctionArgs(itms, adv.nodes[0]); FlattenCommas(itms, adv.nodes[0]);
for (auto item : itms) { for (auto item : itms) {
GenNode(instructions, item, scope, contscope, brkscope, contI, GenNode(instructions, item, scope, contscope, brkscope, contI,
brkI); brkI);
@@ -1233,7 +1234,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
std::vector<SyntaxNode> itms; std::vector<SyntaxNode> itms;
if (adv.nodes.size() > 0) if (adv.nodes.size() > 0)
GetFunctionArgs(itms, adv.nodes[0]); FlattenCommas(itms, adv.nodes[0]);
for (auto item : itms) { for (auto item : itms) {
if (std::holds_alternative<AdvancedSyntaxNode>(item)) { if (std::holds_alternative<AdvancedSyntaxNode>(item)) {
auto tkn = std::get<AdvancedSyntaxNode>(item); auto tkn = std::get<AdvancedSyntaxNode>(item);
@@ -1273,7 +1274,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
contI, brkI); contI, brkI);
if (adv.nodes.size() == 2) { if (adv.nodes.size() == 2) {
std::vector<SyntaxNode> nodes; std::vector<SyntaxNode> nodes;
GetFunctionArgs(nodes, adv.nodes[1]); FlattenCommas(nodes, adv.nodes[1]);
for (auto item : nodes) for (auto item : nodes)
GenNode(instructions, item, scope, contscope, brkscope, GenNode(instructions, item, scope, contscope, brkscope,
contI, brkI); contI, brkI);
@@ -1288,7 +1289,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
contI, brkI); contI, brkI);
if (adv.nodes.size() == 2) { if (adv.nodes.size() == 2) {
std::vector<SyntaxNode> nodes; std::vector<SyntaxNode> nodes;
GetFunctionArgs(nodes, adv.nodes[1]); FlattenCommas(nodes, adv.nodes[1]);
for (auto item : nodes) for (auto item : nodes)
GenNode(instructions, item, scope, contscope, brkscope, GenNode(instructions, item, scope, contscope, brkscope,
contI, brkI); contI, brkI);
@@ -1555,7 +1556,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
} else if (adv.nodeName == ContinueStatement) { } else if (adv.nodeName == ContinueStatement) {
if (contscope == -1) { if (contscope == -1) {
std::cout << "WARN: continue does nothing here\n"; Tesses::Framework::Console::WriteLine(
"WARN: continue does nothing here");
} else if (contscope == -2) { } else if (contscope == -2) {
instructions.push_back(new SimpleInstruction(PUSHCONTINUE)); instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
instructions.push_back(new SimpleInstruction(RET)); instructions.push_back(new SimpleInstruction(RET));
@@ -1572,7 +1574,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
} }
} else if (adv.nodeName == BreakStatement) { } else if (adv.nodeName == BreakStatement) {
if (brkscope == -1) { if (brkscope == -1) {
std::cout << "WARN: break does nothing here\n"; Tesses::Framework::Console::WriteLine(
"WARN: break does nothing here");
} else if (brkscope == -2) { } else if (brkscope == -2) {
instructions.push_back(new SimpleInstruction(PUSHBREAK)); instructions.push_back(new SimpleInstruction(PUSHBREAK));
instructions.push_back(new SimpleInstruction(RET)); instructions.push_back(new SimpleInstruction(RET));
@@ -1978,7 +1981,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
//(a,b) => {} //(a,b) => {}
// it has two args // it has two args
std::vector<uint32_t> args; std::vector<uint32_t> args;
GetFunctionArgs(args, adv.nodes[0]); FlattenCommas(args, adv.nodes[0]);
std::vector<ByteCodeInstruction *> fnInstructions; std::vector<ByteCodeInstruction *> fnInstructions;
size_t fnindex = this->chunks.size(); size_t fnindex = this->chunks.size();
@@ -2008,12 +2011,11 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
// Name => {} // Name => {}
//(a,b) => {} //(a,b) => {}
// it has two args // it has two args
std::vector<uint32_t> args;
GetFunctionArgs(args, adv.nodes[0]);
std::vector<ByteCodeInstruction *> fnInstructions; std::vector<ByteCodeInstruction *> fnInstructions;
size_t fnindex = this->chunks.size(); size_t fnindex = this->chunks.size();
this->chunks.resize(fnindex + 1); this->chunks.resize(fnindex + 1);
std::vector<uint32_t> args;
GetFunctionArgs(args, fnInstructions, adv.nodes[0]);
auto body = adv.nodes[1]; auto body = adv.nodes[1];
@@ -2060,18 +2062,20 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
} }
} }
} }
void CodeGen::GetFunctionArgs(std::vector<SyntaxNode> &args, SyntaxNode n) { void CodeGen::FlattenCommas(std::vector<SyntaxNode> &args, SyntaxNode n) {
AdvancedSyntaxNode sn; AdvancedSyntaxNode sn;
if (std::holds_alternative<AdvancedSyntaxNode>(n) && if (std::holds_alternative<AdvancedSyntaxNode>(n) &&
(sn = std::get<AdvancedSyntaxNode>(n)).nodeName == CommaExpression && (sn = std::get<AdvancedSyntaxNode>(n)).nodeName == CommaExpression &&
sn.nodes.size() == 2) { sn.nodes.size() == 2) {
GetFunctionArgs(args, sn.nodes[0]); FlattenCommas(args, sn.nodes[0]);
GetFunctionArgs(args, sn.nodes[1]); FlattenCommas(args, sn.nodes[1]);
} else { } else {
args.push_back(n); args.push_back(n);
} }
} }
void CodeGen::GetFunctionArgs(std::vector<uint32_t> &name, SyntaxNode n) { void CodeGen::GetFunctionArgs(std::vector<uint32_t> &name,
std::vector<ByteCodeInstruction *> &instrs,
SyntaxNode n) {
if (std::holds_alternative<std::nullptr_t>(n)) if (std::holds_alternative<std::nullptr_t>(n))
return; return;
@@ -2079,10 +2083,90 @@ void CodeGen::GetFunctionArgs(std::vector<uint32_t> &name, SyntaxNode n) {
auto res = std::get<AdvancedSyntaxNode>(n); auto res = std::get<AdvancedSyntaxNode>(n);
if (res.nodeName == ParenthesesExpression) { if (res.nodeName == ParenthesesExpression) {
for (auto n : res.nodes) for (auto n : res.nodes)
GetFunctionArgs(name, n); GetFunctionArgs(name, instrs, n);
} else if (res.nodeName == AssignExpression && res.nodes.size() == 2) {
// ennsure the left argument is a getVariableExpression
if (std::holds_alternative<AdvancedSyntaxNode>(res.nodes[0])) {
auto left = std::get<AdvancedSyntaxNode>(res.nodes[0]);
if (left.nodeName == GetVariableExpression &&
!left.nodes.empty() &&
std::holds_alternative<std::string>(left.nodes[0])) {
std::string key = std::get<std::string>(left.nodes[0]);
if (key.size() >= 2 && key[0] == '$' && key[1] == '$') {
Tesses::Framework::Console::WriteLine(
"WARN: you can't assign variadic functions to a "
"default value, this will be an "
"error on future release.");
return;
}
if (key.size() > 0 && key[0] == '$') {
key.erase(key.cbegin());
}
name.push_back(GetString('$' + key));
uint32_t ifId = NewId();
std::string compGenSetVar = "__compGenSetVar";
compGenSetVar.append(std::to_string(ifId));
std::string compGenSetVarEnd = "__compGenSetVarEnd";
compGenSetVarEnd.append(std::to_string(ifId));
GenNode(instrs,
AdvancedSyntaxNode::Create(GetVariableExpression,
true, {key}),
0, -1, -1, -1, -1);
instrs.push_back(new JumpStyleInstruction(
Tesses::CrossLang::Instruction::JMPUNDEFINED,
compGenSetVar));
instrs.push_back(new SimpleInstruction(POP));
instrs.push_back(new JumpStyleInstruction(
Tesses::CrossLang::Instruction::JMP, compGenSetVarEnd));
instrs.push_back(new LabelInstruction(compGenSetVar));
GenNode(instrs,
AdvancedSyntaxNode::Create(
AssignExpression, true,
{AdvancedSyntaxNode::Create(DeclareExpression,
true, {key}),
res.nodes[1]}),
0, -1, -1, -1, -1);
instrs.push_back(new SimpleInstruction(POP));
instrs.push_back(new LabelInstruction(compGenSetVarEnd));
} else {
Tesses::Framework::Console::WriteLine(
"WARN: assignment does not assign arg, this will be an "
"error on future release.");
}
} else {
Tesses::Framework::Console::WriteLine(
"WARN: assignment does not assign arg, this will be an "
"error on future release.");
}
} else if (res.nodeName == CommaExpression && res.nodes.size() == 2) { } else if (res.nodeName == CommaExpression && res.nodes.size() == 2) {
GetFunctionArgs(name, res.nodes[0]); GetFunctionArgs(name, instrs, res.nodes[0]);
GetFunctionArgs(name, res.nodes[1]); GetFunctionArgs(name, instrs, res.nodes[1]);
} else if (res.nodeName == GetVariableExpression &&
res.nodes.size() == 1) {
if (std::holds_alternative<std::string>(res.nodes[0])) {
name.push_back(GetString(std::get<std::string>(res.nodes[0])));
}
}
}
}
void CodeGen::FlattenCommas(std::vector<uint32_t> &name, SyntaxNode n) {
if (std::holds_alternative<std::nullptr_t>(n))
return;
if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
auto res = std::get<AdvancedSyntaxNode>(n);
if (res.nodeName == ParenthesesExpression) {
for (auto n : res.nodes)
FlattenCommas(name, n);
} else if (res.nodeName == CommaExpression && res.nodes.size() == 2) {
FlattenCommas(name, res.nodes[0]);
FlattenCommas(name, res.nodes[1]);
} else if (res.nodeName == GetVariableExpression && } else if (res.nodeName == GetVariableExpression &&
res.nodes.size() == 1) { res.nodes.size() == 1) {
if (std::holds_alternative<std::string>(res.nodes[0])) { if (std::holds_alternative<std::string>(res.nodes[0])) {
@@ -2175,14 +2259,14 @@ void CodeGen::GenRoot(SyntaxNode n) {
functionName.insert( functionName.insert(
functionName.begin(), functionName.begin(),
{GetString(documentation)}); {GetString(documentation)});
if (fcalli.nodes.size() == 2)
GetFunctionArgs(args,
fcalli.nodes[1]);
std::vector<ByteCodeInstruction *> std::vector<ByteCodeInstruction *>
fnInstructions; fnInstructions;
size_t fnindex = this->chunks.size(); size_t fnindex = this->chunks.size();
this->chunks.resize(fnindex + 1); this->chunks.resize(fnindex + 1);
if (fcalli.nodes.size() == 2)
GetFunctionArgs(args,
fnInstructions,
fcalli.nodes[1]);
GenNode(fnInstructions, res2.nodes[1], GenNode(fnInstructions, res2.nodes[1],
0, -1, -1, -1, -1); 0, -1, -1, -1, -1);
+1 -1
View File
@@ -482,6 +482,7 @@ int Lex(std::string filename, std::istream &strm,
} }
break; break;
case '<': case '<':
case '>':
case '?': case '?':
if (peek == read) { if (peek == read) {
Flush(); Flush();
@@ -532,7 +533,6 @@ int Lex(std::string filename, std::istream &strm,
case '^': case '^':
case '~': case '~':
case '!': case '!':
case '>':
case '*': case '*':
case '%': case '%':
//* //*
+17 -156
View File
@@ -5,7 +5,7 @@ namespace Tesses::CrossLang {
SyntaxNode TObject2SyntaxNode(TObject o) { SyntaxNode TObject2SyntaxNode(TObject o) {
if (std::holds_alternative<Undefined>(o)) if (std::holds_alternative<Undefined>(o))
return Undefined(); return Undefined();
if (std::holds_alternative<std::nullptr_t>(o)) if (IsNull(o))
return nullptr; return nullptr;
if (std::holds_alternative<std::string>(o)) if (std::holds_alternative<std::string>(o))
return std::get<std::string>(o); return std::get<std::string>(o);
@@ -115,58 +115,16 @@ bool Parser::IsIdentifier(std::string txt, bool pop) {
} }
return false; return false;
} }
bool Parser::IsAnySymbol(std::initializer_list<std::string> idents, bool pop) { bool Parser::IsAnySymbol(std::initializer_list<std::string> idents, bool pop) {
if (i < tokens.size()) { if (i < tokens.size()) {
if (tokens[i].type != LexTokenType::Symbol) if (tokens[i].type != LexTokenType::Symbol)
return false; return false;
for (auto item : idents) { for (auto item : idents) {
if (item == ">") { if (item == tokens[i].text) {
if (i + 1 < tokens.size()) { tkn = tokens[i];
if ((tokens[i + 1].text == ">" || if (pop)
tokens[i + 1].text == ">=") && i++;
tokens[i + 1].type == LexTokenType::Symbol) return true;
continue;
}
if (item == tokens[i].text) {
tkn = tokens[i];
if (pop)
i++;
return true;
}
} else if (item == ">>=") {
if (i + 1 < tokens.size()) {
if (tokens[i].text == ">" && tokens[i + 1].text == ">=" &&
tokens[i].type == LexTokenType::Symbol &&
tokens[i + 1].type == LexTokenType::Symbol) {
tkn = tokens[i];
tkn.text = ">>=";
if (pop)
i += 2;
return true;
}
}
} else if (item == ">>") {
if (i + 1 < tokens.size()) {
if (tokens[i].text == ">" && tokens[i + 1].text == ">" &&
tokens[i].type == LexTokenType::Symbol &&
tokens[i + 1].type == LexTokenType::Symbol) {
tkn = tokens[i];
tkn.text = ">>";
if (pop)
i += 2;
return true;
}
}
} else {
if (item == tokens[i].text) {
tkn = tokens[i];
if (pop)
i++;
return true;
}
} }
} }
} }
@@ -176,45 +134,7 @@ bool Parser::IsSymbol(std::string txt, bool pop) {
if (i < tokens.size()) { if (i < tokens.size()) {
if (tokens[i].type != LexTokenType::Symbol) if (tokens[i].type != LexTokenType::Symbol)
return false; return false;
if (txt == ">") { if (tokens[i].text == txt) {
if (i + 1 < tokens.size()) {
if ((tokens[i + 1].text == ">" || tokens[i + 1].text == ">=") &&
tokens[i + 1].type == LexTokenType::Symbol)
return false;
}
if (txt == tokens[i].text) {
tkn = tokens[i];
if (pop)
i++;
return true;
}
} else if (txt == ">>=") {
if (i + 1 < tokens.size()) {
if (tokens[i].text == ">" && tokens[i + 1].text == ">=" &&
tokens[i].type == LexTokenType::Symbol &&
tokens[i + 1].type == LexTokenType::Symbol) {
tkn = tokens[i];
tkn.text = ">>=";
if (pop)
i += 2;
return true;
}
}
} else if (txt == ">>") {
if (i + 1 < tokens.size()) {
if (tokens[i].text == ">" && tokens[i + 1].text == ">" &&
tokens[i].type == LexTokenType::Symbol &&
tokens[i + 1].type == LexTokenType::Symbol) {
tkn = tokens[i];
tkn.text = ">>";
if (pop)
i += 2;
return true;
}
}
} else if (tokens[i].text == txt) {
tkn = tokens[i]; tkn = tokens[i];
if (pop) if (pop)
i++; i++;
@@ -233,7 +153,6 @@ static std::string EnsureSafeVariable(LexToken token) {
} }
void Parser::EnsureSymbol(std::string txt) { void Parser::EnsureSymbol(std::string txt) {
if (i < tokens.size()) { if (i < tokens.size()) {
if (tokens[i].type != LexTokenType::Symbol) { if (tokens[i].type != LexTokenType::Symbol) {
throw SyntaxException( throw SyntaxException(
tokens[i].lineInfo, tokens[i].lineInfo,
@@ -241,69 +160,7 @@ void Parser::EnsureSymbol(std::string txt) {
LexTokenType_ToString(tokens[i].type) + " \"" + LexTokenType_ToString(tokens[i].type) + " \"" +
tokens[i].text + "\" which is not a symbol at all."); tokens[i].text + "\" which is not a symbol at all.");
} }
if (txt == ">") { if (tokens[i].text != txt) {
if (i + 1 < tokens.size()) {
if ((tokens[i + 1].text == ">" || tokens[i + 1].text == ">=") &&
tokens[i + 1].type == LexTokenType::Symbol)
throw SyntaxException(tokens[i].lineInfo,
"expected the symbol \"" + txt +
"\" but got the symbol \"" +
tokens[i].text +
tokens[i + 1].text + "\"");
;
}
if (txt == tokens[i].text) {
tkn = tokens[i];
i++;
return;
}
}
if (txt == ">>=") {
if (i + 1 < tokens.size()) {
if (tokens[i].text == ">" && tokens[i + 1].text == ">=" &&
tokens[i].type == LexTokenType::Symbol &&
tokens[i + 1].type == LexTokenType::Symbol) {
tkn = tokens[i];
i += 2;
return;
}
throw SyntaxException(tokens[i].lineInfo,
"expected the symbol \"" + txt +
"\" but got the symbol \"" +
tokens[i].text + tokens[i + 1].text +
"\"");
}
throw SyntaxException(tokens[i].lineInfo,
"expected the symbol \"" + txt +
"\" but got the symbol \"" +
tokens[i].text + "\"");
} else if (txt == ">>") {
if (i + 1 < tokens.size()) {
if (tokens[i].text == ">" && tokens[i + 1].text == ">" &&
tokens[i].type == LexTokenType::Symbol &&
tokens[i + 1].type == LexTokenType::Symbol) {
tkn = tokens[i];
i += 2;
return;
}
throw SyntaxException(tokens[i].lineInfo,
"expected the symbol \"" + txt +
"\" but got the symbol \"" +
tokens[i].text + tokens[i + 1].text +
"\"");
}
throw SyntaxException(tokens[i].lineInfo,
"expected the symbol \"" + txt +
"\" but got the symbol \"" +
tokens[i].text + "\"");
} else if (tokens[i].text != txt) {
throw SyntaxException(tokens[i].lineInfo, throw SyntaxException(tokens[i].lineInfo,
"expected the symbol \"" + txt + "expected the symbol \"" + txt +
@@ -633,6 +490,10 @@ void Parser::ParseHtml(std::vector<SyntaxNode> &nodes, std::string var) {
EnsureSymbol(")"); EnsureSymbol(")");
EnsureSymbol(">"); EnsureSymbol(">");
if (std::holds_alternative<std::nullptr_t>(item))
item = AdvancedSyntaxNode::Create(DeclareExpression, true,
{"item"});
std::vector<SyntaxNode> _nodes; std::vector<SyntaxNode> _nodes;
parseFn(_nodes, "each"); parseFn(_nodes, "each");
body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes); body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes);
@@ -1411,7 +1272,7 @@ SyntaxNode Parser::ParseNode(bool isRoot) {
} }
if (!isRoot) if (!isRoot)
i++; EnsureSymbol("}");
return aSN; return aSN;
} }
@@ -1517,10 +1378,8 @@ SyntaxNode Parser::ParseNode(bool isRoot) {
body = ParseNode(); body = ParseNode();
} }
if (std::holds_alternative<std::nullptr_t>(item)) if (std::holds_alternative<std::nullptr_t>(item))
item = AdvancedSyntaxNode::Create( item =
DeclareExpression, true, AdvancedSyntaxNode::Create(DeclareExpression, true, {"item"});
{AdvancedSyntaxNode::Create(GetVariableExpression, true,
{"item"})});
return AdvancedSyntaxNode::Create(EachStatement, false, return AdvancedSyntaxNode::Create(EachStatement, false,
{item, list, body}); {item, list, body});
@@ -2006,6 +1865,8 @@ SyntaxNode Parser::ParseBAnd() {
SyntaxNode Parser::ParseExpression() { SyntaxNode Parser::ParseExpression() {
SyntaxNode expr = ParseAssignment(); SyntaxNode expr = ParseAssignment();
while (IsSymbol(",")) { while (IsSymbol(",")) {
if (IsAnySymbol({"]", "}"}, false))
break;
expr = AdvancedSyntaxNode::Create(CommaExpression, true, expr = AdvancedSyntaxNode::Create(CommaExpression, true,
{expr, ParseAssignment()}); {expr, ParseAssignment()});
} }
+2 -2
View File
@@ -16,7 +16,7 @@ static void Help(std::string &filename) {
printf(" -n: Set name (MyAppOrLibName defaults to out)\n"); printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
printf(" -h, --help: Prints help\n"); printf(" -h, --help: Prints help\n");
printf("Options except for help have flag with arg like this: -F ARG\n"); printf("Options except for help have flag with arg like this: -F ARG\n");
exit(1); std::exit(1);
} }
int64_t CrossArchiveCreate(std::vector<std::string> &argv) { int64_t CrossArchiveCreate(std::vector<std::string> &argv) {
@@ -53,7 +53,7 @@ int64_t CrossArchiveCreate(std::vector<std::string> &argv) {
printf("Expected " printf("Expected "
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]" "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]"
"]]]\n"); "]]]\n");
exit(1); std::exit(1);
} }
} }
} else { } else {
+1 -1
View File
@@ -94,7 +94,7 @@ void CrossLangDump(std::shared_ptr<Tesses::Framework::Streams::Stream> strm) {
uint32_t ents = EnsureInt(strm); uint32_t ents = EnsureInt(strm);
for (uint8_t k = 0; k < ents; k++) { for (uint32_t k = 0; k < ents; k++) {
Ensure(strm, main_header, 1); Ensure(strm, main_header, 1);
uint8_t flags = main_header[0]; uint8_t flags = main_header[0];
std::cout << "\t\t/^" << strs.at(EnsureInt(strm)) << "^/" std::cout << "\t\t/^" << strs.at(EnsureInt(strm)) << "^/"
+8 -8
View File
@@ -85,7 +85,7 @@ TObject CrossLangShell(GCList &ls, std::vector<std::string> &argv) {
"Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm"; "Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm";
if (argv.size() == 2 && argv[1] == "configdir") { if (argv.size() == 2 && argv[1] == "configdir") {
std::cout << dir.ToString() << std::endl; std::cout << dir.ToString() << std::endl;
return 0; return (int64_t)0;
} }
if (argv.size() > 1 && argv[1] == "update-shell") { if (argv.size() > 1 && argv[1] == "update-shell") {
@@ -101,15 +101,15 @@ TObject CrossLangShell(GCList &ls, std::vector<std::string> &argv) {
auto strm = resp.ReadAsStream(); auto strm = resp.ReadAsStream();
CrossLang::CrossArchiveExtract(strm, subdir); CrossLang::CrossArchiveExtract(strm, subdir);
return 0; return (int64_t)0;
} else { } else {
std::cout << "Error when fetching the script error: " std::cout << "Error when fetching the script error: "
<< std::to_string(resp.statusCode) << " " << std::to_string(resp.statusCode) << " "
<< HttpUtils::StatusCodeString(resp.statusCode) << HttpUtils::StatusCodeString(resp.statusCode)
<< std::endl; << std::endl;
return 1; return (int64_t)1;
} }
return 0; return (int64_t)0;
} }
if (!Tesses::Framework::Filesystem::LocalFS->RegularFileExists(filename)) { if (!Tesses::Framework::Filesystem::LocalFS->RegularFileExists(filename)) {
@@ -125,12 +125,12 @@ TObject CrossLangShell(GCList &ls, std::vector<std::string> &argv) {
CrossLang::CrossArchiveExtract(strm, subdir); CrossLang::CrossArchiveExtract(strm, subdir);
} else { } else {
return 1; return (int64_t)1;
} }
} else { } else {
if (!Download(filename, subdir)) if (!Download(filename, subdir))
return 1; return (int64_t)1;
return 0; return (int64_t)0;
} }
} }
@@ -142,7 +142,7 @@ TObject CrossLangShell(GCList &ls, std::vector<std::string> &argv) {
env->LoadFileWithDependencies( env->LoadFileWithDependencies(
ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, filename); ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, filename);
TList *args = TList::Create(ls); TList *args = ls.Create<TList>();
args->Add(filename.ToString()); args->Add(filename.ToString());
+8 -8
View File
@@ -27,7 +27,7 @@ static void Help(std::string filename) {
"for sane with file access to current directory and sub " "for sane with file access to current directory and sub "
"directories, \"full\" has full runtime.\n"); "directories, \"full\" has full runtime.\n");
printf("Options except for help have flag with arg like this: -F ARG\n"); printf("Options except for help have flag with arg like this: -F ARG\n");
exit(1); std::exit(1);
} }
void CrossLangCompiler(std::vector<std::string> &argv) { void CrossLangCompiler(std::vector<std::string> &argv) {
/*std::ifstream strm(argv[1],std::ios_base::in|std::ios_base::binary); /*std::ifstream strm(argv[1],std::ios_base::in|std::ios_base::binary);
@@ -107,14 +107,14 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
printf("Expected " printf("Expected "
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-" "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-"
"prod]]]]\n"); "prod]]]]\n");
exit(1); std::exit(1);
} }
dependencies.push_back( dependencies.push_back(
std::pair<std::string, TVMVersion>(str1, v2)); std::pair<std::string, TVMVersion>(str1, v2));
} else { } else {
printf("ERROR: Dependency must have version\n"); printf("ERROR: Dependency must have version\n");
exit(1); std::exit(1);
} }
} }
} else if (argv[i] == "-t") { } else if (argv[i] == "-t") {
@@ -137,14 +137,14 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
printf("Expected " printf("Expected "
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-" "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-"
"prod]]]]\n"); "prod]]]]\n");
exit(1); std::exit(1);
} }
tools.push_back( tools.push_back(
std::pair<std::string, TVMVersion>(str1, v2)); std::pair<std::string, TVMVersion>(str1, v2));
} else { } else {
printf("ERROR: Tool must have version\n"); printf("ERROR: Tool must have version\n");
exit(1); std::exit(1);
} }
} }
} else if (argv[i] == "-n") { } else if (argv[i] == "-n") {
@@ -161,7 +161,7 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
printf("Expected " printf("Expected "
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]" "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]"
"]]]\n"); "]]]\n");
exit(1); std::exit(1);
} }
} }
} else if (argv[i] == "-D" || argv[i] == "--debug") { } else if (argv[i] == "-D" || argv[i] == "--debug") {
@@ -192,7 +192,7 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
if (comptime == "secure") { if (comptime == "secure") {
TStd::RegisterConsole(gc, env); TStd::RegisterConsole(gc, env);
TStd::RegisterClass(gc, env); TStd::RegisterZeClass(gc, env);
TStd::RegisterCrypto(gc, env); TStd::RegisterCrypto(gc, env);
TStd::RegisterDictionary(gc, env); TStd::RegisterDictionary(gc, env);
TStd::RegisterJson(gc, env); TStd::RegisterJson(gc, env);
@@ -201,7 +201,7 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
env->permissions.locked = true; env->permissions.locked = true;
} else if (comptime == "secure_file") { } else if (comptime == "secure_file") {
TStd::RegisterConsole(gc, env); TStd::RegisterConsole(gc, env);
TStd::RegisterClass(gc, env); TStd::RegisterZeClass(gc, env);
TStd::RegisterCrypto(gc, env); TStd::RegisterCrypto(gc, env);
TStd::RegisterDictionary(gc, env); TStd::RegisterDictionary(gc, env);
TStd::RegisterJson(gc, env); TStd::RegisterJson(gc, env);
+1 -1
View File
@@ -39,7 +39,7 @@ TObject CrossLangInterperter(GCList &ls, TRootEnvironment *env,
} }
} }
TList *args = TList::Create(ls); TList *args = ls.Create<TList>();
for (int arg = 1; arg < argv.size(); arg++) for (int arg = 1; arg < argv.size(); arg++)
args->Add(std::string(argv[arg])); args->Add(std::string(argv[arg]));
+5 -5
View File
@@ -7,7 +7,7 @@ TObject CrossLangVM(GCList &ls, TRootEnvironment *env,
std::cout << "USAGE: " std::cout << "USAGE: "
<< (argv.empty() ? (std::string) "crossvm" : argv[0]) << (argv.empty() ? (std::string) "crossvm" : argv[0])
<< " <filename.crvm> <args...>" << std::endl; << " <filename.crvm> <args...>" << std::endl;
return 1; return (int64_t)1;
} }
env->LoadFileWithDependencies( env->LoadFileWithDependencies(
@@ -25,7 +25,7 @@ TObject CrossLangVM(GCList &ls, TRootEnvironment *env,
env->EnsureDictionary(ls.GetGC(), "Net") env->EnsureDictionary(ls.GetGC(), "Net")
->SetValue("WebServerPort", (int64_t)port); ->SetValue("WebServerPort", (int64_t)port);
TList *args2 = TList::Create(ls); TList *args2 = ls.Create<TList>();
for (auto &item : args.positional) { for (auto &item : args.positional) {
args2->Add(item); args2->Add(item);
} }
@@ -33,7 +33,7 @@ TObject CrossLangVM(GCList &ls, TRootEnvironment *env,
auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2}); auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2});
auto svr2 = Tesses::CrossLang::ToHttpServer(ls.GetGC(), res); auto svr2 = Tesses::CrossLang::ToHttpServer(ls.GetGC(), res);
if (svr2 == nullptr) if (svr2 == nullptr)
return 1; return (int64_t)1;
Tesses::Framework::Http::HttpServer svr(port, svr2); Tesses::Framework::Http::HttpServer svr(port, svr2);
svr.StartAccepting(); svr.StartAccepting();
TF_RunEventLoop(); TF_RunEventLoop();
@@ -46,9 +46,9 @@ TObject CrossLangVM(GCList &ls, TRootEnvironment *env,
_co->CallMethod(ls, "", "Close", {}); _co->CallMethod(ls, "", "Close", {});
} }
TF_Quit(); TF_Quit();
return 0; return (int64_t)0;
} else { } else {
TList *args = TList::Create(ls); TList *args = ls.Create<TList>();
for (size_t arg = 1; arg < argv.size(); arg++) for (size_t arg = 1; arg < argv.size(); arg++)
args->Add(std::string(argv[arg])); args->Add(std::string(argv[arg]));
+6 -6
View File
@@ -2,7 +2,7 @@
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
static TList *VectorOfStringToList(GCList &ls, std::vector<std::string> &strs) { static TList *VectorOfStringToList(GCList &ls, std::vector<std::string> &strs) {
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
for (auto &item : strs) for (auto &item : strs)
list->Add(item); list->Add(item);
@@ -10,7 +10,7 @@ static TList *VectorOfStringToList(GCList &ls, std::vector<std::string> &strs) {
return list; return list;
} }
static TList *EntriesToList(GCList &ls, std::vector<TClassEntry> &ents) { static TList *EntriesToList(GCList &ls, std::vector<TClassEntry> &ents) {
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
for (auto &item : ents) { for (auto &item : ents) {
std::string modifier = "public"; std::string modifier = "public";
@@ -42,7 +42,7 @@ static TList *EntriesToList(GCList &ls, std::vector<TClassEntry> &ents) {
return list; return list;
} }
static TList *ClassInstanceToList(GCList &ls, TClassObject *co) { static TList *ClassInstanceToList(GCList &ls, TClassObject *co) {
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
for (auto &item : co->entries) { for (auto &item : co->entries) {
if (item.modifier == TClassModifier::Public) { if (item.modifier == TClassModifier::Public) {
@@ -126,7 +126,7 @@ static TObject Class_CreateInstance(TRootEnvironment *env, GCList &ls,
} }
static TObject Class_GetClassNames(TRootEnvironment *env, GCList &ls, static TObject Class_GetClassNames(TRootEnvironment *env, GCList &ls,
std::vector<TObject> args) { std::vector<TObject> args) {
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
for (auto &item : env->classes) { for (auto &item : env->classes) {
list->Add(JoinPeriod(item.first->classes.at(item.second).name)); list->Add(JoinPeriod(item.first->classes.at(item.second).name));
@@ -190,9 +190,9 @@ static TObject Class_GetInfo(TRootEnvironment *env, GCList &ls,
return nullptr; return nullptr;
} }
void TStd::RegisterClass(std::shared_ptr<GC> gc, TRootEnvironment *env) { void TStd::RegisterZeClass(std::shared_ptr<GC> gc, TRootEnvironment *env) {
GCList ls(gc); GCList ls(gc);
env->permissions.canRegisterClass = true; env->permissions.canRegisterZeClass = true;
TDictionary *cls = env->EnsureDictionary(gc, "Class"); TDictionary *cls = env->EnsureDictionary(gc, "Class");
gc->BarrierBegin(); gc->BarrierBegin();
+18 -5
View File
@@ -3,7 +3,17 @@
#include <iostream> #include <iostream>
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TObject Console_setInvertedColors(GCList &ls, std::vector<TObject> args) {
bool inverted;
if (GetArgument(args, 0, inverted)) {
Tesses::Framework::Console::SetInvertedColors(inverted);
}
return Undefined();
}
TObject Console_Reset(GCList &ls, std::vector<TObject> args) {
Tesses::Framework::Console::Reset();
return Undefined();
}
TObject Console_getIsTTY(GCList &ls, std::vector<TObject> args) { TObject Console_getIsTTY(GCList &ls, std::vector<TObject> args) {
return Tesses::Framework::Console::IsTTY(); return Tesses::Framework::Console::IsTTY();
@@ -62,18 +72,21 @@ TObject Console_Write(GCList &ls, std::vector<TObject> args) {
TObject Console_Fatal(GCList &ls, std::vector<TObject> args) { TObject Console_Fatal(GCList &ls, std::vector<TObject> args) {
if (args.size() < 1) { if (args.size() < 1) {
Tesses::Framework::Console::ErrorLine("FATAL: <NO MESSAGE>"); Tesses::Framework::Console::ErrorLine("FATAL: <NO MESSAGE>");
exit(1); std::exit(1);
} }
Tesses::Framework::Console::ErrorLine("FATAL: " + Tesses::Framework::Console::ErrorLine("FATAL: " +
ToString(ls.GetGC(), args[0])); ToString(ls.GetGC(), args[0]));
exit(1); std::exit(1);
} }
TObject Console_WriteLine(GCList &ls, std::vector<TObject> args) { TObject Console_WriteLine(GCList &ls, std::vector<TObject> args) {
if (args.size() < 1) { if (args.size() < 1) {
Tesses::Framework::Console::WriteLineView(""); Tesses::Framework::Console::WriteLineView("");
return Undefined(); return Undefined();
} }
Tesses::Framework::Console::WriteLine(ToString(ls.GetGC(), args[0])); std::string text = ToString(ls.GetGC(), args[0]);
Tesses::Framework::Console::WriteLine(text);
return Undefined(); return Undefined();
} }
@@ -143,7 +156,7 @@ TObject Console_List(GCList &ls, std::vector<TObject> args) {
return (int64_t)Tesses::Framework::Console::List(items); return (int64_t)Tesses::Framework::Console::List(items);
} }
return 0; return (int64_t)0;
} }
void TStd::RegisterConsole(std::shared_ptr<GC> gc, TRootEnvironment *env) { void TStd::RegisterConsole(std::shared_ptr<GC> gc, TRootEnvironment *env) {
env->permissions.canRegisterConsole = true; env->permissions.canRegisterConsole = true;
+1 -1
View File
@@ -2,7 +2,7 @@
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TObject Dictionary_FindByKey(GCList &ls, std::vector<TObject> args) { TObject Dictionary_FindByKey(GCList &ls, std::vector<TObject> args) {
TList *dest = TList::Create(ls); TList *dest = ls.Create<TList>();
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
std::string key; std::string key;
if (GetArgument(args, 1, key)) { if (GetArgument(args, 1, key)) {
+1 -5
View File
@@ -1,10 +1,6 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
#include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Serialization/BitConverter.hpp"
#if defined(_WIN32)
#include <windows.h>
#endif
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
using namespace Tesses::Framework::Platform::Environment; using namespace Tesses::Framework::Platform::Environment;
#if defined(_WIN32) #if defined(_WIN32)
@@ -95,7 +91,7 @@ static TObject Env_GetRealExecutablePath(GCList &ls,
} }
static TObject Env_GetAll(GCList &ls, std::vector<TObject> args) { static TObject Env_GetAll(GCList &ls, std::vector<TObject> args) {
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
std::vector<std::pair<std::string, std::string>> env; std::vector<std::pair<std::string, std::string>> env;
Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env); Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env);
for (auto &item : env) { for (auto &item : env) {
+1 -1
View File
@@ -63,7 +63,7 @@ static TObject FS_ReadAllLines(GCList &ls, std::vector<TObject> args) {
Tesses::Framework::Filesystem::Helpers::ReadAllLines(vfs, path, lines); Tesses::Framework::Filesystem::Helpers::ReadAllLines(vfs, path, lines);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
auto items = TList::Create(ls); auto items = ls.Create<TList>();
for (auto &l : lines) { for (auto &l : lines) {
items->Add(l); items->Add(l);
} }
+11 -11
View File
@@ -5,7 +5,7 @@ using namespace Tesses::Framework::Serialization::Json;
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
static bool IsValidForJson(TObject v) { static bool IsValidForJson(TObject v) {
if (std::holds_alternative<std::nullptr_t>(v)) if (IsNull(v))
return true; return true;
if (std::holds_alternative<int64_t>(v)) if (std::holds_alternative<int64_t>(v))
@@ -20,10 +20,10 @@ static bool IsValidForJson(TObject v) {
if (std::holds_alternative<std::string>(v)) if (std::holds_alternative<std::string>(v))
return true; return true;
if (std::holds_alternative<THeapObjectHolder>(v)) { if (std::holds_alternative<THeapObject *>(v)) {
auto res = std::get<THeapObjectHolder>(v); auto res = std::get<THeapObject *>(v);
auto ls = dynamic_cast<TList *>(res.obj); auto ls = dynamic_cast<TList *>(res);
auto dict = dynamic_cast<TDictionary *>(res.obj); auto dict = dynamic_cast<TDictionary *>(res);
if (ls != nullptr) if (ls != nullptr)
return true; return true;
if (dict != nullptr) if (dict != nullptr)
@@ -32,7 +32,7 @@ static bool IsValidForJson(TObject v) {
return false; return false;
} }
static JToken JsonSerialize(TObject v) { static JToken JsonSerialize(TObject v) {
if (std::holds_alternative<std::nullptr_t>(v)) if (IsNull(v))
return nullptr; return nullptr;
if (std::holds_alternative<int64_t>(v)) if (std::holds_alternative<int64_t>(v))
return std::get<int64_t>(v); return std::get<int64_t>(v);
@@ -42,8 +42,8 @@ static JToken JsonSerialize(TObject v) {
return std::get<bool>(v); return std::get<bool>(v);
if (std::holds_alternative<std::string>(v)) if (std::holds_alternative<std::string>(v))
return std::get<std::string>(v); return std::get<std::string>(v);
if (std::holds_alternative<THeapObjectHolder>(v)) { if (std::holds_alternative<THeapObject *>(v)) {
auto obj = std::get<THeapObjectHolder>(v).obj; auto obj = std::get<THeapObject *>(v);
auto ls = dynamic_cast<TList *>(obj); auto ls = dynamic_cast<TList *>(obj);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
@@ -114,7 +114,7 @@ static TObject JsonDeserialize(GCList &ls2, JToken json) {
if (TryGetJToken(json, str)) if (TryGetJToken(json, str))
return str; return str;
if (TryGetJToken(json, arr)) { if (TryGetJToken(json, arr)) {
TList *ls = TList::Create(ls2); TList *ls = ls2.Create<TList>();
for (auto &item : arr) { for (auto &item : arr) {
auto itemRes = JsonDeserialize(ls2, item); auto itemRes = JsonDeserialize(ls2, item);
@@ -159,7 +159,7 @@ static TObject JsonDocDecode(GCList &ls2, std::vector<TObject> args) {
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);
} }
TObject Json_Decode(GCList ls, std::string str) { TObject Json_Decode(GCList &ls, std::string str) {
return JsonDeserialize(ls, Json::Decode(str)); return JsonDeserialize(ls, Json::Decode(str));
} }
std::string Json_DocEncode(TObject o, bool indent) { std::string Json_DocEncode(TObject o, bool indent) {
@@ -169,7 +169,7 @@ std::string Json_DocEncode(TObject o, bool indent) {
return Json::DocEncode(ls, indent); return Json::DocEncode(ls, indent);
return ""; return "";
} }
TObject Json_DocDecode(GCList ls, std::string str) { TObject Json_DocDecode(GCList &ls, std::string str) {
return JsonDeserialize(ls, Json::DocDecode(str)); return JsonDeserialize(ls, Json::DocDecode(str));
} }
void TStd::RegisterJson(std::shared_ptr<GC> gc, TRootEnvironment *env) { void TStd::RegisterJson(std::shared_ptr<GC> gc, TRootEnvironment *env) {
+67 -26
View File
@@ -17,13 +17,13 @@ static std::shared_ptr<SMTPBody>
TObjectToSMTPBody(GCList &ls, std::string mimeType, TObject obj) { TObjectToSMTPBody(GCList &ls, std::string mimeType, TObject obj) {
std::shared_ptr<SMTPBody> body; std::shared_ptr<SMTPBody> body;
std::string text; std::string text;
TByteArray *ba; TByteView *ba;
std::shared_ptr<Tesses::Framework::Streams::Stream> sho; std::shared_ptr<Tesses::Framework::Streams::Stream> sho;
if (GetObject(obj, text)) { if (GetObject(obj, text)) {
body = std::make_shared<SMTPStringBody>(text, mimeType); body = std::make_shared<SMTPStringBody>(text, mimeType);
} else if (GetObjectHeap(obj, ba)) { } else if (GetObjectHeap(obj, ba)) {
std::shared_ptr<MemoryStream> ms = std::make_shared<MemoryStream>(true); std::shared_ptr<MemoryStream> ms = std::make_shared<MemoryStream>(true);
ms->WriteBlock(ba->data.data(), ba->data.size()); ms->WriteBlock(ba->GetData(), ba->GetSize());
ms->Seek(0L, SeekOrigin::Begin); ms->Seek(0L, SeekOrigin::Begin);
body = std::make_shared<SMTPStreamBody>(mimeType, ms); body = std::make_shared<SMTPStreamBody>(mimeType, ms);
@@ -150,8 +150,48 @@ class THttpDictionary : public TNativeObject {
value); value);
} }
return nullptr; return nullptr;
} else if (key == "TryGetOnlyOne") {
std::string key;
std::string value;
if (GetArgument(args, 0, key) && dict->TryGetOnlyOne(key, value)) {
return value;
}
return nullptr;
} else if (key == "TryGetOnlyOneBoolean") {
std::string key;
bool value;
if (GetArgument(args, 0, key) &&
dict->TryGetOnlyOneBoolean(key, value)) {
return value;
}
return nullptr;
} else if (key == "TryGetOnlyOneDouble") {
std::string key;
double value;
if (GetArgument(args, 0, key) &&
dict->TryGetOnlyOneDouble(key, value)) {
return value;
}
return nullptr;
} else if (key == "TryGetOnlyOneInt") {
std::string key;
int64_t value;
if (GetArgument(args, 0, key) &&
dict->TryGetOnlyOneInt(key, value)) {
return value;
}
return nullptr;
} else if (key == "TryGetOnlyOneDate") {
std::string key;
Tesses::Framework::Date::DateTime value;
if (GetArgument(args, 0, key) &&
dict->TryGetOnlyOneDate(key, value)) {
return std::make_shared<Tesses::Framework::Date::DateTime>(
value);
}
return nullptr;
} else if (key == "ToList") { } else if (key == "ToList") {
TList *_ls = TList::Create(ls); TList *_ls = ls.Create<TList>();
for (auto item : dict->kvp) { for (auto item : dict->kvp) {
for (auto i : item.second) { for (auto i : item.second) {
auto d = TDictionary::Create(ls); auto d = TDictionary::Create(ls);
@@ -215,7 +255,7 @@ class TServerContext : public TNativeObjectThatReturnsHttpDictionary {
else if (key == "getIP") else if (key == "getIP")
return ctx->ip; return ctx->ip;
else if (key == "getPort") else if (key == "getPort")
return ctx->port; return (int64_t)ctx->port;
else if (key == "getOriginalPath") else if (key == "getOriginalPath")
return ctx->originalPath; return ctx->originalPath;
else if (key == "getPath") else if (key == "getPath")
@@ -235,10 +275,13 @@ class TServerContext : public TNativeObjectThatReturnsHttpDictionary {
return sc; return sc;
} }
} else if (key == "getStatusCode") } else if (key == "getStatusCode")
return ctx->statusCode; return (int64_t)ctx->statusCode;
else if (key == "getQueryParams") else if (key == "getQueryParams")
return TNativeObject::Create<THttpDictionary>(ls, &ctx->queryParams, return TNativeObject::Create<THttpDictionary>(ls, &ctx->queryParams,
this); this);
else if (key == "getBodyParams")
return TNativeObject::Create<THttpDictionary>(ls, &ctx->bodyParams,
this);
else if (key == "getRequestHeaders") else if (key == "getRequestHeaders")
return TNativeObject::Create<THttpDictionary>( return TNativeObject::Create<THttpDictionary>(
ls, &ctx->requestHeaders, this); ls, &ctx->requestHeaders, this);
@@ -291,7 +334,7 @@ class TServerContext : public TNativeObjectThatReturnsHttpDictionary {
return strm; return strm;
}); });
return TList::Create(ls, response.begin(), response.end()); return ls.Create<TList>(response.begin(), response.end());
} }
} else if (key == "getNeedToParseFormData") } else if (key == "getNeedToParseFormData")
return ctx->NeedToParseFormData(); return ctx->NeedToParseFormData();
@@ -780,18 +823,20 @@ static TObject Net_Http_ListenOnUnusedPort(GCList &ls,
static TObject Net_Http_MimeType(GCList &ls, std::vector<TObject> args) { static TObject Net_Http_MimeType(GCList &ls, std::vector<TObject> args) {
Tesses::Framework::Filesystem::VFSPath p; Tesses::Framework::Filesystem::VFSPath p;
if (GetArgumentAsPath(args, 0, p)) { if (GetArgumentAsPath(args, 0, p)) {
std::filesystem::path p2 = p.GetFileName();
return HttpUtils::MimeType(p2); return HttpUtils::GetMimeTypePath(p);
} }
return std::string("application/octet-stream"); return std::string("application/octet-stream");
} }
class THttpRequestBody : public TNativeObject { class THttpRequestBody : public TNativeObject {
HttpRequestBody *body; std::shared_ptr<HttpRequestBody> body;
public: public:
THttpRequestBody(HttpRequestBody *body) { this->body = body; } THttpRequestBody(std::shared_ptr<HttpRequestBody> body) {
this->body = body;
}
bool IsClosed() { return body == nullptr; } bool IsClosed() { return body == nullptr; }
HttpRequestBody *GetBody() { return this->body; } std::shared_ptr<HttpRequestBody> GetBody() { return this->body; }
std::string TypeName() { return "Net.Http.HttpRequestBody"; } std::string TypeName() { return "Net.Http.HttpRequestBody"; }
@@ -799,10 +844,7 @@ class THttpRequestBody : public TNativeObject {
return Undefined(); return Undefined();
} }
void Close() { void Close() { this->body = nullptr; }
delete this->body;
this->body = nullptr;
}
}; };
class THttpResponse : public TNativeObjectThatReturnsHttpDictionary { class THttpResponse : public TNativeObjectThatReturnsHttpDictionary {
@@ -907,7 +949,8 @@ static TObject Net_Http_MakeRequest(GCList &ls, std::vector<TObject> args,
_obj = options->GetValue("Body"); _obj = options->GetValue("Body");
if (GetObjectHeap(_obj, body1)) { if (GetObjectHeap(_obj, body1)) {
req.body = new TDictionaryHttpRequestBody(gc, body1); req.body =
std::make_shared<TDictionaryHttpRequestBody>(gc, body1);
} else if (GetObjectHeap(_obj, body2) && !body2->IsClosed()) { } else if (GetObjectHeap(_obj, body2) && !body2->IsClosed()) {
req.body = body2->GetBody(); req.body = body2->GetBody();
} }
@@ -920,8 +963,6 @@ static TObject Net_Http_MakeRequest(GCList &ls, std::vector<TObject> args,
if (req.body != nullptr) { if (req.body != nullptr) {
if (body2 != nullptr) { if (body2 != nullptr) {
body2->Close(); body2->Close();
} else if (body1 != nullptr) {
delete req.body;
} }
} }
@@ -1073,7 +1114,7 @@ static TObject Net_Http_WebSocketClient(GCList &ls, std::vector<TObject> args) {
if (GetArgument(args, 0, url) && GetArgumentHeap(args, 1, headers) && if (GetArgument(args, 0, url) && GetArgumentHeap(args, 1, headers) &&
GetArgumentHeap(args, 2, dict)) { GetArgumentHeap(args, 2, dict)) {
GetArgumentHeap(args, 3, callable); GetArgumentHeap(args, 3, callable);
HttpDictionary hdict; HttpDictionary hdict(false);
for (int64_t index = 0; index < headers->Count(); index++) { for (int64_t index = 0; index < headers->Count(); index++) {
_obj = headers->Get(index); _obj = headers->Get(index);
TDictionary *dict; TDictionary *dict;
@@ -1171,7 +1212,7 @@ static TObject Net_Http_WebSocketClient(GCList &ls, std::vector<TObject> args) {
if (!GetObjectHeap(hobj, headers)) if (!GetObjectHeap(hobj, headers))
return Undefined(); return Undefined();
HttpDictionary hdict; HttpDictionary hdict(false);
for (int64_t index = 0; index < headers->Count(); index++) { for (int64_t index = 0; index < headers->Count(); index++) {
_obj = headers->Get(index); _obj = headers->Get(index);
TDictionary *dict; TDictionary *dict;
@@ -1381,7 +1422,7 @@ static TObject New_StreamHttpRequestBody(GCList &ls,
if (GetArgument(args, 0, strm) && GetArgument(args, 1, mimeType)) { if (GetArgument(args, 0, strm) && GetArgument(args, 1, mimeType)) {
return TNativeObject::Create<THttpRequestBody>( return TNativeObject::Create<THttpRequestBody>(
ls, new StreamHttpRequestBody(strm, mimeType)); ls, std::make_shared<StreamHttpRequestBody>(strm, mimeType));
} }
return nullptr; return nullptr;
} }
@@ -1390,7 +1431,7 @@ static TObject New_TextHttpRequestBody(GCList &ls, std::vector<TObject> args) {
std::string mimeType; std::string mimeType;
if (GetArgument(args, 0, text) && GetArgument(args, 1, mimeType)) { if (GetArgument(args, 0, text) && GetArgument(args, 1, mimeType)) {
return TNativeObject::Create<THttpRequestBody>( return TNativeObject::Create<THttpRequestBody>(
ls, new TextHttpRequestBody(text, mimeType)); ls, std::make_shared<TextHttpRequestBody>(text, mimeType));
} }
return nullptr; return nullptr;
} }
@@ -1398,8 +1439,8 @@ static TObject New_JsonHttpRequestBody(GCList &ls, std::vector<TObject> args) {
if (!args.empty()) { if (!args.empty()) {
return TNativeObject::Create<THttpRequestBody>( return TNativeObject::Create<THttpRequestBody>(
ls, ls, std::make_shared<TextHttpRequestBody>(Json_Encode(args[0]),
new TextHttpRequestBody(Json_Encode(args[0]), "application/json")); "application/json"));
} }
return nullptr; return nullptr;
} }
@@ -1423,7 +1464,7 @@ void TStd::RegisterNet(std::shared_ptr<GC> gc, TRootEnvironment *env) {
"Create a text request body", {"text", "mimeType"}, "Create a text request body", {"text", "mimeType"},
New_TextHttpRequestBody); New_TextHttpRequestBody);
_new->DeclareFunction(gc, "JsonHttpRequestBody", _new->DeclareFunction(gc, "JsonHttpRequestBody",
"Create a text request body", {"json"}, "Create a json request body", {"json"},
New_JsonHttpRequestBody); New_JsonHttpRequestBody);
_new->DeclareFunction( _new->DeclareFunction(
gc, "HttpServer", "Create a http server (allows multiple)", gc, "HttpServer", "Create a http server (allows multiple)",
@@ -1540,7 +1581,7 @@ void TStd::RegisterNet(std::shared_ptr<GC> gc, TRootEnvironment *env) {
dict->DeclareFunction( dict->DeclareFunction(
gc, "getIPAddresses", "Get the ip addresses of this machine", {"$ipv6"}, gc, "getIPAddresses", "Get the ip addresses of this machine", {"$ipv6"},
[](GCList &ls, std::vector<TObject> args) -> TObject { [](GCList &ls, std::vector<TObject> args) -> TObject {
TList *a = TList::Create(ls); TList *a = ls.Create<TList>();
bool ipv6 = false; bool ipv6 = false;
GetArgument(args, 0, ipv6); GetArgument(args, 0, ipv6);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
+13 -7
View File
@@ -3,13 +3,9 @@
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
class ProcessObject : public TNativeObject { class ProcessObject : public TNativeObject {
public: public:
ProcessObject() {
arguments = nullptr;
environment = nullptr;
}
ProcessObject(GCList &ls) { ProcessObject(GCList &ls) {
arguments = TList::Create(ls); arguments = ls.Create<TList>();
environment = TList::Create(ls); environment = ls.Create<TList>();
process.includeThisEnv = true; process.includeThisEnv = true;
process.redirectStdIn = false; process.redirectStdIn = false;
@@ -167,7 +163,7 @@ static TObject Process_Start(GCList &ls, std::vector<TObject> args,
TDictionary *dict; TDictionary *dict;
if (GetArgumentHeap(args, 0, dict)) { if (GetArgumentHeap(args, 0, dict)) {
auto process = TNativeObject::Create<ProcessObject>(ls); auto process = TNativeObject::Create<ProcessObject>(ls, ls);
auto name = dict->GetValue("FileName"); auto name = dict->GetValue("FileName");
auto inh = dict->GetValue("InheritParentEnvironment"); auto inh = dict->GetValue("InheritParentEnvironment");
auto rStdIn = dict->GetValue("RedirectStandardInput"); auto rStdIn = dict->GetValue("RedirectStandardInput");
@@ -280,6 +276,16 @@ void TStd::RegisterProcess(std::shared_ptr<GC> gc, TRootEnvironment *env) {
} }
return Undefined(); return Undefined();
}); });
dict->DeclareFunction(
gc, "ShellFileOrUrl", "Launch file or url in shell", {"urlOrFilename"},
[](GCList &ls, std::vector<TObject> args) -> TObject {
std::string fileOrUrl;
if (GetArgument(args, 0, fileOrUrl))
Tesses::Framework::Platform::ShellFileOrUrl(fileOrUrl);
return Undefined();
});
gc->BarrierEnd(); gc->BarrierEnd();
} }
} // namespace Tesses::CrossLang } // namespace Tesses::CrossLang
+1 -1
View File
@@ -100,7 +100,7 @@ class SQLiteObject : public TNativeObject {
this->db->Exec(arg, res); this->db->Exec(arg, res);
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
for (auto &item : res) { for (auto &item : res) {
TDictionary *dict = TDictionary::Create(ls); TDictionary *dict = TDictionary::Create(ls);
+31 -44
View File
@@ -6,28 +6,17 @@
#include <memory> #include <memory>
#include <variant> #include <variant>
#include <vector> #include <vector>
#if !defined(CROSSLANG_STATIC) #if !defined(CROSSLANG_STATIC)
#if defined(CROSSLANG_ENABLE_FFI) #if defined(CROSSLANG_ENABLE_FFI)
#include <ffi.h> #include <ffi.h>
#endif #endif
#if defined(_WIN32) #if !defined(_WIN32)
#include <windows.h>
#include <time.h>
#undef min
#undef max
#else
#include <dlfcn.h> #include <dlfcn.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#else #else
#if defined(_WIN32) #if !defined(_WIN32)
#include <windows.h>
#include <time.h>
#undef min
#undef max
#else
#include <unistd.h> #include <unistd.h>
#endif #endif
#endif #endif
@@ -70,15 +59,18 @@ class DL {
Tesses::Framework::Filesystem::LocalFilesystem lfs; Tesses::Framework::Filesystem::LocalFilesystem lfs;
std::string str = lfs.VFSPathToSystem(p); std::string str = lfs.VFSPathToSystem(p);
#if defined(_WIN32) #if defined(_WIN32)
handle =
LoadLibraryExA(str.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); throw std::runtime_error("I removed support on this platform");
// handle =LoadLibraryExA(str.c_str(), NULL,
// LOAD_WITH_ALTERED_SEARCH_PATH);
#else #else
handle = dlopen(str.c_str(), RTLD_LAZY); handle = dlopen(str.c_str(), RTLD_LAZY);
#endif #endif
} }
template <typename T> T Resolve(std::string name) { template <typename T> T Resolve(std::string name) {
#if defined(_WIN32) #if defined(_WIN32)
return (T)GetProcAddress((HMODULE)handle, name.c_str()); throw std::runtime_error("I removed support on this platform");
// return (T)GetProcAddress((HMODULE)handle, name.c_str());
#else #else
return (T)dlsym(handle, name.c_str()); return (T)dlsym(handle, name.c_str());
@@ -86,7 +78,9 @@ class DL {
} }
~DL() { ~DL() {
#if defined(_WIN32) #if defined(_WIN32)
FreeLibrary((HMODULE)handle);
throw std::runtime_error("I removed support on this platform");
// FreeLibrary((HMODULE)handle);
#else #else
dlclose(handle); dlclose(handle);
#endif #endif
@@ -149,8 +143,8 @@ ffi_tmp_type_t FFI_ConvertTObjectToFFIType(TObject &arg, std::string t) {
return (ffi_tmp_type_t){ return (ffi_tmp_type_t){
.v_ptr = (void *)std::get<std::string>(arg).c_str()}; .v_ptr = (void *)std::get<std::string>(arg).c_str()};
} }
} else if (std::holds_alternative<THeapObjectHolder>(arg)) { } else if (std::holds_alternative<THeapObject *>(arg)) {
auto obj = std::get<THeapObjectHolder>(arg).obj; auto obj = std::get<THeapObject *>(arg);
auto bA = dynamic_cast<TByteArray *>(obj); auto bA = dynamic_cast<TByteArray *>(obj);
auto nat = dynamic_cast<TNative *>(obj); auto nat = dynamic_cast<TNative *>(obj);
if (bA != nullptr) { if (bA != nullptr) {
@@ -441,13 +435,7 @@ static TObject TypeIsClass(GCList &ls, std::vector<TObject> args) {
static TObject TypeIsDefined(GCList &ls, std::vector<TObject> args) { static TObject TypeIsDefined(GCList &ls, std::vector<TObject> args) {
if (args.empty()) if (args.empty())
return nullptr; return nullptr;
return (!std::holds_alternative<std::nullptr_t>(args[0]) && return (!IsNull(args[0]) && !std::holds_alternative<Undefined>(args[0]));
!std::holds_alternative<Undefined>(args[0]));
}
static TObject TypeIsHeap(GCList &ls, std::vector<TObject> args) {
if (args.empty())
return nullptr;
return std::holds_alternative<THeapObjectHolder>(args[0]);
} }
static TObject TypeIsNumber(GCList &ls, std::vector<TObject> args) { static TObject TypeIsNumber(GCList &ls, std::vector<TObject> args) {
if (args.empty()) if (args.empty())
@@ -674,7 +662,7 @@ std::string GetObjectTypeString(TObject _obj) {
return "Regex"; return "Regex";
if (std::holds_alternative<Undefined>(_obj)) if (std::holds_alternative<Undefined>(_obj))
return "Undefined"; return "Undefined";
if (std::holds_alternative<std::nullptr_t>(_obj)) if (IsNull(_obj))
return "Null"; return "Null";
if (std::holds_alternative<bool>(_obj)) if (std::holds_alternative<bool>(_obj))
return "Boolean"; return "Boolean";
@@ -826,8 +814,8 @@ std::string GetObjectTypeString(TObject _obj) {
} }
return "VFS"; return "VFS";
} }
if (std::holds_alternative<THeapObjectHolder>(_obj)) { if (std::holds_alternative<THeapObject *>(_obj)) {
auto obj = std::get<THeapObjectHolder>(_obj).obj; auto obj = std::get<THeapObject *>(_obj);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -1004,11 +992,7 @@ static TObject YieldEnumerableFunc(GCList &ls, std::vector<TObject> args) {
static TObject DateTime_Sleep(GCList &ls, std::vector<TObject> args) { static TObject DateTime_Sleep(GCList &ls, std::vector<TObject> args) {
int64_t msec; int64_t msec;
if (GetArgument(args, 0, msec)) { if (GetArgument(args, 0, msec)) {
#if defined(_WIN32) Tesses::Framework::TF_Sleep(msec);
Sleep((int)msec);
#else
usleep(1000 * msec);
#endif
} }
return nullptr; return nullptr;
} }
@@ -1390,10 +1374,7 @@ void TStd::RegisterRoot(std::shared_ptr<GC> gc, TRootEnvironment *env) {
env->DeclareFunction(gc, "TypeIsDefined", env->DeclareFunction(gc, "TypeIsDefined",
"Get whether object is not null or undefined", "Get whether object is not null or undefined",
{"object"}, TypeIsDefined); {"object"}, TypeIsDefined);
env->DeclareFunction(
gc, "TypeIsHeap",
"Get whether object is susceptible to garbage collection", {"object"},
TypeIsHeap);
env->DeclareFunction(gc, "TypeIsNumber", "Get whether object is a number", env->DeclareFunction(gc, "TypeIsNumber", "Get whether object is a number",
{"object"}, TypeIsNumber); {"object"}, TypeIsNumber);
env->DeclareFunction(gc, "TypeIsLong", env->DeclareFunction(gc, "TypeIsLong",
@@ -1465,9 +1446,9 @@ void TStd::RegisterRoot(std::shared_ptr<GC> gc, TRootEnvironment *env) {
gc, "Thread", "Create thread", {"callback"}, gc, "Thread", "Create thread", {"callback"},
[](GCList &ls, std::vector<TObject> args) -> TObject { [](GCList &ls, std::vector<TObject> args) -> TObject {
if (args.size() == 1 && if (args.size() == 1 &&
std::holds_alternative<THeapObjectHolder>(args[0])) { std::holds_alternative<THeapObject *>(args[0])) {
auto cb = dynamic_cast<TCallable *>( auto cb =
std::get<THeapObjectHolder>(args[0]).obj); dynamic_cast<TCallable *>(std::get<THeapObject *>(args[0]));
if (cb != nullptr) { if (cb != nullptr) {
return CreateThread(ls, cb, false); return CreateThread(ls, cb, false);
} }
@@ -1587,7 +1568,7 @@ void TStd::RegisterStd(
RegisterCrypto(gc, env); RegisterCrypto(gc, env);
RegisterOGC(gc, env); RegisterOGC(gc, env);
RegisterProcess(gc, env); RegisterProcess(gc, env);
RegisterClass(gc, env); RegisterZeClass(gc, env);
gc->RegisterEverything(env); gc->RegisterEverything(env);
@@ -1613,7 +1594,13 @@ void TStd::RegisterStd(
gc_dict->DeclareFunction( gc_dict->DeclareFunction(
gc, "Collect", "Collect garbage", {}, gc, "Collect", "Collect garbage", {},
[](GCList &ls, std::vector<TObject> args) -> TObject { [](GCList &ls, std::vector<TObject> args) -> TObject {
ls.GetGC()->Collect(); std::vector<THeapObject *> to_delete;
ls.GetGC()->BarrierBegin();
ls.GetGC()->Collect(to_delete);
ls.GetGC()->BarrierEnd();
for (auto item : to_delete)
delete item;
return nullptr; return nullptr;
}); });
gc_dict->DeclareFunction( gc_dict->DeclareFunction(
+7 -2
View File
@@ -39,7 +39,7 @@ static TObject AstToTObject(GCList &ls, SyntaxNode node) {
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
r->SetValue("Type", asn.nodeName); r->SetValue("Type", asn.nodeName);
r->SetValue("IsExpression", asn.isExpression); r->SetValue("IsExpression", asn.isExpression);
TList *ls2 = TList::Create(ls); TList *ls2 = ls.Create<TList>();
for (auto item : asn.nodes) { for (auto item : asn.nodes) {
ls2->Add(AstToTObject(ls, item)); ls2->Add(AstToTObject(ls, item));
} }
@@ -67,6 +67,8 @@ static TObject VM_SourceToAst(GCList &ls, std::vector<TObject> args) {
static TObject VM_Eval(GCList &ls, std::vector<TObject> args) { static TObject VM_Eval(GCList &ls, std::vector<TObject> args) {
std::string str; std::string str;
if (GetArgument(args, 0, str)) { if (GetArgument(args, 0, str)) {
auto current_function = GC::GetCurrentFunction();
if (current_function != nullptr) { if (current_function != nullptr) {
return current_function->env->Eval(ls, str); return current_function->env->Eval(ls, str);
} }
@@ -90,6 +92,8 @@ static TObject Success(GCList &ls) {
} }
static TObject VM_getCurrentEnvironment(GCList &ls2, static TObject VM_getCurrentEnvironment(GCList &ls2,
std::vector<TObject> args) { std::vector<TObject> args) {
auto current_function = GC::GetCurrentFunction();
if (current_function != nullptr) if (current_function != nullptr)
return current_function->env; return current_function->env;
return Undefined(); return Undefined();
@@ -261,9 +265,10 @@ static TObject VM_Compile(GCList &ls, std::vector<TObject> args) {
} }
} }
static TObject VM_GetStacktrace(GCList &ls, std::vector<TObject> args) { static TObject VM_GetStacktrace(GCList &ls, std::vector<TObject> args) {
auto current_function = GC::GetCurrentFunction();
if (current_function != nullptr) { if (current_function != nullptr) {
if (current_function->thread != nullptr) { if (current_function->thread != nullptr) {
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
for (auto item : current_function->thread->call_stack_entries) { for (auto item : current_function->thread->call_stack_entries) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
+2 -16
View File
@@ -1,22 +1,8 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TAny *TAny::Create(GCList &ls) { TAny *TAny::Create(GCList &ls) { return ls.Create<TAny>(); }
TAny *anyObj = new TAny(); TAny *TAny::Create(GCList *ls) { return ls->Create<TAny>(); }
std::shared_ptr<GC> gc = ls.GetGC();
ls.Add(anyObj);
gc->Watch(anyObj);
return anyObj;
}
TAny *TAny::Create(GCList *ls) {
TAny *anyObj = new TAny();
std::shared_ptr<GC> gc = ls->GetGC();
ls->Add(anyObj);
gc->Watch(anyObj);
return anyObj;
}
void TAny::Mark() { void TAny::Mark() {
if (this->marked) if (this->marked)
return; return;
+2 -10
View File
@@ -3,18 +3,10 @@
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TAssociativeArray *TAssociativeArray::Create(GCList &ls) { TAssociativeArray *TAssociativeArray::Create(GCList &ls) {
TAssociativeArray *list = new TAssociativeArray(); return ls.Create<TAssociativeArray>();
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(list);
_gc->Watch(list);
return list;
} }
TAssociativeArray *TAssociativeArray::Create(GCList *ls) { TAssociativeArray *TAssociativeArray::Create(GCList *ls) {
TAssociativeArray *list = new TAssociativeArray(); return ls->Create<TAssociativeArray>();
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(list);
_gc->Watch(list);
return list;
} }
void TAssociativeArray::Set(std::shared_ptr<GC> gc, TObject key, void TAssociativeArray::Set(std::shared_ptr<GC> gc, TObject key,
TObject value) { TObject value) {
+83
View File
@@ -0,0 +1,83 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang {
std::string TByteView::TypeName() { return "ByteView"; }
TString *TByteView::ToString(GCList &ls) {
auto bounds = GetBounds();
if (bounds.first == nullptr || bounds.second == 0)
return ls.FromString("");
return ls.Create<TString>(reinterpret_cast<const char *>(bounds.first),
bounds.second);
}
bool TByteView::opExecuteMethod(InterperterThread *thrd, std::shared_ptr<GC> gc,
const std::string &name,
const std::vector<TObject> &args) {
if (name == "Slice") {
int64_t offset = 0;
int64_t length = -1;
GetArgument(args, 0, offset);
GetArgument(args, 1, length);
GCList ls(gc);
thrd->call_stack_entries.back()->Push(
gc, ls.Create<TSpan>(this, offset, length));
return false;
}
if (name == "Count" || name == "Length") {
thrd->call_stack_entries.back()->Push(
gc, static_cast<int64_t>(this->GetBounds().second));
return false;
}
if (name == "GetAt") {
int64_t i64;
if (GetArgument(args, 0, i64)) {
auto res = this->GetAt(static_cast<size_t>(i64));
thrd->call_stack_entries.back()->Push(
gc, res == -1 ? static_cast<TObject>(nullptr)
: static_cast<TObject>(res));
return false;
}
}
thrd->call_stack_entries.back()->Push(gc, Undefined());
return false;
}
bool TByteView::opGetField(InterperterThread *thrd, std::shared_ptr<GC> gc,
const std::string &name) {
if (name == "Count" || name == "Length") {
thrd->call_stack_entries.back()->Push(
gc, static_cast<int64_t>(this->GetBounds().second));
return false;
}
thrd->call_stack_entries.back()->Push(gc, Undefined());
return false;
}
void TByteView::CopyTo(TMutByteView *view) {
auto myBounds = this->GetBounds();
if (myBounds.first == nullptr || myBounds.second == 0)
return;
auto theirBounds = view->GetMutableBoundsConstrained(0, myBounds.second);
if (theirBounds.first == nullptr || theirBounds.second == 0)
return;
memcpy(theirBounds.first, myBounds.first, theirBounds.second);
}
void TByteView::CopyTo(TMutByteView *view, size_t srcOffset, size_t destOffset,
size_t length) {
auto myBounds = this->GetBoundsConstrained(srcOffset, length);
if (myBounds.first == nullptr || myBounds.second == 0)
return;
auto theirBounds =
view->GetMutableBoundsConstrained(destOffset, myBounds.second);
if (theirBounds.first == nullptr || theirBounds.second == 0)
return;
memcpy(theirBounds.first, myBounds.first, theirBounds.second);
}
} // namespace Tesses::CrossLang
View File
+10
View File
@@ -0,0 +1,10 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang {
TResource::TResource(std::vector<uint8_t> &&bytes) : bytes(std::move(bytes)) {}
std::pair<const uint8_t *, size_t> TResource::GetBounds() const {
return std::pair<const uint8_t *, size_t>(bytes.data(), bytes.size());
}
std::string TResource::TypeName() { return "Resource"; }
} // namespace Tesses::CrossLang
+123
View File
@@ -0,0 +1,123 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang {
TString::TString() {}
TString::TString(std::string_view str) : text(str) {}
TString::TString(const char *text, size_t len) : text(text, len) {}
TString::TString(std::string_view left, std::string_view right) {
text.reserve(left.size() + right.size());
text.append(left.begin(), left.end());
text.append(right.begin(), right.end());
}
TString::TString(std::string &&str) : text(std::move(str)) {}
const std::string &TString::GetString() const { return this->text; }
std::pair<const uint8_t *, size_t> TString::GetBounds() const {
return std::pair<const uint8_t *, size_t>(
reinterpret_cast<const uint8_t *>(text.data()), text.size());
}
std::string TString::TypeName() { return "String"; }
TString *TString::ToString(GCList &ls) {
ls.Add(this);
return this;
}
bool TString::opAdd(InterperterThread *thrd, std::shared_ptr<GC> gc,
TObject rhs) {
TString *rStr;
char rChr;
if (GetObjectHeap(rhs, rStr)) {
GCList ls(gc);
thrd->call_stack_entries.back()->Push(
gc, ls.Create<TString>(this->GetString(), rStr->GetString()));
return false;
}
if (GetObject(rhs, rChr)) {
GCList ls(gc);
thrd->call_stack_entries.back()->Push(
gc,
ls.Create<TString>(this->GetString(), std::string_view(&rChr, 1)));
return false;
}
thrd->call_stack_entries.back()->Push(gc, Undefined());
return false;
}
bool TString::opLessThan(InterperterThread *thrd, std::shared_ptr<GC> gc,
TObject rhs) {
TString *rStr;
if (GetObjectHeap(rhs, rStr)) {
thrd->call_stack_entries.back()->Push(gc, this->GetString() <
rStr->GetString());
return false;
}
thrd->call_stack_entries.back()->Push(gc, Undefined());
return false;
}
bool TString::opGreaterThan(InterperterThread *thrd, std::shared_ptr<GC> gc,
TObject rhs) {
TString *rStr;
if (GetObjectHeap(rhs, rStr)) {
thrd->call_stack_entries.back()->Push(gc, this->GetString() >
rStr->GetString());
return false;
}
thrd->call_stack_entries.back()->Push(gc, Undefined());
return false;
}
bool TString::opLessThanEqual(InterperterThread *thrd, std::shared_ptr<GC> gc,
TObject rhs) {
TString *rStr;
if (GetObjectHeap(rhs, rStr)) {
thrd->call_stack_entries.back()->Push(gc, this->GetString() <=
rStr->GetString());
return false;
}
thrd->call_stack_entries.back()->Push(gc, Undefined());
return false;
}
bool TString::opGreaterThanEqual(InterperterThread *thrd,
std::shared_ptr<GC> gc, TObject rhs) {
TString *rStr;
if (GetObjectHeap(rhs, rStr)) {
thrd->call_stack_entries.back()->Push(gc, this->GetString() >=
rStr->GetString());
return false;
}
thrd->call_stack_entries.back()->Push(gc, Undefined());
return false;
}
bool TString::IsEqualTo(std::shared_ptr<GC> gc, TObject rhs) {
TString *rStr;
if (GetObjectHeap(rhs, rStr)) {
if (this == rStr)
return true;
return this->GetString() == rStr->GetString();
}
return false;
}
bool TString::IsNotEqualTo(std::shared_ptr<GC> gc, TObject rhs) {
TString *rStr;
if (GetObjectHeap(rhs, rStr)) {
if (this == rStr)
return false;
return this->GetString() != rStr->GetString();
}
return true;
}
} // namespace Tesses::CrossLang
+9 -12
View File
@@ -9,22 +9,12 @@ bool TClassEnvironment::HasConstForSet(std::string key) {
TClassEnvironment *TClassEnvironment::Create(GCList *gc, TEnvironment *env, TClassEnvironment *TClassEnvironment::Create(GCList *gc, TEnvironment *env,
TClassObject *obj) { TClassObject *obj) {
TClassEnvironment *env2 = new TClassEnvironment(env, obj); return gc->Create<TClassEnvironment>(env, obj);
std::shared_ptr<GC> _gc = gc->GetGC();
gc->Add(env2);
_gc->Watch(env2);
return env2;
} }
TClassEnvironment *TClassEnvironment::Create(GCList &gc, TEnvironment *env, TClassEnvironment *TClassEnvironment::Create(GCList &gc, TEnvironment *env,
TClassObject *obj) { TClassObject *obj) {
TClassEnvironment *env2 = new TClassEnvironment(env, obj); return gc.Create<TClassEnvironment>(env, obj);
std::shared_ptr<GC> _gc = gc.GetGC();
gc.Add(env2);
_gc->Watch(env2);
return env2;
} }
TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) { TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) {
this->env = env; this->env = env;
@@ -33,6 +23,7 @@ TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) {
bool TClassEnvironment::HasVariable(std::string key) { bool TClassEnvironment::HasVariable(std::string key) {
if (key == "this") if (key == "this")
return true; return true;
auto current_function = GC::GetCurrentFunction();
if (this->clsObj->HasValue(current_function == nullptr if (this->clsObj->HasValue(current_function == nullptr
? "" ? ""
: current_function->callable->className, : current_function->callable->className,
@@ -49,6 +40,8 @@ bool TClassEnvironment::HasVariableOrFieldRecurse(std::string key,
bool setting) { bool setting) {
if (key == "this") if (key == "this")
return true; return true;
auto current_function = GC::GetCurrentFunction();
std::string clsName = current_function == nullptr std::string clsName = current_function == nullptr
? "" ? ""
: current_function->callable->className; : current_function->callable->className;
@@ -63,6 +56,7 @@ TObject TClassEnvironment::GetVariable(std::string key) {
if (key == "this") if (key == "this")
return this->clsObj; return this->clsObj;
auto current_function = GC::GetCurrentFunction();
std::string clsName = current_function == nullptr std::string clsName = current_function == nullptr
? "" ? ""
: current_function->callable->className; : current_function->callable->className;
@@ -75,6 +69,7 @@ void TClassEnvironment::SetVariable(std::string key, TObject value) {
if (key == "this") if (key == "this")
return; return;
auto current_function = GC::GetCurrentFunction();
std::string clsName = current_function == nullptr std::string clsName = current_function == nullptr
? "" ? ""
: current_function->callable->className; : current_function->callable->className;
@@ -90,6 +85,7 @@ TObject TClassEnvironment::GetVariable(GCList &ls, std::string key) {
if (key == "this") if (key == "this")
return this->clsObj; return this->clsObj;
auto current_function = GC::GetCurrentFunction();
std::string clsName = current_function == nullptr std::string clsName = current_function == nullptr
? "" ? ""
: current_function->callable->className; : current_function->callable->className;
@@ -107,6 +103,7 @@ TObject TClassEnvironment::SetVariable(GCList &ls, std::string key, TObject v) {
if (key == "this") if (key == "this")
return this->clsObj; return this->clsObj;
auto current_function = GC::GetCurrentFunction();
std::string clsName = current_function == nullptr std::string clsName = current_function == nullptr
? "" ? ""
: current_function->callable->className; : current_function->callable->className;
+24 -46
View File
@@ -1,27 +1,18 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TArgWrapper::TArgWrapper(TCallable *callable) : callable(callable) {}
TArgWrapper *TArgWrapper::Create(GCList &ls, TCallable *callable) { TArgWrapper *TArgWrapper::Create(GCList &ls, TCallable *callable) {
TArgWrapper *argWrapper = new TArgWrapper(); return ls.Create<TArgWrapper>(callable);
argWrapper->callable = callable;
std::shared_ptr<GC> gc = ls.GetGC();
ls.Add(argWrapper);
gc->Watch(argWrapper);
return argWrapper;
} }
TArgWrapper *TArgWrapper::Create(GCList *ls, TCallable *callable) { TArgWrapper *TArgWrapper::Create(GCList *ls, TCallable *callable) {
TArgWrapper *argWrapper = new TArgWrapper(); return ls->Create<TArgWrapper>(callable);
argWrapper->callable = callable;
std::shared_ptr<GC> gc = ls->GetGC();
ls->Add(argWrapper);
gc->Watch(argWrapper);
return argWrapper;
} }
TObject TArgWrapper::Call(GCList &ls, std::vector<TObject> args) { TObject TArgWrapper::Call(GCList &ls, std::vector<TObject> args) {
auto cse = current_function; auto cse = GC::GetCurrentFunction();
TList *argList = TList::Create(ls); TList *argList = ls.Create<TList>();
argList->items = args; argList->items = args;
TObject v = this->callable->Call(ls, {argList}); TObject v = this->callable->Call(ls, {argList});
current_function = cse; GC::SetCurrentFunction(cse);
return v; return v;
} }
void TArgWrapper::Mark() { void TArgWrapper::Mark() {
@@ -46,52 +37,39 @@ void TClosure::Mark() {
this->closure->Mark(); this->closure->Mark();
GC::Mark(this->tag); GC::Mark(this->tag);
} }
TClosure *TClosure::Create(GCList &ls, TEnvironment *env, TFile *file, TClosure::TClosure(TEnvironment *env, TFile *file, uint32_t chunkId,
uint32_t chunkId, bool ownScope) { bool ownScope) {
TClosure *closure = new TClosure(); this->className = "";
closure->className = ""; this->ownScope = ownScope;
closure->ownScope = ownScope;
std::shared_ptr<GC> _gc = ls.GetGC(); this->chunkId = chunkId;
ls.Add(closure);
_gc->Watch(closure);
closure->chunkId = chunkId;
if (chunkId < file->chunks.size()) if (chunkId < file->chunks.size())
closure->closure = file->chunks[chunkId]; this->closure = file->chunks[chunkId];
else else
throw VMException("ChunkId out of bounds."); throw VMException("ChunkId out of bounds.");
closure->env = env; this->env = env;
closure->file = file; this->file = file;
}
return closure; TClosure *TClosure::Create(GCList &ls, TEnvironment *env, TFile *file,
uint32_t chunkId, bool ownScope) {
return ls.Create<TClosure>(env, file, chunkId, ownScope);
} }
TClosure *TClosure::Create(GCList *ls, TEnvironment *env, TFile *file, TClosure *TClosure::Create(GCList *ls, TEnvironment *env, TFile *file,
uint32_t chunkId, bool ownScope) { uint32_t chunkId, bool ownScope) {
TClosure *closure = new TClosure(); return ls->Create<TClosure>(env, file, chunkId, ownScope);
closure->className = "";
closure->ownScope = ownScope;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(closure);
_gc->Watch(closure);
closure->chunkId = chunkId;
if (chunkId < file->chunks.size())
closure->closure = file->chunks[chunkId];
else
throw VMException("ChunkId out of bounds.");
closure->env = env;
closure->file = file;
return closure;
} }
TObject TClosure::Call(GCList &ls, std::vector<TObject> args) { TObject TClosure::Call(GCList &ls, std::vector<TObject> args) {
auto cse = current_function; auto cse = GC::GetCurrentFunction();
InterperterThread *thrd = InterperterThread::Create(ls); InterperterThread *thrd = InterperterThread::Create(ls);
thrd->AddCallStackEntry(ls, this, args); thrd->AddCallStackEntry(ls, this, args);
thrd->Execute(ls.GetGC()); thrd->Execute(ls.GetGC());
TObject v = thrd->call_stack_entries[0]->Pop(ls); TObject v = thrd->call_stack_entries[0]->Pop(ls);
current_function = cse; GC::SetCurrentFunction(cse);
// current_function = cse;
return v; return v;
} }
} // namespace Tesses::CrossLang } // namespace Tesses::CrossLang
+9 -25
View File
@@ -1,24 +1,15 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TDynamicDictionary::TDynamicDictionary(TCallable *callable) : cb(callable) {}
TDynamicDictionary *TDynamicDictionary::Create(GCList &ls, TDynamicDictionary *TDynamicDictionary::Create(GCList &ls,
TCallable *callable) { TCallable *callable) {
TDynamicDictionary *dict = new TDynamicDictionary(); return ls.Create<TDynamicDictionary>(callable);
dict->cb = callable;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(dict);
_gc->Watch(dict);
return dict;
} }
TDynamicDictionary *TDynamicDictionary::Create(GCList *ls, TDynamicDictionary *TDynamicDictionary::Create(GCList *ls,
TCallable *callable) { TCallable *callable) {
TDynamicDictionary *dict = new TDynamicDictionary(); return ls->Create<TDynamicDictionary>(callable);
dict->cb = callable;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(dict);
_gc->Watch(dict);
return dict;
} }
void TDynamicDictionary::Mark() { void TDynamicDictionary::Mark() {
@@ -54,7 +45,7 @@ TObject TDynamicDictionary::CallMethod(GCList &ls, std::string name,
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "CallMethod"); dict->SetValue("Type", "CallMethod");
dict->SetValue("Name", name); dict->SetValue("Name", name);
auto argVal = TList::Create(ls); auto argVal = ls.Create<TList>();
argVal->items = args; argVal->items = args;
dict->SetValue("Arguments", argVal); dict->SetValue("Arguments", argVal);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
@@ -165,8 +156,9 @@ void TDictionary::DeclareFunction(
TObject TDictionary::GetValue(std::string key) { TObject TDictionary::GetValue(std::string key) {
if (this->items.empty()) if (this->items.empty())
return Undefined(); return Undefined();
if (this->items.count(key) > 0) auto item = this->items.find(key);
return this->items[key]; if (item != this->items.end())
return item->second;
return Undefined(); return Undefined();
} }
void TDictionary::SetValue(std::string key, TObject value) { void TDictionary::SetValue(std::string key, TObject value) {
@@ -189,18 +181,10 @@ void TDictionary::Mark() {
} }
} }
TDictionary *TDictionary::Create(GCList *gc) { TDictionary *TDictionary::Create(GCList *gc) {
TDictionary *dict = new TDictionary(); return gc->Create<TDictionary>();
std::shared_ptr<GC> _gc = gc->GetGC();
gc->Add(dict);
_gc->Watch(dict);
return dict;
} }
TDictionary *TDictionary::Create(GCList &gc) { TDictionary *TDictionary::Create(GCList &gc) {
TDictionary *dict = new TDictionary(); return gc.Create<TDictionary>();
std::shared_ptr<GC> _gc = gc.GetGC();
gc.Add(dict);
_gc->Watch(dict);
return dict;
} }
}; // namespace Tesses::CrossLang }; // namespace Tesses::CrossLang
+168
View File
@@ -0,0 +1,168 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang {
TException::TException(std::string message, std::string type,
TDictionary *extraFields, TObject innerException)
: message(message), type(type), extraFields(extraFields),
innerException(innerException) {}
TObject TException::CallMethod(GCList &ls, std::string key,
std::vector<TObject> args) {
if (key == "getMessage" ||
key == "getText") // Text is for compatibility reasons
return this->message;
if (key == "getInnerException")
return this->innerException;
if (key == "getType")
return this->type;
if (key == "getLine")
return static_cast<int64_t>(this->line.value_or(0));
if (key == "getOffset")
return static_cast<int64_t>(this->offset.value_or(0));
if (key == "getColumn")
return static_cast<int64_t>(this->column.value_or(0));
if (key == "getFileName")
return this->filename.value_or("");
if (key == "setLine") {
int64_t v;
if (!this->line && GetArgument(args, 0, v))
this->line = static_cast<uint32_t>(v);
return Undefined();
}
if (key == "setColumn") {
int64_t v;
if (!this->column && GetArgument(args, 0, v))
this->column = static_cast<uint32_t>(v);
return Undefined();
}
if (key == "setOffset") {
int64_t v;
if (!this->offset && GetArgument(args, 0, v))
this->offset = static_cast<uint32_t>(v);
return Undefined();
}
if (key == "setFileName") {
std::string v;
if (!this->filename && GetArgument(args, 0, v))
this->filename = v;
return Undefined();
}
if (key == "ToString") {
std::string text;
text.reserve(this->type.size() + this->message.size() + 3);
text.append(this->type);
text.append(": ");
text.append(this->message);
text.push_back('\n');
if (this->filename) {
auto &filename = *this->filename;
text.reserve(text.size() + filename.size() + 4);
text.append("At: ");
text.append(filename);
if (this->line) {
text.push_back(':');
text.append(std::to_string(*this->line));
if (this->column) {
text.push_back(':');
text.append(std::to_string(*this->column));
}
}
text.push_back('\n');
if (!this->line && this->column) {
text.append("Column: ");
text.append(std::to_string(*this->column));
text.push_back('\n');
}
} else {
if (this->line) {
text.append("Line: ");
text.append(std::to_string(*this->line));
text.push_back('\n');
}
if (this->column) {
text.append("Column: ");
text.append(std::to_string(*this->column));
text.push_back('\n');
}
}
if (this->offset) {
text.append("Offset: ");
text.append(std::to_string(*this->offset));
text.push_back('\n');
}
if (!std::holds_alternative<Undefined>(this->innerException)) {
text.append("InnerException:");
std::string textInner = ToString(ls.GetGC(), this->innerException);
for (auto item : Tesses::Framework::Http::HttpUtils::SplitString(
textInner, "\n")) {
if (item.empty()) {
text.push_back('\n');
continue;
}
text.append("\n\t");
text.append(item);
}
}
return text;
}
if (extraFields != nullptr) {
GCList ls2(ls.GetGC());
if (extraFields->MethodExists(ls2, key)) {
return extraFields->CallMethod(ls, key, args);
}
if (key.size() > 3 && key[0] == 'g' && key[1] == 'e' && key[2] == 't') {
ls.GetGC()->BarrierBegin();
auto val = extraFields->GetValue(key.substr(3));
ls.GetGC()->BarrierEnd();
return val;
}
}
return Undefined();
}
std::string TException::TypeName() { return this->type; }
bool TException::ToBool() { return true; }
void TException::Mark() {
if (marked)
return;
marked = true;
if (this->extraFields)
this->extraFields->Mark();
GC::Mark(this->innerException);
}
TNativeException::TNativeException(const char *what, std::exception_ptr ptr)
: what(what != nullptr ? what : ""), ptr(ptr) {}
TObject TNativeException::CallMethod(GCList &ls, std::string key,
std::vector<TObject> args) {
if (key == "getMessage" || key == "getText")
return this->what;
if (key == "getType")
return "NativeException";
if (key == "ToString") {
return "NativeException: " + this->what;
}
return Undefined();
}
std::string TNativeException::TypeName() { return "NativeException"; }
std::string TNativeException::What() { return this->what; }
std::exception_ptr TNativeException::GetPointer() { return this->ptr; }
void TNativeException::ThrowIt() { std::rethrow_exception(this->ptr); }
} // namespace Tesses::CrossLang
+6 -25
View File
@@ -1,8 +1,8 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TExternalMethod::TExternalMethod( TExternalMethod::TExternalMethod(
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
std::string documentation, std::vector<std::string> argNames, std::string documentation, std::vector<std::string> argNames,
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
std::function<void()> destroy) { std::function<void()> destroy) {
this->cb = cb; this->cb = cb;
@@ -14,43 +14,24 @@ TExternalMethod *TExternalMethod::Create(
GCList &ls, std::string documentation, std::vector<std::string> argNames, GCList &ls, std::string documentation, std::vector<std::string> argNames,
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb, std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
std::function<void()> destroy) { std::function<void()> destroy) {
auto gc = ls.GetGC(); return ls.Create<TExternalMethod>(documentation, argNames, cb, destroy);
TExternalMethod *method =
new TExternalMethod(cb, documentation, argNames, destroy);
ls.Add(method);
gc->Watch(method);
return method;
} }
TExternalMethod *TExternalMethod::Create( TExternalMethod *TExternalMethod::Create(
GCList *ls, std::string documentation, std::vector<std::string> argNames, GCList *ls, std::string documentation, std::vector<std::string> argNames,
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb, std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
std::function<void()> destroy) { std::function<void()> destroy) {
auto gc = ls->GetGC(); return ls->Create<TExternalMethod>(documentation, argNames, cb, destroy);
TExternalMethod *method =
new TExternalMethod(cb, documentation, argNames, destroy);
ls->Add(method);
gc->Watch(method);
return method;
} }
TExternalMethod *TExternalMethod::Create( TExternalMethod *TExternalMethod::Create(
GCList &ls, std::string documentation, std::vector<std::string> argNames, GCList &ls, std::string documentation, std::vector<std::string> argNames,
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) { std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) {
auto gc = ls.GetGC(); return ls.Create<TExternalMethod>(documentation, argNames, cb);
TExternalMethod *method =
new TExternalMethod(cb, documentation, argNames, []() -> void {});
ls.Add(method);
gc->Watch(method);
return method;
} }
TExternalMethod *TExternalMethod::Create( TExternalMethod *TExternalMethod::Create(
GCList *ls, std::string documentation, std::vector<std::string> argNames, GCList *ls, std::string documentation, std::vector<std::string> argNames,
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) { std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) {
auto gc = ls->GetGC();
TExternalMethod *method = return ls->Create<TExternalMethod>(documentation, argNames, cb);
new TExternalMethod(cb, documentation, argNames, []() -> void {});
ls->Add(method);
gc->Watch(method);
return method;
} }
TObject TExternalMethod::Call(GCList &ls, std::vector<TObject> args) { TObject TExternalMethod::Call(GCList &ls, std::vector<TObject> args) {
if (cb == nullptr) if (cb == nullptr)
+35 -114
View File
@@ -44,28 +44,15 @@ void TYieldEnumerator::Mark() {
GC::Mark(this->current); GC::Mark(this->current);
GC::Mark(this->enumerator); GC::Mark(this->enumerator);
} }
TYieldEnumerator *TYieldEnumerator::Create(GCList &ls, TObject v) {
TYieldEnumerator *yieldEnum = new TYieldEnumerator();
yieldEnum->current = nullptr;
yieldEnum->hasStarted = false;
yieldEnum->enumerator = v;
std::shared_ptr<GC> _gc = ls.GetGC(); TYieldEnumerator::TYieldEnumerator(TObject v)
ls.Add(yieldEnum); : current(nullptr), hasStarted(false), enumerator(v) {}
_gc->Watch(yieldEnum);
return yieldEnum; TYieldEnumerator *TYieldEnumerator::Create(GCList &ls, TObject v) {
return ls.Create<TYieldEnumerator>(v);
} }
TYieldEnumerator *TYieldEnumerator::Create(GCList *ls, TObject v) { TYieldEnumerator *TYieldEnumerator::Create(GCList *ls, TObject v) {
return ls->Create<TYieldEnumerator>(v);
TYieldEnumerator *yieldEnum = new TYieldEnumerator();
yieldEnum->current = nullptr;
yieldEnum->hasStarted = false;
yieldEnum->enumerator = v;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(yieldEnum);
_gc->Watch(yieldEnum);
return yieldEnum;
} }
bool TCustomEnumerator::MoveNext(std::shared_ptr<GC> ls) { bool TCustomEnumerator::MoveNext(std::shared_ptr<GC> ls) {
@@ -97,21 +84,12 @@ void TCustomEnumerator::Mark() {
return; return;
this->dict->Mark(); this->dict->Mark();
} }
TCustomEnumerator::TCustomEnumerator(TDictionary *dict) : dict(dict) {}
TCustomEnumerator *TCustomEnumerator::Create(GCList *ls, TDictionary *dict) { TCustomEnumerator *TCustomEnumerator::Create(GCList *ls, TDictionary *dict) {
TCustomEnumerator *customEnum = new TCustomEnumerator(); return ls->Create<TCustomEnumerator>(dict);
customEnum->dict = dict;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(customEnum);
_gc->Watch(customEnum);
return customEnum;
} }
TCustomEnumerator *TCustomEnumerator::Create(GCList &ls, TDictionary *dict) { TCustomEnumerator *TCustomEnumerator::Create(GCList &ls, TDictionary *dict) {
TCustomEnumerator *customEnum = new TCustomEnumerator(); return ls.Create<TCustomEnumerator>(dict);
customEnum->dict = dict;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(customEnum);
_gc->Watch(customEnum);
return customEnum;
} }
TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) { TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) {
std::string str; std::string str;
@@ -141,23 +119,16 @@ TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) {
} }
return nullptr; return nullptr;
} }
TVFSPathEnumerator::TVFSPathEnumerator(
Tesses::Framework::Filesystem::VFSPathEnumerator enumerator)
: enumerator(enumerator) {}
TVFSPathEnumerator *TVFSPathEnumerator::Create( TVFSPathEnumerator *TVFSPathEnumerator::Create(
GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) { GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) {
TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator(); return ls.Create<TVFSPathEnumerator>(enumerator);
vfspathe->enumerator = enumerator;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(vfspathe);
_gc->Watch(vfspathe);
return vfspathe;
} }
TVFSPathEnumerator *TVFSPathEnumerator::Create( TVFSPathEnumerator *TVFSPathEnumerator::Create(
GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) { GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) {
TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator(); return ls->Create<TVFSPathEnumerator>(enumerator);
vfspathe->enumerator = enumerator;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(vfspathe);
_gc->Watch(vfspathe);
return vfspathe;
} }
bool TVFSPathEnumerator::MoveNext(std::shared_ptr<GC> ls) { bool TVFSPathEnumerator::MoveNext(std::shared_ptr<GC> ls) {
return enumerator.MoveNext(); return enumerator.MoveNext();
@@ -165,25 +136,15 @@ bool TVFSPathEnumerator::MoveNext(std::shared_ptr<GC> ls) {
TObject TVFSPathEnumerator::GetCurrent(GCList &ls) { TObject TVFSPathEnumerator::GetCurrent(GCList &ls) {
return enumerator.Current; return enumerator.Current;
} }
TDictionaryEnumerator::TDictionaryEnumerator(TDictionary *dict)
: dict(dict), hasStarted(false) {}
TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList &ls, TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList &ls,
TDictionary *dict) { TDictionary *dict) {
TDictionaryEnumerator *dicte = new TDictionaryEnumerator(); return ls.Create<TDictionaryEnumerator>(dict);
dicte->dict = dict;
dicte->hasStarted = false;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(dicte);
_gc->Watch(dicte);
return dicte;
} }
TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList *ls, TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList *ls,
TDictionary *dict) { TDictionary *dict) {
TDictionaryEnumerator *dicte = new TDictionaryEnumerator(); return ls->Create<TDictionaryEnumerator>(dict);
dicte->dict = dict;
dicte->hasStarted = false;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(dicte);
_gc->Watch(dicte);
return dicte;
} }
bool TDictionaryEnumerator::MoveNext(std::shared_ptr<GC> ls) { bool TDictionaryEnumerator::MoveNext(std::shared_ptr<GC> ls) {
@@ -217,24 +178,13 @@ void TDictionaryEnumerator::Mark() {
this->marked = true; this->marked = true;
this->dict->Mark(); this->dict->Mark();
} }
TListEnumerator::TListEnumerator(TList *list) : ls(list), index(-1) {}
TListEnumerator *TListEnumerator::Create(GCList &ls, TList *list) { TListEnumerator *TListEnumerator::Create(GCList &ls, TList *list) {
TListEnumerator *liste = new TListEnumerator(); return ls.Create<TListEnumerator>(list);
liste->ls = list;
liste->index = -1;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(liste);
_gc->Watch(liste);
return liste;
} }
TListEnumerator *TListEnumerator::Create(GCList *ls, TList *list) { TListEnumerator *TListEnumerator::Create(GCList *ls, TList *list) {
TListEnumerator *liste = new TListEnumerator(); return ls->Create<TListEnumerator>(list);
liste->ls = list;
liste->index = -1;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(liste);
_gc->Watch(liste);
return liste;
} }
bool TListEnumerator::MoveNext(std::shared_ptr<GC> ls) { bool TListEnumerator::MoveNext(std::shared_ptr<GC> ls) {
this->index++; this->index++;
@@ -260,25 +210,17 @@ void TListEnumerator::Mark() {
this->ls->Mark(); this->ls->Mark();
} }
TAssociativeArrayEnumerator::TAssociativeArrayEnumerator(
TAssociativeArray *list)
: ls(list), index(-1) {}
TAssociativeArrayEnumerator * TAssociativeArrayEnumerator *
TAssociativeArrayEnumerator::Create(GCList &ls, TAssociativeArray *list) { TAssociativeArrayEnumerator::Create(GCList &ls, TAssociativeArray *list) {
TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator(); return ls.Create<TAssociativeArrayEnumerator>(list);
liste->ls = list;
liste->index = -1;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(liste);
_gc->Watch(liste);
return liste;
} }
TAssociativeArrayEnumerator * TAssociativeArrayEnumerator *
TAssociativeArrayEnumerator::Create(GCList *ls, TAssociativeArray *list) { TAssociativeArrayEnumerator::Create(GCList *ls, TAssociativeArray *list) {
TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator(); return ls->Create<TAssociativeArrayEnumerator>(list);
liste->ls = list;
liste->index = -1;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(liste);
_gc->Watch(liste);
return liste;
} }
bool TAssociativeArrayEnumerator::MoveNext(std::shared_ptr<GC> ls) { bool TAssociativeArrayEnumerator::MoveNext(std::shared_ptr<GC> ls) {
this->index++; this->index++;
@@ -305,26 +247,16 @@ void TAssociativeArrayEnumerator::Mark() {
this->marked = true; this->marked = true;
this->ls->Mark(); this->ls->Mark();
} }
TDynamicListEnumerator::TDynamicListEnumerator(TDynamicList *list)
: ls(list), index(-1) {}
TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList &ls, TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList &ls,
TDynamicList *list) { TDynamicList *list) {
TDynamicListEnumerator *liste = new TDynamicListEnumerator(); return ls.Create<TDynamicListEnumerator>(list);
liste->ls = list;
liste->index = -1;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(liste);
_gc->Watch(liste);
return liste;
} }
TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList *ls, TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList *ls,
TDynamicList *list) { TDynamicList *list) {
TDynamicListEnumerator *liste = new TDynamicListEnumerator(); return ls->Create<TDynamicListEnumerator>(list);
liste->ls = list;
liste->index = -1;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(liste);
_gc->Watch(liste);
return liste;
} }
bool TDynamicListEnumerator::MoveNext(std::shared_ptr<GC> ls) { bool TDynamicListEnumerator::MoveNext(std::shared_ptr<GC> ls) {
this->index++; this->index++;
@@ -351,24 +283,13 @@ void TDynamicListEnumerator::Mark() {
this->marked = true; this->marked = true;
this->ls->Mark(); this->ls->Mark();
} }
TStringEnumerator::TStringEnumerator(std::string str)
: str(str), hasStarted(false) {}
TStringEnumerator *TStringEnumerator::Create(GCList &ls, std::string str) { TStringEnumerator *TStringEnumerator::Create(GCList &ls, std::string str) {
TStringEnumerator *stre = new TStringEnumerator(); return ls.Create<TStringEnumerator>(str);
stre->str = str;
stre->hasStarted = false;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(stre);
_gc->Watch(stre);
return stre;
} }
TStringEnumerator *TStringEnumerator::Create(GCList *ls, std::string str) { TStringEnumerator *TStringEnumerator::Create(GCList *ls, std::string str) {
TStringEnumerator *stre = new TStringEnumerator(); return ls->Create<TStringEnumerator>(str);
stre->str = str;
stre->hasStarted = false;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(stre);
_gc->Watch(stre);
return stre;
} }
bool TStringEnumerator::MoveNext(std::shared_ptr<GC> ls) { bool TStringEnumerator::MoveNext(std::shared_ptr<GC> ls) {
if (!this->hasStarted) { if (!this->hasStarted) {
+214 -51
View File
@@ -1,20 +1,11 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TDynamicList::TDynamicList(TCallable *callable) : cb(callable) {}
TDynamicList *TDynamicList::Create(GCList &ls, TCallable *callable) { TDynamicList *TDynamicList::Create(GCList &ls, TCallable *callable) {
TDynamicList *list = new TDynamicList(); return ls.Create<TDynamicList>(callable);
list->cb = callable;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(list);
_gc->Watch(list);
return list;
} }
TDynamicList *TDynamicList::Create(GCList *ls, TCallable *callable) { TDynamicList *TDynamicList::Create(GCList *ls, TCallable *callable) {
TDynamicList *list = new TDynamicList(); return ls->Create<TDynamicList>(callable);
list->cb = callable;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(list);
_gc->Watch(list);
return list;
} }
void TDynamicList::Mark() { void TDynamicList::Mark() {
@@ -28,7 +19,7 @@ int64_t TDynamicList::Count(GCList &ls) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "Count"); dict->SetValue("Type", ls.FromString("Count"));
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
auto res = cb->Call(ls, {dict}); auto res = cb->Call(ls, {dict});
int64_t n; int64_t n;
@@ -40,7 +31,7 @@ TObject TDynamicList::Add(GCList &ls, TObject v) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "Add"); dict->SetValue("Type", ls.FromString("Add"));
dict->SetValue("Value", v); dict->SetValue("Value", v);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
return cb->Call(ls, {dict}); return cb->Call(ls, {dict});
@@ -49,7 +40,7 @@ TObject TDynamicList::Insert(GCList &ls, int64_t index, TObject v) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "Insert"); dict->SetValue("Type", ls.FromString("Insert"));
dict->SetValue("Index", index); dict->SetValue("Index", index);
dict->SetValue("Value", v); dict->SetValue("Value", v);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
@@ -58,14 +49,14 @@ TObject TDynamicList::Insert(GCList &ls, int64_t index, TObject v) {
TObject TDynamicList::Clear(GCList &ls) { TObject TDynamicList::Clear(GCList &ls) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "Clear"); dict->SetValue("Type", ls.FromString("Clear"));
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
return cb->Call(ls, {dict}); return cb->Call(ls, {dict});
} }
TObject TDynamicList::Remove(GCList &ls, TObject obj) { TObject TDynamicList::Remove(GCList &ls, TObject obj) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "Remove"); dict->SetValue("Type", ls.FromString("Remove"));
dict->SetValue("Value", obj); dict->SetValue("Value", obj);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
@@ -74,7 +65,7 @@ TObject TDynamicList::Remove(GCList &ls, TObject obj) {
TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) { TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "RemoveAllEqual"); dict->SetValue("Type", ls.FromString("RemoveAllEqual"));
dict->SetValue("Value", obj); dict->SetValue("Value", obj);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
@@ -83,7 +74,7 @@ TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) {
TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) { TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "RemoveAt"); dict->SetValue("Type", ls.FromString("RemoveAt"));
dict->SetValue("Index", index); dict->SetValue("Index", index);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
@@ -92,7 +83,7 @@ TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) {
TObject TDynamicList::ToString(GCList &ls) { TObject TDynamicList::ToString(GCList &ls) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "ToString"); dict->SetValue("Type", ls.FromString("ToString"));
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
return cb->Call(ls, {dict}); return cb->Call(ls, {dict});
@@ -102,7 +93,7 @@ TObject TDynamicList::GetAt(GCList &ls, int64_t index) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "GetAt"); dict->SetValue("Type", ls.FromString("GetAt"));
dict->SetValue("Index", index); dict->SetValue("Index", index);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
return cb->Call(ls, {dict}); return cb->Call(ls, {dict});
@@ -111,7 +102,7 @@ TObject TDynamicList::GetAt(GCList &ls, int64_t index) {
TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) { TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) {
auto dict = TDictionary::Create(ls); auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
dict->SetValue("Type", "SetAt"); dict->SetValue("Type", ls.FromString("SetAt"));
dict->SetValue("Index", index); dict->SetValue("Index", index);
dict->SetValue("Value", val); dict->SetValue("Value", val);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
@@ -120,35 +111,10 @@ TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) {
TDynamicList::~TDynamicList() {} TDynamicList::~TDynamicList() {}
TByteArray *TByteArray::Create(GCList &ls) { TByteArray *TByteArray::Create(GCList &ls) { return ls.Create<TByteArray>(); }
TByteArray *arr = new TByteArray();
std::shared_ptr<GC> _gc = ls.GetGC(); TByteArray *TByteArray::Create(GCList *ls) { return ls->Create<TByteArray>(); }
ls.Add(arr);
_gc->Watch(arr);
return arr;
}
TByteArray *TByteArray::Create(GCList *ls) {
TByteArray *arr = new TByteArray();
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(arr);
_gc->Watch(arr);
return arr;
}
TList *TList::Create(GCList *gc) {
TList *list = new TList();
std::shared_ptr<GC> _gc = gc->GetGC();
gc->Add(list);
_gc->Watch(list);
return list;
}
TList *TList::Create(GCList &gc) {
TList *list = new TList();
std::shared_ptr<GC> _gc = gc.GetGC();
gc.Add(list);
_gc->Watch(list);
return list;
}
void TList::Add(TObject value) { this->items.push_back(value); } void TList::Add(TObject value) { this->items.push_back(value); }
void TList::Set(int64_t index, TObject value) { void TList::Set(int64_t index, TObject value) {
if (index >= 0 && index < this->Count()) { if (index >= 0 && index < this->Count()) {
@@ -161,7 +127,7 @@ TObject TList::Get(int64_t index) {
} }
return Undefined(); return Undefined();
} }
int64_t TList::Count() { return (int64_t)this->items.size(); } int64_t TList::Count() { return this->items.size(); }
void TList::Insert(int64_t index, TObject value) { void TList::Insert(int64_t index, TObject value) {
if (index >= 0 && index <= this->Count()) { if (index >= 0 && index <= this->Count()) {
this->items.insert(this->items.begin() + index, value); this->items.insert(this->items.begin() + index, value);
@@ -181,4 +147,201 @@ void TList::Mark() {
GC::Mark(item); GC::Mark(item);
} }
} }
std::string TList::TypeName() { return "List"; }
bool TList::opGetField(InterperterThread *thrd, std::shared_ptr<GC> gc,
const std::string &name) {
auto &cse = thrd->call_stack_entries;
if (name == "Count" || name == "Length") {
int64_t len = this->Count();
if (len < 0)
len = 0;
cse.back()->Push(gc, len);
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
bool TList::opExecuteMethod(InterperterThread *thrd, std::shared_ptr<GC> gc,
const std::string &name,
const std::vector<TObject> &args) {
auto &cse = thrd->call_stack_entries;
GCList ls(gc);
if (name == "GetEnumerator") {
cse.back()->Push(gc, ls.Create<TListEnumerator>(this));
return false;
} else if (name == "ToString") {
cse.back()->Push(gc, Json_Encode(this));
return false;
} else if (name == "Insert") {
if (args.size() != 2) {
throw VMException("List.Insert must only accept two arguments");
}
int64_t index;
if (!GetArgument(args, 0, index)) {
throw VMException("List.Insert first argument must be Long");
}
gc->BarrierBegin();
this->Insert(index, args[1]);
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (name == "Add") {
if (args.size() != 1) {
throw VMException("List.Add must only accept one argument");
}
gc->BarrierBegin();
this->Add(args[0]);
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (name == "Contains") {
if (args.size() != 1) {
throw VMException("List.Contains must only accept one argument");
}
gc->BarrierBegin();
for (int64_t i = 0; i < this->Count(); i++) {
auto item = this->Get(i);
gc->BarrierEnd();
if (Equals(gc, args[0], item)) {
cse.back()->Push(gc, true);
return false;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, false);
return false;
} else if (name == "IndexOf") {
// IndexOf(obj, $idx)
if (args.size() < 1 || args.size() > 2) {
throw VMException("List.IndexOf must either have one "
"or two arguments");
}
int64_t i = 0;
GetArgument(args, 1, i);
gc->BarrierBegin();
for (; i < this->Count(); i++) {
auto item = this->Get(i);
gc->BarrierEnd();
if (Equals(gc, args[0], item)) {
cse.back()->Push(gc, i);
return false;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, (int64_t)-1);
return false;
} else if (name == "RemoveAllEqual") {
if (args.size() != 1) {
throw VMException("List.RemoveAllEqual must only "
"accept one argument");
}
gc->BarrierBegin();
for (int64_t i = 0; i < this->Count(); i++) {
auto item = this->Get(i);
gc->BarrierEnd();
if (Equals(gc, args[0], item)) {
gc->BarrierBegin();
this->RemoveAt(i);
i--;
} else
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (name == "Remove") {
if (args.size() != 1) {
throw VMException("List.Remove must only accept one argument");
}
gc->BarrierBegin();
for (int64_t i = 0; i < this->Count(); i++) {
auto item = this->Get(i);
gc->BarrierEnd();
if (Equals(gc, args[0], item)) {
gc->BarrierBegin();
this->RemoveAt(i);
gc->BarrierEnd();
break;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (name == "RemoveAt") {
if (args.size() != 1) {
throw VMException("List.RemoveAt must only accept one argument");
}
if (!std::holds_alternative<int64_t>(args[0])) {
throw VMException("List.RemoveAt must only accept a long");
}
gc->BarrierBegin();
this->RemoveAt(std::get<int64_t>(args[0]));
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (name == "Clear") {
gc->BarrierBegin();
this->Clear();
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (name == "GetAt") {
if (args.size() != 1) {
throw VMException("List.GetAt must only accept one argument");
}
if (!std::holds_alternative<int64_t>(args[0])) {
throw VMException("List.GetAt must only accept a long");
}
int64_t index = std::get<int64_t>(args[0]);
if (index >= 0 && index < this->Count()) {
cse.back()->Push(gc, this->Get(index));
return false;
}
} else if (name == "SetAt") {
if (args.size() != 2) {
throw VMException("List.SetAt must only accept two arguments");
}
if (!std::holds_alternative<int64_t>(args[0])) {
throw VMException("List.SetAt first argument must only "
"accept a long");
}
int64_t index = std::get<int64_t>(args[0]);
if (index >= 0 && index < this->Count()) {
this->Set(index, args[1]);
return false;
}
}
else if (name == "Count" || name == "Length") {
gc->BarrierBegin();
cse.back()->Push(gc, this->Count());
gc->BarrierEnd();
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
}; // namespace Tesses::CrossLang }; // namespace Tesses::CrossLang
+4 -13
View File
@@ -1,7 +1,6 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TNativeObject::~TNativeObject() {}
TNative::TNative(void *ptr, std::function<void(void *)> destroy) { TNative::TNative(void *ptr, std::function<void(void *)> destroy) {
this->ptr = ptr; this->ptr = ptr;
@@ -27,26 +26,18 @@ void TNative::Destroy() {
} }
bool TNativeObject::ToBool() { return true; } bool TNativeObject::ToBool() { return true; }
bool TNativeObject::Equals(std::shared_ptr<GC> gc, TObject right) { bool TNativeObject::Equals(std::shared_ptr<GC> gc, TObject right) {
if (std::holds_alternative<THeapObjectHolder>(right)) { if (std::holds_alternative<THeapObject *>(right)) {
return this == std::get<THeapObjectHolder>(right).obj; return this == std::get<THeapObject *>(right);
} }
return false; return false;
} }
TNative *TNative::Create(GCList &ls, void *ptr, TNative *TNative::Create(GCList &ls, void *ptr,
std::function<void(void *)> destroy) { std::function<void(void *)> destroy) {
TNative *native = new TNative(ptr, destroy); return ls.Create<TNative>(ptr, destroy);
std::shared_ptr<GC> gc = ls.GetGC();
ls.Add(native);
gc->Watch(native);
return native;
} }
TNative *TNative::Create(GCList *ls, void *ptr, TNative *TNative::Create(GCList *ls, void *ptr,
std::function<void(void *)> destroy) { std::function<void(void *)> destroy) {
TNative *native = new TNative(ptr, destroy); return ls->Create<TNative>(ptr, destroy);
std::shared_ptr<GC> gc = ls->GetGC();
ls->Add(native);
gc->Watch(native);
return native;
} }
TNative::~TNative() { this->Destroy(); } TNative::~TNative() { this->Destroy(); }
+3 -11
View File
@@ -32,7 +32,7 @@ TList *TQueryable::ToList(GCList &ls) {
auto enumerator = this->GetEnumerator(ls); auto enumerator = this->GetEnumerator(ls);
if (enumerator == nullptr) if (enumerator == nullptr)
return nullptr; return nullptr;
auto list = TList::Create(ls); auto list = ls.Create<TList>();
while (enumerator->MoveNext(gc)) { while (enumerator->MoveNext(gc)) {
gc->BarrierBegin(); gc->BarrierBegin();
list->Add(enumerator->GetCurrent(ls)); list->Add(enumerator->GetCurrent(ls));
@@ -41,19 +41,11 @@ TList *TQueryable::ToList(GCList &ls) {
return list; return list;
} }
TQueryable *TQueryable::Create(GCList &ls, TObject parent) { TQueryable *TQueryable::Create(GCList &ls, TObject parent) {
TQueryable *queryable = new TQueryable(parent); return ls.Create<TQueryable>(parent);
std::shared_ptr<GC> gc = ls.GetGC();
ls.Add(queryable);
gc->Watch(queryable);
return queryable;
} }
TQueryable *TQueryable::Create(GCList &ls, TObject parent, TQueryableMode mode, TQueryable *TQueryable::Create(GCList &ls, TObject parent, TQueryableMode mode,
std::vector<TObject> args) { std::vector<TObject> args) {
TQueryable *queryable = new TQueryable(parent, mode, args); return ls.Create<TQueryable>(parent, mode, args);
std::shared_ptr<GC> gc = ls.GetGC();
ls.Add(queryable);
gc->Watch(queryable);
return queryable;
} }
void TQueryable::Mark() { void TQueryable::Mark() {
+6 -2
View File
@@ -16,8 +16,12 @@ TObject TRandom::CallMethod(GCList &ls, std::string name,
return (int64_t)random.Next((uint32_t)first); return (int64_t)random.Next((uint32_t)first);
} }
{
return random.Next(); uint64_t num = random.Next();
int64_t val2 = 0;
memcpy(&val2, &num, sizeof(int64_t));
return val2;
}
} }
if (name == "NextByte") { if (name == "NextByte") {
+14 -22
View File
@@ -9,12 +9,11 @@ void ThrowConstError(std::string key) {
void TEnvironment::DeclareConstVariable(std::string key, TObject value) { void TEnvironment::DeclareConstVariable(std::string key, TObject value) {
this->DeclareVariable(key, value); this->DeclareVariable(key, value);
this->consts.push_back(key); this->decls[key] = TEnvironmentDeclType::TEDT_CONST;
} }
bool TEnvironment::HasConstForDeclare(std::string key) { bool TEnvironment::HasConstForDeclare(std::string key) {
for (auto item : this->consts) if (this->decls.count(key) > 0)
if (item == key) return this->decls[key] == TEnvironmentDeclType::TEDT_CONST;
return true;
return false; return false;
} }
bool TEnvironment::HasConstForSet(std::string key) { bool TEnvironment::HasConstForSet(std::string key) {
@@ -172,9 +171,8 @@ void TEnvironment::DeclareVariable(std::shared_ptr<GC> gc,
TObject v = this->GetVariable(name[0]); TObject v = this->GetVariable(name[0]);
TDictionary *dict = nullptr; TDictionary *dict = nullptr;
if (std::holds_alternative<THeapObjectHolder>(v)) { if (std::holds_alternative<THeapObject *>(v)) {
dict = dict = dynamic_cast<TDictionary *>(std::get<THeapObject *>(v));
dynamic_cast<TDictionary *>(std::get<THeapObjectHolder>(v).obj);
if (dict == nullptr) { if (dict == nullptr) {
dict = TDictionary::Create(ls); dict = TDictionary::Create(ls);
gc->BarrierBegin(); gc->BarrierBegin();
@@ -192,9 +190,9 @@ void TEnvironment::DeclareVariable(std::shared_ptr<GC> gc,
gc->BarrierBegin(); gc->BarrierBegin();
auto v = dict->GetValue(name[i]); auto v = dict->GetValue(name[i]);
gc->BarrierEnd(); gc->BarrierEnd();
if (std::holds_alternative<THeapObjectHolder>(v)) { if (std::holds_alternative<THeapObject *>(v)) {
auto dict2 = dynamic_cast<TDictionary *>( auto dict2 =
std::get<THeapObjectHolder>(v).obj); dynamic_cast<TDictionary *>(std::get<THeapObject *>(v));
if (dict2 == nullptr) { if (dict2 == nullptr) {
dict2 = TDictionary::Create(ls); dict2 = TDictionary::Create(ls);
gc->BarrierBegin(); gc->BarrierBegin();
@@ -308,13 +306,15 @@ void TRootEnvironment::SetVariable(std::string key, TObject value) {
this->dict->SetValue(key, value); this->dict->SetValue(key, value);
} }
void TRootEnvironment::DeclareVariable(std::string key, TObject value) { void TRootEnvironment::DeclareVariable(std::string key, TObject value) {
if (this->decls.count(key) == 0)
this->decls[key] = TEnvironmentDeclType::TEDT_VAR;
return this->dict->SetValue(key, value); return this->dict->SetValue(key, value);
} }
bool TRootEnvironment::HasVariable(std::string key) { bool TRootEnvironment::HasVariable(std::string key) {
return this->dict->HasValue(key); return this->dict->HasValue(key) || this->decls.count(key) > 0;
} }
bool TRootEnvironment::HasVariableRecurse(std::string key) { bool TRootEnvironment::HasVariableRecurse(std::string key) {
return this->dict->HasValue(key); return this->dict->HasValue(key) || this->decls.count(key) > 0;
} }
TEnvironment *TRootEnvironment::GetParentEnvironment() { return this; } TEnvironment *TRootEnvironment::GetParentEnvironment() { return this; }
TRootEnvironment *TRootEnvironment::GetRootEnvironment() { return this; } TRootEnvironment *TRootEnvironment::GetRootEnvironment() { return this; }
@@ -338,18 +338,10 @@ void TRootEnvironment::Mark() {
cls.first->Mark(); cls.first->Mark();
} }
TRootEnvironment *TRootEnvironment::Create(GCList *gc, TDictionary *dict) { TRootEnvironment *TRootEnvironment::Create(GCList *gc, TDictionary *dict) {
TRootEnvironment *env = new TRootEnvironment(dict); return gc->Create<TRootEnvironment>(dict);
std::shared_ptr<GC> _gc = gc->GetGC();
gc->Add(env);
_gc->Watch(env);
return env;
} }
TRootEnvironment *TRootEnvironment::Create(GCList &gc, TDictionary *dict) { TRootEnvironment *TRootEnvironment::Create(GCList &gc, TDictionary *dict) {
TRootEnvironment *env = new TRootEnvironment(dict); return gc.Create<TRootEnvironment>(dict);
std::shared_ptr<GC> _gc = gc.GetGC();
gc.Add(env);
_gc->Watch(env);
return env;
} }
bool TRootEnvironment::HandleException(std::shared_ptr<GC> gc, bool TRootEnvironment::HandleException(std::shared_ptr<GC> gc,
+30
View File
@@ -0,0 +1,30 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang {
TMemoryStream::TMemoryStream(
std::shared_ptr<Tesses::Framework::Streams::MemoryStream> strm)
: strm(strm) {}
std::shared_ptr<Tesses::Framework::Streams::Stream> TMemoryStream::GetStream() {
return this->strm;
}
TObject TMemoryStream::CallMethod(InterperterThread *thrd, GCList &ls,
const std::string &name,
const std::vector<TObject> &args) {
if (name == "GetBytes") {
return ls.Create<TMemoryStreamMutByteView>(strm);
}
return ITStream::CallMethod(thrd, ls, name, args);
}
TMemoryStreamMutByteView::TMemoryStreamMutByteView(
std::shared_ptr<Tesses::Framework::Streams::MemoryStream> strm)
: strm(strm) {}
std::pair<uint8_t *, size_t> TMemoryStreamMutByteView::GetMutableBounds() {
if (!strm)
return std::pair<uint8_t *, size_t>(nullptr, 0);
auto &buff = strm->GetBuffer();
return std::pair<uint8_t *, size_t>(buff.data(), buff.size());
}
std::string TMemoryStream::TypeName() { return "MemoryStream"; }
} // namespace Tesses::CrossLang
+165
View File
@@ -0,0 +1,165 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang {
TNetworkStream::TNetworkStream(
std::shared_ptr<Tesses::Framework::Streams::NetworkStream> strm)
: strm(strm) {}
std::shared_ptr<Tesses::Framework::Streams::Stream>
TNetworkStream::GetStream() {
return this->strm;
}
TObject TNetworkStream::CallMethod(InterperterThread *thrd, GCList &ls,
const std::string &name,
const std::vector<TObject> &args) {
int64_t n0;
bool bc;
if (name == "setBroadcast" && GetArgument(args, 0, bc))
strm->SetBroadcast(bc);
if (name == "setNoDelay" && GetArgument(args, 0, bc))
strm->SetNoDelay(bc);
if (name == "setReuseAddress" && GetArgument(args, 0, bc))
strm->SetReuseAddress(bc);
if (name == "setReusePort" && GetArgument(args, 0, bc))
strm->SetReusePort(bc);
if (name == "MulticastTTL" && GetArgument(args, 0, n0))
strm->SetMulticastTTL((uint8_t)n0);
if (name == "getPort" || name == "GetPort") {
return (int64_t)strm->GetPort();
}
if (name == "SetMulticastMembership") {
std::string ma;
std::string ifaceIP = "0.0.0.0";
if (GetArgument(args, 0, ma)) {
GetArgument(args, 1, ifaceIP);
strm->SetMulticastMembership(ma, ifaceIP);
}
return Undefined();
}
if (name == "Bind") {
std::string ip;
int64_t port;
if (GetArgument(args, 0, ip) && GetArgument(args, 1, port))
strm->Bind(ip, (uint16_t)port);
return Undefined();
}
if (name == "Accept") {
std::string ip;
uint16_t port;
auto strm2 = strm->Accept(ip, port);
if (strm2 ==
nullptr) // just in case, so we don't get a bugged TNetworkStream
return nullptr;
std::array list = {
TDItem("IP", ls.FromString(ip)),
TDItem("Port", (int64_t)port),
TDItem("Stream", ls.Create<TNetworkStream>(strm2)),
};
return ls.Create<TDictionary>(list.begin(), list.end());
}
if (name == "Listen") {
int64_t backlog;
if (GetArgument(args, 0, backlog)) {
strm->Listen((int32_t)backlog);
} else {
strm->Listen(10);
}
return Undefined();
}
if (name == "ReadFrom") {
TByteArray *data;
int64_t offset;
int64_t length;
if (name == "Read") {
TMutByteView *bytes;
if (GetArgumentHeap(args, 0, bytes)) {
int64_t offset;
int64_t length;
if (GetArgument(args, 1, offset) &&
GetArgument(args, 2, length)) {
auto safe = bytes->GetMutableBoundsConstrained(
(size_t)offset, (size_t)length);
if (safe.first != nullptr) {
std::string ip = {};
uint16_t port = 0;
auto read =
strm->ReadFrom(safe.first, safe.second, ip, port);
std::array list = {
TDItem("IP", ls.FromString(ip)),
TDItem("Port", (int64_t)port),
TDItem("Read", (int64_t)read),
};
return ls.Create<TDictionary>(list.begin(), list.end());
} else {
return nullptr;
}
}
auto bounds = bytes->GetMutableBounds();
if (bounds.first) {
std::string ip = {};
uint16_t port = 0;
auto read =
strm->ReadFrom(bounds.first, bounds.second, ip, port);
std::array list = {
TDItem("IP", ls.FromString(ip)),
TDItem("Port", (int64_t)port),
TDItem("Read", (int64_t)read),
};
return ls.Create<TDictionary>(list.begin(), list.end());
}
}
return Undefined();
}
}
if (name == "WriteTo") {
// strm->WriteTo(buff, ip, port)
// strm->WriteTo(buff, off, len, ip, port)
TByteView *bytes;
if (GetArgumentHeap(args, 0, bytes)) {
int64_t offset;
int64_t length;
TString *ip;
int64_t port;
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
if (!(GetArgumentHeap(args, 3, ip) &&
GetArgument(args, 4, port)))
return Undefined();
auto safe =
bytes->GetBoundsConstrained((size_t)offset, (size_t)length);
if (safe.first != nullptr) {
return strm->WriteTo(safe.first, safe.second,
ip->GetString(), (uint16_t)port);
} else
return nullptr;
}
if (!(GetArgumentHeap(args, 1, ip) && GetArgument(args, 2, port)))
return Undefined();
auto bounds = bytes->GetBounds();
if (bounds.first) {
return (int64_t)strm->WriteTo(bounds.first, bounds.second,
ip->GetString(), (uint16_t)port);
}
}
return Undefined();
}
return ITStream::CallMethod(thrd, ls, name, args);
}
std::string TNetworkStream::TypeName() { return "NetworkStream"; }
} // namespace Tesses::CrossLang
+251
View File
@@ -0,0 +1,251 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang {
#define CROSSLANG_TSTREAM_NAMES \
CROSSLANG_TSTREAM_NAME_ENT(getCanRead) \
CROSSLANG_TSTREAM_NAME_ENT(getCanSeek) \
CROSSLANG_TSTREAM_NAME_ENT(getCanWrite) \
CROSSLANG_TSTREAM_NAME_ENT(getEndOfStream) \
CROSSLANG_TSTREAM_NAME_ENT(getLength) \
CROSSLANG_TSTREAM_NAME_ENT(getPosition) \
CROSSLANG_TSTREAM_NAME_ENT(setPosition) \
CROSSLANG_TSTREAM_NAME_ENT(Close) \
CROSSLANG_TSTREAM_NAME_ENT(Dispose) \
CROSSLANG_TSTREAM_NAME_ENT(CopyTo) \
CROSSLANG_TSTREAM_NAME_ENT(CopyToLimit) \
CROSSLANG_TSTREAM_NAME_ENT(Flush) \
CROSSLANG_TSTREAM_NAME_ENT(Read) \
CROSSLANG_TSTREAM_NAME_ENT(ReadBlock) \
CROSSLANG_TSTREAM_NAME_ENT(ReadByte) \
CROSSLANG_TSTREAM_NAME_ENT(Seek) \
CROSSLANG_TSTREAM_NAME_ENT(SetRecvTimeout) \
CROSSLANG_TSTREAM_NAME_ENT(SetSendTimeout) \
CROSSLANG_TSTREAM_NAME_ENT(Write) \
CROSSLANG_TSTREAM_NAME_ENT(WriteText) \
CROSSLANG_TSTREAM_NAME_ENT(WriteBlock) \
CROSSLANG_TSTREAM_NAME_ENT(WriteByte)
enum TStreamFuncNameEnum {
#define CROSSLANG_TSTREAM_NAME_ENT(name) TSF_##name,
CROSSLANG_TSTREAM_NAMES
#undef CROSSLANG_TSTREAM_NAME_ENT
}; // namespace Tesses::CrossLang
static std::unordered_map<std::string_view, TStreamFuncNameEnum>
stream_func_names = {
#define CROSSLANG_TSTREAM_NAME_ENT(name) {#name, TSF_##name},
CROSSLANG_TSTREAM_NAMES
#undef CROSSLANG_TSTREAM_NAME_ENT
};
bool ITStream::Exists(std::string_view str) {
return stream_func_names.count(str) != 0;
}
TObject ITStream::CallMethod(InterperterThread *thrd, GCList &ls,
const std::string &name,
const std::vector<TObject> &args) {
auto strm = GetStream();
if (strm == nullptr)
return Undefined();
auto result = stream_func_names.find(name);
if (result == stream_func_names.end())
return Undefined();
switch (result->second) {
case TSF_getCanRead:
return strm->CanRead();
case TSF_getCanSeek:
return strm->CanSeek();
case TSF_getCanWrite:
return strm->CanWrite();
case TSF_getEndOfStream:
return strm->EndOfStream();
case TSF_getLength:
return strm->GetLength();
case TSF_getPosition:
return strm->GetPosition();
case TSF_setPosition: {
int64_t n;
if (GetArgument(args, 0, n)) {
strm->Seek(n, Tesses::Framework::Streams::SeekOrigin::Begin);
return n;
}
return Undefined();
}
case TSF_Close:
case TSF_Dispose:
strm->Close();
return Undefined();
case TSF_CopyTo: {
ITStream *strmDest;
if (GetArgumentHeap(args, 0, strmDest)) {
int64_t n = 1024;
GetArgument(args, 1, n);
strm->CopyTo(strmDest->GetStream(), (size_t)n);
}
return Undefined();
}
case TSF_CopyToLimit: {
ITStream *strmDest;
int64_t len;
if (GetArgumentHeap(args, 0, strmDest) && GetArgument(args, 1, len)) {
int64_t n = 1024;
GetArgument(args, 2, n);
strm->CopyToLimit(strmDest->GetStream(), (uint64_t)len, (size_t)n);
}
return Undefined();
}
case TSF_Flush:
strm->Flush();
return Undefined();
case TSF_Read: {
TMutByteView *bytes;
if (GetArgumentHeap(args, 0, bytes)) {
int64_t offset;
int64_t length;
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
auto safe = bytes->GetMutableBoundsConstrained((size_t)offset,
(size_t)length);
if (safe.first != nullptr)
return strm->Read(safe.first, safe.second);
else
return 0;
}
auto bounds = bytes->GetMutableBounds();
if (bounds.first) {
return (int64_t)strm->Read(bounds.first, bounds.second);
}
}
return Undefined();
}
case TSF_ReadBlock: {
TMutByteView *bytes;
if (GetArgumentHeap(args, 0, bytes)) {
int64_t offset;
int64_t length;
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
auto safe = bytes->GetMutableBoundsConstrained((size_t)offset,
(size_t)length);
if (safe.first != nullptr)
return strm->ReadBlock(safe.first, safe.second);
else
return 0;
}
auto bounds = bytes->GetMutableBounds();
if (bounds.first) {
return (int64_t)strm->ReadBlock(bounds.first, bounds.second);
}
}
return Undefined();
}
case TSF_ReadByte: {
return (int64_t)strm->ReadByte();
}
case TSF_Seek: {
int64_t offset;
int64_t whence;
if (GetArgument(args, 0, offset) && GetArgument(args, 1, whence)) {
strm->Seek(offset, (Tesses::Framework::Streams::SeekOrigin)whence);
}
return Undefined();
}
case TSF_SetRecvTimeout: {
int64_t to;
if (GetArgument(args, 0, to)) {
strm->SetRecvTimeout((uint64_t)to);
}
return Undefined();
}
case TSF_SetSendTimeout: {
int64_t to;
if (GetArgument(args, 0, to)) {
strm->SetSendTimeout((uint64_t)to);
}
return Undefined();
}
case TSF_Write: {
TByteView *bytes;
if (GetArgumentHeap(args, 0, bytes)) {
int64_t offset;
int64_t length;
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
auto safe =
bytes->GetBoundsConstrained((size_t)offset, (size_t)length);
if (safe.first != nullptr)
return strm->Write(safe.first, safe.second);
else
return 0;
}
auto bounds = bytes->GetBounds();
if (bounds.first) {
return (int64_t)strm->Write(bounds.first, bounds.second);
}
}
return Undefined();
}
case TSF_WriteText: { // for compat
TByteView *bytes;
if (GetArgumentHeap(args, 0, bytes)) {
auto bounds = bytes->GetBounds();
if (bounds.first)
strm->WriteBlock(bounds.first, bounds.second);
}
return Undefined();
}
case TSF_WriteBlock: {
TByteView *bytes;
if (GetArgumentHeap(args, 0, bytes)) {
int64_t offset;
int64_t length;
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
auto safe =
bytes->GetBoundsConstrained((size_t)offset, (size_t)length);
if (safe.first != nullptr)
strm->WriteBlock(safe.first, safe.second);
return Undefined();
}
auto bounds = bytes->GetBounds();
if (bounds.first) {
strm->WriteBlock(bounds.first, bounds.second);
}
}
return Undefined();
}
case TSF_WriteByte: {
int64_t b0;
if (GetArgument(args, 0, b0)) {
strm->WriteByte((uint8_t)b0);
}
return Undefined();
}
}
return Undefined();
}
std::string ITStream::TypeName() { return "Stream"; }
TStream::TStream(std::shared_ptr<Tesses::Framework::Streams::Stream> strm)
: strm(strm) {}
std::shared_ptr<Tesses::Framework::Streams::Stream> TStream::GetStream() {
return this->strm;
}
} // namespace Tesses::CrossLang
+56
View File
@@ -0,0 +1,56 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang {
TObjectStreamWrapper::TObjectStreamWrapper(std::shared_ptr<TObjectStream> strm)
: strm(strm) {}
TObject TObjectStreamWrapper::CallMethod(InterperterThread *thrd, GCList &ls,
const std::string &name,
const std::vector<TObject> &args) {
if (Exists(name)) {
return ITStream::CallMethod(thrd, ls, name, args);
}
TDictionary *dict;
if (GetObjectHeap(strm->obj, dict)) {
auto val = dict->GetValue(name);
TCallable *call;
if (GetObjectHeap(val, call)) {
auto closure = dynamic_cast<TClosure *>(call);
if (closure && !closure->closure->args.empty() &&
closure->closure->args[0]->GetString() == "this") {
std::vector<TObject> args_new;
args_new.reserve(args.size() + 1);
args_new.push_back(dict);
args_new.insert(args_new.cend(), args.begin(), args.end());
return closure->Call(ls, args_new);
} else {
return call->Call(ls, args);
}
}
if (name.size() > 3 && name[1] == 'e' && name[2] == 't') {
char c = name[0];
if (c == 'g') {
auto fieldName = name.substr(3);
return dict->GetValue(fieldName);
} else if (c == 's' && !args.empty()) {
auto fieldName = name.substr(3);
dict->SetValue(fieldName, args[0]);
ls.Add(args[0]);
return args[0];
}
}
}
return Undefined();
}
std::shared_ptr<Tesses::Framework::Streams::Stream>
TObjectStreamWrapper::GetStream() {
return this->strm;
}
std::string TObjectStreamWrapper::TypeName() { return "CustomStream"; }
} // namespace Tesses::CrossLang
+13 -13
View File
@@ -82,16 +82,24 @@ TObject TSubEnvironment::GetVariable(std::string key) {
if (this->dict->HasValue(key)) { if (this->dict->HasValue(key)) {
return this->dict->GetValue(key); return this->dict->GetValue(key);
} }
if (this->decls.count(key) > 0 &&
this->decls[key] == TEnvironmentDeclType::TEDT_VAR) {
return Undefined();
}
if (this->env->HasVariableRecurse(key)) { if (this->env->HasVariableRecurse(key)) {
return this->env->GetVariable(key); return this->env->GetVariable(key);
} }
return Undefined(); return Undefined();
} }
void TSubEnvironment::DeclareVariable(std::string key, TObject value) { void TSubEnvironment::DeclareVariable(std::string key, TObject value) {
if (this->decls.count(key) == 0)
this->decls[key] = TEnvironmentDeclType::TEDT_VAR;
this->dict->SetValue(key, value); this->dict->SetValue(key, value);
} }
void TSubEnvironment::SetVariable(std::string key, TObject value) { void TSubEnvironment::SetVariable(std::string key, TObject value) {
if (this->dict->HasValue(key)) {
if (this->dict->HasValue(key) || this->decls.count(key) > 0) {
this->dict->SetValue(key, value); this->dict->SetValue(key, value);
return; return;
} }
@@ -102,10 +110,10 @@ void TSubEnvironment::SetVariable(std::string key, TObject value) {
} }
} }
bool TSubEnvironment::HasVariable(std::string key) { bool TSubEnvironment::HasVariable(std::string key) {
return this->dict->HasValue(key); return this->dict->HasValue(key) || this->decls.count(key) > 0;
} }
bool TSubEnvironment::HasVariableRecurse(std::string key) { bool TSubEnvironment::HasVariableRecurse(std::string key) {
if (this->dict->HasValue(key)) if (this->dict->HasValue(key) || this->decls.count(key) > 0)
return true; return true;
return this->env->HasVariableRecurse(key); return this->env->HasVariableRecurse(key);
} }
@@ -159,19 +167,11 @@ TSubEnvironment *TEnvironment::GetSubEnvironment(GCList &gc) {
} }
TSubEnvironment *TSubEnvironment::Create(GCList *gc, TEnvironment *env, TSubEnvironment *TSubEnvironment::Create(GCList *gc, TEnvironment *env,
TDictionary *dict) { TDictionary *dict) {
TSubEnvironment *senv = new TSubEnvironment(env, dict); return gc->Create<TSubEnvironment>(env, dict);
std::shared_ptr<GC> _gc = gc->GetGC();
gc->Add(senv);
_gc->Watch(senv);
return senv;
} }
TSubEnvironment *TSubEnvironment::Create(GCList &gc, TEnvironment *env, TSubEnvironment *TSubEnvironment::Create(GCList &gc, TEnvironment *env,
TDictionary *dict) { TDictionary *dict) {
TSubEnvironment *senv = new TSubEnvironment(env, dict); return gc.Create<TSubEnvironment>(env, dict);
std::shared_ptr<GC> _gc = gc.GetGC();
gc.Add(senv);
_gc->Watch(senv);
return senv;
} }
TEnvironment *TSubEnvironment::GetParentEnvironment() { return this->env; } TEnvironment *TSubEnvironment::GetParentEnvironment() { return this->env; }
TRootEnvironment *TSubEnvironment::GetRootEnvironment() { TRootEnvironment *TSubEnvironment::GetRootEnvironment() {
+12 -2
View File
@@ -119,8 +119,17 @@ bool InterperterThread::Add(std::shared_ptr<GC> gc) {
str.append(std::get<std::string>(left)); str.append(std::get<std::string>(left));
str.push_back(std::get<char>(right)); str.push_back(std::get<char>(right));
cse.back()->Push(gc, str); cse.back()->Push(gc, str);
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
if (obj == nullptr) {
cse.back()->Push(gc, Undefined());
return false;
}
return obj->opAdd(this, gc, right);
/*
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
auto natObj = dynamic_cast<TNativeObject *>(obj); auto natObj = dynamic_cast<TNativeObject *>(obj);
@@ -156,6 +165,7 @@ bool InterperterThread::Add(std::shared_ptr<GC> gc) {
} else { } else {
cse.back()->Push(gc, Undefined()); cse.back()->Push(gc, Undefined());
} }
*/
} else { } else {
cse.back()->Push(gc, Undefined()); cse.back()->Push(gc, Undefined());
+18 -21
View File
@@ -14,8 +14,7 @@ namespace Tesses::CrossLang {
bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) { bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
GCList ls(gc); GCList ls(gc);
if (std::holds_alternative<std::nullptr_t>(left) && if (IsNull(left) && IsNull(right)) {
std::holds_alternative<std::nullptr_t>(right)) {
return true; return true;
} }
@@ -92,8 +91,8 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
auto r = std::get<Tesses::Framework::Uuid>(right); auto r = std::get<Tesses::Framework::Uuid>(right);
return l == r; return l == r;
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -109,12 +108,12 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
if (GetObjectHeap(obj, callable)) { if (GetObjectHeap(obj, callable)) {
return ToBool(callable->Call(ls, {right})); return ToBool(callable->Call(ls, {right}));
} else if (std::holds_alternative<std::nullptr_t>(right)) { } else if (IsNull(right)) {
return false; return false;
} else if (std::holds_alternative<Undefined>(right)) { } else if (std::holds_alternative<Undefined>(right)) {
return false; return false;
} else if (std::holds_alternative<THeapObjectHolder>(right)) { } else if (std::holds_alternative<THeapObject *>(right)) {
return cls == std::get<THeapObjectHolder>(right).obj; return cls == std::get<THeapObject *>(right);
} }
} else if (natObj != nullptr) { } else if (natObj != nullptr) {
return natObj->Equals(gc, right); return natObj->Equals(gc, right);
@@ -124,10 +123,10 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
TObject fn = dict->GetValue("operator=="); TObject fn = dict->GetValue("operator==");
gc->BarrierEnd(); gc->BarrierEnd();
if (!std::holds_alternative<Undefined>(fn)) { if (!std::holds_alternative<Undefined>(fn)) {
if (std::holds_alternative<THeapObjectHolder>(fn)) { if (std::holds_alternative<THeapObject *>(fn)) {
auto obj = dynamic_cast<TCallable *>( auto obj =
std::get<THeapObjectHolder>(fn).obj); dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
if (obj != nullptr) { if (obj != nullptr) {
auto closure = dynamic_cast<TClosure *>(obj); auto closure = dynamic_cast<TClosure *>(obj);
if (closure != nullptr) { if (closure != nullptr) {
@@ -144,17 +143,17 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
} }
} else { } else {
return dict == std::get<THeapObjectHolder>(right).obj; return dict == std::get<THeapObject *>(right);
} }
} else { } else {
return dict == std::get<THeapObjectHolder>(right).obj; return dict == std::get<THeapObject *>(right);
} }
} else { } else {
return dict == std::get<THeapObjectHolder>(right).obj; return dict == std::get<THeapObject *>(right);
} }
return false; return false;
@@ -162,21 +161,19 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
else if (dynDict != nullptr) { else if (dynDict != nullptr) {
auto res = dynDict->CallMethod(ls, "operator==", {right}); auto res = dynDict->CallMethod(ls, "operator==", {right});
if (!std::holds_alternative<std::nullptr_t>(res) && if (!IsNull(res) && std::holds_alternative<Undefined>(res)) {
std::holds_alternative<Undefined>(res)) {
return ToBool(res); return ToBool(res);
} }
} else if (native != nullptr && } else if (native != nullptr && IsNull(right)) {
std::holds_alternative<std::nullptr_t>(right)) {
return native->GetDestroyed(); return native->GetDestroyed();
} }
if (std::holds_alternative<THeapObjectHolder>(right)) { if (std::holds_alternative<THeapObject *>(right)) {
return obj == std::get<THeapObjectHolder>(right).obj; return obj == std::get<THeapObject *>(right);
} }
else if (std::holds_alternative<std::nullptr_t>(right)) { else if (IsNull(right)) {
return false; return false;
} else if (std::holds_alternative<Undefined>(right)) { } else if (std::holds_alternative<Undefined>(right)) {
@@ -187,7 +184,7 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
} }
else if (std::holds_alternative<std::nullptr_t>(right)) { else if (IsNull(right)) {
return false; return false;
} else if (std::holds_alternative<Undefined>(right)) { } else if (std::holds_alternative<Undefined>(right)) {
return false; return false;
+15 -327
View File
@@ -24,7 +24,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
GCList ls(gc); GCList ls(gc);
std::regex regex; std::regex regex;
TVMVersion version; TVMVersion version;
if (std::holds_alternative<std::nullptr_t>(instance)) { if (IsNull(instance)) {
if (key == "ToString") { if (key == "ToString") {
cse.back()->Push(gc, "null"); cse.back()->Push(gc, "null");
return false; return false;
@@ -58,7 +58,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
if (GetArgument(args, 0, str)) { if (GetArgument(args, 0, str)) {
std::smatch m; std::smatch m;
if (std::regex_search(str, m, regex)) { if (std::regex_search(str, m, regex)) {
auto myLs = TList::Create(ls); auto myLs = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (auto item : m) { for (auto item : m) {
auto itm = TDictionary::Create(ls); auto itm = TDictionary::Create(ls);
@@ -288,7 +288,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
std::get<Tesses::Framework::Filesystem::VFSPath>(instance); std::get<Tesses::Framework::Filesystem::VFSPath>(instance);
if (key == "GetEnumerator") { if (key == "GetEnumerator") {
TList *_ls = TList::Create(ls); TList *_ls = ls.Create<TList>();
for (auto item : path.path) { for (auto item : path.path) {
_ls->Add(item); _ls->Add(item);
} }
@@ -683,7 +683,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
auto res = Tesses::Framework::Http::HttpUtils::SplitString( auto res = Tesses::Framework::Http::HttpUtils::SplitString(
str, delimiter, count); str, delimiter, count);
TList *mls = TList::Create(ls); TList *mls = ls.Create<TList>();
for (auto item : res) { for (auto item : res) {
if (!removeEmpty || !item.empty()) if (!removeEmpty || !item.empty())
mls->Add(item); mls->Add(item);
@@ -825,7 +825,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
std::vector<std::string> lines; std::vector<std::string> lines;
textReader->ReadAllLines(lines); textReader->ReadAllLines(lines);
gc->BarrierBegin(); gc->BarrierBegin();
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
for (auto &item : lines) for (auto &item : lines)
list->Add(item); list->Add(item);
gc->BarrierEnd(); gc->BarrierEnd();
@@ -1072,8 +1072,6 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>( std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(
instance); instance);
if (strm != nullptr) { if (strm != nullptr) {
auto memStrm = std::dynamic_pointer_cast<
Tesses::Framework::Streams::MemoryStream>(strm);
auto netStrm = std::dynamic_pointer_cast< auto netStrm = std::dynamic_pointer_cast<
Tesses::Framework::Streams::NetworkStream>(strm); Tesses::Framework::Streams::NetworkStream>(strm);
@@ -1090,134 +1088,8 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
return InvokeMethod(ls, o, dict2, args); return InvokeMethod(ls, o, dict2, args);
} }
} }
if (memStrm != nullptr) {
if (key == "GetBytes") {
auto res = TByteArray::Create(ls);
res->data = memStrm->GetBuffer();
cse.back()->Push(gc, res);
return false;
}
}
if (netStrm != nullptr) { if (netStrm != nullptr) {
if (key == "SetMulticastMembership") {
std::string ma;
std::string ifaceIP = "0.0.0.0";
if (GetArgument(args, 0, ma)) {
GetArgument(args, 1, ifaceIP);
netStrm->SetMulticastMembership(ma, ifaceIP);
}
cse.back()->Push(gc, Undefined());
return false;
}
if (key == "GetPort") {
cse.back()->Push(gc, (int64_t)netStrm->GetPort());
return false;
}
if (key == "Bind") {
std::string ip;
int64_t port;
if (GetArgument(args, 0, ip) &&
GetArgument(args, 1, port))
netStrm->Bind(ip, (uint16_t)port);
cse.back()->Push(gc, nullptr);
return false;
}
if (key == "Accept") {
std::string ip;
uint16_t port;
auto strm = netStrm->Accept(ip, port);
TDictionary *dict = TDictionary::Create(ls);
gc->BarrierBegin();
dict->SetValue("IP", ip);
dict->SetValue("Port", (int64_t)port);
dict->SetValue("Stream", strm);
gc->BarrierEnd();
cse.back()->Push(gc, dict);
return false;
}
if (key == "Listen") {
int64_t backlog;
if (GetArgument(args, 0, backlog)) {
netStrm->Listen((int32_t)backlog);
} else {
netStrm->Listen(10);
}
cse.back()->Push(gc, nullptr);
return false;
}
if (key == "ReadFrom") {
TByteArray *data;
int64_t offset;
int64_t length;
if (GetArgumentHeap<TByteArray *>(args, 0, data) &&
GetArgument<int64_t>(args, 1, offset) &&
GetArgument<int64_t>(args, 2, length)) {
size_t off = (size_t)offset;
size_t len = (size_t)length;
std::string ip = {};
uint16_t port = 0;
if (off < len)
len = netStrm->ReadFrom(
data->data.data() + off,
std::min(len,
std::min(data->data.size() - off,
data->data.size())),
ip, port);
else
len = 0;
TDictionary *dict = TDictionary::Create(ls);
gc->BarrierBegin();
dict->SetValue("IP", ip);
dict->SetValue("Port", (int64_t)port);
dict->SetValue("Read", (int64_t)len);
gc->BarrierEnd();
cse.back()->Push(gc, dict);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if (key == "WriteTo") {
TByteArray *data;
int64_t offset;
int64_t length;
std::string ip;
int64_t port;
if (GetArgumentHeap<TByteArray *>(args, 0, data) &&
GetArgument<int64_t>(args, 1, offset) &&
GetArgument<int64_t>(args, 2, length) &&
GetArgument(args, 3, ip) &&
GetArgument(args, 4, port)) {
size_t off = (size_t)offset;
size_t len = (size_t)length;
if (off < len)
len = netStrm->WriteTo(
data->data.data() + off,
std::min(len,
std::min(data->data.size() - off,
data->data.size())),
ip, (int64_t)port);
else
len = 0;
cse.back()->Push(gc, (int64_t)len);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
} }
if (key == "Read") { if (key == "Read") {
@@ -1490,12 +1362,12 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
pattern, pattern,
callable->ToRouteServerRequestHandler(gc)); callable->ToRouteServerRequestHandler(gc));
} }
} else if (key == "Trace") { } else if (key == "Query") {
std::string pattern; std::string pattern;
TCallable *callable; TCallable *callable;
if (GetArgument(args, 0, pattern) && if (GetArgument(args, 0, pattern) &&
GetArgumentHeap(args, 1, callable)) { GetArgumentHeap(args, 1, callable)) {
routable->Trace( routable->Query(
pattern, pattern,
callable->ToRouteServerRequestHandler(gc)); callable->ToRouteServerRequestHandler(gc));
} }
@@ -1964,9 +1836,9 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
} }
cse.back()->Push(gc, Undefined()); cse.back()->Push(gc, Undefined());
return false; return false;
} else if (std::holds_alternative<THeapObjectHolder>(instance)) { } else if (std::holds_alternative<THeapObject *>(instance)) {
auto obj = std::get<THeapObjectHolder>(instance).obj; auto obj = std::get<THeapObject *>(instance);
auto list = dynamic_cast<TList *>(obj);
auto dynList = dynamic_cast<TDynamicList *>(obj); auto dynList = dynamic_cast<TDynamicList *>(obj);
auto bArray = dynamic_cast<TByteArray *>(obj); auto bArray = dynamic_cast<TByteArray *>(obj);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
@@ -2292,9 +2164,9 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
} }
if (key == "RegisterClass") { if (key == "RegisterClass") {
if ((myEnv->permissions.canRegisterEverything || if ((myEnv->permissions.canRegisterEverything ||
myEnv->permissions.canRegisterClass) && myEnv->permissions.canRegisterZeClass) &&
!rootEnv->permissions.locked) !rootEnv->permissions.locked)
TStd::RegisterClass(gc, rootEnv); TStd::RegisterZeClass(gc, rootEnv);
cse.back()->Push(gc, nullptr); cse.back()->Push(gc, nullptr);
return false; return false;
} }
@@ -3195,7 +3067,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
if (GetArgument(args, 0, index) && if (GetArgument(args, 0, index) &&
(size_t)index < bArray->data.size() && (size_t)index < bArray->data.size() &&
(size_t)index + 8 <= bArray->data.size()) { (size_t)index + 8 <= bArray->data.size()) {
uint64_t value = BitConverter::ToDoubleLE( double value = BitConverter::ToDoubleLE(
bArray->data[(size_t)index]); bArray->data[(size_t)index]);
cse.back()->Push(gc, value); cse.back()->Push(gc, value);
@@ -3218,7 +3090,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
if (GetArgument(args, 0, index) && if (GetArgument(args, 0, index) &&
(size_t)index < bArray->data.size() && (size_t)index < bArray->data.size() &&
(size_t)index + 8 <= bArray->data.size()) { (size_t)index + 8 <= bArray->data.size()) {
uint64_t value = BitConverter::ToDoubleBE( double value = BitConverter::ToDoubleBE(
bArray->data[(size_t)index]); bArray->data[(size_t)index]);
cse.back()->Push(gc, value); cse.back()->Push(gc, value);
@@ -3336,190 +3208,6 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
} }
cse.back()->Push(gc, Undefined()); cse.back()->Push(gc, Undefined());
return false; return false;
} else if (list != nullptr) {
if (key == "GetEnumerator") {
cse.back()->Push(gc, TListEnumerator::Create(ls, list));
return false;
} else if (key == "ToString") {
cse.back()->Push(gc, Json_Encode(list));
return false;
} else if (key == "Insert") {
if (args.size() != 2) {
throw VMException(
"List.Insert must only accept two arguments");
}
int64_t index;
if (!GetArgument(args, 0, index)) {
throw VMException(
"List.Insert first argument must be Long");
}
gc->BarrierBegin();
list->Insert(index, args[1]);
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (key == "Add") {
if (args.size() != 1) {
throw VMException(
"List.Add must only accept one argument");
}
gc->BarrierBegin();
list->Add(args[0]);
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (key == "Contains") {
if (args.size() != 1) {
throw VMException(
"List.Contains must only accept one argument");
}
gc->BarrierBegin();
for (int64_t i = 0; i < list->Count(); i++) {
auto item = list->Get(i);
gc->BarrierEnd();
if (Equals(gc, args[0], item)) {
cse.back()->Push(gc, true);
return false;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, false);
return false;
} else if (key == "IndexOf") {
// IndexOf(obj, $idx)
if (args.size() < 1 || args.size() > 2) {
throw VMException("List.IndexOf must either have one "
"or two arguments");
}
int64_t i = 0;
GetArgument(args, 1, i);
gc->BarrierBegin();
for (; i < list->Count(); i++) {
auto item = list->Get(i);
gc->BarrierEnd();
if (Equals(gc, args[0], item)) {
cse.back()->Push(gc, i);
return false;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, (int64_t)-1);
return false;
} else if (key == "RemoveAllEqual") {
if (args.size() != 1) {
throw VMException("List.RemoveAllEqual must only "
"accept one argument");
}
gc->BarrierBegin();
for (int64_t i = 0; i < list->Count(); i++) {
auto item = list->Get(i);
gc->BarrierEnd();
if (Equals(gc, args[0], item)) {
gc->BarrierBegin();
list->RemoveAt(i);
i--;
} else
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (key == "Remove") {
if (args.size() != 1) {
throw VMException(
"List.Remove must only accept one argument");
}
gc->BarrierBegin();
for (int64_t i = 0; i < list->Count(); i++) {
auto item = list->Get(i);
gc->BarrierEnd();
if (Equals(gc, args[0], item)) {
gc->BarrierBegin();
list->RemoveAt(i);
gc->BarrierEnd();
break;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (key == "RemoveAt") {
if (args.size() != 1) {
throw VMException(
"List.RemoveAt must only accept one argument");
}
if (!std::holds_alternative<int64_t>(args[0])) {
throw VMException(
"List.RemoveAt must only accept a long");
}
gc->BarrierBegin();
list->RemoveAt(std::get<int64_t>(args[0]));
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (key == "Clear") {
gc->BarrierBegin();
list->Clear();
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
} else if (key == "GetAt") {
if (args.size() != 1) {
throw VMException(
"List.GetAt must only accept one argument");
}
if (!std::holds_alternative<int64_t>(args[0])) {
throw VMException("List.GetAt must only accept a long");
}
int64_t index = std::get<int64_t>(args[0]);
if (index >= 0 && index < list->Count()) {
cse.back()->Push(gc, list->Get(index));
return false;
}
} else if (key == "SetAt") {
if (args.size() != 2) {
throw VMException(
"List.SetAt must only accept two arguments");
}
if (!std::holds_alternative<int64_t>(args[0])) {
throw VMException("List.SetAt first argument must only "
"accept a long");
}
int64_t index = std::get<int64_t>(args[0]);
if (index >= 0 && index < list->Count()) {
list->Set(index, args[1]);
return false;
}
}
else if (key == "Count" || key == "Length") {
gc->BarrierBegin();
cse.back()->Push(gc, list->Count());
gc->BarrierEnd();
return false;
}
cse.back()->Push(gc, Undefined());
return false;
} else if (dynList != nullptr) { } else if (dynList != nullptr) {
if (key == "GetEnumerator") { if (key == "GetEnumerator") {
+18 -80
View File
@@ -145,59 +145,6 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, Undefined()); cse.back()->Push(gc, Undefined());
return false; return false;
} }
if (std::holds_alternative<
std::shared_ptr<Tesses::Framework::Streams::Stream>>(
instance)) {
auto strm =
std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(
instance);
if (strm != nullptr) {
auto netStrm = std::dynamic_pointer_cast<
Tesses::Framework::Streams::NetworkStream>(strm);
if (key == "CanRead") {
cse.back()->Push(gc, strm->CanRead());
return false;
}
if (key == "CanWrite") {
cse.back()->Push(gc, strm->CanWrite());
return false;
}
if (key == "CanSeek") {
cse.back()->Push(gc, strm->CanSeek());
return false;
}
if (key == "EndOfStream") {
cse.back()->Push(gc, strm->EndOfStream());
return false;
}
if (key == "Length") {
cse.back()->Push(gc, strm->GetLength());
return false;
}
if (key == "Position") {
cse.back()->Push(gc, strm->GetPosition());
return false;
}
if (netStrm != nullptr) {
if (key == "Port") {
cse.back()->Push(gc, netStrm->GetPort());
return false;
}
}
cse.back()->Push(gc, Undefined());
return false;
}
}
if (std::holds_alternative<TVMVersion>(instance)) { if (std::holds_alternative<TVMVersion>(instance)) {
TVMVersion &version = std::get<TVMVersion>(instance); TVMVersion &version = std::get<TVMVersion>(instance);
if (key == "Major") { if (key == "Major") {
@@ -323,8 +270,8 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
stk->Push(gc, Undefined()); stk->Push(gc, Undefined());
return false; return false;
} }
if (std::holds_alternative<THeapObjectHolder>(instance)) { if (std::holds_alternative<THeapObject *>(instance)) {
auto obj = std::get<THeapObjectHolder>(instance).obj; auto obj = std::get<THeapObject *>(instance);
auto bA = dynamic_cast<TByteArray *>(obj); auto bA = dynamic_cast<TByteArray *>(obj);
auto list = dynamic_cast<TList *>(obj); auto list = dynamic_cast<TList *>(obj);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
@@ -391,7 +338,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, file->info); cse.back()->Push(gc, file->info);
return false; return false;
} else if (key == "Dependencies") { } else if (key == "Dependencies") {
auto list = TList::Create(ls); auto list = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (auto item : file->dependencies) { for (auto item : file->dependencies) {
auto res = TDictionary::Create(ls); auto res = TDictionary::Create(ls);
@@ -403,7 +350,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, list); cse.back()->Push(gc, list);
return false; return false;
} else if (key == "Tools") { } else if (key == "Tools") {
auto list = TList::Create(ls); auto list = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (auto item : file->tools) { for (auto item : file->tools) {
auto res = TDictionary::Create(ls); auto res = TDictionary::Create(ls);
@@ -415,7 +362,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, list); cse.back()->Push(gc, list);
return false; return false;
} else if (key == "Strings") { } else if (key == "Strings") {
auto list = TList::Create(ls); auto list = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (auto item : file->name) { for (auto item : file->name) {
list->Add(item); list->Add(item);
@@ -429,7 +376,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, (int64_t)file->metadata.size()); cse.back()->Push(gc, (int64_t)file->metadata.size());
return false; return false;
} else if (key == "Metadata") { } else if (key == "Metadata") {
TList *meta = TList::Create(ls); TList *meta = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (size_t i = 0; i < file->metadata.size(); i++) { for (size_t i = 0; i < file->metadata.size(); i++) {
meta->Add(TDictionary::Create( meta->Add(TDictionary::Create(
@@ -441,7 +388,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, meta); cse.back()->Push(gc, meta);
return false; return false;
} else if (key == "Sections") { } else if (key == "Sections") {
TList *sections = TList::Create(ls); TList *sections = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (auto &item : file->sections) { for (auto &item : file->sections) {
TByteArray *ba = TByteArray::Create(ls); TByteArray *ba = TByteArray::Create(ls);
@@ -455,7 +402,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, sections); cse.back()->Push(gc, sections);
return false; return false;
} else if (key == "SupportedVMs") { } else if (key == "SupportedVMs") {
TList *supported = TList::Create(ls); TList *supported = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
if (file->vms.empty()) { if (file->vms.empty()) {
supported->Add(TDictionary::Create( supported->Add(TDictionary::Create(
@@ -471,7 +418,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, supported); cse.back()->Push(gc, supported);
return false; return false;
} else if (key == "Chunks") { } else if (key == "Chunks") {
auto list = TList::Create(ls); auto list = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (auto item : file->chunks) { for (auto item : file->chunks) {
list->Add(item); list->Add(item);
@@ -482,7 +429,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, list); cse.back()->Push(gc, list);
return false; return false;
} else if (key == "Classes") { } else if (key == "Classes") {
auto list = TList::Create(ls); auto list = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (uint32_t i = 0; i < (uint32_t)file->classes.size(); for (uint32_t i = 0; i < (uint32_t)file->classes.size();
@@ -494,13 +441,13 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
gc->BarrierEnd(); gc->BarrierEnd();
return false; return false;
} else if (key == "Functions") { } else if (key == "Functions") {
auto list = TList::Create(ls); auto list = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (auto &item : file->functions) { for (auto &item : file->functions) {
TDictionary *dict = TDictionary::Create(ls); TDictionary *dict = TDictionary::Create(ls);
if (!item.first.empty()) if (!item.first.empty())
dict->SetValue("Documentation", item.first[0]); dict->SetValue("Documentation", item.first[0]);
TList *nameParts = TList::Create(ls); TList *nameParts = ls.Create<TList>();
for (size_t i = 1; i < item.first.size(); i++) { for (size_t i = 1; i < item.first.size(); i++) {
nameParts->Add(item.first[i]); nameParts->Add(item.first[i]);
} }
@@ -530,7 +477,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
} }
if (chunk != nullptr) { if (chunk != nullptr) {
if (key == "Arguments") { if (key == "Arguments") {
auto myargs = TList::Create(ls); auto myargs = ls.Create<TList>();
gc->BarrierBegin(); gc->BarrierBegin();
for (auto item : chunk->args) { for (auto item : chunk->args) {
myargs->Add(item); myargs->Add(item);
@@ -586,7 +533,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
if (closure != nullptr) { if (closure != nullptr) {
if (key == "Arguments") { if (key == "Arguments") {
GCList ls2(gc); GCList ls2(gc);
TList *ls = TList::Create(ls2); TList *ls = ls2.Create<TList>();
for (auto arg : closure->closure->args) { for (auto arg : closure->closure->args) {
ls->Add(arg); ls->Add(arg);
} }
@@ -601,7 +548,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
if (externalMethod != nullptr) { if (externalMethod != nullptr) {
if (key == "Arguments") { if (key == "Arguments") {
GCList ls2(gc); GCList ls2(gc);
TList *ls = TList::Create(ls2); TList *ls = ls2.Create<TList>();
for (auto arg : externalMethod->args) { for (auto arg : externalMethod->args) {
ls->Add(arg); ls->Add(arg);
} }
@@ -635,16 +582,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
return false; return false;
} }
} }
if (list != nullptr) {
if (key == "Count" || key == "Length") {
int64_t len = list->Count();
if (len < 0)
len = 0;
stk->Push(gc, len);
return false;
}
}
if (dynList != nullptr) { if (dynList != nullptr) {
if (key == "Count" || key == "Length") { if (key == "Count" || key == "Length") {
int64_t len = dynList->Count(ls); int64_t len = dynList->Count(ls);
@@ -669,9 +607,9 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
gc->BarrierBegin(); gc->BarrierBegin();
TObject fn = dict->GetValue("get" + key); TObject fn = dict->GetValue("get" + key);
gc->BarrierEnd(); gc->BarrierEnd();
if (std::holds_alternative<THeapObjectHolder>(fn) && if (std::holds_alternative<THeapObject *>(fn) &&
dynamic_cast<TCallable *>( dynamic_cast<TCallable *>(std::get<THeapObject *>(fn)) !=
std::get<THeapObjectHolder>(fn).obj) != nullptr) { nullptr) {
return InvokeOne(ls, fn, dict); return InvokeOne(ls, fn, dict);
} else { } else {
gc->BarrierBegin(); gc->BarrierBegin();
+3 -4
View File
@@ -15,16 +15,15 @@ namespace Tesses::CrossLang {
bool InterperterThread::InvokeMethod(GCList &ls, TObject fn, TObject instance, bool InterperterThread::InvokeMethod(GCList &ls, TObject fn, TObject instance,
std::vector<TObject> args) { std::vector<TObject> args) {
if (std::holds_alternative<THeapObjectHolder>(fn)) { if (std::holds_alternative<THeapObject *>(fn)) {
auto obj = auto obj = dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
dynamic_cast<TCallable *>(std::get<THeapObjectHolder>(fn).obj);
if (obj != nullptr) { if (obj != nullptr) {
auto closure = dynamic_cast<TClosure *>(obj); auto closure = dynamic_cast<TClosure *>(obj);
if (closure != nullptr) { if (closure != nullptr) {
if (!closure->closure->args.empty() && if (!closure->closure->args.empty() &&
closure->closure->args[0] == "this") { closure->closure->args[0].GetString() == "this") {
std::vector<TObject> args2; std::vector<TObject> args2;
args2.push_back(instance); args2.push_back(instance);
args2.insert(args2.end(), args.begin(), args.end()); args2.insert(args2.end(), args.begin(), args.end());
+2 -3
View File
@@ -12,10 +12,9 @@
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
bool InterperterThread::InvokeTwo(GCList &ls, TObject fn, TObject left, bool InterperterThread::InvokeTwo(GCList &ls, TObject fn, TObject left,
TObject right) { TObject right) {
if (std::holds_alternative<THeapObjectHolder>(fn)) { if (std::holds_alternative<THeapObject *>(fn)) {
auto obj = auto obj = dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
dynamic_cast<TCallable *>(std::get<THeapObjectHolder>(fn).obj);
if (obj != nullptr) { if (obj != nullptr) {
auto closure = dynamic_cast<TClosure *>(obj); auto closure = dynamic_cast<TClosure *>(obj);
if (closure != nullptr) { if (closure != nullptr) {
+5 -30
View File
@@ -231,34 +231,9 @@ bool InterperterThread::SetField(std::shared_ptr<GC> gc) {
stk->Push(gc, Undefined()); stk->Push(gc, Undefined());
return false; return false;
} }
if (std::holds_alternative<
std::shared_ptr<Tesses::Framework::Streams::Stream>>(
instance)) {
auto strm =
std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(
instance);
auto netStrm = std::dynamic_pointer_cast< if (std::holds_alternative<THeapObject *>(instance)) {
Tesses::Framework::Streams::NetworkStream>(strm); auto obj = std::get<THeapObject *>(instance);
if (netStrm != nullptr) {
int64_t n0;
bool bc;
if (key == "Broadcast" && GetObject(value, bc))
netStrm->SetBroadcast(bc);
if (key == "NoDelay" && GetObject(value, bc))
netStrm->SetNoDelay(bc);
if (key == "ReuseAddress" && GetObject(value, bc))
netStrm->SetReuseAddress(bc);
if (key == "ReusePort" && GetObject(value, bc))
netStrm->SetReusePort(bc);
if (key == "MulticastTTL" && GetObject(value, n0))
netStrm->SetMulticastTTL((uint8_t)n0);
}
stk->Push(gc, Undefined());
return false;
}
if (std::holds_alternative<THeapObjectHolder>(instance)) {
auto obj = std::get<THeapObjectHolder>(instance).obj;
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -313,9 +288,9 @@ bool InterperterThread::SetField(std::shared_ptr<GC> gc) {
gc->BarrierBegin(); gc->BarrierBegin();
TObject fn = dict->GetValue("set" + key); TObject fn = dict->GetValue("set" + key);
gc->BarrierEnd(); gc->BarrierEnd();
if (std::holds_alternative<THeapObjectHolder>(fn) && if (std::holds_alternative<THeapObject *>(fn) &&
dynamic_cast<TCallable *>( dynamic_cast<TCallable *>(std::get<THeapObject *>(fn)) !=
std::get<THeapObjectHolder>(fn).obj) != nullptr) { nullptr) {
return InvokeTwo(ls, fn, dict, value); return InvokeTwo(ls, fn, dict, value);
} else { } else {
gc->BarrierBegin(); gc->BarrierBegin();
+12 -4
View File
@@ -65,9 +65,17 @@ bool InterperterThread::Sub(std::shared_ptr<GC> gc) {
cse.back()->Push( cse.back()->Push(
gc, gc,
std::make_shared<Tesses::Framework::Date::DateTime>((*l) - (*r))); std::make_shared<Tesses::Framework::Date::DateTime>((*l) - (*r)));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj);
if (obj == nullptr) {
cse.back()->Push(gc, Undefined());
return false;
}
return obj->opSub(this, gc, right);
/*auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
auto natObj = dynamic_cast<TNativeObject *>(obj); auto natObj = dynamic_cast<TNativeObject *>(obj);
@@ -104,7 +112,7 @@ bool InterperterThread::Sub(std::shared_ptr<GC> gc) {
} else { } else {
cse.back()->Push(gc, Undefined()); cse.back()->Push(gc, Undefined());
} }
*/
} else { } else {
cse.back()->Push(gc, Undefined()); cse.back()->Push(gc, Undefined());
} }
+2 -2
View File
@@ -44,8 +44,8 @@ bool ToBool(TObject obj) {
} else if (std::holds_alternative<Tesses::Framework::Uuid>(obj)) { } else if (std::holds_alternative<Tesses::Framework::Uuid>(obj)) {
auto &uuid = std::get<Tesses::Framework::Uuid>(obj); auto &uuid = std::get<Tesses::Framework::Uuid>(obj);
return !uuid.IsEmpty(); return !uuid.IsEmpty();
} else if (std::holds_alternative<THeapObjectHolder>(obj)) { } else if (std::holds_alternative<THeapObject *>(obj)) {
auto o = std::get<THeapObjectHolder>(obj).obj; auto o = std::get<THeapObject *>(obj);
auto ls = dynamic_cast<TList *>(o); auto ls = dynamic_cast<TList *>(o);
auto aarray = dynamic_cast<TAssociativeArray *>(o); auto aarray = dynamic_cast<TAssociativeArray *>(o);
auto dict = dynamic_cast<TDictionary *>(o); auto dict = dynamic_cast<TDictionary *>(o);
+3 -3
View File
@@ -31,7 +31,7 @@ std::string ToString(std::shared_ptr<GC> gc, TObject o) {
if (std::holds_alternative<char>(o)) { if (std::holds_alternative<char>(o)) {
return std::string{std::get<char>(o)}; return std::string{std::get<char>(o)};
} }
if (std::holds_alternative<std::nullptr_t>(o)) { if (IsNull(o)) {
return "null"; return "null";
} }
if (std::holds_alternative<Undefined>(o)) { if (std::holds_alternative<Undefined>(o)) {
@@ -54,8 +54,8 @@ std::string ToString(std::shared_ptr<GC> gc, TObject o) {
return std::get<Tesses::Framework::Uuid>(o).ToString( return std::get<Tesses::Framework::Uuid>(o).ToString(
Framework::UuidStringifyConfig::LowercaseNoCurly); Framework::UuidStringifyConfig::LowercaseNoCurly);
} }
if (std::holds_alternative<THeapObjectHolder>(o)) { if (std::holds_alternative<THeapObject *>(o)) {
auto obj = std::get<THeapObjectHolder>(o).obj; auto obj = std::get<THeapObject *>(o);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto list = dynamic_cast<TList *>(obj); auto list = dynamic_cast<TList *>(obj);
auto bArray = dynamic_cast<TByteArray *>(obj); auto bArray = dynamic_cast<TByteArray *>(obj);
+4 -4
View File
@@ -58,13 +58,13 @@ void ThrowFatalError(std::exception &ex) {
error.WriteLine(text); error.WriteLine(text);
} }
exit(1); std::exit(1);
} }
if (clrtexcept != nullptr) { if (clrtexcept != nullptr) {
error.WriteLine("CrossLang has encountered a fatal runtime exception"); error.WriteLine("CrossLang has encountered a fatal runtime exception");
error.WriteLine(); error.WriteLine();
error.WriteLine(clrtexcept->what()); error.WriteLine(clrtexcept->what());
exit(1); std::exit(1);
} }
if (compiler != nullptr) { if (compiler != nullptr) {
error.WriteLine("CrossLang has encountered a compiler error"); error.WriteLine("CrossLang has encountered a compiler error");
@@ -81,13 +81,13 @@ void ThrowFatalError(std::exception &ex) {
error.Write(":"); error.Write(":");
error.WriteLine((int64_t)li.offset); error.WriteLine((int64_t)li.offset);
exit(1); std::exit(1);
} }
error.WriteLine("CrossLang has encountered a fatal C++ exception"); error.WriteLine("CrossLang has encountered a fatal C++ exception");
error.WriteLine(); error.WriteLine();
error.Write("what(): "); error.Write("what(): ");
error.WriteLine(ex2->what()); error.WriteLine(ex2->what());
exit(1); std::exit(1);
} }
} // namespace Tesses::CrossLang } // namespace Tesses::CrossLang
+68 -61
View File
@@ -5,22 +5,8 @@
#include <iostream> #include <iostream>
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TFile *TFile::Create(GCList &ls) { TFile *TFile::Create(GCList &ls) { return ls.Create<TFile>(); }
TFile *f = new TFile(); TFile *TFile::Create(GCList *ls) { return ls->Create<TFile>(); }
f->icon = -1;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(f);
_gc->Watch(f);
return f;
}
TFile *TFile::Create(GCList *ls) {
TFile *f = new TFile();
f->icon = -1;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(f);
_gc->Watch(f);
return f;
}
void TFileChunk::Mark() { void TFileChunk::Mark() {
if (this->marked) if (this->marked)
return; return;
@@ -28,20 +14,8 @@ void TFileChunk::Mark() {
this->file->Mark(); this->file->Mark();
} }
TFileChunk *TFileChunk::Create(GCList &ls) { TFileChunk *TFileChunk::Create(GCList &ls) { return ls.Create<TFileChunk>(); }
TFileChunk *chk = new TFileChunk(); TFileChunk *TFileChunk::Create(GCList *ls) { return ls->Create<TFileChunk>(); }
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(chk);
_gc->Watch(chk);
return chk;
}
TFileChunk *TFileChunk::Create(GCList *ls) {
TFileChunk *chk = new TFileChunk();
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(chk);
_gc->Watch(chk);
return chk;
}
void TFile::Mark() { void TFile::Mark() {
if (this->marked) if (this->marked)
return; return;
@@ -69,15 +43,18 @@ void TFile::Ensure(std::shared_ptr<Tesses::Framework::Streams::Stream> stream,
"End of file, could not read " + std::to_string((int64_t)len) + "End of file, could not read " + std::to_string((int64_t)len) +
" byte(s)., offset=" + std::to_string(stream->GetLength())); " byte(s)., offset=" + std::to_string(stream->GetLength()));
} }
std::string TFile::EnsureString( void TFile::EnsureString(
std::shared_ptr<Tesses::Framework::Streams::Stream> stream) { GCList &ls, std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
auto len = EnsureInt(stream); auto len = EnsureInt(stream);
if (len == 0) if (len == 0) {
return {}; this->strings.push_back(ls.FromString(""));
return;
}
std::string str = {}; std::string str = {};
str.resize((size_t)len); str.resize((size_t)len);
Ensure(stream, (uint8_t *)str.data(), str.size()); Ensure(stream, (uint8_t *)str.data(), str.size());
return str;
this->strings.push_back(ls.Create<TString>(std::move(str)));
} }
uint32_t uint32_t
@@ -86,7 +63,7 @@ TFile::EnsureInt(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
Ensure(stream, buffer, 4); Ensure(stream, buffer, 4);
return BitConverter::ToUint32BE(buffer[0]); return BitConverter::ToUint32BE(buffer[0]);
} }
std::string TString *
TFile::GetString(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) { TFile::GetString(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
uint32_t index = EnsureInt(stream); uint32_t index = EnsureInt(stream);
if (index >= this->strings.size()) if (index >= this->strings.size())
@@ -101,7 +78,7 @@ void TFile::EnsureCanRunInCrossLang() {
return; return;
for (auto item : this->vms) { for (auto item : this->vms) {
if (item.first == VMName) { if (item.first->GetString() == VMName) {
return; return;
} }
} }
@@ -109,7 +86,8 @@ void TFile::EnsureCanRunInCrossLang() {
std::string errorMessage = "The virtual machines supported are:\n"; std::string errorMessage = "The virtual machines supported are:\n";
for (auto item : this->vms) { for (auto item : this->vms) {
errorMessage += item.first + "\n\t" + item.second + "\n"; errorMessage +=
item.first->GetString() + "\n\t" + item.second->GetString() + "\n";
} }
throw VMException(errorMessage); throw VMException(errorMessage);
} }
@@ -178,7 +156,7 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
items.push_back(parseEnt()); items.push_back(parseEnt());
} }
return TList::Create(ls, items.begin(), items.end()); return ls.Create<TList>(items.begin(), items.end());
} else } else
throw std::out_of_range("Abrupt end of metadata"); throw std::out_of_range("Abrupt end of metadata");
} break; } break;
@@ -192,8 +170,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
if (index + 4 <= bytes.size()) { if (index + 4 <= bytes.size()) {
auto val2 = BitConverter::ToUint32BE(bytes[index]); auto val2 = BitConverter::ToUint32BE(bytes[index]);
index += 4; index += 4;
std::string &text = this->strings.at((size_t)val2); TString *text = this->strings.at((size_t)val2);
items.emplace_back(text, parseEnt()); items.emplace_back(text->GetString(), parseEnt());
} else } else
throw std::out_of_range("Abrupt end of metadata"); throw std::out_of_range("Abrupt end of metadata");
} }
@@ -206,9 +184,7 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
if (index + 4 <= bytes.size()) { if (index + 4 <= bytes.size()) {
auto val = BitConverter::ToUint32BE(bytes[index]); auto val = BitConverter::ToUint32BE(bytes[index]);
index += 4; index += 4;
auto ba = TByteArray::Create(ls); return ls.Create<TByteArray>(this->resources.at((size_t)val));
ba->data = this->resources.at((size_t)val);
return ba;
} else } else
throw std::out_of_range("Abrupt end of metadata"); throw std::out_of_range("Abrupt end of metadata");
} break; } break;
@@ -216,7 +192,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
if (index + 4 <= bytes.size()) { if (index + 4 <= bytes.size()) {
auto val = BitConverter::ToUint32BE(bytes[index]); auto val = BitConverter::ToUint32BE(bytes[index]);
index += 4; index += 4;
return std::make_shared<EmbedStream>(ls.GetGC(), this, val); return ls.Create<TStream>(
std::make_shared<EmbedStream>(ls.GetGC(), this, val));
} else } else
throw std::out_of_range("Abrupt end of metadata"); throw std::out_of_range("Abrupt end of metadata");
} break; } break;
@@ -238,8 +215,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
ls, "", {}, ls, "", {},
[val, this](GCList &ls, [val, this](GCList &ls,
std::vector<TObject> args) -> TObject { std::vector<TObject> args) -> TObject {
return std::make_shared<EmbedStream>(ls.GetGC(), this, return ls.Create<TStream>(std::make_shared<EmbedStream>(
val); ls.GetGC(), this, val));
}); });
em->watch.push_back(this); em->watch.push_back(this);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();
@@ -287,26 +264,36 @@ void TFile::Load(std::shared_ptr<GC> gc,
this->info = GetString(stream); this->info = GetString(stream);
} else if (strncmp(table_name, "DEPS", 4) == 0) // dependencies } else if (strncmp(table_name, "DEPS", 4) == 0) // dependencies
{ {
std::string name = GetString(stream); TString *name = GetString(stream);
uint8_t version_bytes[5]; uint8_t version_bytes[5];
Ensure(stream, version_bytes, sizeof(version_bytes)); Ensure(stream, version_bytes, sizeof(version_bytes));
TVMVersion depVersion(version_bytes); TVMVersion depVersion(version_bytes);
gc->BarrierBegin();
this->dependencies.push_back( this->dependencies.push_back(
std::pair<std::string, TVMVersion>(name, depVersion)); std::pair<TString *, TVMVersion>(name, depVersion));
gc->BarrierEnd();
} else if (strncmp(table_name, "TOOL", 4) == } else if (strncmp(table_name, "TOOL", 4) ==
0) // compile tools (for package manager) 0) // compile tools (for package manager)
{ {
std::string name = GetString(stream); TString *name = GetString(stream);
uint8_t version_bytes[5]; uint8_t version_bytes[5];
Ensure(stream, version_bytes, sizeof(version_bytes)); Ensure(stream, version_bytes, sizeof(version_bytes));
TVMVersion depVersion(version_bytes); TVMVersion depVersion(version_bytes);
gc->BarrierBegin();
this->tools.push_back( this->tools.push_back(
std::pair<std::string, TVMVersion>(name, depVersion)); std::pair<TString *, TVMVersion>(name, depVersion));
gc->BarrierEnd();
} else if (strncmp(table_name, "RESO", 4) == } else if (strncmp(table_name, "RESO", 4) ==
0) // resources (using embed) 0) // resources (using embed)
{ {
auto &data = this->resources.emplace_back(tableLen); std::vector<uint8_t> data;
data.resize(tableLen);
Ensure(stream, data.data(), data.size()); Ensure(stream, data.data(), data.size());
GCList ls(gc);
gc->BarrierBegin();
this->resources.push_back(ls.Create<TResource>(std::move(data)));
gc->BarrierEnd();
} else if (strncmp(table_name, "CHKS", 4) == 0 && } else if (strncmp(table_name, "CHKS", 4) == 0 &&
gc != nullptr) // chunks gc != nullptr) // chunks
{ {
@@ -314,11 +301,13 @@ void TFile::Load(std::shared_ptr<GC> gc,
size_t chunkCount = (size_t)EnsureInt(stream); size_t chunkCount = (size_t)EnsureInt(stream);
for (size_t j = 0; j < chunkCount; j++) { for (size_t j = 0; j < chunkCount; j++) {
auto chunk = TFileChunk::Create(ls); auto chunk = ls.Create<TFileChunk>();
chunk->file = this; chunk->file = this;
size_t argCount = (size_t)EnsureInt(stream); size_t argCount = (size_t)EnsureInt(stream);
for (size_t k = 0; k < argCount; k++) { for (size_t k = 0; k < argCount; k++) {
gc->BarrierBegin();
chunk->args.push_back(GetString(stream)); chunk->args.push_back(GetString(stream));
gc->BarrierEnd();
} }
size_t len = (size_t)EnsureInt(stream); size_t len = (size_t)EnsureInt(stream);
chunk->code.resize(len); chunk->code.resize(len);
@@ -333,33 +322,45 @@ void TFile::Load(std::shared_ptr<GC> gc,
size_t funLength = (size_t)EnsureInt(stream); size_t funLength = (size_t)EnsureInt(stream);
for (size_t j = 0; j < funLength; j++) { for (size_t j = 0; j < funLength; j++) {
std::vector<std::string> fnParts; std::vector<TString *> fnParts;
uint32_t fnPartsC = EnsureInt(stream); uint32_t fnPartsC = EnsureInt(stream);
for (uint32_t k = 0; k < fnPartsC; k++) { for (uint32_t k = 0; k < fnPartsC; k++) {
fnParts.push_back(GetString(stream)); fnParts.push_back(GetString(stream));
} }
uint32_t fnNumber = EnsureInt(stream); uint32_t fnNumber = EnsureInt(stream);
gc->BarrierBegin();
this->functions.push_back( this->functions.push_back(
std::pair<std::vector<std::string>, uint32_t>(fnParts, std::pair<std::vector<TString *>, uint32_t>(fnParts,
fnNumber)); fnNumber));
gc->BarrierEnd();
} }
} else if (strncmp(table_name, "STRS", 4) == 0) // strings } else if (strncmp(table_name, "STRS", 4) == 0) // strings
{ {
size_t strsLen = (size_t)EnsureInt(stream); size_t strsLen = (size_t)EnsureInt(stream);
gc->BarrierBegin();
this->strings.reserve(strsLen);
gc->BarrierEnd();
GCList ls(gc);
for (size_t j = 0; j < strsLen; j++) { for (size_t j = 0; j < strsLen; j++) {
this->strings.push_back(EnsureString(stream)); gc->BarrierBegin();
EnsureString(ls, stream);
gc->BarrierEnd();
} }
} else if (strncmp(table_name, "ICON", 4) == 0) // icon } else if (strncmp(table_name, "ICON", 4) == 0) // icon
{ {
this->icon = (int32_t)EnsureInt(stream); this->icon = this->resources.at(EnsureInt(stream));
} else if (strncmp(table_name, "MACH", 4) == 0) // machine } else if (strncmp(table_name, "MACH", 4) == 0) // machine
{ {
std::string name = GetString(stream); TString *name = GetString(stream);
std::string howToGet = GetString(stream); TString *howToGet = GetString(stream);
gc->BarrierBegin();
this->vms.push_back( this->vms.push_back(
std::pair<std::string, std::string>(name, howToGet)); std::pair<TString *, TString *>(name, howToGet));
gc->BarrierEnd();
} else if (strncmp(table_name, "CLSS", 4) == 0) // classes } else if (strncmp(table_name, "CLSS", 4) == 0) // classes
{ {
uint32_t clsCnt = EnsureInt(stream); uint32_t clsCnt = EnsureInt(stream);
@@ -367,14 +368,17 @@ void TFile::Load(std::shared_ptr<GC> gc,
TClass cls; TClass cls;
cls.documentation = GetString(stream); cls.documentation = GetString(stream);
uint32_t name_cnt = EnsureInt(stream); uint32_t name_cnt = EnsureInt(stream);
cls.name.reserve((size_t)name_cnt);
for (uint32_t k = 0; k < name_cnt; k++) { for (uint32_t k = 0; k < name_cnt; k++) {
cls.name.push_back(GetString(stream)); cls.name.push_back(GetString(stream));
} }
name_cnt = EnsureInt(stream); name_cnt = EnsureInt(stream);
cls.inherits.reserve((size_t)name_cnt);
for (uint32_t k = 0; k < name_cnt; k++) { for (uint32_t k = 0; k < name_cnt; k++) {
cls.inherits.push_back(GetString(stream)); cls.inherits.push_back(GetString(stream));
} }
name_cnt = EnsureInt(stream); name_cnt = EnsureInt(stream);
cls.entry.reserve((size_t)name_cnt);
for (uint32_t k = 0; k < name_cnt; k++) { for (uint32_t k = 0; k < name_cnt; k++) {
TClassEntry ent; TClassEntry ent;
Ensure(stream, main_header, 1); Ensure(stream, main_header, 1);
@@ -385,12 +389,15 @@ void TFile::Load(std::shared_ptr<GC> gc,
ent.documentation = GetString(stream); ent.documentation = GetString(stream);
ent.name = GetString(stream); ent.name = GetString(stream);
uint32_t arglen = EnsureInt(stream); uint32_t arglen = EnsureInt(stream);
ent.args.reserve((size_t)arglen);
for (uint32_t l = 0; l < arglen; l++) for (uint32_t l = 0; l < arglen; l++)
ent.args.push_back(GetString(stream)); ent.args.push_back(GetString(stream));
ent.chunkId = EnsureInt(stream); ent.chunkId = EnsureInt(stream);
cls.entry.push_back(ent); cls.entry.push_back(ent);
} }
gc->BarrierBegin();
this->classes.push_back(cls); this->classes.push_back(cls);
gc->BarrierEnd();
} }
} else if (strncmp(table_name, "META", 4) == 0) // structured metadata } else if (strncmp(table_name, "META", 4) == 0) // structured metadata
{ {
+92 -88
View File
@@ -2,16 +2,25 @@
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <time.h> #include <time.h>
#if defined(_WIN32) #if !defined(_WIN32)
#include <windows.h>
#else
#include <unistd.h> #include <unistd.h>
#endif #endif
using namespace Tesses::Framework::Threading; using namespace Tesses::Framework::Threading;
using namespace std::chrono; using namespace std::chrono;
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
#if defined(GEKKO) || defined(_EE)
struct PthreadCmp {
bool operator()(const pthread_t &a, const pthread_t &b) const {
return pthread_equal(a, b) != 0;
}
};
static std::map<pthread_t, CallStackEntry *, PthreadCmp> current_funcs;
static Tesses::Framework::Threading::Mutex current_funcs_mtx;
#else
thread_local CallStackEntry *current_function;
#endif
bool GC::IsRunning() { bool GC::IsRunning() {
bool run = this->running; bool run = this->running;
@@ -74,7 +83,13 @@ TDictionary *CreateThread(GCList &ls, TCallable *callable, bool detached) {
TObject cb = th->callable->Call(ls, {}); TObject cb = th->callable->Call(ls, {});
gc->BarrierBegin(); gc->BarrierBegin();
th->returnValue = cb; th->returnValue = cb;
#if defined(GEKKO) || defined(_EE)
current_funcs_mtx.Lock();
current_funcs.erase(pthread_self());
current_funcs_mtx.Unlock();
#endif
gc->BarrierEnd(); gc->BarrierEnd();
th->hasReturned = true; th->hasReturned = true;
}); });
while (!th->hasInit) while (!th->hasInit)
@@ -93,121 +108,88 @@ void GC::Start() {
return new Tesses::Framework::Threading::ThreadPool(threads); return new Tesses::Framework::Threading::ThreadPool(threads);
}, },
[](Tesses::Framework::Threading::ThreadPool *p) -> void { delete p; }); [](Tesses::Framework::Threading::ThreadPool *p) -> void { delete p; });
this->mtx = new Mutex();
this->running = true; this->running = true;
this->thrd = new Thread([this]() -> void { this->thrd = new Thread([this]() -> void {
std::chrono::time_point<std::chrono::system_clock> last_frame,
this_frame;
this_frame = system_clock::now();
last_frame = this_frame;
while (this->IsRunning()) { while (this->IsRunning()) {
this_frame = system_clock::now(); this->BarrierBegin();
if ((this_frame - last_frame) > 10s) { while (this->IsRunning() && (this->allocs < ALLOC_THRESHOLD))
this->cond.Wait(&this->mtx);
this->allocs = 0;
std::vector<THeapObject *> to_delete;
this->Collect(to_delete);
this->BarrierEnd();
last_frame = this_frame; for (auto o : to_delete)
this->Collect(); delete o;
} }
{
std::vector<THeapObject *> to_delete;
this->BarrierBegin();
this->Collect(to_delete);
this->BarrierEnd();
#if defined(_WIN32) for (auto item : to_delete)
Sleep(100); delete item;
#else
usleep(100000);
#endif
} }
GC::Collect();
}); });
} }
bool GC::UsingNullThreads() { return false; } bool GC::UsingNullThreads() { return false; }
void GC::BarrierBegin() { this->mtx->Lock(); } void GC::BarrierBegin() { this->mtx.Lock(); }
void GC::BarrierEnd() { this->mtx->Unlock(); } void GC::BarrierEnd() { this->mtx.Unlock(); }
void GC::Watch(TObject obj) { void GC::Watch(TObject obj) {
if (std::holds_alternative<THeapObjectHolder>(obj)) { if (std::holds_alternative<THeapObject *>(obj)) {
auto _item = std::get<THeapObjectHolder>(obj).obj; auto _item = std::get<THeapObject *>(obj);
this->BarrierBegin(); this->BarrierBegin();
this->objects.insert(_item);
for (auto item : this->objects) { auto nowAllocs = ++this->allocs;
if (item == _item) {
this->BarrierEnd();
return;
}
}
this->objects.push_back(_item);
this->BarrierEnd(); this->BarrierEnd();
if (nowAllocs >= ALLOC_THRESHOLD)
this->cond.Signal();
} }
} }
void GC::Mark(TObject obj) { void GC::Mark(TObject obj) {
if (std::holds_alternative<THeapObjectHolder>(obj)) { if (std::holds_alternative<THeapObject *>(obj)) {
auto _item = std::get<THeapObjectHolder>(obj).obj; auto _item = std::get<THeapObject *>(obj);
_item->Mark(); _item->Mark();
} }
} }
void GC::Unwatch(TObject obj) { void GC::Unwatch(TObject obj) {
if (std::holds_alternative<THeapObjectHolder>(obj)) { if (std::holds_alternative<THeapObject *>(obj)) {
auto _item = std::get<THeapObjectHolder>(obj).obj; auto _item = std::get<THeapObject *>(obj);
this->BarrierBegin(); this->BarrierBegin();
for (auto index = this->objects.begin(); this->objects.erase(_item);
index != this->objects.end();) {
if (*index == _item) {
index = this->objects.erase(index);
continue;
}
index++;
}
this->BarrierEnd(); this->BarrierEnd();
} }
} }
void GC::SetRoot(TObject obj) { void GC::SetRoot(GCList *_item) {
if (std::holds_alternative<THeapObjectHolder>(obj)) { if (_item == nullptr)
auto _item = std::get<THeapObjectHolder>(obj).obj; return;
this->BarrierBegin(); this->BarrierBegin();
for (auto item : this->roots) { this->roots.insert(_item);
if (item == _item) { this->BarrierEnd();
this->BarrierEnd();
return;
}
}
this->roots.push_back(_item);
this->BarrierEnd();
}
} }
Tesses::Framework::Threading::ThreadPool *GC::GetPool() { Tesses::Framework::Threading::ThreadPool *GC::GetPool() {
return this->tpool->GetValue(); return this->tpool->GetValue();
} }
void GC::UnsetRoot(TObject obj) { void GC::UnsetRoot(GCList *_item) {
if (std::holds_alternative<THeapObjectHolder>(obj)) { if (_item == nullptr)
auto _item = std::get<THeapObjectHolder>(obj).obj; return;
this->BarrierBegin(); this->BarrierBegin();
for (auto index = this->roots.begin(); index != this->roots.end();) { this->roots.erase(_item);
if (*index == _item) { this->BarrierEnd();
index = this->roots.erase(index);
continue;
}
index++;
}
this->BarrierEnd();
}
} }
GC::~GC() { GC::~GC() {
GC::BarrierBegin();
this->roots.clear();
GC::BarrierEnd();
this->running = false; this->running = false;
this->cond.Signal();
this->thrd->Join(); this->thrd->Join();
delete this->thrd; delete this->thrd;
for (auto item : objects)
delete item;
delete this->tpool; delete this->tpool;
delete this->mtx;
} }
void GC::RegisterEverythingCallback( void GC::RegisterEverythingCallback(
@@ -218,23 +200,45 @@ void GC::RegisterEverything(TRootEnvironment *env) {
for (auto item : this->register_everything) for (auto item : this->register_everything)
item(this->shared_from_this(), env); item(this->shared_from_this(), env);
} }
void GC::Collect() {
this->BarrierBegin(); CallStackEntry *GC::GetCurrentFunction() {
#if defined(GEKKO) || defined(_EE)
current_funcs_mtx.Lock();
auto val = current_funcs[pthread_self()];
current_funcs_mtx.Unlock();
return val;
#else
return current_function;
#endif
}
void GC::SetCurrentFunction(CallStackEntry *cse) {
#if defined(GEKKO) || defined(_EE)
current_funcs_mtx.Lock();
current_funcs[pthread_self()] = cse;
current_funcs_mtx.Unlock();
#else
current_function = cse;
#endif
}
void GC::Collect(std::vector<THeapObject *> &to_delete) {
for (auto item : this->objects) { for (auto item : this->objects) {
item->marked = false; item->marked = false;
} }
for (auto item : this->roots) { for (auto item : this->roots) {
item->Mark(); item->Mark();
} }
for (auto index = this->objects.begin(); index != this->objects.end(); for (auto index = this->objects.begin(); index != this->objects.end();) {
index++) {
THeapObject *o = *index; THeapObject *o = *index;
if (!o->marked) { if (!o->marked) {
delete o; to_delete.push_back(o);
this->objects.erase(index); index = this->objects.erase(index);
index--; } else {
++index;
} }
} }
this->BarrierEnd();
} }
}; // namespace Tesses::CrossLang }; // namespace Tesses::CrossLang
+5 -6
View File
@@ -8,10 +8,10 @@ GCList::GCList(std::shared_ptr<GC> gc) {
gc->BarrierEnd(); gc->BarrierEnd();
} }
std::shared_ptr<GC> GCList::GetGC() { return this->gc; } std::shared_ptr<GC> GCList::GetGC() const { return this->gc; }
void GCList::Remove(TObject obj) { void GCList::Remove(TObject obj) {
if (std::holds_alternative<THeapObjectHolder>(obj)) { if (std::holds_alternative<THeapObject *>(obj)) {
auto _item = std::get<THeapObjectHolder>(obj).obj; auto _item = std::get<THeapObject *>(obj);
this->gc->BarrierBegin(); this->gc->BarrierBegin();
for (auto index = this->items.begin(); index != this->items.end(); for (auto index = this->items.begin(); index != this->items.end();
index++) { index++) {
@@ -25,8 +25,8 @@ void GCList::Remove(TObject obj) {
} }
void GCList::Add(TObject obj) { void GCList::Add(TObject obj) {
if (std::holds_alternative<THeapObjectHolder>(obj)) { if (std::holds_alternative<THeapObject *>(obj)) {
auto _item = std::get<THeapObjectHolder>(obj).obj; auto _item = std::get<THeapObject *>(obj);
this->gc->BarrierBegin(); this->gc->BarrierBegin();
for (auto item : this->items) { for (auto item : this->items) {
@@ -40,7 +40,6 @@ void GCList::Add(TObject obj) {
} }
} }
void GCList::Mark() { void GCList::Mark() {
this->marked = true;
for (auto item : this->items) { for (auto item : this->items) {
item->Mark(); item->Mark();
} }
+143 -139
View File
@@ -12,8 +12,6 @@
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
thread_local CallStackEntry *current_function = nullptr;
TObject ExecuteFunction(GCList &ls, TCallable *callable, TObject ExecuteFunction(GCList &ls, TCallable *callable,
std::vector<TObject> args) { std::vector<TObject> args) {
return callable->Call(ls, args); return callable->Call(ls, args);
@@ -81,8 +79,8 @@ bool InterperterThread::Times(std::shared_ptr<GC> gc) {
} else if (std::holds_alternative<int64_t>(left) && } else if (std::holds_alternative<int64_t>(left) &&
std::holds_alternative<double>(right)) { std::holds_alternative<double>(right)) {
cse.back()->Push(gc, std::get<int64_t>(left) * std::get<double>(right)); cse.back()->Push(gc, std::get<int64_t>(left) * std::get<double>(right));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -182,8 +180,8 @@ bool InterperterThread::Divide(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, std::get<int64_t>(left) / std::get<double>(right)); cse.back()->Push(gc, std::get<int64_t>(left) / std::get<double>(right));
} }
else if (std::holds_alternative<THeapObjectHolder>(left)) { else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -258,8 +256,8 @@ bool InterperterThread::Mod(std::shared_ptr<GC> gc) {
gc, fmod(std::get<int64_t>(left), std::get<double>(right))); gc, fmod(std::get<int64_t>(left), std::get<double>(right)));
} }
else if (std::holds_alternative<THeapObjectHolder>(left)) { else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -314,8 +312,8 @@ bool InterperterThread::Neg(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, -std::get<int64_t>(left)); cse.back()->Push(gc, -std::get<int64_t>(left));
} else if (std::holds_alternative<double>(left)) { } else if (std::holds_alternative<double>(left)) {
cse.back()->Push(gc, -std::get<double>(left)); cse.back()->Push(gc, -std::get<double>(left));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -367,7 +365,7 @@ bool InterperterThread::LNot(std::shared_ptr<GC> gc) {
if (std::holds_alternative<Undefined>(left)) { if (std::holds_alternative<Undefined>(left)) {
cse.back()->Push(gc, true); cse.back()->Push(gc, true);
} else if (std::holds_alternative<std::nullptr_t>(left)) { } else if (IsNull(left)) {
cse.back()->Push(gc, true); cse.back()->Push(gc, true);
} }
@@ -377,8 +375,8 @@ bool InterperterThread::LNot(std::shared_ptr<GC> gc) {
else if (std::holds_alternative<bool>(left)) { else if (std::holds_alternative<bool>(left)) {
cse.back()->Push(gc, !std::get<bool>(left)); cse.back()->Push(gc, !std::get<bool>(left));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -433,8 +431,8 @@ bool InterperterThread::BNot(std::shared_ptr<GC> gc) {
cse.back()->Push(gc, ~std::get<int64_t>(left)); cse.back()->Push(gc, ~std::get<int64_t>(left));
} }
else if (std::holds_alternative<THeapObjectHolder>(left)) { else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -540,8 +538,8 @@ bool InterperterThread::Lt(std::shared_ptr<GC> gc) {
auto &r = auto &r =
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right); std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
cse.back()->Push(gc, l->TotalSeconds() < r->TotalSeconds()); cse.back()->Push(gc, l->TotalSeconds() < r->TotalSeconds());
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -646,8 +644,8 @@ bool InterperterThread::Gt(std::shared_ptr<GC> gc) {
auto &r = auto &r =
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right); std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
cse.back()->Push(gc, l->TotalSeconds() > r->TotalSeconds()); cse.back()->Push(gc, l->TotalSeconds() > r->TotalSeconds());
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -753,8 +751,8 @@ bool InterperterThread::Lte(std::shared_ptr<GC> gc) {
auto &r = auto &r =
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right); std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
cse.back()->Push(gc, l->TotalSeconds() <= r->TotalSeconds()); cse.back()->Push(gc, l->TotalSeconds() <= r->TotalSeconds());
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -865,8 +863,8 @@ bool InterperterThread::Gte(std::shared_ptr<GC> gc) {
auto &r = auto &r =
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right); std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
cse.back()->Push(gc, l->TotalSeconds() >= r->TotalSeconds()); cse.back()->Push(gc, l->TotalSeconds() >= r->TotalSeconds());
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -919,8 +917,7 @@ bool InterperterThread::Eq(std::shared_ptr<GC> gc) {
GCList ls(gc); GCList ls(gc);
auto right = cse.back()->Pop(ls); auto right = cse.back()->Pop(ls);
auto left = cse.back()->Pop(ls); auto left = cse.back()->Pop(ls);
if (std::holds_alternative<std::nullptr_t>(left) && if (IsNull(left) && IsNull(right)) {
std::holds_alternative<std::nullptr_t>(right)) {
cse.back()->Push(gc, true); cse.back()->Push(gc, true);
return false; return false;
} }
@@ -1002,8 +999,8 @@ bool InterperterThread::Eq(std::shared_ptr<GC> gc) {
auto &r = auto &r =
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right); std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
cse.back()->Push(gc, l->TotalSeconds() == r->TotalSeconds()); cse.back()->Push(gc, l->TotalSeconds() == r->TotalSeconds());
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -1041,25 +1038,23 @@ bool InterperterThread::Eq(std::shared_ptr<GC> gc) {
else if (dynDict != nullptr) { else if (dynDict != nullptr) {
auto res = dynDict->CallMethod(ls, "operator==", {right}); auto res = dynDict->CallMethod(ls, "operator==", {right});
if (!std::holds_alternative<std::nullptr_t>(res) && if (!IsNull(res) && std::holds_alternative<Undefined>(res)) {
std::holds_alternative<Undefined>(res)) {
cse.back()->Push(gc, res); cse.back()->Push(gc, res);
return false; return false;
} }
} }
else if (native != nullptr && else if (native != nullptr && IsNull(right)) {
std::holds_alternative<std::nullptr_t>(right)) {
cse.back()->Push(gc, native->GetDestroyed()); cse.back()->Push(gc, native->GetDestroyed());
return false; return false;
} }
if (std::holds_alternative<THeapObjectHolder>(right)) { if (std::holds_alternative<THeapObject *>(right)) {
cse.back()->Push(gc, obj == std::get<THeapObjectHolder>(right).obj); cse.back()->Push(gc, obj == std::get<THeapObject *>(right));
return false; return false;
} }
else if (std::holds_alternative<std::nullptr_t>(right)) { else if (IsNull(right)) {
cse.back()->Push(gc, false); cse.back()->Push(gc, false);
return false; return false;
} else if (std::holds_alternative<Undefined>(right)) { } else if (std::holds_alternative<Undefined>(right)) {
@@ -1071,7 +1066,7 @@ bool InterperterThread::Eq(std::shared_ptr<GC> gc) {
} }
else if (std::holds_alternative<std::nullptr_t>(right)) { else if (IsNull(right)) {
cse.back()->Push(gc, false); cse.back()->Push(gc, false);
return false; return false;
} else if (std::holds_alternative<Undefined>(right)) { } else if (std::holds_alternative<Undefined>(right)) {
@@ -1089,8 +1084,7 @@ bool InterperterThread::NEq(std::shared_ptr<GC> gc) {
auto right = cse.back()->Pop(ls); auto right = cse.back()->Pop(ls);
auto left = cse.back()->Pop(ls); auto left = cse.back()->Pop(ls);
if (std::holds_alternative<std::nullptr_t>(left) && if (IsNull(left) && IsNull(right)) {
std::holds_alternative<std::nullptr_t>(right)) {
cse.back()->Push(gc, false); cse.back()->Push(gc, false);
return false; return false;
} else if (std::holds_alternative<Undefined>(left) && } else if (std::holds_alternative<Undefined>(left) &&
@@ -1160,8 +1154,8 @@ bool InterperterThread::NEq(std::shared_ptr<GC> gc) {
auto &r = auto &r =
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right); std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
cse.back()->Push(gc, l->TotalSeconds() != r->TotalSeconds()); cse.back()->Push(gc, l->TotalSeconds() != r->TotalSeconds());
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto native = dynamic_cast<TNative *>(obj); auto native = dynamic_cast<TNative *>(obj);
auto natObj = dynamic_cast<TNativeObject *>(obj); auto natObj = dynamic_cast<TNativeObject *>(obj);
@@ -1198,22 +1192,20 @@ bool InterperterThread::NEq(std::shared_ptr<GC> gc) {
else if (dynDict != nullptr) { else if (dynDict != nullptr) {
auto res = dynDict->CallMethod(ls, "operator!=", {right}); auto res = dynDict->CallMethod(ls, "operator!=", {right});
if (!std::holds_alternative<std::nullptr_t>(res) && if (!IsNull(res) && std::holds_alternative<Undefined>(res)) {
std::holds_alternative<Undefined>(res)) {
cse.back()->Push(gc, res); cse.back()->Push(gc, res);
return false; return false;
} }
} }
else if (native != nullptr && else if (native != nullptr && IsNull(right)) {
std::holds_alternative<std::nullptr_t>(right)) {
cse.back()->Push(gc, !native->GetDestroyed()); cse.back()->Push(gc, !native->GetDestroyed());
return false; return false;
} }
if (std::holds_alternative<THeapObjectHolder>(right)) { if (std::holds_alternative<THeapObject *>(right)) {
cse.back()->Push(gc, obj != std::get<THeapObjectHolder>(right).obj); cse.back()->Push(gc, obj != std::get<THeapObject *>(right));
return false; return false;
} else if (std::holds_alternative<std::nullptr_t>(right)) { } else if (IsNull(right)) {
cse.back()->Push(gc, true); cse.back()->Push(gc, true);
return false; return false;
} else if (std::holds_alternative<Undefined>(right)) { } else if (std::holds_alternative<Undefined>(right)) {
@@ -1226,7 +1218,7 @@ bool InterperterThread::NEq(std::shared_ptr<GC> gc) {
} else if (std::holds_alternative<Undefined>(right)) { } else if (std::holds_alternative<Undefined>(right)) {
cse.back()->Push(gc, true); cse.back()->Push(gc, true);
return false; return false;
} else if (std::holds_alternative<std::nullptr_t>(right)) { } else if (IsNull(right)) {
cse.back()->Push(gc, true); cse.back()->Push(gc, true);
return false; return false;
} else { } else {
@@ -1245,8 +1237,8 @@ bool InterperterThread::LShift(std::shared_ptr<GC> gc) {
std::holds_alternative<int64_t>(right)) { std::holds_alternative<int64_t>(right)) {
cse.back()->Push(gc, std::get<int64_t>(left) cse.back()->Push(gc, std::get<int64_t>(left)
<< (int)std::get<int64_t>(right)); << (int)std::get<int64_t>(right));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -1303,8 +1295,8 @@ bool InterperterThread::RShift(std::shared_ptr<GC> gc) {
std::holds_alternative<int64_t>(right)) { std::holds_alternative<int64_t>(right)) {
cse.back()->Push(gc, std::get<int64_t>(left) >> cse.back()->Push(gc, std::get<int64_t>(left) >>
(int)std::get<int64_t>(right)); (int)std::get<int64_t>(right));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -1361,8 +1353,8 @@ bool InterperterThread::BOr(std::shared_ptr<GC> gc) {
std::holds_alternative<int64_t>(right)) { std::holds_alternative<int64_t>(right)) {
cse.back()->Push(gc, cse.back()->Push(gc,
std::get<int64_t>(left) | std::get<int64_t>(right)); std::get<int64_t>(left) | std::get<int64_t>(right));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -1419,8 +1411,8 @@ bool InterperterThread::XOr(std::shared_ptr<GC> gc) {
std::holds_alternative<int64_t>(right)) { std::holds_alternative<int64_t>(right)) {
cse.back()->Push(gc, cse.back()->Push(gc,
std::get<int64_t>(left) ^ std::get<int64_t>(right)); std::get<int64_t>(left) ^ std::get<int64_t>(right));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -1476,8 +1468,8 @@ bool InterperterThread::BAnd(std::shared_ptr<GC> gc) {
std::holds_alternative<int64_t>(right)) { std::holds_alternative<int64_t>(right)) {
cse.back()->Push(gc, cse.back()->Push(gc,
std::get<int64_t>(left) & std::get<int64_t>(right)); std::get<int64_t>(left) & std::get<int64_t>(right));
} else if (std::holds_alternative<THeapObjectHolder>(left)) { } else if (std::holds_alternative<THeapObject *>(left)) {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObject *>(left);
auto dict = dynamic_cast<TDictionary *>(obj); auto dict = dynamic_cast<TDictionary *>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj); auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
@@ -1522,10 +1514,9 @@ bool InterperterThread::BAnd(std::shared_ptr<GC> gc) {
return false; return false;
} }
bool InterperterThread::InvokeOne(GCList &ls, TObject fn, TObject arg) { bool InterperterThread::InvokeOne(GCList &ls, TObject fn, TObject arg) {
if (std::holds_alternative<THeapObjectHolder>(fn)) { if (std::holds_alternative<THeapObject *>(fn)) {
auto obj = auto obj = dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
dynamic_cast<TCallable *>(std::get<THeapObjectHolder>(fn).obj);
if (obj != nullptr) { if (obj != nullptr) {
auto closure = dynamic_cast<TClosure *>(obj); auto closure = dynamic_cast<TClosure *>(obj);
if (closure != nullptr) { if (closure != nullptr) {
@@ -1570,10 +1561,10 @@ bool InterperterThread::ExecuteFunction(std::shared_ptr<GC> gc) {
if (args.size() == 3) { if (args.size() == 3) {
if (std::holds_alternative<std::string>(args[1]) && if (std::holds_alternative<std::string>(args[1]) &&
std::holds_alternative<THeapObjectHolder>(args[2])) { std::holds_alternative<THeapObject *>(args[2])) {
std::string key = std::get<std::string>(args[1]); std::string key = std::get<std::string>(args[1]);
TList *ls = dynamic_cast<TList *>( TList *ls = dynamic_cast<TList *>(
std::get<THeapObjectHolder>(args[2]).obj); std::get<THeapObject *>(args[2]));
if (ls != nullptr) if (ls != nullptr)
return ExecuteMethod2(gc, args[0], key, ls->items); return ExecuteMethod2(gc, args[0], key, ls->items);
} }
@@ -1582,10 +1573,10 @@ bool InterperterThread::ExecuteFunction(std::shared_ptr<GC> gc) {
return false; return false;
} }
if (std::holds_alternative<THeapObjectHolder>(fn)) { if (std::holds_alternative<THeapObject *>(fn)) {
auto obj = dynamic_cast<TCallable *>( auto obj =
std::get<THeapObjectHolder>(fn).obj); dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
if (obj != nullptr) { if (obj != nullptr) {
auto closure = dynamic_cast<TClosure *>(obj); auto closure = dynamic_cast<TClosure *>(obj);
if (closure != nullptr) { if (closure != nullptr) {
@@ -2051,7 +2042,8 @@ bool InterperterThread::DeclareConstVariable(std::shared_ptr<GC> gc) {
throw VMException( throw VMException(
"[DECLARECONSTVARIABLE] Can't pop string, got type " + "[DECLARECONSTVARIABLE] Can't pop string, got type " +
GetObjectTypeString(key) + " = " + ToString(gc, key) + "."); GetObjectTypeString(key) + " = " + ObjectToString(gc, key) +
".");
} }
} }
return false; return false;
@@ -2069,10 +2061,8 @@ bool InterperterThread::PushResourceStream(std::shared_ptr<GC> gc) {
gc->BarrierBegin(); gc->BarrierBegin();
GCList ls(gc); GCList ls(gc);
// TByteArray* arr = TByteArray::Create(ls); stk->Push(gc, ls.Create<TStream>(std::make_shared<EmbedStream>(
// arr->data = stk->callable->file->resources[n]; gc, stk->callable->file->resources[n])));
stk->Push(
gc, std::make_shared<EmbedStream>(gc, stk->callable->file, n));
gc->BarrierEnd(); gc->BarrierEnd();
} else { } else {
@@ -2095,9 +2085,9 @@ bool InterperterThread::PushResource(std::shared_ptr<GC> gc) {
gc->BarrierBegin(); gc->BarrierBegin();
GCList ls(gc); GCList ls(gc);
TByteArray *arr = TByteArray::Create(ls);
arr->data = stk->callable->file->resources[n]; stk->Push(gc,
stk->Push(gc, arr); ls.Create<TByteArray>(stk->callable->file->resources[n]));
gc->BarrierEnd(); gc->BarrierEnd();
} else { } else {
@@ -2113,8 +2103,14 @@ bool InterperterThread::Throw(std::shared_ptr<GC> gc) {
if (!std::holds_alternative<Undefined>(_res2)) { if (!std::holds_alternative<Undefined>(_res2)) {
auto env = cse.back()->env; auto env = cse.back()->env;
if (!env->GetRootEnvironment()->HandleException(gc, env, _res2)) if (!env->GetRootEnvironment()->HandleException(gc, env, _res2)) {
TNativeException *nex;
if (GetObjectHeap(_res2, nex)) {
nex->ThrowIt();
}
throw VMByteCodeException(gc, _res2, cse.back()); throw VMByteCodeException(gc, _res2, cse.back());
}
} }
return false; return false;
} }
@@ -2143,8 +2139,7 @@ bool InterperterThread::JumpIfDefined(std::shared_ptr<GC> gc) {
auto _res2 = stk->Pop(ls); auto _res2 = stk->Pop(ls);
stk->ip = stk->ip + 4; stk->ip = stk->ip + 4;
if (!std::holds_alternative<Undefined>(_res2) && if (!std::holds_alternative<Undefined>(_res2) && !IsNull(_res2)) {
!std::holds_alternative<std::nullptr_t>(_res2)) {
stk->ip = n; stk->ip = n;
stk->Push(gc, _res2); stk->Push(gc, _res2);
} }
@@ -2223,6 +2218,7 @@ bool InterperterThread::JumpUndefined(std::shared_ptr<GC> gc) {
bool InterperterThread::Jump(std::shared_ptr<GC> gc) { bool InterperterThread::Jump(std::shared_ptr<GC> gc) {
std::vector<CallStackEntry *> &cse = this->call_stack_entries; std::vector<CallStackEntry *> &cse = this->call_stack_entries;
auto stk = cse.back(); auto stk = cse.back();
if (stk->ip + 4 <= stk->callable->closure->code.size()) { if (stk->ip + 4 <= stk->callable->closure->code.size()) {
@@ -2316,9 +2312,8 @@ bool InterperterThread::AppendList(std::shared_ptr<GC> gc) {
gc->BarrierBegin(); gc->BarrierBegin();
auto obj = stk->Pop(ls); auto obj = stk->Pop(ls);
auto objhold = stk->Pop(ls); auto objhold = stk->Pop(ls);
if (std::holds_alternative<THeapObjectHolder>(objhold)) { if (std::holds_alternative<THeapObject *>(objhold)) {
auto list = auto list = dynamic_cast<TList *>(std::get<THeapObject *>(objhold));
dynamic_cast<TList *>(std::get<THeapObjectHolder>(objhold).obj);
if (list != nullptr) { if (list != nullptr) {
list->Add(obj); list->Add(obj);
} }
@@ -2348,12 +2343,12 @@ bool InterperterThread::AppendDictionary(std::shared_ptr<GC> gc) {
auto value = stk->Pop(ls); auto value = stk->Pop(ls);
auto k = stk->Pop(ls); auto k = stk->Pop(ls);
auto objhold = stk->Pop(ls); auto objhold = stk->Pop(ls);
if (std::holds_alternative<THeapObjectHolder>(objhold) && if (std::holds_alternative<THeapObject *>(objhold) &&
std::holds_alternative<std::string>(k)) { std::holds_alternative<std::string>(k)) {
auto dict = dynamic_cast<TDictionary *>( auto dict =
std::get<THeapObjectHolder>(objhold).obj); dynamic_cast<TDictionary *>(std::get<THeapObject *>(objhold));
auto cls = dynamic_cast<TClassObject *>( auto cls =
std::get<THeapObjectHolder>(objhold).obj); dynamic_cast<TClassObject *>(std::get<THeapObject *>(objhold));
if (dict != nullptr) { if (dict != nullptr) {
dict->SetValue(std::get<std::string>(k), value); dict->SetValue(std::get<std::string>(k), value);
@@ -2383,7 +2378,7 @@ bool InterperterThread::CreateArray(std::shared_ptr<GC> gc) {
std::vector<CallStackEntry *> &cse = this->call_stack_entries; std::vector<CallStackEntry *> &cse = this->call_stack_entries;
auto stk = cse.back(); auto stk = cse.back();
GCList ls(gc); GCList ls(gc);
TList *dict = TList::Create(ls); TList *dict = ls.Create<TList>();
stk->Push(gc, dict); stk->Push(gc, dict);
return false; return false;
} }
@@ -2409,23 +2404,39 @@ bool InterperterThread::TryCatch(std::shared_ptr<GC> gc) {
if (GetObjectHeap(tryFn, tryC) && GetObjectHeap(catchFn, catchC)) { if (GetObjectHeap(tryFn, tryC) && GetObjectHeap(catchFn, catchC)) {
try { try {
stk->Push(gc, tryC->Call(ls, {})); stk->Push(gc, tryC->Call(ls, {}));
}
catch (std::exception &ex) { } catch (std::bad_alloc &ex) {
TDictionary *dict = TDictionary::Create(ls); std::cerr
auto gc = ls.GetGC(); << "CrossLang has failed to allocate, sorry for termination."
auto myEx = dynamic_cast<VMByteCodeException *>(&ex); << std::endl;
if (myEx != nullptr) { std::exit(1);
stk->Push(gc, catchC->Call(ls, {myEx->exception})); } catch (const std::string &ex) {
} else { stk->Push(gc, catchC->Call(ls, {ex}));
gc->BarrierBegin(); } catch (const char *ex) {
dict->SetValue("Type", "NativeException"); stk->Push(gc,
dict->SetValue("Text", ex.what()); catchC->Call(ls, {std::string{ex != nullptr ? ex : ""}}));
gc->BarrierEnd(); } catch (std::runtime_error &ex) {
stk->Push(gc, catchC->Call(ls, {dict})); stk->Push(
} gc, catchC->Call(ls, {TNativeObject::Create<TException>(
ls, ex.what(), "RuntimeException")}));
} catch (VMException &ex) {
stk->Push(
gc, catchC->Call(ls, {TNativeObject::Create<TException>(
ls, ex.GetMessage(), "VMException")}));
} catch (VMByteCodeException &ex) {
stk->Push(gc, catchC->Call(ls, {ex.exception}));
} catch (std::exception &ex) {
stk->Push(gc,
catchC->Call(
ls, {TNativeObject::Create<TNativeException>(
ls, ex.what(), std::current_exception())}));
} catch (...) {
stk->Push(gc,
catchC->Call(ls, {TNativeObject::Create<TNativeException>(
ls, "<No Message>",
std::current_exception())}));
} }
} }
return false; return false;
@@ -2693,14 +2704,14 @@ void InterperterThread::Execute(std::shared_ptr<GC> gc) {
std::vector<CallStackEntry *> &cse = this->call_stack_entries; std::vector<CallStackEntry *> &cse = this->call_stack_entries;
#define VM_OPCODE_TABLE_INLINE #define VM_OPCODE_TABLE_INLINE
#include "vm_opcode_table.h" #include "vm_opcode_table.def"
#undef VM_OPCODE_TABLE_INLINE #undef VM_OPCODE_TABLE_INLINE
execute: execute:
if (!cse.empty()) { if (!cse.empty()) {
auto stk = cse.back(); auto stk = cse.back();
current_function = stk; GC::SetCurrentFunction(stk);
try { try {
while (stk->ip < 0xFFFFFFFF && while (stk->ip < 0xFFFFFFFF &&
@@ -2721,7 +2732,7 @@ execute:
cse[cse.size() - 2]->Push(gc, o); cse[cse.size() - 2]->Push(gc, o);
cse.erase(cse.end() - 1); cse.erase(cse.end() - 1);
current_function = cse.back(); GC::SetCurrentFunction(cse.back());
gc->BarrierEnd(); gc->BarrierEnd();
goto execute; goto execute;
} else { } else {
@@ -2729,8 +2740,13 @@ execute:
} }
} }
if (gc->UsingNullThreads()) if (gc->UsingNullThreads()) {
gc->Collect(); std::vector<THeapObject *> objs;
gc->Collect(objs);
for (auto &item : objs) {
delete item;
}
}
} }
stk->mustReturn = false; stk->mustReturn = false;
@@ -2764,7 +2780,7 @@ execute:
} }
if (cse.size() == 1) { if (cse.size() == 1) {
current_function = nullptr; GC::SetCurrentFunction(nullptr);
{ {
gc->BarrierBegin(); gc->BarrierBegin();
@@ -2817,7 +2833,7 @@ execute:
cse[cse.size() - 2]->Push(gc, o); cse[cse.size() - 2]->Push(gc, o);
cse.erase(cse.end() - 1); cse.erase(cse.end() - 1);
current_function = cse.back(); GC::SetCurrentFunction(cse.back());
gc->BarrierEnd(); gc->BarrierEnd();
for (auto item : callable) { for (auto item : callable) {
@@ -2846,7 +2862,7 @@ void CallStackEntry::Push(std::shared_ptr<GC> gc, TObject o) {
gc->BarrierEnd(); gc->BarrierEnd();
} }
TObject CallStackEntry::Resume(GCList &ls) { TObject CallStackEntry::Resume(GCList &ls) {
auto cse = current_function; auto cse = GC::GetCurrentFunction();
InterperterThread *thrd = InterperterThread::Create(ls); InterperterThread *thrd = InterperterThread::Create(ls);
ls.GetGC()->BarrierBegin(); ls.GetGC()->BarrierBegin();
thrd->call_stack_entries.push_back(this); thrd->call_stack_entries.push_back(this);
@@ -2855,7 +2871,7 @@ TObject CallStackEntry::Resume(GCList &ls) {
thrd->Execute(ls.GetGC()); thrd->Execute(ls.GetGC());
TObject v = thrd->call_stack_entries[0]->Pop(ls); TObject v = thrd->call_stack_entries[0]->Pop(ls);
current_function = cse; GC::SetCurrentFunction(cse);
return v; return v;
} }
TObject CallStackEntry::Pop(GCList &gc) { TObject CallStackEntry::Pop(GCList &gc) {
@@ -2870,41 +2886,17 @@ TObject CallStackEntry::Pop(GCList &gc) {
} }
InterperterThread *InterperterThread::Create(GCList &ls) { InterperterThread *InterperterThread::Create(GCList &ls) {
InterperterThread *it = new InterperterThread(); return ls.Create<InterperterThread>();
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(it);
_gc->Watch(it);
return it;
} }
InterperterThread *InterperterThread::Create(GCList *ls) { InterperterThread *InterperterThread::Create(GCList *ls) {
InterperterThread *it = new InterperterThread(); return ls->Create<InterperterThread>();
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(it);
_gc->Watch(it);
return it;
} }
CallStackEntry *CallStackEntry::Create(GCList &ls) { CallStackEntry *CallStackEntry::Create(GCList &ls) {
CallStackEntry *cse = new CallStackEntry(); return ls.Create<CallStackEntry>();
cse->mustReturn = false;
cse->srcline = -1;
cse->srcfile = "";
cse->thread = nullptr;
std::shared_ptr<GC> _gc = ls.GetGC();
ls.Add(cse);
_gc->Watch(cse);
return cse;
} }
CallStackEntry *CallStackEntry::Create(GCList *ls) { CallStackEntry *CallStackEntry::Create(GCList *ls) {
CallStackEntry *cse = new CallStackEntry(); return ls->Create<CallStackEntry>();
cse->mustReturn = false;
cse->srcline = -1;
cse->srcfile = "";
cse->thread = nullptr;
std::shared_ptr<GC> _gc = ls->GetGC();
ls->Add(cse);
_gc->Watch(cse);
return cse;
} }
void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure, void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
std::vector<TObject> args) { std::vector<TObject> args) {
@@ -2917,7 +2909,7 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
: closure->env; : closure->env;
cse->ip = 0; cse->ip = 0;
if (closure->closure->args.empty() && closure->chunkId != 0) { if (closure->closure->args.empty() && closure->chunkId != 0) {
TList *list = TList::Create(ls); TList *list = ls.Create<TList>();
list->items = args; list->items = args;
cse->env->DeclareVariable("arguments", list); cse->env->DeclareVariable("arguments", list);
@@ -2963,13 +2955,25 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
cse->env->DeclareVariable(trimStart(closure->closure->args[i]), cse->env->DeclareVariable(trimStart(closure->closure->args[i]),
args[i]); args[i]);
} }
for (; i < closure->closure->args.size(); i++) {
auto &a = closure->closure->args[i];
if (a.size() > 1 && a[0] == '$') {
if (a[1] == '$') {
break;
}
cse->env->DeclareVariable(trimStart(a), Undefined());
} else {
break;
}
}
std::string back = closure->closure->args.empty() std::string back = closure->closure->args.empty()
? std::string() ? std::string()
: closure->closure->args.back(); : closure->closure->args.back();
if (i == closure->closure->args.size() - 1 && back.size() > 2 && if (i == closure->closure->args.size() - 1 && back.size() > 2 &&
back[0] == '$' && back[1] == '$') { back[0] == '$' && back[1] == '$') {
auto argName = closure->closure->args[i]; auto argName = closure->closure->args[i];
auto lsArgs = TList::Create(ls); auto lsArgs = ls.Create<TList>();
for (; i < args.size(); i++) for (; i < args.size(); i++)
lsArgs->Add(args[i]); lsArgs->Add(args[i]);
cse->env->DeclareVariable(trimStart(argName), lsArgs); cse->env->DeclareVariable(trimStart(argName), lsArgs);
@@ -2979,7 +2983,7 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
throw VMException("Too many arguments"); throw VMException("Too many arguments");
} }
current_function = cse; GC::SetCurrentFunction(cse);
this->call_stack_entries.push_back(cse); this->call_stack_entries.push_back(cse);
ls.GetGC()->BarrierEnd(); ls.GetGC()->BarrierEnd();