xo-object: initial implementation [wip]
This commit is contained in:
commit
d830632aea
16 changed files with 652 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# emacs projectile config
|
||||
.projectile
|
||||
# clangd working space (see emacs+lsp)
|
||||
.cache
|
||||
# typical cmake build directory (source-tree-nephew)
|
||||
.build*
|
||||
# symlink to builddir/compile_commands.json; should be set manually in dev sandbox
|
||||
compile_commands.json
|
||||
34
CMakeLists.txt
Normal file
34
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# xo-object/CMakeLists.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(xo_object VERSION 0.1)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(cmake/xo-bootstrap-macros.cmake)
|
||||
|
||||
xo_cxx_toplevel_options3()
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# c++ settings
|
||||
|
||||
set(PROJECT_CXX_FLAGS "")
|
||||
#set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") # gcc-only!
|
||||
add_definitions(${PROJECT_CXX_FLAGS})
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# must complete definition of object lib before configuring examples
|
||||
add_subdirectory(src/object)
|
||||
|
||||
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
add_subdirectory(example)
|
||||
#add_subdirectory(utest)
|
||||
|
||||
# reminder: must come last: docs targets depend on all the other library/utest targets
|
||||
#add_subdirectory(docs)
|
||||
|
||||
# end CMakeLists.txt
|
||||
29
LICENSE
Normal file
29
LICENSE
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
Copyright (c) 2024 Roland Conybeare <git3ub@nym.hush.com>, All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of
|
||||
external contributions to this project including patches, pull requests, etc.
|
||||
57
README.md
Normal file
57
README.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# xo-object library
|
||||
|
||||
A library for scaffolding an object hierarchy for dynamic typing.
|
||||
Using this for interpreter integration with schematica
|
||||
|
||||
## Getting Started
|
||||
|
||||
### build + install `xo-cmake` dependency
|
||||
|
||||
- [github/Rconybea/xo-cmake](https://github.com/Rconybea/xo-cmake)
|
||||
|
||||
Installs a few cmake ingredients, along with a build assistant `xo-build` for XO projects such as this one.
|
||||
|
||||
### build + install other necessary XO dependencies
|
||||
```
|
||||
$ xo-build --clone --configure --build --install xo-indentlog
|
||||
$ xo-build --clone --configure --build --install xo-refnct
|
||||
$ xo-build --clone --configure --build --install xo-subsys
|
||||
$ xo-build --clone --configure --build --install xo-reflect
|
||||
```
|
||||
|
||||
Note: can use `xo-build -n` to dry-run here
|
||||
|
||||
### copy `xo-object` repository locally
|
||||
```
|
||||
$ xo-build --clone xo-object
|
||||
```
|
||||
|
||||
or equivalently
|
||||
```
|
||||
$ git clone git@github.com:Rconybea/xo-object.git
|
||||
```
|
||||
|
||||
### build + install xo-object
|
||||
```
|
||||
$ xo-build --configure --build --install xo-object
|
||||
```
|
||||
|
||||
or equivalently:
|
||||
```
|
||||
$ PREFIX=/usr/local # or wherever you prefer
|
||||
$ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} -S xo-object -B xo-object/.build
|
||||
$ cmake --build xo-object/.build
|
||||
$ cmake --install xo-object/.build
|
||||
```
|
||||
|
||||
### build for unit test coverage
|
||||
```
|
||||
$ cmake -DCMAKE_BUILD_TYPE=coverage -DCMAKE_INSTALL_PREFIX=$PREFIX xo-object/.build-ccov
|
||||
$ cmake --build xo-object/.build-ccov
|
||||
```
|
||||
|
||||
### LSP support
|
||||
```
|
||||
$ cd xo-object
|
||||
$ ln -s build/compile_commands.json # lsp will look for compile_commands.json in the root of the source tree
|
||||
```
|
||||
35
cmake/xo-bootstrap-macros.cmake
Executable file
35
cmake/xo-bootstrap-macros.cmake
Executable file
|
|
@ -0,0 +1,35 @@
|
|||
# ----------------------------------------------------------------
|
||||
# for example:
|
||||
# $ PREFIX=/usr/local # for example
|
||||
# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build
|
||||
#
|
||||
# will get
|
||||
# CMAKE_MODULE_PATH
|
||||
# from xo-cmake-config --cmake-module-path
|
||||
#
|
||||
# and expect .cmake macros in
|
||||
# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED)
|
||||
|
||||
if ("${XO_CMAKE_CONFIG_EXECUTABLE}" STREQUAL "XO_CMAKE_CONFIG_EXECUTABLE-NOT_FOUND")
|
||||
message(FATAL "could not find xo-cmake-config executable")
|
||||
endif()
|
||||
|
||||
message(STATUS "XO_CMAKE_CONFIG_EXECUTABLE=${XO_CMAKE_CONFIG_EXECUTABLE}")
|
||||
|
||||
if (NOT XO_SUBMODULE_BUILD)
|
||||
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix))
|
||||
# default to typical install location for xo-project-macros
|
||||
execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH)
|
||||
message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# needs to have been installed somewhere on CMAKE_MODULE_PATH,
|
||||
# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX)
|
||||
#
|
||||
include(xo_macros/xo_cxx)
|
||||
|
||||
xo_cxx_bootstrap_message()
|
||||
6
cmake/xo_objectConfig.cmake.in
Normal file
6
cmake/xo_objectConfig.cmake.in
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(xo_reflect)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
||||
1
example/CMakeLists.txt
Normal file
1
example/CMakeLists.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
add_subdirectory(ex1)
|
||||
12
example/ex1/CMakeLists.txt
Normal file
12
example/ex1/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# xo-object/example/ex1/CMakeLists.txt
|
||||
|
||||
set(SELF_EXE xo_object_ex1)
|
||||
set(SELF_SRCS ex1.cpp)
|
||||
|
||||
if (XO_ENABLE_EXAMPLES)
|
||||
xo_add_executable(${SELF_EXE} ${SELF_SRCS})
|
||||
xo_self_headeronly_dependency(${SELF_EXE} xo_reflect)
|
||||
xo_dependency(${SELF_EXE} xo_flatstring)
|
||||
endif()
|
||||
|
||||
# end CMakeLists.txt
|
||||
14
example/ex1/ex1.cpp
Normal file
14
example/ex1/ex1.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* @file ex1.cpp */
|
||||
|
||||
#include "xo/object/object.hpp"
|
||||
#include <iostream>
|
||||
|
||||
int
|
||||
main() {
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
cout << "hello, world!" << endl;
|
||||
}
|
||||
|
||||
/* end ex1.cpp */
|
||||
21
include/xo/object/cons.hpp
Normal file
21
include/xo/object/cons.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/** @file cons.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#Include "variant.hpp"
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace var {
|
||||
struct cons {
|
||||
variant car_;
|
||||
variant cdr_;
|
||||
};
|
||||
} /*namespace var*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end cons.hpp **/
|
||||
205
include/xo/object/object.hpp
Normal file
205
include/xo/object/object.hpp
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/** @file object.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/reflect/Object.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace obj {
|
||||
enum class otag : std::uint16_t {
|
||||
ot_invalid = static_cast<uint16_t>(-1),
|
||||
ot_sentinel = 0x00,
|
||||
ot_boolean = 0x01,
|
||||
ot_char = 0x02,
|
||||
ot_i32 = 0x03,
|
||||
ot_f32 = 0x04,
|
||||
|
||||
/* 0x05, 0x06, 0x07 reserved */
|
||||
|
||||
ot_i64 = 0x08,
|
||||
ot_f64 = 0x09,
|
||||
ot_zstring = 0x0a,
|
||||
ot_symbol = 0x0b,
|
||||
ot_cons = 0x0c,
|
||||
|
||||
/* 0x0d, 0x0e reserved */
|
||||
ot_rc_object = 0x10, /* refcounted pointer to xo::reflect::Object */
|
||||
};
|
||||
|
||||
class cons;
|
||||
class zstring;
|
||||
class symbol;
|
||||
|
||||
/** @class object
|
||||
*
|
||||
* @brief dynamically tyyped object; support for schematica
|
||||
**/
|
||||
class object {
|
||||
public:
|
||||
using Object = xo::reflect::Object;
|
||||
|
||||
/** tags involving pointers use values 0x08 .. 0x10 **/
|
||||
static constexpr uint16_t c_tag_pointer_mask = 0xfff8;
|
||||
|
||||
/** number of pointer bits stolen for type tag **/
|
||||
static constexpr int c_tag_bits = 16;
|
||||
/** number of pointer bits remaining after hi tag bits stolen **/
|
||||
static constexpr int c_ptr_bits = 64 - c_tag_bits;
|
||||
|
||||
static constexpr std::uint64_t c_tag_mask = (0UL - 1) << c_ptr_bits;
|
||||
static constexpr std::uint64_t c_ptr_mask = (0UL - 1) >> c_tag_bits;
|
||||
|
||||
public:
|
||||
object() = default;
|
||||
object(const object & x);
|
||||
|
||||
otag tag() const noexcept { return (static_cast<otag>(value_ >> c_ptr_bits)); }
|
||||
std::uint64_t masked_value() const noexcept { return value_ & c_ptr_mask; }
|
||||
|
||||
std::int32_t as_int32(std::int32_t sentinel = 0) const noexcept {
|
||||
if (tag() == otag::ot_i32) {
|
||||
return masked_value();
|
||||
} else {
|
||||
return sentinel;
|
||||
}
|
||||
}
|
||||
|
||||
float as_float32(float sentinel = std::numeric_limits<float>::quiet_NaN()) const noexcept {
|
||||
if (tag() == otag::ot_f64) {
|
||||
std::uint32_t bits = masked_value();
|
||||
|
||||
return * reinterpret_cast<float *>(&bits);
|
||||
} else {
|
||||
return sentinel;
|
||||
}
|
||||
}
|
||||
|
||||
std::int64_t as_int64(int64_t sentinel = 0) const noexcept {
|
||||
if (tag() == otag::ot_i64) {
|
||||
return cast_int64();
|
||||
} else {
|
||||
return sentinel;
|
||||
}
|
||||
}
|
||||
|
||||
double as_float64(double sentinel = std::numeric_limits<double>::quiet_NaN()) const noexcept {
|
||||
if (tag() == otag::ot_f64) {
|
||||
return * reinterpret_cast<double *>(masked_value());
|
||||
} else {
|
||||
return sentinel;
|
||||
}
|
||||
}
|
||||
|
||||
zstring * as_zstring() const noexcept {
|
||||
if (tag() == otag::ot_zstring) {
|
||||
return reinterpret_cast<zstring *>(masked_value());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Object * as_object() const noexcept {
|
||||
if (tag() == otag::ot_rc_object) {
|
||||
return reinterpret_cast<Object *>(masked_value());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/** ctor. only use least-significant c_ptr_bits (48) bits from value **/
|
||||
explicit object(otag tag, std::uint64_t value) {
|
||||
this->set_tag_value(tag, value);
|
||||
}
|
||||
|
||||
/** undefined behavior if tag != ot_i64 **/
|
||||
std::int64_t cast_int64() const noexcept {
|
||||
return * reinterpret_cast<std::int64_t *>(masked_value());
|
||||
}
|
||||
|
||||
/** undefined behavior if tag != ot_f64 **/
|
||||
double cast_double() const noexcept {
|
||||
return * reinterpret_cast<double *>(masked_value());
|
||||
}
|
||||
|
||||
zstring * cast_zstring() const noexcept {
|
||||
return reinterpret_cast<zstring *>(masked_value());
|
||||
}
|
||||
|
||||
symbol * cast_symbol() const noexcept {
|
||||
return reinterpret_cast<symbol *>(masked_value());
|
||||
}
|
||||
|
||||
Object * cast_object() const noexcept {
|
||||
return reinterpret_cast<Object *>(masked_value());
|
||||
}
|
||||
|
||||
/** only use bottom c_ptr_bits (48) from value **/
|
||||
void set_tag_value(otag tag, std::uint64_t value) {
|
||||
value_ = (static_cast<std::uint16_t>(tag) | (value & c_ptr_mask));
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Rely on being able to steal the 16 most-significant
|
||||
* bits from a 64-bit pointer
|
||||
*
|
||||
* @code
|
||||
*
|
||||
* - ot_i64, ot_f64, ot_zstring, ot_symbol, ot_cons, ot_rc_object:
|
||||
*
|
||||
* <- 16 -> <---------- 48 ---------->
|
||||
* +--------+--------------------------+
|
||||
* | tag | ptr |
|
||||
* +--------+--------------------------+
|
||||
*
|
||||
* - ot_f32:
|
||||
*
|
||||
* <- 16 -> <- 16 -> <------ 32 ----->
|
||||
* +--------+--------+-----------------+
|
||||
* | ot_f32 | unused | 32-bit float |
|
||||
* +--------+--------+-----------------+
|
||||
*
|
||||
* - ot_boolean
|
||||
*
|
||||
* <- 16 -> <-------- 47 ----------> 1
|
||||
* +--------+------------------------+-+
|
||||
* | ot_f32 | unused |b|
|
||||
* +--------+------------------------+-+
|
||||
*
|
||||
* etc...
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* tag values given by @ref otag
|
||||
*
|
||||
* 0x00 -> sentinel. sentinel value. not accessible from schematica
|
||||
* 0x01 -> boolean. truth value in least-significant bit
|
||||
* 0x02 -> char. ascii character in least-significant 8 bits
|
||||
* 0x03 -> int. integer in least-significant 32 bits
|
||||
* 0x04 -> float. 32-bit float in least-significant 32 bitsg
|
||||
*
|
||||
* 0x05..0x07 reserved
|
||||
*
|
||||
* 0x08 -> long. ptr refers to 64-bit integer
|
||||
* 0x09 -> double. ptr refers to 64-bit floating-point value
|
||||
* 0x0a -> zstring. ptr refers to length-prefixed null-terminated cstring.
|
||||
* 0x0b -> symbol. ptr refers to interned (unique'd) symbol
|
||||
* 0x0c -> cons. ptr refers to 128-bit cons-cell (or is nullptr, representing nil)
|
||||
*
|
||||
* 0x0d..0x0f reserved
|
||||
*
|
||||
* 0x10 -> Object. ptr to refcounted xo::obj::Object
|
||||
* see xo-reflect/ Object.hpp
|
||||
**/
|
||||
std::uint64_t value_ = 0;
|
||||
};
|
||||
} /*namespace obj*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end object.hpp **/
|
||||
23
include/xo/object/symbol.hpp
Normal file
23
include/xo/object/symbol.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/** @file symbol.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "zstring.hpp"
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace obj {
|
||||
class symbol {
|
||||
public:
|
||||
symbol(const symbol & x) : name_{x.name_} {}
|
||||
|
||||
zstring * name_;
|
||||
};
|
||||
} /*namespace obj*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end symbol.hpp **/
|
||||
128
include/xo/object/variant.hpp
Normal file
128
include/xo/object/variant.hpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/** @file object.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/reflect/Object.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace obj {
|
||||
enum class otag : std::uint16_t {
|
||||
vt_invalid = -1,
|
||||
vt_sentinel = 0x00,
|
||||
vt_boolean = 0x01,
|
||||
vt_char = 0x02,
|
||||
vt_i32 = 0x03,
|
||||
vt_f32 = 0x04,
|
||||
vt_i64 = 0x08,
|
||||
vt_f64 = 0x09,
|
||||
vt_list = 0x0a,
|
||||
vt_object = 0x10,
|
||||
};
|
||||
|
||||
class cons;
|
||||
|
||||
/** @class object
|
||||
*
|
||||
* @brief dynamically tyyped object; support for schematica
|
||||
**/
|
||||
class object {
|
||||
public:
|
||||
using Object = xo::reflect::Object;
|
||||
|
||||
/** number of pointer bits stolen for type tag **/
|
||||
static constexpr int c_tag_bits = 16;
|
||||
/** number of pointer bits remaining after hi tag bits stolen **/
|
||||
static constexpr int c_ptr_bits = 64 - c_tag_bits;
|
||||
|
||||
static constexpr std::uint64_t c_ptr_mask = (0UL - 1) >> c_tag_bits;
|
||||
|
||||
public:
|
||||
object() = default;
|
||||
|
||||
otag tag() const noexcept { return reinterpret_cast<vtag>(value_ >> c_ptr_bits); }
|
||||
std::uint64_t masked_value() const noexcept { return value_ & c_ptr_mask; }
|
||||
|
||||
std::int32_t as_int32(std::int32_t sentinel = 0) const noexcept {
|
||||
if (tag() == vtag::vt_i32) {
|
||||
return masked_value();
|
||||
} else {
|
||||
return sentinel;
|
||||
}
|
||||
}
|
||||
|
||||
float as_float32(float sentinel = std::numeric_limits<float>::quiet_NaN()) const noexcept {
|
||||
if (tag() == vtag::vt_f64) {
|
||||
return masked_value();
|
||||
} else {
|
||||
return sentinel;
|
||||
}
|
||||
}
|
||||
|
||||
std::int64_t as_int64(int64_t sentinel = 0) const noexcept {
|
||||
if (tag() == vtag::vt_i64) {
|
||||
return * reinterpret_cast<std::int64_t *>(masked_value());
|
||||
} else {
|
||||
return sentinel;
|
||||
}
|
||||
}
|
||||
|
||||
double as_float64(double sentinel = std::numeric_limits<double>::quiet_NaN()) const noexcept {
|
||||
if (tag() == vtag::vt_f64) {
|
||||
return * reinterpret_cast<double *>(masked_value());
|
||||
} else {
|
||||
return sentinel;
|
||||
}
|
||||
}
|
||||
|
||||
Object * as_object() const noexcept {
|
||||
if (tag() == vtag::vt_object) {
|
||||
return reinterpret_cast<Object *>(masked_value());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Rely on being able to steal the 16 most-significant
|
||||
* bits from a 64-bit pointer
|
||||
*
|
||||
* @code
|
||||
* <- 16 -> <---------- 48 ---------->
|
||||
* +--------+--------------------------+
|
||||
* | tag | |
|
||||
* +--------+--------------------------+
|
||||
* @endcode
|
||||
*
|
||||
* tag values given by @ref otag
|
||||
*
|
||||
* 0x00 -> sentinel. sentinel value. not accessible from schematica
|
||||
* 0x01 -> boolean. truth value in least-significant bit
|
||||
* 0x02 -> char. ascii character in least-significant 8 bits
|
||||
* 0x03 -> int. integer in least-significant 32 bits
|
||||
* 0x04 -> float. 32-bit float in least-significant 32 bitsg
|
||||
*
|
||||
* 0x05..0x07 reserved
|
||||
*
|
||||
* 0x08 -> long. ptr refers to 64-bit integer
|
||||
* 0x09 -> double. ptr refers to 64-bit floating-point value
|
||||
* 0x0a -> zstring. ptr refers to length-prefixed null-terminated cstring.
|
||||
* 0x0b -> symbol. ptr refers to interned (unique'd) symbol
|
||||
* 0x0c -> cons. ptr refers to 128-bit cons-cell (or is nullptr, representing nil)
|
||||
*
|
||||
* 0x0d..0x0f reserved
|
||||
*
|
||||
* 0x10 -> Object. ptr to refcounted xo::obj::Object
|
||||
* see xo-reflect/ Object.hpp
|
||||
**/
|
||||
std::uint64_t value_ = 0;
|
||||
};
|
||||
} /*namespace obj*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end object.hpp **/
|
||||
26
include/xo/object/zstring.hpp
Normal file
26
include/xo/object/zstring.hpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/** @file zstring.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "object.hpp"
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace obj {
|
||||
struct zstring {
|
||||
/* need to count trailing \0 */
|
||||
std::size_t alloc_size() const { return sizeof(zstring) + len_ + 1; }
|
||||
|
||||
/** number of characters in string, not counting trailing null **/
|
||||
std::int32_t len_;
|
||||
/** must use placement new to create **/
|
||||
char data_[];
|
||||
};
|
||||
} /*namespace obj*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end zstring.hpp **/
|
||||
11
src/object/CMakeLists.txt
Normal file
11
src/object/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# object/CMakeLists.txt
|
||||
|
||||
set(SELF_LIB xo_object)
|
||||
set(SELF_SRCS
|
||||
object.cpp)
|
||||
|
||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
xo_dependency(${SELF_LIB} reflect)
|
||||
#xo_boost_dependency(${SELF_LIB})
|
||||
|
||||
# end CMakeLists.txt
|
||||
42
src/object/object.cpp
Normal file
42
src/object/object.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* @file object.cpp */
|
||||
|
||||
#include "object.hpp"
|
||||
#include "zstring.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace obj {
|
||||
object::object(const object & x) : value_{0} {
|
||||
switch (x.tag()) {
|
||||
case otag::ot_invalid:
|
||||
case otag::ot_sentinel:
|
||||
case otag::ot_boolean:
|
||||
case otag::ot_char:
|
||||
case otag::ot_i32:
|
||||
case otag::ot_f32:
|
||||
case otag::ot_i64:
|
||||
case otag::ot_f64:
|
||||
case otag::ot_zstring:
|
||||
case otag::ot_symbol:
|
||||
case otag::ot_cons:
|
||||
/* in most cases where value_ embeds a pointer,
|
||||
* it's a passive garbage-collected pointer,
|
||||
* no special treatment required here.
|
||||
*/
|
||||
|
||||
value_ = x.value_;
|
||||
break;
|
||||
case otag::ot_rc_object:
|
||||
/* must bump refcount */
|
||||
{
|
||||
Object * rc_obj = cast_object();
|
||||
|
||||
intrusive_ptr_add_ref(rc_obj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /*namespace obj*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end object.cpp */
|
||||
Loading…
Add table
Add a link
Reference in a new issue