Add tests, type implementation, modify constants and conventions.

This commit is contained in:
yukirij 2023-08-10 23:38:03 -07:00
parent afd3e23e04
commit 2d6f643373
28 changed files with 1397 additions and 521 deletions

64
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,64 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'szun'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=szun"
],
"filter": {
"name": "szun",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'main'",
"cargo": {
"args": [
"build",
"--bin=main",
"--package=szun"
],
"filter": {
"name": "main",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'main'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=main",
"--package=szun"
],
"filter": {
"name": "main",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

View File

@ -1,33 +1,2 @@
# Suzu Data Notation
# Suzu Runtime and Notation
## Types
|Tag|Type|Data|
|---|---|
|**Tags**| | |
|01|Null|No data|
|02|Boolean|True (02) or False (03)|
|**Primitives**| | |
|10|Natural|Integer on [0, inf)|
|11|Integer|Integer on (-inf, inf)|
|12|Decimal|Floating-point number|
|13|Complex|Floating-point number with imaginary component|
|**Compounds**| | |
|1c|Range| |
|1d|Char|Natural representing character code|
|1e|Block|Fixed-length series of bytes|
|1f|String|Variable-length series of bytes|
|**Containers**| | |
|20|Option| |
|21|Set|Unordered, unique collection of elements|
|22|Array|Fixed-length, ordered collection of elements|
|23|List|Variable-length, ordered collection of elements|
|24|Sparse|Discontinuous, ordered collection of elements|
|25|Map|Mapping of elements onto elements|
|26|Trie|Mapping of string onto elements|
|27|Tree| |
|28|Graph| |
|**Objects**| | |
|3e|Record| |
|3f|Schema| |
|40+|User-defined| |

View File

@ -1,10 +1,19 @@
extern crate cc;
fn main() {
let debug = match std::env::var("PROFILE") {
Ok(s) => match s.as_str() {
"debug" => true,
_ => false,
},
_ => false,
};
println!("cargo:rerun-if-changed=src/runtime");
cc::Build::new()
.cpp(true)
.file("src/runtime/lib.cc")
.debug(debug)
.compile("runtime");
}

View File

@ -14,7 +14,8 @@
"rust-analyzer.showUnlinkedFileNotification": false,
"files.associations": {
"xstring": "cpp",
"xmemory": "cpp"
"xmemory": "cpp",
"vector": "cpp"
}
}
}

View File

@ -1,26 +1,42 @@
use crate::runtime::{
Variable,
Reference,
type_key,
acquire, release,
array_length, array_get, array_set
array_length, array_at, array_update
};
use super::{Type, array};
use crate::tag;
use super::array;
pub struct Array {
managed:bool,
addr:Variable,
addr:Reference,
}
impl Array {
pub fn new(size:usize, class:usize) -> Self
pub fn new(length:usize, class:usize) -> Self
{
Self {
managed:true,
addr:unsafe {acquire(array(size, class))},
addr:unsafe {acquire(array(length, class))},
}
}
pub fn from(addr:Variable) -> Self
pub fn from(addr:Reference) -> Result<Self,()>
{
Self { managed:false, addr:addr }
return if(unsafe {type_key(addr.class)} == tag::ARRAY) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(length:usize, class:usize, data:Vec<Reference>) -> Self
{
let mut obj = Self::new(length, class);
for i in 0..usize::min(length, data.len()) {
obj.update(i, data[i]);
}
return obj;
}
pub fn length(&self) -> usize
@ -28,18 +44,18 @@ impl Array {
unsafe {array_length(self.addr)}
}
pub fn set(&mut self, index:usize, source:Variable)
pub fn update(&mut self, index:usize, source:Reference)
{
unsafe { array_set(self.addr, index, source); }
unsafe { array_update(self.addr, index, source); }
}
pub fn get(&self, index:usize) -> Type
pub fn at(&self, index:usize) -> Reference
{
Type::from(unsafe {array_get(self.addr, index)})
unsafe {array_at(self.addr, index)}
}
}
impl std::ops::Deref for Array {
type Target = Variable;
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Array {

View File

@ -1,9 +1,15 @@
use crate::runtime::{Variable, acquire, release, type_inner, type_key, block_set, block_get};
use crate::runtime::{
Reference,
acquire, release,
type_inner, type_key,
block_set, block_get
};
use crate::tag;
use super::block;
pub struct Block {
managed:bool,
addr:Variable,
addr:Reference,
}
impl Block {
pub fn new(size:usize) -> Self
@ -14,9 +20,14 @@ impl Block {
}
}
pub fn from(addr:Variable) -> Self
pub fn from(addr:Reference) -> Result<Self,()>
{
Self { managed:false, addr:addr }
return if(unsafe {type_key(addr.class)} == tag::BLOCK) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn set(&mut self, data:Vec<u8>)
@ -41,7 +52,7 @@ impl Block {
}
}
impl std::ops::Deref for Block {
type Target = Variable;
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Block {

View File

@ -1,11 +1,16 @@
use crate::runtime::{Variable, acquire, release, bool_get, bool_set};
use crate::runtime::{
Reference,
acquire, release,
type_key,
bool_get, bool_set
};
use crate::tag;
use super::boolean;
pub struct Boolean {
managed:bool,
addr:Variable,
addr:Reference,
}
impl Boolean {
pub fn new() -> Self
{
@ -15,9 +20,14 @@ impl Boolean {
}
}
pub fn from(addr:Variable) -> Self
pub fn from(addr:Reference) -> Result<Self,()>
{
Self { managed:false, addr:addr }
return if(unsafe {type_key(addr.class)} == tag::BOOLEAN) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(value:bool) -> Self
@ -38,7 +48,7 @@ impl Boolean {
}
}
impl std::ops::Deref for Boolean {
type Target = Variable;
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Boolean {

View File

@ -14,6 +14,8 @@ pub fn block(size:usize) -> usize {
}
}
pub fn sequence() -> usize { unsafe { runtime::type_outer(0, tag::SEQUENCE) } }
pub fn array(size:usize, type_id:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(type_id, size);
@ -22,3 +24,12 @@ pub fn array(size:usize, type_id:usize) -> usize {
}
pub fn list(type_id:usize) -> usize { unsafe { runtime::type_outer(type_id, tag::LIST) } }
pub fn record(schema_id:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(0, schema_id);
runtime::type_outer(inner_node, tag::RECORD)
}
}
pub fn schema() -> usize { unsafe { runtime::type_outer(0, tag::SCHEMA) } }

View File

@ -1,9 +1,15 @@
use crate::runtime::{Variable, acquire, release, integer_get, integer_set};
use crate::runtime::{
Reference,
acquire, release,
type_key,
integer_get, integer_set
};
use crate::tag;
use super::integer;
pub struct Integer {
managed:bool,
addr:Variable,
addr:Reference,
}
impl Integer {
pub fn new() -> Self
@ -14,9 +20,14 @@ impl Integer {
}
}
pub fn from(addr:Variable) -> Self
pub fn from(addr:Reference) -> Result<Self,()>
{
Self { managed:false, addr:addr }
return if(unsafe {type_key(addr.class)} == tag::INTEGER) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(value:i64) -> Self
@ -37,7 +48,7 @@ impl Integer {
}
}
impl std::ops::Deref for Integer {
type Target = Variable;
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Integer {

View File

@ -1,6 +1,7 @@
use crate::runtime::{
Variable,
Reference,
acquire, release,
type_key,
list_capacity, list_length,
list_at,
list_clear,
@ -8,11 +9,12 @@ use crate::runtime::{
list_remove,
list_reserve,
};
use crate::tag;
use super::{varying, list};
pub struct List {
managed:bool,
addr:Variable,
addr:Reference,
}
impl List {
pub fn new(class:usize) -> Self
@ -23,12 +25,17 @@ impl List {
}
}
pub fn from(addr:Variable) -> Self
pub fn from(addr:Reference) -> Result<Self,()>
{
Self { managed:false, addr:addr }
return if(unsafe {type_key(addr.class)} == tag::LIST) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(data:Vec<Variable>) -> Self
pub fn with(data:Vec<Reference>) -> Self
{
let mut obj = Self::new(varying());
for item in data {
@ -47,7 +54,7 @@ impl List {
unsafe {list_length(self.addr)}
}
pub fn at(&self, index:usize) -> Variable
pub fn at(&self, index:usize) -> Reference
{
unsafe {list_at(self.addr, index)}
}
@ -57,19 +64,19 @@ impl List {
unsafe{list_clear(self.addr)};
}
pub fn insert(&mut self, index:usize, source:Variable)
pub fn insert(&mut self, index:usize, source:Reference)
{
unsafe{list_insert(self.addr, index, source)};
}
pub fn update(&mut self, index:usize, source:Variable)
pub fn update(&mut self, index:usize, source:Reference)
{
unsafe{list_update(self.addr, index, source)};
}
pub fn remove(&mut self, index:usize, maximum:usize)
pub fn remove(&mut self, index:usize, count:usize)
{
unsafe{list_remove(self.addr, index, maximum)};
unsafe{list_remove(self.addr, index, count)};
}
pub fn reserve(&mut self, length:usize)
@ -78,7 +85,7 @@ impl List {
}
}
impl std::ops::Deref for List {
type Target = Variable;
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for List {

View File

@ -1,17 +1,20 @@
use crate::runtime::{Variable, type_key};
use crate::runtime::{Reference, type_key};
use crate::tag;
mod builder; pub use builder::*;
mod varying; pub use varying::Varying;
mod boolean; pub use boolean::Boolean;
mod natural; pub use natural::Natural;
mod integer; pub use integer::Integer;
mod block; pub use block::Block;
mod sequence; pub use sequence::Sequence;
mod array; pub use array::Array;
mod list; pub use list::List;
mod schema; pub use schema::Schema;
pub enum Type {
Varying,
Varying(Varying),
Null,
Boolean(Boolean),
Natural(Natural),
@ -21,16 +24,16 @@ pub enum Type {
List(List),
}
impl Type {
pub fn from(addr:Variable) -> Self
pub fn from(addr:Reference) -> Self
{
match unsafe {type_key(addr.class)} {
tag::VARYING => Type::Varying,
tag::VARYING => Type::Varying(Varying::from(addr).unwrap()),
tag::NULL => Type::Null,
tag::BOOLEAN => Type::Boolean(Boolean::from(addr)),
tag::NATURAL => Type::Natural(Natural::from(addr)),
tag::INTEGER => Type::Integer(Integer::from(addr)),
tag::ARRAY => Type::Array(Array::from(addr)),
//tag::LIST => Type::List(List::from(addr)),
tag::BOOLEAN => Type::Boolean(Boolean::from(addr).unwrap()),
tag::NATURAL => Type::Natural(Natural::from(addr).unwrap()),
tag::INTEGER => Type::Integer(Integer::from(addr).unwrap()),
tag::ARRAY => Type::Array(Array::from(addr).unwrap()),
tag::LIST => Type::List(List::from(addr).unwrap()),
_ => Type::Null,
}
}

View File

@ -1,9 +1,15 @@
use crate::runtime::{Variable, acquire, release, natural_get, natural_set};
use crate::runtime::{
Reference,
acquire, release,
type_key,
natural_get, natural_set
};
use crate::tag;
use super::natural;
pub struct Natural {
managed:bool,
addr:Variable,
addr:Reference,
}
impl Natural {
pub fn new() -> Self
@ -14,9 +20,14 @@ impl Natural {
}
}
pub fn from(addr:Variable) -> Self
pub fn from(addr:Reference) -> Result<Self,()>
{
Self { managed:false, addr:addr }
return if(unsafe {type_key(addr.class)} == tag::NATURAL) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(value:u64) -> Self
@ -37,7 +48,7 @@ impl Natural {
}
}
impl std::ops::Deref for Natural {
type Target = Variable;
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Natural {

44
src/interface/record.rs Normal file
View File

@ -0,0 +1,44 @@
use crate::runtime::{
Reference,
acquire, release,
};
use crate::tag;
use super::record;
pub struct Record {
managed:bool,
addr:Reference,
}
impl Record {
pub fn new(schema:usize) -> Result<Self,()>
{
//if get_schema(schema) {
Ok(Self {
managed:true,
addr:unsafe {acquire(record())},
})
//} else {
// Err(())
//}
}
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::Record) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
//pub fn set(key, Reference)
//pub fn get(key) -> Reference
}
impl std::ops::Deref for Record {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Record {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

135
src/interface/schema.rs Normal file
View File

@ -0,0 +1,135 @@
use crate::runtime::{
//util::{name_indexof, name_keyof},
util::name_indexof,
Reference,
acquire, release,
type_key,
schema_length,
schema_add,
schema_remove,
schema_reorder,
schema_map, schema_unmap, schema_index,
schema_bind,
};
use crate::tag;
use super::schema;
//pub struct Builder {
// data:Schema,
//}
//impl Builder {
// pub fn add() { }
// pub fn map() { }
// pub fn bind() { }
//}
pub struct Schema {
managed:bool,
addr:Reference,
}
impl Schema {
pub fn new() -> Self
{
Self {
managed:true,
addr:unsafe {acquire(schema())},
}
}
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::SCHEMA) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(data:Vec<(&str, usize)>) -> Self
{
let mut obj = Self::new();
for binding in data {
let (key, type_id) = binding;
obj.assign(key, type_id);
}
return obj;
}
//pub fn build() -> Builder
//{
// Builder { }
//}
pub fn length(&self) -> usize
{
unsafe {schema_length(self.addr)}
}
pub fn add(&mut self, type_id:usize) -> usize
{
unsafe {schema_add(self.addr, type_id)}
}
pub fn assign(&mut self, key:&str, type_id:usize)
{
if key.len() > 0 {
let key_index = name_indexof(key);
unsafe {
schema_map(
self.addr,
key_index,
schema_add(self.addr, type_id)
);
}
}
else {
self.add(type_id);
}
}
pub fn remove(&mut self, index:usize)
{
unsafe { schema_remove(self.addr, index); }
}
pub fn reorder(&mut self, from:usize, to:usize)
{
unsafe { schema_reorder(self.addr, from, to); }
}
pub fn map(&mut self, key:&str, index:usize)
{
let key_index = name_indexof(key);
unsafe { schema_map(self.addr, key_index, index); }
}
pub fn unmap(&mut self, key:&str)
{
let key_index = name_indexof(key);
unsafe { schema_unmap(self.addr, key_index); }
}
pub fn index(&mut self, key:&str) -> usize
{
let key_index = name_indexof(key);
unsafe {schema_index(self.addr, key_index)}
}
//pub fn key(&mut self, index:usize) -> String
//{
// name_keyof(unsafe {schema_key(self.addr, index)})
//}
pub fn bind(&mut self, id:usize) -> usize
{
unsafe {schema_bind(self.addr, id)}
}
}
impl std::ops::Deref for Schema {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Schema {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

79
src/interface/sequence.rs Normal file
View File

@ -0,0 +1,79 @@
use crate::runtime::{
Reference,
acquire, release,
type_key,
sequence_length,
sequence_clear, sequence_reserve,
sequence_get,
sequence_insert,
};
use crate::tag;
use super::sequence;
pub struct Sequence {
managed:bool,
addr:Reference,
}
impl Sequence {
pub fn new() -> Self
{
Self {
managed:true,
addr:unsafe {acquire(sequence())},
}
}
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::SEQUENCE) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(data:&str) -> Self
{
let mut obj = Self::new();
obj.set(data);
return obj;
}
pub fn set(&mut self, data:&str)
{
unsafe { sequence_clear(self.addr); }
let bytes = Vec::from(data.as_bytes());
if bytes.len() > 0 {
unsafe { sequence_reserve(self.addr, bytes.len()); }
for i in 0..bytes.len() {
unsafe { sequence_insert(self.addr, i, bytes[i]); }
}
}
}
pub fn get(&self) -> String
{
let length = unsafe {sequence_length(self.addr)};
if length > 0 {
let mut bytes = Vec::<u8>::with_capacity(length);
for i in 0..length {
bytes.push(unsafe {sequence_get(self.addr, i)});
}
return match String::from_utf8(bytes) {
Ok(data) => data,
Err(_) => String::new(),
}
}
else {
return String::new();
}
}
}
impl std::ops::Deref for Sequence {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Sequence {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

View File

@ -1,11 +1,15 @@
use crate::runtime::{Variable, acquire, release, bool_get, bool_set};
use crate::runtime::{
Reference,
acquire, release,
type_key,
};
use crate::tag;
use super::varying;
pub struct Boolean {
pub struct Varying {
managed:bool,
addr:Variable,
addr:Reference,
}
impl Varying {
pub fn new() -> Self
{
@ -15,21 +19,30 @@ impl Varying {
}
}
pub fn set(&mut self, value:bool)
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::VARYING) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn set(&mut self, _addr:Reference)
{
}
pub fn get(&self) -> Variable
pub fn get(&self) -> Reference
{
false
self.addr
}
}
impl std::ops::Deref for Varying {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Varying {
fn drop(&mut self) {
if self.managed {
unsafe {release(self.addr)};
}
}
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

8
src/language/mod.rs Normal file
View File

@ -0,0 +1,8 @@
struct Parser {
}
pub fn compile() -> Result<(),()>
{
Err(())
}

View File

@ -5,7 +5,112 @@ mod util;
mod runtime;
mod interface; pub use interface::*;
fn assert<T>(expected:T, actual:T) where T:std::fmt::Display, T:std::cmp::PartialEq
{
print!(" ({}) ", if expected == actual { " " } else { "!" });
println!("'{}' = '{}'", expected, actual);
}
pub fn test()
{
{
println!("Boolean");
let mut dat = Boolean::new();
assert::<bool>(false, dat.get());
dat.set(true);
assert::<bool>(true, dat.get());
dat.set(false);
assert::<bool>(false, dat.get());
}
{
println!("Natural");
let mut dat = Natural::new();
assert::<u64>(0, dat.get());
dat.set(50);
assert::<u64>(50, dat.get());
dat.set(25000);
assert::<u64>(25000, dat.get());
}
{
println!("Integer");
let mut dat = Integer::new();
assert::<i64>(0, dat.get());
dat.set(-12);
assert::<i64>(-12, dat.get());
dat.set(38695);
assert::<i64>(38695, dat.get());
}
{
println!("Block");
let mut dat = Block::new(4);
dat.set(vec![1, 2, 3, 4]);
assert::<usize>(4, dat.get().len());
assert::<u8>(1, dat.get()[0]);
assert::<u8>(2, dat.get()[1]);
assert::<u8>(3, dat.get()[2]);
assert::<u8>(4, dat.get()[3]);
}
{
println!("Sequence");
let mut dat = Sequence::new();
assert::<String>(String::from(""), dat.get());
dat.set("hello");
assert::<String>(String::from("hello"), dat.get());
}
{
println!("Array<Natural>");
let dat = Array::new(4, natural());
Natural::from(dat.at(0)).unwrap().set(250);
Natural::from(dat.at(1)).unwrap().set(500);
Natural::from(dat.at(2)).unwrap().set(750);
Natural::from(dat.at(3)).unwrap().set(1000);
assert::<usize>(4, dat.length());
assert::<u64>(250, Natural::from(dat.at(0)).unwrap().get());
assert::<u64>(500, Natural::from(dat.at(1)).unwrap().get());
assert::<u64>(750, Natural::from(dat.at(2)).unwrap().get());
assert::<u64>(1000,Natural::from(dat.at(3)).unwrap().get());
}
/* {
println!("List - Undefined");
println!("List - Variable");
let mut dat = List::new(varying());
dat.insert(usize::MAX, *Integer::with(15));
match Type::from(dat.at(0)) {
Type::Integer(value) => {
println!(" = {}", value.get());
}
_ => { println!(" - Not Integer"); }
}
println!("List<Sequence>");
let mut dat = List::new(sequence());
dat.insert(usize::MAX, *Sequence::with("hello"));
dat.insert(usize::MAX, *Sequence::with("world"));
dat.insert(usize::MAX, *Sequence::with("konnichiwa"));
dat.insert(usize::MAX, *Sequence::with("konbanwa"));
dat.insert(usize::MAX, *Sequence::with("tasogare"));
println!(" = {}", Integer::from(dat.at(0)).unwrap().get());
} */
/*{
println!("Sparse");
}*/
/*{
println!("Schema");
}*/
/*{
println!("Record");
}*/
}

View File

@ -1,8 +1,10 @@
#include "lib.h"
#include "rawlist.cc"
TypeTree DB_TYPE;
NameTree DB_NAME;
Pool<Variable> DB_DATA;
//Pool<Type::Schema> DB_SCHEMA;
Pool<Reference> DB_DATA;
extern "C" size_t type_outer(size_t type_id, size_t key)
{
@ -25,25 +27,64 @@ extern "C" size_t type_size(size_t type_id)
size_t type = DB_TYPE.key(type_id);
switch(type) {
case Type::Tag::Varying: return sizeof(Variable);
case Type::Tag::Null: return 0;
case Type::Tag::Boolean: return sizeof(Type::Boolean);
case Type::Tag::Natural: return sizeof(Type::Natural);
case Type::Tag::Integer: return sizeof(Type::Integer);
case Type::Tag::Block: return DB_TYPE.key(DB_TYPE.inner(type_id));
case Type::Tag::String: return sizeof(Type::List);
case Type::Tag::Null: return 0;
case Type::Tag::Varying: return sizeof(Reference);
case Type::Tag::Boolean: return sizeof(Type::Boolean);
case Type::Tag::Natural: return sizeof(Type::Natural);
case Type::Tag::Integer: return sizeof(Type::Integer);
case Type::Tag::Block: return DB_TYPE.key(DB_TYPE.inner(type_id));
case Type::Tag::Sequence: return sizeof(Type::Sequence);
case Type::Tag::Array: {
size_t length = DB_TYPE.inner(type_id);
size_t inner = DB_TYPE.inner(length);
return static_cast<size_t>(DB_TYPE.key(length)) * type_size(inner);
};
case Type::Tag::List: return sizeof(Type::List);
case Type::Tag::List: return sizeof(Type::List);
case Type::Tag::Record: {
//if(DB_SCHEMA.has(type_key(type_inner(type_id)))) {
// return DB_SCHEMA.get().size;
//}
return 0;
}
case Type::Tag::Schema: return sizeof(Type::Schema);
default: return 0;
}
}
return 0;
}
extern "C" size_t name_indexof(const uint8_t* bytes, size_t length)
{
std::string str(reinterpret_cast<const char*>(bytes), length);
return DB_NAME.indexof(str);
}
extern "C" Str name_keyof(size_t index)
{
Str result {0};
std::string str = DB_NAME.keyof(index);
if(str.length() > 0) {
result.bytes = new uint8_t[str.length()];
}
for(size_t i = 0; i < str.length(); ++i) {
result.bytes[i] = str[i];
}
result.length = str.length();
return result;
}
std::string name_keyof_internal(size_t index)
{
return DB_NAME.keyof(index);
}
extern "C" void name_release(Str data)
{
if(data.bytes != nullptr) {
delete[] data.bytes;
}
}
void* allocate(size_t type_id, size_t count)
{
void* mem = nullptr;
@ -58,9 +99,9 @@ void* allocate(size_t type_id, size_t count)
return nullptr;
}
extern "C" Variable acquire(size_t type_id)
extern "C" Reference acquire(size_t type_id)
{
Variable addr {0};
Reference addr {0};
addr.address = allocate(type_id, 1);
if(addr.address != nullptr) {
addr.type = type_id;
@ -68,10 +109,10 @@ extern "C" Variable acquire(size_t type_id)
return addr;
}
void drop(Variable addr)
void drop(Reference addr)
{
if(addr.address != nullptr) {
switch(addr.type) {
switch(type_key(addr.type)) {
case Type::Tag::Boolean:
case Type::Tag::Natural:
case Type::Tag::Integer:
@ -79,7 +120,7 @@ void drop(Variable addr)
break;
case Type::Tag::Varying: {
Variable& var = *reinterpret_cast<Variable*>(addr.address);
auto& var = *reinterpret_cast<Reference*>(addr.address);
if(var.address != nullptr) {
drop(var);
}
@ -87,21 +128,24 @@ void drop(Variable addr)
var.address = nullptr;
} break;
case Type::Tag::Sequence: {
auto& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
rawlist_clear(seq.data);
} break;
case Type::Tag::List: {
//Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
//if(list.data != nullptr) {
// for(size_t i = 0; i < list.length; ++i) {
// drop(list_cell(addr, i));
// }
// free(list.data);
//}
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
for(size_t i = 0; i < list.data.length; ++i) {
drop(list_cell(addr, i));
}
rawlist_clear(list.data);
} break;
}
memset(addr.address, 0, type_size(addr.type));
}
}
extern "C" void release(Variable addr)
extern "C" void release(Reference addr)
{
if(addr.address != nullptr) {
drop(addr);
@ -109,19 +153,19 @@ extern "C" void release(Variable addr)
}
}
bool copy(Variable src, Variable dst)
bool copy(Reference src, Reference dst)
{
Variable source = src;
Variable destination = dst;
Reference source = src;
Reference destination = dst;
// dereference varying data
if(type_key(src.type) == Type::Tag::Varying) {
source = *reinterpret_cast<Variable*>(src.address);
source = *reinterpret_cast<Reference*>(src.address);
}
// prepare destination for varying data
if(type_key(dst.type) == Type::Tag::Varying) {
auto& dest_ref = *reinterpret_cast<Variable*>(dst.address);
auto& dest_ref = *reinterpret_cast<Reference*>(dst.address);
// determine if memory can be reused, otherwise free and reallocate
if(source.type != dest_ref.type) {
@ -147,268 +191,270 @@ bool copy(Variable src, Variable dst)
memcpy(destination.address, source.address, type_size(source.type));
} break;
/*case Type::Tag::List: {
case Type::Tag::List: {
auto& src_list = *reinterpret_cast<Type::List*>(source.address);
auto& dst_list = *reinterpret_cast<Type::List*>(destination.address);
dst_list.capacity = src_list.capacity;
dst_list.length = src_list.length;
dst_list.data = allocate(type_inner(source.type), src_list.capacity);
for(size_t i = 0; i < src_list.length; ++i) {
rawlist_reserve(dst_list.data, type_size(type_inner(source.type)), src_list.data.capacity);
dst_list.data.length = src_list.data.length;
//dst_list.data = allocate(type_inner(source.type), src_list.capacity);
for(size_t i = 0; i < src_list.data.length; ++i) {
copy(list_at(source, i), list_at(destination, i));
}
} break;*/
} break;
}
return true;
}
return false;
}
// Varying //
extern "C" Variable varying_get(Variable addr)
extern "C" Reference varying_get(Reference addr)
{
Variable result {0};
//if(type_key(addr.type) == Type::Tag::Varying) {
result = *reinterpret_cast<Variable*>(addr.address);
//}
Reference result {0};
result = *reinterpret_cast<Reference*>(addr.address);
return result;
}
extern "C" void varying_set(Variable addr, Variable source)
extern "C" void varying_set(Reference addr, Reference source)
{
//if(type_key(addr.type) == Type::Tag::Varying) {
Variable& var = *reinterpret_cast<Variable*>(addr.address);
if(var.address != nullptr) {
drop(var);
}
Reference& var = *reinterpret_cast<Reference*>(addr.address);
if(var.type != source.type || var.address == nullptr) {
if(var.address != nullptr) {
free(var.address);
}
var.type = source.type;
var.address = allocate(source.type, 1);
}
if(var.address != nullptr) {
drop(var);
}
copy(source, var);
//}
if(var.type != source.type || var.address == nullptr) {
if(var.address != nullptr) {
free(var.address);
}
var.type = source.type;
var.address = allocate(source.type, 1);
}
copy(source, var);
}
extern "C" void varying_clear(Variable addr)
extern "C" void varying_clear(Reference addr)
{
//if(type_key(addr.type) == Type::Tag::Varying) {
Variable& var = *reinterpret_cast<Variable*>(addr.address);
if(var.address != nullptr) {
drop(var);
free(var.address);
var.type = 0;
var.address = nullptr;
}
//}
Reference& var = *reinterpret_cast<Reference*>(addr.address);
if(var.address != nullptr) {
drop(var);
free(var.address);
var.type = 0;
var.address = nullptr;
}
}
// Boolean //
extern "C" void bool_set(Variable addr, Type::Boolean value)
extern "C" void bool_set(Reference addr, Type::Boolean value)
{
//if(type_key(addr.type) == Type::Tag::Boolean) {
*(reinterpret_cast<Type::Boolean*>(addr.address)) = value;
//}
*(reinterpret_cast<Type::Boolean*>(addr.address)) = value;
}
extern "C" Type::Boolean bool_get(Variable addr)
extern "C" Type::Boolean bool_get(Reference addr)
{
//if(type_key(addr.type) == Type::Tag::Boolean) {
return *(reinterpret_cast<Type::Boolean*>(addr.address));
//}
//return false;
return *(reinterpret_cast<Type::Boolean*>(addr.address));
}
// Natural //
extern "C" void natural_set(Variable addr, Type::Natural value)
extern "C" void natural_set(Reference addr, Type::Natural value)
{
//if(type_key(addr.type) == Type::Tag::Natural) {
*(reinterpret_cast<Type::Natural*>(addr.address)) = value;
//}
*(reinterpret_cast<Type::Natural*>(addr.address)) = value;
}
extern "C" Type::Natural natural_get(Variable addr)
extern "C" Type::Natural natural_get(Reference addr)
{
//if(type_key(addr.type) == Type::Tag::Natural) {
return *(reinterpret_cast<Type::Natural*>(addr.address));
//}
//return false;
return *(reinterpret_cast<Type::Natural*>(addr.address));
}
// Integer //
extern "C" void integer_set(Variable addr, Type::Integer value)
extern "C" void integer_set(Reference addr, Type::Integer value)
{
//if(type_key(addr.type) == Type::Tag::Integer) {
*(reinterpret_cast<Type::Integer*>(addr.address)) = value;
//}
*(reinterpret_cast<Type::Integer*>(addr.address)) = value;
}
extern "C" Type::Integer integer_get(Variable addr)
extern "C" Type::Integer integer_get(Reference addr)
{
//if(type_key(addr.type) == Type::Tag::Integer) {
return *(reinterpret_cast<Type::Integer*>(addr.address));
//}
//return false;
return *(reinterpret_cast<Type::Integer*>(addr.address));
}
// Block //
extern "C" uint8_t block_get(Variable addr, size_t index)
extern "C" uint8_t block_get(Reference addr, size_t index)
{
//if(type_key(addr.type) == Type::Tag::Block) {
size_t length = type_key(type_inner(addr.type));
if(index < length) {
return reinterpret_cast<uint8_t*>(addr.address)[index];
}
//}
size_t length = type_key(type_inner(addr.type));
if(index < length) {
return reinterpret_cast<uint8_t*>(addr.address)[index];
}
return 0;
}
extern "C" void block_set(Variable addr, size_t index, uint8_t value)
extern "C" void block_set(Reference addr, size_t index, uint8_t value)
{
//if(type_key(addr.type) == Type::Tag::Block) {
size_t length = type_key(type_inner(addr.type));
if(index < length) {
reinterpret_cast<uint8_t*>(addr.address)[index] = value;
}
//}
size_t length = type_key(type_inner(addr.type));
if(index < length) {
reinterpret_cast<uint8_t*>(addr.address)[index] = value;
}
}
// String //
// Sequence //
extern "C" size_t sequence_length(Reference addr)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
return seq.data.length;
}
extern "C" uint8_t sequence_get(Reference addr, size_t index)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
if(index < seq.data.length) {
return *reinterpret_cast<uint8_t*>(rawlist_cell(seq.data, 1, index));
}
return 0;
}
extern "C" void sequence_clear(Reference addr)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
rawlist_clear(seq.data);
}
extern "C" void sequence_set(Reference addr, size_t index, uint8_t value)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
auto cell = reinterpret_cast<uint8_t*>(rawlist_cell(seq.data, 1, index));
if(cell != nullptr) {
*cell = value;
}
}
extern "C" void sequence_insert(Reference addr, size_t index, uint8_t value)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
auto cell = reinterpret_cast<uint8_t*>(rawlist_insert(seq.data, 1, index));
if(cell != nullptr) {
*cell = value;
}
}
extern "C" void sequence_reserve(Reference addr, size_t capacity)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
rawlist_reserve(seq.data, 1, capacity);
}
// Array //
extern "C" size_t array_length(Variable addr)
extern "C" size_t array_length(Reference addr)
{
//if(type_key(addr.type) == Type::Tag::Array) {
return type_key(type_inner(addr.type));
//}
//return 0;
return type_key(type_inner(addr.type));
}
Variable array_cell(Variable addr, size_t index)
Reference array_cell(Reference addr, size_t index)
{
Variable result {0};
//if(type_key(addr.type) == Type::Tag::Array) {
size_t length_n = type_inner(addr.type);
size_t length = type_key(length_n);
size_t type = type_inner(length_n);
size_t offset = type_size(type);
Reference result {0};
size_t length_n = type_inner(addr.type);
size_t length = type_key(length_n);
size_t type = type_inner(length_n);
size_t offset = type_size(type);
// validate for overflow
if(addr.address != nullptr && offset > 0 && index < length) {
result.type = type;
result.address = reinterpret_cast<void*>(reinterpret_cast<size_t>(addr.address) + (offset * index));
}
//}
// validate for overflow
if(addr.address != nullptr && offset > 0 && index < length) {
result.type = type;
result.address = reinterpret_cast<void*>(reinterpret_cast<size_t>(addr.address) + (offset * index));
}
return result;
}
extern "C" Variable array_get(Variable addr, size_t index)
extern "C" Reference array_at(Reference addr, size_t index)
{
Variable result {0};
//if(type_key(addr.type) == Type::Tag::Array) {
Variable cell = array_cell(addr, index);
if(cell.address != nullptr) {
if(cell.type == Type::Tag::Varying) {
result = varying_get(cell);
}
else {
result = cell;
}
}
//}
return result;
}
extern "C" void array_set(Variable addr, size_t index, Variable source)
{
//if(type_key(addr.type) == Type::Tag::Array) {
Variable cell = array_cell(addr, index);
if(cell.type == Type::Tag::Varying) {
varying_set(cell, source);
Reference result {0};
Reference cell = array_cell(addr, index);
if(cell.address != nullptr) {
if(type_key(cell.type) == Type::Tag::Varying) {
result = varying_get(cell);
}
else {
copy(source, cell);
result = cell;
}
//}
}
return result;
}
extern "C" void array_update(Reference addr, size_t index, Reference source)
{
Reference cell = array_cell(addr, index);
if(type_key(cell.type) == Type::Tag::Varying) {
varying_set(cell, source);
}
else {
copy(source, cell);
}
}
// List //
extern "C" size_t list_capacity(Variable addr)
extern "C" size_t list_capacity(Reference addr)
{
//if(type_key(addr.type) == Type::Tag::List) {
return (*reinterpret_cast<Type::List*>(addr.address)).capacity;
//}
//return 0;
return (*reinterpret_cast<Type::List*>(addr.address)).data.capacity;
}
extern "C" size_t list_length(Variable addr)
extern "C" size_t list_length(Reference addr)
{
//if(type_key(addr.type) == Type::Tag::List) {
return (*reinterpret_cast<Type::List*>(addr.address)).length;
//}
//return 0;
return (*reinterpret_cast<Type::List*>(addr.address)).data.length;
}
Variable list_cell(Variable addr, size_t index)
Reference list_cell(Reference addr, size_t index)
{
Variable result {0};
//if(type_key(addr.type) == Type::Tag::List) {
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
Reference result {0};
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
// validate for overflow
if(list.data.data != nullptr && offset > 0 && index < list.data.capacity) {
result.type = inner;
result.address = rawlist_cell(list.data, offset, index);
}
// validate for overflow
if(list.data != nullptr && offset > 0 && index < list.length) {
result.type = inner;
result.address = reinterpret_cast<void*>(reinterpret_cast<size_t>(list.data) + (offset * index));
}
//}
return result;
}
extern "C" Variable list_at(Variable addr, size_t index)
extern "C" Reference list_at(Reference addr, size_t index)
{
Variable result {0};
//if(type_key(addr.type) == Type::Tag::List) {
Variable cell = list_cell(addr, index);
if(cell.address != nullptr) {
if(cell.type == Type::Tag::Varying) {
result = *reinterpret_cast<Variable*>(cell.address);
} else {
result = cell;
}
Reference result {0};
Reference cell = list_cell(addr, index);
if(cell.address != nullptr) {
if(type_key(cell.type) == Type::Tag::Varying) {
result = *reinterpret_cast<Reference*>(cell.address);
} else {
result = cell;
}
//}
}
return result;
}
/*extern "C" Variable list_first(Variable addr)
/*extern "C" Reference list_first(Reference addr)
{
Variable result {0};
Reference result {0};
if(type_key(addr.type) == Type::Tag::List) {
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
if(list.length > 0) {
@ -418,9 +464,9 @@ extern "C" Variable list_at(Variable addr, size_t index)
return result;
}*/
/*extern "C" Variable list_last(Variable addr)
/*extern "C" Reference list_last(Reference addr)
{
Variable result {0};
Reference result {0};
if(type_key(addr.type) == Type::Tag::List) {
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
if(list.length > 0) {
@ -430,20 +476,12 @@ extern "C" Variable list_at(Variable addr, size_t index)
return result;
}*/
extern "C" void list_clear(Variable addr)
extern "C" void list_clear(Reference addr)
{
//if(type_key(addr.type) == Type::Tag::List) {
size_t offset = type_size(type_inner(addr.type));
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
for(size_t i = 0; i < list.length; ++i) {
drop(list_cell(addr, i));
}
list.length = 0;
memset(list.data, 0, offset * list.capacity);
//}
drop(addr);
}
/*extern "C" void list_prepend(Variable addr, Variable source)
/*extern "C" void list_prepend(Reference addr, Reference source)
{
if(type_key(addr.type) == Type::Tag::List) {
size_t inner = type_inner(addr.type);
@ -464,7 +502,7 @@ extern "C" void list_clear(Variable addr)
}
}*/
/*extern "C" void list_append(Variable addr, Variable source)
/*extern "C" void list_append(Reference addr, Reference source)
{
if(type_key(addr.type) == Type::Tag::List) {
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
@ -484,64 +522,192 @@ extern "C" void list_clear(Variable addr)
}
}*/
extern "C" void list_insert(Variable addr, size_t index, Variable source)
extern "C" void list_insert(Reference addr, size_t index, Reference source)
{
//if(type_key(addr.type) == Type::Tag::List) {
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
//}
}
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
extern "C" void list_update(Variable addr, size_t index, Variable source)
{
//if(type_key(addr.type) == Type::Tag::List) {
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
//}
}
if(index > list.data.length) { index = list.data.length; }
/*extern "C" void list_truncate(Variable addr, size_t maximum)
{
if(type_key(addr.type) == Type::Tag::List) {
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
void* cell = rawlist_insert(list.data, offset, index);
if(type_key(inner) == Type::Tag::Varying) {
varying_set(list_cell(addr, index), source);
}
}*/
/*extern "C" void list_shift(Variable addr)
{
if(type_key(addr.type) == Type::Tag::List) {
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
else {
copy(source, list_cell(addr, index));
}
}*/
extern "C" void list_remove(Variable addr, size_t index, size_t maximum)
{
//if(type_key(addr.type) == Type::Tag::List) {
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
//}
}
extern "C" void list_reserve(Variable addr, size_t capacity)
extern "C" void list_update(Reference addr, size_t index, Reference source)
{
//if(type_key(addr.type) == Type::Tag::List) {
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
if(index < list.data.length) {
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
if(list.capacity < capacity) {
void* new_data = allocate(inner, capacity);
memcpy(new_data, list.data, offset * list.capacity);
if(type_key(inner) == Type::Tag::Varying) {
varying_set(list_cell(addr, index), source);
}
//}
else {
copy(source, list_cell(addr, index));
}
}
}
/*extern "C" void list_resize(Variable addr, size_t length)
/*extern "C" void list_truncate(Reference addr, size_t maximum)
{
if(type_key(addr.type) == Type::Tag::List) {
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
}
}*/
/*extern "C" void list_shift(Reference addr)
{
if(type_key(addr.type) == Type::Tag::List) {
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
}
}*/
extern "C" void list_remove(Reference addr, size_t index)
{
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
drop(list_at(addr, index));
rawlist_remove(list.data, offset, index);
}
extern "C" void list_reserve(Reference addr, size_t capacity)
{
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
rawlist_reserve(list.data, offset, capacity);
}
/*extern "C" void list_resize(Reference addr, size_t length)
{
if(type_key(addr.type) == Type::Tag::List) {
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
}
}*/
// Schema //
extern "C" size_t schema_length(Reference addr)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
return object.data.length;
}
extern "C" size_t schema_add(Reference addr, size_t type_id)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
void* cell = rawlist_insert(object.data, sizeof(size_t), object.data.length);
*reinterpret_cast<size_t*>(cell) = type_id;
return object.data.length - 1;
}
extern "C" void schema_remove(Reference addr, size_t index)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index < object.data.length) {
}
}
extern "C" void schema_reorder(Reference addr, size_t index_from, size_t index_to)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index_from < object.data.length && index_to <= object.data.length) {
if(index_from > index_to) {
}
else {
}
}
}
extern "C" void schema_map(Reference addr, size_t key, size_t index)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index < object.data.length) {
size_t find_index = 0;
for(; find_index < object.map.length; find_index++) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), find_index));
if(cell != nullptr) {
if(cell->key == key) { break; }
}
}
// if key is not found, add new mapping
if(find_index == object.map.length) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_insert(object.map, sizeof(Type::Schema::Mapping), object.map.length));
cell->key = key;
cell->index = index;
}
// otherwise, update existing key
else {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), find_index));
cell->index = index;
}
}
}
extern "C" void schema_unmap(Reference addr, size_t key)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
for(size_t i; i < object.map.length; i++) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
if(cell != nullptr) {
if(cell->key == key) {
rawlist_remove(object.map, sizeof(Type::Schema::Mapping), i);
return;
}
}
}
}
extern "C" size_t schema_index(Reference addr, size_t key)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
for(size_t i; i < object.map.length; i++) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
if(cell != nullptr) {
if(cell->key == key) {
return cell->index;
}
}
}
return object.data.length;
}
extern "C" size_t schema_bind(Reference addr, size_t id)
{
Type::SchemaBinding binding {0};
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
// prepare binding
binding.schema = object;
binding.binding = id;
//for(size_t type_id : object.data) {
// binding.size += type_size(type_id);
//}
printf("bind: (%zu) %zu\n", binding.binding, binding.size);
// add binding to pool
//DB_SCHEMA.add(id, binding);
return id;
}

