From 182bf00f717a727e49330b58e08c93b770b7f689 Mon Sep 17 00:00:00 2001 From: yukirij Date: Fri, 11 Aug 2023 18:32:50 -0700 Subject: [PATCH] Add tests, add interface methods, updated README. --- README.md | 224 ++++++++++++++++++++++++++++++++++++++ src/bin/main.rs | 2 +- src/interface/array.rs | 4 +- src/interface/block.rs | 8 +- src/interface/list.rs | 2 +- src/interface/sequence.rs | 43 +++++--- src/lib.rs | 171 +++++++++++++++++++++++------ src/runtime/lib.cc | 21 +++- src/runtime/lib.h | 4 + src/runtime/mod.rs | 1 + src/runtime/sparselist.h | 41 +++++++ src/runtime/type.h | 1 + 12 files changed, 464 insertions(+), 58 deletions(-) create mode 100644 src/runtime/sparselist.h diff --git a/README.md b/README.md index daf56be..a29b859 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,226 @@ # Suzu Runtime and Notation +# Documentation + +## Conventions + +### Namespacing +Examples in this documentation will assume inclusion of the szun namespace. +In practice, this is not recommended outside of limited scopes. +``` +fn procedure() +{ + use szun::*; + + /* ... */ +} +``` + + +## Type Building +Type building functions allow for the construction of identifiers representing complex data types. These identifiers are used to allocate typed +``` +varying() +boolean() +natural() +integer() +block(size) +sequence() +array(size, type) +list(type) +schema() +record(schema) +``` + +### Example +This example produces an identifier representing a list of blocks of 4 bytes each. +``` +let type_id = list(block(4)); +``` + +## Global Functions + +### allocate(type) +``` +let ref = allocate(list(integer())); +``` + +### encode(ref:Reference) -> vec + +### decode(data:Vec) -> Reference + + +## Language Compiler + + +## Common Methods + +### new() -> Self +``` +let value = Integer::new(); +``` + +### from(ref:Reference) -> Result +``` +match Integer::from(list.at(0)) { + Ok(data) => { println!("Integer: {}", data); } + Err(_) => { println!("Not Integer"); } +} +``` + +### with(value) -> Self +``` +let b = Boolean::with(true); +``` + +### Dereference +``` +let ref = *Integer::new(); +``` + + +## Varying + +### set(ref:Reference) +``` +let var = Varying::new(); +var.set(*Sequence::with("Hello!")) +``` + +### get() -> Reference +``` +let var = Varying::with(*Boolean::with(true)); +let ref = var.get(); +``` + + +## Boolean +Stores the value true or false. + +### get() -> bool +``` +let value = Boolean::with(true); +if value.get() { + println!("True"); +} +``` + +### set(value:bool) +``` +let mut value = Boolean::new(); +value.set(true); +``` + + +## Natural +Stores a non-negative integer value. + +### get() -> u64 +``` +let value = Integer::with(-1); +println!("{}", value.get()); +``` + +### set(value:u64) +``` +let mut value = Integer::new(); +value.set(-273); +``` + + +## Integer +Stores a signed integer value. + +### get() -> i64 +``` +let value = Integer::with(-1); +println!("{}", value.get()); +``` + +### set(value:i64) +``` +let mut value = Integer::new(); +value.set(-273); +``` + + +## Block +Constant-sized series of bytes. + + +## Sequence +Variable-sized series of bytes. + +### get() -> String + +### get_raw() -> Vec + +### set(data:&str) + +### set_raw(data:Vec) + + +## Array +Constant-sized, ordered collection of items. + +### new(size:usize, type_id:usize) + +### length() -> usize + +### at(index:usize) -> Reference + +### set(index:usize, ref:Reference) + + +## List +Variable-sized, ordered collection of items. + +### new(type_id:usize) + +### length() -> usize + +### capacity() -> usize + +### at(index:usize) -> Reference + +### set(index:usize, ref:Reference) + +### insert(index:usize, ref:Reference) + +### remove(index:usize) + +### reserve(capacity:usize) + +### clear() + + +## Schema +Definition of an abstract structure composed of named items. + +### get(index:usize) -> usize + +### add(type_id:usize) -> usize + +### remove(index:usize) + +### assign(key:&str, type_id:usize) -> usize + +### map(key:&str, index:usize) + +### unmap(key:&str) + +### clear() + +### bind(id:usize) + + +## Record +Instance of a schema. + +### at(index:usize) -> Reference + +### set(index:usize, source:Reference) + +### keyof(index:usize) -> String + +### indexof(key:&str) -> usize diff --git a/src/bin/main.rs b/src/bin/main.rs index 32c3e56..933b1e8 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,4 +1,4 @@ fn main() { - szun::test(); + } diff --git a/src/interface/array.rs b/src/interface/array.rs index 4479293..fb0b3c3 100644 --- a/src/interface/array.rs +++ b/src/interface/array.rs @@ -34,7 +34,7 @@ impl Array { { let mut obj = Self::new(length, class); for i in 0..usize::min(length, data.len()) { - obj.update(i, data[i]); + obj.set(i, data[i]); } return obj; } @@ -44,7 +44,7 @@ impl Array { unsafe {array_length(self.addr)} } - pub fn update(&mut self, index:usize, source:Reference) + pub fn set(&mut self, index:usize, source:Reference) { unsafe { array_update(self.addr, index, source); } } diff --git a/src/interface/block.rs b/src/interface/block.rs index 5f2c9fa..1bb9791 100644 --- a/src/interface/block.rs +++ b/src/interface/block.rs @@ -2,7 +2,8 @@ use crate::runtime::{ Reference, acquire, release, type_inner, type_key, - block_set, block_get + block_length, + block_set, block_get, }; use crate::tag; use super::block; @@ -30,6 +31,11 @@ impl Block { } } + pub fn length(&self) -> usize + { + unsafe {block_length(self.addr)} + } + pub fn set(&mut self, data:Vec) { let length = unsafe {type_key(type_inner(self.addr.class))}; diff --git a/src/interface/list.rs b/src/interface/list.rs index 93c5802..98b5807 100644 --- a/src/interface/list.rs +++ b/src/interface/list.rs @@ -69,7 +69,7 @@ impl List { unsafe{list_insert(self.addr, index, source)}; } - pub fn update(&mut self, index:usize, source:Reference) + pub fn set(&mut self, index:usize, source:Reference) { unsafe{list_update(self.addr, index, source)}; } diff --git a/src/interface/sequence.rs b/src/interface/sequence.rs index dd0f251..53f30b4 100644 --- a/src/interface/sequence.rs +++ b/src/interface/sequence.rs @@ -40,33 +40,46 @@ impl Sequence { return obj; } - pub fn set(&mut self, data:&str) + pub fn length(&self) -> usize + { + unsafe {sequence_length(self.addr)} + } + + pub fn set_raw(&mut self, data:Vec) { 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]); } + if data.len() > 0 { + unsafe { sequence_reserve(self.addr, data.len()); } + for i in 0..data.len() { + unsafe { sequence_insert(self.addr, i, data[i]); } } } } - pub fn get(&self) -> String + pub fn set(&mut self, data:&str) + { + self.set_raw(Vec::from(data.as_bytes())); + } + + pub fn get_raw(&self) -> Vec { let length = unsafe {sequence_length(self.addr)}; + let mut result = Vec::::new(); + if length > 0 { - let mut bytes = Vec::::with_capacity(length); + result.reserve_exact(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(), + result.push(unsafe {sequence_get(self.addr, i)}); } } - else { - return String::new(); + return result; + } + + pub fn get(&self) -> String + { + match String::from_utf8(self.get_raw()) { + Ok(s) => s, + Err(_) => String::new(), } } } diff --git a/src/lib.rs b/src/lib.rs index 6a3c8d8..fcb20f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,61 +5,61 @@ mod util; mod runtime; mod interface; pub use interface::*; -fn assert(expected:T, actual:T) where T:std::fmt::Display, T:std::cmp::PartialEq +fn check(expected:T, actual:T) where T:std::fmt::Display, T:std::cmp::PartialEq { print!(" ({}) ", if expected == actual { " " } else { "!" }); println!("'{}' = '{}'", expected, actual); } -pub fn test() +/*pub fn test() { { println!("Boolean"); let mut dat = Boolean::new(); - assert::(false, dat.get()); + check(false, dat.get()); dat.set(true); - assert::(true, dat.get()); + check(true, dat.get()); dat.set(false); - assert::(false, dat.get()); + check(false, dat.get()); } { println!("Natural"); let mut dat = Natural::new(); - assert::(0, dat.get()); + check(0, dat.get()); dat.set(50); - assert::(50, dat.get()); + check(50, dat.get()); dat.set(25000); - assert::(25000, dat.get()); + check(25000, dat.get()); } { println!("Integer"); let mut dat = Integer::new(); - assert::(0, dat.get()); + check(0, dat.get()); dat.set(-12); - assert::(-12, dat.get()); + check(-12, dat.get()); dat.set(38695); - assert::(38695, dat.get()); + check(38695, dat.get()); } { println!("Block"); let mut dat = Block::new(4); dat.set(vec![1, 2, 3, 4]); - assert::(4, dat.get().len()); - assert::(1, dat.get()[0]); - assert::(2, dat.get()[1]); - assert::(3, dat.get()[2]); - assert::(4, dat.get()[3]); + check(4, dat.get().len()); + check(1, dat.get()[0]); + check(2, dat.get()[1]); + check(3, dat.get()[2]); + check(4, dat.get()[3]); } { println!("Sequence"); let mut dat = Sequence::new(); - assert::(String::from(""), dat.get()); + check(String::from(""), dat.get()); dat.set("hello"); - assert::(String::from("hello"), dat.get()); + check(String::from("hello"), dat.get()); } { @@ -69,14 +69,14 @@ pub fn test() 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::(4, dat.length()); - assert::(250, Natural::from(dat.at(0)).unwrap().get()); - assert::(500, Natural::from(dat.at(1)).unwrap().get()); - assert::(750, Natural::from(dat.at(2)).unwrap().get()); - assert::(1000,Natural::from(dat.at(3)).unwrap().get()); + check(4, dat.length()); + check(250, Natural::from(dat.at(0)).unwrap().get()); + check(500, Natural::from(dat.at(1)).unwrap().get()); + check(750, Natural::from(dat.at(2)).unwrap().get()); + check(1000,Natural::from(dat.at(3)).unwrap().get()); } - /* { + { println!("List - Undefined"); println!("List - Variable"); @@ -97,20 +97,127 @@ pub fn test() 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"); + let mut sch = Schema::new(); + sch.add(integer()); + sch.map("abc", 0); + check(1, sch.length()); + check(0, sch.index("abc")); + check(sch.length(), sch.index("def")); + } - }*/ - - /*{ + { println!("Record"); - }*/ + } +}*/ + +#[cfg(test)] +mod tests { + #[test] + fn boolean_initialize() + { + let value = crate::Boolean::new(); + assert_eq!(false, value.get(), "Boolean::new() produces value of false."); + } + + #[test] + fn boolean_with() + { + assert_eq!(false, crate::Boolean::with(false).get(), "Boolean::with(false) produces value of false."); + assert_eq!(true, crate::Boolean::with(true).get(), "Boolean::with(true) produces value of true."); + } + + #[test] + fn boolean_set_get() + { + let mut value = crate::Boolean::new(); + value.set(true); + assert_eq!(true, value.get(), "Boolean.set(true) produces value of true."); + value.set(false); + assert_eq!(false, value.get(), "Boolean.set(false) produces value of false."); + } + + #[test] + fn natural_initialize() + { + let value = crate::Natural::new(); + assert_eq!(0, value.get(), "Natural::new() produces value of 0."); + } + + #[test] + fn natural_set_get() + { + let mut value = crate::Natural::new(); + value.set(12); + assert_eq!(12, value.get(), "Natural.set(12) produces value of 12."); + value.set(38695); + assert_eq!(38695, value.get(), "Natural.set(38695) produces value of 38695."); + } + + #[test] + fn integer_initialize() + { + let value = crate::Integer::new(); + assert_eq!(0, value.get(), "Integer::new() produces value of 0."); + } + + #[test] + fn integer_set_get() + { + let mut value = crate::Integer::new(); + value.set(-273); + assert_eq!(-273, value.get(), "Integer.set(-273) produces value of -273."); + value.set(100); + assert_eq!(100, value.get(), "Integer.set(100) produces value of 100."); + } + + #[test] + fn block_initialize() + { + let value = crate::Block::new(8); + assert_eq!(8, value.length(), "Block::new(8) has length of 8."); + assert_eq!(vec![0;8], value.get(), "Block::new(8) has value of 0."); + } + + #[test] + fn block_set_get() + { + let mut value = crate::Block::new(4); + value.set(vec![1, 2, 3, 4]); + assert_eq!(vec![1, 2, 3, 4], value.get(), "Block::set([1,2,3,4]) has value of [1,2,3,4]."); + } + + #[test] + fn sequence_initialize() + { + let value = crate::Sequence::new(); + assert_eq!(0, value.length(), "Sequence::new() has length 0."); + } + + #[test] + fn sequence_set_get_raw() + { + let mut value = crate::Sequence::new(); + value.set_raw(vec![0, 1, 2, 3, 2, 1]); + assert_eq!(6, value.length(), "Sequence.set_raw([0,1,2,3,2,1]) has length 6."); + assert_eq!(vec![0,1,2,3,2,1], value.get_raw(), "Sequence.set_raw([0,1,2,3,2,1]) produces value [0,1,2,3,2,1]."); + } + + #[test] + fn sequence_set_get_str() + { + let mut value = crate::Sequence::new(); + value.set("hello"); + assert_eq!(5, value.length(), "Sequence.set(hello) has length 5."); + assert_eq!(String::from("hello"), value.get(), "Sequence.set(hello) produces value hello."); + } } diff --git a/src/runtime/lib.cc b/src/runtime/lib.cc index bad764a..ac051ae 100644 --- a/src/runtime/lib.cc +++ b/src/runtime/lib.cc @@ -293,6 +293,11 @@ extern "C" Type::Integer integer_get(Reference addr) // Block // +extern "C" size_t block_length(Reference addr) +{ + return type_key(type_inner(addr.type)); +} + extern "C" uint8_t block_get(Reference addr, size_t index) { size_t length = type_key(type_inner(addr.type)); @@ -681,7 +686,7 @@ extern "C" void schema_unmap(Reference addr, size_t key) extern "C" size_t schema_index(Reference addr, size_t key) { auto& object = (*reinterpret_cast(addr.address)); - for(size_t i; i < object.map.length; i++) { + for(size_t i = 0; i < object.map.length; i++) { auto cell = reinterpret_cast(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i)); if(cell != nullptr) { if(cell->key == key) { @@ -700,11 +705,15 @@ extern "C" size_t schema_bind(Reference addr, size_t id) // 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); + for(size_t i = 0; i < object.data.length; ++i) { + size_t type_id = *reinterpret_cast(rawlist_cell(object.data, sizeof(size_t), i)); + size_t size = type_size(type_id); + size_t alignment = size; + binding.alignment = std::max(alignment, binding.alignment); + size_t position = ((binding.size + (alignment - 1)) & ~(alignment - 1)); + binding.size = size + position; + } + binding.size = ((binding.size + (binding.alignment - 1)) & ~(binding.alignment - 1)); // add binding to pool //DB_SCHEMA.add(id, binding); diff --git a/src/runtime/lib.h b/src/runtime/lib.h index b29c31a..619e9c9 100644 --- a/src/runtime/lib.h +++ b/src/runtime/lib.h @@ -5,6 +5,7 @@ #include "type.h" #include "typetree.h" #include "nametree.h" +//#include "sparselist.h" #include "rawlist.h" #include "pool.h" @@ -23,6 +24,8 @@ 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 schema_bind(Reference addr, size_t 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); @@ -50,6 +53,7 @@ extern "C" void integer_set(Reference addr, Type::Integer value); extern "C" Type::Integer integer_get(Reference addr); // Block // +extern "C" size_t block_length(Reference addr); extern "C" uint8_t block_get(Reference addr, size_t index); extern "C" void block_set(Reference addr, size_t index, uint8_t value); diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 78dbced..0c8a612 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -43,6 +43,7 @@ extern "C" { pub fn integer_set(addr:Reference, data:i64); pub fn integer_get(addr:Reference) -> i64; + pub fn block_length(addr:Reference) -> usize; pub fn block_set(addr:Reference, index:usize, data:u8); pub fn block_get(addr:Reference, index:usize) -> u8; diff --git a/src/runtime/sparselist.h b/src/runtime/sparselist.h new file mode 100644 index 0000000..aa222b5 --- /dev/null +++ b/src/runtime/sparselist.h @@ -0,0 +1,41 @@ +#ifndef H_SPARSELIST +#define H_SPARSELIST + +#include + +template +class SparseList { +public: + SparseList() + { } + + ~SparseList() + { } + + void set(size_t index, const T& value) + { + + } + + void unset(size_t index) + { + + } + + T& get(size_t index) + { + + } + +private: + struct Header { + size_t start; + size_t length; + size_t index; + }; + + std::vector
headers; + std::vector data; +}; + +#endif diff --git a/src/runtime/type.h b/src/runtime/type.h index 480a8ac..9d8f6b6 100644 --- a/src/runtime/type.h +++ b/src/runtime/type.h @@ -67,6 +67,7 @@ struct Schema { struct SchemaBinding { size_t binding; + size_t alignment; size_t size; Schema schema; };