Clean up project structure
All checks were successful
per-push tests / build (push) Successful in 32s
per-push tests / test-utility (push) Successful in 32s
per-push tests / test-frontend (push) Successful in 34s
per-push tests / test-backend (push) Successful in 30s
per-push tests / timed-decomposer-parse (push) Successful in 26s

The number package is moved into its own package henceforth referred
to as "organelle". Hyphae and Mycelium are updated accordingly. In
addition, Hyphae gets a copy of the sexpr module of Mycelium. This
will not remain a copy, rather it will be the basis of a heap manager
module within Mycelium to be worked on in the future.

Fixes #32

Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
Ava Apples Affine 2025-07-24 19:44:43 +00:00
parent 6f95381e5e
commit 8d2d0ebf0c
12 changed files with 247 additions and 10 deletions

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2024"
[dependencies]
mycelium = { path = "../mycelium" }
organelle = { path = "../organelle" }
num = { version = "0.4.3", features = ["alloc"] }
[build-dependencies]

219
hyphae/src/heap.rs Normal file
View file

@ -0,0 +1,219 @@
/* Mycelium Scheme
* Copyright (C) 2025 Ava Affine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use core::fmt::{self, Formatter};
use core::ops::Index;
use core::cell::RefCell;
use alloc::format;
use alloc::rc::Rc;
use alloc::vec::Vec;
use alloc::string::String;
use organelle::Number;
#[derive(Default, Clone, PartialEq)]
pub enum Datum {
Number(Number),
Bool(bool),
List(Rc<Ast>),
Symbol(String),
Char(u8),
String(Vec<u8>),
Vector(RefCell<Vec<Rc<Datum>>>),
ByteVector(RefCell<Vec<u8>>),
#[default]
None,
}
fn byte_to_escaped_char(b: u8) -> String {
// alarm, backspace, delete
match b {
_ if b > 31 && b < 127 => String::from(b as char),
_ => format!("x{:x}", b),
}
}
fn fmt_vec<T: fmt::Display>(ve: &RefCell<Vec<T>>) -> String {
let v = ve.borrow();
if v.len() == 0 {
return String::new()
}
let mut s = format!("{}", v[0]);
let mut i = v.iter();
i.next(); // discard
i.for_each(|e| {
s = format!("{} {}", s, e);
});
s
}
impl fmt::Display for Datum {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Datum::Number(n) => write!(f, "{}", Into::<String>::into(*n)),
Datum::Bool(n) => write!(f, "{}", if *n {"#t"} else {"#f"}),
Datum::List(n) => write!(f, "{n}"),
Datum::Symbol(n) => write!(f, "{n}"),
Datum::Char(n) => write!(f, "#\\{}",
byte_to_escaped_char(*n)),
Datum::String(n) =>
write!(f, "\"{}\"", String::from_utf8_lossy(&*n)),
Datum::Vector(n) => write!(f, "#({})", fmt_vec(n)),
Datum::ByteVector(n) => write!(f, "#u8({})", fmt_vec(n)),
Datum::None => Ok(())
}
}
}
/* WARNING
* This is in a sense overloaded.
* Instead of using this to print debugging information for the
* Rust code, I have instead overloaded it to print the most
* maximal expanded valid syntax for this Datum
*/
impl fmt::Debug for Datum {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Datum::Number(n) => write!(f, "{}", Into::<String>::into(*n)),
Datum::Bool(n) => write!(f, "{}", if *n {"#t"} else {"#f"}),
Datum::List(n) => write!(f, "{n}"),
Datum::Char(n) => write!(f, "{}",
byte_to_escaped_char(*n)),
Datum::Symbol(n) => write!(f, "{n}"),
Datum::String(n) =>
write!(f, "\"{}\"", String::from_utf8_lossy(&*n)),
Datum::Vector(n) => write!(f, "#({n:?})"),
Datum::ByteVector(n) => write!(f, "#u8({n:?})"),
Datum::None => Ok(())
}
}
}
#[derive(Default, Clone, PartialEq)]
pub struct Ast(pub Rc<Datum>, pub Rc<Datum>);
impl Ast {
pub fn subsl(&self, start: isize, end: isize) -> Ast {
if end - start == 1 {
return Ast(Rc::from(self[start as usize].clone()), Rc::from(Datum::None))
}
if end == 0 {
return Ast(
Rc::from((*(self.0)).clone()),
Rc::from(Datum::None)
)
}
let Datum::List(ref next) = *self.1 else {
panic!("index into improper list form")
};
if start <= 0 {
Ast(
Rc::from((*(self.0)).clone()),
Rc::from(Datum::List(
Rc::from(next.subsl(start - 1, end - 1))))
)
} else {
next.subsl(start - 1, end - 1)
}
}
pub fn len(&self) -> usize {
let Datum::List(ref next) = *self.1 else {
return 1
};
1 + next.len()
}
}
impl Iterator for Ast {
type Item = Rc<Datum>;
fn next(&mut self) -> Option<Self::Item> {
if let Datum::List(n) = &*self.1 {
let tmp_pair = n;
self.0 = tmp_pair.0.clone();
self.1 = tmp_pair.1.clone();
return Some(self.0.clone());
}
if let Datum::None = *self.1 {
return None;
}
let tmp = self.1.clone();
self.0 = Rc::from(Datum::None);
self.1 = Rc::from(Datum::None);
return Some(tmp);
}
}
impl Index<usize> for Ast {
type Output = Datum;
fn index(&self, index: usize) -> &Self::Output {
if index == 0 {
if let Datum::None = *self.0 {
panic!("out of bounds indexing into AST")
} else {
self.0.as_ref()
}
} else {
let Datum::List(ref next) = *self.1 else {
panic!("out of bounds indexing into AST")
};
next.index(index - 1)
}
}
}
impl fmt::Display for Ast {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}", self.0)?;
let mut cur = self;
while let Datum::List(next) = &*cur.1 {
cur = &next;
write!(f, " {}", cur.0)?;
}
if let Datum::None = &*cur.1 {
write!(f, ")")
} else {
write!(f, " . {})", cur.1)
}
}
}
impl fmt::Debug for Ast {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}", self.0)?;
let mut cur = self;
let mut end = 1;
while let Datum::List(next) = &*cur.1 {
cur = &next;
end += 1;
write!(f, "({} . ", cur.0)?
}
write!(f, "{}{}", cur.1, ")".repeat(end))
}
}

View file

@ -22,5 +22,6 @@ pub mod stackstack;
pub mod instr;
pub mod vm;
pub mod util;
pub mod heap;
extern crate alloc;

View file

@ -16,13 +16,13 @@
*/
use mycelium::sexpr::Datum;
use mycelium::number::{Fraction, Number, Numeric};
use organelle::{Fraction, Number, Numeric};
use crate::hmap::QuickMap;
use crate::stackstack::StackStack;
use crate::instr as i;
use crate::util::{Operand, Program, Address};
use crate::heap::Datum;
use core::cell::RefCell;