Compare commits
2 Commits
b1a210ef12
...
94be79c529
| Author | SHA1 | Date | |
|---|---|---|---|
| 94be79c529 | |||
| 2ccf7ca27d |
1
play/car.scm
Normal file
1
play/car.scm
Normal file
@@ -0,0 +1 @@
|
||||
(prim:write (prim:car (prim:cons 123 456)))
|
||||
1
play/cdr.scm
Normal file
1
play/cdr.scm
Normal file
@@ -0,0 +1 @@
|
||||
(prim:write (prim:cdr (prim:cons 123 456)))
|
||||
13
runtime/src/capi.rs
Normal file
13
runtime/src/capi.rs
Normal file
@@ -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 ())
|
||||
}
|
||||
@@ -1,26 +1,8 @@
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use std::{io::{stdout, Write}};
|
||||
mod gc;
|
||||
mod scm;
|
||||
use scm::{scm_bits, SCM};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn scm_write (x: scm_bits) -> scm_bits {
|
||||
match scm::unpack (x) {
|
||||
SCM::SmallInt (n) => print! ("{n}"),
|
||||
SCM::Cons (car, cdr) => {
|
||||
print! ("(");
|
||||
scm_write (car);
|
||||
print! (" . ");
|
||||
scm_write (cdr);
|
||||
print! (")");
|
||||
},
|
||||
SCM::Nil => print! ("()"),
|
||||
SCM::False => print! ("#f"),
|
||||
SCM::True => print! ("#t"),
|
||||
};
|
||||
let _ = stdout ().flush ();
|
||||
return 0;
|
||||
}
|
||||
mod primitives;
|
||||
mod obarray;
|
||||
mod capi;
|
||||
|
||||
10
runtime/src/obarray.rs
Normal file
10
runtime/src/obarray.rs
Normal file
@@ -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 () {
|
||||
}
|
||||
28
runtime/src/obarray/fnv1a.rs
Normal file
28
runtime/src/obarray/fnv1a.rs
Normal file
@@ -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;
|
||||
23
runtime/src/primitives.rs
Normal file
23
runtime/src/primitives.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
use crate::scm;
|
||||
use crate::scm::{scm_bits, SCM};
|
||||
use std::io::{stdout, Write};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn scm_write (x: scm_bits) -> scm_bits {
|
||||
match scm::unpack (x) {
|
||||
SCM::SmallInt (n) => print! ("{n}"),
|
||||
SCM::Cons (car, cdr) => {
|
||||
print! ("(");
|
||||
scm_write (car);
|
||||
print! (" . ");
|
||||
scm_write (cdr);
|
||||
print! (")");
|
||||
},
|
||||
SCM::String (s) => print! ("\"{s}\""),
|
||||
SCM::Nil => print! ("()"),
|
||||
SCM::False => print! ("#f"),
|
||||
SCM::True => print! ("#t"),
|
||||
};
|
||||
let _ = stdout ().flush ();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use std::slice;
|
||||
|
||||
use crate::gc;
|
||||
|
||||
pub type scm_bits = u64;
|
||||
|
||||
pub const tc2_int : u64 = 2;
|
||||
@@ -16,6 +20,7 @@ pub const tc7_string : u64 = 0x15;
|
||||
pub enum SCM {
|
||||
SmallInt (i64),
|
||||
Cons (scm_bits, scm_bits),
|
||||
String (String),
|
||||
Nil,
|
||||
False,
|
||||
True,
|
||||
@@ -35,6 +40,18 @@ pub fn unpack (x : scm_bits) -> SCM {
|
||||
} else if is_cons (x) {
|
||||
// `car` x and `cdr` x are safe iff `is_cons` 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 {
|
||||
// concat_panic! ("don't know how to unpack: ", x)
|
||||
panic! ("don't know how to unpack {x:#016x}")
|
||||
@@ -49,6 +66,10 @@ const fn is_immediate (x: scm_bits) -> bool {
|
||||
6 & x != 0
|
||||
}
|
||||
|
||||
fn is_string (x: scm_bits) -> bool {
|
||||
has_tc7 (x, tc7_string)
|
||||
}
|
||||
|
||||
fn is_cons (x: scm_bits) -> bool {
|
||||
// safety of `cell_type` is mutually exclusive with
|
||||
// `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 { 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 { 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