strings
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
(prim:write (prim:car (prim:cons 123 456)))
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
(prim:write (prim:cdr (prim:cons 123 456)))
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
use std::slice;
|
||||||
|
|
||||||
|
use crate::scm::scm_bits;
|
||||||
|
use crate::scm;
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn scm_from_utf8_string (
|
||||||
|
ptr : *const u8,
|
||||||
|
len : usize
|
||||||
|
) -> scm_bits {
|
||||||
|
let bytes = unsafe { slice::from_raw_parts (ptr, len) };
|
||||||
|
scm::make_string (str::from_utf8 (bytes).unwrap ())
|
||||||
|
}
|
||||||
+2
-1
@@ -4,4 +4,5 @@
|
|||||||
mod gc;
|
mod gc;
|
||||||
mod scm;
|
mod scm;
|
||||||
mod primitives;
|
mod primitives;
|
||||||
|
mod obarray;
|
||||||
|
mod capi;
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
use std::{collections::HashMap, hash::{BuildHasher, Hasher}};
|
||||||
|
use crate::scm::scm_bits;
|
||||||
|
use crate::scm;
|
||||||
|
|
||||||
|
mod fnv1a;
|
||||||
|
|
||||||
|
pub struct Obarray (HashMap <String, scm_bits>);
|
||||||
|
|
||||||
|
pub fn hash () {
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
use std::{collections::HashMap, hash::{BuildHasher, Hasher}};
|
||||||
|
|
||||||
|
pub struct FNV1a (u64);
|
||||||
|
pub struct SymbolHash;
|
||||||
|
|
||||||
|
impl Hasher for FNV1a {
|
||||||
|
fn finish (&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write (&mut self, bytes: &[u8]) {
|
||||||
|
for b in bytes {
|
||||||
|
self.0 ^= *b as u64;
|
||||||
|
self.0 *= prime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuildHasher for SymbolHash {
|
||||||
|
type Hasher = FNV1a;
|
||||||
|
|
||||||
|
fn build_hasher (&self) -> Self::Hasher {
|
||||||
|
FNV1a (offset_basis)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const offset_basis : u64 = 0xcbf29ce484222325;
|
||||||
|
const prime : u64 = 0x100000001b3;
|
||||||
@@ -13,6 +13,7 @@ pub extern "C" fn scm_write (x: scm_bits) -> scm_bits {
|
|||||||
scm_write (cdr);
|
scm_write (cdr);
|
||||||
print! (")");
|
print! (")");
|
||||||
},
|
},
|
||||||
|
SCM::String (s) => print! ("\"{s}\""),
|
||||||
SCM::Nil => print! ("()"),
|
SCM::Nil => print! ("()"),
|
||||||
SCM::False => print! ("#f"),
|
SCM::False => print! ("#f"),
|
||||||
SCM::True => print! ("#t"),
|
SCM::True => print! ("#t"),
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
|
use crate::gc;
|
||||||
|
|
||||||
pub type scm_bits = u64;
|
pub type scm_bits = u64;
|
||||||
|
|
||||||
pub const tc2_int : u64 = 2;
|
pub const tc2_int : u64 = 2;
|
||||||
@@ -16,6 +20,7 @@ pub const tc7_string : u64 = 0x15;
|
|||||||
pub enum SCM {
|
pub enum SCM {
|
||||||
SmallInt (i64),
|
SmallInt (i64),
|
||||||
Cons (scm_bits, scm_bits),
|
Cons (scm_bits, scm_bits),
|
||||||
|
String (String),
|
||||||
Nil,
|
Nil,
|
||||||
False,
|
False,
|
||||||
True,
|
True,
|
||||||
@@ -35,6 +40,18 @@ pub fn unpack (x : scm_bits) -> SCM {
|
|||||||
} else if is_cons (x) {
|
} else if is_cons (x) {
|
||||||
// `car` x and `cdr` x are safe iff `is_cons` x.
|
// `car` x and `cdr` x are safe iff `is_cons` x.
|
||||||
unsafe { SCM::Cons (car (x), cdr (x)) }
|
unsafe { SCM::Cons (car (x), cdr (x)) }
|
||||||
|
} else if is_string (x) {
|
||||||
|
let len = unsafe { cell_word (x, 1) };
|
||||||
|
let str_beginning = (x as *const scm_bits).wrapping_add (2) as *const u8;
|
||||||
|
let slice = unsafe {
|
||||||
|
str::from_utf8 (
|
||||||
|
slice::from_raw_parts (
|
||||||
|
str_beginning,
|
||||||
|
len.try_into ().unwrap ()
|
||||||
|
)
|
||||||
|
).unwrap ()
|
||||||
|
};
|
||||||
|
return SCM::String (String::from (slice));
|
||||||
} else {
|
} else {
|
||||||
// concat_panic! ("don't know how to unpack: ", x)
|
// concat_panic! ("don't know how to unpack: ", x)
|
||||||
panic! ("don't know how to unpack {x:#016x}")
|
panic! ("don't know how to unpack {x:#016x}")
|
||||||
@@ -49,6 +66,10 @@ const fn is_immediate (x: scm_bits) -> bool {
|
|||||||
6 & x != 0
|
6 & x != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_string (x: scm_bits) -> bool {
|
||||||
|
has_tc7 (x, tc7_string)
|
||||||
|
}
|
||||||
|
|
||||||
fn is_cons (x: scm_bits) -> bool {
|
fn is_cons (x: scm_bits) -> bool {
|
||||||
// safety of `cell_type` is mutually exclusive with
|
// safety of `cell_type` is mutually exclusive with
|
||||||
// `is_immediate`, so this is okay.
|
// `is_immediate`, so this is okay.
|
||||||
@@ -57,6 +78,12 @@ fn is_cons (x: scm_bits) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_tc7 (x: scm_bits, tc7: u64) -> bool {
|
||||||
|
unsafe {
|
||||||
|
! is_immediate (x) && (0x7f & cell_type (x)) == tc7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn cell_type (x: scm_bits) -> scm_bits {
|
unsafe fn cell_type (x: scm_bits) -> scm_bits {
|
||||||
unsafe { cell_word (x, 0) }
|
unsafe { cell_word (x, 0) }
|
||||||
}
|
}
|
||||||
@@ -75,3 +102,50 @@ unsafe fn car (x: scm_bits) -> scm_bits {
|
|||||||
unsafe fn cdr (x: scm_bits) -> scm_bits {
|
unsafe fn cdr (x: scm_bits) -> scm_bits {
|
||||||
unsafe { cell_word (x, 1) }
|
unsafe { cell_word (x, 1) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn words (tag : scm_bits, n : usize) -> *mut scm_bits {
|
||||||
|
let r = unsafe { gc::malloc (n * size_of::<scm_bits> ()) };
|
||||||
|
unsafe { *r = tag };
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pack_ptr (obj : *const scm_bits) -> scm_bits {
|
||||||
|
obj as scm_bits
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn set_word (obj : *mut scm_bits, ix : usize, val : scm_bits) {
|
||||||
|
let x = obj.wrapping_add (ix);
|
||||||
|
unsafe { *x = val; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn make_string_from_raw_parts (
|
||||||
|
ptr : *const u8,
|
||||||
|
len : usize
|
||||||
|
) -> scm_bits {
|
||||||
|
let bytes = unsafe { slice::from_raw_parts (ptr, len) };
|
||||||
|
make_string (str::from_utf8 (bytes).unwrap ())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_string (s : &str) -> scm_bits {
|
||||||
|
let len = s.len ();
|
||||||
|
let size_of_tag_and_len = 2 * size_of::<scm_bits> ();
|
||||||
|
let size_of_contents = len;
|
||||||
|
let r = unsafe { gc::malloc (size_of_tag_and_len + size_of_contents) };
|
||||||
|
unsafe {
|
||||||
|
set_word (r, 0, tc7_string);
|
||||||
|
set_word (r, 1, len as u64);
|
||||||
|
}
|
||||||
|
let str_beginning = r.wrapping_add (2) as *mut u8;
|
||||||
|
for (i, b) in s.as_bytes ().iter ().enumerate () {
|
||||||
|
unsafe { *(str_beginning.wrapping_add (i)) = *b };
|
||||||
|
}
|
||||||
|
return pack_ptr (r)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn make_symbol (name : &str) -> scm_bits {
|
||||||
|
todo! ()
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
use std::collections;
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user