View File

@ -1,84 +1,108 @@
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include "type.h"
#include "typetree.h"
#include "nametree.h"
#include "rawlist.h"
#include "pool.h"
#include "schema.h"
extern "C" struct Str {
uint8_t* bytes;
size_t length;
};
extern TypeTree DB_TYPE;
extern NameTree DB_NAME;
extern Pool<Variable> DB_DATA;
//extern Pool<Type::Schema> DB_SCHEMA;
extern Pool<Reference> DB_DATA;
extern "C" size_t type_outer(size_t id, size_t key);
extern "C" size_t type_inner(size_t id);
extern "C" size_t type_key(size_t id);
extern "C" size_t type_size(size_t type_id);
extern "C" size_t name_indexof(const uint8_t* bytes, size_t length);
std::string name_keyof_internal(size_t index);
extern "C" Str name_keyof(size_t index);
void* allocate(size_t type_id, size_t count);
extern "C" Variable acquire(size_t type_id);
extern "C" void release(Variable id);
extern "C" bool copy(Variable src, Variable dst);
extern "C" Reference acquire(size_t type_id);
extern "C" void release(Reference id);
extern "C" bool copy(Reference src, Reference dst);
// Varying //
extern "C" Variable varying_get(Variable addr);
extern "C" void varying_set(Variable addr, Variable source);
extern "C" void varying_clear(Variable addr);
extern "C" Reference varying_get(Reference addr);
extern "C" void varying_set(Reference addr, Reference source);
extern "C" void varying_clear(Reference addr);
// Boolean //
extern "C" void bool_set(Variable addr, Type::Boolean value);
extern "C" Type::Boolean bool_get(Variable addr);
extern "C" void bool_set(Reference addr, Type::Boolean value);
extern "C" Type::Boolean bool_get(Reference addr);
// Natural //p
extern "C" void natural_set(Variable addr, Type::Natural value);
extern "C" Type::Natural natural_get(Variable addr);
extern "C" void natural_set(Reference addr, Type::Natural value);
extern "C" Type::Natural natural_get(Reference addr);
// Integer //
extern "C" void integer_set(Variable addr, Type::Integer value);
extern "C" Type::Integer integer_get(Variable addr);
extern "C" void integer_set(Reference addr, Type::Integer value);
extern "C" Type::Integer integer_get(Reference addr);
// Block //
extern "C" uint8_t block_get(Variable addr, size_t index);
extern "C" void block_set(Variable addr, size_t index, uint8_t value);
extern "C" uint8_t block_get(Reference addr, size_t index);
extern "C" void block_set(Reference addr, size_t index, uint8_t value);
// String //
//extern "C" size_t string_length(Variable addr);
//extern "C" Variable string_get(Variable addr, size_t index);
//extern "C" void string_clear(Variable addr);
//extern "C" void string_prepend(Variable addr, Variable source);
//extern "C" void string_append(Variable addr, Variable source);
//extern "C" void string_insert(Variable addr, size_t index, Variable source);
//extern "C" void string_set(Variable addr, size_t index, Variable source);
//extern "C" void string_truncate(Variable addr, size_t maximum);
//extern "C" void string_remove(Variable addr, size_t index, size_t maximum);
extern "C" size_t sequence_length(Reference addr);
extern "C" uint8_t sequence_get(Reference addr, size_t index);
extern "C" void sequence_clear(Reference addr);
extern "C" void sequence_set(Reference addr, size_t index, uint8_t value);
extern "C" void sequence_insert(Reference addr, size_t index, uint8_t value);
extern "C" void sequence_reserve(Reference addr, size_t capacity);
// Array //
extern "C" size_t array_length(Variable addr);
Variable array_cell(Variable addr, size_t index);
extern "C" Variable array_get(Variable addr, size_t index);
extern "C" void array_set(Variable addr, size_t index, Variable source);
extern "C" size_t array_length(Reference addr);
Reference array_cell(Reference addr, size_t index);
extern "C" Reference array_at(Reference addr, size_t index);
extern "C" void array_update(Reference addr, size_t index, Reference source);
// List //
extern "C" size_t list_capacity(Variable addr);
extern "C" size_t list_length(Variable addr);
Variable list_cell(Variable addr, size_t index);
extern "C" Variable list_at(Variable addr, size_t index);
//extern "C" Variable list_first(Variable addr);
//extern "C" Variable list_last(Variable addr);
extern "C" void list_clear(Variable addr);
//extern "C" void list_prepend(Variable addr, Variable source);
//extern "C" void list_append(Variable addr, Variable source);
extern "C" void list_insert(Variable addr, size_t index, Variable source);
extern "C" void list_update(Variable addr, size_t index, Variable source);
//extern "C" void list_truncate(Variable addr, size_t maximum);
//extern "C" void list_shift(Variable addr);
extern "C" void list_remove(Variable addr, size_t index, size_t maximum);
extern "C" void list_reserve(Variable addr, size_t capacity);
//extern "C" void list_resize(Variable addr, size_t length);
extern "C" size_t list_capacity(Reference addr);
extern "C" size_t list_length(Reference addr);
Reference list_cell(Reference addr, size_t index);
extern "C" Reference list_at(Reference addr, size_t index);
//extern "C" Reference list_first(Reference addr);
//extern "C" Reference list_last(Reference addr);
extern "C" void list_clear(Reference addr);
//extern "C" void list_prepend(Reference addr, Reference source);
//extern "C" void list_append(Reference addr, Reference source);
extern "C" void list_insert(Reference addr, size_t index, Reference source);
extern "C" void list_update(Reference addr, size_t index, Reference source);
//extern "C" void list_truncate(Reference addr, size_t maximum);
//extern "C" void list_shift(Reference addr);
extern "C" void list_remove(Reference addr, size_t index);
extern "C" void list_reserve(Reference addr, size_t capacity);
//extern "C" void list_resize(Reference addr, size_t length);
// Record //
/*
- set_at(index, value)
- set(key, value)
- get_at(index) value
- get(key) value
- key(index) key
- index(key) index
*/
// Schema //
extern "C" size_t schema_length(Reference addr);
extern "C" size_t schema_add(Reference addr, size_t type_id);
extern "C" void schema_remove(Reference addr, size_t index);
extern "C" void schema_reorder(Reference addr, size_t index_from, size_t index_to);
extern "C" void schema_map(Reference addr, size_t key, size_t index);
extern "C" void schema_unmap(Reference addr, size_t key);
extern "C" size_t schema_index(Reference addr, size_t key);
extern "C" size_t schema_bind(Reference addr, size_t key);

View File

@ -1,13 +1,28 @@
pub mod util;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Variable {
pub class:usize,
pub address:usize,
pub struct Reference {
pub(crate) class:usize,
pub(crate) address:usize,
}
impl Reference {
pub fn is_null(&self) -> bool
{
self.address != 0
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Str {
pub bytes:*mut u8,
pub length:usize,
}
extern "C" {
pub fn acquire(type_id:usize) -> Variable;
pub fn release(addr:Variable);
pub fn acquire(type_id:usize) -> Reference;
pub fn release(addr:Reference);
pub fn type_outer(type_id:usize, key:usize) -> usize;
pub fn type_inner(type_id:usize) -> usize;
@ -15,46 +30,60 @@ extern "C" {
pub fn type_size(type_id:usize) -> usize;
pub fn bool_set(addr:Variable, data:bool);
pub fn bool_get(addr:Variable) -> bool;
pub fn name_indexof(data:*const u8, length:usize) -> usize;
pub fn name_keyof(index:usize) -> Str;
pub fn name_release(data:Str);
pub fn bool_set(addr:Reference, data:bool);
pub fn bool_get(addr:Reference) -> bool;
pub fn natural_set(addr:Variable, data:u64);
pub fn natural_get(addr:Variable) -> u64;
pub fn natural_set(addr:Reference, data:u64);
pub fn natural_get(addr:Reference) -> u64;
pub fn integer_set(addr:Variable, data:i64);
pub fn integer_get(addr:Variable) -> i64;
pub fn integer_set(addr:Reference, data:i64);
pub fn integer_get(addr:Reference) -> i64;
pub fn block_set(addr:Variable, index:usize, data:u8);
pub fn block_get(addr:Variable, index:usize) -> u8;
pub fn block_set(addr:Reference, index:usize, data:u8);
pub fn block_get(addr:Reference, index:usize) -> u8;
//pub fn string_set(id:u64, data:Vec<u8>);
//pub fn string_get(id:u64) -> Vec<u8>;
//pub fn string_at(id:u64, index:u64) -> u32;
pub fn sequence_length(addr:Reference) -> usize;
pub fn sequence_get(addr:Reference, index:usize) -> u8;
pub fn sequence_clear(addr:Reference);
pub fn sequence_set(addr:Reference, index:usize, value:u8);
pub fn sequence_insert(addr:Reference, index:usize, value:u8);
pub fn sequence_reserve(addr:Reference, capacity:usize);
pub fn array_length(addr:Variable) -> usize;
pub fn array_get(addr:Variable, index:usize) -> Variable;
pub fn array_set(addr:Variable, index:usize, source:Variable);
pub fn array_length(addr:Reference) -> usize;
pub fn array_at(addr:Reference, index:usize) -> Reference;
pub fn array_update(addr:Reference, index:usize, source:Reference);
pub fn list_capacity(addr:Variable) -> usize;
pub fn list_length(addr:Variable) -> usize;
//pub fn list_first(addr:Variable) -> Variable;
//pub fn list_last(addr:Variable) -> Variable;
pub fn list_at(addr:Variable, index:usize) -> Variable;
pub fn list_clear(addr:Variable);
//pub fn list_prepend(addr:Variable, src:Variable);
//pub fn list_append(addr:Variable, src:Variable);
pub fn list_insert(addr:Variable, index:usize, src:Variable);
pub fn list_update(addr:Variable, index:usize, src:Variable);
//pub fn list_truncate(addr:Variable, maximum:usize);
//pub fn list_shift(addr:Variable, maximum:usize);
pub fn list_remove(addr:Variable, index:usize, maximum:usize);
pub fn list_reserve(addr:Variable, capacity:usize);
//pub fn list_resize(addr:Variable, length:usize);
pub fn list_capacity(addr:Reference) -> usize;
pub fn list_length(addr:Reference) -> usize;
//pub fn list_first(addr:Reference) -> Reference;
//pub fn list_last(addr:Reference) -> Reference;
pub fn list_at(addr:Reference, index:usize) -> Reference;
pub fn list_clear(addr:Reference);
//pub fn list_prepend(addr:Reference, src:Reference);
//pub fn list_append(addr:Reference, src:Reference);
pub fn list_insert(addr:Reference, index:usize, src:Reference);
pub fn list_update(addr:Reference, index:usize, src:Reference);
//pub fn list_truncate(addr:Reference, maximum:usize);
//pub fn list_shift(addr:Reference, maximum:usize);
pub fn list_remove(addr:Reference, index:usize, count:usize);
pub fn list_reserve(addr:Reference, capacity:usize);
//pub fn list_resize(addr:Reference, length:usize);
//pub fn list_cut(addr:Variable, index:usize, length:usize) -> Variable;
//pub fn list_cut(addr:Reference, index:usize, length:usize) -> Reference;
//pub fn list_find(addr:Variable, target:Variable, start:usize) -> usize;
//pub fn list_count(addr:Variable, target:Variable, start:usize) -> usize;
//pub fn list_find(addr:Reference, target:Reference, start:usize) -> usize;
//pub fn list_count(addr:Reference, target:Reference, start:usize) -> usize;
pub fn schema_length(addr:Reference) -> usize;
pub fn schema_add(addr:Reference, type_id:usize) -> usize;
pub fn schema_remove(addr:Reference, index:usize);
pub fn schema_reorder(addr:Reference, from:usize, to:usize);
pub fn schema_map(addr:Reference, key:usize, index:usize);
pub fn schema_unmap(addr:Reference, key:usize);
pub fn schema_index(addr:Reference, key:usize) -> usize;
pub fn schema_bind(addr:Reference, id:usize) -> usize;
}

View File

@ -18,8 +18,8 @@ public:
NameTree();
~NameTree();
size_t lookup(const std::string& value);
std::string get(size_t) const;
size_t indexof(const std::string& value);
std::string keyof(size_t) const;
private:
std::vector<Node> m_nodes;
@ -36,64 +36,72 @@ NameTree::NameTree()
NameTree::~NameTree()
{ }
size_t NameTree::lookup(const std::string& value)
size_t NameTree::indexof(const std::string& key)
{
size_t current = 0;
size_t index = 0;
while(index < value.length()) {
// descend node tree until key is found
while(index < key.length()) {
Node& node = m_nodes[current];
size_t find = 0;
for(size_t ci = 0; ci < node.children.size(); ++ci) {
size_t child = node.children[ci];
if(value[index] == m_nodes[child].prefix[0]) {
size_t prefix_index = 0;
for(; prefix_index < m_nodes[child].prefix.length() && index < value.length(); prefix_index++ && index++) {
if(m_nodes[child].prefix[prefix_index] != value[index]) {
break;
}
// search child nodes for first character match
bool find = false;
for(size_t list_index = 0; list_index < node.children.size(); ++list_index) {
size_t child_index = node.children[list_index];
Node& child = m_nodes[child_index];
// match extent of key to child prefix
if(child.prefix[0] == key[index]) {
index++;
find = true;
size_t prefix_index = 1;
for(; prefix_index < child.prefix.length() && index < key.length(); prefix_index++ && index++) {
// check whether prefixes are equal
if(child.prefix[prefix_index] != key[index]) { break; }
}
if(prefix_index == m_nodes[child].prefix.length()) {
current = child;
// if prefix matches, continue to child node
if(prefix_index == child.prefix.length()) {
current = child_index;
break;
}
else {
find = child;
// create intermediate node
m_nodes.push_back(Node(m_nodes[child].prefix.substr(0, prefix_index), child));
m_nodes[current].children[ci] = m_nodes.size() - 1;
m_nodes[m_nodes.size() - 1].children.push_back(child);
// otherwise, branch prefix and create node for key
else {
// create intermediate node, retaining node index of original
m_nodes.push_back(Node(m_nodes[child_index].prefix.substr(0, prefix_index), current));
size_t intermediate_index = m_nodes.size() - 1;
m_nodes[current].children[list_index] = intermediate_index;
m_nodes[intermediate_index].children.push_back(child_index);
// update child node
m_nodes[child].parent = m_nodes.size() - 1;
m_nodes[child_index].prefix = m_nodes[child_index].prefix.substr(prefix_index);
m_nodes[child_index].parent = intermediate_index;
// create branching node if value is not prefix
if(index != value.length()) {
m_nodes.push_back(Node(value.substr(index), child));
find = m_nodes.size() - 1;
if(index != key.length()) {
m_nodes.push_back(Node(key.substr(index), intermediate_index));
}
return find;
return m_nodes.size() - 1;
}
}
}
if(find == 0) {
// add suffix to new node pointing to value
m_nodes.push_back(Node(value.substr(index), current));
find = m_nodes.size() - 1;
node.children.push_back(find);
return find;
// if first character is not found, create new child
if(!find) {
m_nodes.push_back(Node(key.substr(index), current));
m_nodes[current].children.push_back(m_nodes.size() - 1);
return m_nodes.size() - 1;
}
}
return current;
}
std::string NameTree::get(size_t id) const
std::string NameTree::keyof(size_t id) const
{
size_t length = 0;
std::string out;
@ -104,7 +112,7 @@ std::string NameTree::get(size_t id) const
current = m_nodes[current].parent;
}
out = std::string(length, '\0');
out = std::string(length, 0);
size_t index = length - 1;
for(size_t current = id; current != 0;) {

93
src/runtime/rawlist.cc Normal file
View File

@ -0,0 +1,93 @@
#include "rawlist.h"
void* rawlist_insert(RawList& list, size_t offset, size_t index)
{
if(list.length == list.capacity) { rawlist_reserve(list, offset, (list.capacity == 0) + list.capacity * 2); }
if(index > list.length) { index = list.length; }
// shift elements back until index is reached
for(size_t i = list.length; i > index; --i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset);
}
list.length++;
return rawlist_cell(list, offset, index);
}
void rawlist_remove(RawList& list, size_t offset, size_t index)
{
if(index > list.length) { index = list.length - 1; }
// shift elements back until index is reached
for(size_t i = index; i < list.length - 1; ++i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset);
}
list.length--;
memset(rawlist_cell(list, offset, list.length), 0, offset);
}
void rawlist_reorder(RawList& list, size_t offset, size_t from, size_t to)
{
// ensure there is a trailing cell in which to swap moving data
if(list.length == list.capacity) { rawlist_reserve(list, offset, list.capacity * 2); }
if(from > list.length) { from = list.length - 1; }
if(to > list.length) { to = list.length - 1; }
if(from != to) {
// move data to unused cell
memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset);
if(from < to) {
for(size_t i = from; i < to; ++i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset);
}
}
else if(from > to) {
for(size_t i = from; i > to; --i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset);
}
}
// move data to target cell and clear swap cell
memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset);
memset(rawlist_cell(list, offset, list.length), 0, offset);
}
}
inline void* rawlist_cell(RawList& list, size_t offset, size_t index)
{
if(index < list.capacity) {
return reinterpret_cast<void*>(reinterpret_cast<size_t>(list.data) + (offset * index));
}
else {
return nullptr;
}
}
void rawlist_reserve(RawList& list, size_t offset, size_t capacity)
{
if(capacity > list.capacity) {
size_t block_size = offset * capacity;
void* old_data = list.data;
list.data = malloc(block_size);
memset(list.data, 0, block_size);
if(old_data != nullptr) {
memcpy(list.data, old_data, offset * list.length);
free(old_data);
}
list.capacity = capacity;
}
}
void rawlist_clear(RawList& list)
{
if(list.data != nullptr) {
free(list.data);
}
list.capacity = 0;
list.length = 0;
list.data = nullptr;
}

20
src/runtime/rawlist.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef RAWLIST_H
#define RAWLIST_H
#include <cstdlib>
#include <cstring>
struct RawList {
size_t offset;
size_t capacity;
size_t length;
void* data;
};
void* rawlist_insert(RawList& list, size_t offset, size_t index);
void rawlist_remove(RawList& list, size_t offset, size_t index);
inline void* rawlist_cell(RawList& list, size_t offset, size_t index);
void rawlist_reserve(RawList& list, size_t offset, size_t capacity);
void rawlist_clear(RawList& list);
#endif

View File

@ -1,11 +0,0 @@
#ifndef H_SCHEMA
#define H_SCHEMA
#include <cstdint>
struct Schema {
std::vector<uint32_t> types;
std::vector<std::pair<uint32_t, uint16_t>> names;
};
#endif

View File

@ -1,6 +1,7 @@
#include <cstdint>
#include "rawlist.h"
extern "C" struct Variable {
extern "C" struct Reference {
size_t type;
void* address;
};
@ -9,22 +10,19 @@ namespace Type {
namespace Tag {
enum {
Varying = 0x00,
Null = 0x01,
Boolean = 0x02,
Natural = 0x10,
Integer = 0x11,
Block = 0x1e,
String = 0x1f,
//Optional = 0x20,
//Set = 0x21,
Array = 0x22,
List = 0x23,
Sparse = 0x24,
//Trie = 0x27,
//Map = 0x28,
Record = 0x4e,
Schema = 0x4f,
Null = 0x00,
Varying = 0x01,
Boolean = 0x02,
Natural = 0x10,
Integer = 0x11,
Decimal = 0x12,
Block = 0x1e,
Sequence = 0x1f,
Array = 0x22,
List = 0x23,
Sparse = 0x24,
Record = 0x7e,
Schema = 0x7f,
};
}
@ -32,16 +30,45 @@ typedef bool Boolean;
typedef uint64_t Natural;
typedef int64_t Integer;
struct Sequence {
RawList data;
};
struct List {
size_t capacity;
size_t length;
void* data;
RawList data;
};
struct Sparse {
struct Header {
size_t start;
size_t length;
size_t index;
Header() {
start = 0;
length = 0;
index = 0;
}
};
RawList data;
RawList header;
};
struct Schema {
size_t capacity;
size_t length;
void* data;
struct Mapping {
size_t key;
size_t index;
};
RawList data;
RawList map;
};
struct SchemaBinding {
size_t binding;
size_t size;
Schema schema;
};
}

16
src/runtime/util.rs Normal file
View File

@ -0,0 +1,16 @@
pub fn name_indexof(key:&str) -> usize
{
unsafe {super::name_indexof(key.as_ptr(), key.len())}
}
pub fn name_keyof(index:usize) -> String
{
let str = unsafe {super::name_keyof(index)};
let bytes = Vec::<u8>::from(unsafe {std::slice::from_raw_parts(str.bytes, str.length)});
let result = match String::from_utf8(bytes) {
Ok(str) => str,
Err(_) => String::new()
};
unsafe { super::name_release(str); }
return result;
}

View File

@ -1,28 +1,25 @@
//pub type Class = usize;
pub const VARYING :usize = 0x00;
pub const NULL :usize = 0x01;
pub const BOOLEAN :usize = 0x02;
//...
pub const NATURAL :usize = 0x10;
pub const INTEGER :usize = 0x11;
//pub const DECIMAL :usize = 0x12;
//pub const FLOAT :usize = 0x13;
//pub const COMPLEX :usize = 0x14;
//...
//pub const RANGE :usize = 0x1c;
//pub const CHAR :usize = 0x1d;
pub const BLOCK :usize = 0x1e;
pub const STRING :usize = 0x1f;
pub const NULL :usize = 0x00;
pub const VARYING :usize = 0x01;
pub const BOOLEAN :usize = 0x02;
pub const NATURAL :usize = 0x10;
pub const INTEGER :usize = 0x11;
pub const DECIMAL :usize = 0x12;
//pub const FLOAT :usize = 0x13;
//pub const COMPLEX :usize = 0x14;
//pub const RANGE :usize = 0x1c;
//pub const CHAR :usize = 0x1d;
pub const BLOCK :usize = 0x1e;
pub const SEQUENCE :usize = 0x1f;
//pub const OPTIONAL :usize = 0x20;
//pub const SET :usize = 0x21;
pub const ARRAY :usize = 0x22;
pub const LIST :usize = 0x23;
pub const SPARSE :usize = 0x24;
//pub const MAP :usize = 0x25;
//pub const TRIE :usize = 0x26;
//pub const TREE :usize = 0x27;
//pub const GRAPH :usize = 0x28;
//...
pub const RECORD :usize = 0x7e;
pub const SCHEMA :usize = 0x7f;
//pub const SET :usize = 0x21;
pub const ARRAY :usize = 0x22;
pub const LIST :usize = 0x23;
pub const SPARSE :usize = 0x24;
//pub const TRIE :usize = 0x25;
//pub const MAP :usize = 0x26;
//pub const TREE :usize = 0x27;
//pub const GRAPH :usize = 0x28;
pub const RECORD :usize = 0x7e;
pub const SCHEMA :usize = 0x7f;